From db0835a38faea36086c2a0c5ad0bbbd0dcef6546 Mon Sep 17 00:00:00 2001 From: tibimunteanu Date: Tue, 23 Feb 2021 21:07:09 +0200 Subject: [PATCH] initial commit --- .gitignore | 16 + premake5.lua | 20 + scripts/win-genprojects.bat | 5 + vendor/glfw/LICENSE.md | 23 + vendor/glfw/include/GLFW/glfw3.h | 5874 +++++++++++++++++ vendor/glfw/include/GLFW/glfw3native.h | 525 ++ vendor/glfw/lib-mingw-w64/glfw3.dll | Bin 0 -> 249344 bytes vendor/glfw/lib-mingw-w64/libglfw3.a | Bin 0 -> 305548 bytes vendor/glfw/lib-mingw-w64/libglfw3dll.a | Bin 0 -> 83380 bytes vendor/glfw/lib-vc2012/glfw3.dll | Bin 0 -> 221696 bytes vendor/glfw/lib-vc2012/glfw3.lib | Bin 0 -> 642782 bytes vendor/glfw/lib-vc2012/glfw3dll.lib | Bin 0 -> 30306 bytes vendor/glfw/lib-vc2013/glfw3.dll | Bin 0 -> 220672 bytes vendor/glfw/lib-vc2013/glfw3.lib | Bin 0 -> 642892 bytes vendor/glfw/lib-vc2013/glfw3dll.lib | Bin 0 -> 30306 bytes vendor/glfw/lib-vc2015/glfw3.dll | Bin 0 -> 224768 bytes vendor/glfw/lib-vc2015/glfw3.lib | Bin 0 -> 639666 bytes vendor/glfw/lib-vc2015/glfw3dll.lib | Bin 0 -> 30306 bytes vendor/glfw/lib-vc2017/glfw3.dll | Bin 0 -> 225280 bytes vendor/glfw/lib-vc2017/glfw3.lib | Bin 0 -> 646850 bytes vendor/glfw/lib-vc2017/glfw3dll.lib | Bin 0 -> 30306 bytes vendor/glfw/lib-vc2019/glfw3.dll | Bin 0 -> 225792 bytes vendor/glfw/lib-vc2019/glfw3.lib | Bin 0 -> 648436 bytes vendor/glfw/lib-vc2019/glfw3dll.lib | Bin 0 -> 30306 bytes vendor/glm/.appveyor.yml | 87 + vendor/glm/.gitignore | 61 + vendor/glm/.travis.yml | 735 +++ vendor/glm/CMakeLists.txt | 15 + vendor/glm/cmake/glm/glmConfig-version.cmake | 11 + vendor/glm/cmake/glm/glmConfig.cmake | 22 + vendor/glm/copying.txt | 54 + vendor/glm/glm/CMakeLists.txt | 70 + vendor/glm/glm/common.hpp | 539 ++ vendor/glm/glm/detail/_features.hpp | 394 ++ vendor/glm/glm/detail/_fixes.hpp | 27 + vendor/glm/glm/detail/_noise.hpp | 81 + vendor/glm/glm/detail/_swizzle.hpp | 804 +++ vendor/glm/glm/detail/_swizzle_func.hpp | 682 ++ vendor/glm/glm/detail/_vectorize.hpp | 162 + vendor/glm/glm/detail/compute_common.hpp | 50 + .../glm/detail/compute_vector_relational.hpp | 30 + vendor/glm/glm/detail/func_common.inl | 792 +++ vendor/glm/glm/detail/func_common_simd.inl | 231 + vendor/glm/glm/detail/func_exponential.inl | 152 + .../glm/glm/detail/func_exponential_simd.inl | 37 + vendor/glm/glm/detail/func_geometric.inl | 243 + vendor/glm/glm/detail/func_geometric_simd.inl | 163 + vendor/glm/glm/detail/func_integer.inl | 372 ++ vendor/glm/glm/detail/func_integer_simd.inl | 65 + vendor/glm/glm/detail/func_matrix.inl | 398 ++ vendor/glm/glm/detail/func_matrix_simd.inl | 249 + vendor/glm/glm/detail/func_packing.inl | 189 + vendor/glm/glm/detail/func_packing_simd.inl | 6 + vendor/glm/glm/detail/func_trigonometric.inl | 197 + .../glm/detail/func_trigonometric_simd.inl | 0 .../glm/glm/detail/func_vector_relational.inl | 87 + .../detail/func_vector_relational_simd.inl | 6 + vendor/glm/glm/detail/glm.cpp | 263 + vendor/glm/glm/detail/qualifier.hpp | 230 + vendor/glm/glm/detail/setup.hpp | 1135 ++++ vendor/glm/glm/detail/type_float.hpp | 68 + vendor/glm/glm/detail/type_half.hpp | 16 + vendor/glm/glm/detail/type_half.inl | 241 + vendor/glm/glm/detail/type_mat2x2.hpp | 177 + vendor/glm/glm/detail/type_mat2x2.inl | 536 ++ vendor/glm/glm/detail/type_mat2x3.hpp | 159 + vendor/glm/glm/detail/type_mat2x3.inl | 510 ++ vendor/glm/glm/detail/type_mat2x4.hpp | 161 + vendor/glm/glm/detail/type_mat2x4.inl | 520 ++ vendor/glm/glm/detail/type_mat3x2.hpp | 167 + vendor/glm/glm/detail/type_mat3x2.inl | 532 ++ vendor/glm/glm/detail/type_mat3x3.hpp | 184 + vendor/glm/glm/detail/type_mat3x3.inl | 601 ++ vendor/glm/glm/detail/type_mat3x4.hpp | 166 + vendor/glm/glm/detail/type_mat3x4.inl | 578 ++ vendor/glm/glm/detail/type_mat4x2.hpp | 171 + vendor/glm/glm/detail/type_mat4x2.inl | 574 ++ vendor/glm/glm/detail/type_mat4x3.hpp | 171 + vendor/glm/glm/detail/type_mat4x3.inl | 598 ++ vendor/glm/glm/detail/type_mat4x4.hpp | 189 + vendor/glm/glm/detail/type_mat4x4.inl | 706 ++ vendor/glm/glm/detail/type_mat4x4_simd.inl | 6 + vendor/glm/glm/detail/type_quat.hpp | 186 + vendor/glm/glm/detail/type_quat.inl | 408 ++ vendor/glm/glm/detail/type_quat_simd.inl | 188 + vendor/glm/glm/detail/type_vec1.hpp | 308 + vendor/glm/glm/detail/type_vec1.inl | 551 ++ vendor/glm/glm/detail/type_vec2.hpp | 399 ++ vendor/glm/glm/detail/type_vec2.inl | 913 +++ vendor/glm/glm/detail/type_vec3.hpp | 432 ++ vendor/glm/glm/detail/type_vec3.inl | 1068 +++ vendor/glm/glm/detail/type_vec4.hpp | 505 ++ vendor/glm/glm/detail/type_vec4.inl | 1140 ++++ vendor/glm/glm/detail/type_vec4_simd.inl | 775 +++ vendor/glm/glm/exponential.hpp | 110 + vendor/glm/glm/ext.hpp | 253 + vendor/glm/glm/ext/matrix_clip_space.hpp | 522 ++ vendor/glm/glm/ext/matrix_clip_space.inl | 555 ++ vendor/glm/glm/ext/matrix_common.hpp | 36 + vendor/glm/glm/ext/matrix_common.inl | 16 + vendor/glm/glm/ext/matrix_double2x2.hpp | 23 + .../glm/ext/matrix_double2x2_precision.hpp | 49 + vendor/glm/glm/ext/matrix_double2x3.hpp | 18 + .../glm/ext/matrix_double2x3_precision.hpp | 31 + vendor/glm/glm/ext/matrix_double2x4.hpp | 18 + .../glm/ext/matrix_double2x4_precision.hpp | 31 + vendor/glm/glm/ext/matrix_double3x2.hpp | 18 + .../glm/ext/matrix_double3x2_precision.hpp | 31 + vendor/glm/glm/ext/matrix_double3x3.hpp | 23 + .../glm/ext/matrix_double3x3_precision.hpp | 49 + vendor/glm/glm/ext/matrix_double3x4.hpp | 18 + .../glm/ext/matrix_double3x4_precision.hpp | 31 + vendor/glm/glm/ext/matrix_double4x2.hpp | 18 + .../glm/ext/matrix_double4x2_precision.hpp | 31 + vendor/glm/glm/ext/matrix_double4x3.hpp | 18 + .../glm/ext/matrix_double4x3_precision.hpp | 31 + vendor/glm/glm/ext/matrix_double4x4.hpp | 23 + .../glm/ext/matrix_double4x4_precision.hpp | 49 + vendor/glm/glm/ext/matrix_float2x2.hpp | 23 + .../glm/glm/ext/matrix_float2x2_precision.hpp | 49 + vendor/glm/glm/ext/matrix_float2x3.hpp | 18 + .../glm/glm/ext/matrix_float2x3_precision.hpp | 31 + vendor/glm/glm/ext/matrix_float2x4.hpp | 18 + .../glm/glm/ext/matrix_float2x4_precision.hpp | 31 + vendor/glm/glm/ext/matrix_float3x2.hpp | 18 + .../glm/glm/ext/matrix_float3x2_precision.hpp | 31 + vendor/glm/glm/ext/matrix_float3x3.hpp | 23 + .../glm/glm/ext/matrix_float3x3_precision.hpp | 49 + vendor/glm/glm/ext/matrix_float3x4.hpp | 18 + .../glm/glm/ext/matrix_float3x4_precision.hpp | 31 + vendor/glm/glm/ext/matrix_float4x2.hpp | 18 + .../glm/glm/ext/matrix_float4x2_precision.hpp | 31 + vendor/glm/glm/ext/matrix_float4x3.hpp | 18 + .../glm/glm/ext/matrix_float4x3_precision.hpp | 31 + vendor/glm/glm/ext/matrix_float4x4.hpp | 23 + .../glm/glm/ext/matrix_float4x4_precision.hpp | 49 + vendor/glm/glm/ext/matrix_int2x2.hpp | 38 + vendor/glm/glm/ext/matrix_int2x2_sized.hpp | 70 + vendor/glm/glm/ext/matrix_int2x3.hpp | 33 + vendor/glm/glm/ext/matrix_int2x3_sized.hpp | 49 + vendor/glm/glm/ext/matrix_int2x4.hpp | 33 + vendor/glm/glm/ext/matrix_int2x4_sized.hpp | 49 + vendor/glm/glm/ext/matrix_int3x2.hpp | 33 + vendor/glm/glm/ext/matrix_int3x2_sized.hpp | 49 + vendor/glm/glm/ext/matrix_int3x3.hpp | 38 + vendor/glm/glm/ext/matrix_int3x3_sized.hpp | 70 + vendor/glm/glm/ext/matrix_int3x4.hpp | 33 + vendor/glm/glm/ext/matrix_int3x4_sized.hpp | 49 + vendor/glm/glm/ext/matrix_int4x2.hpp | 33 + vendor/glm/glm/ext/matrix_int4x2_sized.hpp | 49 + vendor/glm/glm/ext/matrix_int4x3.hpp | 33 + vendor/glm/glm/ext/matrix_int4x3_sized.hpp | 49 + vendor/glm/glm/ext/matrix_int4x4.hpp | 38 + vendor/glm/glm/ext/matrix_int4x4_sized.hpp | 70 + vendor/glm/glm/ext/matrix_projection.hpp | 149 + vendor/glm/glm/ext/matrix_projection.inl | 106 + vendor/glm/glm/ext/matrix_relational.hpp | 132 + vendor/glm/glm/ext/matrix_relational.inl | 82 + vendor/glm/glm/ext/matrix_transform.hpp | 144 + vendor/glm/glm/ext/matrix_transform.inl | 152 + vendor/glm/glm/ext/matrix_uint2x2.hpp | 38 + vendor/glm/glm/ext/matrix_uint2x2_sized.hpp | 70 + vendor/glm/glm/ext/matrix_uint2x3.hpp | 33 + vendor/glm/glm/ext/matrix_uint2x3_sized.hpp | 49 + vendor/glm/glm/ext/matrix_uint2x4.hpp | 33 + vendor/glm/glm/ext/matrix_uint2x4_sized.hpp | 49 + vendor/glm/glm/ext/matrix_uint3x2.hpp | 33 + vendor/glm/glm/ext/matrix_uint3x2_sized.hpp | 49 + vendor/glm/glm/ext/matrix_uint3x3.hpp | 38 + vendor/glm/glm/ext/matrix_uint3x3_sized.hpp | 70 + vendor/glm/glm/ext/matrix_uint3x4.hpp | 33 + vendor/glm/glm/ext/matrix_uint3x4_sized.hpp | 49 + vendor/glm/glm/ext/matrix_uint4x2.hpp | 33 + vendor/glm/glm/ext/matrix_uint4x2_sized.hpp | 49 + vendor/glm/glm/ext/matrix_uint4x3.hpp | 33 + vendor/glm/glm/ext/matrix_uint4x3_sized.hpp | 49 + vendor/glm/glm/ext/matrix_uint4x4.hpp | 38 + vendor/glm/glm/ext/matrix_uint4x4_sized.hpp | 70 + vendor/glm/glm/ext/quaternion_common.hpp | 135 + vendor/glm/glm/ext/quaternion_common.inl | 144 + vendor/glm/glm/ext/quaternion_common_simd.inl | 18 + vendor/glm/glm/ext/quaternion_double.hpp | 39 + .../glm/ext/quaternion_double_precision.hpp | 42 + vendor/glm/glm/ext/quaternion_exponential.hpp | 63 + vendor/glm/glm/ext/quaternion_exponential.inl | 85 + vendor/glm/glm/ext/quaternion_float.hpp | 39 + .../glm/ext/quaternion_float_precision.hpp | 36 + vendor/glm/glm/ext/quaternion_geometric.hpp | 70 + vendor/glm/glm/ext/quaternion_geometric.inl | 36 + vendor/glm/glm/ext/quaternion_relational.hpp | 62 + vendor/glm/glm/ext/quaternion_relational.inl | 35 + vendor/glm/glm/ext/quaternion_transform.hpp | 47 + vendor/glm/glm/ext/quaternion_transform.inl | 24 + .../glm/glm/ext/quaternion_trigonometric.hpp | 63 + .../glm/glm/ext/quaternion_trigonometric.inl | 34 + vendor/glm/glm/ext/scalar_common.hpp | 157 + vendor/glm/glm/ext/scalar_common.inl | 152 + vendor/glm/glm/ext/scalar_constants.hpp | 40 + vendor/glm/glm/ext/scalar_constants.inl | 24 + vendor/glm/glm/ext/scalar_int_sized.hpp | 70 + vendor/glm/glm/ext/scalar_integer.hpp | 92 + vendor/glm/glm/ext/scalar_integer.inl | 243 + vendor/glm/glm/ext/scalar_packing.hpp | 32 + vendor/glm/glm/ext/scalar_packing.inl | 0 vendor/glm/glm/ext/scalar_relational.hpp | 65 + vendor/glm/glm/ext/scalar_relational.inl | 40 + vendor/glm/glm/ext/scalar_uint_sized.hpp | 70 + vendor/glm/glm/ext/scalar_ulp.hpp | 74 + vendor/glm/glm/ext/scalar_ulp.inl | 284 + vendor/glm/glm/ext/vector_bool1.hpp | 30 + vendor/glm/glm/ext/vector_bool1_precision.hpp | 34 + vendor/glm/glm/ext/vector_bool2.hpp | 18 + vendor/glm/glm/ext/vector_bool2_precision.hpp | 31 + vendor/glm/glm/ext/vector_bool3.hpp | 18 + vendor/glm/glm/ext/vector_bool3_precision.hpp | 31 + vendor/glm/glm/ext/vector_bool4.hpp | 18 + vendor/glm/glm/ext/vector_bool4_precision.hpp | 31 + vendor/glm/glm/ext/vector_common.hpp | 204 + vendor/glm/glm/ext/vector_common.inl | 129 + vendor/glm/glm/ext/vector_double1.hpp | 31 + .../glm/glm/ext/vector_double1_precision.hpp | 36 + vendor/glm/glm/ext/vector_double2.hpp | 18 + .../glm/glm/ext/vector_double2_precision.hpp | 31 + vendor/glm/glm/ext/vector_double3.hpp | 18 + .../glm/glm/ext/vector_double3_precision.hpp | 34 + vendor/glm/glm/ext/vector_double4.hpp | 18 + .../glm/glm/ext/vector_double4_precision.hpp | 35 + vendor/glm/glm/ext/vector_float1.hpp | 31 + .../glm/glm/ext/vector_float1_precision.hpp | 36 + vendor/glm/glm/ext/vector_float2.hpp | 18 + .../glm/glm/ext/vector_float2_precision.hpp | 31 + vendor/glm/glm/ext/vector_float3.hpp | 18 + .../glm/glm/ext/vector_float3_precision.hpp | 31 + vendor/glm/glm/ext/vector_float4.hpp | 18 + .../glm/glm/ext/vector_float4_precision.hpp | 31 + vendor/glm/glm/ext/vector_int1.hpp | 32 + vendor/glm/glm/ext/vector_int1_sized.hpp | 49 + vendor/glm/glm/ext/vector_int2.hpp | 18 + vendor/glm/glm/ext/vector_int2_sized.hpp | 49 + vendor/glm/glm/ext/vector_int3.hpp | 18 + vendor/glm/glm/ext/vector_int3_sized.hpp | 49 + vendor/glm/glm/ext/vector_int4.hpp | 18 + vendor/glm/glm/ext/vector_int4_sized.hpp | 49 + vendor/glm/glm/ext/vector_integer.hpp | 149 + vendor/glm/glm/ext/vector_integer.inl | 85 + vendor/glm/glm/ext/vector_packing.hpp | 32 + vendor/glm/glm/ext/vector_packing.inl | 0 vendor/glm/glm/ext/vector_relational.hpp | 107 + vendor/glm/glm/ext/vector_relational.inl | 75 + vendor/glm/glm/ext/vector_uint1.hpp | 32 + vendor/glm/glm/ext/vector_uint1_sized.hpp | 49 + vendor/glm/glm/ext/vector_uint2.hpp | 18 + vendor/glm/glm/ext/vector_uint2_sized.hpp | 49 + vendor/glm/glm/ext/vector_uint3.hpp | 18 + vendor/glm/glm/ext/vector_uint3_sized.hpp | 49 + vendor/glm/glm/ext/vector_uint4.hpp | 18 + vendor/glm/glm/ext/vector_uint4_sized.hpp | 49 + vendor/glm/glm/ext/vector_ulp.hpp | 109 + vendor/glm/glm/ext/vector_ulp.inl | 74 + vendor/glm/glm/fwd.hpp | 1233 ++++ vendor/glm/glm/geometric.hpp | 116 + vendor/glm/glm/glm.hpp | 136 + vendor/glm/glm/gtc/bitfield.hpp | 266 + vendor/glm/glm/gtc/bitfield.inl | 626 ++ vendor/glm/glm/gtc/color_space.hpp | 56 + vendor/glm/glm/gtc/color_space.inl | 84 + vendor/glm/glm/gtc/constants.hpp | 165 + vendor/glm/glm/gtc/constants.inl | 167 + vendor/glm/glm/gtc/epsilon.hpp | 60 + vendor/glm/glm/gtc/epsilon.inl | 80 + vendor/glm/glm/gtc/integer.hpp | 65 + vendor/glm/glm/gtc/integer.inl | 68 + vendor/glm/glm/gtc/matrix_access.hpp | 60 + vendor/glm/glm/gtc/matrix_access.inl | 62 + vendor/glm/glm/gtc/matrix_integer.hpp | 433 ++ vendor/glm/glm/gtc/matrix_inverse.hpp | 50 + vendor/glm/glm/gtc/matrix_inverse.inl | 118 + vendor/glm/glm/gtc/matrix_transform.hpp | 36 + vendor/glm/glm/gtc/matrix_transform.inl | 3 + vendor/glm/glm/gtc/noise.hpp | 61 + vendor/glm/glm/gtc/noise.inl | 807 +++ vendor/glm/glm/gtc/packing.hpp | 728 ++ vendor/glm/glm/gtc/packing.inl | 938 +++ vendor/glm/glm/gtc/quaternion.hpp | 173 + vendor/glm/glm/gtc/quaternion.inl | 202 + vendor/glm/glm/gtc/quaternion_simd.inl | 0 vendor/glm/glm/gtc/random.hpp | 82 + vendor/glm/glm/gtc/random.inl | 303 + vendor/glm/glm/gtc/reciprocal.hpp | 135 + vendor/glm/glm/gtc/reciprocal.inl | 191 + vendor/glm/glm/gtc/round.hpp | 160 + vendor/glm/glm/gtc/round.inl | 155 + vendor/glm/glm/gtc/type_aligned.hpp | 1315 ++++ vendor/glm/glm/gtc/type_precision.hpp | 2094 ++++++ vendor/glm/glm/gtc/type_precision.inl | 6 + vendor/glm/glm/gtc/type_ptr.hpp | 230 + vendor/glm/glm/gtc/type_ptr.inl | 386 ++ vendor/glm/glm/gtc/ulp.hpp | 152 + vendor/glm/glm/gtc/ulp.inl | 173 + vendor/glm/glm/gtc/vec1.hpp | 30 + vendor/glm/glm/gtx/associated_min_max.hpp | 207 + vendor/glm/glm/gtx/associated_min_max.inl | 354 + vendor/glm/glm/gtx/bit.hpp | 98 + vendor/glm/glm/gtx/bit.inl | 92 + vendor/glm/glm/gtx/closest_point.hpp | 49 + vendor/glm/glm/gtx/closest_point.inl | 45 + vendor/glm/glm/gtx/color_encoding.hpp | 54 + vendor/glm/glm/gtx/color_encoding.inl | 45 + vendor/glm/glm/gtx/color_space.hpp | 72 + vendor/glm/glm/gtx/color_space.inl | 141 + vendor/glm/glm/gtx/color_space_YCoCg.hpp | 60 + vendor/glm/glm/gtx/color_space_YCoCg.inl | 107 + vendor/glm/glm/gtx/common.hpp | 76 + vendor/glm/glm/gtx/common.inl | 125 + vendor/glm/glm/gtx/compatibility.hpp | 133 + vendor/glm/glm/gtx/compatibility.inl | 62 + vendor/glm/glm/gtx/component_wise.hpp | 69 + vendor/glm/glm/gtx/component_wise.inl | 127 + vendor/glm/glm/gtx/dual_quaternion.hpp | 274 + vendor/glm/glm/gtx/dual_quaternion.inl | 352 + vendor/glm/glm/gtx/easing.hpp | 219 + vendor/glm/glm/gtx/easing.inl | 436 ++ vendor/glm/glm/gtx/euler_angles.hpp | 335 + vendor/glm/glm/gtx/euler_angles.inl | 899 +++ vendor/glm/glm/gtx/extend.hpp | 42 + vendor/glm/glm/gtx/extend.inl | 48 + vendor/glm/glm/gtx/extended_min_max.hpp | 137 + vendor/glm/glm/gtx/extended_min_max.inl | 138 + vendor/glm/glm/gtx/exterior_product.hpp | 45 + vendor/glm/glm/gtx/exterior_product.inl | 26 + vendor/glm/glm/gtx/fast_exponential.hpp | 95 + vendor/glm/glm/gtx/fast_exponential.inl | 136 + vendor/glm/glm/gtx/fast_square_root.hpp | 92 + vendor/glm/glm/gtx/fast_square_root.inl | 75 + vendor/glm/glm/gtx/fast_trigonometry.hpp | 79 + vendor/glm/glm/gtx/fast_trigonometry.inl | 142 + vendor/glm/glm/gtx/float_notmalize.inl | 13 + vendor/glm/glm/gtx/functions.hpp | 56 + vendor/glm/glm/gtx/functions.inl | 30 + vendor/glm/glm/gtx/gradient_paint.hpp | 53 + vendor/glm/glm/gtx/gradient_paint.inl | 36 + .../glm/glm/gtx/handed_coordinate_space.hpp | 50 + .../glm/glm/gtx/handed_coordinate_space.inl | 26 + vendor/glm/glm/gtx/hash.hpp | 142 + vendor/glm/glm/gtx/hash.inl | 184 + vendor/glm/glm/gtx/integer.hpp | 76 + vendor/glm/glm/gtx/integer.inl | 185 + vendor/glm/glm/gtx/intersect.hpp | 92 + vendor/glm/glm/gtx/intersect.inl | 200 + vendor/glm/glm/gtx/io.hpp | 201 + vendor/glm/glm/gtx/io.inl | 440 ++ vendor/glm/glm/gtx/log_base.hpp | 48 + vendor/glm/glm/gtx/log_base.inl | 16 + vendor/glm/glm/gtx/matrix_cross_product.hpp | 47 + vendor/glm/glm/gtx/matrix_cross_product.inl | 37 + vendor/glm/glm/gtx/matrix_decompose.hpp | 46 + vendor/glm/glm/gtx/matrix_decompose.inl | 186 + vendor/glm/glm/gtx/matrix_factorisation.hpp | 69 + vendor/glm/glm/gtx/matrix_factorisation.inl | 84 + vendor/glm/glm/gtx/matrix_interpolation.hpp | 60 + vendor/glm/glm/gtx/matrix_interpolation.inl | 129 + vendor/glm/glm/gtx/matrix_major_storage.hpp | 119 + vendor/glm/glm/gtx/matrix_major_storage.inl | 166 + vendor/glm/glm/gtx/matrix_operation.hpp | 103 + vendor/glm/glm/gtx/matrix_operation.inl | 176 + vendor/glm/glm/gtx/matrix_query.hpp | 77 + vendor/glm/glm/gtx/matrix_query.inl | 113 + vendor/glm/glm/gtx/matrix_transform_2d.hpp | 81 + vendor/glm/glm/gtx/matrix_transform_2d.inl | 68 + vendor/glm/glm/gtx/mixed_product.hpp | 41 + vendor/glm/glm/gtx/mixed_product.inl | 15 + vendor/glm/glm/gtx/norm.hpp | 88 + vendor/glm/glm/gtx/norm.inl | 95 + vendor/glm/glm/gtx/normal.hpp | 41 + vendor/glm/glm/gtx/normal.inl | 15 + vendor/glm/glm/gtx/normalize_dot.hpp | 49 + vendor/glm/glm/gtx/normalize_dot.inl | 16 + vendor/glm/glm/gtx/number_precision.hpp | 61 + vendor/glm/glm/gtx/number_precision.inl | 6 + vendor/glm/glm/gtx/optimum_pow.hpp | 54 + vendor/glm/glm/gtx/optimum_pow.inl | 22 + vendor/glm/glm/gtx/orthonormalize.hpp | 49 + vendor/glm/glm/gtx/orthonormalize.inl | 29 + vendor/glm/glm/gtx/perpendicular.hpp | 41 + vendor/glm/glm/gtx/perpendicular.inl | 10 + vendor/glm/glm/gtx/polar_coordinates.hpp | 48 + vendor/glm/glm/gtx/polar_coordinates.inl | 36 + vendor/glm/glm/gtx/projection.hpp | 43 + vendor/glm/glm/gtx/projection.inl | 10 + vendor/glm/glm/gtx/quaternion.hpp | 174 + vendor/glm/glm/gtx/quaternion.inl | 159 + vendor/glm/glm/gtx/range.hpp | 98 + vendor/glm/glm/gtx/raw_data.hpp | 51 + vendor/glm/glm/gtx/raw_data.inl | 2 + vendor/glm/glm/gtx/rotate_normalized_axis.hpp | 68 + vendor/glm/glm/gtx/rotate_normalized_axis.inl | 58 + vendor/glm/glm/gtx/rotate_vector.hpp | 123 + vendor/glm/glm/gtx/rotate_vector.inl | 187 + vendor/glm/glm/gtx/scalar_multiplication.hpp | 75 + vendor/glm/glm/gtx/scalar_relational.hpp | 36 + vendor/glm/glm/gtx/scalar_relational.inl | 88 + vendor/glm/glm/gtx/spline.hpp | 65 + vendor/glm/glm/gtx/spline.inl | 60 + vendor/glm/glm/gtx/std_based_type.hpp | 68 + vendor/glm/glm/gtx/std_based_type.inl | 6 + vendor/glm/glm/gtx/string_cast.hpp | 52 + vendor/glm/glm/gtx/string_cast.inl | 492 ++ vendor/glm/glm/gtx/texture.hpp | 46 + vendor/glm/glm/gtx/texture.inl | 17 + vendor/glm/glm/gtx/transform.hpp | 60 + vendor/glm/glm/gtx/transform.inl | 23 + vendor/glm/glm/gtx/transform2.hpp | 89 + vendor/glm/glm/gtx/transform2.inl | 125 + vendor/glm/glm/gtx/type_aligned.hpp | 982 +++ vendor/glm/glm/gtx/type_aligned.inl | 6 + vendor/glm/glm/gtx/type_trait.hpp | 85 + vendor/glm/glm/gtx/type_trait.inl | 61 + vendor/glm/glm/gtx/vec_swizzle.hpp | 2782 ++++++++ vendor/glm/glm/gtx/vector_angle.hpp | 57 + vendor/glm/glm/gtx/vector_angle.inl | 44 + vendor/glm/glm/gtx/vector_query.hpp | 66 + vendor/glm/glm/gtx/vector_query.inl | 154 + vendor/glm/glm/gtx/wrap.hpp | 37 + vendor/glm/glm/gtx/wrap.inl | 6 + vendor/glm/glm/integer.hpp | 212 + vendor/glm/glm/mat2x2.hpp | 9 + vendor/glm/glm/mat2x3.hpp | 9 + vendor/glm/glm/mat2x4.hpp | 9 + vendor/glm/glm/mat3x2.hpp | 9 + vendor/glm/glm/mat3x3.hpp | 8 + vendor/glm/glm/mat3x4.hpp | 8 + vendor/glm/glm/mat4x2.hpp | 9 + vendor/glm/glm/mat4x3.hpp | 8 + vendor/glm/glm/mat4x4.hpp | 9 + vendor/glm/glm/matrix.hpp | 161 + vendor/glm/glm/packing.hpp | 173 + vendor/glm/glm/simd/common.h | 240 + vendor/glm/glm/simd/exponential.h | 20 + vendor/glm/glm/simd/geometric.h | 124 + vendor/glm/glm/simd/integer.h | 115 + vendor/glm/glm/simd/matrix.h | 1028 +++ vendor/glm/glm/simd/neon.h | 155 + vendor/glm/glm/simd/packing.h | 8 + vendor/glm/glm/simd/platform.h | 398 ++ vendor/glm/glm/simd/trigonometric.h | 9 + vendor/glm/glm/simd/vector_relational.h | 8 + vendor/glm/glm/trigonometric.hpp | 210 + vendor/glm/glm/vec2.hpp | 14 + vendor/glm/glm/vec3.hpp | 14 + vendor/glm/glm/vec4.hpp | 15 + vendor/glm/glm/vector_relational.hpp | 121 + vendor/glm/manual.md | 2411 +++++++ vendor/glm/readme.md | 1209 ++++ vendor/glm/test/CMakeLists.txt | 246 + vendor/glm/test/bug/CMakeLists.txt | 1 + vendor/glm/test/bug/bug_ms_vec_static.cpp | 31 + vendor/glm/test/cmake/CMakeLists.txt | 8 + vendor/glm/test/cmake/test_find_glm.cpp | 22 + vendor/glm/test/core/CMakeLists.txt | 52 + vendor/glm/test/core/core_cpp_constexpr.cpp | 750 +++ .../glm/test/core/core_cpp_defaulted_ctor.cpp | 145 + .../test/core/core_force_aligned_gentypes.cpp | 10 + .../glm/test/core/core_force_arch_unknown.cpp | 14 + .../test/core/core_force_compiler_unknown.cpp | 14 + vendor/glm/test/core/core_force_ctor_init.cpp | 139 + vendor/glm/test/core/core_force_cxx03.cpp | 14 + vendor/glm/test/core/core_force_cxx98.cpp | 14 + .../glm/test/core/core_force_cxx_unknown.cpp | 14 + .../core/core_force_depth_zero_to_one.cpp | 12 + .../test/core/core_force_explicit_ctor.cpp | 17 + vendor/glm/test/core/core_force_inline.cpp | 12 + .../glm/test/core/core_force_left_handed.cpp | 12 + .../test/core/core_force_platform_unknown.cpp | 14 + vendor/glm/test/core/core_force_pure.cpp | 434 ++ vendor/glm/test/core/core_force_quat_wxyz.cpp | 13 + .../test/core/core_force_size_t_length.cpp | 12 + .../core/core_force_unrestricted_gentype.cpp | 12 + vendor/glm/test/core/core_force_xyzw_only.cpp | 58 + vendor/glm/test/core/core_func_common.cpp | 1349 ++++ .../glm/test/core/core_func_exponential.cpp | 185 + vendor/glm/test/core/core_func_geometric.cpp | 200 + vendor/glm/test/core/core_func_integer.cpp | 1556 +++++ .../test/core/core_func_integer_bit_count.cpp | 291 + .../test/core/core_func_integer_find_lsb.cpp | 416 ++ .../test/core/core_func_integer_find_msb.cpp | 440 ++ vendor/glm/test/core/core_func_matrix.cpp | 329 + vendor/glm/test/core/core_func_noise.cpp | 7 + vendor/glm/test/core/core_func_packing.cpp | 156 + vendor/glm/test/core/core_func_swizzle.cpp | 164 + .../glm/test/core/core_func_trigonometric.cpp | 10 + .../test/core/core_func_vector_relational.cpp | 180 + .../glm/test/core/core_setup_force_cxx98.cpp | 12 + .../core/core_setup_force_size_t_length.cpp | 22 + vendor/glm/test/core/core_setup_message.cpp | 230 + .../test/core/core_setup_platform_unknown.cpp | 21 + vendor/glm/test/core/core_setup_precision.cpp | 58 + vendor/glm/test/core/core_type_aligned.cpp | 92 + vendor/glm/test/core/core_type_cast.cpp | 146 + vendor/glm/test/core/core_type_ctor.cpp | 351 + vendor/glm/test/core/core_type_int.cpp | 26 + vendor/glm/test/core/core_type_length.cpp | 79 + vendor/glm/test/core/core_type_mat2x2.cpp | 177 + vendor/glm/test/core/core_type_mat2x3.cpp | 142 + vendor/glm/test/core/core_type_mat2x4.cpp | 147 + vendor/glm/test/core/core_type_mat3x2.cpp | 148 + vendor/glm/test/core/core_type_mat3x3.cpp | 197 + vendor/glm/test/core/core_type_mat3x4.cpp | 149 + vendor/glm/test/core/core_type_mat4x2.cpp | 151 + vendor/glm/test/core/core_type_mat4x3.cpp | 152 + vendor/glm/test/core/core_type_mat4x4.cpp | 218 + vendor/glm/test/core/core_type_vec1.cpp | 169 + vendor/glm/test/core/core_type_vec2.cpp | 392 ++ vendor/glm/test/core/core_type_vec3.cpp | 628 ++ vendor/glm/test/core/core_type_vec4.cpp | 850 +++ vendor/glm/test/ext/CMakeLists.txt | 52 + vendor/glm/test/ext/ext_matrix_clip_space.cpp | 13 + vendor/glm/test/ext/ext_matrix_common.cpp | 53 + .../glm/test/ext/ext_matrix_int2x2_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int2x3_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int2x4_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int3x2_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int3x3_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int3x4_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int4x2_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int4x3_sized.cpp | 28 + .../glm/test/ext/ext_matrix_int4x4_sized.cpp | 28 + vendor/glm/test/ext/ext_matrix_projection.cpp | 13 + vendor/glm/test/ext/ext_matrix_relational.cpp | 163 + vendor/glm/test/ext/ext_matrix_transform.cpp | 61 + .../glm/test/ext/ext_matrix_uint2x2_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint2x3_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint2x4_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint3x2_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint3x3_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint3x4_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint4x2_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint4x3_sized.cpp | 28 + .../glm/test/ext/ext_matrix_uint4x4_sized.cpp | 28 + vendor/glm/test/ext/ext_quaternion_common.cpp | 61 + .../test/ext/ext_quaternion_exponential.cpp | 87 + .../glm/test/ext/ext_quaternion_geometric.cpp | 88 + .../test/ext/ext_quaternion_relational.cpp | 51 + .../glm/test/ext/ext_quaternion_transform.cpp | 45 + .../test/ext/ext_quaternion_trigonometric.cpp | 34 + vendor/glm/test/ext/ext_quaternion_type.cpp | 113 + vendor/glm/test/ext/ext_scalar_common.cpp | 327 + vendor/glm/test/ext/ext_scalar_constants.cpp | 36 + vendor/glm/test/ext/ext_scalar_int_sized.cpp | 43 + vendor/glm/test/ext/ext_scalar_integer.cpp | 686 ++ vendor/glm/test/ext/ext_scalar_packing.cpp | 28 + vendor/glm/test/ext/ext_scalar_relational.cpp | 106 + vendor/glm/test/ext/ext_scalar_uint_sized.cpp | 43 + vendor/glm/test/ext/ext_scalar_ulp.cpp | 96 + vendor/glm/test/ext/ext_vec1.cpp | 157 + vendor/glm/test/ext/ext_vector_bool1.cpp | 104 + vendor/glm/test/ext/ext_vector_common.cpp | 332 + vendor/glm/test/ext/ext_vector_iec559.cpp | 166 + vendor/glm/test/ext/ext_vector_int1_sized.cpp | 41 + vendor/glm/test/ext/ext_vector_int2_sized.cpp | 41 + vendor/glm/test/ext/ext_vector_int3_sized.cpp | 41 + vendor/glm/test/ext/ext_vector_int4_sized.cpp | 41 + vendor/glm/test/ext/ext_vector_integer.cpp | 547 ++ .../glm/test/ext/ext_vector_integer_sized.cpp | 216 + vendor/glm/test/ext/ext_vector_packing.cpp | 58 + vendor/glm/test/ext/ext_vector_relational.cpp | 205 + .../glm/test/ext/ext_vector_uint1_sized.cpp | 41 + .../glm/test/ext/ext_vector_uint2_sized.cpp | 41 + .../glm/test/ext/ext_vector_uint3_sized.cpp | 41 + .../glm/test/ext/ext_vector_uint4_sized.cpp | 41 + vendor/glm/test/ext/ext_vector_ulp.cpp | 99 + vendor/glm/test/glm.cppcheck | 6 + vendor/glm/test/gtc/CMakeLists.txt | 20 + vendor/glm/test/gtc/gtc_bitfield.cpp | 936 +++ vendor/glm/test/gtc/gtc_color_space.cpp | 78 + vendor/glm/test/gtc/gtc_constants.cpp | 30 + vendor/glm/test/gtc/gtc_epsilon.cpp | 78 + vendor/glm/test/gtc/gtc_integer.cpp | 233 + vendor/glm/test/gtc/gtc_matrix_access.cpp | 383 ++ vendor/glm/test/gtc/gtc_matrix_integer.cpp | 8 + vendor/glm/test/gtc/gtc_matrix_inverse.cpp | 51 + vendor/glm/test/gtc/gtc_matrix_transform.cpp | 55 + vendor/glm/test/gtc/gtc_noise.cpp | 86 + vendor/glm/test/gtc/gtc_packing.cpp | 878 +++ vendor/glm/test/gtc/gtc_quaternion.cpp | 345 + vendor/glm/test/gtc/gtc_random.cpp | 381 ++ vendor/glm/test/gtc/gtc_reciprocal.cpp | 8 + vendor/glm/test/gtc/gtc_round.cpp | 458 ++ vendor/glm/test/gtc/gtc_type_aligned.cpp | 181 + vendor/glm/test/gtc/gtc_type_precision.cpp | 1041 +++ vendor/glm/test/gtc/gtc_type_ptr.cpp | 335 + vendor/glm/test/gtc/gtc_ulp.cpp | 99 + .../glm/test/gtc/gtc_user_defined_types.cpp | 30 + vendor/glm/test/gtc/gtc_vec1.cpp | 8 + vendor/glm/test/gtx/CMakeLists.txt | 58 + vendor/glm/test/gtx/gtx.cpp | 8 + .../glm/test/gtx/gtx_associated_min_max.cpp | 10 + vendor/glm/test/gtx/gtx_closest_point.cpp | 9 + vendor/glm/test/gtx/gtx_color_encoding.cpp | 51 + vendor/glm/test/gtx/gtx_color_space.cpp | 20 + vendor/glm/test/gtx/gtx_color_space_YCoCg.cpp | 9 + vendor/glm/test/gtx/gtx_common.cpp | 161 + vendor/glm/test/gtx/gtx_compatibility.cpp | 19 + vendor/glm/test/gtx/gtx_component_wise.cpp | 116 + vendor/glm/test/gtx/gtx_dual_quaternion.cpp | 205 + vendor/glm/test/gtx/gtx_easing.cpp | 65 + vendor/glm/test/gtx/gtx_euler_angle.cpp | 539 ++ vendor/glm/test/gtx/gtx_extend.cpp | 9 + vendor/glm/test/gtx/gtx_extended_min_max.cpp | 101 + vendor/glm/test/gtx/gtx_extented_min_max.cpp | 39 + vendor/glm/test/gtx/gtx_exterior_product.cpp | 14 + vendor/glm/test/gtx/gtx_fast_exponential.cpp | 9 + vendor/glm/test/gtx/gtx_fast_square_root.cpp | 45 + vendor/glm/test/gtx/gtx_fast_trigonometry.cpp | 564 ++ vendor/glm/test/gtx/gtx_functions.cpp | 36 + vendor/glm/test/gtx/gtx_gradient_paint.cpp | 34 + .../test/gtx/gtx_handed_coordinate_space.cpp | 9 + vendor/glm/test/gtx/gtx_int_10_10_10_2.cpp | 18 + vendor/glm/test/gtx/gtx_integer.cpp | 108 + vendor/glm/test/gtx/gtx_intersect.cpp | 88 + vendor/glm/test/gtx/gtx_io.cpp | 186 + vendor/glm/test/gtx/gtx_load.cpp | 124 + vendor/glm/test/gtx/gtx_log_base.cpp | 54 + .../glm/test/gtx/gtx_matrix_cross_product.cpp | 9 + vendor/glm/test/gtx/gtx_matrix_decompose.cpp | 19 + .../glm/test/gtx/gtx_matrix_factorisation.cpp | 105 + .../glm/test/gtx/gtx_matrix_interpolation.cpp | 59 + .../glm/test/gtx/gtx_matrix_major_storage.cpp | 9 + vendor/glm/test/gtx/gtx_matrix_operation.cpp | 9 + vendor/glm/test/gtx/gtx_matrix_query.cpp | 66 + .../glm/test/gtx/gtx_matrix_transform_2d.cpp | 9 + vendor/glm/test/gtx/gtx_mixed_product.cpp | 18 + vendor/glm/test/gtx/gtx_norm.cpp | 81 + vendor/glm/test/gtx/gtx_normal.cpp | 9 + vendor/glm/test/gtx/gtx_normalize_dot.cpp | 9 + vendor/glm/test/gtx/gtx_number_precision.cpp | 9 + vendor/glm/test/gtx/gtx_optimum_pow.cpp | 9 + vendor/glm/test/gtx/gtx_orthonormalize.cpp | 9 + vendor/glm/test/gtx/gtx_perpendicular.cpp | 9 + vendor/glm/test/gtx/gtx_polar_coordinates.cpp | 9 + vendor/glm/test/gtx/gtx_projection.cpp | 9 + vendor/glm/test/gtx/gtx_quaternion.cpp | 107 + vendor/glm/test/gtx/gtx_random.cpp | 99 + vendor/glm/test/gtx/gtx_range.cpp | 83 + .../test/gtx/gtx_rotate_normalized_axis.cpp | 9 + vendor/glm/test/gtx/gtx_rotate_vector.cpp | 77 + .../test/gtx/gtx_scalar_multiplication.cpp | 37 + vendor/glm/test/gtx/gtx_scalar_relational.cpp | 174 + vendor/glm/test/gtx/gtx_simd_mat4.cpp | 324 + vendor/glm/test/gtx/gtx_simd_vec4.cpp | 71 + vendor/glm/test/gtx/gtx_spline.cpp | 100 + vendor/glm/test/gtx/gtx_string_cast.cpp | 155 + vendor/glm/test/gtx/gtx_texture.cpp | 22 + vendor/glm/test/gtx/gtx_type_aligned.cpp | 114 + vendor/glm/test/gtx/gtx_type_trait.cpp | 13 + vendor/glm/test/gtx/gtx_vec_swizzle.cpp | 11 + vendor/glm/test/gtx/gtx_vector_angle.cpp | 59 + vendor/glm/test/gtx/gtx_vector_query.cpp | 82 + vendor/glm/test/gtx/gtx_wrap.cpp | 191 + vendor/glm/test/perf/CMakeLists.txt | 6 + vendor/glm/test/perf/perf_matrix_div.cpp | 153 + vendor/glm/test/perf/perf_matrix_inverse.cpp | 150 + vendor/glm/test/perf/perf_matrix_mul.cpp | 154 + .../glm/test/perf/perf_matrix_mul_vector.cpp | 154 + .../glm/test/perf/perf_matrix_transpose.cpp | 150 + .../glm/test/perf/perf_vector_mul_matrix.cpp | 154 + vendor/glm/util/autoexp.txt | 28 + vendor/glm/util/autoexp.vc2010.dat | 3896 +++++++++++ vendor/glm/util/glm.natvis | 65 + vendor/glm/util/usertype.dat | 407 ++ vendor/premake/bin/LICENSE.txt | 27 + vendor/premake/bin/premake5.exe | Bin 0 -> 1371136 bytes vktest/assets/shaders/frag.spv | Bin 0 -> 608 bytes vktest/assets/shaders/shader.frag | 10 + vktest/assets/shaders/shader.vert | 21 + vktest/assets/shaders/vert.spv | Bin 0 -> 1540 bytes vktest/compileShaders.bat | 4 + vktest/premake5.lua | 67 + vktest/src/main.cpp | 1139 ++++ 678 files changed, 107528 insertions(+) create mode 100644 .gitignore create mode 100644 premake5.lua create mode 100644 scripts/win-genprojects.bat create mode 100644 vendor/glfw/LICENSE.md create mode 100644 vendor/glfw/include/GLFW/glfw3.h create mode 100644 vendor/glfw/include/GLFW/glfw3native.h create mode 100644 vendor/glfw/lib-mingw-w64/glfw3.dll create mode 100644 vendor/glfw/lib-mingw-w64/libglfw3.a create mode 100644 vendor/glfw/lib-mingw-w64/libglfw3dll.a create mode 100644 vendor/glfw/lib-vc2012/glfw3.dll create mode 100644 vendor/glfw/lib-vc2012/glfw3.lib create mode 100644 vendor/glfw/lib-vc2012/glfw3dll.lib create mode 100644 vendor/glfw/lib-vc2013/glfw3.dll create mode 100644 vendor/glfw/lib-vc2013/glfw3.lib create mode 100644 vendor/glfw/lib-vc2013/glfw3dll.lib create mode 100644 vendor/glfw/lib-vc2015/glfw3.dll create mode 100644 vendor/glfw/lib-vc2015/glfw3.lib create mode 100644 vendor/glfw/lib-vc2015/glfw3dll.lib create mode 100644 vendor/glfw/lib-vc2017/glfw3.dll create mode 100644 vendor/glfw/lib-vc2017/glfw3.lib create mode 100644 vendor/glfw/lib-vc2017/glfw3dll.lib create mode 100644 vendor/glfw/lib-vc2019/glfw3.dll create mode 100644 vendor/glfw/lib-vc2019/glfw3.lib create mode 100644 vendor/glfw/lib-vc2019/glfw3dll.lib create mode 100644 vendor/glm/.appveyor.yml create mode 100644 vendor/glm/.gitignore create mode 100644 vendor/glm/.travis.yml create mode 100644 vendor/glm/CMakeLists.txt create mode 100644 vendor/glm/cmake/glm/glmConfig-version.cmake create mode 100644 vendor/glm/cmake/glm/glmConfig.cmake create mode 100644 vendor/glm/copying.txt create mode 100644 vendor/glm/glm/CMakeLists.txt create mode 100644 vendor/glm/glm/common.hpp create mode 100644 vendor/glm/glm/detail/_features.hpp create mode 100644 vendor/glm/glm/detail/_fixes.hpp create mode 100644 vendor/glm/glm/detail/_noise.hpp create mode 100644 vendor/glm/glm/detail/_swizzle.hpp create mode 100644 vendor/glm/glm/detail/_swizzle_func.hpp create mode 100644 vendor/glm/glm/detail/_vectorize.hpp create mode 100644 vendor/glm/glm/detail/compute_common.hpp create mode 100644 vendor/glm/glm/detail/compute_vector_relational.hpp create mode 100644 vendor/glm/glm/detail/func_common.inl create mode 100644 vendor/glm/glm/detail/func_common_simd.inl create mode 100644 vendor/glm/glm/detail/func_exponential.inl create mode 100644 vendor/glm/glm/detail/func_exponential_simd.inl create mode 100644 vendor/glm/glm/detail/func_geometric.inl create mode 100644 vendor/glm/glm/detail/func_geometric_simd.inl create mode 100644 vendor/glm/glm/detail/func_integer.inl create mode 100644 vendor/glm/glm/detail/func_integer_simd.inl create mode 100644 vendor/glm/glm/detail/func_matrix.inl create mode 100644 vendor/glm/glm/detail/func_matrix_simd.inl create mode 100644 vendor/glm/glm/detail/func_packing.inl create mode 100644 vendor/glm/glm/detail/func_packing_simd.inl create mode 100644 vendor/glm/glm/detail/func_trigonometric.inl create mode 100644 vendor/glm/glm/detail/func_trigonometric_simd.inl create mode 100644 vendor/glm/glm/detail/func_vector_relational.inl create mode 100644 vendor/glm/glm/detail/func_vector_relational_simd.inl create mode 100644 vendor/glm/glm/detail/glm.cpp create mode 100644 vendor/glm/glm/detail/qualifier.hpp create mode 100644 vendor/glm/glm/detail/setup.hpp create mode 100644 vendor/glm/glm/detail/type_float.hpp create mode 100644 vendor/glm/glm/detail/type_half.hpp create mode 100644 vendor/glm/glm/detail/type_half.inl create mode 100644 vendor/glm/glm/detail/type_mat2x2.hpp create mode 100644 vendor/glm/glm/detail/type_mat2x2.inl create mode 100644 vendor/glm/glm/detail/type_mat2x3.hpp create mode 100644 vendor/glm/glm/detail/type_mat2x3.inl create mode 100644 vendor/glm/glm/detail/type_mat2x4.hpp create mode 100644 vendor/glm/glm/detail/type_mat2x4.inl create mode 100644 vendor/glm/glm/detail/type_mat3x2.hpp create mode 100644 vendor/glm/glm/detail/type_mat3x2.inl create mode 100644 vendor/glm/glm/detail/type_mat3x3.hpp create mode 100644 vendor/glm/glm/detail/type_mat3x3.inl create mode 100644 vendor/glm/glm/detail/type_mat3x4.hpp create mode 100644 vendor/glm/glm/detail/type_mat3x4.inl create mode 100644 vendor/glm/glm/detail/type_mat4x2.hpp create mode 100644 vendor/glm/glm/detail/type_mat4x2.inl create mode 100644 vendor/glm/glm/detail/type_mat4x3.hpp create mode 100644 vendor/glm/glm/detail/type_mat4x3.inl create mode 100644 vendor/glm/glm/detail/type_mat4x4.hpp create mode 100644 vendor/glm/glm/detail/type_mat4x4.inl create mode 100644 vendor/glm/glm/detail/type_mat4x4_simd.inl create mode 100644 vendor/glm/glm/detail/type_quat.hpp create mode 100644 vendor/glm/glm/detail/type_quat.inl create mode 100644 vendor/glm/glm/detail/type_quat_simd.inl create mode 100644 vendor/glm/glm/detail/type_vec1.hpp create mode 100644 vendor/glm/glm/detail/type_vec1.inl create mode 100644 vendor/glm/glm/detail/type_vec2.hpp create mode 100644 vendor/glm/glm/detail/type_vec2.inl create mode 100644 vendor/glm/glm/detail/type_vec3.hpp create mode 100644 vendor/glm/glm/detail/type_vec3.inl create mode 100644 vendor/glm/glm/detail/type_vec4.hpp create mode 100644 vendor/glm/glm/detail/type_vec4.inl create mode 100644 vendor/glm/glm/detail/type_vec4_simd.inl create mode 100644 vendor/glm/glm/exponential.hpp create mode 100644 vendor/glm/glm/ext.hpp create mode 100644 vendor/glm/glm/ext/matrix_clip_space.hpp create mode 100644 vendor/glm/glm/ext/matrix_clip_space.inl create mode 100644 vendor/glm/glm/ext/matrix_common.hpp create mode 100644 vendor/glm/glm/ext/matrix_common.inl create mode 100644 vendor/glm/glm/ext/matrix_double2x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_double2x2_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double2x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_double2x3_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double2x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_double2x4_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double3x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_double3x2_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double3x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_double3x3_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double3x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_double3x4_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double4x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_double4x2_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double4x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_double4x3_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_double4x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_double4x4_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float2x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_float2x2_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float2x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_float2x3_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float2x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_float2x4_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float3x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_float3x2_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float3x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_float3x3_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float3x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_float3x4_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float4x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_float4x2_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float4x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_float4x3_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_float4x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_float4x4_precision.hpp create mode 100644 vendor/glm/glm/ext/matrix_int2x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_int2x2_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int2x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_int2x3_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int2x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_int2x4_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int3x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_int3x2_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int3x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_int3x3_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int3x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_int3x4_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int4x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_int4x2_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int4x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_int4x3_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_int4x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_int4x4_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_projection.hpp create mode 100644 vendor/glm/glm/ext/matrix_projection.inl create mode 100644 vendor/glm/glm/ext/matrix_relational.hpp create mode 100644 vendor/glm/glm/ext/matrix_relational.inl create mode 100644 vendor/glm/glm/ext/matrix_transform.hpp create mode 100644 vendor/glm/glm/ext/matrix_transform.inl create mode 100644 vendor/glm/glm/ext/matrix_uint2x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint2x2_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint2x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint2x3_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint2x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint2x4_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint3x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint3x2_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint3x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint3x3_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint3x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint3x4_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint4x2.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint4x2_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint4x3.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint4x3_sized.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint4x4.hpp create mode 100644 vendor/glm/glm/ext/matrix_uint4x4_sized.hpp create mode 100644 vendor/glm/glm/ext/quaternion_common.hpp create mode 100644 vendor/glm/glm/ext/quaternion_common.inl create mode 100644 vendor/glm/glm/ext/quaternion_common_simd.inl create mode 100644 vendor/glm/glm/ext/quaternion_double.hpp create mode 100644 vendor/glm/glm/ext/quaternion_double_precision.hpp create mode 100644 vendor/glm/glm/ext/quaternion_exponential.hpp create mode 100644 vendor/glm/glm/ext/quaternion_exponential.inl create mode 100644 vendor/glm/glm/ext/quaternion_float.hpp create mode 100644 vendor/glm/glm/ext/quaternion_float_precision.hpp create mode 100644 vendor/glm/glm/ext/quaternion_geometric.hpp create mode 100644 vendor/glm/glm/ext/quaternion_geometric.inl create mode 100644 vendor/glm/glm/ext/quaternion_relational.hpp create mode 100644 vendor/glm/glm/ext/quaternion_relational.inl create mode 100644 vendor/glm/glm/ext/quaternion_transform.hpp create mode 100644 vendor/glm/glm/ext/quaternion_transform.inl create mode 100644 vendor/glm/glm/ext/quaternion_trigonometric.hpp create mode 100644 vendor/glm/glm/ext/quaternion_trigonometric.inl create mode 100644 vendor/glm/glm/ext/scalar_common.hpp create mode 100644 vendor/glm/glm/ext/scalar_common.inl create mode 100644 vendor/glm/glm/ext/scalar_constants.hpp create mode 100644 vendor/glm/glm/ext/scalar_constants.inl create mode 100644 vendor/glm/glm/ext/scalar_int_sized.hpp create mode 100644 vendor/glm/glm/ext/scalar_integer.hpp create mode 100644 vendor/glm/glm/ext/scalar_integer.inl create mode 100644 vendor/glm/glm/ext/scalar_packing.hpp create mode 100644 vendor/glm/glm/ext/scalar_packing.inl create mode 100644 vendor/glm/glm/ext/scalar_relational.hpp create mode 100644 vendor/glm/glm/ext/scalar_relational.inl create mode 100644 vendor/glm/glm/ext/scalar_uint_sized.hpp create mode 100644 vendor/glm/glm/ext/scalar_ulp.hpp create mode 100644 vendor/glm/glm/ext/scalar_ulp.inl create mode 100644 vendor/glm/glm/ext/vector_bool1.hpp create mode 100644 vendor/glm/glm/ext/vector_bool1_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_bool2.hpp create mode 100644 vendor/glm/glm/ext/vector_bool2_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_bool3.hpp create mode 100644 vendor/glm/glm/ext/vector_bool3_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_bool4.hpp create mode 100644 vendor/glm/glm/ext/vector_bool4_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_common.hpp create mode 100644 vendor/glm/glm/ext/vector_common.inl create mode 100644 vendor/glm/glm/ext/vector_double1.hpp create mode 100644 vendor/glm/glm/ext/vector_double1_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_double2.hpp create mode 100644 vendor/glm/glm/ext/vector_double2_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_double3.hpp create mode 100644 vendor/glm/glm/ext/vector_double3_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_double4.hpp create mode 100644 vendor/glm/glm/ext/vector_double4_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_float1.hpp create mode 100644 vendor/glm/glm/ext/vector_float1_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_float2.hpp create mode 100644 vendor/glm/glm/ext/vector_float2_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_float3.hpp create mode 100644 vendor/glm/glm/ext/vector_float3_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_float4.hpp create mode 100644 vendor/glm/glm/ext/vector_float4_precision.hpp create mode 100644 vendor/glm/glm/ext/vector_int1.hpp create mode 100644 vendor/glm/glm/ext/vector_int1_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_int2.hpp create mode 100644 vendor/glm/glm/ext/vector_int2_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_int3.hpp create mode 100644 vendor/glm/glm/ext/vector_int3_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_int4.hpp create mode 100644 vendor/glm/glm/ext/vector_int4_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_integer.hpp create mode 100644 vendor/glm/glm/ext/vector_integer.inl create mode 100644 vendor/glm/glm/ext/vector_packing.hpp create mode 100644 vendor/glm/glm/ext/vector_packing.inl create mode 100644 vendor/glm/glm/ext/vector_relational.hpp create mode 100644 vendor/glm/glm/ext/vector_relational.inl create mode 100644 vendor/glm/glm/ext/vector_uint1.hpp create mode 100644 vendor/glm/glm/ext/vector_uint1_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_uint2.hpp create mode 100644 vendor/glm/glm/ext/vector_uint2_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_uint3.hpp create mode 100644 vendor/glm/glm/ext/vector_uint3_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_uint4.hpp create mode 100644 vendor/glm/glm/ext/vector_uint4_sized.hpp create mode 100644 vendor/glm/glm/ext/vector_ulp.hpp create mode 100644 vendor/glm/glm/ext/vector_ulp.inl create mode 100644 vendor/glm/glm/fwd.hpp create mode 100644 vendor/glm/glm/geometric.hpp create mode 100644 vendor/glm/glm/glm.hpp create mode 100644 vendor/glm/glm/gtc/bitfield.hpp create mode 100644 vendor/glm/glm/gtc/bitfield.inl create mode 100644 vendor/glm/glm/gtc/color_space.hpp create mode 100644 vendor/glm/glm/gtc/color_space.inl create mode 100644 vendor/glm/glm/gtc/constants.hpp create mode 100644 vendor/glm/glm/gtc/constants.inl create mode 100644 vendor/glm/glm/gtc/epsilon.hpp create mode 100644 vendor/glm/glm/gtc/epsilon.inl create mode 100644 vendor/glm/glm/gtc/integer.hpp create mode 100644 vendor/glm/glm/gtc/integer.inl create mode 100644 vendor/glm/glm/gtc/matrix_access.hpp create mode 100644 vendor/glm/glm/gtc/matrix_access.inl create mode 100644 vendor/glm/glm/gtc/matrix_integer.hpp create mode 100644 vendor/glm/glm/gtc/matrix_inverse.hpp create mode 100644 vendor/glm/glm/gtc/matrix_inverse.inl create mode 100644 vendor/glm/glm/gtc/matrix_transform.hpp create mode 100644 vendor/glm/glm/gtc/matrix_transform.inl create mode 100644 vendor/glm/glm/gtc/noise.hpp create mode 100644 vendor/glm/glm/gtc/noise.inl create mode 100644 vendor/glm/glm/gtc/packing.hpp create mode 100644 vendor/glm/glm/gtc/packing.inl create mode 100644 vendor/glm/glm/gtc/quaternion.hpp create mode 100644 vendor/glm/glm/gtc/quaternion.inl create mode 100644 vendor/glm/glm/gtc/quaternion_simd.inl create mode 100644 vendor/glm/glm/gtc/random.hpp create mode 100644 vendor/glm/glm/gtc/random.inl create mode 100644 vendor/glm/glm/gtc/reciprocal.hpp create mode 100644 vendor/glm/glm/gtc/reciprocal.inl create mode 100644 vendor/glm/glm/gtc/round.hpp create mode 100644 vendor/glm/glm/gtc/round.inl create mode 100644 vendor/glm/glm/gtc/type_aligned.hpp create mode 100644 vendor/glm/glm/gtc/type_precision.hpp create mode 100644 vendor/glm/glm/gtc/type_precision.inl create mode 100644 vendor/glm/glm/gtc/type_ptr.hpp create mode 100644 vendor/glm/glm/gtc/type_ptr.inl create mode 100644 vendor/glm/glm/gtc/ulp.hpp create mode 100644 vendor/glm/glm/gtc/ulp.inl create mode 100644 vendor/glm/glm/gtc/vec1.hpp create mode 100644 vendor/glm/glm/gtx/associated_min_max.hpp create mode 100644 vendor/glm/glm/gtx/associated_min_max.inl create mode 100644 vendor/glm/glm/gtx/bit.hpp create mode 100644 vendor/glm/glm/gtx/bit.inl create mode 100644 vendor/glm/glm/gtx/closest_point.hpp create mode 100644 vendor/glm/glm/gtx/closest_point.inl create mode 100644 vendor/glm/glm/gtx/color_encoding.hpp create mode 100644 vendor/glm/glm/gtx/color_encoding.inl create mode 100644 vendor/glm/glm/gtx/color_space.hpp create mode 100644 vendor/glm/glm/gtx/color_space.inl create mode 100644 vendor/glm/glm/gtx/color_space_YCoCg.hpp create mode 100644 vendor/glm/glm/gtx/color_space_YCoCg.inl create mode 100644 vendor/glm/glm/gtx/common.hpp create mode 100644 vendor/glm/glm/gtx/common.inl create mode 100644 vendor/glm/glm/gtx/compatibility.hpp create mode 100644 vendor/glm/glm/gtx/compatibility.inl create mode 100644 vendor/glm/glm/gtx/component_wise.hpp create mode 100644 vendor/glm/glm/gtx/component_wise.inl create mode 100644 vendor/glm/glm/gtx/dual_quaternion.hpp create mode 100644 vendor/glm/glm/gtx/dual_quaternion.inl create mode 100644 vendor/glm/glm/gtx/easing.hpp create mode 100644 vendor/glm/glm/gtx/easing.inl create mode 100644 vendor/glm/glm/gtx/euler_angles.hpp create mode 100644 vendor/glm/glm/gtx/euler_angles.inl create mode 100644 vendor/glm/glm/gtx/extend.hpp create mode 100644 vendor/glm/glm/gtx/extend.inl create mode 100644 vendor/glm/glm/gtx/extended_min_max.hpp create mode 100644 vendor/glm/glm/gtx/extended_min_max.inl create mode 100644 vendor/glm/glm/gtx/exterior_product.hpp create mode 100644 vendor/glm/glm/gtx/exterior_product.inl create mode 100644 vendor/glm/glm/gtx/fast_exponential.hpp create mode 100644 vendor/glm/glm/gtx/fast_exponential.inl create mode 100644 vendor/glm/glm/gtx/fast_square_root.hpp create mode 100644 vendor/glm/glm/gtx/fast_square_root.inl create mode 100644 vendor/glm/glm/gtx/fast_trigonometry.hpp create mode 100644 vendor/glm/glm/gtx/fast_trigonometry.inl create mode 100644 vendor/glm/glm/gtx/float_notmalize.inl create mode 100644 vendor/glm/glm/gtx/functions.hpp create mode 100644 vendor/glm/glm/gtx/functions.inl create mode 100644 vendor/glm/glm/gtx/gradient_paint.hpp create mode 100644 vendor/glm/glm/gtx/gradient_paint.inl create mode 100644 vendor/glm/glm/gtx/handed_coordinate_space.hpp create mode 100644 vendor/glm/glm/gtx/handed_coordinate_space.inl create mode 100644 vendor/glm/glm/gtx/hash.hpp create mode 100644 vendor/glm/glm/gtx/hash.inl create mode 100644 vendor/glm/glm/gtx/integer.hpp create mode 100644 vendor/glm/glm/gtx/integer.inl create mode 100644 vendor/glm/glm/gtx/intersect.hpp create mode 100644 vendor/glm/glm/gtx/intersect.inl create mode 100644 vendor/glm/glm/gtx/io.hpp create mode 100644 vendor/glm/glm/gtx/io.inl create mode 100644 vendor/glm/glm/gtx/log_base.hpp create mode 100644 vendor/glm/glm/gtx/log_base.inl create mode 100644 vendor/glm/glm/gtx/matrix_cross_product.hpp create mode 100644 vendor/glm/glm/gtx/matrix_cross_product.inl create mode 100644 vendor/glm/glm/gtx/matrix_decompose.hpp create mode 100644 vendor/glm/glm/gtx/matrix_decompose.inl create mode 100644 vendor/glm/glm/gtx/matrix_factorisation.hpp create mode 100644 vendor/glm/glm/gtx/matrix_factorisation.inl create mode 100644 vendor/glm/glm/gtx/matrix_interpolation.hpp create mode 100644 vendor/glm/glm/gtx/matrix_interpolation.inl create mode 100644 vendor/glm/glm/gtx/matrix_major_storage.hpp create mode 100644 vendor/glm/glm/gtx/matrix_major_storage.inl create mode 100644 vendor/glm/glm/gtx/matrix_operation.hpp create mode 100644 vendor/glm/glm/gtx/matrix_operation.inl create mode 100644 vendor/glm/glm/gtx/matrix_query.hpp create mode 100644 vendor/glm/glm/gtx/matrix_query.inl create mode 100644 vendor/glm/glm/gtx/matrix_transform_2d.hpp create mode 100644 vendor/glm/glm/gtx/matrix_transform_2d.inl create mode 100644 vendor/glm/glm/gtx/mixed_product.hpp create mode 100644 vendor/glm/glm/gtx/mixed_product.inl create mode 100644 vendor/glm/glm/gtx/norm.hpp create mode 100644 vendor/glm/glm/gtx/norm.inl create mode 100644 vendor/glm/glm/gtx/normal.hpp create mode 100644 vendor/glm/glm/gtx/normal.inl create mode 100644 vendor/glm/glm/gtx/normalize_dot.hpp create mode 100644 vendor/glm/glm/gtx/normalize_dot.inl create mode 100644 vendor/glm/glm/gtx/number_precision.hpp create mode 100644 vendor/glm/glm/gtx/number_precision.inl create mode 100644 vendor/glm/glm/gtx/optimum_pow.hpp create mode 100644 vendor/glm/glm/gtx/optimum_pow.inl create mode 100644 vendor/glm/glm/gtx/orthonormalize.hpp create mode 100644 vendor/glm/glm/gtx/orthonormalize.inl create mode 100644 vendor/glm/glm/gtx/perpendicular.hpp create mode 100644 vendor/glm/glm/gtx/perpendicular.inl create mode 100644 vendor/glm/glm/gtx/polar_coordinates.hpp create mode 100644 vendor/glm/glm/gtx/polar_coordinates.inl create mode 100644 vendor/glm/glm/gtx/projection.hpp create mode 100644 vendor/glm/glm/gtx/projection.inl create mode 100644 vendor/glm/glm/gtx/quaternion.hpp create mode 100644 vendor/glm/glm/gtx/quaternion.inl create mode 100644 vendor/glm/glm/gtx/range.hpp create mode 100644 vendor/glm/glm/gtx/raw_data.hpp create mode 100644 vendor/glm/glm/gtx/raw_data.inl create mode 100644 vendor/glm/glm/gtx/rotate_normalized_axis.hpp create mode 100644 vendor/glm/glm/gtx/rotate_normalized_axis.inl create mode 100644 vendor/glm/glm/gtx/rotate_vector.hpp create mode 100644 vendor/glm/glm/gtx/rotate_vector.inl create mode 100644 vendor/glm/glm/gtx/scalar_multiplication.hpp create mode 100644 vendor/glm/glm/gtx/scalar_relational.hpp create mode 100644 vendor/glm/glm/gtx/scalar_relational.inl create mode 100644 vendor/glm/glm/gtx/spline.hpp create mode 100644 vendor/glm/glm/gtx/spline.inl create mode 100644 vendor/glm/glm/gtx/std_based_type.hpp create mode 100644 vendor/glm/glm/gtx/std_based_type.inl create mode 100644 vendor/glm/glm/gtx/string_cast.hpp create mode 100644 vendor/glm/glm/gtx/string_cast.inl create mode 100644 vendor/glm/glm/gtx/texture.hpp create mode 100644 vendor/glm/glm/gtx/texture.inl create mode 100644 vendor/glm/glm/gtx/transform.hpp create mode 100644 vendor/glm/glm/gtx/transform.inl create mode 100644 vendor/glm/glm/gtx/transform2.hpp create mode 100644 vendor/glm/glm/gtx/transform2.inl create mode 100644 vendor/glm/glm/gtx/type_aligned.hpp create mode 100644 vendor/glm/glm/gtx/type_aligned.inl create mode 100644 vendor/glm/glm/gtx/type_trait.hpp create mode 100644 vendor/glm/glm/gtx/type_trait.inl create mode 100644 vendor/glm/glm/gtx/vec_swizzle.hpp create mode 100644 vendor/glm/glm/gtx/vector_angle.hpp create mode 100644 vendor/glm/glm/gtx/vector_angle.inl create mode 100644 vendor/glm/glm/gtx/vector_query.hpp create mode 100644 vendor/glm/glm/gtx/vector_query.inl create mode 100644 vendor/glm/glm/gtx/wrap.hpp create mode 100644 vendor/glm/glm/gtx/wrap.inl create mode 100644 vendor/glm/glm/integer.hpp create mode 100644 vendor/glm/glm/mat2x2.hpp create mode 100644 vendor/glm/glm/mat2x3.hpp create mode 100644 vendor/glm/glm/mat2x4.hpp create mode 100644 vendor/glm/glm/mat3x2.hpp create mode 100644 vendor/glm/glm/mat3x3.hpp create mode 100644 vendor/glm/glm/mat3x4.hpp create mode 100644 vendor/glm/glm/mat4x2.hpp create mode 100644 vendor/glm/glm/mat4x3.hpp create mode 100644 vendor/glm/glm/mat4x4.hpp create mode 100644 vendor/glm/glm/matrix.hpp create mode 100644 vendor/glm/glm/packing.hpp create mode 100644 vendor/glm/glm/simd/common.h create mode 100644 vendor/glm/glm/simd/exponential.h create mode 100644 vendor/glm/glm/simd/geometric.h create mode 100644 vendor/glm/glm/simd/integer.h create mode 100644 vendor/glm/glm/simd/matrix.h create mode 100644 vendor/glm/glm/simd/neon.h create mode 100644 vendor/glm/glm/simd/packing.h create mode 100644 vendor/glm/glm/simd/platform.h create mode 100644 vendor/glm/glm/simd/trigonometric.h create mode 100644 vendor/glm/glm/simd/vector_relational.h create mode 100644 vendor/glm/glm/trigonometric.hpp create mode 100644 vendor/glm/glm/vec2.hpp create mode 100644 vendor/glm/glm/vec3.hpp create mode 100644 vendor/glm/glm/vec4.hpp create mode 100644 vendor/glm/glm/vector_relational.hpp create mode 100644 vendor/glm/manual.md create mode 100644 vendor/glm/readme.md create mode 100644 vendor/glm/test/CMakeLists.txt create mode 100644 vendor/glm/test/bug/CMakeLists.txt create mode 100644 vendor/glm/test/bug/bug_ms_vec_static.cpp create mode 100644 vendor/glm/test/cmake/CMakeLists.txt create mode 100644 vendor/glm/test/cmake/test_find_glm.cpp create mode 100644 vendor/glm/test/core/CMakeLists.txt create mode 100644 vendor/glm/test/core/core_cpp_constexpr.cpp create mode 100644 vendor/glm/test/core/core_cpp_defaulted_ctor.cpp create mode 100644 vendor/glm/test/core/core_force_aligned_gentypes.cpp create mode 100644 vendor/glm/test/core/core_force_arch_unknown.cpp create mode 100644 vendor/glm/test/core/core_force_compiler_unknown.cpp create mode 100644 vendor/glm/test/core/core_force_ctor_init.cpp create mode 100644 vendor/glm/test/core/core_force_cxx03.cpp create mode 100644 vendor/glm/test/core/core_force_cxx98.cpp create mode 100644 vendor/glm/test/core/core_force_cxx_unknown.cpp create mode 100644 vendor/glm/test/core/core_force_depth_zero_to_one.cpp create mode 100644 vendor/glm/test/core/core_force_explicit_ctor.cpp create mode 100644 vendor/glm/test/core/core_force_inline.cpp create mode 100644 vendor/glm/test/core/core_force_left_handed.cpp create mode 100644 vendor/glm/test/core/core_force_platform_unknown.cpp create mode 100644 vendor/glm/test/core/core_force_pure.cpp create mode 100644 vendor/glm/test/core/core_force_quat_wxyz.cpp create mode 100644 vendor/glm/test/core/core_force_size_t_length.cpp create mode 100644 vendor/glm/test/core/core_force_unrestricted_gentype.cpp create mode 100644 vendor/glm/test/core/core_force_xyzw_only.cpp create mode 100644 vendor/glm/test/core/core_func_common.cpp create mode 100644 vendor/glm/test/core/core_func_exponential.cpp create mode 100644 vendor/glm/test/core/core_func_geometric.cpp create mode 100644 vendor/glm/test/core/core_func_integer.cpp create mode 100644 vendor/glm/test/core/core_func_integer_bit_count.cpp create mode 100644 vendor/glm/test/core/core_func_integer_find_lsb.cpp create mode 100644 vendor/glm/test/core/core_func_integer_find_msb.cpp create mode 100644 vendor/glm/test/core/core_func_matrix.cpp create mode 100644 vendor/glm/test/core/core_func_noise.cpp create mode 100644 vendor/glm/test/core/core_func_packing.cpp create mode 100644 vendor/glm/test/core/core_func_swizzle.cpp create mode 100644 vendor/glm/test/core/core_func_trigonometric.cpp create mode 100644 vendor/glm/test/core/core_func_vector_relational.cpp create mode 100644 vendor/glm/test/core/core_setup_force_cxx98.cpp create mode 100644 vendor/glm/test/core/core_setup_force_size_t_length.cpp create mode 100644 vendor/glm/test/core/core_setup_message.cpp create mode 100644 vendor/glm/test/core/core_setup_platform_unknown.cpp create mode 100644 vendor/glm/test/core/core_setup_precision.cpp create mode 100644 vendor/glm/test/core/core_type_aligned.cpp create mode 100644 vendor/glm/test/core/core_type_cast.cpp create mode 100644 vendor/glm/test/core/core_type_ctor.cpp create mode 100644 vendor/glm/test/core/core_type_int.cpp create mode 100644 vendor/glm/test/core/core_type_length.cpp create mode 100644 vendor/glm/test/core/core_type_mat2x2.cpp create mode 100644 vendor/glm/test/core/core_type_mat2x3.cpp create mode 100644 vendor/glm/test/core/core_type_mat2x4.cpp create mode 100644 vendor/glm/test/core/core_type_mat3x2.cpp create mode 100644 vendor/glm/test/core/core_type_mat3x3.cpp create mode 100644 vendor/glm/test/core/core_type_mat3x4.cpp create mode 100644 vendor/glm/test/core/core_type_mat4x2.cpp create mode 100644 vendor/glm/test/core/core_type_mat4x3.cpp create mode 100644 vendor/glm/test/core/core_type_mat4x4.cpp create mode 100644 vendor/glm/test/core/core_type_vec1.cpp create mode 100644 vendor/glm/test/core/core_type_vec2.cpp create mode 100644 vendor/glm/test/core/core_type_vec3.cpp create mode 100644 vendor/glm/test/core/core_type_vec4.cpp create mode 100644 vendor/glm/test/ext/CMakeLists.txt create mode 100644 vendor/glm/test/ext/ext_matrix_clip_space.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_common.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int2x2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int2x3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int2x4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int3x2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int3x3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int3x4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int4x2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int4x3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_int4x4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_projection.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_relational.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_transform.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint2x2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint2x3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint2x4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint3x2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint3x3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint3x4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint4x2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint4x3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_matrix_uint4x4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_quaternion_common.cpp create mode 100644 vendor/glm/test/ext/ext_quaternion_exponential.cpp create mode 100644 vendor/glm/test/ext/ext_quaternion_geometric.cpp create mode 100644 vendor/glm/test/ext/ext_quaternion_relational.cpp create mode 100644 vendor/glm/test/ext/ext_quaternion_transform.cpp create mode 100644 vendor/glm/test/ext/ext_quaternion_trigonometric.cpp create mode 100644 vendor/glm/test/ext/ext_quaternion_type.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_common.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_constants.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_int_sized.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_integer.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_packing.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_relational.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_uint_sized.cpp create mode 100644 vendor/glm/test/ext/ext_scalar_ulp.cpp create mode 100644 vendor/glm/test/ext/ext_vec1.cpp create mode 100644 vendor/glm/test/ext/ext_vector_bool1.cpp create mode 100644 vendor/glm/test/ext/ext_vector_common.cpp create mode 100644 vendor/glm/test/ext/ext_vector_iec559.cpp create mode 100644 vendor/glm/test/ext/ext_vector_int1_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_int2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_int3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_int4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_integer.cpp create mode 100644 vendor/glm/test/ext/ext_vector_integer_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_packing.cpp create mode 100644 vendor/glm/test/ext/ext_vector_relational.cpp create mode 100644 vendor/glm/test/ext/ext_vector_uint1_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_uint2_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_uint3_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_uint4_sized.cpp create mode 100644 vendor/glm/test/ext/ext_vector_ulp.cpp create mode 100644 vendor/glm/test/glm.cppcheck create mode 100644 vendor/glm/test/gtc/CMakeLists.txt create mode 100644 vendor/glm/test/gtc/gtc_bitfield.cpp create mode 100644 vendor/glm/test/gtc/gtc_color_space.cpp create mode 100644 vendor/glm/test/gtc/gtc_constants.cpp create mode 100644 vendor/glm/test/gtc/gtc_epsilon.cpp create mode 100644 vendor/glm/test/gtc/gtc_integer.cpp create mode 100644 vendor/glm/test/gtc/gtc_matrix_access.cpp create mode 100644 vendor/glm/test/gtc/gtc_matrix_integer.cpp create mode 100644 vendor/glm/test/gtc/gtc_matrix_inverse.cpp create mode 100644 vendor/glm/test/gtc/gtc_matrix_transform.cpp create mode 100644 vendor/glm/test/gtc/gtc_noise.cpp create mode 100644 vendor/glm/test/gtc/gtc_packing.cpp create mode 100644 vendor/glm/test/gtc/gtc_quaternion.cpp create mode 100644 vendor/glm/test/gtc/gtc_random.cpp create mode 100644 vendor/glm/test/gtc/gtc_reciprocal.cpp create mode 100644 vendor/glm/test/gtc/gtc_round.cpp create mode 100644 vendor/glm/test/gtc/gtc_type_aligned.cpp create mode 100644 vendor/glm/test/gtc/gtc_type_precision.cpp create mode 100644 vendor/glm/test/gtc/gtc_type_ptr.cpp create mode 100644 vendor/glm/test/gtc/gtc_ulp.cpp create mode 100644 vendor/glm/test/gtc/gtc_user_defined_types.cpp create mode 100644 vendor/glm/test/gtc/gtc_vec1.cpp create mode 100644 vendor/glm/test/gtx/CMakeLists.txt create mode 100644 vendor/glm/test/gtx/gtx.cpp create mode 100644 vendor/glm/test/gtx/gtx_associated_min_max.cpp create mode 100644 vendor/glm/test/gtx/gtx_closest_point.cpp create mode 100644 vendor/glm/test/gtx/gtx_color_encoding.cpp create mode 100644 vendor/glm/test/gtx/gtx_color_space.cpp create mode 100644 vendor/glm/test/gtx/gtx_color_space_YCoCg.cpp create mode 100644 vendor/glm/test/gtx/gtx_common.cpp create mode 100644 vendor/glm/test/gtx/gtx_compatibility.cpp create mode 100644 vendor/glm/test/gtx/gtx_component_wise.cpp create mode 100644 vendor/glm/test/gtx/gtx_dual_quaternion.cpp create mode 100644 vendor/glm/test/gtx/gtx_easing.cpp create mode 100644 vendor/glm/test/gtx/gtx_euler_angle.cpp create mode 100644 vendor/glm/test/gtx/gtx_extend.cpp create mode 100644 vendor/glm/test/gtx/gtx_extended_min_max.cpp create mode 100644 vendor/glm/test/gtx/gtx_extented_min_max.cpp create mode 100644 vendor/glm/test/gtx/gtx_exterior_product.cpp create mode 100644 vendor/glm/test/gtx/gtx_fast_exponential.cpp create mode 100644 vendor/glm/test/gtx/gtx_fast_square_root.cpp create mode 100644 vendor/glm/test/gtx/gtx_fast_trigonometry.cpp create mode 100644 vendor/glm/test/gtx/gtx_functions.cpp create mode 100644 vendor/glm/test/gtx/gtx_gradient_paint.cpp create mode 100644 vendor/glm/test/gtx/gtx_handed_coordinate_space.cpp create mode 100644 vendor/glm/test/gtx/gtx_int_10_10_10_2.cpp create mode 100644 vendor/glm/test/gtx/gtx_integer.cpp create mode 100644 vendor/glm/test/gtx/gtx_intersect.cpp create mode 100644 vendor/glm/test/gtx/gtx_io.cpp create mode 100644 vendor/glm/test/gtx/gtx_load.cpp create mode 100644 vendor/glm/test/gtx/gtx_log_base.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_cross_product.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_decompose.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_factorisation.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_interpolation.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_major_storage.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_operation.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_query.cpp create mode 100644 vendor/glm/test/gtx/gtx_matrix_transform_2d.cpp create mode 100644 vendor/glm/test/gtx/gtx_mixed_product.cpp create mode 100644 vendor/glm/test/gtx/gtx_norm.cpp create mode 100644 vendor/glm/test/gtx/gtx_normal.cpp create mode 100644 vendor/glm/test/gtx/gtx_normalize_dot.cpp create mode 100644 vendor/glm/test/gtx/gtx_number_precision.cpp create mode 100644 vendor/glm/test/gtx/gtx_optimum_pow.cpp create mode 100644 vendor/glm/test/gtx/gtx_orthonormalize.cpp create mode 100644 vendor/glm/test/gtx/gtx_perpendicular.cpp create mode 100644 vendor/glm/test/gtx/gtx_polar_coordinates.cpp create mode 100644 vendor/glm/test/gtx/gtx_projection.cpp create mode 100644 vendor/glm/test/gtx/gtx_quaternion.cpp create mode 100644 vendor/glm/test/gtx/gtx_random.cpp create mode 100644 vendor/glm/test/gtx/gtx_range.cpp create mode 100644 vendor/glm/test/gtx/gtx_rotate_normalized_axis.cpp create mode 100644 vendor/glm/test/gtx/gtx_rotate_vector.cpp create mode 100644 vendor/glm/test/gtx/gtx_scalar_multiplication.cpp create mode 100644 vendor/glm/test/gtx/gtx_scalar_relational.cpp create mode 100644 vendor/glm/test/gtx/gtx_simd_mat4.cpp create mode 100644 vendor/glm/test/gtx/gtx_simd_vec4.cpp create mode 100644 vendor/glm/test/gtx/gtx_spline.cpp create mode 100644 vendor/glm/test/gtx/gtx_string_cast.cpp create mode 100644 vendor/glm/test/gtx/gtx_texture.cpp create mode 100644 vendor/glm/test/gtx/gtx_type_aligned.cpp create mode 100644 vendor/glm/test/gtx/gtx_type_trait.cpp create mode 100644 vendor/glm/test/gtx/gtx_vec_swizzle.cpp create mode 100644 vendor/glm/test/gtx/gtx_vector_angle.cpp create mode 100644 vendor/glm/test/gtx/gtx_vector_query.cpp create mode 100644 vendor/glm/test/gtx/gtx_wrap.cpp create mode 100644 vendor/glm/test/perf/CMakeLists.txt create mode 100644 vendor/glm/test/perf/perf_matrix_div.cpp create mode 100644 vendor/glm/test/perf/perf_matrix_inverse.cpp create mode 100644 vendor/glm/test/perf/perf_matrix_mul.cpp create mode 100644 vendor/glm/test/perf/perf_matrix_mul_vector.cpp create mode 100644 vendor/glm/test/perf/perf_matrix_transpose.cpp create mode 100644 vendor/glm/test/perf/perf_vector_mul_matrix.cpp create mode 100644 vendor/glm/util/autoexp.txt create mode 100644 vendor/glm/util/autoexp.vc2010.dat create mode 100644 vendor/glm/util/glm.natvis create mode 100644 vendor/glm/util/usertype.dat create mode 100644 vendor/premake/bin/LICENSE.txt create mode 100644 vendor/premake/bin/premake5.exe create mode 100644 vktest/assets/shaders/frag.spv create mode 100644 vktest/assets/shaders/shader.frag create mode 100644 vktest/assets/shaders/shader.vert create mode 100644 vktest/assets/shaders/vert.spv create mode 100644 vktest/compileShaders.bat create mode 100644 vktest/premake5.lua create mode 100644 vktest/src/main.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c0e5b2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# Binaries +**/bin/ +!vendor/premake/bin/ +bin-int/ + +# Custom files +*.log +**Profile*.json + +# Visual Studio files and folders +.vs/ +**.sln +**.vcxproj +**.vcxproj.filters +**.vcxproj.user + diff --git a/premake5.lua b/premake5.lua new file mode 100644 index 0000000..1c8d901 --- /dev/null +++ b/premake5.lua @@ -0,0 +1,20 @@ +workspace "vktest" + architecture "x86_64" + startproject "vktest" + + configurations + { + "Debug", + "Release", + "Dist" + } + + flags + { + --"MultiProcessorCompile" + } + +outputdir = "%{cfg.buildcfg}-%{cfg.system}-%{cfg.architecture}" + +include "vktest" + diff --git a/scripts/win-genprojects.bat b/scripts/win-genprojects.bat new file mode 100644 index 0000000..435ac78 --- /dev/null +++ b/scripts/win-genprojects.bat @@ -0,0 +1,5 @@ +@echo off +pushd %~dp0\..\ +call vendor\premake\bin\premake5.exe vs2019 +popd +PAUSE \ No newline at end of file diff --git a/vendor/glfw/LICENSE.md b/vendor/glfw/LICENSE.md new file mode 100644 index 0000000..7494a3f --- /dev/null +++ b/vendor/glfw/LICENSE.md @@ -0,0 +1,23 @@ +Copyright (c) 2002-2006 Marcus Geelnard + +Copyright (c) 2006-2019 Camilla Löwy + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would + be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not + be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. + diff --git a/vendor/glfw/include/GLFW/glfw3.h b/vendor/glfw/include/GLFW/glfw3.h new file mode 100644 index 0000000..66dff64 --- /dev/null +++ b/vendor/glfw/include/GLFW/glfw3.h @@ -0,0 +1,5874 @@ +/************************************************************************* + * GLFW 3.3 - www.glfw.org + * A library for OpenGL, window and input + *------------------------------------------------------------------------ + * Copyright (c) 2002-2006 Marcus Geelnard + * Copyright (c) 2006-2019 Camilla Löwy + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would + * be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + *************************************************************************/ + +#ifndef _glfw3_h_ +#define _glfw3_h_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************* + * Doxygen documentation + *************************************************************************/ + +/*! @file glfw3.h + * @brief The header of the GLFW 3 API. + * + * This is the header file of the GLFW 3 API. It defines all its types and + * declares all its functions. + * + * For more information about how to use this file, see @ref build_include. + */ +/*! @defgroup context Context reference + * @brief Functions and types related to OpenGL and OpenGL ES contexts. + * + * This is the reference documentation for OpenGL and OpenGL ES context related + * functions. For more task-oriented information, see the @ref context_guide. + */ +/*! @defgroup vulkan Vulkan reference + * @brief Functions and types related to Vulkan. + * + * This is the reference documentation for Vulkan related functions and types. + * For more task-oriented information, see the @ref vulkan_guide. + */ +/*! @defgroup init Initialization, version and error reference + * @brief Functions and types related to initialization and error handling. + * + * This is the reference documentation for initialization and termination of + * the library, version management and error handling. For more task-oriented + * information, see the @ref intro_guide. + */ +/*! @defgroup input Input reference + * @brief Functions and types related to input handling. + * + * This is the reference documentation for input related functions and types. + * For more task-oriented information, see the @ref input_guide. + */ +/*! @defgroup monitor Monitor reference + * @brief Functions and types related to monitors. + * + * This is the reference documentation for monitor related functions and types. + * For more task-oriented information, see the @ref monitor_guide. + */ +/*! @defgroup window Window reference + * @brief Functions and types related to windows. + * + * This is the reference documentation for window related functions and types, + * including creation, deletion and event polling. For more task-oriented + * information, see the @ref window_guide. + */ + + +/************************************************************************* + * Compiler- and platform-specific preprocessor work + *************************************************************************/ + +/* If we are we on Windows, we want a single define for it. + */ +#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) + #define _WIN32 +#endif /* _WIN32 */ + +/* Include because most Windows GLU headers need wchar_t and + * the macOS OpenGL header blocks the definition of ptrdiff_t by glext.h. + * Include it unconditionally to avoid surprising side-effects. + */ +#include + +/* Include because it is needed by Vulkan and related functions. + * Include it unconditionally to avoid surprising side-effects. + */ +#include + +#if defined(GLFW_INCLUDE_VULKAN) + #include +#endif /* Vulkan header */ + +/* The Vulkan header may have indirectly included windows.h (because of + * VK_USE_PLATFORM_WIN32_KHR) so we offer our replacement symbols after it. + */ + +/* It is customary to use APIENTRY for OpenGL function pointer declarations on + * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. + */ +#if !defined(APIENTRY) + #if defined(_WIN32) + #define APIENTRY __stdcall + #else + #define APIENTRY + #endif + #define GLFW_APIENTRY_DEFINED +#endif /* APIENTRY */ + +/* Some Windows OpenGL headers need this. + */ +#if !defined(WINGDIAPI) && defined(_WIN32) + #define WINGDIAPI __declspec(dllimport) + #define GLFW_WINGDIAPI_DEFINED +#endif /* WINGDIAPI */ + +/* Some Windows GLU headers need this. + */ +#if !defined(CALLBACK) && defined(_WIN32) + #define CALLBACK __stdcall + #define GLFW_CALLBACK_DEFINED +#endif /* CALLBACK */ + +/* Include the chosen OpenGL or OpenGL ES headers. + */ +#if defined(GLFW_INCLUDE_ES1) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES2) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES3) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES31) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_ES32) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + +#elif defined(GLFW_INCLUDE_GLCOREARB) + + #if defined(__APPLE__) + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif /*GLFW_INCLUDE_GLEXT*/ + + #else /*__APPLE__*/ + + #include + + #endif /*__APPLE__*/ + +#elif !defined(GLFW_INCLUDE_NONE) + + #if defined(__APPLE__) + + #if !defined(GLFW_INCLUDE_GLEXT) + #define GL_GLEXT_LEGACY + #endif + #include + #if defined(GLFW_INCLUDE_GLU) + #include + #endif + + #else /*__APPLE__*/ + + #include + #if defined(GLFW_INCLUDE_GLEXT) + #include + #endif + #if defined(GLFW_INCLUDE_GLU) + #include + #endif + + #endif /*__APPLE__*/ + +#endif /* OpenGL and OpenGL ES headers */ + +#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL) + /* GLFW_DLL must be defined by applications that are linking against the DLL + * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW + * configuration header when compiling the DLL version of the library. + */ + #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined" +#endif + +/* GLFWAPI is used to declare public API functions for export + * from the DLL / shared library / dynamic library. + */ +#if defined(_WIN32) && defined(_GLFW_BUILD_DLL) + /* We are building GLFW as a Win32 DLL */ + #define GLFWAPI __declspec(dllexport) +#elif defined(_WIN32) && defined(GLFW_DLL) + /* We are calling GLFW as a Win32 DLL */ + #define GLFWAPI __declspec(dllimport) +#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) + /* We are building GLFW as a shared / dynamic library */ + #define GLFWAPI __attribute__((visibility("default"))) +#else + /* We are building or calling GLFW as a static library */ + #define GLFWAPI +#endif + + +/************************************************************************* + * GLFW API tokens + *************************************************************************/ + +/*! @name GLFW version macros + * @{ */ +/*! @brief The major version number of the GLFW library. + * + * This is incremented when the API is changed in non-compatible ways. + * @ingroup init + */ +#define GLFW_VERSION_MAJOR 3 +/*! @brief The minor version number of the GLFW library. + * + * This is incremented when features are added to the API but it remains + * backward-compatible. + * @ingroup init + */ +#define GLFW_VERSION_MINOR 3 +/*! @brief The revision number of the GLFW library. + * + * This is incremented when a bug fix release is made that does not contain any + * API changes. + * @ingroup init + */ +#define GLFW_VERSION_REVISION 2 +/*! @} */ + +/*! @brief One. + * + * This is only semantic sugar for the number 1. You can instead use `1` or + * `true` or `_True` or `GL_TRUE` or `VK_TRUE` or anything else that is equal + * to one. + * + * @ingroup init + */ +#define GLFW_TRUE 1 +/*! @brief Zero. + * + * This is only semantic sugar for the number 0. You can instead use `0` or + * `false` or `_False` or `GL_FALSE` or `VK_FALSE` or anything else that is + * equal to zero. + * + * @ingroup init + */ +#define GLFW_FALSE 0 + +/*! @name Key and button actions + * @{ */ +/*! @brief The key or mouse button was released. + * + * The key or mouse button was released. + * + * @ingroup input + */ +#define GLFW_RELEASE 0 +/*! @brief The key or mouse button was pressed. + * + * The key or mouse button was pressed. + * + * @ingroup input + */ +#define GLFW_PRESS 1 +/*! @brief The key was held down until it repeated. + * + * The key was held down until it repeated. + * + * @ingroup input + */ +#define GLFW_REPEAT 2 +/*! @} */ + +/*! @defgroup hat_state Joystick hat states + * @brief Joystick hat states. + * + * See [joystick hat input](@ref joystick_hat) for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_HAT_CENTERED 0 +#define GLFW_HAT_UP 1 +#define GLFW_HAT_RIGHT 2 +#define GLFW_HAT_DOWN 4 +#define GLFW_HAT_LEFT 8 +#define GLFW_HAT_RIGHT_UP (GLFW_HAT_RIGHT | GLFW_HAT_UP) +#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN) +#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP) +#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN) +/*! @} */ + +/*! @defgroup keys Keyboard keys + * @brief Keyboard key IDs. + * + * See [key input](@ref input_key) for how these are used. + * + * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60), + * but re-arranged to map to 7-bit ASCII for printable keys (function keys are + * put in the 256+ range). + * + * The naming of the key codes follow these rules: + * - The US keyboard layout is used + * - Names of printable alpha-numeric characters are used (e.g. "A", "R", + * "3", etc.) + * - For non-alphanumeric characters, Unicode:ish names are used (e.g. + * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not + * correspond to the Unicode standard (usually for brevity) + * - Keys that lack a clear US mapping are named "WORLD_x" + * - For non-printable keys, custom names are used (e.g. "F4", + * "BACKSPACE", etc.) + * + * @ingroup input + * @{ + */ + +/* The unknown key */ +#define GLFW_KEY_UNKNOWN -1 + +/* Printable keys */ +#define GLFW_KEY_SPACE 32 +#define GLFW_KEY_APOSTROPHE 39 /* ' */ +#define GLFW_KEY_COMMA 44 /* , */ +#define GLFW_KEY_MINUS 45 /* - */ +#define GLFW_KEY_PERIOD 46 /* . */ +#define GLFW_KEY_SLASH 47 /* / */ +#define GLFW_KEY_0 48 +#define GLFW_KEY_1 49 +#define GLFW_KEY_2 50 +#define GLFW_KEY_3 51 +#define GLFW_KEY_4 52 +#define GLFW_KEY_5 53 +#define GLFW_KEY_6 54 +#define GLFW_KEY_7 55 +#define GLFW_KEY_8 56 +#define GLFW_KEY_9 57 +#define GLFW_KEY_SEMICOLON 59 /* ; */ +#define GLFW_KEY_EQUAL 61 /* = */ +#define GLFW_KEY_A 65 +#define GLFW_KEY_B 66 +#define GLFW_KEY_C 67 +#define GLFW_KEY_D 68 +#define GLFW_KEY_E 69 +#define GLFW_KEY_F 70 +#define GLFW_KEY_G 71 +#define GLFW_KEY_H 72 +#define GLFW_KEY_I 73 +#define GLFW_KEY_J 74 +#define GLFW_KEY_K 75 +#define GLFW_KEY_L 76 +#define GLFW_KEY_M 77 +#define GLFW_KEY_N 78 +#define GLFW_KEY_O 79 +#define GLFW_KEY_P 80 +#define GLFW_KEY_Q 81 +#define GLFW_KEY_R 82 +#define GLFW_KEY_S 83 +#define GLFW_KEY_T 84 +#define GLFW_KEY_U 85 +#define GLFW_KEY_V 86 +#define GLFW_KEY_W 87 +#define GLFW_KEY_X 88 +#define GLFW_KEY_Y 89 +#define GLFW_KEY_Z 90 +#define GLFW_KEY_LEFT_BRACKET 91 /* [ */ +#define GLFW_KEY_BACKSLASH 92 /* \ */ +#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */ +#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */ +#define GLFW_KEY_WORLD_1 161 /* non-US #1 */ +#define GLFW_KEY_WORLD_2 162 /* non-US #2 */ + +/* Function keys */ +#define GLFW_KEY_ESCAPE 256 +#define GLFW_KEY_ENTER 257 +#define GLFW_KEY_TAB 258 +#define GLFW_KEY_BACKSPACE 259 +#define GLFW_KEY_INSERT 260 +#define GLFW_KEY_DELETE 261 +#define GLFW_KEY_RIGHT 262 +#define GLFW_KEY_LEFT 263 +#define GLFW_KEY_DOWN 264 +#define GLFW_KEY_UP 265 +#define GLFW_KEY_PAGE_UP 266 +#define GLFW_KEY_PAGE_DOWN 267 +#define GLFW_KEY_HOME 268 +#define GLFW_KEY_END 269 +#define GLFW_KEY_CAPS_LOCK 280 +#define GLFW_KEY_SCROLL_LOCK 281 +#define GLFW_KEY_NUM_LOCK 282 +#define GLFW_KEY_PRINT_SCREEN 283 +#define GLFW_KEY_PAUSE 284 +#define GLFW_KEY_F1 290 +#define GLFW_KEY_F2 291 +#define GLFW_KEY_F3 292 +#define GLFW_KEY_F4 293 +#define GLFW_KEY_F5 294 +#define GLFW_KEY_F6 295 +#define GLFW_KEY_F7 296 +#define GLFW_KEY_F8 297 +#define GLFW_KEY_F9 298 +#define GLFW_KEY_F10 299 +#define GLFW_KEY_F11 300 +#define GLFW_KEY_F12 301 +#define GLFW_KEY_F13 302 +#define GLFW_KEY_F14 303 +#define GLFW_KEY_F15 304 +#define GLFW_KEY_F16 305 +#define GLFW_KEY_F17 306 +#define GLFW_KEY_F18 307 +#define GLFW_KEY_F19 308 +#define GLFW_KEY_F20 309 +#define GLFW_KEY_F21 310 +#define GLFW_KEY_F22 311 +#define GLFW_KEY_F23 312 +#define GLFW_KEY_F24 313 +#define GLFW_KEY_F25 314 +#define GLFW_KEY_KP_0 320 +#define GLFW_KEY_KP_1 321 +#define GLFW_KEY_KP_2 322 +#define GLFW_KEY_KP_3 323 +#define GLFW_KEY_KP_4 324 +#define GLFW_KEY_KP_5 325 +#define GLFW_KEY_KP_6 326 +#define GLFW_KEY_KP_7 327 +#define GLFW_KEY_KP_8 328 +#define GLFW_KEY_KP_9 329 +#define GLFW_KEY_KP_DECIMAL 330 +#define GLFW_KEY_KP_DIVIDE 331 +#define GLFW_KEY_KP_MULTIPLY 332 +#define GLFW_KEY_KP_SUBTRACT 333 +#define GLFW_KEY_KP_ADD 334 +#define GLFW_KEY_KP_ENTER 335 +#define GLFW_KEY_KP_EQUAL 336 +#define GLFW_KEY_LEFT_SHIFT 340 +#define GLFW_KEY_LEFT_CONTROL 341 +#define GLFW_KEY_LEFT_ALT 342 +#define GLFW_KEY_LEFT_SUPER 343 +#define GLFW_KEY_RIGHT_SHIFT 344 +#define GLFW_KEY_RIGHT_CONTROL 345 +#define GLFW_KEY_RIGHT_ALT 346 +#define GLFW_KEY_RIGHT_SUPER 347 +#define GLFW_KEY_MENU 348 + +#define GLFW_KEY_LAST GLFW_KEY_MENU + +/*! @} */ + +/*! @defgroup mods Modifier key flags + * @brief Modifier key flags. + * + * See [key input](@ref input_key) for how these are used. + * + * @ingroup input + * @{ */ + +/*! @brief If this bit is set one or more Shift keys were held down. + * + * If this bit is set one or more Shift keys were held down. + */ +#define GLFW_MOD_SHIFT 0x0001 +/*! @brief If this bit is set one or more Control keys were held down. + * + * If this bit is set one or more Control keys were held down. + */ +#define GLFW_MOD_CONTROL 0x0002 +/*! @brief If this bit is set one or more Alt keys were held down. + * + * If this bit is set one or more Alt keys were held down. + */ +#define GLFW_MOD_ALT 0x0004 +/*! @brief If this bit is set one or more Super keys were held down. + * + * If this bit is set one or more Super keys were held down. + */ +#define GLFW_MOD_SUPER 0x0008 +/*! @brief If this bit is set the Caps Lock key is enabled. + * + * If this bit is set the Caps Lock key is enabled and the @ref + * GLFW_LOCK_KEY_MODS input mode is set. + */ +#define GLFW_MOD_CAPS_LOCK 0x0010 +/*! @brief If this bit is set the Num Lock key is enabled. + * + * If this bit is set the Num Lock key is enabled and the @ref + * GLFW_LOCK_KEY_MODS input mode is set. + */ +#define GLFW_MOD_NUM_LOCK 0x0020 + +/*! @} */ + +/*! @defgroup buttons Mouse buttons + * @brief Mouse button IDs. + * + * See [mouse button input](@ref input_mouse_button) for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_MOUSE_BUTTON_1 0 +#define GLFW_MOUSE_BUTTON_2 1 +#define GLFW_MOUSE_BUTTON_3 2 +#define GLFW_MOUSE_BUTTON_4 3 +#define GLFW_MOUSE_BUTTON_5 4 +#define GLFW_MOUSE_BUTTON_6 5 +#define GLFW_MOUSE_BUTTON_7 6 +#define GLFW_MOUSE_BUTTON_8 7 +#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8 +#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1 +#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2 +#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3 +/*! @} */ + +/*! @defgroup joysticks Joysticks + * @brief Joystick IDs. + * + * See [joystick input](@ref joystick) for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_JOYSTICK_1 0 +#define GLFW_JOYSTICK_2 1 +#define GLFW_JOYSTICK_3 2 +#define GLFW_JOYSTICK_4 3 +#define GLFW_JOYSTICK_5 4 +#define GLFW_JOYSTICK_6 5 +#define GLFW_JOYSTICK_7 6 +#define GLFW_JOYSTICK_8 7 +#define GLFW_JOYSTICK_9 8 +#define GLFW_JOYSTICK_10 9 +#define GLFW_JOYSTICK_11 10 +#define GLFW_JOYSTICK_12 11 +#define GLFW_JOYSTICK_13 12 +#define GLFW_JOYSTICK_14 13 +#define GLFW_JOYSTICK_15 14 +#define GLFW_JOYSTICK_16 15 +#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16 +/*! @} */ + +/*! @defgroup gamepad_buttons Gamepad buttons + * @brief Gamepad buttons. + * + * See @ref gamepad for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_GAMEPAD_BUTTON_A 0 +#define GLFW_GAMEPAD_BUTTON_B 1 +#define GLFW_GAMEPAD_BUTTON_X 2 +#define GLFW_GAMEPAD_BUTTON_Y 3 +#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER 4 +#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER 5 +#define GLFW_GAMEPAD_BUTTON_BACK 6 +#define GLFW_GAMEPAD_BUTTON_START 7 +#define GLFW_GAMEPAD_BUTTON_GUIDE 8 +#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB 9 +#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB 10 +#define GLFW_GAMEPAD_BUTTON_DPAD_UP 11 +#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT 12 +#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN 13 +#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT 14 +#define GLFW_GAMEPAD_BUTTON_LAST GLFW_GAMEPAD_BUTTON_DPAD_LEFT + +#define GLFW_GAMEPAD_BUTTON_CROSS GLFW_GAMEPAD_BUTTON_A +#define GLFW_GAMEPAD_BUTTON_CIRCLE GLFW_GAMEPAD_BUTTON_B +#define GLFW_GAMEPAD_BUTTON_SQUARE GLFW_GAMEPAD_BUTTON_X +#define GLFW_GAMEPAD_BUTTON_TRIANGLE GLFW_GAMEPAD_BUTTON_Y +/*! @} */ + +/*! @defgroup gamepad_axes Gamepad axes + * @brief Gamepad axes. + * + * See @ref gamepad for how these are used. + * + * @ingroup input + * @{ */ +#define GLFW_GAMEPAD_AXIS_LEFT_X 0 +#define GLFW_GAMEPAD_AXIS_LEFT_Y 1 +#define GLFW_GAMEPAD_AXIS_RIGHT_X 2 +#define GLFW_GAMEPAD_AXIS_RIGHT_Y 3 +#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER 4 +#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5 +#define GLFW_GAMEPAD_AXIS_LAST GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER +/*! @} */ + +/*! @defgroup errors Error codes + * @brief Error codes. + * + * See [error handling](@ref error_handling) for how these are used. + * + * @ingroup init + * @{ */ +/*! @brief No error has occurred. + * + * No error has occurred. + * + * @analysis Yay. + */ +#define GLFW_NO_ERROR 0 +/*! @brief GLFW has not been initialized. + * + * This occurs if a GLFW function was called that must not be called unless the + * library is [initialized](@ref intro_init). + * + * @analysis Application programmer error. Initialize GLFW before calling any + * function that requires initialization. + */ +#define GLFW_NOT_INITIALIZED 0x00010001 +/*! @brief No context is current for this thread. + * + * This occurs if a GLFW function was called that needs and operates on the + * current OpenGL or OpenGL ES context but no context is current on the calling + * thread. One such function is @ref glfwSwapInterval. + * + * @analysis Application programmer error. Ensure a context is current before + * calling functions that require a current context. + */ +#define GLFW_NO_CURRENT_CONTEXT 0x00010002 +/*! @brief One of the arguments to the function was an invalid enum value. + * + * One of the arguments to the function was an invalid enum value, for example + * requesting @ref GLFW_RED_BITS with @ref glfwGetWindowAttrib. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_INVALID_ENUM 0x00010003 +/*! @brief One of the arguments to the function was an invalid value. + * + * One of the arguments to the function was an invalid value, for example + * requesting a non-existent OpenGL or OpenGL ES version like 2.7. + * + * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead + * result in a @ref GLFW_VERSION_UNAVAILABLE error. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_INVALID_VALUE 0x00010004 +/*! @brief A memory allocation failed. + * + * A memory allocation failed. + * + * @analysis A bug in GLFW or the underlying operating system. Report the bug + * to our [issue tracker](https://github.com/glfw/glfw/issues). + */ +#define GLFW_OUT_OF_MEMORY 0x00010005 +/*! @brief GLFW could not find support for the requested API on the system. + * + * GLFW could not find support for the requested API on the system. + * + * @analysis The installed graphics driver does not support the requested + * API, or does not support it via the chosen context creation backend. + * Below are a few examples. + * + * @par + * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only + * supports OpenGL ES via EGL, while Nvidia and Intel only support it via + * a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa + * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary + * driver. Older graphics drivers do not support Vulkan. + */ +#define GLFW_API_UNAVAILABLE 0x00010006 +/*! @brief The requested OpenGL or OpenGL ES version is not available. + * + * The requested OpenGL or OpenGL ES version (including any requested context + * or framebuffer hints) is not available on this machine. + * + * @analysis The machine does not support your requirements. If your + * application is sufficiently flexible, downgrade your requirements and try + * again. Otherwise, inform the user that their machine does not match your + * requirements. + * + * @par + * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0 + * comes out before the 4.x series gets that far, also fail with this error and + * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions + * will exist. + */ +#define GLFW_VERSION_UNAVAILABLE 0x00010007 +/*! @brief A platform-specific error occurred that does not match any of the + * more specific categories. + * + * A platform-specific error occurred that does not match any of the more + * specific categories. + * + * @analysis A bug or configuration error in GLFW, the underlying operating + * system or its drivers, or a lack of required resources. Report the issue to + * our [issue tracker](https://github.com/glfw/glfw/issues). + */ +#define GLFW_PLATFORM_ERROR 0x00010008 +/*! @brief The requested format is not supported or available. + * + * If emitted during window creation, the requested pixel format is not + * supported. + * + * If emitted when querying the clipboard, the contents of the clipboard could + * not be converted to the requested format. + * + * @analysis If emitted during window creation, one or more + * [hard constraints](@ref window_hints_hard) did not match any of the + * available pixel formats. If your application is sufficiently flexible, + * downgrade your requirements and try again. Otherwise, inform the user that + * their machine does not match your requirements. + * + * @par + * If emitted when querying the clipboard, ignore the error or report it to + * the user, as appropriate. + */ +#define GLFW_FORMAT_UNAVAILABLE 0x00010009 +/*! @brief The specified window does not have an OpenGL or OpenGL ES context. + * + * A window that does not have an OpenGL or OpenGL ES context was passed to + * a function that requires it to have one. + * + * @analysis Application programmer error. Fix the offending call. + */ +#define GLFW_NO_WINDOW_CONTEXT 0x0001000A +/*! @} */ + +/*! @addtogroup window + * @{ */ +/*! @brief Input focus window hint and attribute + * + * Input focus [window hint](@ref GLFW_FOCUSED_hint) or + * [window attribute](@ref GLFW_FOCUSED_attrib). + */ +#define GLFW_FOCUSED 0x00020001 +/*! @brief Window iconification window attribute + * + * Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib). + */ +#define GLFW_ICONIFIED 0x00020002 +/*! @brief Window resize-ability window hint and attribute + * + * Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and + * [window attribute](@ref GLFW_RESIZABLE_attrib). + */ +#define GLFW_RESIZABLE 0x00020003 +/*! @brief Window visibility window hint and attribute + * + * Window visibility [window hint](@ref GLFW_VISIBLE_hint) and + * [window attribute](@ref GLFW_VISIBLE_attrib). + */ +#define GLFW_VISIBLE 0x00020004 +/*! @brief Window decoration window hint and attribute + * + * Window decoration [window hint](@ref GLFW_DECORATED_hint) and + * [window attribute](@ref GLFW_DECORATED_attrib). + */ +#define GLFW_DECORATED 0x00020005 +/*! @brief Window auto-iconification window hint and attribute + * + * Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and + * [window attribute](@ref GLFW_AUTO_ICONIFY_attrib). + */ +#define GLFW_AUTO_ICONIFY 0x00020006 +/*! @brief Window decoration window hint and attribute + * + * Window decoration [window hint](@ref GLFW_FLOATING_hint) and + * [window attribute](@ref GLFW_FLOATING_attrib). + */ +#define GLFW_FLOATING 0x00020007 +/*! @brief Window maximization window hint and attribute + * + * Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and + * [window attribute](@ref GLFW_MAXIMIZED_attrib). + */ +#define GLFW_MAXIMIZED 0x00020008 +/*! @brief Cursor centering window hint + * + * Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint). + */ +#define GLFW_CENTER_CURSOR 0x00020009 +/*! @brief Window framebuffer transparency hint and attribute + * + * Window framebuffer transparency + * [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and + * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib). + */ +#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A +/*! @brief Mouse cursor hover window attribute. + * + * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). + */ +#define GLFW_HOVERED 0x0002000B +/*! @brief Input focus on calling show window hint and attribute + * + * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or + * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). + */ +#define GLFW_FOCUS_ON_SHOW 0x0002000C + +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). + */ +#define GLFW_RED_BITS 0x00021001 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS). + */ +#define GLFW_GREEN_BITS 0x00021002 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS). + */ +#define GLFW_BLUE_BITS 0x00021003 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS). + */ +#define GLFW_ALPHA_BITS 0x00021004 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS). + */ +#define GLFW_DEPTH_BITS 0x00021005 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS). + */ +#define GLFW_STENCIL_BITS 0x00021006 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS). + */ +#define GLFW_ACCUM_RED_BITS 0x00021007 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS). + */ +#define GLFW_ACCUM_GREEN_BITS 0x00021008 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS). + */ +#define GLFW_ACCUM_BLUE_BITS 0x00021009 +/*! @brief Framebuffer bit depth hint. + * + * Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS). + */ +#define GLFW_ACCUM_ALPHA_BITS 0x0002100A +/*! @brief Framebuffer auxiliary buffer hint. + * + * Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS). + */ +#define GLFW_AUX_BUFFERS 0x0002100B +/*! @brief OpenGL stereoscopic rendering hint. + * + * OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO). + */ +#define GLFW_STEREO 0x0002100C +/*! @brief Framebuffer MSAA samples hint. + * + * Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES). + */ +#define GLFW_SAMPLES 0x0002100D +/*! @brief Framebuffer sRGB hint. + * + * Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE). + */ +#define GLFW_SRGB_CAPABLE 0x0002100E +/*! @brief Monitor refresh rate hint. + * + * Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE). + */ +#define GLFW_REFRESH_RATE 0x0002100F +/*! @brief Framebuffer double buffering hint. + * + * Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER). + */ +#define GLFW_DOUBLEBUFFER 0x00021010 + +/*! @brief Context client API hint and attribute. + * + * Context client API [hint](@ref GLFW_CLIENT_API_hint) and + * [attribute](@ref GLFW_CLIENT_API_attrib). + */ +#define GLFW_CLIENT_API 0x00022001 +/*! @brief Context client API major version hint and attribute. + * + * Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint) + * and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib). + */ +#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 +/*! @brief Context client API minor version hint and attribute. + * + * Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint) + * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). + */ +#define GLFW_CONTEXT_VERSION_MINOR 0x00022003 +/*! @brief Context client API revision number hint and attribute. + * + * Context client API revision number + * [attribute](@ref GLFW_CONTEXT_REVISION_attrib). + */ +#define GLFW_CONTEXT_REVISION 0x00022004 +/*! @brief Context robustness hint and attribute. + * + * Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint) + * and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib). + */ +#define GLFW_CONTEXT_ROBUSTNESS 0x00022005 +/*! @brief OpenGL forward-compatibility hint and attribute. + * + * OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) + * and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib). + */ +#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006 +/*! @brief OpenGL debug context hint and attribute. + * + * OpenGL debug context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and + * [attribute](@ref GLFW_OPENGL_DEBUG_CONTEXT_attrib). + */ +#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 +/*! @brief OpenGL profile hint and attribute. + * + * OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and + * [attribute](@ref GLFW_OPENGL_PROFILE_attrib). + */ +#define GLFW_OPENGL_PROFILE 0x00022008 +/*! @brief Context flush-on-release hint and attribute. + * + * Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and + * [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib). + */ +#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 +/*! @brief Context error suppression hint and attribute. + * + * Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and + * [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib). + */ +#define GLFW_CONTEXT_NO_ERROR 0x0002200A +/*! @brief Context creation API hint and attribute. + * + * Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and + * [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib). + */ +#define GLFW_CONTEXT_CREATION_API 0x0002200B +/*! @brief Window content area scaling window + * [window hint](@ref GLFW_SCALE_TO_MONITOR). + */ +#define GLFW_SCALE_TO_MONITOR 0x0002200C +/*! @brief macOS specific + * [window hint](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint). + */ +#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001 +/*! @brief macOS specific + * [window hint](@ref GLFW_COCOA_FRAME_NAME_hint). + */ +#define GLFW_COCOA_FRAME_NAME 0x00023002 +/*! @brief macOS specific + * [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint). + */ +#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003 +/*! @brief X11 specific + * [window hint](@ref GLFW_X11_CLASS_NAME_hint). + */ +#define GLFW_X11_CLASS_NAME 0x00024001 +/*! @brief X11 specific + * [window hint](@ref GLFW_X11_CLASS_NAME_hint). + */ +#define GLFW_X11_INSTANCE_NAME 0x00024002 +/*! @} */ + +#define GLFW_NO_API 0 +#define GLFW_OPENGL_API 0x00030001 +#define GLFW_OPENGL_ES_API 0x00030002 + +#define GLFW_NO_ROBUSTNESS 0 +#define GLFW_NO_RESET_NOTIFICATION 0x00031001 +#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002 + +#define GLFW_OPENGL_ANY_PROFILE 0 +#define GLFW_OPENGL_CORE_PROFILE 0x00032001 +#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002 + +#define GLFW_CURSOR 0x00033001 +#define GLFW_STICKY_KEYS 0x00033002 +#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 +#define GLFW_LOCK_KEY_MODS 0x00033004 +#define GLFW_RAW_MOUSE_MOTION 0x00033005 + +#define GLFW_CURSOR_NORMAL 0x00034001 +#define GLFW_CURSOR_HIDDEN 0x00034002 +#define GLFW_CURSOR_DISABLED 0x00034003 + +#define GLFW_ANY_RELEASE_BEHAVIOR 0 +#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 +#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002 + +#define GLFW_NATIVE_CONTEXT_API 0x00036001 +#define GLFW_EGL_CONTEXT_API 0x00036002 +#define GLFW_OSMESA_CONTEXT_API 0x00036003 + +/*! @defgroup shapes Standard cursor shapes + * @brief Standard system cursor shapes. + * + * See [standard cursor creation](@ref cursor_standard) for how these are used. + * + * @ingroup input + * @{ */ + +/*! @brief The regular arrow cursor shape. + * + * The regular arrow cursor. + */ +#define GLFW_ARROW_CURSOR 0x00036001 +/*! @brief The text input I-beam cursor shape. + * + * The text input I-beam cursor shape. + */ +#define GLFW_IBEAM_CURSOR 0x00036002 +/*! @brief The crosshair shape. + * + * The crosshair shape. + */ +#define GLFW_CROSSHAIR_CURSOR 0x00036003 +/*! @brief The hand shape. + * + * The hand shape. + */ +#define GLFW_HAND_CURSOR 0x00036004 +/*! @brief The horizontal resize arrow shape. + * + * The horizontal resize arrow shape. + */ +#define GLFW_HRESIZE_CURSOR 0x00036005 +/*! @brief The vertical resize arrow shape. + * + * The vertical resize arrow shape. + */ +#define GLFW_VRESIZE_CURSOR 0x00036006 +/*! @} */ + +#define GLFW_CONNECTED 0x00040001 +#define GLFW_DISCONNECTED 0x00040002 + +/*! @addtogroup init + * @{ */ +/*! @brief Joystick hat buttons init hint. + * + * Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS). + */ +#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001 +/*! @brief macOS specific init hint. + * + * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint). + */ +#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001 +/*! @brief macOS specific init hint. + * + * macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint). + */ +#define GLFW_COCOA_MENUBAR 0x00051002 +/*! @} */ + +#define GLFW_DONT_CARE -1 + + +/************************************************************************* + * GLFW API types + *************************************************************************/ + +/*! @brief Client API function pointer type. + * + * Generic function pointer used for returning client API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref context_glext + * @sa @ref glfwGetProcAddress + * + * @since Added in version 3.0. + * + * @ingroup context + */ +typedef void (*GLFWglproc)(void); + +/*! @brief Vulkan API function pointer type. + * + * Generic function pointer used for returning Vulkan API function pointers + * without forcing a cast from a regular pointer. + * + * @sa @ref vulkan_proc + * @sa @ref glfwGetInstanceProcAddress + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +typedef void (*GLFWvkproc)(void); + +/*! @brief Opaque monitor object. + * + * Opaque monitor object. + * + * @see @ref monitor_object + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +typedef struct GLFWmonitor GLFWmonitor; + +/*! @brief Opaque window object. + * + * Opaque window object. + * + * @see @ref window_object + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef struct GLFWwindow GLFWwindow; + +/*! @brief Opaque cursor object. + * + * Opaque cursor object. + * + * @see @ref cursor_object + * + * @since Added in version 3.1. + * + * @ingroup input + */ +typedef struct GLFWcursor GLFWcursor; + +/*! @brief The function pointer type for error callbacks. + * + * This is the function pointer type for error callbacks. An error callback + * function has the following signature: + * @code + * void callback_name(int error_code, const char* description) + * @endcode + * + * @param[in] error_code An [error code](@ref errors). Future releases may add + * more error codes. + * @param[in] description A UTF-8 encoded string describing the error. + * + * @pointer_lifetime The error description string is valid until the callback + * function returns. + * + * @sa @ref error_handling + * @sa @ref glfwSetErrorCallback + * + * @since Added in version 3.0. + * + * @ingroup init + */ +typedef void (* GLFWerrorfun)(int,const char*); + +/*! @brief The function pointer type for window position callbacks. + * + * This is the function pointer type for window position callbacks. A window + * position callback function has the following signature: + * @code + * void callback_name(GLFWwindow* window, int xpos, int ypos) + * @endcode + * + * @param[in] window The window that was moved. + * @param[in] xpos The new x-coordinate, in screen coordinates, of the + * upper-left corner of the content area of the window. + * @param[in] ypos The new y-coordinate, in screen coordinates, of the + * upper-left corner of the content area of the window. + * + * @sa @ref window_pos + * @sa @ref glfwSetWindowPosCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWwindowposfun)(GLFWwindow*,int,int); + +/*! @brief The function pointer type for window size callbacks. + * + * This is the function pointer type for window size callbacks. A window size + * callback function has the following signature: + * @code + * void callback_name(GLFWwindow* window, int width, int height) + * @endcode + * + * @param[in] window The window that was resized. + * @param[in] width The new width, in screen coordinates, of the window. + * @param[in] height The new height, in screen coordinates, of the window. + * + * @sa @ref window_size + * @sa @ref glfwSetWindowSizeCallback + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); + +/*! @brief The function pointer type for window close callbacks. + * + * This is the function pointer type for window close callbacks. A window + * close callback function has the following signature: + * @code + * void function_name(GLFWwindow* window) + * @endcode + * + * @param[in] window The window that the user attempted to close. + * + * @sa @ref window_close + * @sa @ref glfwSetWindowCloseCallback + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +typedef void (* GLFWwindowclosefun)(GLFWwindow*); + +/*! @brief The function pointer type for window content refresh callbacks. + * + * This is the function pointer type for window content refresh callbacks. + * A window content refresh callback function has the following signature: + * @code + * void function_name(GLFWwindow* window); + * @endcode + * + * @param[in] window The window whose content needs to be refreshed. + * + * @sa @ref window_refresh + * @sa @ref glfwSetWindowRefreshCallback + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +typedef void (* GLFWwindowrefreshfun)(GLFWwindow*); + +/*! @brief The function pointer type for window focus callbacks. + * + * This is the function pointer type for window focus callbacks. A window + * focus callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int focused) + * @endcode + * + * @param[in] window The window that gained or lost input focus. + * @param[in] focused `GLFW_TRUE` if the window was given input focus, or + * `GLFW_FALSE` if it lost it. + * + * @sa @ref window_focus + * @sa @ref glfwSetWindowFocusCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWwindowfocusfun)(GLFWwindow*,int); + +/*! @brief The function pointer type for window iconify callbacks. + * + * This is the function pointer type for window iconify callbacks. A window + * iconify callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int iconified) + * @endcode + * + * @param[in] window The window that was iconified or restored. + * @param[in] iconified `GLFW_TRUE` if the window was iconified, or + * `GLFW_FALSE` if it was restored. + * + * @sa @ref window_iconify + * @sa @ref glfwSetWindowIconifyCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWwindowiconifyfun)(GLFWwindow*,int); + +/*! @brief The function pointer type for window maximize callbacks. + * + * This is the function pointer type for window maximize callbacks. A window + * maximize callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int maximized) + * @endcode + * + * @param[in] window The window that was maximized or restored. + * @param[in] iconified `GLFW_TRUE` if the window was maximized, or + * `GLFW_FALSE` if it was restored. + * + * @sa @ref window_maximize + * @sa glfwSetWindowMaximizeCallback + * + * @since Added in version 3.3. + * + * @ingroup window + */ +typedef void (* GLFWwindowmaximizefun)(GLFWwindow*,int); + +/*! @brief The function pointer type for framebuffer size callbacks. + * + * This is the function pointer type for framebuffer size callbacks. + * A framebuffer size callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int width, int height) + * @endcode + * + * @param[in] window The window whose framebuffer was resized. + * @param[in] width The new width, in pixels, of the framebuffer. + * @param[in] height The new height, in pixels, of the framebuffer. + * + * @sa @ref window_fbsize + * @sa @ref glfwSetFramebufferSizeCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +typedef void (* GLFWframebuffersizefun)(GLFWwindow*,int,int); + +/*! @brief The function pointer type for window content scale callbacks. + * + * This is the function pointer type for window content scale callbacks. + * A window content scale callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, float xscale, float yscale) + * @endcode + * + * @param[in] window The window whose content scale changed. + * @param[in] xscale The new x-axis content scale of the window. + * @param[in] yscale The new y-axis content scale of the window. + * + * @sa @ref window_scale + * @sa @ref glfwSetWindowContentScaleCallback + * + * @since Added in version 3.3. + * + * @ingroup window + */ +typedef void (* GLFWwindowcontentscalefun)(GLFWwindow*,float,float); + +/*! @brief The function pointer type for mouse button callbacks. + * + * This is the function pointer type for mouse button callback functions. + * A mouse button callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int button, int action, int mods) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] button The [mouse button](@ref buttons) that was pressed or + * released. + * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. Future releases + * may add more actions. + * @param[in] mods Bit field describing which [modifier keys](@ref mods) were + * held down. + * + * @sa @ref input_mouse_button + * @sa @ref glfwSetMouseButtonCallback + * + * @since Added in version 1.0. + * @glfw3 Added window handle and modifier mask parameters. + * + * @ingroup input + */ +typedef void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int); + +/*! @brief The function pointer type for cursor position callbacks. + * + * This is the function pointer type for cursor position callbacks. A cursor + * position callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, double xpos, double ypos); + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] xpos The new cursor x-coordinate, relative to the left edge of + * the content area. + * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the + * content area. + * + * @sa @ref cursor_pos + * @sa @ref glfwSetCursorPosCallback + * + * @since Added in version 3.0. Replaces `GLFWmouseposfun`. + * + * @ingroup input + */ +typedef void (* GLFWcursorposfun)(GLFWwindow*,double,double); + +/*! @brief The function pointer type for cursor enter/leave callbacks. + * + * This is the function pointer type for cursor enter/leave callbacks. + * A cursor enter/leave callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int entered) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] entered `GLFW_TRUE` if the cursor entered the window's content + * area, or `GLFW_FALSE` if it left it. + * + * @sa @ref cursor_enter + * @sa @ref glfwSetCursorEnterCallback + * + * @since Added in version 3.0. + * + * @ingroup input + */ +typedef void (* GLFWcursorenterfun)(GLFWwindow*,int); + +/*! @brief The function pointer type for scroll callbacks. + * + * This is the function pointer type for scroll callbacks. A scroll callback + * function has the following signature: + * @code + * void function_name(GLFWwindow* window, double xoffset, double yoffset) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] xoffset The scroll offset along the x-axis. + * @param[in] yoffset The scroll offset along the y-axis. + * + * @sa @ref scrolling + * @sa @ref glfwSetScrollCallback + * + * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. + * + * @ingroup input + */ +typedef void (* GLFWscrollfun)(GLFWwindow*,double,double); + +/*! @brief The function pointer type for keyboard key callbacks. + * + * This is the function pointer type for keyboard key callbacks. A keyboard + * key callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] key The [keyboard key](@ref keys) that was pressed or released. + * @param[in] scancode The system-specific scancode of the key. + * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. Future + * releases may add more actions. + * @param[in] mods Bit field describing which [modifier keys](@ref mods) were + * held down. + * + * @sa @ref input_key + * @sa @ref glfwSetKeyCallback + * + * @since Added in version 1.0. + * @glfw3 Added window handle, scancode and modifier mask parameters. + * + * @ingroup input + */ +typedef void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int); + +/*! @brief The function pointer type for Unicode character callbacks. + * + * This is the function pointer type for Unicode character callbacks. + * A Unicode character callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, unsigned int codepoint) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] codepoint The Unicode code point of the character. + * + * @sa @ref input_char + * @sa @ref glfwSetCharCallback + * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter. + * + * @ingroup input + */ +typedef void (* GLFWcharfun)(GLFWwindow*,unsigned int); + +/*! @brief The function pointer type for Unicode character with modifiers + * callbacks. + * + * This is the function pointer type for Unicode character with modifiers + * callbacks. It is called for each input character, regardless of what + * modifier keys are held down. A Unicode character with modifiers callback + * function has the following signature: + * @code + * void function_name(GLFWwindow* window, unsigned int codepoint, int mods) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] codepoint The Unicode code point of the character. + * @param[in] mods Bit field describing which [modifier keys](@ref mods) were + * held down. + * + * @sa @ref input_char + * @sa @ref glfwSetCharModsCallback + * + * @deprecated Scheduled for removal in version 4.0. + * + * @since Added in version 3.1. + * + * @ingroup input + */ +typedef void (* GLFWcharmodsfun)(GLFWwindow*,unsigned int,int); + +/*! @brief The function pointer type for path drop callbacks. + * + * This is the function pointer type for path drop callbacks. A path drop + * callback function has the following signature: + * @code + * void function_name(GLFWwindow* window, int path_count, const char* paths[]) + * @endcode + * + * @param[in] window The window that received the event. + * @param[in] path_count The number of dropped paths. + * @param[in] paths The UTF-8 encoded file and/or directory path names. + * + * @pointer_lifetime The path array and its strings are valid until the + * callback function returns. + * + * @sa @ref path_drop + * @sa @ref glfwSetDropCallback + * + * @since Added in version 3.1. + * + * @ingroup input + */ +typedef void (* GLFWdropfun)(GLFWwindow*,int,const char*[]); + +/*! @brief The function pointer type for monitor configuration callbacks. + * + * This is the function pointer type for monitor configuration callbacks. + * A monitor callback function has the following signature: + * @code + * void function_name(GLFWmonitor* monitor, int event) + * @endcode + * + * @param[in] monitor The monitor that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future + * releases may add more events. + * + * @sa @ref monitor_event + * @sa @ref glfwSetMonitorCallback + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); + +/*! @brief The function pointer type for joystick configuration callbacks. + * + * This is the function pointer type for joystick configuration callbacks. + * A joystick configuration callback function has the following signature: + * @code + * void function_name(int jid, int event) + * @endcode + * + * @param[in] jid The joystick that was connected or disconnected. + * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future + * releases may add more events. + * + * @sa @ref joystick_event + * @sa @ref glfwSetJoystickCallback + * + * @since Added in version 3.2. + * + * @ingroup input + */ +typedef void (* GLFWjoystickfun)(int,int); + +/*! @brief Video mode type. + * + * This describes a single video mode. + * + * @sa @ref monitor_modes + * @sa @ref glfwGetVideoMode + * @sa @ref glfwGetVideoModes + * + * @since Added in version 1.0. + * @glfw3 Added refresh rate member. + * + * @ingroup monitor + */ +typedef struct GLFWvidmode +{ + /*! The width, in screen coordinates, of the video mode. + */ + int width; + /*! The height, in screen coordinates, of the video mode. + */ + int height; + /*! The bit depth of the red channel of the video mode. + */ + int redBits; + /*! The bit depth of the green channel of the video mode. + */ + int greenBits; + /*! The bit depth of the blue channel of the video mode. + */ + int blueBits; + /*! The refresh rate, in Hz, of the video mode. + */ + int refreshRate; +} GLFWvidmode; + +/*! @brief Gamma ramp. + * + * This describes the gamma ramp for a monitor. + * + * @sa @ref monitor_gamma + * @sa @ref glfwGetGammaRamp + * @sa @ref glfwSetGammaRamp + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +typedef struct GLFWgammaramp +{ + /*! An array of value describing the response of the red channel. + */ + unsigned short* red; + /*! An array of value describing the response of the green channel. + */ + unsigned short* green; + /*! An array of value describing the response of the blue channel. + */ + unsigned short* blue; + /*! The number of elements in each array. + */ + unsigned int size; +} GLFWgammaramp; + +/*! @brief Image data. + * + * This describes a single 2D image. See the documentation for each related + * function what the expected pixel format is. + * + * @sa @ref cursor_custom + * @sa @ref window_icon + * + * @since Added in version 2.1. + * @glfw3 Removed format and bytes-per-pixel members. + * + * @ingroup window + */ +typedef struct GLFWimage +{ + /*! The width, in pixels, of this image. + */ + int width; + /*! The height, in pixels, of this image. + */ + int height; + /*! The pixel data of this image, arranged left-to-right, top-to-bottom. + */ + unsigned char* pixels; +} GLFWimage; + +/*! @brief Gamepad input state + * + * This describes the input state of a gamepad. + * + * @sa @ref gamepad + * @sa @ref glfwGetGamepadState + * + * @since Added in version 3.3. + * + * @ingroup input + */ +typedef struct GLFWgamepadstate +{ + /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS` + * or `GLFW_RELEASE`. + */ + unsigned char buttons[15]; + /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0 + * to 1.0 inclusive. + */ + float axes[6]; +} GLFWgamepadstate; + + +/************************************************************************* + * GLFW API functions + *************************************************************************/ + +/*! @brief Initializes the GLFW library. + * + * This function initializes the GLFW library. Before most GLFW functions can + * be used, GLFW must be initialized, and before an application terminates GLFW + * should be terminated in order to free any resources allocated during or + * after initialization. + * + * If this function fails, it calls @ref glfwTerminate before returning. If it + * succeeds, you should call @ref glfwTerminate before the application exits. + * + * Additional calls to this function after successful initialization but before + * termination will return `GLFW_TRUE` immediately. + * + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark @macos This function will change the current directory of the + * application to the `Contents/Resources` subdirectory of the application's + * bundle, if present. This can be disabled with the @ref + * GLFW_COCOA_CHDIR_RESOURCES init hint. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref intro_init + * @sa @ref glfwTerminate + * + * @since Added in version 1.0. + * + * @ingroup init + */ +GLFWAPI int glfwInit(void); + +/*! @brief Terminates the GLFW library. + * + * This function destroys all remaining windows and cursors, restores any + * modified gamma ramps and frees any other allocated resources. Once this + * function is called, you must again call @ref glfwInit successfully before + * you will be able to use most GLFW functions. + * + * If GLFW has been successfully initialized, this function should be called + * before the application exits. If initialization fails, there is no need to + * call this function, as it is called by @ref glfwInit before it returns + * failure. + * + * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. + * + * @remark This function may be called before @ref glfwInit. + * + * @warning The contexts of any remaining windows must not be current on any + * other thread when this function is called. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref intro_init + * @sa @ref glfwInit + * + * @since Added in version 1.0. + * + * @ingroup init + */ +GLFWAPI void glfwTerminate(void); + +/*! @brief Sets the specified init hint to the desired value. + * + * This function sets hints for the next initialization of GLFW. + * + * The values you set hints to are never reset by GLFW, but they only take + * effect during initialization. Once GLFW has been initialized, any values + * you set will be ignored until the library is terminated and initialized + * again. + * + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. + * + * @param[in] hint The [init hint](@ref init_hints) to set. + * @param[in] value The new value of the init hint. + * + * @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref + * GLFW_INVALID_VALUE. + * + * @remarks This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa init_hints + * @sa glfwInit + * + * @since Added in version 3.3. + * + * @ingroup init + */ +GLFWAPI void glfwInitHint(int hint, int value); + +/*! @brief Retrieves the version of the GLFW library. + * + * This function retrieves the major, minor and revision numbers of the GLFW + * library. It is intended for when you are using GLFW as a shared library and + * want to ensure that you are using the minimum required version. + * + * Any or all of the version arguments may be `NULL`. + * + * @param[out] major Where to store the major version number, or `NULL`. + * @param[out] minor Where to store the minor version number, or `NULL`. + * @param[out] rev Where to store the revision number, or `NULL`. + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref intro_version + * @sa @ref glfwGetVersionString + * + * @since Added in version 1.0. + * + * @ingroup init + */ +GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev); + +/*! @brief Returns a string describing the compile-time configuration. + * + * This function returns the compile-time generated + * [version string](@ref intro_version_string) of the GLFW library binary. It + * describes the version, platform, compiler and any platform-specific + * compile-time options. It should not be confused with the OpenGL or OpenGL + * ES version string, queried with `glGetString`. + * + * __Do not use the version string__ to parse the GLFW library version. The + * @ref glfwGetVersion function provides the version of the running library + * binary in numerical format. + * + * @return The ASCII encoded GLFW version string. + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @pointer_lifetime The returned string is static and compile-time generated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref intro_version + * @sa @ref glfwGetVersion + * + * @since Added in version 3.0. + * + * @ingroup init + */ +GLFWAPI const char* glfwGetVersionString(void); + +/*! @brief Returns and clears the last error for the calling thread. + * + * This function returns and clears the [error code](@ref errors) of the last + * error that occurred on the calling thread, and optionally a UTF-8 encoded + * human-readable description of it. If no error has occurred since the last + * call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is + * set to `NULL`. + * + * @param[in] description Where to store the error description pointer, or `NULL`. + * @return The last error code for the calling thread, or @ref GLFW_NO_ERROR + * (zero). + * + * @errors None. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * next error occurs or the library is terminated. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref error_handling + * @sa @ref glfwSetErrorCallback + * + * @since Added in version 3.3. + * + * @ingroup init + */ +GLFWAPI int glfwGetError(const char** description); + +/*! @brief Sets the error callback. + * + * This function sets the error callback, which is called with an error code + * and a human-readable description each time a GLFW error occurs. + * + * The error code is set before the callback is called. Calling @ref + * glfwGetError from the error callback will return the same value as the error + * code argument. + * + * The error callback is called on the thread where the error occurred. If you + * are using GLFW from multiple threads, your error callback needs to be + * written accordingly. + * + * Because the description string may have been generated specifically for that + * error, it is not guaranteed to be valid after the callback has returned. If + * you wish to use it after the callback returns, you need to make a copy. + * + * Once set, the error callback remains set even after the library has been + * terminated. + * + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set. + * + * @callback_signature + * @code + * void callback_name(int error_code, const char* description) + * @endcode + * For more information about the callback parameters, see the + * [callback pointer type](@ref GLFWerrorfun). + * + * @errors None. + * + * @remark This function may be called before @ref glfwInit. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref error_handling + * @sa @ref glfwGetError + * + * @since Added in version 3.0. + * + * @ingroup init + */ +GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun callback); + +/*! @brief Returns the currently connected monitors. + * + * This function returns an array of handles for all currently connected + * monitors. The primary monitor is always first in the returned array. If no + * monitors were found, this function returns `NULL`. + * + * @param[out] count Where to store the number of monitors in the returned + * array. This is set to zero if an error occurred. + * @return An array of monitor handles, or `NULL` if no monitors were found or + * if an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * monitor configuration changes or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_monitors + * @sa @ref monitor_event + * @sa @ref glfwGetPrimaryMonitor + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI GLFWmonitor** glfwGetMonitors(int* count); + +/*! @brief Returns the primary monitor. + * + * This function returns the primary monitor. This is usually the monitor + * where elements like the task bar or global menu bar are located. + * + * @return The primary monitor, or `NULL` if no monitors were found or if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @remark The primary monitor is always first in the array returned by @ref + * glfwGetMonitors. + * + * @sa @ref monitor_monitors + * @sa @ref glfwGetMonitors + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void); + +/*! @brief Returns the position of the monitor's viewport on the virtual screen. + * + * This function returns the position, in screen coordinates, of the upper-left + * corner of the specified monitor. + * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. + * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); + +/*! @brief Retrieves the work area of the monitor. + * + * This function returns the position, in screen coordinates, of the upper-left + * corner of the work area of the specified monitor along with the work area + * size in screen coordinates. The work area is defined as the area of the + * monitor not occluded by the operating system task bar where present. If no + * task bar exists then the work area is the monitor resolution in screen + * coordinates. + * + * Any or all of the position and size arguments may be `NULL`. If an error + * occurs, all non-`NULL` position and size arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. + * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. + * @param[out] width Where to store the monitor width, or `NULL`. + * @param[out] height Where to store the monitor height, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_workarea + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); + +/*! @brief Returns the physical size of the monitor. + * + * This function returns the size, in millimetres, of the display area of the + * specified monitor. + * + * Some systems do not provide accurate monitor size information, either + * because the monitor + * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data) + * data is incorrect or because the driver does not report it accurately. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] monitor The monitor to query. + * @param[out] widthMM Where to store the width, in millimetres, of the + * monitor's display area, or `NULL`. + * @param[out] heightMM Where to store the height, in millimetres, of the + * monitor's display area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @win32 calculates the returned physical size from the + * current resolution and system DPI instead of querying the monitor EDID data. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM); + +/*! @brief Retrieves the content scale for the specified monitor. + * + * This function retrieves the content scale for the specified monitor. The + * content scale is the ratio between the current DPI and the platform's + * default DPI. This is especially important for text and any UI elements. If + * the pixel dimensions of your UI scaled by this look appropriate on your + * machine then it should appear at a reasonable size on other machines + * regardless of their DPI and scaling settings. This relies on the system DPI + * and scaling settings being somewhat correct. + * + * The content scale may depend on both the monitor resolution and pixel + * density and on user settings. It may be very different from the raw DPI + * calculated from the physical size and current resolution. + * + * @param[in] monitor The monitor to query. + * @param[out] xscale Where to store the x-axis content scale, or `NULL`. + * @param[out] yscale Where to store the y-axis content scale, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_scale + * @sa @ref glfwGetWindowContentScale + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale); + +/*! @brief Returns the name of the specified monitor. + * + * This function returns a human-readable name, encoded as UTF-8, of the + * specified monitor. The name typically reflects the make and model of the + * monitor and is not guaranteed to be unique among the connected monitors. + * + * @param[in] monitor The monitor to query. + * @return The UTF-8 encoded name of the monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_properties + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor); + +/*! @brief Sets the user pointer of the specified monitor. + * + * This function sets the user-defined pointer of the specified monitor. The + * current value is retained until the monitor is disconnected. The initial + * value is `NULL`. + * + * This function may be called from the monitor callback, even for a monitor + * that is being disconnected. + * + * @param[in] monitor The monitor whose pointer to set. + * @param[in] pointer The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref monitor_userptr + * @sa @ref glfwGetMonitorUserPointer + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer); + +/*! @brief Returns the user pointer of the specified monitor. + * + * This function returns the current value of the user-defined pointer of the + * specified monitor. The initial value is `NULL`. + * + * This function may be called from the monitor callback, even for a monitor + * that is being disconnected. + * + * @param[in] monitor The monitor whose pointer to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref monitor_userptr + * @sa @ref glfwSetMonitorUserPointer + * + * @since Added in version 3.3. + * + * @ingroup monitor + */ +GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor); + +/*! @brief Sets the monitor configuration callback. + * + * This function sets the monitor configuration callback, or removes the + * currently set callback. This is called when a monitor is connected to or + * disconnected from the system. + * + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWmonitor* monitor, int event) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWmonitorfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_event + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun callback); + +/*! @brief Returns the available video modes for the specified monitor. + * + * This function returns an array of all video modes supported by the specified + * monitor. The returned array is sorted in ascending order, first by color + * bit depth (the sum of all channel depths) and then by resolution area (the + * product of width and height). + * + * @param[in] monitor The monitor to query. + * @param[out] count Where to store the number of video modes in the returned + * array. This is set to zero if an error occurred. + * @return An array of video modes, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected, this function is called again for that monitor or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_modes + * @sa @ref glfwGetVideoMode + * + * @since Added in version 1.0. + * @glfw3 Changed to return an array of modes for a specific monitor. + * + * @ingroup monitor + */ +GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count); + +/*! @brief Returns the current mode of the specified monitor. + * + * This function returns the current video mode of the specified monitor. If + * you have created a full screen window for that monitor, the return value + * will depend on whether that window is iconified. + * + * @param[in] monitor The monitor to query. + * @return The current mode of the monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified monitor is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_modes + * @sa @ref glfwGetVideoModes + * + * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. + * + * @ingroup monitor + */ +GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor); + +/*! @brief Generates a gamma ramp and sets it for the specified monitor. + * + * This function generates an appropriately sized gamma ramp from the specified + * exponent and then calls @ref glfwSetGammaRamp with it. The value must be + * a finite number greater than zero. + * + * The software controlled gamma ramp is applied _in addition_ to the hardware + * gamma correction, which today is usually an approximation of sRGB gamma. + * This means that setting a perfectly linear ramp, or gamma 1.0, will produce + * the default (usually sRGB-like) behavior. + * + * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref + * GLFW_SRGB_CAPABLE hint. + * + * @param[in] monitor The monitor whose gamma ramp to set. + * @param[in] gamma The desired exponent. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark @wayland Gamma handling is a privileged protocol, this function + * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma); + +/*! @brief Returns the current gamma ramp for the specified monitor. + * + * This function returns the current gamma ramp of the specified monitor. + * + * @param[in] monitor The monitor to query. + * @return The current gamma ramp, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland Gamma handling is a privileged protocol, this function + * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while + * returning `NULL`. + * + * @pointer_lifetime The returned structure and its arrays are allocated and + * freed by GLFW. You should not free them yourself. They are valid until the + * specified monitor is disconnected, this function is called again for that + * monitor or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor); + +/*! @brief Sets the current gamma ramp for the specified monitor. + * + * This function sets the current gamma ramp for the specified monitor. The + * original gamma ramp for that monitor is saved by GLFW the first time this + * function is called and is restored by @ref glfwTerminate. + * + * The software controlled gamma ramp is applied _in addition_ to the hardware + * gamma correction, which today is usually an approximation of sRGB gamma. + * This means that setting a perfectly linear ramp, or gamma 1.0, will produce + * the default (usually sRGB-like) behavior. + * + * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref + * GLFW_SRGB_CAPABLE hint. + * + * @param[in] monitor The monitor whose gamma ramp to set. + * @param[in] ramp The gamma ramp to use. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark The size of the specified gamma ramp should match the size of the + * current ramp for that monitor. + * + * @remark @win32 The gamma ramp size must be 256. + * + * @remark @wayland Gamma handling is a privileged protocol, this function + * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified gamma ramp is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref monitor_gamma + * + * @since Added in version 3.0. + * + * @ingroup monitor + */ +GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp); + +/*! @brief Resets all window hints to their default values. + * + * This function resets all window hints to their + * [default values](@ref window_hints_values). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hints + * @sa @ref glfwWindowHint + * @sa @ref glfwWindowHintString + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwDefaultWindowHints(void); + +/*! @brief Sets the specified window hint to the desired value. + * + * This function sets hints for the next call to @ref glfwCreateWindow. The + * hints, once set, retain their values until changed by a call to this + * function or @ref glfwDefaultWindowHints, or until the library is terminated. + * + * Only integer value hints can be set with this function. String value hints + * are set with @ref glfwWindowHintString. + * + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. + * + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. + * + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hints + * @sa @ref glfwWindowHintString + * @sa @ref glfwDefaultWindowHints + * + * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. + * + * @ingroup window + */ +GLFWAPI void glfwWindowHint(int hint, int value); + +/*! @brief Sets the specified window hint to the desired value. + * + * This function sets hints for the next call to @ref glfwCreateWindow. The + * hints, once set, retain their values until changed by a call to this + * function or @ref glfwDefaultWindowHints, or until the library is terminated. + * + * Only string type hints can be set with this function. Integer value hints + * are set with @ref glfwWindowHint. + * + * This function does not check whether the specified hint values are valid. + * If you set hints to invalid values this will instead be reported by the next + * call to @ref glfwCreateWindow. + * + * Some hints are platform specific. These may be set on any platform but they + * will only affect their specific platform. Other platforms will ignore them. + * Setting these hints requires no platform specific headers or functions. + * + * @param[in] hint The [window hint](@ref window_hints) to set. + * @param[in] value The new value of the window hint. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hints + * @sa @ref glfwWindowHint + * @sa @ref glfwDefaultWindowHints + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwWindowHintString(int hint, const char* value); + +/*! @brief Creates a window and its associated context. + * + * This function creates a window and its associated OpenGL or OpenGL ES + * context. Most of the options controlling how the window and its context + * should be created are specified with [window hints](@ref window_hints). + * + * Successful creation does not change which context is current. Before you + * can use the newly created context, you need to + * [make it current](@ref context_current). For information about the `share` + * parameter, see @ref context_sharing. + * + * The created window, framebuffer and context may differ from what you + * requested, as not all parameters and hints are + * [hard constraints](@ref window_hints_hard). This includes the size of the + * window, especially for full screen windows. To query the actual attributes + * of the created window, framebuffer and context, see @ref + * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. + * + * To create a full screen window, you need to specify the monitor the window + * will cover. If no monitor is specified, the window will be windowed mode. + * Unless you have a way for the user to choose a specific monitor, it is + * recommended that you pick the primary monitor. For more information on how + * to query connected monitors, see @ref monitor_monitors. + * + * For full screen windows, the specified size becomes the resolution of the + * window's _desired video mode_. As long as a full screen window is not + * iconified, the supported video mode most closely matching the desired video + * mode is set for the specified monitor. For more information about full + * screen windows, including the creation of so called _windowed full screen_ + * or _borderless full screen_ windows, see @ref window_windowed_full_screen. + * + * Once you have created the window, you can switch it between windowed and + * full screen mode with @ref glfwSetWindowMonitor. This will not affect its + * OpenGL or OpenGL ES context. + * + * By default, newly created windows use the placement recommended by the + * window system. To create the window at a specific position, make it + * initially invisible using the [GLFW_VISIBLE](@ref GLFW_VISIBLE_hint) window + * hint, set its [position](@ref window_pos) and then [show](@ref window_hide) + * it. + * + * As long as at least one full screen window is not iconified, the screensaver + * is prohibited from starting. + * + * Window systems put limits on window sizes. Very large or very small window + * dimensions may be overridden by the window system on creation. Check the + * actual [size](@ref window_size) after creation. + * + * The [swap interval](@ref buffer_swap) is not set during window creation and + * the initial value may vary depending on driver settings and defaults. + * + * @param[in] width The desired width, in screen coordinates, of the window. + * This must be greater than zero. + * @param[in] height The desired height, in screen coordinates, of the window. + * This must be greater than zero. + * @param[in] title The initial, UTF-8 encoded window title. + * @param[in] monitor The monitor to use for full screen mode, or `NULL` for + * windowed mode. + * @param[in] share The window whose context to share resources with, or `NULL` + * to not share resources. + * @return The handle of the created window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref + * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @win32 Window creation will fail if the Microsoft GDI software + * OpenGL implementation is the only one available. + * + * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it + * will be set as the initial icon for the window. If no such icon is present, + * the `IDI_APPLICATION` icon will be used instead. To set a different icon, + * see @ref glfwSetWindowIcon. + * + * @remark @win32 The context to share resources with must not be current on + * any other thread. + * + * @remark @macos The OS only supports forward-compatible core profile contexts + * for OpenGL versions 3.2 and later. Before creating an OpenGL context of + * version 3.2 or later you must set the + * [GLFW_OPENGL_FORWARD_COMPAT](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) and + * [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) hints accordingly. + * OpenGL 3.0 and 3.1 contexts are not supported at all on macOS. + * + * @remark @macos The GLFW window has no icon, as it is not a document + * window, but the dock icon will be the same as the application bundle's icon. + * For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @remark @macos The first time a window is created the menu bar is created. + * If GLFW finds a `MainMenu.nib` it is loaded and assumed to contain a menu + * bar. Otherwise a minimal menu bar is created manually with common commands + * like Hide, Quit and About. The About entry opens a minimal about dialog + * with information from the application's bundle. Menu bar creation can be + * disabled entirely with the @ref GLFW_COCOA_MENUBAR init hint. + * + * @remark @macos On OS X 10.10 and later the window frame will not be rendered + * at full resolution on Retina displays unless the + * [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint) + * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the + * application bundle's `Info.plist`. For more information, see + * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) + * in the Mac Developer Library. The GLFW test and example programs use + * a custom `Info.plist` template for this, which can be found as + * `CMake/MacOSXBundleInfo.plist.in` in the source tree. + * + * @remark @macos When activating frame autosaving with + * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified + * window size and position may be overridden by previously saved values. + * + * @remark @x11 Some window managers will not respect the placement of + * initially hidden windows. + * + * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for + * a window to reach its requested state. This means you may not be able to + * query the final size, position or other attributes directly after window + * creation. + * + * @remark @x11 The class part of the `WM_CLASS` window property will by + * default be set to the window title passed to this function. The instance + * part will use the contents of the `RESOURCE_NAME` environment variable, if + * present and not empty, or fall back to the window title. Set the + * [GLFW_X11_CLASS_NAME](@ref GLFW_X11_CLASS_NAME_hint) and + * [GLFW_X11_INSTANCE_NAME](@ref GLFW_X11_INSTANCE_NAME_hint) window hints to + * override this. + * + * @remark @wayland Compositors should implement the xdg-decoration protocol + * for GLFW to decorate the window properly. If this protocol isn't + * supported, or if the compositor prefers client-side decorations, a very + * simple fallback frame will be drawn using the wp_viewporter protocol. A + * compositor can still emit close, maximize or fullscreen events, using for + * instance a keybind mechanism. If neither of these protocols is supported, + * the window won't be decorated. + * + * @remark @wayland A full screen window will not attempt to change the mode, + * no matter what the requested size or refresh rate. + * + * @remark @wayland Screensaver inhibition requires the idle-inhibit protocol + * to be implemented in the user's compositor. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_creation + * @sa @ref glfwDestroyWindow + * + * @since Added in version 3.0. Replaces `glfwOpenWindow`. + * + * @ingroup window + */ +GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share); + +/*! @brief Destroys the specified window and its context. + * + * This function destroys the specified window and its context. On calling + * this function, no further callbacks will be called for that window. + * + * If the context of the specified window is current on the main thread, it is + * detached before being destroyed. + * + * @param[in] window The window to destroy. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @note The context of the specified window must not be current on any other + * thread when this function is called. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_creation + * @sa @ref glfwCreateWindow + * + * @since Added in version 3.0. Replaces `glfwCloseWindow`. + * + * @ingroup window + */ +GLFWAPI void glfwDestroyWindow(GLFWwindow* window); + +/*! @brief Checks the close flag of the specified window. + * + * This function returns the value of the close flag of the specified window. + * + * @param[in] window The window to query. + * @return The value of the close flag. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_close + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI int glfwWindowShouldClose(GLFWwindow* window); + +/*! @brief Sets the close flag of the specified window. + * + * This function sets the value of the close flag of the specified window. + * This can be used to override the user's attempt to close the window, or + * to signal that it should be closed. + * + * @param[in] window The window whose flag to change. + * @param[in] value The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_close + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value); + +/*! @brief Sets the title of the specified window. + * + * This function sets the window title, encoded as UTF-8, of the specified + * window. + * + * @param[in] window The window whose title to change. + * @param[in] title The UTF-8 encoded window title. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @macos The window title will not be updated until the next time you + * process events. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_title + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); + +/*! @brief Sets the icon for the specified window. + * + * This function sets the icon of the specified window. If passed an array of + * candidate images, those of or closest to the sizes desired by the system are + * selected. If no images are specified, the window reverts to its default + * icon. + * + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel with the red channel first. They are arranged canonically + * as packed sequential rows, starting from the top-left corner. + * + * The desired image sizes varies depending on platform and system settings. + * The selected images will be rescaled as needed. Good sizes include 16x16, + * 32x32 and 48x48. + * + * @param[in] window The window whose icon to set. + * @param[in] count The number of images in the specified array, or zero to + * revert to the default window icon. + * @param[in] images The images to create the icon from. This is ignored if + * count is zero. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @remark @macos The GLFW window has no icon, as it is not a document + * window, so this function does nothing. The dock icon will be the same as + * the application bundle's icon. For more information on bundles, see the + * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) + * in the Mac Developer Library. + * + * @remark @wayland There is no existing protocol to change an icon, the + * window will thus inherit the one defined in the application's desktop file. + * This function always emits @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_icon + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); + +/*! @brief Retrieves the position of the content area of the specified window. + * + * This function retrieves the position, in screen coordinates, of the + * upper-left corner of the content area of the specified window. + * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * + * @param[in] window The window to query. + * @param[out] xpos Where to store the x-coordinate of the upper-left corner of + * the content area, or `NULL`. + * @param[out] ypos Where to store the y-coordinate of the upper-left corner of + * the content area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland There is no way for an application to retrieve the global + * position of its windows, this function will always emit @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_pos + * @sa @ref glfwSetWindowPos + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos); + +/*! @brief Sets the position of the content area of the specified window. + * + * This function sets the position, in screen coordinates, of the upper-left + * corner of the content area of the specified windowed mode window. If the + * window is a full screen window, this function does nothing. + * + * __Do not use this function__ to move an already visible window unless you + * have very good reasons for doing so, as it will confuse and annoy the user. + * + * The window manager may put limits on what positions are allowed. GLFW + * cannot and should not override these limits. + * + * @param[in] window The window to query. + * @param[in] xpos The x-coordinate of the upper-left corner of the content area. + * @param[in] ypos The y-coordinate of the upper-left corner of the content area. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland There is no way for an application to set the global + * position of its windows, this function will always emit @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_pos + * @sa @ref glfwGetWindowPos + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos); + +/*! @brief Retrieves the size of the content area of the specified window. + * + * This function retrieves the size, in screen coordinates, of the content area + * of the specified window. If you wish to retrieve the size of the + * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] window The window whose size to retrieve. + * @param[out] width Where to store the width, in screen coordinates, of the + * content area, or `NULL`. + * @param[out] height Where to store the height, in screen coordinates, of the + * content area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * @sa @ref glfwSetWindowSize + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); + +/*! @brief Sets the size limits of the specified window. + * + * This function sets the size limits of the content area of the specified + * window. If the window is full screen, the size limits only take effect + * once it is made windowed. If the window is not resizable, this function + * does nothing. + * + * The size limits are applied immediately to a windowed mode window and may + * cause it to be resized. + * + * The maximum dimensions must be greater than or equal to the minimum + * dimensions and all must be greater than or equal to zero. + * + * @param[in] window The window to set limits for. + * @param[in] minwidth The minimum width, in screen coordinates, of the content + * area, or `GLFW_DONT_CARE`. + * @param[in] minheight The minimum height, in screen coordinates, of the + * content area, or `GLFW_DONT_CARE`. + * @param[in] maxwidth The maximum width, in screen coordinates, of the content + * area, or `GLFW_DONT_CARE`. + * @param[in] maxheight The maximum height, in screen coordinates, of the + * content area, or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @remark @wayland The size limits will not be applied until the window is + * actually resized, either by the user or by the compositor. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa @ref glfwSetWindowAspectRatio + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); + +/*! @brief Sets the aspect ratio of the specified window. + * + * This function sets the required aspect ratio of the content area of the + * specified window. If the window is full screen, the aspect ratio only takes + * effect once it is made windowed. If the window is not resizable, this + * function does nothing. + * + * The aspect ratio is specified as a numerator and a denominator and both + * values must be greater than zero. For example, the common 16:9 aspect ratio + * is specified as 16 and 9, respectively. + * + * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect + * ratio limit is disabled. + * + * The aspect ratio is applied immediately to a windowed mode window and may + * cause it to be resized. + * + * @param[in] window The window to set limits for. + * @param[in] numer The numerator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * @param[in] denom The denominator of the desired aspect ratio, or + * `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark If you set size limits and an aspect ratio that conflict, the + * results are undefined. + * + * @remark @wayland The aspect ratio will not be applied until the window is + * actually resized, either by the user or by the compositor. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_sizelimits + * @sa @ref glfwSetWindowSizeLimits + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); + +/*! @brief Sets the size of the content area of the specified window. + * + * This function sets the size, in screen coordinates, of the content area of + * the specified window. + * + * For full screen windows, this function updates the resolution of its desired + * video mode and switches to the video mode closest to it, without affecting + * the window's context. As the context is unaffected, the bit depths of the + * framebuffer remain unchanged. + * + * If you wish to update the refresh rate of the desired video mode in addition + * to its resolution, see @ref glfwSetWindowMonitor. + * + * The window manager may put limits on what sizes are allowed. GLFW cannot + * and should not override these limits. + * + * @param[in] window The window to resize. + * @param[in] width The desired width, in screen coordinates, of the window + * content area. + * @param[in] height The desired height, in screen coordinates, of the window + * content area. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland A full screen window will not attempt to change the mode, + * no matter what the requested size. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * @sa @ref glfwGetWindowSize + * @sa @ref glfwSetWindowMonitor + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); + +/*! @brief Retrieves the size of the framebuffer of the specified window. + * + * This function retrieves the size, in pixels, of the framebuffer of the + * specified window. If you wish to retrieve the size of the window in screen + * coordinates, see @ref glfwGetWindowSize. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] window The window whose framebuffer to query. + * @param[out] width Where to store the width, in pixels, of the framebuffer, + * or `NULL`. + * @param[out] height Where to store the height, in pixels, of the framebuffer, + * or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_fbsize + * @sa @ref glfwSetFramebufferSizeCallback + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height); + +/*! @brief Retrieves the size of the frame of the window. + * + * This function retrieves the size, in screen coordinates, of each edge of the + * frame of the specified window. This size includes the title bar, if the + * window has one. The size of the frame may vary depending on the + * [window-related hints](@ref window_hints_wnd) used to create it. + * + * Because this function retrieves the size of each window frame edge and not + * the offset along a particular coordinate axis, the retrieved values will + * always be zero or positive. + * + * Any or all of the size arguments may be `NULL`. If an error occurs, all + * non-`NULL` size arguments will be set to zero. + * + * @param[in] window The window whose frame size to query. + * @param[out] left Where to store the size, in screen coordinates, of the left + * edge of the window frame, or `NULL`. + * @param[out] top Where to store the size, in screen coordinates, of the top + * edge of the window frame, or `NULL`. + * @param[out] right Where to store the size, in screen coordinates, of the + * right edge of the window frame, or `NULL`. + * @param[out] bottom Where to store the size, in screen coordinates, of the + * bottom edge of the window frame, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * + * @since Added in version 3.1. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom); + +/*! @brief Retrieves the content scale for the specified window. + * + * This function retrieves the content scale for the specified window. The + * content scale is the ratio between the current DPI and the platform's + * default DPI. This is especially important for text and any UI elements. If + * the pixel dimensions of your UI scaled by this look appropriate on your + * machine then it should appear at a reasonable size on other machines + * regardless of their DPI and scaling settings. This relies on the system DPI + * and scaling settings being somewhat correct. + * + * On systems where each monitors can have its own content scale, the window + * content scale will depend on which monitor the system considers the window + * to be on. + * + * @param[in] window The window to query. + * @param[out] xscale Where to store the x-axis content scale, or `NULL`. + * @param[out] yscale Where to store the y-axis content scale, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_scale + * @sa @ref glfwSetWindowContentScaleCallback + * @sa @ref glfwGetMonitorContentScale + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale); + +/*! @brief Returns the opacity of the whole window. + * + * This function returns the opacity of the window, including any decorations. + * + * The opacity (or alpha) value is a positive finite number between zero and + * one, where zero is fully transparent and one is fully opaque. If the system + * does not support whole window transparency, this function always returns one. + * + * The initial opacity value for newly created windows is one. + * + * @param[in] window The window to query. + * @return The opacity value of the specified window. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_transparency + * @sa @ref glfwSetWindowOpacity + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window); + +/*! @brief Sets the opacity of the whole window. + * + * This function sets the opacity of the window, including any decorations. + * + * The opacity (or alpha) value is a positive finite number between zero and + * one, where zero is fully transparent and one is fully opaque. + * + * The initial opacity value for newly created windows is one. + * + * A window created with framebuffer transparency may not use whole window + * transparency. The results of doing this are undefined. + * + * @param[in] window The window to set the opacity for. + * @param[in] opacity The desired opacity of the specified window. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_transparency + * @sa @ref glfwGetWindowOpacity + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity); + +/*! @brief Iconifies the specified window. + * + * This function iconifies (minimizes) the specified window if it was + * previously restored. If the window is already iconified, this function does + * nothing. + * + * If the specified window is a full screen window, the original monitor + * resolution is restored until the window is restored. + * + * @param[in] window The window to iconify. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland There is no concept of iconification in wl_shell, this + * function will emit @ref GLFW_PLATFORM_ERROR when using this deprecated + * protocol. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa @ref glfwRestoreWindow + * @sa @ref glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwIconifyWindow(GLFWwindow* window); + +/*! @brief Restores the specified window. + * + * This function restores the specified window if it was previously iconified + * (minimized) or maximized. If the window is already restored, this function + * does nothing. + * + * If the specified window is a full screen window, the resolution chosen for + * the window is restored on the selected monitor. + * + * @param[in] window The window to restore. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * @sa @ref glfwIconifyWindow + * @sa @ref glfwMaximizeWindow + * + * @since Added in version 2.1. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwRestoreWindow(GLFWwindow* window); + +/*! @brief Maximizes the specified window. + * + * This function maximizes the specified window if it was previously not + * maximized. If the window is already maximized, this function does nothing. + * + * If the specified window is a full screen window, this function does nothing. + * + * @param[in] window The window to maximize. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @par Thread Safety + * This function may only be called from the main thread. + * + * @sa @ref window_iconify + * @sa @ref glfwIconifyWindow + * @sa @ref glfwRestoreWindow + * + * @since Added in GLFW 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); + +/*! @brief Makes the specified window visible. + * + * This function makes the specified window visible if it was previously + * hidden. If the window is already visible or is in full screen mode, this + * function does nothing. + * + * By default, windowed mode windows are focused when shown + * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint + * to change this behavior for all newly created windows, or change the + * behavior for an existing window with @ref glfwSetWindowAttrib. + * + * @param[in] window The window to make visible. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hide + * @sa @ref glfwHideWindow + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwShowWindow(GLFWwindow* window); + +/*! @brief Hides the specified window. + * + * This function hides the specified window if it was previously visible. If + * the window is already hidden or is in full screen mode, this function does + * nothing. + * + * @param[in] window The window to hide. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_hide + * @sa @ref glfwShowWindow + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwHideWindow(GLFWwindow* window); + +/*! @brief Brings the specified window to front and sets input focus. + * + * This function brings the specified window to front and sets input focus. + * The window should already be visible and not iconified. + * + * By default, both windowed and full screen mode windows are focused when + * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to + * disable this behavior. + * + * Also by default, windowed mode windows are focused when shown + * with @ref glfwShowWindow. Set the + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior. + * + * __Do not use this function__ to steal focus from other applications unless + * you are certain that is what the user wants. Focus stealing can be + * extremely disruptive. + * + * For a less disruptive way of getting the user's attention, see + * [attention requests](@ref window_attention). + * + * @param[in] window The window to give input focus. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland It is not possible for an application to bring its windows + * to front, this function will always emit @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * @sa @ref window_attention + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwFocusWindow(GLFWwindow* window); + +/*! @brief Requests user attention to the specified window. + * + * This function requests user attention to the specified window. On + * platforms where this is not supported, attention is requested to the + * application as a whole. + * + * Once the user has given attention, usually by focusing the window or + * application, the system will end the request automatically. + * + * @param[in] window The window to request attention to. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @macos Attention is requested to the application as a whole, not the + * specific window. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_attention + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); + +/*! @brief Returns the monitor that the window uses for full screen mode. + * + * This function returns the handle of the monitor that the specified window is + * in full screen on. + * + * @param[in] window The window to query. + * @return The monitor, or `NULL` if the window is in windowed mode or an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref glfwSetWindowMonitor + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); + +/*! @brief Sets the mode, monitor, video mode and placement of a window. + * + * This function sets the monitor that the window uses for full screen mode or, + * if the monitor is `NULL`, makes it windowed mode. + * + * When setting a monitor, this function updates the width, height and refresh + * rate of the desired video mode and switches to the video mode closest to it. + * The window position is ignored when setting a monitor. + * + * When the monitor is `NULL`, the position, width and height are used to + * place the window content area. The refresh rate is ignored when no monitor + * is specified. + * + * If you only wish to update the resolution of a full screen window or the + * size of a windowed mode window, see @ref glfwSetWindowSize. + * + * When a window transitions from full screen to windowed mode, this function + * restores any previous window settings such as whether it is decorated, + * floating, resizable, has size or aspect ratio limits, etc. + * + * @param[in] window The window whose monitor, size or video mode to set. + * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. + * @param[in] xpos The desired x-coordinate of the upper-left corner of the + * content area. + * @param[in] ypos The desired y-coordinate of the upper-left corner of the + * content area. + * @param[in] width The desired with, in screen coordinates, of the content + * area or video mode. + * @param[in] height The desired height, in screen coordinates, of the content + * area or video mode. + * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode, + * or `GLFW_DONT_CARE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise + * affected by any resizing or mode switching, although you may need to update + * your viewport if the framebuffer size has changed. + * + * @remark @wayland The desired window position is ignored, as there is no way + * for an application to set this property. + * + * @remark @wayland Setting the window to full screen will not attempt to + * change the mode, no matter what the requested size or refresh rate. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_monitor + * @sa @ref window_full_screen + * @sa @ref glfwGetWindowMonitor + * @sa @ref glfwSetWindowSize + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); + +/*! @brief Returns an attribute of the specified window. + * + * This function returns the value of an attribute of the specified window or + * its OpenGL or OpenGL ES context. + * + * @param[in] window The window to query. + * @param[in] attrib The [window attribute](@ref window_attribs) whose value to + * return. + * @return The value of the attribute, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @remark Framebuffer related hints are not window attributes. See @ref + * window_attribs_fb for more information. + * + * @remark Zero is a valid value for many window and context related + * attributes so you cannot use a return value of zero as an indication of + * errors. However, this function should not fail as long as it is passed + * valid arguments and the library has been [initialized](@ref intro_init). + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_attribs + * @sa @ref glfwSetWindowAttrib + * + * @since Added in version 3.0. Replaces `glfwGetWindowParam` and + * `glfwGetGLVersion`. + * + * @ingroup window + */ +GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); + +/*! @brief Sets an attribute of the specified window. + * + * This function sets the value of an attribute of the specified window. + * + * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), + * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), + * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), + * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and + * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). + * + * Some of these attributes are ignored for full screen windows. The new + * value will take effect if the window is later made windowed. + * + * Some of these attributes are ignored for windowed mode windows. The new + * value will take effect if the window is later made full screen. + * + * @param[in] window The window to set the attribute for. + * @param[in] attrib A supported window attribute. + * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @remark Calling @ref glfwGetWindowAttrib will always return the latest + * value, even if that value is ignored by the current mode of the window. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_attribs + * @sa @ref glfwGetWindowAttrib + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value); + +/*! @brief Sets the user pointer of the specified window. + * + * This function sets the user-defined pointer of the specified window. The + * current value is retained until the window is destroyed. The initial value + * is `NULL`. + * + * @param[in] window The window whose pointer to set. + * @param[in] pointer The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_userptr + * @sa @ref glfwGetWindowUserPointer + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer); + +/*! @brief Returns the user pointer of the specified window. + * + * This function returns the current value of the user-defined pointer of the + * specified window. The initial value is `NULL`. + * + * @param[in] window The window whose pointer to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref window_userptr + * @sa @ref glfwSetWindowUserPointer + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window); + +/*! @brief Sets the position callback for the specified window. + * + * This function sets the position callback of the specified window, which is + * called when the window is moved. The callback is provided with the + * position, in screen coordinates, of the upper-left corner of the content + * area of the window. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int xpos, int ypos) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowposfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @wayland This callback will never be called, as there is no way for + * an application to know its global position. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_pos + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun callback); + +/*! @brief Sets the size callback for the specified window. + * + * This function sets the size callback of the specified window, which is + * called when the window is resized. The callback is provided with the size, + * in screen coordinates, of the content area of the window. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int width, int height) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowsizefun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_size + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup window + */ +GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun callback); + +/*! @brief Sets the close callback for the specified window. + * + * This function sets the close callback of the specified window, which is + * called when the user attempts to close the window, for example by clicking + * the close widget in the title bar. + * + * The close flag is set before this callback is called, but you can modify it + * at any time with @ref glfwSetWindowShouldClose. + * + * The close callback is not triggered by @ref glfwDestroyWindow. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowclosefun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @macos Selecting Quit from the application menu will trigger the + * close callback for all windows. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_close + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup window + */ +GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback); + +/*! @brief Sets the refresh callback for the specified window. + * + * This function sets the refresh callback of the specified window, which is + * called when the content area of the window needs to be redrawn, for example + * if the window has been exposed after having been covered by another window. + * + * On compositing window systems such as Aero, Compiz, Aqua or Wayland, where + * the window contents are saved off-screen, this callback may be called only + * very infrequently or never at all. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window); + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowrefreshfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_refresh + * + * @since Added in version 2.5. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup window + */ +GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun callback); + +/*! @brief Sets the focus callback for the specified window. + * + * This function sets the focus callback of the specified window, which is + * called when the window gains or loses input focus. + * + * After the focus callback is called for a window that lost input focus, + * synthetic key and mouse button release events will be generated for all such + * that had been pressed. For more information, see @ref glfwSetKeyCallback + * and @ref glfwSetMouseButtonCallback. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int focused) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowfocusfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_focus + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun callback); + +/*! @brief Sets the iconify callback for the specified window. + * + * This function sets the iconification callback of the specified window, which + * is called when the window is iconified or restored. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int iconified) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowiconifyfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @wayland The wl_shell protocol has no concept of iconification, + * this callback will never be called when using this deprecated protocol. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_iconify + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun callback); + +/*! @brief Sets the maximize callback for the specified window. + * + * This function sets the maximization callback of the specified window, which + * is called when the window is maximized or restored. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int maximized) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowmaximizefun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_maximize + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback); + +/*! @brief Sets the framebuffer resize callback for the specified window. + * + * This function sets the framebuffer resize callback of the specified window, + * which is called when the framebuffer of the specified window is resized. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int width, int height) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWframebuffersizefun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_fbsize + * + * @since Added in version 3.0. + * + * @ingroup window + */ +GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun callback); + +/*! @brief Sets the window content scale callback for the specified window. + * + * This function sets the window content scale callback of the specified window, + * which is called when the content scale of the specified window changes. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, float xscale, float yscale) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWwindowcontentscalefun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref window_scale + * @sa @ref glfwGetWindowContentScale + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun callback); + +/*! @brief Processes all pending events. + * + * This function processes only those events that are already in the event + * queue and then returns immediately. Processing events will cause the window + * and input callbacks associated with those events to be called. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * Do not assume that callbacks you set will _only_ be called in response to + * event processing functions like this one. While it is necessary to poll for + * events, window systems that require GLFW to register callbacks of its own + * can pass events to GLFW in response to many window system function calls. + * GLFW will pass those events on to the application callbacks before + * returning. + * + * Event processing is not required for joystick input to work. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa @ref glfwWaitEvents + * @sa @ref glfwWaitEventsTimeout + * + * @since Added in version 1.0. + * + * @ingroup window + */ +GLFWAPI void glfwPollEvents(void); + +/*! @brief Waits until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue. Once one or more events are available, + * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue + * are processed and the function then returns immediately. Processing events + * will cause the window and input callbacks associated with those events to be + * called. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * Do not assume that callbacks you set will _only_ be called in response to + * event processing functions like this one. While it is necessary to poll for + * events, window systems that require GLFW to register callbacks of its own + * can pass events to GLFW in response to many window system function calls. + * GLFW will pass those events on to the application callbacks before + * returning. + * + * Event processing is not required for joystick input to work. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa @ref glfwPollEvents + * @sa @ref glfwWaitEventsTimeout + * + * @since Added in version 2.5. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEvents(void); + +/*! @brief Waits with timeout until events are queued and processes them. + * + * This function puts the calling thread to sleep until at least one event is + * available in the event queue, or until the specified timeout is reached. If + * one or more events are available, it behaves exactly like @ref + * glfwPollEvents, i.e. the events in the queue are processed and the function + * then returns immediately. Processing events will cause the window and input + * callbacks associated with those events to be called. + * + * The timeout value must be a positive finite number. + * + * Since not all events are associated with callbacks, this function may return + * without a callback having been called even if you are monitoring all + * callbacks. + * + * On some platforms, a window move, resize or menu operation will cause event + * processing to block. This is due to how event processing is designed on + * those platforms. You can use the + * [window refresh callback](@ref window_refresh) to redraw the contents of + * your window when necessary during such operations. + * + * Do not assume that callbacks you set will _only_ be called in response to + * event processing functions like this one. While it is necessary to poll for + * events, window systems that require GLFW to register callbacks of its own + * can pass events to GLFW in response to many window system function calls. + * GLFW will pass those events on to the application callbacks before + * returning. + * + * Event processing is not required for joystick input to work. + * + * @param[in] timeout The maximum amount of time, in seconds, to wait. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref events + * @sa @ref glfwPollEvents + * @sa @ref glfwWaitEvents + * + * @since Added in version 3.2. + * + * @ingroup window + */ +GLFWAPI void glfwWaitEventsTimeout(double timeout); + +/*! @brief Posts an empty event to the event queue. + * + * This function posts an empty event from the current thread to the event + * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref events + * @sa @ref glfwWaitEvents + * @sa @ref glfwWaitEventsTimeout + * + * @since Added in version 3.1. + * + * @ingroup window + */ +GLFWAPI void glfwPostEmptyEvent(void); + +/*! @brief Returns the value of an input option for the specified window. + * + * This function returns the value of an input option for the specified window. + * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or + * @ref GLFW_RAW_MOUSE_MOTION. + * + * @param[in] window The window to query. + * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or + * `GLFW_RAW_MOUSE_MOTION`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref glfwSetInputMode + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); + +/*! @brief Sets an input option for the specified window. + * + * This function sets an input mode option for the specified window. The mode + * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, + * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or + * @ref GLFW_RAW_MOUSE_MOTION. + * + * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor + * modes: + * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally. + * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the + * content area of the window but does not restrict the cursor from leaving. + * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual + * and unlimited cursor movement. This is useful for implementing for + * example 3D camera controls. + * + * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to + * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are + * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` + * the next time it is called even if the key had been released before the + * call. This is useful when you are only interested in whether keys have been + * pressed but not when or in which order. + * + * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either + * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. + * If sticky mouse buttons are enabled, a mouse button press will ensure that + * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even + * if the mouse button had been released before the call. This is useful when + * you are only interested in whether mouse buttons have been pressed but not + * when or in which order. + * + * If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to + * enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled, + * callbacks that receive modifier bits will also have the @ref + * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on, + * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on. + * + * If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE` + * to enable raw (unscaled and unaccelerated) mouse motion when the cursor is + * disabled, or `GLFW_FALSE` to disable it. If raw motion is not supported, + * attempting to set this will emit @ref GLFW_PLATFORM_ERROR. Call @ref + * glfwRawMouseMotionSupported to check for support. + * + * @param[in] window The window whose input mode to set. + * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, + * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or + * `GLFW_RAW_MOUSE_MOTION`. + * @param[in] value The new value of the specified input mode. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref glfwGetInputMode + * + * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. + * + * @ingroup input + */ +GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); + +/*! @brief Returns whether raw mouse motion is supported. + * + * This function returns whether raw mouse motion is supported on the current + * system. This status does not change after GLFW has been initialized so you + * only need to check this once. If you attempt to enable raw motion on + * a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted. + * + * Raw mouse motion is closer to the actual motion of the mouse across + * a surface. It is not affected by the scaling and acceleration applied to + * the motion of the desktop cursor. That processing is suitable for a cursor + * while raw motion is better for controlling for example a 3D camera. Because + * of this, raw mouse motion is only provided when the cursor is disabled. + * + * @return `GLFW_TRUE` if raw mouse motion is supported on the current machine, + * or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref raw_mouse_motion + * @sa @ref glfwSetInputMode + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwRawMouseMotionSupported(void); + +/*! @brief Returns the layout-specific name of the specified printable key. + * + * This function returns the name of the specified printable key, encoded as + * UTF-8. This is typically the character that key would produce without any + * modifier keys, intended for displaying key bindings to the user. For dead + * keys, it is typically the diacritic it would add to a character. + * + * __Do not use this function__ for [text input](@ref input_char). You will + * break text input for many languages even if it happens to work for yours. + * + * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key, + * otherwise the scancode is ignored. If you specify a non-printable key, or + * `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this + * function returns `NULL` but does not emit an error. + * + * This behavior allows you to always pass in the arguments in the + * [key callback](@ref input_key) without modification. + * + * The printable keys are: + * - `GLFW_KEY_APOSTROPHE` + * - `GLFW_KEY_COMMA` + * - `GLFW_KEY_MINUS` + * - `GLFW_KEY_PERIOD` + * - `GLFW_KEY_SLASH` + * - `GLFW_KEY_SEMICOLON` + * - `GLFW_KEY_EQUAL` + * - `GLFW_KEY_LEFT_BRACKET` + * - `GLFW_KEY_RIGHT_BRACKET` + * - `GLFW_KEY_BACKSLASH` + * - `GLFW_KEY_WORLD_1` + * - `GLFW_KEY_WORLD_2` + * - `GLFW_KEY_0` to `GLFW_KEY_9` + * - `GLFW_KEY_A` to `GLFW_KEY_Z` + * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` + * - `GLFW_KEY_KP_DECIMAL` + * - `GLFW_KEY_KP_DIVIDE` + * - `GLFW_KEY_KP_MULTIPLY` + * - `GLFW_KEY_KP_SUBTRACT` + * - `GLFW_KEY_KP_ADD` + * - `GLFW_KEY_KP_EQUAL` + * + * Names for printable keys depend on keyboard layout, while names for + * non-printable keys are the same across layouts but depend on the application + * language and should be localized along with other user interface text. + * + * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. + * @param[in] scancode The scancode of the key to query. + * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark The contents of the returned string may change when a keyboard + * layout change event is received. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key_name + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetKeyName(int key, int scancode); + +/*! @brief Returns the platform-specific scancode of the specified key. + * + * This function returns the platform-specific scancode of the specified key. + * + * If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this + * method will return `-1`. + * + * @param[in] key Any [named key](@ref keys). + * @return The platform-specific scancode for the key, or `-1` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref input_key + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwGetKeyScancode(int key); + +/*! @brief Returns the last reported state of a keyboard key for the specified + * window. + * + * This function returns the last state reported for the specified key to the + * specified window. The returned state is one of `GLFW_PRESS` or + * `GLFW_RELEASE`. The higher-level action `GLFW_REPEAT` is only reported to + * the key callback. + * + * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns + * `GLFW_PRESS` the first time you call it for a key that was pressed, even if + * that key has already been released. + * + * The key functions deal with physical keys, with [key tokens](@ref keys) + * named after their use on the standard US keyboard layout. If you want to + * input text, use the Unicode character callback instead. + * + * The [modifier key bit masks](@ref mods) are not key tokens and cannot be + * used with this function. + * + * __Do not use this function__ to implement [text input](@ref input_char). + * + * @param[in] window The desired window. + * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is + * not a valid key for this function. + * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup input + */ +GLFWAPI int glfwGetKey(GLFWwindow* window, int key); + +/*! @brief Returns the last reported state of a mouse button for the specified + * window. + * + * This function returns the last state reported for the specified mouse button + * to the specified window. The returned state is one of `GLFW_PRESS` or + * `GLFW_RELEASE`. + * + * If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function + * returns `GLFW_PRESS` the first time you call it for a mouse button that was + * pressed, even if that mouse button has already been released. + * + * @param[in] window The desired window. + * @param[in] button The desired [mouse button](@ref buttons). + * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_mouse_button + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup input + */ +GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button); + +/*! @brief Retrieves the position of the cursor relative to the content area of + * the window. + * + * This function returns the position of the cursor, in screen coordinates, + * relative to the upper-left corner of the content area of the specified + * window. + * + * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor + * position is unbounded and limited only by the minimum and maximum values of + * a `double`. + * + * The coordinate can be converted to their integer equivalents with the + * `floor` function. Casting directly to an integer type works for positive + * coordinates, but fails for negative ones. + * + * Any or all of the position arguments may be `NULL`. If an error occurs, all + * non-`NULL` position arguments will be set to zero. + * + * @param[in] window The desired window. + * @param[out] xpos Where to store the cursor x-coordinate, relative to the + * left edge of the content area, or `NULL`. + * @param[out] ypos Where to store the cursor y-coordinate, relative to the to + * top edge of the content area, or `NULL`. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_pos + * @sa @ref glfwSetCursorPos + * + * @since Added in version 3.0. Replaces `glfwGetMousePos`. + * + * @ingroup input + */ +GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); + +/*! @brief Sets the position of the cursor, relative to the content area of the + * window. + * + * This function sets the position, in screen coordinates, of the cursor + * relative to the upper-left corner of the content area of the specified + * window. The window must have input focus. If the window does not have + * input focus when this function is called, it fails silently. + * + * __Do not use this function__ to implement things like camera controls. GLFW + * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the + * cursor, transparently re-centers it and provides unconstrained cursor + * motion. See @ref glfwSetInputMode for more information. + * + * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is + * unconstrained and limited only by the minimum and maximum values of + * a `double`. + * + * @param[in] window The desired window. + * @param[in] xpos The desired x-coordinate, relative to the left edge of the + * content area. + * @param[in] ypos The desired y-coordinate, relative to the top edge of the + * content area. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @wayland This function will only work when the cursor mode is + * `GLFW_CURSOR_DISABLED`, otherwise it will do nothing. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_pos + * @sa @ref glfwGetCursorPos + * + * @since Added in version 3.0. Replaces `glfwSetMousePos`. + * + * @ingroup input + */ +GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); + +/*! @brief Creates a custom cursor. + * + * Creates a new custom cursor image that can be set for a window with @ref + * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. + * Any remaining cursors are destroyed by @ref glfwTerminate. + * + * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight + * bits per channel with the red channel first. They are arranged canonically + * as packed sequential rows, starting from the top-left corner. + * + * The cursor hotspot is specified in pixels, relative to the upper-left corner + * of the cursor image. Like all other coordinate systems in GLFW, the X-axis + * points to the right and the Y-axis points down. + * + * @param[in] image The desired cursor image. + * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. + * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. + * @return The handle of the created cursor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified image data is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * @sa @ref glfwDestroyCursor + * @sa @ref glfwCreateStandardCursor + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot); + +/*! @brief Creates a cursor with a standard shape. + * + * Returns a cursor with a [standard shape](@ref shapes), that can be set for + * a window with @ref glfwSetCursor. + * + * @param[in] shape One of the [standard shapes](@ref shapes). + * @return A new cursor ready to use or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * @sa @ref glfwCreateCursor + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape); + +/*! @brief Destroys a cursor. + * + * This function destroys a cursor previously created with @ref + * glfwCreateCursor. Any remaining cursors will be destroyed by @ref + * glfwTerminate. + * + * If the specified cursor is current for any window, that window will be + * reverted to the default cursor. This does not affect the cursor mode. + * + * @param[in] cursor The cursor object to destroy. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @reentrancy This function must not be called from a callback. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * @sa @ref glfwCreateCursor + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor); + +/*! @brief Sets the cursor for the window. + * + * This function sets the cursor image to be used when the cursor is over the + * content area of the specified window. The set cursor will only be visible + * when the [cursor mode](@ref cursor_mode) of the window is + * `GLFW_CURSOR_NORMAL`. + * + * On some platforms, the set cursor may not be visible unless the window also + * has input focus. + * + * @param[in] window The window to set the cursor for. + * @param[in] cursor The cursor to set, or `NULL` to switch back to the default + * arrow cursor. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_object + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); + +/*! @brief Sets the key callback. + * + * This function sets the key callback of the specified window, which is called + * when a key is pressed, repeated or released. + * + * The key functions deal with physical keys, with layout independent + * [key tokens](@ref keys) named after their values in the standard US keyboard + * layout. If you want to input text, use the + * [character callback](@ref glfwSetCharCallback) instead. + * + * When a window loses input focus, it will generate synthetic key release + * events for all pressed keys. You can tell these events from user-generated + * events by the fact that the synthetic ones are generated after the focus + * loss event has been processed, i.e. after the + * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. + * + * The scancode of a key is specific to that platform or sometimes even to that + * machine. Scancodes are intended to allow users to bind keys that don't have + * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their + * state is not saved and so it cannot be queried with @ref glfwGetKey. + * + * Sometimes GLFW needs to generate synthetic key events, in which case the + * scancode may be zero. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new key callback, or `NULL` to remove the currently + * set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWkeyfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_key + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup input + */ +GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun callback); + +/*! @brief Sets the Unicode character callback. + * + * This function sets the character callback of the specified window, which is + * called when a Unicode character is input. + * + * The character callback is intended for Unicode text input. As it deals with + * characters, it is keyboard layout dependent, whereas the + * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1 + * to physical keys, as a key may produce zero, one or more characters. If you + * want to know whether a specific physical key was pressed or released, see + * the key callback instead. + * + * The character callback behaves as system text input normally does and will + * not be called if modifier keys are held down that would prevent normal text + * input on that platform, for example a Super (Command) key on macOS or Alt key + * on Windows. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, unsigned int codepoint) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWcharfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_char + * + * @since Added in version 2.4. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup input + */ +GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun callback); + +/*! @brief Sets the Unicode character with modifiers callback. + * + * This function sets the character with modifiers callback of the specified + * window, which is called when a Unicode character is input regardless of what + * modifier keys are used. + * + * The character with modifiers callback is intended for implementing custom + * Unicode character input. For regular Unicode text input, see the + * [character callback](@ref glfwSetCharCallback). Like the character + * callback, the character with modifiers callback deals with characters and is + * keyboard layout dependent. Characters do not map 1:1 to physical keys, as + * a key may produce zero, one or more characters. If you want to know whether + * a specific physical key was pressed or released, see the + * [key callback](@ref glfwSetKeyCallback) instead. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or an + * [error](@ref error_handling) occurred. + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, unsigned int codepoint, int mods) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWcharmodsfun). + * + * @deprecated Scheduled for removal in version 4.0. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_char + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun callback); + +/*! @brief Sets the mouse button callback. + * + * This function sets the mouse button callback of the specified window, which + * is called when a mouse button is pressed or released. + * + * When a window loses input focus, it will generate synthetic mouse button + * release events for all pressed mouse buttons. You can tell these events + * from user-generated events by the fact that the synthetic ones are generated + * after the focus loss event has been processed, i.e. after the + * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int button, int action, int mods) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWmousebuttonfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref input_mouse_button + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter and return value. + * + * @ingroup input + */ +GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun callback); + +/*! @brief Sets the cursor position callback. + * + * This function sets the cursor position callback of the specified window, + * which is called when the cursor is moved. The callback is provided with the + * position, in screen coordinates, relative to the upper-left corner of the + * content area of the window. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, double xpos, double ypos); + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWcursorposfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_pos + * + * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. + * + * @ingroup input + */ +GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun callback); + +/*! @brief Sets the cursor enter/leave callback. + * + * This function sets the cursor boundary crossing callback of the specified + * window, which is called when the cursor enters or leaves the content area of + * the window. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int entered) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWcursorenterfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref cursor_enter + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun callback); + +/*! @brief Sets the scroll callback. + * + * This function sets the scroll callback of the specified window, which is + * called when a scrolling device is used, such as a mouse wheel or scrolling + * area of a touchpad. + * + * The scroll callback receives all scrolling input, like that from a mouse + * wheel or a touchpad scrolling area. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new scroll callback, or `NULL` to remove the + * currently set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, double xoffset, double yoffset) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWscrollfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref scrolling + * + * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. + * + * @ingroup input + */ +GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback); + +/*! @brief Sets the path drop callback. + * + * This function sets the path drop callback of the specified window, which is + * called when one or more dragged paths are dropped on the window. + * + * Because the path array and its strings may have been generated specifically + * for that event, they are not guaranteed to be valid after the callback has + * returned. If you wish to use them after the callback returns, you need to + * make a deep copy. + * + * @param[in] window The window whose callback to set. + * @param[in] callback The new file drop callback, or `NULL` to remove the + * currently set callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(GLFWwindow* window, int path_count, const char* paths[]) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWdropfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @remark @wayland File drop is currently unimplemented. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref path_drop + * + * @since Added in version 3.1. + * + * @ingroup input + */ +GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback); + +/*! @brief Returns whether the specified joystick is present. + * + * This function returns whether the specified joystick is present. + * + * There is no need to call this function before other functions that accept + * a joystick ID, as they all check for presence before performing any other + * work. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick + * + * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. + * + * @ingroup input + */ +GLFWAPI int glfwJoystickPresent(int jid); + +/*! @brief Returns the values of all axes of the specified joystick. + * + * This function returns the values of all axes of the specified joystick. + * Each element in the array is a value between -1.0 and 1.0. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of axis values in the returned + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of axis values, or `NULL` if the joystick is not present or + * an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_axis + * + * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. + * + * @ingroup input + */ +GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count); + +/*! @brief Returns the state of all buttons of the specified joystick. + * + * This function returns the state of all buttons of the specified joystick. + * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. + * + * For backward compatibility with earlier versions that did not have @ref + * glfwGetJoystickHats, the button array also includes all hats, each + * represented as four buttons. The hats are in the same order as returned by + * __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and + * _left_. To disable these extra buttons, set the @ref + * GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of button states in the returned + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of button states, or `NULL` if the joystick is not present + * or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_button + * + * @since Added in version 2.2. + * @glfw3 Changed to return a dynamic array. + * + * @ingroup input + */ +GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count); + +/*! @brief Returns the state of all hats of the specified joystick. + * + * This function returns the state of all hats of the specified joystick. + * Each element in the array is one of the following values: + * + * Name | Value + * ---- | ----- + * `GLFW_HAT_CENTERED` | 0 + * `GLFW_HAT_UP` | 1 + * `GLFW_HAT_RIGHT` | 2 + * `GLFW_HAT_DOWN` | 4 + * `GLFW_HAT_LEFT` | 8 + * `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP` + * `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN` + * `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP` + * `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN` + * + * The diagonal directions are bitwise combinations of the primary (up, right, + * down and left) directions and you can test for these individually by ANDing + * it with the corresponding direction. + * + * @code + * if (hats[2] & GLFW_HAT_RIGHT) + * { + * // State of hat 2 could be right-up, right or right-down + * } + * @endcode + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] count Where to store the number of hat states in the returned + * array. This is set to zero if the joystick is not present or an error + * occurred. + * @return An array of hat states, or `NULL` if the joystick is not present + * or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, this function is called again for that joystick or the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_hat + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count); + +/*! @brief Returns the name of the specified joystick. + * + * This function returns the name, encoded as UTF-8, of the specified joystick. + * The returned string is allocated and freed by GLFW. You should not free it + * yourself. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick + * is not present or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_name + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetJoystickName(int jid); + +/*! @brief Returns the SDL compatible GUID of the specified joystick. + * + * This function returns the SDL compatible GUID, as a UTF-8 encoded + * hexadecimal string, of the specified joystick. The returned string is + * allocated and freed by GLFW. You should not free it yourself. + * + * The GUID is what connects a joystick to a gamepad mapping. A connected + * joystick will always have a GUID even if there is no gamepad mapping + * assigned to it. + * + * If the specified joystick is not present this function will return `NULL` + * but will not generate an error. This can be used instead of first calling + * @ref glfwJoystickPresent. + * + * The GUID uses the format introduced in SDL 2.0.5. This GUID tries to + * uniquely identify the make and model of a joystick but does not identify + * a specific unit, e.g. all wired Xbox 360 controllers will have the same + * GUID on that platform. The GUID for a unit may vary between platforms + * depending on what hardware information the platform specific APIs provide. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return The UTF-8 encoded GUID of the joystick, or `NULL` if the joystick + * is not present or an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetJoystickGUID(int jid); + +/*! @brief Sets the user pointer of the specified joystick. + * + * This function sets the user-defined pointer of the specified joystick. The + * current value is retained until the joystick is disconnected. The initial + * value is `NULL`. + * + * This function may be called from the joystick callback, even for a joystick + * that is being disconnected. + * + * @param[in] jid The joystick whose pointer to set. + * @param[in] pointer The new value. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref joystick_userptr + * @sa @ref glfwGetJoystickUserPointer + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer); + +/*! @brief Returns the user pointer of the specified joystick. + * + * This function returns the current value of the user-defined pointer of the + * specified joystick. The initial value is `NULL`. + * + * This function may be called from the joystick callback, even for a joystick + * that is being disconnected. + * + * @param[in] jid The joystick whose pointer to return. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @sa @ref joystick_userptr + * @sa @ref glfwSetJoystickUserPointer + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI void* glfwGetJoystickUserPointer(int jid); + +/*! @brief Returns whether the specified joystick has a gamepad mapping. + * + * This function returns whether the specified joystick is both present and has + * a gamepad mapping. + * + * If the specified joystick is present but does not have a gamepad mapping + * this function will return `GLFW_FALSE` but will not generate an error. Call + * @ref glfwJoystickPresent to check if a joystick is present regardless of + * whether it has a mapping. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping, + * or `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwGetGamepadState + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwJoystickIsGamepad(int jid); + +/*! @brief Sets the joystick configuration callback. + * + * This function sets the joystick configuration callback, or removes the + * currently set callback. This is called when a joystick is connected to or + * disconnected from the system. + * + * For joystick connection and disconnection events to be delivered on all + * platforms, you need to call one of the [event processing](@ref events) + * functions. Joystick disconnection may also be detected and the callback + * called by joystick functions. The function will then return whatever it + * returns if the joystick is not present. + * + * @param[in] callback The new callback, or `NULL` to remove the currently set + * callback. + * @return The previously set callback, or `NULL` if no callback was set or the + * library had not been [initialized](@ref intro_init). + * + * @callback_signature + * @code + * void function_name(int jid, int event) + * @endcode + * For more information about the callback parameters, see the + * [function pointer type](@ref GLFWjoystickfun). + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref joystick_event + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun callback); + +/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings. + * + * This function parses the specified ASCII encoded string and updates the + * internal list with any gamepad mappings it finds. This string may + * contain either a single gamepad mapping or many mappings separated by + * newlines. The parser supports the full format of the `gamecontrollerdb.txt` + * source file including empty lines and comments. + * + * See @ref gamepad_mapping for a description of the format. + * + * If there is already a gamepad mapping for a given GUID in the internal list, + * it will be replaced by the one passed to this function. If the library is + * terminated and re-initialized the internal list will revert to the built-in + * default. + * + * @param[in] string The string containing the gamepad mappings. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwJoystickIsGamepad + * @sa @ref glfwGetGamepadName + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwUpdateGamepadMappings(const char* string); + +/*! @brief Returns the human-readable gamepad name for the specified joystick. + * + * This function returns the human-readable name of the gamepad from the + * gamepad mapping assigned to the specified joystick. + * + * If the specified joystick is not present or does not have a gamepad mapping + * this function will return `NULL` but will not generate an error. Call + * @ref glfwJoystickPresent to check whether it is present regardless of + * whether it has a mapping. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @return The UTF-8 encoded name of the gamepad, or `NULL` if the + * joystick is not present, does not have a mapping or an + * [error](@ref error_handling) occurred. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the specified joystick is + * disconnected, the gamepad mappings are updated or the library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwJoystickIsGamepad + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetGamepadName(int jid); + +/*! @brief Retrieves the state of the specified joystick remapped as a gamepad. + * + * This function retrieves the state of the specified joystick remapped to + * an Xbox-like gamepad. + * + * If the specified joystick is not present or does not have a gamepad mapping + * this function will return `GLFW_FALSE` but will not generate an error. Call + * @ref glfwJoystickPresent to check whether it is present regardless of + * whether it has a mapping. + * + * The Guide button may not be available for input as it is often hooked by the + * system or the Steam client. + * + * Not all devices have all the buttons or axes provided by @ref + * GLFWgamepadstate. Unavailable buttons and axes will always report + * `GLFW_RELEASE` and 0.0 respectively. + * + * @param[in] jid The [joystick](@ref joysticks) to query. + * @param[out] state The gamepad input state of the joystick. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is + * connected, it has no gamepad mapping or an [error](@ref error_handling) + * occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_ENUM. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref gamepad + * @sa @ref glfwUpdateGamepadMappings + * @sa @ref glfwJoystickIsGamepad + * + * @since Added in version 3.3. + * + * @ingroup input + */ +GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state); + +/*! @brief Sets the clipboard to the specified string. + * + * This function sets the system clipboard to the specified, UTF-8 encoded + * string. + * + * @param[in] window Deprecated. Any valid window or `NULL`. + * @param[in] string A UTF-8 encoded string. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa @ref glfwGetClipboardString + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); + +/*! @brief Returns the contents of the clipboard as a string. + * + * This function returns the contents of the system clipboard, if it contains + * or is convertible to a UTF-8 encoded string. If the clipboard is empty or + * if its contents cannot be converted, `NULL` is returned and a @ref + * GLFW_FORMAT_UNAVAILABLE error is generated. + * + * @param[in] window Deprecated. Any valid window or `NULL`. + * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` + * if an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library + * is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa @ref glfwSetClipboardString + * + * @since Added in version 3.0. + * + * @ingroup input + */ +GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); + +/*! @brief Returns the GLFW time. + * + * This function returns the current GLFW time, in seconds. Unless the time + * has been set using @ref glfwSetTime it measures time elapsed since GLFW was + * initialized. + * + * This function and @ref glfwSetTime are helper functions on top of @ref + * glfwGetTimerFrequency and @ref glfwGetTimerValue. + * + * The resolution of the timer is system dependent, but is usually on the order + * of a few micro- or nanoseconds. It uses the highest-resolution monotonic + * time source on each supported platform. + * + * @return The current time, in seconds, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. Reading and + * writing of the internal base time is not atomic, so it needs to be + * externally synchronized with calls to @ref glfwSetTime. + * + * @sa @ref time + * + * @since Added in version 1.0. + * + * @ingroup input + */ +GLFWAPI double glfwGetTime(void); + +/*! @brief Sets the GLFW time. + * + * This function sets the current GLFW time, in seconds. The value must be + * a positive finite number less than or equal to 18446744073.0, which is + * approximately 584.5 years. + * + * This function and @ref glfwGetTime are helper functions on top of @ref + * glfwGetTimerFrequency and @ref glfwGetTimerValue. + * + * @param[in] time The new value, in seconds. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_INVALID_VALUE. + * + * @remark The upper limit of GLFW time is calculated as + * floor((264 - 1) / 109) and is due to implementations + * storing nanoseconds in 64 bits. The limit may be increased in the future. + * + * @thread_safety This function may be called from any thread. Reading and + * writing of the internal base time is not atomic, so it needs to be + * externally synchronized with calls to @ref glfwGetTime. + * + * @sa @ref time + * + * @since Added in version 2.2. + * + * @ingroup input + */ +GLFWAPI void glfwSetTime(double time); + +/*! @brief Returns the current value of the raw timer. + * + * This function returns the current value of the raw timer, measured in + * 1 / frequency seconds. To get the frequency, call @ref + * glfwGetTimerFrequency. + * + * @return The value of the timer, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa @ref glfwGetTimerFrequency + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerValue(void); + +/*! @brief Returns the frequency, in Hz, of the raw timer. + * + * This function returns the frequency, in Hz, of the raw timer. + * + * @return The frequency of the timer, in Hz, or zero if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref time + * @sa @ref glfwGetTimerValue + * + * @since Added in version 3.2. + * + * @ingroup input + */ +GLFWAPI uint64_t glfwGetTimerFrequency(void); + +/*! @brief Makes the context of the specified window current for the calling + * thread. + * + * This function makes the OpenGL or OpenGL ES context of the specified window + * current on the calling thread. A context must only be made current on + * a single thread at a time and each thread can have only a single current + * context at a time. + * + * When moving a context between threads, you must make it non-current on the + * old thread before making it current on the new one. + * + * By default, making a context non-current implicitly forces a pipeline flush. + * On machines that support `GL_KHR_context_flush_control`, you can control + * whether a context performs this flush by setting the + * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) + * hint. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * @param[in] window The window whose context to make current, or `NULL` to + * detach the current context. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_current + * @sa @ref glfwGetCurrentContext + * + * @since Added in version 3.0. + * + * @ingroup context + */ +GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window); + +/*! @brief Returns the window whose context is current on the calling thread. + * + * This function returns the window whose OpenGL or OpenGL ES context is + * current on the calling thread. + * + * @return The window whose context is current, or `NULL` if no window's + * context is current. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_current + * @sa @ref glfwMakeContextCurrent + * + * @since Added in version 3.0. + * + * @ingroup context + */ +GLFWAPI GLFWwindow* glfwGetCurrentContext(void); + +/*! @brief Swaps the front and back buffers of the specified window. + * + * This function swaps the front and back buffers of the specified window when + * rendering with OpenGL or OpenGL ES. If the swap interval is greater than + * zero, the GPU driver waits the specified number of screen updates before + * swapping the buffers. + * + * The specified window must have an OpenGL or OpenGL ES context. Specifying + * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT + * error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see `vkQueuePresentKHR` instead. + * + * @param[in] window The window whose buffers to swap. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark __EGL:__ The context of the specified window must be current on the + * calling thread. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref buffer_swap + * @sa @ref glfwSwapInterval + * + * @since Added in version 1.0. + * @glfw3 Added window handle parameter. + * + * @ingroup window + */ +GLFWAPI void glfwSwapBuffers(GLFWwindow* window); + +/*! @brief Sets the swap interval for the current context. + * + * This function sets the swap interval for the current OpenGL or OpenGL ES + * context, i.e. the number of screen updates to wait from the time @ref + * glfwSwapBuffers was called before swapping the buffers and returning. This + * is sometimes called _vertical synchronization_, _vertical retrace + * synchronization_ or just _vsync_. + * + * A context that supports either of the `WGL_EXT_swap_control_tear` and + * `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap + * intervals, which allows the driver to swap immediately even if a frame + * arrives a little bit late. You can check for these extensions with @ref + * glfwExtensionSupported. + * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see the present mode of your swapchain instead. + * + * @param[in] interval The minimum number of screen updates to wait for + * until the buffers are swapped by @ref glfwSwapBuffers. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark This function is not called during context creation, leaving the + * swap interval set to whatever is the default on that platform. This is done + * because some swap interval extensions used by GLFW do not allow the swap + * interval to be reset to zero once it has been set to a non-zero value. + * + * @remark Some GPU drivers do not honor the requested swap interval, either + * because of a user setting that overrides the application's request or due to + * bugs in the driver. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref buffer_swap + * @sa @ref glfwSwapBuffers + * + * @since Added in version 1.0. + * + * @ingroup context + */ +GLFWAPI void glfwSwapInterval(int interval); + +/*! @brief Returns whether the specified extension is available. + * + * This function returns whether the specified + * [API extension](@ref context_glext) is supported by the current OpenGL or + * OpenGL ES context. It searches both for client API extension and context + * creation API extensions. + * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * + * As this functions retrieves and searches one or more extension strings each + * call, it is recommended that you cache its results if it is going to be used + * frequently. The extension strings will not change during the lifetime of + * a context, so there is no danger in doing this. + * + * This function does not apply to Vulkan. If you are using Vulkan, see @ref + * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` + * and `vkEnumerateDeviceExtensionProperties` instead. + * + * @param[in] extension The ASCII encoded name of the extension. + * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_glext + * @sa @ref glfwGetProcAddress + * + * @since Added in version 1.0. + * + * @ingroup context + */ +GLFWAPI int glfwExtensionSupported(const char* extension); + +/*! @brief Returns the address of the specified function for the current + * context. + * + * This function returns the address of the specified OpenGL or OpenGL ES + * [core or extension function](@ref context_glext), if it is supported + * by the current context. + * + * A context must be current on the calling thread. Calling this function + * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. + * + * This function does not apply to Vulkan. If you are rendering with Vulkan, + * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and + * `vkGetDeviceProcAddr` instead. + * + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. + * + * @remark The address of a given function is not guaranteed to be the same + * between contexts. + * + * @remark This function may return a non-`NULL` address despite the + * associated version or extension not being available. Always check the + * context version or extension string first. + * + * @pointer_lifetime The returned function pointer is valid until the context + * is destroyed or the library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref context_glext + * @sa @ref glfwExtensionSupported + * + * @since Added in version 1.0. + * + * @ingroup context + */ +GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); + +/*! @brief Returns whether the Vulkan loader and an ICD have been found. + * + * This function returns whether the Vulkan loader and any minimally functional + * ICD have been found. + * + * The availability of a Vulkan loader and even an ICD does not by itself + * guarantee that surface creation or even instance creation is possible. + * For example, on Fermi systems Nvidia will install an ICD that provides no + * actual Vulkan support. Call @ref glfwGetRequiredInstanceExtensions to check + * whether the extensions necessary for Vulkan surface creation are available + * and @ref glfwGetPhysicalDevicePresentationSupport to check whether a queue + * family of a physical device supports image presentation. + * + * @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE` + * otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_support + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwVulkanSupported(void); + +/*! @brief Returns the Vulkan instance extensions required by GLFW. + * + * This function returns an array of names of Vulkan instance extensions required + * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the + * list will always contain `VK_KHR_surface`, so if you don't require any + * additional extensions you can pass this list directly to the + * `VkInstanceCreateInfo` struct. + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is at least minimally available. + * + * If Vulkan is available but no set of extensions allowing window surface + * creation was found, this function returns `NULL`. You may still use Vulkan + * for off-screen rendering and compute work. + * + * @param[out] count Where to store the number of extensions in the returned + * array. This is set to zero if an error occurred. + * @return An array of ASCII encoded extension names, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @remark Additional extensions may be required by future versions of GLFW. + * You should check if any extensions you wish to enable are already in the + * returned array, as it is an error to specify an extension more than once in + * the `VkInstanceCreateInfo` struct. + * + * @remark @macos This function currently supports either the + * `VK_MVK_macos_surface` extension from MoltenVK or `VK_EXT_metal_surface` + * extension. + * + * @pointer_lifetime The returned array is allocated and freed by GLFW. You + * should not free it yourself. It is guaranteed to be valid only until the + * library is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_ext + * @sa @ref glfwCreateWindowSurface + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); + +#if defined(VK_VERSION_1_0) + +/*! @brief Returns the address of the specified Vulkan instance function. + * + * This function returns the address of the specified Vulkan core or extension + * function for the specified instance. If instance is set to `NULL` it can + * return any function exported from the Vulkan loader, including at least the + * following functions: + * + * - `vkEnumerateInstanceExtensionProperties` + * - `vkEnumerateInstanceLayerProperties` + * - `vkCreateInstance` + * - `vkGetInstanceProcAddr` + * + * If Vulkan is not available on the machine, this function returns `NULL` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is at least minimally available. + * + * This function is equivalent to calling `vkGetInstanceProcAddr` with + * a platform-specific query of the Vulkan loader as a fallback. + * + * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve + * functions related to instance creation. + * @param[in] procname The ASCII encoded name of the function. + * @return The address of the function, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_API_UNAVAILABLE. + * + * @pointer_lifetime The returned function pointer is valid until the library + * is terminated. + * + * @thread_safety This function may be called from any thread. + * + * @sa @ref vulkan_proc + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); + +/*! @brief Returns whether the specified queue family can present images. + * + * This function returns whether the specified queue family of the specified + * physical device supports presentation to the platform GLFW was built for. + * + * If Vulkan or the required window surface creation instance extensions are + * not available on the machine, or if the specified instance was not created + * with the required extensions, this function returns `GLFW_FALSE` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported + * to check whether Vulkan is at least minimally available and @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * @param[in] instance The instance that the physical device belongs to. + * @param[in] device The physical device that the queue family belongs to. + * @param[in] queuefamily The index of the queue family to query. + * @return `GLFW_TRUE` if the queue family supports presentation, or + * `GLFW_FALSE` otherwise. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. + * + * @remark @macos This function currently always returns `GLFW_TRUE`, as the + * `VK_MVK_macos_surface` extension does not provide + * a `vkGetPhysicalDevice*PresentationSupport` type function. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_present + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); + +/*! @brief Creates a Vulkan surface for the specified window. + * + * This function creates a Vulkan surface for the specified window. + * + * If the Vulkan loader or at least one minimally functional ICD were not found, + * this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref + * GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported to check whether + * Vulkan is at least minimally available. + * + * If the required window surface creation instance extensions are not + * available or if the specified instance was not created with these extensions + * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and + * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref + * glfwGetRequiredInstanceExtensions to check what instance extensions are + * required. + * + * The window surface cannot be shared with another API so the window must + * have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib) + * set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error + * and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`. + * + * The window surface must be destroyed before the specified Vulkan instance. + * It is the responsibility of the caller to destroy the window surface. GLFW + * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the + * surface. + * + * @param[in] instance The Vulkan instance to create the surface in. + * @param[in] window The window to create the surface for. + * @param[in] allocator The allocator to use, or `NULL` to use the default + * allocator. + * @param[out] surface Where to store the handle of the surface. This is set + * to `VK_NULL_HANDLE` if an error occurred. + * @return `VK_SUCCESS` if successful, or a Vulkan error code if an + * [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref + * GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE + * + * @remark If an error occurs before the creation call is made, GLFW returns + * the Vulkan error code most appropriate for the error. Appropriate use of + * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should + * eliminate almost all occurrences of these errors. + * + * @remark @macos This function currently only supports the + * `VK_MVK_macos_surface` extension from MoltenVK. + * + * @remark @macos This function creates and sets a `CAMetalLayer` instance for + * the window content view, which is required for MoltenVK to function. + * + * @thread_safety This function may be called from any thread. For + * synchronization details of Vulkan objects, see the Vulkan specification. + * + * @sa @ref vulkan_surface + * @sa @ref glfwGetRequiredInstanceExtensions + * + * @since Added in version 3.2. + * + * @ingroup vulkan + */ +GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); + +#endif /*VK_VERSION_1_0*/ + + +/************************************************************************* + * Global definition cleanup + *************************************************************************/ + +/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ + +#ifdef GLFW_WINGDIAPI_DEFINED + #undef WINGDIAPI + #undef GLFW_WINGDIAPI_DEFINED +#endif + +#ifdef GLFW_CALLBACK_DEFINED + #undef CALLBACK + #undef GLFW_CALLBACK_DEFINED +#endif + +/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally + * defined by some gl.h variants (OpenBSD) so define it after if needed. + */ +#ifndef GLAPIENTRY + #define GLAPIENTRY APIENTRY +#endif + +/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ + + +#ifdef __cplusplus +} +#endif + +#endif /* _glfw3_h_ */ + diff --git a/vendor/glfw/include/GLFW/glfw3native.h b/vendor/glfw/include/GLFW/glfw3native.h new file mode 100644 index 0000000..267e75c --- /dev/null +++ b/vendor/glfw/include/GLFW/glfw3native.h @@ -0,0 +1,525 @@ +/************************************************************************* + * GLFW 3.3 - www.glfw.org + * A library for OpenGL, window and input + *------------------------------------------------------------------------ + * Copyright (c) 2002-2006 Marcus Geelnard + * Copyright (c) 2006-2018 Camilla Löwy + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would + * be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + * + *************************************************************************/ + +#ifndef _glfw3_native_h_ +#define _glfw3_native_h_ + +#ifdef __cplusplus +extern "C" { +#endif + + +/************************************************************************* + * Doxygen documentation + *************************************************************************/ + +/*! @file glfw3native.h + * @brief The header of the native access functions. + * + * This is the header file of the native access functions. See @ref native for + * more information. + */ +/*! @defgroup native Native access + * @brief Functions related to accessing native handles. + * + * **By using the native access functions you assert that you know what you're + * doing and how to fix problems caused by using them. If you don't, you + * shouldn't be using them.** + * + * Before the inclusion of @ref glfw3native.h, you may define zero or more + * window system API macro and zero or more context creation API macros. + * + * The chosen backends must match those the library was compiled for. Failure + * to do this will cause a link-time error. + * + * The available window API macros are: + * * `GLFW_EXPOSE_NATIVE_WIN32` + * * `GLFW_EXPOSE_NATIVE_COCOA` + * * `GLFW_EXPOSE_NATIVE_X11` + * * `GLFW_EXPOSE_NATIVE_WAYLAND` + * + * The available context API macros are: + * * `GLFW_EXPOSE_NATIVE_WGL` + * * `GLFW_EXPOSE_NATIVE_NSGL` + * * `GLFW_EXPOSE_NATIVE_GLX` + * * `GLFW_EXPOSE_NATIVE_EGL` + * * `GLFW_EXPOSE_NATIVE_OSMESA` + * + * These macros select which of the native access functions that are declared + * and which platform-specific headers to include. It is then up your (by + * definition platform-specific) code to handle which of these should be + * defined. + */ + + +/************************************************************************* + * System headers and types + *************************************************************************/ + +#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL) + // This is a workaround for the fact that glfw3.h needs to export APIENTRY (for + // example to allow applications to correctly declare a GL_ARB_debug_output + // callback) but windows.h assumes no one will define APIENTRY before it does + #if defined(GLFW_APIENTRY_DEFINED) + #undef APIENTRY + #undef GLFW_APIENTRY_DEFINED + #endif + #include +#elif defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL) + #if defined(__OBJC__) + #import + #else + #include + typedef void* id; + #endif +#elif defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) + #include + #include +#elif defined(GLFW_EXPOSE_NATIVE_WAYLAND) + #include +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WGL) + /* WGL is declared by windows.h */ +#endif +#if defined(GLFW_EXPOSE_NATIVE_NSGL) + /* NSGL is declared by Cocoa.h */ +#endif +#if defined(GLFW_EXPOSE_NATIVE_GLX) + #include +#endif +#if defined(GLFW_EXPOSE_NATIVE_EGL) + #include +#endif +#if defined(GLFW_EXPOSE_NATIVE_OSMESA) + #include +#endif + + +/************************************************************************* + * Functions + *************************************************************************/ + +#if defined(GLFW_EXPOSE_NATIVE_WIN32) +/*! @brief Returns the adapter device name of the specified monitor. + * + * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) + * of the specified monitor, or `NULL` if an [error](@ref error_handling) + * occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetWin32Adapter(GLFWmonitor* monitor); + +/*! @brief Returns the display device name of the specified monitor. + * + * @return The UTF-8 encoded display device name (for example + * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetWin32Monitor(GLFWmonitor* monitor); + +/*! @brief Returns the `HWND` of the specified window. + * + * @return The `HWND` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI HWND glfwGetWin32Window(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WGL) +/*! @brief Returns the `HGLRC` of the specified window. + * + * @return The `HGLRC` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_COCOA) +/*! @brief Returns the `CGDirectDisplayID` of the specified monitor. + * + * @return The `CGDirectDisplayID` of the specified monitor, or + * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the `NSWindow` of the specified window. + * + * @return The `NSWindow` of the specified window, or `nil` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI id glfwGetCocoaWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_NSGL) +/*! @brief Returns the `NSOpenGLContext` of the specified window. + * + * @return The `NSOpenGLContext` of the specified window, or `nil` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI id glfwGetNSGLContext(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_X11) +/*! @brief Returns the `Display` used by GLFW. + * + * @return The `Display` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI Display* glfwGetX11Display(void); + +/*! @brief Returns the `RRCrtc` of the specified monitor. + * + * @return The `RRCrtc` of the specified monitor, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI RRCrtc glfwGetX11Adapter(GLFWmonitor* monitor); + +/*! @brief Returns the `RROutput` of the specified monitor. + * + * @return The `RROutput` of the specified monitor, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.1. + * + * @ingroup native + */ +GLFWAPI RROutput glfwGetX11Monitor(GLFWmonitor* monitor); + +/*! @brief Returns the `Window` of the specified window. + * + * @return The `Window` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI Window glfwGetX11Window(GLFWwindow* window); + +/*! @brief Sets the current primary selection to the specified string. + * + * @param[in] string A UTF-8 encoded string. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The specified string is copied before this function + * returns. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa glfwGetX11SelectionString + * @sa glfwSetClipboardString + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI void glfwSetX11SelectionString(const char* string); + +/*! @brief Returns the contents of the current primary selection as a string. + * + * If the selection is empty or if its contents cannot be converted, `NULL` + * is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated. + * + * @return The contents of the selection as a UTF-8 encoded string, or `NULL` + * if an [error](@ref error_handling) occurred. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @pointer_lifetime The returned string is allocated and freed by GLFW. You + * should not free it yourself. It is valid until the next call to @ref + * glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the + * library is terminated. + * + * @thread_safety This function must only be called from the main thread. + * + * @sa @ref clipboard + * @sa glfwSetX11SelectionString + * @sa glfwGetClipboardString + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI const char* glfwGetX11SelectionString(void); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_GLX) +/*! @brief Returns the `GLXContext` of the specified window. + * + * @return The `GLXContext` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI GLXContext glfwGetGLXContext(GLFWwindow* window); + +/*! @brief Returns the `GLXWindow` of the specified window. + * + * @return The `GLXWindow` of the specified window, or `None` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI GLXWindow glfwGetGLXWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) +/*! @brief Returns the `struct wl_display*` used by GLFW. + * + * @return The `struct wl_display*` used by GLFW, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_display* glfwGetWaylandDisplay(void); + +/*! @brief Returns the `struct wl_output*` of the specified monitor. + * + * @return The `struct wl_output*` of the specified monitor, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_output* glfwGetWaylandMonitor(GLFWmonitor* monitor); + +/*! @brief Returns the main `struct wl_surface*` of the specified window. + * + * @return The main `struct wl_surface*` of the specified window, or `NULL` if + * an [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.2. + * + * @ingroup native + */ +GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_EGL) +/*! @brief Returns the `EGLDisplay` used by GLFW. + * + * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI EGLDisplay glfwGetEGLDisplay(void); + +/*! @brief Returns the `EGLContext` of the specified window. + * + * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI EGLContext glfwGetEGLContext(GLFWwindow* window); + +/*! @brief Returns the `EGLSurface` of the specified window. + * + * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.0. + * + * @ingroup native + */ +GLFWAPI EGLSurface glfwGetEGLSurface(GLFWwindow* window); +#endif + +#if defined(GLFW_EXPOSE_NATIVE_OSMESA) +/*! @brief Retrieves the color buffer associated with the specified window. + * + * @param[in] window The window whose color buffer to retrieve. + * @param[out] width Where to store the width of the color buffer, or `NULL`. + * @param[out] height Where to store the height of the color buffer, or `NULL`. + * @param[out] format Where to store the OSMesa pixel format of the color + * buffer, or `NULL`. + * @param[out] buffer Where to store the address of the color buffer, or + * `NULL`. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* window, int* width, int* height, int* format, void** buffer); + +/*! @brief Retrieves the depth buffer associated with the specified window. + * + * @param[in] window The window whose depth buffer to retrieve. + * @param[out] width Where to store the width of the depth buffer, or `NULL`. + * @param[out] height Where to store the height of the depth buffer, or `NULL`. + * @param[out] bytesPerValue Where to store the number of bytes per depth + * buffer element, or `NULL`. + * @param[out] buffer Where to store the address of the depth buffer, or + * `NULL`. + * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* window, int* width, int* height, int* bytesPerValue, void** buffer); + +/*! @brief Returns the `OSMesaContext` of the specified window. + * + * @return The `OSMesaContext` of the specified window, or `NULL` if an + * [error](@ref error_handling) occurred. + * + * @thread_safety This function may be called from any thread. Access is not + * synchronized. + * + * @since Added in version 3.3. + * + * @ingroup native + */ +GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* window); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _glfw3_native_h_ */ + diff --git a/vendor/glfw/lib-mingw-w64/glfw3.dll b/vendor/glfw/lib-mingw-w64/glfw3.dll new file mode 100644 index 0000000000000000000000000000000000000000..9eabeb5ca9ca4c49585e5646d268925798dc42d0 GIT binary patch literal 249344 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 Yg|MqsT|P&79j%M{qK#1$_yzy{FC~Vdpa1{> literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-mingw-w64/libglfw3.a b/vendor/glfw/lib-mingw-w64/libglfw3.a new file mode 100644 index 0000000000000000000000000000000000000000..574afb25416fc36a24b118c5dddd561c6a2fbc0b GIT binary patch literal 305548 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 F{6Auf@ihPd literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2012/glfw3.dll b/vendor/glfw/lib-vc2012/glfw3.dll new file mode 100644 index 0000000000000000000000000000000000000000..2a34496dcf1a969bee4e568d95c82156eed7f209 GIT binary patch literal 221696 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 literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2012/glfw3.lib b/vendor/glfw/lib-vc2012/glfw3.lib new file mode 100644 index 0000000000000000000000000000000000000000..c296927159bfb33d3e6665f2da1452b15b51efd6 GIT binary patch literal 642782 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 z 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

btus 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 OQpwjt^(!imbN(-+Gsu|$ literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2012/glfw3dll.lib b/vendor/glfw/lib-vc2012/glfw3dll.lib new file mode 100644 index 0000000000000000000000000000000000000000..c26e9c7250c55260d85a19c3c1b82d5f289bf96d GIT binary patch literal 30306 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 literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2013/glfw3.lib b/vendor/glfw/lib-vc2013/glfw3.lib new file mode 100644 index 0000000000000000000000000000000000000000..7d9658fe49f8c97d75c976d002ce16d2665ce193 GIT binary patch literal 642892 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/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�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 literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2013/glfw3dll.lib b/vendor/glfw/lib-vc2013/glfw3dll.lib new file mode 100644 index 0000000000000000000000000000000000000000..738ac36b3ba9bf11cae929df6666de1702585c2d GIT binary patch literal 30306 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


Eqh4>KYzH5=koGg)(xB~K#Bf~z6@NNnx9d!Wu z5{(~)r9izD4jw!Gs3W+a(lhTx9Jk;8OwWoeu>!gQZB$gs%f}%vv$Di2yq_tBmy4k) zAwC6Kavh#Wa)@_9{_VG+4WKZj@AM-NxYuzX;@JJ39JEV?vqVn*%+!qG?C7+{slG** zXNk+t;F(X)5F?v~SYCa{|=0SnG;`Z;65@Q!V9WZfx5{ip$-=46RE3Dgs` zC!=Vr=OEsrIvs>N!=MlBaU_q>hd{5l4zy&6DktidJJP~GI3+zCUIloQgNf_da+>i z%GA7(D~5AW5Q=|-o@kfmx`3kP*lS<+B)Z7T%bJyj6%yFYDwSR6TABZxbW$z}}~K zqD^0<rakT*xV z@Z0mV@ZMSC-ZMWIkyAesO@%2j+w(nw>ugUvd;r*}> z_kb!F^EXy2BLE1tetT=w{@L{?qC7LMyI5pV;edDCZ7tCw|~UA z;$g_tjp`lO6-fUggdL!;DFth>oI8w)ATyq3_CHqugjmBtt zTw@Qnk9Tb0a!i*m+YYa6o6z2*{sny%&>-pTc~iwaw3V|@p)GoRx(xp-uAPwjoa5R3 z_Ip`RPGdcZzEbwb`8ia7p-P0*JKxNZ^_l#O=4FX_Xa}aCy^elHh|htRqfbLTxBKn- zs)W+H4(;@VGo*Y<|3ZwXkj9MIRGBtJ8gbC(d*+I1sVO7+`HPm%6wA-d5{n+c9DTLf z&@nma4?%ZBKM(f{@l()4^7#-*#1n`oaNT(geKWc?CLGEL;m)|i;ioz|7y2D}ie@#E z7Gv4%M1B{c3=7X7KabB5$xlFcehR!mpO|=I_sj7F^txwpmRO8F^3<9PFSnEPgl;Fh zC_U0`i3Oq?!-SGS^tCCiRWrn@GgpY4PR$hy9$zSO0#~8@SIX-V#Cb?PkK)_?_B7=4 zoACUrXNar8!>a?Ai>vEqiL0TjuYT~#)WT&m#6r&vV%F$osp%urhIL8l9i))2h1a0& zwoVb#ew^vk`7NRRHf4*Z#O30;Gc(29Q?sC#=Zfg(h4?TicNy`4-pNcfGT=SpIj=!p zY;mQ$V0=u^Bw3JsPvTQ~mMBkLCdbZnO|~iVsW{s{8}gGQW_)~Vqm~slzTrB8erfkt zQLjNy%eA6Kv{nYLGum{gKvW0PGJ>>J%7_V%A9ANPDGraPjV>om(^U2|tI&qpX zekVi+i01)>!@sa`s%Q*cChF1e#Jq_tt9&GH-ZixF>9xi1mAM$rcrnm$B;Vjf& zQ~qQdw+L8GCWn?rf0xgs^L(eYa@^N9OE-_`NwWkWB6FsC#Rap&ddM5kXp z6?Gi-J%&DKbZ(=*_ZPVD{WCq{kGPjmKC33f=Ry6NPI`jcrx>>b(`hbbu@L&+Ept5L zJD?Q{7-bou6FoFW#Jidmo9bitbTKO*?)g(t*3UwoPl%}$?~1A7ibOX08R$RfU*_Y| z$|9TV2akFAoZnj!OmqVC!;h}a6vL}AkGle67!ZwzN_Ik5-w9oti+cWgxEDaD+$BWg zO0>aOqrL-&&QaQ=Q$Pm7aGmBvXdc5?ErgMW%exQ{NOM&*4@7fMG}kl&GS zg7{)9(gsCANze$$*oJ#?-I$8fU@gH1iXzQMgf}7|IrYdJu6r>@)ClTEK88U_Tu;%x zzs2)E3OC4j64#K&?nWRe$B(>#q9Dq95;y`PgC8SEL*U)e+>?RIF^p#!2={@apl*b9 z1BXDvaEoSzQd5tafa;ZA{QE+?lM z&jA?$!~rEiDG-jei4ss3D5nM2K;57bP|j}f0n`Xef_zZEQBXIi@fw7I8j%;8?}~zN zDTL#IoM;3^+u#R11^M^^=)XbJ@-oE@pdwHu=nl{uL2m^e1bqzj1<=2PeggUBSBq=Jwc`bc8Hx&F!eYEbq7ur+$ml!?h*~6QTS1Xn?(SXr3EKJTOs6c z5PL)$&WDC^7Bni}C}KDznh+ggFHVMb!m`iZ;!WZn@n-QBaj)nSyW3j!@u^#KsTFo< zTt;5v0GytcW@oS;9ad*-7kGQim;k-sg_0}}w)nC8nqyYVJt!P3H%r-4RIB&4B+dQe z>IeunKhdq5BF!CfTQpk6*C$ZaMj47m!MxF4?Ie&lb0|vTi^O#RZ~Kt@`qhmH(VL2_ z5PPYR4DT{hmp54($!oFmQKwAi)nKJ*8^9F=mf}FNx?7&>s=@Yj9UxCkZ>0l3Du%XF zW8Z(EE@{L3rJdLr;|kj-?M00V-n^r#+#R*jkKIA8+wJ+*kJ*7E>^|B{6l6gFC$pS7J-vloXobyp8m9{$hEZ<2uLC4X}LaIyl1XPedB4p>SzGS^e6_O^0>dLN2Y!5ah z;>y(4AzHO{cn(H-o#p&RVsT z&L`T1(+n^ljs4QDN{9MdkY5_`M{RN=!(1hmVb03UKD7-{m50O92@zkB_0cXZ96a`6 z*ao_ttxV`Lb4;6h;DE7-x#g@9eBrnJt17Ovg(Fmn ziVTzcn0RBN(rhXiRyUw@Y)|q<+S)3};1a(P6edy89!>0*Ve%$eG?UW4RoXLiDp(RN z>~`ezz;~oW8;6PYH3-M1UE8B-p=PlUz6{&+q{TRjrNSU1@iF0PG&M!HS{Bn+K{{s4 z{W79{J7!!2xMP;XqK-RE>TGwQOLx03OXVyJkEb~`H3FQP8Ugxsx|7l2ZmGd7(30-h zN>IlMPLqaBb-8buKCSSS!ZQl9i6{77t1w?-xx#x?JQ)dpGQey4U9IpY zg@ppPp6)sj-sBoh~pTZ`EZ&CQ5!hVG(6h5wS zMBxt=jw%$D{M;OcHz_Pqn6L6TT*2`gRd`I{eF{IQFsX1*;pY{OC_JU`_X>rQ+shR$ zQCO_-HiaKk&rd4sR@kL5tnf~Sn-mr*yk23J!e5tjc}5gIuJBQXOH{e1Dm<<3+o8j`<1_1;YQc>ewY8V%HIWDNx#=9j452KP$>MFihqalKdt;vxYAv&{B^GI zu<~~*98&l;h1V<8WlFmItsab(&Orud-H*$fCu~daY$WRYQx;_^%Mi$|-!%3!yKOpn&8 z(}BN-%{c0IyMo25GpmEJr#UA4n?e~taNY2&th%;%DH&oF;@jj#L3yP49rA%!?0cGg z#BA}e8Jnez629pP<*SAv5+S~(d^^Hqm_&%jlwaN`l37TuPM))@=!7|Y8m;jB%9e_n zZ57qp-a}SqUCbYjx1p1xUV#w*ENG&K402j;Wo?Ep7~Es|cV^T`qdvhH58t<8%mmBf z^61|#F*|byj=Zutm$BDr3lvYHaW|);bC>7?&*bbE2Z^6&p!1{qZQ{=vb&(z6P&3W` z%*;SHY-cEzfJror5+EICGHRuTX`i;Q9w*yyyTltkU@!)Cay-J>pbL=A_}D9CMgseY za7THW2%&Vamk|%by;QJ8K{fdWw$jI9;*@FeOGrjXyXy+Ve~~U+-tklW70y$9m+;eb z)%b?<{xf?#btNwTnt`{~yhjdfc-(rIyc2UEFmot}FQO}>76*Qx2ku2L&jDZC{iBrb-GjK2=iFtpXfQt-{xD)VUn7k&Z!gT6K}SNEC~yxPC_j_EWLC@~R9vgJjN|lD#51qSM23A?~NAni0z7 z*^UL2KUdhdg`8S2Lva#??v!IZ=vTU<6eo|(Lf=XuG%+Y=K<|@J!L$%e31bhJmc=q1 zVq|QM@1~as)hYEJOn7XU2AJbGHG!14I&3Ag+|A(Nhxpm3kTEhKt{A-y=>}lZNqNO5 zC>CUZ*4Nr8741emG9bm?Z&578L7eMB+$$+AN{Sf~GJh$O+7BaCaCCg|| zT!;rOKXxlpiq^GCyoXR!O^0AbfFD*D!5|(6p@n#32D|Dadu7NayzS>;n9bGUq{2o&H;#1QLu9%}12N4vyft-DCj#2@6f zDzfp5n7fsxqf1q22xG(|v~j9RQwG%wh|+URZAGGW7dX#4)C`v9pyFajZAFdN;Q8ta z6XPgKhTwI#kv>9K}^cN*&Jugu?JcCiEA~x!`O1b zEgVZ7Y~SfTRBhCaCRT;YS|gYc!8vtpiAMaKI3>*|*+Uh472UN)*M}gmbxMtMqE=D}{lFXo7Bui`vSHYTf*8#BP@u{-gIL zVE#NF#Jkx*uIA`|oD?7zi9XiA8XC$PlsSv$2DTW6yOtt6o(MFMZS95-+Lnd@w_*)! ztYK$a&5mt#Ra-0a3fX9@cz~W5ZpN}k4&NJ!;FvF-5^mTVk7Hc`E4fz*bUtJ+VS#9& zZU9!^Rh zNA@+q48dOPJLNn1lPUUAFuXSui-gJkJ8GvRMkE~U3?&+*wJYL&gYGyqs4FcUVYbq+ zSTqD>UnZz8@lDqwFEJd7#%dKNldptNIt0wxu56F5+!qS3#PyY60JQ(gw!D>jE7jW= z6C)6c*dw^Ew+8)D`(^hNz!8{#N!X*fQb0cphIsc+5CeVTR{Lf5Gh*n=Vlv4dWkD8f zTR|I1_3s0y(Df{G=3 zW!#ZPAbK~@YTUk2cc(N?m0EUuerM~!*HUk;5;jIe2A*3Eb5`^*Nc}uL!nuSm1P2Ut@pHHyDQ%c8##V``=agHyInhrNWN||$8Aju~3cttb`wzy( z?=yD&fU*0BjKlxQIGSQi{fKeo$Ljh|7?Yh>Savj zF^U34qmVIY4P!|WV{|QJvY2sr9b@-;M&GL$yEZTm-NG1s4P)c2jJ^^TUdq_Lk#VSu zaipAaw1Uyt%;>9REU9Abx{Yyo3!~V|Xl!FF+0NMLW9+(}F$* z*ww~3)Xta+Gv-7UzL8PH7)KQj#o0fUP~jbn-hGTEoeK9eM(<`!zKL<<9!BvN#+-W@ zjV?ytTN%6F##r)p#!-dI``AD74o2}VM&kfu$-5b&?_o^-9plLTjN$=C?|T`2-HcuD zV@y8C*!X@%;~~b94=_eQsPG>cyALuBeTXsjVMgO&M&CymyFSX8{3piYB;)8I##9eu zPA_B05yogAWA{OWZjjt;IQ|kKH7?WRT9R3F5=m?|nO-A3h7`vWkOn#ejsZ2&Oh0&O*a2lg8TV0>d=$*mXc$vCBlQBArF?l)T z$ZSS2hq2@e<)5qk^BAM^8IxBs4qwGMxv%IG4&e8kz19&gmJW#F{g~tTh17*VC>$+IJ}uL zRmqrh8>85wt}7g^X1}qG(YKwk%f~o$J7cPbakN&2*D3!FM(-}h#(Ku&YZ-^{U`)M^ zQM{fp=PpL0fw82KG3saZHZl5|Rd|3g8Dt!8VNC62#H6Y0_Ze?s^zC8nYGWK~XH10| zbE1qTZ)A+d7?W|vkp!dI%jn(5*x0FXKV#0_j3sYkjNZf8{bt7Dw=kyeWfX5^G~TAd z6?VOy{oeZ+8{fg${Z7W@yBJ3fFk1tj3xIoM*p5M`2gd{dl|+17`+cNM&Hjk z^blj$2N-=HWHkPPaa5u4A>~(S{3H8I9%gL(2xIq08HfLgQ5<6Q_Ao{dD}S%LeuUBJ zV=Ot!IIM7_pZ%l97;^?xyg|n3BaF$9F^>E*qxcs_@5dP%Kf##%B;)Y^V;uby0PEiN-XV?Bk~7pR9P9=gxJ>NQf|`!n5GEhYzdpY*+Y*3ZLl;PpR-6SNNz3 zpXUk}XE{F$#tFaH6`rHw8wk&#{Hvc1UouYk@^Qj*UEwM@dG>6kEqxuH2S>Va92rR) zUNBC0;W*)R#3Wt%I5v_teC;^lbj%}NIymZ)Hk^)sq>KORal&yVByD^g2}v7{V%_}n{W?X@@epkVs4Up_qk=-A=y(+tnE3$RTSaabtwHKp%0gm^EA+#^73&x`Pfp!;zz;Tcdb+;)3ec3WCxV=MPYyaS|9 z*bSURML8Dd(H=ThT1ktnX_P)qA*mY>&{(}4v=7DlhUc#-QC2-sAdyy@$ z&w(}|oG=CQ!A*EZxe4ivWdPxJn_Fa`s~vO-;e>AjorRn5gP@tno82ZD*$?5E-gcA;chT$fB0`xT8bl!8$8s-C?`+UE0)A`TeD>t13 z-3}sN(V5Q^%1!4xSEErb2S4eY=W9U}ht7MxTe<0+rnVzS_#4m?#37`E?Zt2tUIVIz zo6dCJ2cmT7EazvGo6d6nLAk{`tYv{H4xQ=zgmTl_&d;pJx;)+;o$>qwh~m&$&jJv+ z^%+mnKXle}E*fzPZv?(yxs$+eDR&Au7Y#baq4S^Gwin?KKzE|-gy%p}xakb1wsl6R z?U@nYQHru59l{4e55rA302+kbZZqpIWtJ^2vdQ(iP2d;oT@ii_bS>P3KL@qKP53KN zF5HBF2KnG7ybKLD#mNDNKvegmz^{>;^c7Isnj-uaD2X_P=Rham&Ou{706Gb`-Hw&r z?iJa?x_Jxa0dWY|gX-ZX+y-ieo6rxs2ksGIX*KE$+;lGa8=wVn(|P0NAmTZlH~xxp z8{5D`kbGajgUU^3ihl^|L>cL9@ftMr^nUF&zU=nD?DoP^h}+%9&{c`E@%lsgIhigME#?aXG5V+7EqgQN@q z->=+B;J1`pU|qfdB+~@OmAkt|h%bRCd<2-eTcrbhzjD)=>}Np4H#&En-Oh0g;9o$w z;IrLM7}*f}Bq$5vgkJ_NfO`b^WCZVq+`vQ>bph@!;O%cj{|4?TaD7bW6ZmQ69tM6Q z0X`$nFtBPb+DEv3z^nK3yEcG>AS%lcP}>9}JoP5LU&JT;(mjv|xb1el$iCO>--7l9 z{U5>+kQZ*kKi!MG!7aL=&q2Sw39w=Pzr9s zuY*S6Cj1UaAWg#Gfhhe^;OzUM8xbc5xCcc2z$hVz?1kBFe%bATk)5#r0nNm{gtHz% zx!@+85AwoIxC&GPw-@-|p!@J#YyuGj-PE^3`oLZ9L!SxZjlii7f^Tr=03QS8AkGL- z+pQve_#u=LaR`3`5{NSjJo!QB2Z|5;;fIhP#7O~f{4n0jGUNfMZE+D^^N#|y1~Mf+ z26qB(yB#Qpji`q$n^Sh%Qe9cYyK?)02@uIr7x0V9Jp!C|h{JP$`O4h|{Iqfp z1EW366T*)iX8BA4-_#3T2RTmyZ#lyCs|2_gB%cNRH;~jDz>Ge26BdJ7Q7*#0pnKpZ z{50qxxQBtOkMgs;!1sc>mf~5!--AeRd;9T4J`knf1^g_C!tFMi$mY}h;}{3wUc#F} zBXASm3i>tNgms`Sl!b5~XaU?^z~6wVETh2n1K=;>+wCRUZ7GpWrRyKTvv4orO`xaX zCj27k`*7RseUWXjBOouzOL*NsLnh%S+@Rcqn?dym_W?f%qWla4uN`8y0StnO4^iMb z5a}QBFG4&3iXzWR;P*gn2u}gEJupIT?~5?w6UZ~3Mfe`jX}Af=M%7uk?Y64OhShza zMxK!-;YUGt!kq-Z<^*I8?h;`5GiZa62fNKLvIX{?&q59mPWTIu5AIRm{(nVXgS!j( zMG(EyQDEkyT*e&Wtsp9639uPNJQ)J^ehzVv&mrKylbh-bF!*_nW49wkwx?>ofc&Gr z6W$LBz)g6=Fyswx16ceR>Koi8z#sh^m2sh!|e}nSFO_&6=!ApRC=0^H zA0ey%i+sRc0(?72@*Jq`J`ryFE94Dv2tNSIMn03kdH<*K0Bln3#&eJjkd#T_SrDa3 zv+cPca(jWD%1smOH+wuXz8846a(4rt%=Cy2#1mlO6r3w0IS2j^h|(uJLT5mAaFacu zN)V+_c7>K?bGR1>L#wh~BfC_KKon;Q@XeqA?(GKt3n&WrCxKb8FGX<(SHlKW0^wfZ z$3guR2Y3wjpiaR(2!w$v?pFhEAvff_1egF(J_#!>_lS8bV8;dc8PK(GKMMRKx$&&C zz}(sFCM;F%a$uWs6TVfs?*sl6ME&{Gzy&#cFJZ276Lx?o51qhL*rW2{x#hqgfR@9Z z0%l#oaR^r{w-}72!_-ubj_(SO9EN z?lxdPY-x2O&M=T{cpZS7knD3MkxxRhw?%G3vY#~*aR|#mm2hABy?7ib!lO2WZUbHR z;yw1#lU|k_fSy6VKwZx4k&P+z<}{FY_=gYjjzzGl{p4fI{b_NKP|1`-IzZ&`+K z$E}Yyw+8XW_Lc1+ScHg2S`zdMTp%M2VJ47FfKzcK;CPeW3Mu^|z|XJ_fG zmP&2$v!qtASl)*_<2a6olY#q{A0g5P4L$`JfTf$g*w4H>7&kB4FPkU%s)Kv+S?o6Y zd&@FEj=SxR>BKJdQN61bCL^^Msj)5 zn=DS2BrB7?WPP$R*_w1Ig~>!DKSopBze_NDe1YCP$LbBvZ-L$!IkO&O=>?4jk$}bnsB}Q2(K!LnjUmA3Awx z~|pWArTV@%9w=l=M{g_bZC)IPhXSC;Rk2sutIOp(!!^Yv|hrNf34^tU^hwBeF9&SAx zJ=}S?>+pfY-G>hzP9E+*JaqWP;bCxK>W?%YX+07>(up^5;7Iq8gGZ7_`i~49IdNq8$jKukN1i#7 zI&%8R=#jHWL|=AaPTzt)qi=bix39Rbq_48i*H_=y*w@+@?d$C8>O0Wa-FL7r+1KAU z)OVt9xbI}&NZ&JkslL;FqkU)l#L?`dIY$>9HI6Pn>OER~wB%^zQQy(}qm4&fk4BGn z9_>1M;Ar>JgGZA``;QJCJ#lpS=*goaN1r*GI(qu(=+U!BMSpgGPXB^_qknn7x4*c* zq`$J?*I(b?*x%Y8?eFaG>Oaum-G8t@+27wk)PJIXxc_ATNdGhass7Xbqy1<5#j)&T zImZ?pGmb4k<~>$?tmIhbG2gNJV~xjJk42Al9_u=G;8^#ugU6D``i~7AJ8^9I*vVrf z$DTQsI(GWl=&`fM#PRIoImZ_qH;ykq?mb?7yyST0ao_R!@{!adXCFardP#r(KR_rvp8x;= literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2015/glfw3.lib b/vendor/glfw/lib-vc2015/glfw3.lib new file mode 100644 index 0000000000000000000000000000000000000000..731337d748a60a41333726c16e677a72f677c6a3 GIT binary patch literal 639666 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

^epK!#P--=gyP;BPgA}3F_?bncZ`8?z(PN$V6 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�$R^o35?=RWV#At9MM1>u%B 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

i^LsC6z0mg4-UxpBcusK~y28HD(s> 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 z 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 literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2019/glfw3.lib b/vendor/glfw/lib-vc2019/glfw3.lib new file mode 100644 index 0000000000000000000000000000000000000000..b3444dff3eb8b0aa1bc0515b112071cd73419f24 GIT binary patch literal 648436 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%0AegZ^LGdM*WmAV@~vQ%y;{tLxj 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 literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2019/glfw3dll.lib b/vendor/glfw/lib-vc2019/glfw3dll.lib new file mode 100644 index 0000000000000000000000000000000000000000..e0ac6f80eaeccf6d242a9268bac5b7006e2e359c GIT binary patch literal 30306 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 4.20.8 specification, section 8.3 Common Functions +/// +/// @defgroup core_func_common Common functions +/// @ingroup core +/// +/// Provides GLSL common functions +/// +/// These all operate component-wise. The description is per component. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/qualifier.hpp" +#include "detail/_fixes.hpp" + +namespace glm +{ + /// @addtogroup core_func_common + /// @{ + + /// Returns x if x >= 0; otherwise, it returns -x. + /// + /// @tparam genType floating-point or signed integer; scalar or vector types. + /// + /// @see GLSL abs man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType abs(genType x); + + /// Returns x if x >= 0; otherwise, it returns -x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL abs man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec abs(vec const& x); + + /// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL sign man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec sign(vec const& x); + + /// Returns a value equal to the nearest integer that is less then or equal to x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL floor man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec floor(vec const& x); + + /// Returns a value equal to the nearest integer to x + /// whose absolute value is not larger than the absolute value of x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL trunc man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec trunc(vec const& x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// This includes the possibility that round(x) returns the + /// same value as roundEven(x) for all values of x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL round man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec round(vec const& x); + + /// Returns a value equal to the nearest integer to x. + /// A fractional part of 0.5 will round toward the nearest even + /// integer. (Both 3.5 and 4.5 for x will return 4.0.) + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL roundEven man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + /// @see New round to even technique + template + GLM_FUNC_DECL vec roundEven(vec const& x); + + /// Returns a value equal to the nearest integer + /// that is greater than or equal to x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL ceil man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec ceil(vec const& x); + + /// Return x - floor(x). + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL fract man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType fract(genType x); + + /// Return x - floor(x). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL fract man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec fract(vec const& x); + + template + GLM_FUNC_DECL genType mod(genType x, genType y); + + template + GLM_FUNC_DECL vec mod(vec const& x, T y); + + /// Modulus. Returns x - y * floor(x / y) + /// for each component in x using the floating point value y. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types, include glm/gtc/integer for integer scalar types support + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL mod man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec mod(vec const& x, vec const& y); + + /// Returns the fractional part of x and sets i to the integer + /// part (as a whole number floating point value). Both the + /// return value and the output parameter will have the same + /// sign as x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL modf man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType modf(genType x, genType& i); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL min man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType min(genType x, genType y); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL min man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& x, T y); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL min man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& x, vec const& y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL max man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType max(genType x, genType y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL max man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max(vec const& x, T y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL max man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max(vec const& x, vec const& y); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see GLSL clamp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL clamp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec clamp(vec const& x, T minVal, T maxVal); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL clamp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec clamp(vec const& x, vec const& minVal, vec const& maxVal); + + /// If genTypeU is a floating scalar or vector: + /// Returns x * (1.0 - a) + y * a, i.e., the linear blend of + /// x and y using the floating-point value a. + /// The value for a is not restricted to the range [0, 1]. + /// + /// If genTypeU is a boolean scalar or vector: + /// Selects which vector each returned component comes + /// from. For a component of 'a' that is false, the + /// corresponding component of 'x' is returned. For a + /// component of 'a' that is true, the corresponding + /// component of 'y' is returned. Components of 'x' and 'y' that + /// are not selected are allowed to be invalid floating point + /// values and will have no effect on the results. Thus, this + /// provides different functionality than + /// genType mix(genType x, genType y, genType(a)) + /// where a is a Boolean vector. + /// + /// @see GLSL mix man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + /// + /// @param[in] x Value to interpolate. + /// @param[in] y Value to interpolate. + /// @param[in] a Interpolant. + /// + /// @tparam genTypeT Floating point scalar or vector. + /// @tparam genTypeU Floating point or boolean scalar or vector. It can't be a vector if it is the length of genTypeT. + /// + /// @code + /// #include + /// ... + /// float a; + /// bool b; + /// glm::dvec3 e; + /// glm::dvec3 f; + /// glm::vec4 g; + /// glm::vec4 h; + /// ... + /// glm::vec4 r = glm::mix(g, h, a); // Interpolate with a floating-point scalar two vectors. + /// glm::vec4 s = glm::mix(g, h, b); // Returns g or h; + /// glm::dvec3 t = glm::mix(e, f, a); // Types of the third parameter is not required to match with the first and the second. + /// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter. + /// @endcode + template + GLM_FUNC_DECL genTypeT mix(genTypeT x, genTypeT y, genTypeU a); + + template + GLM_FUNC_DECL vec mix(vec const& x, vec const& y, vec const& a); + + template + GLM_FUNC_DECL vec mix(vec const& x, vec const& y, U a); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType. + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType step(genType edge, genType x); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec step(T edge, vec const& x); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL step man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec step(vec const& edge, vec const& x); + + /// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and + /// performs smooth Hermite interpolation between 0 and 1 + /// when edge0 < x < edge1. This is useful in cases where + /// you would want a threshold function with a smooth + /// transition. This is equivalent to: + /// genType t; + /// t = clamp ((x - edge0) / (edge1 - edge0), 0, 1); + /// return t * t * (3 - 2 * t); + /// Results are undefined if edge0 >= edge1. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL smoothstep man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType smoothstep(genType edge0, genType edge1, genType x); + + template + GLM_FUNC_DECL vec smoothstep(T edge0, T edge1, vec const& x); + + template + GLM_FUNC_DECL vec smoothstep(vec const& edge0, vec const& edge1, vec const& x); + + /// Returns true if x holds a NaN (not a number) + /// representation in the underlying implementation's set of + /// floating point representations. Returns false otherwise, + /// including for implementations with no NaN + /// representations. + /// + /// /!\ When using compiler fast math, this function may fail. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL isnan man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec isnan(vec const& x); + + /// Returns true if x holds a positive infinity or negative + /// infinity representation in the underlying implementation's + /// set of floating point representations. Returns false + /// otherwise, including for implementations with no infinity + /// representations. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL isinf man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec isinf(vec const& x); + + /// Returns a signed integer value representing + /// the encoding of a floating-point value. The floating-point + /// value's bit-level representation is preserved. + /// + /// @see GLSL floatBitsToInt man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL int floatBitsToInt(float const& v); + + /// Returns a signed integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL floatBitsToInt man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec floatBitsToInt(vec const& v); + + /// Returns a unsigned integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @see GLSL floatBitsToUint man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL uint floatBitsToUint(float const& v); + + /// Returns a unsigned integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL floatBitsToUint man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec floatBitsToUint(vec const& v); + + /// Returns a floating-point value corresponding to a signed + /// integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see GLSL intBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL float intBitsToFloat(int const& v); + + /// Returns a floating-point value corresponding to a signed + /// integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL intBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec intBitsToFloat(vec const& v); + + /// Returns a floating-point value corresponding to a + /// unsigned integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see GLSL uintBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + GLM_FUNC_DECL float uintBitsToFloat(uint const& v); + + /// Returns a floating-point value corresponding to a + /// unsigned integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL uintBitsToFloat man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL vec uintBitsToFloat(vec const& v); + + /// Computes and returns a * b + c. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL fma man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType fma(genType const& a, genType const& b, genType const& c); + + /// Splits x into a floating-point significand in the range + /// [0.5, 1.0) and an integral exponent of two, such that: + /// x = significand * exp(2, exponent) + /// + /// The significand is returned by the function and the + /// exponent is returned in the parameter exp. For a + /// floating-point value of zero, the significant and exponent + /// are both zero. For a floating-point value that is an + /// infinity or is not a number, the results are undefined. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL frexp man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType frexp(genType x, int& exp); + + template + GLM_FUNC_DECL vec frexp(vec const& v, vec& exp); + + /// Builds a floating-point number from x and the + /// corresponding integral exponent of two in exp, returning: + /// significand * exp(2, exponent) + /// + /// If this product is too large to be represented in the + /// floating-point type, the result is undefined. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL ldexp man page; + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL genType ldexp(genType const& x, int const& exp); + + template + GLM_FUNC_DECL vec ldexp(vec const& v, vec const& exp); + + /// @} +}//namespace glm + +#include "detail/func_common.inl" + diff --git a/vendor/glm/glm/detail/_features.hpp b/vendor/glm/glm/detail/_features.hpp new file mode 100644 index 0000000..b0cbe9f --- /dev/null +++ b/vendor/glm/glm/detail/_features.hpp @@ -0,0 +1,394 @@ +#pragma once + +// #define GLM_CXX98_EXCEPTIONS +// #define GLM_CXX98_RTTI + +// #define GLM_CXX11_RVALUE_REFERENCES +// Rvalue references - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html + +// GLM_CXX11_TRAILING_RETURN +// Rvalue references for *this - GCC not supported +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Initialization of class objects by rvalues - GCC any +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1610.html + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Non-static data member initializers - GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm + +// #define GLM_CXX11_VARIADIC_TEMPLATE +// Variadic templates - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf + +// +// Extending variadic template template parameters - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf + +// #define GLM_CXX11_GENERALIZED_INITIALIZERS +// Initializer lists - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm + +// #define GLM_CXX11_STATIC_ASSERT +// Static assertions - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html + +// #define GLM_CXX11_AUTO_TYPE +// auto-typed variables - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Multi-declarator auto - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1737.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Removal of auto as a storage-class specifier - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2546.htm + +// #define GLM_CXX11_AUTO_TYPE +// New function declarator syntax - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm + +// #define GLM_CXX11_LAMBDAS +// New wording for C++0x lambdas - GCC 4.5 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2927.pdf + +// #define GLM_CXX11_DECLTYPE +// Declared type of an expression - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf + +// +// Right angle brackets - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html + +// +// Default template arguments for function templates DR226 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226 + +// +// Solving the SFINAE problem for expressions DR339 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html + +// #define GLM_CXX11_ALIAS_TEMPLATE +// Template aliases N2258 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf + +// +// Extern templates N1987 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm + +// #define GLM_CXX11_NULLPTR +// Null pointer constant N2431 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf + +// #define GLM_CXX11_STRONG_ENUMS +// Strongly-typed enums N2347 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf + +// +// Forward declarations for enums N2764 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf + +// +// Generalized attributes N2761 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf + +// +// Generalized constant expressions N2235 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf + +// +// Alignment support N2341 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf + +// #define GLM_CXX11_DELEGATING_CONSTRUCTORS +// Delegating constructors N1986 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf + +// +// Inheriting constructors N2540 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm + +// #define GLM_CXX11_EXPLICIT_CONVERSIONS +// Explicit conversion operators N2437 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf + +// +// New character types N2249 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html + +// +// Unicode string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Raw string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Universal character name literals N2170 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html + +// #define GLM_CXX11_USER_LITERALS +// User-defined literals N2765 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf + +// +// Standard Layout Types N2342 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm + +// #define GLM_CXX11_DEFAULTED_FUNCTIONS +// #define GLM_CXX11_DELETED_FUNCTIONS +// Defaulted and deleted functions N2346 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm + +// +// Extended friend declarations N1791 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf + +// +// Extending sizeof N2253 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html + +// #define GLM_CXX11_INLINE_NAMESPACES +// Inline namespaces N2535 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm + +// #define GLM_CXX11_UNRESTRICTED_UNIONS +// Unrestricted unions N2544 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + +// #define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +// Local and unnamed types as template arguments N2657 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm + +// #define GLM_CXX11_RANGE_FOR +// Range-based for N2930 GCC 4.6 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html + +// #define GLM_CXX11_OVERRIDE_CONTROL +// Explicit virtual overrides N2928 N3206 N3272 GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm + +// +// Minimal support for garbage collection and reachability-based leak detection N2670 No +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2670.htm + +// #define GLM_CXX11_NOEXCEPT +// Allowing move constructors to throw [noexcept] N3050 GCC 4.6 (core language only) +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html + +// +// Defining move special member functions N3053 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html + +// +// Sequence points N2239 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Atomic operations N2427 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Strong Compare and Exchange N2748 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html + +// +// Bidirectional Fences N2752 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm + +// +// Memory model N2429 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm + +// +// Data-dependency ordering: atomics and memory model N2664 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm + +// +// Propagating exceptions N2179 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html + +// +// Abandoning a process and at_quick_exit N2440 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2440.htm + +// +// Allow atomics use in signal handlers N2547 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2547.htm + +// +// Thread-local storage N2659 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm + +// +// Dynamic initialization and destruction with concurrency N2660 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm + +// +// __func__ predefined identifier N2340 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2340.htm + +// +// C99 preprocessor N1653 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm + +// +// long long N1811 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf + +// +// Extended integral types N1988 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf + +#if(GLM_COMPILER & GLM_COMPILER_GCC) + +# define GLM_CXX11_STATIC_ASSERT + +#elif(GLM_COMPILER & GLM_COMPILER_CLANG) +# if(__has_feature(cxx_exceptions)) +# define GLM_CXX98_EXCEPTIONS +# endif + +# if(__has_feature(cxx_rtti)) +# define GLM_CXX98_RTTI +# endif + +# if(__has_feature(cxx_access_control_sfinae)) +# define GLM_CXX11_ACCESS_CONTROL_SFINAE +# endif + +# if(__has_feature(cxx_alias_templates)) +# define GLM_CXX11_ALIAS_TEMPLATE +# endif + +# if(__has_feature(cxx_alignas)) +# define GLM_CXX11_ALIGNAS +# endif + +# if(__has_feature(cxx_attributes)) +# define GLM_CXX11_ATTRIBUTES +# endif + +# if(__has_feature(cxx_constexpr)) +# define GLM_CXX11_CONSTEXPR +# endif + +# if(__has_feature(cxx_decltype)) +# define GLM_CXX11_DECLTYPE +# endif + +# if(__has_feature(cxx_default_function_template_args)) +# define GLM_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_defaulted_functions)) +# define GLM_CXX11_DEFAULTED_FUNCTIONS +# endif + +# if(__has_feature(cxx_delegating_constructors)) +# define GLM_CXX11_DELEGATING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_deleted_functions)) +# define GLM_CXX11_DELETED_FUNCTIONS +# endif + +# if(__has_feature(cxx_explicit_conversions)) +# define GLM_CXX11_EXPLICIT_CONVERSIONS +# endif + +# if(__has_feature(cxx_generalized_initializers)) +# define GLM_CXX11_GENERALIZED_INITIALIZERS +# endif + +# if(__has_feature(cxx_implicit_moves)) +# define GLM_CXX11_IMPLICIT_MOVES +# endif + +# if(__has_feature(cxx_inheriting_constructors)) +# define GLM_CXX11_INHERITING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_inline_namespaces)) +# define GLM_CXX11_INLINE_NAMESPACES +# endif + +# if(__has_feature(cxx_lambdas)) +# define GLM_CXX11_LAMBDAS +# endif + +# if(__has_feature(cxx_local_type_template_args)) +# define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_noexcept)) +# define GLM_CXX11_NOEXCEPT +# endif + +# if(__has_feature(cxx_nonstatic_member_init)) +# define GLM_CXX11_NONSTATIC_MEMBER_INIT +# endif + +# if(__has_feature(cxx_nullptr)) +# define GLM_CXX11_NULLPTR +# endif + +# if(__has_feature(cxx_override_control)) +# define GLM_CXX11_OVERRIDE_CONTROL +# endif + +# if(__has_feature(cxx_reference_qualified_functions)) +# define GLM_CXX11_REFERENCE_QUALIFIED_FUNCTIONS +# endif + +# if(__has_feature(cxx_range_for)) +# define GLM_CXX11_RANGE_FOR +# endif + +# if(__has_feature(cxx_raw_string_literals)) +# define GLM_CXX11_RAW_STRING_LITERALS +# endif + +# if(__has_feature(cxx_rvalue_references)) +# define GLM_CXX11_RVALUE_REFERENCES +# endif + +# if(__has_feature(cxx_static_assert)) +# define GLM_CXX11_STATIC_ASSERT +# endif + +# if(__has_feature(cxx_auto_type)) +# define GLM_CXX11_AUTO_TYPE +# endif + +# if(__has_feature(cxx_strong_enums)) +# define GLM_CXX11_STRONG_ENUMS +# endif + +# if(__has_feature(cxx_trailing_return)) +# define GLM_CXX11_TRAILING_RETURN +# endif + +# if(__has_feature(cxx_unicode_literals)) +# define GLM_CXX11_UNICODE_LITERALS +# endif + +# if(__has_feature(cxx_unrestricted_unions)) +# define GLM_CXX11_UNRESTRICTED_UNIONS +# endif + +# if(__has_feature(cxx_user_literals)) +# define GLM_CXX11_USER_LITERALS +# endif + +# if(__has_feature(cxx_variadic_templates)) +# define GLM_CXX11_VARIADIC_TEMPLATES +# endif + +#endif//(GLM_COMPILER & GLM_COMPILER_CLANG) diff --git a/vendor/glm/glm/detail/_fixes.hpp b/vendor/glm/glm/detail/_fixes.hpp new file mode 100644 index 0000000..a503c7c --- /dev/null +++ b/vendor/glm/glm/detail/_fixes.hpp @@ -0,0 +1,27 @@ +#include + +//! Workaround for compatibility with other libraries +#ifdef max +#undef max +#endif + +//! Workaround for compatibility with other libraries +#ifdef min +#undef min +#endif + +//! Workaround for Android +#ifdef isnan +#undef isnan +#endif + +//! Workaround for Android +#ifdef isinf +#undef isinf +#endif + +//! Workaround for Chrone Native Client +#ifdef log2 +#undef log2 +#endif + diff --git a/vendor/glm/glm/detail/_noise.hpp b/vendor/glm/glm/detail/_noise.hpp new file mode 100644 index 0000000..5a874a0 --- /dev/null +++ b/vendor/glm/glm/detail/_noise.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include "../common.hpp" + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER T mod289(T const& x) + { + return x - floor(x * (static_cast(1.0) / static_cast(289.0))) * static_cast(289.0); + } + + template + GLM_FUNC_QUALIFIER T permute(T const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> permute(vec<2, T, Q> const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> permute(vec<3, T, Q> const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> permute(vec<4, T, Q> const& x) + { + return mod289(((x * static_cast(34)) + static_cast(1)) * x); + } + + template + GLM_FUNC_QUALIFIER T taylorInvSqrt(T const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> taylorInvSqrt(vec<2, T, Q> const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> taylorInvSqrt(vec<3, T, Q> const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> taylorInvSqrt(vec<4, T, Q> const& r) + { + return static_cast(1.79284291400159) - static_cast(0.85373472095314) * r; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> fade(vec<2, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast(6) - static_cast(15)) + static_cast(10)); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> fade(vec<3, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast(6) - static_cast(15)) + static_cast(10)); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> fade(vec<4, T, Q> const& t) + { + return (t * t * t) * (t * (t * static_cast(6) - static_cast(15)) + static_cast(10)); + } +}//namespace detail +}//namespace glm + diff --git a/vendor/glm/glm/detail/_swizzle.hpp b/vendor/glm/glm/detail/_swizzle.hpp new file mode 100644 index 0000000..87896ef --- /dev/null +++ b/vendor/glm/glm/detail/_swizzle.hpp @@ -0,0 +1,804 @@ +#pragma once + +namespace glm{ +namespace detail +{ + // Internal class for implementing swizzle operators + template + struct _swizzle_base0 + { + protected: + GLM_FUNC_QUALIFIER T& elem(size_t i){ return (reinterpret_cast(_buffer))[i]; } + GLM_FUNC_QUALIFIER T const& elem(size_t i) const{ return (reinterpret_cast(_buffer))[i]; } + + // Use an opaque buffer to *ensure* the compiler doesn't call a constructor. + // The size 1 buffer is assumed to aligned to the actual members so that the + // elem() + char _buffer[1]; + }; + + template + struct _swizzle_base1 : public _swizzle_base0 + { + }; + + template + struct _swizzle_base1<2, T, Q, E0,E1,-1,-2, Aligned> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<2, T, Q> operator ()() const { return vec<2, T, Q>(this->elem(E0), this->elem(E1)); } + }; + + template + struct _swizzle_base1<3, T, Q, E0,E1,E2,-1, Aligned> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<3, T, Q> operator ()() const { return vec<3, T, Q>(this->elem(E0), this->elem(E1), this->elem(E2)); } + }; + + template + struct _swizzle_base1<4, T, Q, E0,E1,E2,E3, Aligned> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, T, Q> operator ()() const { return vec<4, T, Q>(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); } + }; + + // Internal class for implementing swizzle operators + /* + Template parameters: + + T = type of scalar values (e.g. float, double) + N = number of components in the vector (e.g. 3) + E0...3 = what index the n-th element of this swizzle refers to in the unswizzled vec + + DUPLICATE_ELEMENTS = 1 if there is a repeated element, 0 otherwise (used to specialize swizzles + containing duplicate elements so that they cannot be used as r-values). + */ + template + struct _swizzle_base2 : public _swizzle_base1::value> + { + struct op_equal + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e = t; } + }; + + struct op_minus + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e -= t; } + }; + + struct op_plus + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e += t; } + }; + + struct op_mul + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e *= t; } + }; + + struct op_div + { + GLM_FUNC_QUALIFIER void operator() (T& e, T& t) const{ e /= t; } + }; + + public: + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const T& t) + { + for (int i = 0; i < N; ++i) + (*this)[i] = t; + return *this; + } + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (vec const& that) + { + _apply_op(that, op_equal()); + return *this; + } + + GLM_FUNC_QUALIFIER void operator -= (vec const& that) + { + _apply_op(that, op_minus()); + } + + GLM_FUNC_QUALIFIER void operator += (vec const& that) + { + _apply_op(that, op_plus()); + } + + GLM_FUNC_QUALIFIER void operator *= (vec const& that) + { + _apply_op(that, op_mul()); + } + + GLM_FUNC_QUALIFIER void operator /= (vec const& that) + { + _apply_op(that, op_div()); + } + + GLM_FUNC_QUALIFIER T& operator[](size_t i) + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + GLM_FUNC_QUALIFIER T operator[](size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + + protected: + template + GLM_FUNC_QUALIFIER void _apply_op(vec const& that, const U& op) + { + // Make a copy of the data in this == &that. + // The copier should optimize out the copy in cases where the function is + // properly inlined and the copy is not necessary. + T t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + op( (*this)[i], t[i] ); + } + }; + + // Specialization for swizzles containing duplicate elements. These cannot be modified. + template + struct _swizzle_base2 : public _swizzle_base1::value> + { + struct Stub {}; + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const&) { return *this; } + + GLM_FUNC_QUALIFIER T operator[] (size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + }; + + template + struct _swizzle : public _swizzle_base2 + { + typedef _swizzle_base2 base_type; + + using base_type::operator=; + + GLM_FUNC_QUALIFIER operator vec () const { return (*this)(); } + }; + +// +// To prevent the C++ syntax from getting entirely overwhelming, define some alias macros +// +#define GLM_SWIZZLE_TEMPLATE1 template +#define GLM_SWIZZLE_TEMPLATE2 template +#define GLM_SWIZZLE_TYPE1 _swizzle +#define GLM_SWIZZLE_TYPE2 _swizzle + +// +// Wrapper for a binary operator (e.g. u.yy + v.zy) +// +#define GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE2& b) \ + { \ + return a() OPERAND b(); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const vec& b) \ + { \ + return a() OPERAND b; \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const vec& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Wrapper for a operand between a swizzle and a binary (e.g. 1.0f - u.xyz) +// +#define GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const GLM_SWIZZLE_TYPE1& a, const T& b) \ + { \ + return a() OPERAND b; \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER vec operator OPERAND ( const T& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Macro for wrapping a function taking one argument (e.g. abs()) +// +#define GLM_SWIZZLE_FUNCTION_1_ARGS(RETURN_TYPE,FUNCTION) \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a) \ + { \ + return FUNCTION(a()); \ + } + +// +// Macro for wrapping a function taking two vector arguments (e.g. dot()). +// +#define GLM_SWIZZLE_FUNCTION_2_ARGS(RETURN_TYPE,FUNCTION) \ + GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE2& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const typename V& b) \ + { \ + return FUNCTION(a(), b); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const V& a, const GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a, b()); \ + } + +// +// Macro for wrapping a function take 2 vec arguments followed by a scalar (e.g. mix()). +// +#define GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(RETURN_TYPE,FUNCTION) \ + GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE2& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const GLM_SWIZZLE_TYPE1& a, const typename S0::vec_type& b, const T& c)\ + { \ + return FUNCTION(a(), b, c); \ + } \ + GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const typename V& a, const GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a, b(), c); \ + } + +}//namespace detail +}//namespace glm + +namespace glm +{ + namespace detail + { + GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(-) + GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(*) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(+) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(-) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(*) + GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(/) + } + + // + // Swizzles are distinct types from the unswizzled type. The below macros will + // provide template specializations for the swizzle types for the given functions + // so that the compiler does not have any ambiguity to choosing how to handle + // the function. + // + // The alternative is to use the operator()() when calling the function in order + // to explicitly convert the swizzled type to the unswizzled type. + // + + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, abs); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acos); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acosh); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, all); + //GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, any); + + //GLM_SWIZZLE_FUNCTION_2_ARGS(value_type, dot); + //GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, cross); + //GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, step); + //GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(vec_type, mix); +} + +#define GLM_SWIZZLE2_2_MEMBERS(T, Q, E0,E1) \ + struct { detail::_swizzle<2, T, Q, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2, T, Q, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2, T, Q, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2, T, Q, 1,1,-1,-2> E1 ## E1; }; + +#define GLM_SWIZZLE2_3_MEMBERS(T, Q, E0,E1) \ + struct { detail::_swizzle<3,T, Q, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, Q, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T, Q, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, Q, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, Q, 1,1,1,-1> E1 ## E1 ## E1; }; + +#define GLM_SWIZZLE2_4_MEMBERS(T, Q, E0,E1) \ + struct { detail::_swizzle<4,T, Q, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; + +#define GLM_SWIZZLE3_2_MEMBERS(T, Q, E0,E1,E2) \ + struct { detail::_swizzle<2,T, Q, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 2,2,-1,-2> E2 ## E2; }; + +#define GLM_SWIZZLE3_3_MEMBERS(T, Q ,E0,E1,E2) \ + struct { detail::_swizzle<3, T, Q, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,2,-1> E2 ## E2 ## E2; }; + +#define GLM_SWIZZLE3_4_MEMBERS(T, Q, E0,E1,E2) \ + struct { detail::_swizzle<4,T, Q, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, Q, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; + +#define GLM_SWIZZLE4_2_MEMBERS(T, Q, E0,E1,E2,E3) \ + struct { detail::_swizzle<2,T, Q, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 0,3,-1,-2> E0 ## E3; }; \ + struct { detail::_swizzle<2,T, Q, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 1,3,-1,-2> E1 ## E3; }; \ + struct { detail::_swizzle<2,T, Q, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 2,2,-1,-2> E2 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 2,3,-1,-2> E2 ## E3; }; \ + struct { detail::_swizzle<2,T, Q, 3,0,-1,-2> E3 ## E0; }; \ + struct { detail::_swizzle<2,T, Q, 3,1,-1,-2> E3 ## E1; }; \ + struct { detail::_swizzle<2,T, Q, 3,2,-1,-2> E3 ## E2; }; \ + struct { detail::_swizzle<2,T, Q, 3,3,-1,-2> E3 ## E3; }; + +#define GLM_SWIZZLE4_3_MEMBERS(T, Q, E0,E1,E2,E3) \ + struct { detail::_swizzle<3, T, Q, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,0,3,-1> E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,1,3,-1> E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,2,3,-1> E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,0,-1> E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,1,-1> E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,2,-1> E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 0,3,3,-1> E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,0,3,-1> E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,1,3,-1> E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,2,3,-1> E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,0,-1> E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,1,-1> E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,2,-1> E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 1,3,3,-1> E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,0,3,-1> E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,1,3,-1> E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,2,-1> E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,2,3,-1> E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,0,-1> E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,1,-1> E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,2,-1> E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 2,3,3,-1> E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,0,-1> E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,1,-1> E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,2,-1> E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,0,3,-1> E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,0,-1> E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,1,-1> E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,2,-1> E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,1,3,-1> E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,0,-1> E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,1,-1> E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,2,-1> E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,2,3,-1> E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,0,-1> E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,1,-1> E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,2,-1> E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<3, T, Q, 3,3,3,-1> E3 ## E3 ## E3; }; + +#define GLM_SWIZZLE4_4_MEMBERS(T, Q, E0,E1,E2,E3) \ + struct { detail::_swizzle<4, T, Q, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, Q, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; diff --git a/vendor/glm/glm/detail/_swizzle_func.hpp b/vendor/glm/glm/detail/_swizzle_func.hpp new file mode 100644 index 0000000..d93c6af --- /dev/null +++ b/vendor/glm/glm/detail/_swizzle_func.hpp @@ -0,0 +1,682 @@ +#pragma once + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, CONST, A, B) \ + vec<2, T, Q> A ## B() CONST \ + { \ + return vec<2, T, Q>(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, CONST, A, B, C) \ + vec<3, T, Q> A ## B ## C() CONST \ + { \ + return vec<3, T, Q>(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, CONST, A, B, C, D) \ + vec<4, T, Q> A ## B ## C ## D() CONST \ + { \ + return vec<4, T, Q>(this->A, this->B, this->C, this->D); \ + } + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY_DEF(T, P, L, CONST, A, B) \ + template \ + vec vec::A ## B() CONST \ + { \ + return vec<2, T, Q>(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY_DEF(T, P, L, CONST, A, B, C) \ + template \ + vec<3, T, Q> vec::A ## B ## C() CONST \ + { \ + return vec<3, T, Q>(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY_DEF(T, P, L, CONST, A, B, C, D) \ + template \ + vec<4, T, Q> vec::A ## B ## C ## D() CONST \ + { \ + return vec<4, T, Q>(this->A, this->B, this->C, this->D); \ + } + +#define GLM_MUTABLE + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, 2, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, 2, GLM_MUTABLE, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC2(T, P) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, x, y) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, r, g) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(T, P, s, t) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, B) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, GLM_MUTABLE, C, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(T, P, A, B, C) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3(T, P) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, x, y, z) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, r, g, b) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(T, P, s, t, p) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, GLM_MUTABLE, D, C) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, , D, C, B) + +#define GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, , D, B, C, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4(T, P) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, x, y, z, w) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, r, g, b, a) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(T, P, s, t, p, q) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, B) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(T, P, A, B) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(T, P, A, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2(T, P) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, x, y) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, r, g) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, P, s, t) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, C) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(T, P, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(T, P, A, B, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3(T, P) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, x, y, z) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, r, g, b) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, P, s, t, p) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, const, D, D) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, A, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, B, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, C, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(T, P, const, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, A, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, B, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, C, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(T, P, const, D, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(T, P, A, B, C, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4(T, P) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, x, y, z, w) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, r, g, b, a) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, P, s, t, p, q) + diff --git a/vendor/glm/glm/detail/_vectorize.hpp b/vendor/glm/glm/detail/_vectorize.hpp new file mode 100644 index 0000000..1fcaec3 --- /dev/null +++ b/vendor/glm/glm/detail/_vectorize.hpp @@ -0,0 +1,162 @@ +#pragma once + +namespace glm{ +namespace detail +{ + template class vec, length_t L, typename R, typename T, qualifier Q> + struct functor1{}; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<1, R, Q> call(R (*Func) (T x), vec<1, T, Q> const& v) + { + return vec<1, R, Q>(Func(v.x)); + } + }; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<2, R, Q> call(R (*Func) (T x), vec<2, T, Q> const& v) + { + return vec<2, R, Q>(Func(v.x), Func(v.y)); + } + }; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<3, R, Q> call(R (*Func) (T x), vec<3, T, Q> const& v) + { + return vec<3, R, Q>(Func(v.x), Func(v.y), Func(v.z)); + } + }; + + template class vec, typename R, typename T, qualifier Q> + struct functor1 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, R, Q> call(R (*Func) (T x), vec<4, T, Q> const& v) + { + return vec<4, R, Q>(Func(v.x), Func(v.y), Func(v.z), Func(v.w)); + } + }; + + template class vec, length_t L, typename T, qualifier Q> + struct functor2{}; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<1, T, Q> call(T (*Func) (T x, T y), vec<1, T, Q> const& a, vec<1, T, Q> const& b) + { + return vec<1, T, Q>(Func(a.x, b.x)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<2, T, Q> call(T (*Func) (T x, T y), vec<2, T, Q> const& a, vec<2, T, Q> const& b) + { + return vec<2, T, Q>(Func(a.x, b.x), Func(a.y, b.y)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<3, T, Q> call(T (*Func) (T x, T y), vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + return vec<3, T, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2 + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(T (*Func) (T x, T y), vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w)); + } + }; + + template class vec, length_t L, typename T, qualifier Q> + struct functor2_vec_sca{}; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<1, T, Q> call(T (*Func) (T x, T y), vec<1, T, Q> const& a, T b) + { + return vec<1, T, Q>(Func(a.x, b)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<2, T, Q> call(T (*Func) (T x, T y), vec<2, T, Q> const& a, T b) + { + return vec<2, T, Q>(Func(a.x, b), Func(a.y, b)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<3, T, Q> call(T (*Func) (T x, T y), vec<3, T, Q> const& a, T b) + { + return vec<3, T, Q>(Func(a.x, b), Func(a.y, b), Func(a.z, b)); + } + }; + + template class vec, typename T, qualifier Q> + struct functor2_vec_sca + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(T (*Func) (T x, T y), vec<4, T, Q> const& a, T b) + { + return vec<4, T, Q>(Func(a.x, b), Func(a.y, b), Func(a.z, b), Func(a.w, b)); + } + }; + + template + struct functor2_vec_int {}; + + template + struct functor2_vec_int<1, T, Q> + { + GLM_FUNC_QUALIFIER static vec<1, int, Q> call(int (*Func) (T x, int y), vec<1, T, Q> const& a, vec<1, int, Q> const& b) + { + return vec<1, int, Q>(Func(a.x, b.x)); + } + }; + + template + struct functor2_vec_int<2, T, Q> + { + GLM_FUNC_QUALIFIER static vec<2, int, Q> call(int (*Func) (T x, int y), vec<2, T, Q> const& a, vec<2, int, Q> const& b) + { + return vec<2, int, Q>(Func(a.x, b.x), Func(a.y, b.y)); + } + }; + + template + struct functor2_vec_int<3, T, Q> + { + GLM_FUNC_QUALIFIER static vec<3, int, Q> call(int (*Func) (T x, int y), vec<3, T, Q> const& a, vec<3, int, Q> const& b) + { + return vec<3, int, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z)); + } + }; + + template + struct functor2_vec_int<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(int (*Func) (T x, int y), vec<4, T, Q> const& a, vec<4, int, Q> const& b) + { + return vec<4, int, Q>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w)); + } + }; +}//namespace detail +}//namespace glm diff --git a/vendor/glm/glm/detail/compute_common.hpp b/vendor/glm/glm/detail/compute_common.hpp new file mode 100644 index 0000000..cc24b9e --- /dev/null +++ b/vendor/glm/glm/detail/compute_common.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include "setup.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct compute_abs + {}; + + template + struct compute_abs + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || std::numeric_limits::is_signed, + "'abs' only accept floating-point and integer scalar or vector inputs"); + + return x >= genFIType(0) ? x : -x; + // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; + } + }; + +#if GLM_COMPILER & GLM_COMPILER_CUDA + template<> + struct compute_abs + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static float call(float x) + { + return fabsf(x); + } + }; +#endif + + template + struct compute_abs + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + (!std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'abs' only accept floating-point and integer scalar or vector inputs"); + return x; + } + }; +}//namespace detail +}//namespace glm diff --git a/vendor/glm/glm/detail/compute_vector_relational.hpp b/vendor/glm/glm/detail/compute_vector_relational.hpp new file mode 100644 index 0000000..167b634 --- /dev/null +++ b/vendor/glm/glm/detail/compute_vector_relational.hpp @@ -0,0 +1,30 @@ +#pragma once + +//#include "compute_common.hpp" +#include "setup.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct compute_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(T a, T b) + { + return a == b; + } + }; +/* + template + struct compute_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(T a, T b) + { + return detail::compute_abs::is_signed>::call(b - a) <= static_cast(0); + //return std::memcmp(&a, &b, sizeof(T)) == 0; + } + }; +*/ +}//namespace detail +}//namespace glm diff --git a/vendor/glm/glm/detail/func_common.inl b/vendor/glm/glm/detail/func_common.inl new file mode 100644 index 0000000..4b5f144 --- /dev/null +++ b/vendor/glm/glm/detail/func_common.inl @@ -0,0 +1,792 @@ +/// @ref core +/// @file glm/detail/func_common.inl + +#include "../vector_relational.hpp" +#include "compute_common.hpp" +#include "type_vec1.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include "_vectorize.hpp" +#include + +namespace glm +{ + // min + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType min(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'min' only accept floating-point or integer inputs"); + return (y < x) ? y : x; + } + + // max + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType max(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'max' only accept floating-point or integer inputs"); + + return (x < y) ? y : x; + } + + // abs + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR int abs(int x) + { + int const y = x >> (sizeof(int) * 8 - 1); + return (x ^ y) - y; + } + + // round +# if GLM_HAS_CXX11_STL + using ::std::round; +# else + template + GLM_FUNC_QUALIFIER genType round(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'round' only accept floating-point inputs"); + + return x < static_cast(0) ? static_cast(int(x - static_cast(0.5))) : static_cast(int(x + static_cast(0.5))); + } +# endif + + // trunc +# if GLM_HAS_CXX11_STL + using ::std::trunc; +# else + template + GLM_FUNC_QUALIFIER genType trunc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'trunc' only accept floating-point inputs"); + + return x < static_cast(0) ? -std::floor(-x) : std::floor(x); + } +# endif + +}//namespace glm + +namespace glm{ +namespace detail +{ + template + struct compute_abs_vector + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& x) + { + return detail::functor1::call(abs, x); + } + }; + + template + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y, vec const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vec(vec(x) * (static_cast(1) - a) + vec(y) * a); + } + }; + + template + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y, vec const& a) + { + vec Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = a[i] ? y[i] : x[i]; + return Result; + } + }; + + template + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return vec(vec(x) * (static_cast(1) - a) + vec(y) * a); + } + }; + + template + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y, bool const& a) + { + return a ? y : x; + } + }; + + template + struct compute_mix + { + GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a"); + + return static_cast(static_cast(x) * (static_cast(1) - a) + static_cast(y) * a); + } + }; + + template + struct compute_mix + { + GLM_FUNC_QUALIFIER static T call(T const& x, T const& y, bool const& a) + { + return a ? y : x; + } + }; + + template + struct compute_sign + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return vec(glm::lessThan(vec(0), x)) - vec(glm::lessThan(x, vec(0))); + } + }; + +# if GLM_ARCH == GLM_ARCH_X86 + template + struct compute_sign + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + T const Shift(static_cast(sizeof(T) * 8 - 1)); + vec const y(vec::type, Q>(-x) >> typename detail::make_unsigned::type(Shift)); + + return (x >> Shift) | y; + } + }; +# endif + + template + struct compute_floor + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(std::floor, x); + } + }; + + template + struct compute_ceil + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(std::ceil, x); + } + }; + + template + struct compute_fract + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return x - floor(x); + } + }; + + template + struct compute_trunc + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(trunc, x); + } + }; + + template + struct compute_round + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(round, x); + } + }; + + template + struct compute_mod + { + GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'mod' only accept floating-point inputs. Include for integer inputs."); + return a - b * floor(a / b); + } + }; + + template + struct compute_min_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y) + { + return detail::functor2::call(min, x, y); + } + }; + + template + struct compute_max_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& y) + { + return detail::functor2::call(max, x, y); + } + }; + + template + struct compute_clamp_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, vec const& minVal, vec const& maxVal) + { + return min(max(x, minVal), maxVal); + } + }; + + template + struct compute_step_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& edge, vec const& x) + { + return mix(vec(1), vec(0), glm::lessThan(x, edge)); + } + }; + + template + struct compute_smoothstep_vector + { + GLM_FUNC_QUALIFIER static vec call(vec const& edge0, vec const& edge1, vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs"); + vec const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast(0), static_cast(1))); + return tmp * tmp * (static_cast(3) - static_cast(2) * tmp); + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genFIType abs(genFIType x) + { + return detail::compute_abs::is_signed>::call(x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec abs(vec const& x) + { + return detail::compute_abs_vector::value>::call(x); + } + + // sign + // fast and works for any type + template + GLM_FUNC_QUALIFIER genFIType sign(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign<1, genFIType, defaultp, + std::numeric_limits::is_iec559, detail::is_aligned::value>::call(vec<1, genFIType>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec sign(vec const& x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || (std::numeric_limits::is_signed && std::numeric_limits::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign::is_iec559, detail::is_aligned::value>::call(x); + } + + // floor + using ::std::floor; + template + GLM_FUNC_QUALIFIER vec floor(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'floor' only accept floating-point inputs."); + return detail::compute_floor::value>::call(x); + } + + template + GLM_FUNC_QUALIFIER vec trunc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'trunc' only accept floating-point inputs"); + return detail::compute_trunc::value>::call(x); + } + + template + GLM_FUNC_QUALIFIER vec round(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'round' only accept floating-point inputs"); + return detail::compute_round::value>::call(x); + } + +/* + // roundEven + template + GLM_FUNC_QUALIFIER genType roundEven(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'roundEven' only accept floating-point inputs"); + + return genType(int(x + genType(int(x) % 2))); + } +*/ + + // roundEven + template + GLM_FUNC_QUALIFIER genType roundEven(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'roundEven' only accept floating-point inputs"); + + int Integer = static_cast(x); + genType IntegerPart = static_cast(Integer); + genType FractionalPart = fract(x); + + if(FractionalPart > static_cast(0.5) || FractionalPart < static_cast(0.5)) + { + return round(x); + } + else if((Integer % 2) == 0) + { + return IntegerPart; + } + else if(x <= static_cast(0)) // Work around... + { + return IntegerPart - static_cast(1); + } + else + { + return IntegerPart + static_cast(1); + } + //else // Bug on MinGW 4.5.2 + //{ + // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0)); + //} + } + + template + GLM_FUNC_QUALIFIER vec roundEven(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'roundEven' only accept floating-point inputs"); + return detail::functor1::call(roundEven, x); + } + + // ceil + using ::std::ceil; + template + GLM_FUNC_QUALIFIER vec ceil(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'ceil' only accept floating-point inputs"); + return detail::compute_ceil::value>::call(x); + } + + // fract + template + GLM_FUNC_QUALIFIER genType fract(genType x) + { + return fract(vec<1, genType>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec fract(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fract' only accept floating-point inputs"); + return detail::compute_fract::value>::call(x); + } + + // mod + template + GLM_FUNC_QUALIFIER genType mod(genType x, genType y) + { +# if GLM_COMPILER & GLM_COMPILER_CUDA + // Another Cuda compiler bug https://github.com/g-truc/glm/issues/530 + vec<1, genType, defaultp> Result(mod(vec<1, genType, defaultp>(x), y)); + return Result.x; +# else + return mod(vec<1, genType, defaultp>(x), y).x; +# endif + } + + template + GLM_FUNC_QUALIFIER vec mod(vec const& x, T y) + { + return detail::compute_mod::value>::call(x, vec(y)); + } + + template + GLM_FUNC_QUALIFIER vec mod(vec const& x, vec const& y) + { + return detail::compute_mod::value>::call(x, y); + } + + // modf + template + GLM_FUNC_QUALIFIER genType modf(genType x, genType & i) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'modf' only accept floating-point inputs"); + return std::modf(x, &i); + } + + template + GLM_FUNC_QUALIFIER vec<1, T, Q> modf(vec<1, T, Q> const& x, vec<1, T, Q> & i) + { + return vec<1, T, Q>( + modf(x.x, i.x)); + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> modf(vec<2, T, Q> const& x, vec<2, T, Q> & i) + { + return vec<2, T, Q>( + modf(x.x, i.x), + modf(x.y, i.y)); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> modf(vec<3, T, Q> const& x, vec<3, T, Q> & i) + { + return vec<3, T, Q>( + modf(x.x, i.x), + modf(x.y, i.y), + modf(x.z, i.z)); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> modf(vec<4, T, Q> const& x, vec<4, T, Q> & i) + { + return vec<4, T, Q>( + modf(x.x, i.x), + modf(x.y, i.y), + modf(x.z, i.z), + modf(x.w, i.w)); + } + + //// Only valid if (INT_MIN <= x-y <= INT_MAX) + //// min(x,y) + //r = y + ((x - y) & ((x - y) >> (sizeof(int) * + //CHAR_BIT - 1))); + //// max(x,y) + //r = x - ((x - y) & ((x - y) >> (sizeof(int) * + //CHAR_BIT - 1))); + + // min + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'min' only accept floating-point or integer inputs"); + return detail::compute_min_vector::value>::call(a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& a, vec const& b) + { + return detail::compute_min_vector::value>::call(a, b); + } + + // max + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'max' only accept floating-point or integer inputs"); + return detail::compute_max_vector::value>::call(a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& a, vec const& b) + { + return detail::compute_max_vector::value>::call(a, b); + } + + // clamp + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); + return min(max(x, minVal), maxVal); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec clamp(vec const& x, T minVal, T maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector::value>::call(x, vec(minVal), vec(maxVal)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec clamp(vec const& x, vec const& minVal, vec const& maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer, "'clamp' only accept floating-point or integer inputs"); + return detail::compute_clamp_vector::value>::call(x, minVal, maxVal); + } + + template + GLM_FUNC_QUALIFIER genTypeT mix(genTypeT x, genTypeT y, genTypeU a) + { + return detail::compute_mix::call(x, y, a); + } + + template + GLM_FUNC_QUALIFIER vec mix(vec const& x, vec const& y, U a) + { + return detail::compute_mix_scalar::value>::call(x, y, a); + } + + template + GLM_FUNC_QUALIFIER vec mix(vec const& x, vec const& y, vec const& a) + { + return detail::compute_mix_vector::value>::call(x, y, a); + } + + // step + template + GLM_FUNC_QUALIFIER genType step(genType edge, genType x) + { + return mix(static_cast(1), static_cast(0), x < edge); + } + + template + GLM_FUNC_QUALIFIER vec step(T edge, vec const& x) + { + return detail::compute_step_vector::value>::call(vec(edge), x); + } + + template + GLM_FUNC_QUALIFIER vec step(vec const& edge, vec const& x) + { + return detail::compute_step_vector::value>::call(edge, x); + } + + // smoothstep + template + GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs"); + + genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1))); + return tmp * tmp * (genType(3) - genType(2) * tmp); + } + + template + GLM_FUNC_QUALIFIER vec smoothstep(T edge0, T edge1, vec const& x) + { + return detail::compute_smoothstep_vector::value>::call(vec(edge0), vec(edge1), x); + } + + template + GLM_FUNC_QUALIFIER vec smoothstep(vec const& edge0, vec const& edge1, vec const& x) + { + return detail::compute_smoothstep_vector::value>::call(edge0, edge1, x); + } + +# if GLM_HAS_CXX11_STL + using std::isnan; +# else + template + GLM_FUNC_QUALIFIER bool isnan(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isnan' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::isnan(x); +# elif GLM_COMPILER & GLM_COMPILER_VC + return _isnan(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# if GLM_PLATFORM & GLM_PLATFORM_WINDOWS + return _isnan(x) != 0; +# else + return ::isnan(x) != 0; +# endif +# elif (GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG)) && (GLM_PLATFORM & GLM_PLATFORM_ANDROID) && __cplusplus < 201103L + return _isnan(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_CUDA + return ::isnan(x) != 0; +# else + return std::isnan(x); +# endif + } +# endif + + template + GLM_FUNC_QUALIFIER vec isnan(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isnan' only accept floating-point inputs"); + + vec Result; + for (length_t l = 0; l < v.length(); ++l) + Result[l] = glm::isnan(v[l]); + return Result; + } + +# if GLM_HAS_CXX11_STL + using std::isinf; +# else + template + GLM_FUNC_QUALIFIER bool isinf(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isinf' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::isinf(x); +# elif GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC) +# if(GLM_PLATFORM & GLM_PLATFORM_WINDOWS) + return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF; +# else + return ::isinf(x); +# endif +# elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG) +# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L) + return _isinf(x) != 0; +# else + return std::isinf(x); +# endif +# elif GLM_COMPILER & GLM_COMPILER_CUDA + // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab + return ::isinf(double(x)) != 0; +# else + return std::isinf(x); +# endif + } +# endif + + template + GLM_FUNC_QUALIFIER vec isinf(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isinf' only accept floating-point inputs"); + + vec Result; + for (length_t l = 0; l < v.length(); ++l) + Result[l] = glm::isinf(v[l]); + return Result; + } + + GLM_FUNC_QUALIFIER int floatBitsToInt(float const& v) + { + union + { + float in; + int out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec floatBitsToInt(vec const& v) + { + return reinterpret_cast&>(const_cast&>(v)); + } + + GLM_FUNC_QUALIFIER uint floatBitsToUint(float const& v) + { + union + { + float in; + uint out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec floatBitsToUint(vec const& v) + { + return reinterpret_cast&>(const_cast&>(v)); + } + + GLM_FUNC_QUALIFIER float intBitsToFloat(int const& v) + { + union + { + int in; + float out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec intBitsToFloat(vec const& v) + { + return reinterpret_cast&>(const_cast&>(v)); + } + + GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const& v) + { + union + { + uint in; + float out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec uintBitsToFloat(vec const& v) + { + return reinterpret_cast&>(const_cast&>(v)); + } + +# if GLM_HAS_CXX11_STL + using std::fma; +# else + template + GLM_FUNC_QUALIFIER genType fma(genType const& a, genType const& b, genType const& c) + { + return a * b + c; + } +# endif + + template + GLM_FUNC_QUALIFIER genType frexp(genType x, int& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'frexp' only accept floating-point inputs"); + + return std::frexp(x, &exp); + } + + template + GLM_FUNC_QUALIFIER vec frexp(vec const& v, vec& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'frexp' only accept floating-point inputs"); + + vec Result; + for (length_t l = 0; l < v.length(); ++l) + Result[l] = std::frexp(v[l], &exp[l]); + return Result; + } + + template + GLM_FUNC_QUALIFIER genType ldexp(genType const& x, int const& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'ldexp' only accept floating-point inputs"); + + return std::ldexp(x, exp); + } + + template + GLM_FUNC_QUALIFIER vec ldexp(vec const& v, vec const& exp) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'ldexp' only accept floating-point inputs"); + + vec Result; + for (length_t l = 0; l < v.length(); ++l) + Result[l] = std::ldexp(v[l], exp[l]); + return Result; + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_common_simd.inl" +#endif diff --git a/vendor/glm/glm/detail/func_common_simd.inl b/vendor/glm/glm/detail/func_common_simd.inl new file mode 100644 index 0000000..ce0032d --- /dev/null +++ b/vendor/glm/glm/detail/func_common_simd.inl @@ -0,0 +1,231 @@ +/// @ref core +/// @file glm/detail/func_common_simd.inl + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#include "../simd/common.h" + +#include + +namespace glm{ +namespace detail +{ + template + struct compute_abs_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_abs(v.data); + return result; + } + }; + + template + struct compute_abs_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v) + { + vec<4, int, Q> result; + result.data = glm_ivec4_abs(v.data); + return result; + } + }; + + template + struct compute_floor<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_floor(v.data); + return result; + } + }; + + template + struct compute_ceil<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_ceil(v.data); + return result; + } + }; + + template + struct compute_fract<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_fract(v.data); + return result; + } + }; + + template + struct compute_round<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> result; + result.data = glm_vec4_round(v.data); + return result; + } + }; + + template + struct compute_mod<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& x, vec<4, float, Q> const& y) + { + vec<4, float, Q> result; + result.data = glm_vec4_mod(x.data, y.data); + return result; + } + }; + + template + struct compute_min_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + vec<4, float, Q> result; + result.data = _mm_min_ps(v1.data, v2.data); + return result; + } + }; + + template + struct compute_min_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + vec<4, int, Q> result; + result.data = _mm_min_epi32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_min_vector<4, uint, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + vec<4, uint, Q> result; + result.data = _mm_min_epu32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_max_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + vec<4, float, Q> result; + result.data = _mm_max_ps(v1.data, v2.data); + return result; + } + }; + + template + struct compute_max_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + vec<4, int, Q> result; + result.data = _mm_max_epi32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_max_vector<4, uint, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + vec<4, uint, Q> result; + result.data = _mm_max_epu32(v1.data, v2.data); + return result; + } + }; + + template + struct compute_clamp_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& x, vec<4, float, Q> const& minVal, vec<4, float, Q> const& maxVal) + { + vec<4, float, Q> result; + result.data = _mm_min_ps(_mm_max_ps(x.data, minVal.data), maxVal.data); + return result; + } + }; + + template + struct compute_clamp_vector<4, int, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& x, vec<4, int, Q> const& minVal, vec<4, int, Q> const& maxVal) + { + vec<4, int, Q> result; + result.data = _mm_min_epi32(_mm_max_epi32(x.data, minVal.data), maxVal.data); + return result; + } + }; + + template + struct compute_clamp_vector<4, uint, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& x, vec<4, uint, Q> const& minVal, vec<4, uint, Q> const& maxVal) + { + vec<4, uint, Q> result; + result.data = _mm_min_epu32(_mm_max_epu32(x.data, minVal.data), maxVal.data); + return result; + } + }; + + template + struct compute_mix_vector<4, float, bool, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& x, vec<4, float, Q> const& y, vec<4, bool, Q> const& a) + { + __m128i const Load = _mm_set_epi32(-static_cast(a.w), -static_cast(a.z), -static_cast(a.y), -static_cast(a.x)); + __m128 const Mask = _mm_castsi128_ps(Load); + + vec<4, float, Q> Result; +# if 0 && GLM_ARCH & GLM_ARCH_AVX + Result.data = _mm_blendv_ps(x.data, y.data, Mask); +# else + Result.data = _mm_or_ps(_mm_and_ps(Mask, y.data), _mm_andnot_ps(Mask, x.data)); +# endif + return Result; + } + }; +/* FIXME + template + struct compute_step_vector + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& edge, vec<4, float, Q> const& x) + { + vec<4, float, Q> Result; + result.data = glm_vec4_step(edge.data, x.data); + return result; + } + }; +*/ + template + struct compute_smoothstep_vector<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& edge0, vec<4, float, Q> const& edge1, vec<4, float, Q> const& x) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_smoothstep(edge0.data, edge1.data, x.data); + return Result; + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/detail/func_exponential.inl b/vendor/glm/glm/detail/func_exponential.inl new file mode 100644 index 0000000..2040d41 --- /dev/null +++ b/vendor/glm/glm/detail/func_exponential.inl @@ -0,0 +1,152 @@ +/// @ref core +/// @file glm/detail/func_exponential.inl + +#include "../vector_relational.hpp" +#include "_vectorize.hpp" +#include +#include +#include + +namespace glm{ +namespace detail +{ +# if GLM_HAS_CXX11_STL + using std::log2; +# else + template + genType log2(genType Value) + { + return std::log(Value) * static_cast(1.4426950408889634073599246810019); + } +# endif + + template + struct compute_log2 + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'log2' only accept floating-point inputs. Include for integer inputs."); + + return detail::functor1::call(log2, v); + } + }; + + template + struct compute_sqrt + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(std::sqrt, x); + } + }; + + template + struct compute_inversesqrt + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return static_cast(1) / sqrt(x); + } + }; + + template + struct compute_inversesqrt + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + vec tmp(x); + vec xhalf(tmp * 0.5f); + vec* p = reinterpret_cast*>(const_cast*>(&x)); + vec i = vec(0x5f375a86) - (*p >> vec(1)); + vec* ptmp = reinterpret_cast*>(&i); + tmp = *ptmp; + tmp = tmp * (1.5f - xhalf * tmp * tmp); + return tmp; + } + }; +}//namespace detail + + // pow + using std::pow; + template + GLM_FUNC_QUALIFIER vec pow(vec const& base, vec const& exponent) + { + return detail::functor2::call(pow, base, exponent); + } + + // exp + using std::exp; + template + GLM_FUNC_QUALIFIER vec exp(vec const& x) + { + return detail::functor1::call(exp, x); + } + + // log + using std::log; + template + GLM_FUNC_QUALIFIER vec log(vec const& x) + { + return detail::functor1::call(log, x); + } + +# if GLM_HAS_CXX11_STL + using std::exp2; +# else + //exp2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType exp2(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'exp2' only accept floating-point inputs"); + + return std::exp(static_cast(0.69314718055994530941723212145818) * x); + } +# endif + + template + GLM_FUNC_QUALIFIER vec exp2(vec const& x) + { + return detail::functor1::call(exp2, x); + } + + // log2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType log2(genType x) + { + return log2(vec<1, genType>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec log2(vec const& x) + { + return detail::compute_log2::is_iec559, detail::is_aligned::value>::call(x); + } + + // sqrt + using std::sqrt; + template + GLM_FUNC_QUALIFIER vec sqrt(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'sqrt' only accept floating-point inputs"); + return detail::compute_sqrt::value>::call(x); + } + + // inversesqrt + template + GLM_FUNC_QUALIFIER genType inversesqrt(genType x) + { + return static_cast(1) / sqrt(x); + } + + template + GLM_FUNC_QUALIFIER vec inversesqrt(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'inversesqrt' only accept floating-point inputs"); + return detail::compute_inversesqrt::value>::call(x); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_exponential_simd.inl" +#endif + diff --git a/vendor/glm/glm/detail/func_exponential_simd.inl b/vendor/glm/glm/detail/func_exponential_simd.inl new file mode 100644 index 0000000..fb78951 --- /dev/null +++ b/vendor/glm/glm/detail/func_exponential_simd.inl @@ -0,0 +1,37 @@ +/// @ref core +/// @file glm/detail/func_exponential_simd.inl + +#include "../simd/exponential.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_sqrt<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> Result; + Result.data = _mm_sqrt_ps(v.data); + return Result; + } + }; + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<> + struct compute_sqrt<4, float, aligned_lowp, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, aligned_lowp> call(vec<4, float, aligned_lowp> const& v) + { + vec<4, float, aligned_lowp> Result; + Result.data = glm_vec4_sqrt_lowp(v.data); + return Result; + } + }; +# endif +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/detail/func_geometric.inl b/vendor/glm/glm/detail/func_geometric.inl new file mode 100644 index 0000000..9cde28f --- /dev/null +++ b/vendor/glm/glm/detail/func_geometric.inl @@ -0,0 +1,243 @@ +#include "../exponential.hpp" +#include "../common.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_length + { + GLM_FUNC_QUALIFIER static T call(vec const& v) + { + return sqrt(dot(v, v)); + } + }; + + template + struct compute_distance + { + GLM_FUNC_QUALIFIER static T call(vec const& p0, vec const& p1) + { + return length(p1 - p0); + } + }; + + template + struct compute_dot{}; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER static T call(vec<1, T, Q> const& a, vec<1, T, Q> const& b) + { + return a.x * b.x; + } + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER static T call(vec<2, T, Q> const& a, vec<2, T, Q> const& b) + { + vec<2, T, Q> tmp(a * b); + return tmp.x + tmp.y; + } + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER static T call(vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + vec<3, T, Q> tmp(a * b); + return tmp.x + tmp.y + tmp.z; + } + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER static T call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> tmp(a * b); + return (tmp.x + tmp.y) + (tmp.z + tmp.w); + } + }; + + template + struct compute_cross + { + GLM_FUNC_QUALIFIER static vec<3, T, Q> call(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'cross' accepts only floating-point inputs"); + + return vec<3, T, Q>( + x.y * y.z - y.y * x.z, + x.z * y.x - y.z * x.x, + x.x * y.y - y.x * x.y); + } + }; + + template + struct compute_normalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return v * inversesqrt(dot(v, v)); + } + }; + + template + struct compute_faceforward + { + GLM_FUNC_QUALIFIER static vec call(vec const& N, vec const& I, vec const& Nref) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return dot(Nref, I) < static_cast(0) ? N : -N; + } + }; + + template + struct compute_reflect + { + GLM_FUNC_QUALIFIER static vec call(vec const& I, vec const& N) + { + return I - N * dot(N, I) * static_cast(2); + } + }; + + template + struct compute_refract + { + GLM_FUNC_QUALIFIER static vec call(vec const& I, vec const& N, T eta) + { + T const dotValue(dot(N, I)); + T const k(static_cast(1) - eta * eta * (static_cast(1) - dotValue * dotValue)); + vec const Result = + (k >= static_cast(0)) ? (eta * I - (eta * dotValue + std::sqrt(k)) * N) : vec(0); + return Result; + } + }; +}//namespace detail + + // length + template + GLM_FUNC_QUALIFIER genType length(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'length' accepts only floating-point inputs"); + + return abs(x); + } + + template + GLM_FUNC_QUALIFIER T length(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'length' accepts only floating-point inputs"); + + return detail::compute_length::value>::call(v); + } + + // distance + template + GLM_FUNC_QUALIFIER genType distance(genType const& p0, genType const& p1) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'distance' accepts only floating-point inputs"); + + return length(p1 - p0); + } + + template + GLM_FUNC_QUALIFIER T distance(vec const& p0, vec const& p1) + { + return detail::compute_distance::value>::call(p0, p1); + } + + // dot + template + GLM_FUNC_QUALIFIER T dot(T x, T y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'dot' accepts only floating-point inputs"); + return x * y; + } + + template + GLM_FUNC_QUALIFIER T dot(vec const& x, vec const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'dot' accepts only floating-point inputs"); + return detail::compute_dot, T, detail::is_aligned::value>::call(x, y); + } + + // cross + template + GLM_FUNC_QUALIFIER vec<3, T, Q> cross(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + return detail::compute_cross::value>::call(x, y); + } +/* + // normalize + template + GLM_FUNC_QUALIFIER genType normalize(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return x < genType(0) ? genType(-1) : genType(1); + } +*/ + template + GLM_FUNC_QUALIFIER vec normalize(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'normalize' accepts only floating-point inputs"); + + return detail::compute_normalize::value>::call(x); + } + + // faceforward + template + GLM_FUNC_QUALIFIER genType faceforward(genType const& N, genType const& I, genType const& Nref) + { + return dot(Nref, I) < static_cast(0) ? N : -N; + } + + template + GLM_FUNC_QUALIFIER vec faceforward(vec const& N, vec const& I, vec const& Nref) + { + return detail::compute_faceforward::value>::call(N, I, Nref); + } + + // reflect + template + GLM_FUNC_QUALIFIER genType reflect(genType const& I, genType const& N) + { + return I - N * dot(N, I) * genType(2); + } + + template + GLM_FUNC_QUALIFIER vec reflect(vec const& I, vec const& N) + { + return detail::compute_reflect::value>::call(I, N); + } + + // refract + template + GLM_FUNC_QUALIFIER genType refract(genType const& I, genType const& N, genType eta) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'refract' accepts only floating-point inputs"); + genType const dotValue(dot(N, I)); + genType const k(static_cast(1) - eta * eta * (static_cast(1) - dotValue * dotValue)); + return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast(k >= static_cast(0)); + } + + template + GLM_FUNC_QUALIFIER vec refract(vec const& I, vec const& N, T eta) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'refract' accepts only floating-point inputs"); + return detail::compute_refract::value>::call(I, N, eta); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_geometric_simd.inl" +#endif diff --git a/vendor/glm/glm/detail/func_geometric_simd.inl b/vendor/glm/glm/detail/func_geometric_simd.inl new file mode 100644 index 0000000..2076dae --- /dev/null +++ b/vendor/glm/glm/detail/func_geometric_simd.inl @@ -0,0 +1,163 @@ +/// @ref core +/// @file glm/detail/func_geometric_simd.inl + +#include "../simd/geometric.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_length<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& v) + { + return _mm_cvtss_f32(glm_vec4_length(v.data)); + } + }; + + template + struct compute_distance<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& p0, vec<4, float, Q> const& p1) + { + return _mm_cvtss_f32(glm_vec4_distance(p0.data, p1.data)); + } + }; + + template + struct compute_dot, float, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& x, vec<4, float, Q> const& y) + { + return _mm_cvtss_f32(glm_vec1_dot(x.data, y.data)); + } + }; + + template + struct compute_cross + { + GLM_FUNC_QUALIFIER static vec<3, float, Q> call(vec<3, float, Q> const& a, vec<3, float, Q> const& b) + { + __m128 const set0 = _mm_set_ps(0.0f, a.z, a.y, a.x); + __m128 const set1 = _mm_set_ps(0.0f, b.z, b.y, b.x); + __m128 const xpd0 = glm_vec4_cross(set0, set1); + + vec<4, float, Q> Result; + Result.data = xpd0; + return vec<3, float, Q>(Result); + } + }; + + template + struct compute_normalize<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_normalize(v.data); + return Result; + } + }; + + template + struct compute_faceforward<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& N, vec<4, float, Q> const& I, vec<4, float, Q> const& Nref) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_faceforward(N.data, I.data, Nref.data); + return Result; + } + }; + + template + struct compute_reflect<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& I, vec<4, float, Q> const& N) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_reflect(I.data, N.data); + return Result; + } + }; + + template + struct compute_refract<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& I, vec<4, float, Q> const& N, float eta) + { + vec<4, float, Q> Result; + Result.data = glm_vec4_refract(I.data, N.data, _mm_set1_ps(eta)); + return Result; + } + }; +}//namespace detail +}//namespace glm + +#elif GLM_ARCH & GLM_ARCH_NEON_BIT +namespace glm{ +namespace detail +{ + template + struct compute_length<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& v) + { + return sqrt(compute_dot, float, true>::call(v, v)); + } + }; + + template + struct compute_distance<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& p0, vec<4, float, Q> const& p1) + { + return compute_length<4, float, Q, true>::call(p1 - p0); + } + }; + + + template + struct compute_dot, float, true> + { + GLM_FUNC_QUALIFIER static float call(vec<4, float, Q> const& x, vec<4, float, Q> const& y) + { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + float32x4_t v = vmulq_f32(x.data, y.data); + return vaddvq_f32(v); +#else // Armv7a with Neon + float32x4_t p = vmulq_f32(x.data, y.data); + float32x2_t v = vpadd_f32(vget_low_f32(p), vget_high_f32(p)); + v = vpadd_f32(v, v); + return vget_lane_f32(v, 0); +#endif + } + }; + + template + struct compute_normalize<4, float, Q, true> + { + GLM_FUNC_QUALIFIER static vec<4, float, Q> call(vec<4, float, Q> const& v) + { + float32x4_t p = vmulq_f32(v.data, v.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + p = vpaddq_f32(p, p); + p = vpaddq_f32(p, p); +#else + float32x2_t t = vpadd_f32(vget_low_f32(p), vget_high_f32(p)); + t = vpadd_f32(t, t); + p = vcombine_f32(t, t); +#endif + + float32x4_t vd = vrsqrteq_f32(p); + vec<4, float, Q> Result; + Result.data = vmulq_f32(v.data, vd); + return Result; + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/detail/func_integer.inl b/vendor/glm/glm/detail/func_integer.inl new file mode 100644 index 0000000..091e1e0 --- /dev/null +++ b/vendor/glm/glm/detail/func_integer.inl @@ -0,0 +1,372 @@ +/// @ref core + +#include "_vectorize.hpp" +#if(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC) +# include +# pragma intrinsic(_BitScanReverse) +#endif//(GLM_ARCH & GLM_ARCH_X86 && GLM_COMPILER & GLM_COMPILER_VC) +#include + +#if !GLM_HAS_EXTENDED_INTEGER_TYPE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic ignored "-Wc++11-long-long" +# endif +#endif + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER T mask(T Bits) + { + return Bits >= static_cast(sizeof(T) * 8) ? ~static_cast(0) : (static_cast(1) << Bits) - static_cast(1); + } + + template + struct compute_bitfieldReverseStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T, T) + { + return v; + } + }; + + template + struct compute_bitfieldReverseStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Mask, T Shift) + { + return (v & Mask) << Shift | (v & (~Mask)) >> Shift; + } + }; + + template + struct compute_bitfieldBitCountStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T, T) + { + return v; + } + }; + + template + struct compute_bitfieldBitCountStep + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Mask, T Shift) + { + return (v & Mask) + ((v >> Shift) & Mask); + } + }; + + template + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + if(Value == 0) + return -1; + + return glm::bitCount(~Value & (Value - static_cast(1))); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward64(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; +# endif +# endif//GLM_HAS_BITSCAN_WINDOWS + + template + struct compute_findMSB_step_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, T Shift) + { + return x | (x >> Shift); + } + }; + + template + struct compute_findMSB_step_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x, T) + { + return x; + } + }; + + template + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + vec x(v); + x = compute_findMSB_step_vec= 8>::call(x, static_cast( 1)); + x = compute_findMSB_step_vec= 8>::call(x, static_cast( 2)); + x = compute_findMSB_step_vec= 8>::call(x, static_cast( 4)); + x = compute_findMSB_step_vec= 16>::call(x, static_cast( 8)); + x = compute_findMSB_step_vec= 32>::call(x, static_cast(16)); + x = compute_findMSB_step_vec= 64>::call(x, static_cast(32)); + return vec(sizeof(T) * 8 - 1) - glm::bitCount(~x); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + GLM_FUNC_QUALIFIER int compute_findMSB_32(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(compute_findMSB_32, x); + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template + GLM_FUNC_QUALIFIER int compute_findMSB_64(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse64(&Result, *reinterpret_cast(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + return detail::functor1::call(compute_findMSB_64, x); + } + }; +# endif +# endif//GLM_HAS_BITSCAN_WINDOWS +}//namespace detail + + // uaddCarry + GLM_FUNC_QUALIFIER uint uaddCarry(uint const& x, uint const& y, uint & Carry) + { + detail::uint64 const Value64(static_cast(x) + static_cast(y)); + detail::uint64 const Max32((static_cast(1) << static_cast(32)) - static_cast(1)); + Carry = Value64 > Max32 ? 1u : 0u; + return static_cast(Value64 % (Max32 + static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER vec uaddCarry(vec const& x, vec const& y, vec& Carry) + { + vec Value64(vec(x) + vec(y)); + vec Max32((static_cast(1) << static_cast(32)) - static_cast(1)); + Carry = mix(vec(0), vec(1), greaterThan(Value64, Max32)); + return vec(Value64 % (Max32 + static_cast(1))); + } + + // usubBorrow + GLM_FUNC_QUALIFIER uint usubBorrow(uint const& x, uint const& y, uint & Borrow) + { + Borrow = x >= y ? static_cast(0) : static_cast(1); + if(y >= x) + return y - x; + else + return static_cast((static_cast(1) << static_cast(32)) + (static_cast(y) - static_cast(x))); + } + + template + GLM_FUNC_QUALIFIER vec usubBorrow(vec const& x, vec const& y, vec& Borrow) + { + Borrow = mix(vec(1), vec(0), greaterThanEqual(x, y)); + vec const YgeX(y - x); + vec const XgeY(vec((static_cast(1) << static_cast(32)) + (vec(y) - vec(x)))); + return mix(XgeY, YgeX, greaterThanEqual(y, x)); + } + + // umulExtended + GLM_FUNC_QUALIFIER void umulExtended(uint const& x, uint const& y, uint & msb, uint & lsb) + { + detail::uint64 Value64 = static_cast(x) * static_cast(y); + msb = static_cast(Value64 >> static_cast(32)); + lsb = static_cast(Value64); + } + + template + GLM_FUNC_QUALIFIER void umulExtended(vec const& x, vec const& y, vec& msb, vec& lsb) + { + vec Value64(vec(x) * vec(y)); + msb = vec(Value64 >> static_cast(32)); + lsb = vec(Value64); + } + + // imulExtended + GLM_FUNC_QUALIFIER void imulExtended(int x, int y, int& msb, int& lsb) + { + detail::int64 Value64 = static_cast(x) * static_cast(y); + msb = static_cast(Value64 >> static_cast(32)); + lsb = static_cast(Value64); + } + + template + GLM_FUNC_QUALIFIER void imulExtended(vec const& x, vec const& y, vec& msb, vec& lsb) + { + vec Value64(vec(x) * vec(y)); + lsb = vec(Value64 & static_cast(0xFFFFFFFF)); + msb = vec((Value64 >> static_cast(32)) & static_cast(0xFFFFFFFF)); + } + + // bitfieldExtract + template + GLM_FUNC_QUALIFIER genIUType bitfieldExtract(genIUType Value, int Offset, int Bits) + { + return bitfieldExtract(vec<1, genIUType>(Value), Offset, Bits).x; + } + + template + GLM_FUNC_QUALIFIER vec bitfieldExtract(vec const& Value, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldExtract' only accept integer inputs"); + + return (Value >> static_cast(Offset)) & static_cast(detail::mask(Bits)); + } + + // bitfieldInsert + template + GLM_FUNC_QUALIFIER genIUType bitfieldInsert(genIUType const& Base, genIUType const& Insert, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldInsert' only accept integer values"); + + return bitfieldInsert(vec<1, genIUType>(Base), vec<1, genIUType>(Insert), Offset, Bits).x; + } + + template + GLM_FUNC_QUALIFIER vec bitfieldInsert(vec const& Base, vec const& Insert, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldInsert' only accept integer values"); + + T const Mask = static_cast(detail::mask(Bits) << Offset); + return (Base & ~Mask) | ((Insert << static_cast(Offset)) & Mask); + } + + // bitfieldReverse + template + GLM_FUNC_QUALIFIER genIUType bitfieldReverse(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldReverse' only accept integer values"); + + return bitfieldReverse(glm::vec<1, genIUType, glm::defaultp>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec bitfieldReverse(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldReverse' only accept integer values"); + + vec x(v); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 2>::call(x, static_cast(0x5555555555555555ull), static_cast( 1)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 4>::call(x, static_cast(0x3333333333333333ull), static_cast( 2)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 8>::call(x, static_cast(0x0F0F0F0F0F0F0F0Full), static_cast( 4)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 16>::call(x, static_cast(0x00FF00FF00FF00FFull), static_cast( 8)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 32>::call(x, static_cast(0x0000FFFF0000FFFFull), static_cast(16)); + x = detail::compute_bitfieldReverseStep::value, sizeof(T) * 8>= 64>::call(x, static_cast(0x00000000FFFFFFFFull), static_cast(32)); + return x; + } + + // bitCount + template + GLM_FUNC_QUALIFIER int bitCount(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitCount' only accept integer values"); + + return bitCount(glm::vec<1, genIUType, glm::defaultp>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec bitCount(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitCount' only accept integer values"); + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4310) //cast truncates constant value +# endif + + vec::type, Q> x(*reinterpret_cast::type, Q> const *>(&v)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 2>::call(x, typename detail::make_unsigned::type(0x5555555555555555ull), typename detail::make_unsigned::type( 1)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 4>::call(x, typename detail::make_unsigned::type(0x3333333333333333ull), typename detail::make_unsigned::type( 2)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 8>::call(x, typename detail::make_unsigned::type(0x0F0F0F0F0F0F0F0Full), typename detail::make_unsigned::type( 4)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 16>::call(x, typename detail::make_unsigned::type(0x00FF00FF00FF00FFull), typename detail::make_unsigned::type( 8)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 32>::call(x, typename detail::make_unsigned::type(0x0000FFFF0000FFFFull), typename detail::make_unsigned::type(16)); + x = detail::compute_bitfieldBitCountStep::type, Q, detail::is_aligned::value, sizeof(T) * 8>= 64>::call(x, typename detail::make_unsigned::type(0x00000000FFFFFFFFull), typename detail::make_unsigned::type(32)); + return vec(x); + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + } + + // findLSB + template + GLM_FUNC_QUALIFIER int findLSB(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findLSB' only accept integer values"); + + return detail::compute_findLSB::call(Value); + } + + template + GLM_FUNC_QUALIFIER vec findLSB(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findLSB' only accept integer values"); + + return detail::functor1::call(findLSB, x); + } + + // findMSB + template + GLM_FUNC_QUALIFIER int findMSB(genIUType v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + return findMSB(vec<1, genIUType>(v)).x; + } + + template + GLM_FUNC_QUALIFIER vec findMSB(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + return detail::compute_findMSB_vec::call(v); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_integer_simd.inl" +#endif + diff --git a/vendor/glm/glm/detail/func_integer_simd.inl b/vendor/glm/glm/detail/func_integer_simd.inl new file mode 100644 index 0000000..8be6c9c --- /dev/null +++ b/vendor/glm/glm/detail/func_integer_simd.inl @@ -0,0 +1,65 @@ +#include "../simd/integer.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_bitfieldReverseStep<4, uint, Q, true, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v, uint Mask, uint Shift) + { + __m128i const set0 = v.data; + + __m128i const set1 = _mm_set1_epi32(static_cast(Mask)); + __m128i const and1 = _mm_and_si128(set0, set1); + __m128i const sft1 = _mm_slli_epi32(and1, Shift); + + __m128i const set2 = _mm_andnot_si128(set0, _mm_set1_epi32(-1)); + __m128i const and2 = _mm_and_si128(set0, set2); + __m128i const sft2 = _mm_srai_epi32(and2, Shift); + + __m128i const or0 = _mm_or_si128(sft1, sft2); + + return or0; + } + }; + + template + struct compute_bitfieldBitCountStep<4, uint, Q, true, true> + { + GLM_FUNC_QUALIFIER static vec<4, uint, Q> call(vec<4, uint, Q> const& v, uint Mask, uint Shift) + { + __m128i const set0 = v.data; + + __m128i const set1 = _mm_set1_epi32(static_cast(Mask)); + __m128i const and0 = _mm_and_si128(set0, set1); + __m128i const sft0 = _mm_slli_epi32(set0, Shift); + __m128i const and1 = _mm_and_si128(sft0, set1); + __m128i const add0 = _mm_add_epi32(and0, and1); + + return add0; + } + }; +}//namespace detail + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template<> + GLM_FUNC_QUALIFIER int bitCount(uint x) + { + return _mm_popcnt_u32(x); + } + +# if(GLM_MODEL == GLM_MODEL_64) + template<> + GLM_FUNC_QUALIFIER int bitCount(detail::uint64 x) + { + return static_cast(_mm_popcnt_u64(x)); + } +# endif//GLM_MODEL +# endif//GLM_ARCH + +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/detail/func_matrix.inl b/vendor/glm/glm/detail/func_matrix.inl new file mode 100644 index 0000000..d980c6d --- /dev/null +++ b/vendor/glm/glm/detail/func_matrix.inl @@ -0,0 +1,398 @@ +#include "../geometric.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct compute_matrixCompMult + { + GLM_FUNC_QUALIFIER static mat call(mat const& x, mat const& y) + { + mat Result; + for(length_t i = 0; i < Result.length(); ++i) + Result[i] = x[i] * y[i]; + return Result; + } + }; + + template + struct compute_transpose{}; + + template + struct compute_transpose<2, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 2, T, Q> call(mat<2, 2, T, Q> const& m) + { + mat<2, 2, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + return Result; + } + }; + + template + struct compute_transpose<2, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 2, T, Q> call(mat<2, 3, T, Q> const& m) + { + mat<3,2, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + return Result; + } + }; + + template + struct compute_transpose<2, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 2, T, Q> call(mat<2, 4, T, Q> const& m) + { + mat<4, 2, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + return Result; + } + }; + + template + struct compute_transpose<3, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 3, T, Q> call(mat<3, 2, T, Q> const& m) + { + mat<2, 3, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + return Result; + } + }; + + template + struct compute_transpose<3, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m) + { + mat<3, 3, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + return Result; + } + }; + + template + struct compute_transpose<3, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 3, T, Q> call(mat<3, 4, T, Q> const& m) + { + mat<4, 3, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + Result[3][2] = m[2][3]; + return Result; + } + }; + + template + struct compute_transpose<4, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 4, T, Q> call(mat<4, 2, T, Q> const& m) + { + mat<2, 4, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + return Result; + } + }; + + template + struct compute_transpose<4, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 4, T, Q> call(mat<4, 3, T, Q> const& m) + { + mat<3, 4, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[2][3] = m[3][2]; + return Result; + } + }; + + template + struct compute_transpose<4, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 4, T, Q> call(mat<4, 4, T, Q> const& m) + { + mat<4, 4, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[2][3] = m[3][2]; + + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + Result[3][2] = m[2][3]; + Result[3][3] = m[3][3]; + return Result; + } + }; + + template + struct compute_determinant{}; + + template + struct compute_determinant<2, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static T call(mat<2, 2, T, Q> const& m) + { + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; + } + }; + + template + struct compute_determinant<3, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static T call(mat<3, 3, T, Q> const& m) + { + return + + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); + } + }; + + template + struct compute_determinant<4, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static T call(mat<4, 4, T, Q> const& m) + { + T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + vec<4, T, Q> DetCof( + + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + return + m[0][0] * DetCof[0] + m[0][1] * DetCof[1] + + m[0][2] * DetCof[2] + m[0][3] * DetCof[3]; + } + }; + + template + struct compute_inverse{}; + + template + struct compute_inverse<2, 2, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<2, 2, T, Q> call(mat<2, 2, T, Q> const& m) + { + T OneOverDeterminant = static_cast(1) / ( + + m[0][0] * m[1][1] + - m[1][0] * m[0][1]); + + mat<2, 2, T, Q> Inverse( + + m[1][1] * OneOverDeterminant, + - m[0][1] * OneOverDeterminant, + - m[1][0] * OneOverDeterminant, + + m[0][0] * OneOverDeterminant); + + return Inverse; + } + }; + + template + struct compute_inverse<3, 3, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<3, 3, T, Q> call(mat<3, 3, T, Q> const& m) + { + T OneOverDeterminant = static_cast(1) / ( + + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2])); + + mat<3, 3, T, Q> Inverse; + Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant; + Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant; + Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant; + Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant; + Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant; + + return Inverse; + } + }; + + template + struct compute_inverse<4, 4, T, Q, Aligned> + { + GLM_FUNC_QUALIFIER static mat<4, 4, T, Q> call(mat<4, 4, T, Q> const& m) + { + T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + vec<4, T, Q> Fac0(Coef00, Coef00, Coef02, Coef03); + vec<4, T, Q> Fac1(Coef04, Coef04, Coef06, Coef07); + vec<4, T, Q> Fac2(Coef08, Coef08, Coef10, Coef11); + vec<4, T, Q> Fac3(Coef12, Coef12, Coef14, Coef15); + vec<4, T, Q> Fac4(Coef16, Coef16, Coef18, Coef19); + vec<4, T, Q> Fac5(Coef20, Coef20, Coef22, Coef23); + + vec<4, T, Q> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]); + vec<4, T, Q> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]); + vec<4, T, Q> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]); + vec<4, T, Q> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]); + + vec<4, T, Q> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2); + vec<4, T, Q> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4); + vec<4, T, Q> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5); + vec<4, T, Q> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5); + + vec<4, T, Q> SignA(+1, -1, +1, -1); + vec<4, T, Q> SignB(-1, +1, -1, +1); + mat<4, 4, T, Q> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB); + + vec<4, T, Q> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]); + + vec<4, T, Q> Dot0(m[0] * Row0); + T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w); + + T OneOverDeterminant = static_cast(1) / Dot1; + + return Inverse * OneOverDeterminant; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER mat matrixCompMult(mat const& x, mat const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'matrixCompMult' only accept floating-point inputs"); + return detail::compute_matrixCompMult::value>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER typename detail::outerProduct_trait::type outerProduct(vec const& c, vec const& r) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'outerProduct' only accept floating-point inputs"); + + typename detail::outerProduct_trait::type m; + for(length_t i = 0; i < m.length(); ++i) + m[i] = c * r[i]; + return m; + } + + template + GLM_FUNC_QUALIFIER typename mat::transpose_type transpose(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'transpose' only accept floating-point inputs"); + return detail::compute_transpose::value>::call(m); + } + + template + GLM_FUNC_QUALIFIER T determinant(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'determinant' only accept floating-point inputs"); + return detail::compute_determinant::value>::call(m); + } + + template + GLM_FUNC_QUALIFIER mat inverse(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'inverse' only accept floating-point inputs"); + return detail::compute_inverse::value>::call(m); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_matrix_simd.inl" +#endif + diff --git a/vendor/glm/glm/detail/func_matrix_simd.inl b/vendor/glm/glm/detail/func_matrix_simd.inl new file mode 100644 index 0000000..f67ac66 --- /dev/null +++ b/vendor/glm/glm/detail/func_matrix_simd.inl @@ -0,0 +1,249 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#include "type_mat4x4.hpp" +#include "../geometric.hpp" +#include "../simd/matrix.h" +#include + +namespace glm{ +namespace detail +{ +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template + struct compute_matrixCompMult<4, 4, float, Q, true> + { + GLM_STATIC_ASSERT(detail::is_aligned::value, "Specialization requires aligned"); + + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& x, mat<4, 4, float, Q> const& y) + { + mat<4, 4, float, Q> Result; + glm_mat4_matrixCompMult( + *static_cast(&x[0].data), + *static_cast(&y[0].data), + *static_cast(&Result[0].data)); + return Result; + } + }; +# endif + + template + struct compute_transpose<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& m) + { + mat<4, 4, float, Q> Result; + glm_mat4_transpose(&m[0].data, &Result[0].data); + return Result; + } + }; + + template + struct compute_determinant<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static float call(mat<4, 4, float, Q> const& m) + { + return _mm_cvtss_f32(glm_mat4_determinant(&m[0].data)); + } + }; + + template + struct compute_inverse<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& m) + { + mat<4, 4, float, Q> Result; + glm_mat4_inverse(&m[0].data, &Result[0].data); + return Result; + } + }; +}//namespace detail + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<> + GLM_FUNC_QUALIFIER mat<4, 4, float, aligned_lowp> outerProduct<4, 4, float, aligned_lowp>(vec<4, float, aligned_lowp> const& c, vec<4, float, aligned_lowp> const& r) + { + __m128 NativeResult[4]; + glm_mat4_outerProduct(c.data, r.data, NativeResult); + mat<4, 4, float, aligned_lowp> Result; + std::memcpy(&Result[0], &NativeResult[0], sizeof(Result)); + return Result; + } + + template<> + GLM_FUNC_QUALIFIER mat<4, 4, float, aligned_mediump> outerProduct<4, 4, float, aligned_mediump>(vec<4, float, aligned_mediump> const& c, vec<4, float, aligned_mediump> const& r) + { + __m128 NativeResult[4]; + glm_mat4_outerProduct(c.data, r.data, NativeResult); + mat<4, 4, float, aligned_mediump> Result; + std::memcpy(&Result[0], &NativeResult[0], sizeof(Result)); + return Result; + } + + template<> + GLM_FUNC_QUALIFIER mat<4, 4, float, aligned_highp> outerProduct<4, 4, float, aligned_highp>(vec<4, float, aligned_highp> const& c, vec<4, float, aligned_highp> const& r) + { + __m128 NativeResult[4]; + glm_mat4_outerProduct(c.data, r.data, NativeResult); + mat<4, 4, float, aligned_highp> Result; + std::memcpy(&Result[0], &NativeResult[0], sizeof(Result)); + return Result; + } +# endif +}//namespace glm + +#elif GLM_ARCH & GLM_ARCH_NEON_BIT + +namespace glm { +#if GLM_LANG & GLM_LANG_CXX11_FLAG + template + GLM_FUNC_QUALIFIER + typename std::enable_if::value, mat<4, 4, float, Q>>::type + operator*(mat<4, 4, float, Q> const & m1, mat<4, 4, float, Q> const & m2) + { + auto MulRow = [&](int l) { + float32x4_t const SrcA = m2[l].data; + + float32x4_t r = neon::mul_lane(m1[0].data, SrcA, 0); + r = neon::madd_lane(r, m1[1].data, SrcA, 1); + r = neon::madd_lane(r, m1[2].data, SrcA, 2); + r = neon::madd_lane(r, m1[3].data, SrcA, 3); + + return r; + }; + + mat<4, 4, float, aligned_highp> Result; + Result[0].data = MulRow(0); + Result[1].data = MulRow(1); + Result[2].data = MulRow(2); + Result[3].data = MulRow(3); + + return Result; + } +#endif // CXX11 + + template + struct detail::compute_inverse<4, 4, float, Q, true> + { + GLM_FUNC_QUALIFIER static mat<4, 4, float, Q> call(mat<4, 4, float, Q> const& m) + { + float32x4_t const& m0 = m[0].data; + float32x4_t const& m1 = m[1].data; + float32x4_t const& m2 = m[2].data; + float32x4_t const& m3 = m[3].data; + + // m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + float32x4_t Fac0; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 2), neon::dup_lane(m1, 2)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 3), 3, m2, 3); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 2), 3, m2, 2); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 3), neon::dup_lane(m1, 3)); + Fac0 = w0 * w1 - w2 * w3; + } + + // m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + float32x4_t Fac1; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 1), neon::dup_lane(m1, 1)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 3), 3, m2, 3); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 1), 3, m2, 1); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 3), neon::dup_lane(m1, 3)); + Fac1 = w0 * w1 - w2 * w3; + } + + // m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + float32x4_t Fac2; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 1), neon::dup_lane(m1, 1)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 2), 3, m2, 2); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 1), 3, m2, 1); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 2), neon::dup_lane(m1, 2)); + Fac2 = w0 * w1 - w2 * w3; + } + + // m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + float32x4_t Fac3; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 0), neon::dup_lane(m1, 0)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 3), 3, m2, 3); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 0), 3, m2, 0); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 3), neon::dup_lane(m1, 3)); + Fac3 = w0 * w1 - w2 * w3; + } + + // m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + float32x4_t Fac4; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 0), neon::dup_lane(m1, 0)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 2), 3, m2, 2); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 0), 3, m2, 0); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 2), neon::dup_lane(m1, 2)); + Fac4 = w0 * w1 - w2 * w3; + } + + // m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + float32x4_t Fac5; + { + float32x4_t w0 = vcombine_f32(neon::dup_lane(m2, 0), neon::dup_lane(m1, 0)); + float32x4_t w1 = neon::copy_lane(neon::dupq_lane(m3, 1), 3, m2, 1); + float32x4_t w2 = neon::copy_lane(neon::dupq_lane(m3, 0), 3, m2, 0); + float32x4_t w3 = vcombine_f32(neon::dup_lane(m2, 1), neon::dup_lane(m1, 1)); + Fac5 = w0 * w1 - w2 * w3; + } + + float32x4_t Vec0 = neon::copy_lane(neon::dupq_lane(m0, 0), 0, m1, 0); // (m[1][0], m[0][0], m[0][0], m[0][0]); + float32x4_t Vec1 = neon::copy_lane(neon::dupq_lane(m0, 1), 0, m1, 1); // (m[1][1], m[0][1], m[0][1], m[0][1]); + float32x4_t Vec2 = neon::copy_lane(neon::dupq_lane(m0, 2), 0, m1, 2); // (m[1][2], m[0][2], m[0][2], m[0][2]); + float32x4_t Vec3 = neon::copy_lane(neon::dupq_lane(m0, 3), 0, m1, 3); // (m[1][3], m[0][3], m[0][3], m[0][3]); + + float32x4_t Inv0 = Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2; + float32x4_t Inv1 = Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4; + float32x4_t Inv2 = Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5; + float32x4_t Inv3 = Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5; + + float32x4_t r0 = float32x4_t{-1, +1, -1, +1} * Inv0; + float32x4_t r1 = float32x4_t{+1, -1, +1, -1} * Inv1; + float32x4_t r2 = float32x4_t{-1, +1, -1, +1} * Inv2; + float32x4_t r3 = float32x4_t{+1, -1, +1, -1} * Inv3; + + float32x4_t det = neon::mul_lane(r0, m0, 0); + det = neon::madd_lane(det, r1, m0, 1); + det = neon::madd_lane(det, r2, m0, 2); + det = neon::madd_lane(det, r3, m0, 3); + + float32x4_t rdet = vdupq_n_f32(1 / vgetq_lane_f32(det, 0)); + + mat<4, 4, float, Q> r; + r[0].data = vmulq_f32(r0, rdet); + r[1].data = vmulq_f32(r1, rdet); + r[2].data = vmulq_f32(r2, rdet); + r[3].data = vmulq_f32(r3, rdet); + return r; + } + }; +}//namespace glm +#endif diff --git a/vendor/glm/glm/detail/func_packing.inl b/vendor/glm/glm/detail/func_packing.inl new file mode 100644 index 0000000..234b093 --- /dev/null +++ b/vendor/glm/glm/detail/func_packing.inl @@ -0,0 +1,189 @@ +/// @ref core +/// @file glm/detail/func_packing.inl + +#include "../common.hpp" +#include "type_half.hpp" + +namespace glm +{ + GLM_FUNC_QUALIFIER uint packUnorm2x16(vec2 const& v) + { + union + { + unsigned short in[2]; + uint out; + } u; + + vec<2, unsigned short, defaultp> result(round(clamp(v, 0.0f, 1.0f) * 65535.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + + return u.out; + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x16(uint p) + { + union + { + uint in; + unsigned short out[2]; + } u; + + u.in = p; + + return vec2(u.out[0], u.out[1]) * 1.5259021896696421759365224689097e-5f; + } + + GLM_FUNC_QUALIFIER uint packSnorm2x16(vec2 const& v) + { + union + { + signed short in[2]; + uint out; + } u; + + vec<2, short, defaultp> result(round(clamp(v, -1.0f, 1.0f) * 32767.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + + return u.out; + } + + GLM_FUNC_QUALIFIER vec2 unpackSnorm2x16(uint p) + { + union + { + uint in; + signed short out[2]; + } u; + + u.in = p; + + return clamp(vec2(u.out[0], u.out[1]) * 3.0518509475997192297128208258309e-5f, -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint packUnorm4x8(vec4 const& v) + { + union + { + unsigned char in[4]; + uint out; + } u; + + vec<4, unsigned char, defaultp> result(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + u.in[2] = result[2]; + u.in[3] = result[3]; + + return u.out; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x8(uint p) + { + union + { + uint in; + unsigned char out[4]; + } u; + + u.in = p; + + return vec4(u.out[0], u.out[1], u.out[2], u.out[3]) * 0.0039215686274509803921568627451f; + } + + GLM_FUNC_QUALIFIER uint packSnorm4x8(vec4 const& v) + { + union + { + signed char in[4]; + uint out; + } u; + + vec<4, signed char, defaultp> result(round(clamp(v, -1.0f, 1.0f) * 127.0f)); + + u.in[0] = result[0]; + u.in[1] = result[1]; + u.in[2] = result[2]; + u.in[3] = result[3]; + + return u.out; + } + + GLM_FUNC_QUALIFIER glm::vec4 unpackSnorm4x8(uint p) + { + union + { + uint in; + signed char out[4]; + } u; + + u.in = p; + + return clamp(vec4(u.out[0], u.out[1], u.out[2], u.out[3]) * 0.0078740157480315f, -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER double packDouble2x32(uvec2 const& v) + { + union + { + uint in[2]; + double out; + } u; + + u.in[0] = v[0]; + u.in[1] = v[1]; + + return u.out; + } + + GLM_FUNC_QUALIFIER uvec2 unpackDouble2x32(double v) + { + union + { + double in; + uint out[2]; + } u; + + u.in = v; + + return uvec2(u.out[0], u.out[1]); + } + + GLM_FUNC_QUALIFIER uint packHalf2x16(vec2 const& v) + { + union + { + signed short in[2]; + uint out; + } u; + + u.in[0] = detail::toFloat16(v.x); + u.in[1] = detail::toFloat16(v.y); + + return u.out; + } + + GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint v) + { + union + { + uint in; + signed short out[2]; + } u; + + u.in = v; + + return vec2( + detail::toFloat32(u.out[0]), + detail::toFloat32(u.out[1])); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_packing_simd.inl" +#endif + diff --git a/vendor/glm/glm/detail/func_packing_simd.inl b/vendor/glm/glm/detail/func_packing_simd.inl new file mode 100644 index 0000000..fd0fe8b --- /dev/null +++ b/vendor/glm/glm/detail/func_packing_simd.inl @@ -0,0 +1,6 @@ +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm diff --git a/vendor/glm/glm/detail/func_trigonometric.inl b/vendor/glm/glm/detail/func_trigonometric.inl new file mode 100644 index 0000000..e129dce --- /dev/null +++ b/vendor/glm/glm/detail/func_trigonometric.inl @@ -0,0 +1,197 @@ +#include "_vectorize.hpp" +#include +#include + +namespace glm +{ + // radians + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType radians(genType degrees) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'radians' only accept floating-point input"); + + return degrees * static_cast(0.01745329251994329576923690768489); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec radians(vec const& v) + { + return detail::functor1::call(radians, v); + } + + // degrees + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType degrees(genType radians) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'degrees' only accept floating-point input"); + + return radians * static_cast(57.295779513082320876798154814105); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec degrees(vec const& v) + { + return detail::functor1::call(degrees, v); + } + + // sin + using ::std::sin; + + template + GLM_FUNC_QUALIFIER vec sin(vec const& v) + { + return detail::functor1::call(sin, v); + } + + // cos + using std::cos; + + template + GLM_FUNC_QUALIFIER vec cos(vec const& v) + { + return detail::functor1::call(cos, v); + } + + // tan + using std::tan; + + template + GLM_FUNC_QUALIFIER vec tan(vec const& v) + { + return detail::functor1::call(tan, v); + } + + // asin + using std::asin; + + template + GLM_FUNC_QUALIFIER vec asin(vec const& v) + { + return detail::functor1::call(asin, v); + } + + // acos + using std::acos; + + template + GLM_FUNC_QUALIFIER vec acos(vec const& v) + { + return detail::functor1::call(acos, v); + } + + // atan + template + GLM_FUNC_QUALIFIER genType atan(genType y, genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'atan' only accept floating-point input"); + + return ::std::atan2(y, x); + } + + template + GLM_FUNC_QUALIFIER vec atan(vec const& a, vec const& b) + { + return detail::functor2::call(::std::atan2, a, b); + } + + using std::atan; + + template + GLM_FUNC_QUALIFIER vec atan(vec const& v) + { + return detail::functor1::call(atan, v); + } + + // sinh + using std::sinh; + + template + GLM_FUNC_QUALIFIER vec sinh(vec const& v) + { + return detail::functor1::call(sinh, v); + } + + // cosh + using std::cosh; + + template + GLM_FUNC_QUALIFIER vec cosh(vec const& v) + { + return detail::functor1::call(cosh, v); + } + + // tanh + using std::tanh; + + template + GLM_FUNC_QUALIFIER vec tanh(vec const& v) + { + return detail::functor1::call(tanh, v); + } + + // asinh +# if GLM_HAS_CXX11_STL + using std::asinh; +# else + template + GLM_FUNC_QUALIFIER genType asinh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'asinh' only accept floating-point input"); + + return (x < static_cast(0) ? static_cast(-1) : (x > static_cast(0) ? static_cast(1) : static_cast(0))) * log(std::abs(x) + sqrt(static_cast(1) + x * x)); + } +# endif + + template + GLM_FUNC_QUALIFIER vec asinh(vec const& v) + { + return detail::functor1::call(asinh, v); + } + + // acosh +# if GLM_HAS_CXX11_STL + using std::acosh; +# else + template + GLM_FUNC_QUALIFIER genType acosh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acosh' only accept floating-point input"); + + if(x < static_cast(1)) + return static_cast(0); + return log(x + sqrt(x * x - static_cast(1))); + } +# endif + + template + GLM_FUNC_QUALIFIER vec acosh(vec const& v) + { + return detail::functor1::call(acosh, v); + } + + // atanh +# if GLM_HAS_CXX11_STL + using std::atanh; +# else + template + GLM_FUNC_QUALIFIER genType atanh(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'atanh' only accept floating-point input"); + + if(std::abs(x) >= static_cast(1)) + return 0; + return static_cast(0.5) * log((static_cast(1) + x) / (static_cast(1) - x)); + } +# endif + + template + GLM_FUNC_QUALIFIER vec atanh(vec const& v) + { + return detail::functor1::call(atanh, v); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_trigonometric_simd.inl" +#endif + diff --git a/vendor/glm/glm/detail/func_trigonometric_simd.inl b/vendor/glm/glm/detail/func_trigonometric_simd.inl new file mode 100644 index 0000000..e69de29 diff --git a/vendor/glm/glm/detail/func_vector_relational.inl b/vendor/glm/glm/detail/func_vector_relational.inl new file mode 100644 index 0000000..80c9e87 --- /dev/null +++ b/vendor/glm/glm/detail/func_vector_relational.inl @@ -0,0 +1,87 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec lessThan(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] < y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec lessThanEqual(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec greaterThan(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec greaterThanEqual(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] >= y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] == y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = x[i] != y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool any(vec const& v) + { + bool Result = false; + for(length_t i = 0; i < L; ++i) + Result = Result || v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool all(vec const& v) + { + bool Result = true; + for(length_t i = 0; i < L; ++i) + Result = Result && v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec not_(vec const& v) + { + vec Result(true); + for(length_t i = 0; i < L; ++i) + Result[i] = !v[i]; + return Result; + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_vector_relational_simd.inl" +#endif diff --git a/vendor/glm/glm/detail/func_vector_relational_simd.inl b/vendor/glm/glm/detail/func_vector_relational_simd.inl new file mode 100644 index 0000000..fd0fe8b --- /dev/null +++ b/vendor/glm/glm/detail/func_vector_relational_simd.inl @@ -0,0 +1,6 @@ +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm diff --git a/vendor/glm/glm/detail/glm.cpp b/vendor/glm/glm/detail/glm.cpp new file mode 100644 index 0000000..e0755bd --- /dev/null +++ b/vendor/glm/glm/detail/glm.cpp @@ -0,0 +1,263 @@ +/// @ref core +/// @file glm/glm.cpp + +#ifndef GLM_ENABLE_EXPERIMENTAL +#define GLM_ENABLE_EXPERIMENTAL +#endif +#include +#include +#include +#include +#include +#include + +namespace glm +{ +// tvec1 type explicit instantiation +template struct vec<1, uint8, lowp>; +template struct vec<1, uint16, lowp>; +template struct vec<1, uint32, lowp>; +template struct vec<1, uint64, lowp>; +template struct vec<1, int8, lowp>; +template struct vec<1, int16, lowp>; +template struct vec<1, int32, lowp>; +template struct vec<1, int64, lowp>; +template struct vec<1, float32, lowp>; +template struct vec<1, float64, lowp>; + +template struct vec<1, uint8, mediump>; +template struct vec<1, uint16, mediump>; +template struct vec<1, uint32, mediump>; +template struct vec<1, uint64, mediump>; +template struct vec<1, int8, mediump>; +template struct vec<1, int16, mediump>; +template struct vec<1, int32, mediump>; +template struct vec<1, int64, mediump>; +template struct vec<1, float32, mediump>; +template struct vec<1, float64, mediump>; + +template struct vec<1, uint8, highp>; +template struct vec<1, uint16, highp>; +template struct vec<1, uint32, highp>; +template struct vec<1, uint64, highp>; +template struct vec<1, int8, highp>; +template struct vec<1, int16, highp>; +template struct vec<1, int32, highp>; +template struct vec<1, int64, highp>; +template struct vec<1, float32, highp>; +template struct vec<1, float64, highp>; + +// tvec2 type explicit instantiation +template struct vec<2, uint8, lowp>; +template struct vec<2, uint16, lowp>; +template struct vec<2, uint32, lowp>; +template struct vec<2, uint64, lowp>; +template struct vec<2, int8, lowp>; +template struct vec<2, int16, lowp>; +template struct vec<2, int32, lowp>; +template struct vec<2, int64, lowp>; +template struct vec<2, float32, lowp>; +template struct vec<2, float64, lowp>; + +template struct vec<2, uint8, mediump>; +template struct vec<2, uint16, mediump>; +template struct vec<2, uint32, mediump>; +template struct vec<2, uint64, mediump>; +template struct vec<2, int8, mediump>; +template struct vec<2, int16, mediump>; +template struct vec<2, int32, mediump>; +template struct vec<2, int64, mediump>; +template struct vec<2, float32, mediump>; +template struct vec<2, float64, mediump>; + +template struct vec<2, uint8, highp>; +template struct vec<2, uint16, highp>; +template struct vec<2, uint32, highp>; +template struct vec<2, uint64, highp>; +template struct vec<2, int8, highp>; +template struct vec<2, int16, highp>; +template struct vec<2, int32, highp>; +template struct vec<2, int64, highp>; +template struct vec<2, float32, highp>; +template struct vec<2, float64, highp>; + +// tvec3 type explicit instantiation +template struct vec<3, uint8, lowp>; +template struct vec<3, uint16, lowp>; +template struct vec<3, uint32, lowp>; +template struct vec<3, uint64, lowp>; +template struct vec<3, int8, lowp>; +template struct vec<3, int16, lowp>; +template struct vec<3, int32, lowp>; +template struct vec<3, int64, lowp>; +template struct vec<3, float32, lowp>; +template struct vec<3, float64, lowp>; + +template struct vec<3, uint8, mediump>; +template struct vec<3, uint16, mediump>; +template struct vec<3, uint32, mediump>; +template struct vec<3, uint64, mediump>; +template struct vec<3, int8, mediump>; +template struct vec<3, int16, mediump>; +template struct vec<3, int32, mediump>; +template struct vec<3, int64, mediump>; +template struct vec<3, float32, mediump>; +template struct vec<3, float64, mediump>; + +template struct vec<3, uint8, highp>; +template struct vec<3, uint16, highp>; +template struct vec<3, uint32, highp>; +template struct vec<3, uint64, highp>; +template struct vec<3, int8, highp>; +template struct vec<3, int16, highp>; +template struct vec<3, int32, highp>; +template struct vec<3, int64, highp>; +template struct vec<3, float32, highp>; +template struct vec<3, float64, highp>; + +// tvec4 type explicit instantiation +template struct vec<4, uint8, lowp>; +template struct vec<4, uint16, lowp>; +template struct vec<4, uint32, lowp>; +template struct vec<4, uint64, lowp>; +template struct vec<4, int8, lowp>; +template struct vec<4, int16, lowp>; +template struct vec<4, int32, lowp>; +template struct vec<4, int64, lowp>; +template struct vec<4, float32, lowp>; +template struct vec<4, float64, lowp>; + +template struct vec<4, uint8, mediump>; +template struct vec<4, uint16, mediump>; +template struct vec<4, uint32, mediump>; +template struct vec<4, uint64, mediump>; +template struct vec<4, int8, mediump>; +template struct vec<4, int16, mediump>; +template struct vec<4, int32, mediump>; +template struct vec<4, int64, mediump>; +template struct vec<4, float32, mediump>; +template struct vec<4, float64, mediump>; + +template struct vec<4, uint8, highp>; +template struct vec<4, uint16, highp>; +template struct vec<4, uint32, highp>; +template struct vec<4, uint64, highp>; +template struct vec<4, int8, highp>; +template struct vec<4, int16, highp>; +template struct vec<4, int32, highp>; +template struct vec<4, int64, highp>; +template struct vec<4, float32, highp>; +template struct vec<4, float64, highp>; + +// tmat2x2 type explicit instantiation +template struct mat<2, 2, float32, lowp>; +template struct mat<2, 2, float64, lowp>; + +template struct mat<2, 2, float32, mediump>; +template struct mat<2, 2, float64, mediump>; + +template struct mat<2, 2, float32, highp>; +template struct mat<2, 2, float64, highp>; + +// tmat2x3 type explicit instantiation +template struct mat<2, 3, float32, lowp>; +template struct mat<2, 3, float64, lowp>; + +template struct mat<2, 3, float32, mediump>; +template struct mat<2, 3, float64, mediump>; + +template struct mat<2, 3, float32, highp>; +template struct mat<2, 3, float64, highp>; + +// tmat2x4 type explicit instantiation +template struct mat<2, 4, float32, lowp>; +template struct mat<2, 4, float64, lowp>; + +template struct mat<2, 4, float32, mediump>; +template struct mat<2, 4, float64, mediump>; + +template struct mat<2, 4, float32, highp>; +template struct mat<2, 4, float64, highp>; + +// tmat3x2 type explicit instantiation +template struct mat<3, 2, float32, lowp>; +template struct mat<3, 2, float64, lowp>; + +template struct mat<3, 2, float32, mediump>; +template struct mat<3, 2, float64, mediump>; + +template struct mat<3, 2, float32, highp>; +template struct mat<3, 2, float64, highp>; + +// tmat3x3 type explicit instantiation +template struct mat<3, 3, float32, lowp>; +template struct mat<3, 3, float64, lowp>; + +template struct mat<3, 3, float32, mediump>; +template struct mat<3, 3, float64, mediump>; + +template struct mat<3, 3, float32, highp>; +template struct mat<3, 3, float64, highp>; + +// tmat3x4 type explicit instantiation +template struct mat<3, 4, float32, lowp>; +template struct mat<3, 4, float64, lowp>; + +template struct mat<3, 4, float32, mediump>; +template struct mat<3, 4, float64, mediump>; + +template struct mat<3, 4, float32, highp>; +template struct mat<3, 4, float64, highp>; + +// tmat4x2 type explicit instantiation +template struct mat<4, 2, float32, lowp>; +template struct mat<4, 2, float64, lowp>; + +template struct mat<4, 2, float32, mediump>; +template struct mat<4, 2, float64, mediump>; + +template struct mat<4, 2, float32, highp>; +template struct mat<4, 2, float64, highp>; + +// tmat4x3 type explicit instantiation +template struct mat<4, 3, float32, lowp>; +template struct mat<4, 3, float64, lowp>; + +template struct mat<4, 3, float32, mediump>; +template struct mat<4, 3, float64, mediump>; + +template struct mat<4, 3, float32, highp>; +template struct mat<4, 3, float64, highp>; + +// tmat4x4 type explicit instantiation +template struct mat<4, 4, float32, lowp>; +template struct mat<4, 4, float64, lowp>; + +template struct mat<4, 4, float32, mediump>; +template struct mat<4, 4, float64, mediump>; + +template struct mat<4, 4, float32, highp>; +template struct mat<4, 4, float64, highp>; + +// tquat type explicit instantiation +template struct qua; +template struct qua; + +template struct qua; +template struct qua; + +template struct qua; +template struct qua; + +//tdualquat type explicit instantiation +template struct tdualquat; +template struct tdualquat; + +template struct tdualquat; +template struct tdualquat; + +template struct tdualquat; +template struct tdualquat; + +}//namespace glm + diff --git a/vendor/glm/glm/detail/qualifier.hpp b/vendor/glm/glm/detail/qualifier.hpp new file mode 100644 index 0000000..b6c9df0 --- /dev/null +++ b/vendor/glm/glm/detail/qualifier.hpp @@ -0,0 +1,230 @@ +#pragma once + +#include "setup.hpp" + +namespace glm +{ + /// Qualify GLM types in term of alignment (packed, aligned) and precision in term of ULPs (lowp, mediump, highp) + enum qualifier + { + packed_highp, ///< Typed data is tightly packed in memory and operations are executed with high precision in term of ULPs + packed_mediump, ///< Typed data is tightly packed in memory and operations are executed with medium precision in term of ULPs for higher performance + packed_lowp, ///< Typed data is tightly packed in memory and operations are executed with low precision in term of ULPs to maximize performance + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + aligned_highp, ///< Typed data is aligned in memory allowing SIMD optimizations and operations are executed with high precision in term of ULPs + aligned_mediump, ///< Typed data is aligned in memory allowing SIMD optimizations and operations are executed with high precision in term of ULPs for higher performance + aligned_lowp, // ///< Typed data is aligned in memory allowing SIMD optimizations and operations are executed with high precision in term of ULPs to maximize performance + aligned = aligned_highp, ///< By default aligned qualifier is also high precision +# endif + + highp = packed_highp, ///< By default highp qualifier is also packed + mediump = packed_mediump, ///< By default mediump qualifier is also packed + lowp = packed_lowp, ///< By default lowp qualifier is also packed + packed = packed_highp, ///< By default packed qualifier is also high precision + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE && defined(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES) + defaultp = aligned_highp +# else + defaultp = highp +# endif + }; + + typedef qualifier precision; + + template struct vec; + template struct mat; + template struct qua; + +# if GLM_HAS_TEMPLATE_ALIASES + template using tvec1 = vec<1, T, Q>; + template using tvec2 = vec<2, T, Q>; + template using tvec3 = vec<3, T, Q>; + template using tvec4 = vec<4, T, Q>; + template using tmat2x2 = mat<2, 2, T, Q>; + template using tmat2x3 = mat<2, 3, T, Q>; + template using tmat2x4 = mat<2, 4, T, Q>; + template using tmat3x2 = mat<3, 2, T, Q>; + template using tmat3x3 = mat<3, 3, T, Q>; + template using tmat3x4 = mat<3, 4, T, Q>; + template using tmat4x2 = mat<4, 2, T, Q>; + template using tmat4x3 = mat<4, 3, T, Q>; + template using tmat4x4 = mat<4, 4, T, Q>; + template using tquat = qua; +# endif + +namespace detail +{ + template + struct is_aligned + { + static const bool value = false; + }; + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + template<> + struct is_aligned + { + static const bool value = true; + }; + + template<> + struct is_aligned + { + static const bool value = true; + }; + + template<> + struct is_aligned + { + static const bool value = true; + }; +# endif + + template + struct storage + { + typedef struct type { + T data[L]; + } type; + }; + +# if GLM_HAS_ALIGNOF + template + struct storage + { + typedef struct alignas(L * sizeof(T)) type { + T data[L]; + } type; + }; + + template + struct storage<3, T, true> + { + typedef struct alignas(4 * sizeof(T)) type { + T data[4]; + } type; + }; +# endif + +# if GLM_ARCH & GLM_ARCH_SSE2_BIT + template<> + struct storage<4, float, true> + { + typedef glm_f32vec4 type; + }; + + template<> + struct storage<4, int, true> + { + typedef glm_i32vec4 type; + }; + + template<> + struct storage<4, unsigned int, true> + { + typedef glm_u32vec4 type; + }; + + template<> + struct storage<2, double, true> + { + typedef glm_f64vec2 type; + }; + + template<> + struct storage<2, detail::int64, true> + { + typedef glm_i64vec2 type; + }; + + template<> + struct storage<2, detail::uint64, true> + { + typedef glm_u64vec2 type; + }; +# endif + +# if (GLM_ARCH & GLM_ARCH_AVX_BIT) + template<> + struct storage<4, double, true> + { + typedef glm_f64vec4 type; + }; +# endif + +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) + template<> + struct storage<4, detail::int64, true> + { + typedef glm_i64vec4 type; + }; + + template<> + struct storage<4, detail::uint64, true> + { + typedef glm_u64vec4 type; + }; +# endif + +# if GLM_ARCH & GLM_ARCH_NEON_BIT + template<> + struct storage<4, float, true> + { + typedef glm_f32vec4 type; + }; + + template<> + struct storage<4, int, true> + { + typedef glm_i32vec4 type; + }; + + template<> + struct storage<4, unsigned int, true> + { + typedef glm_u32vec4 type; + }; +# endif + + enum genTypeEnum + { + GENTYPE_VEC, + GENTYPE_MAT, + GENTYPE_QUAT + }; + + template + struct genTypeTrait + {}; + + template + struct genTypeTrait > + { + static const genTypeEnum GENTYPE = GENTYPE_MAT; + }; + + template + struct init_gentype + { + }; + + template + struct init_gentype + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genType identity() + { + return genType(1, 0, 0, 0); + } + }; + + template + struct init_gentype + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static genType identity() + { + return genType(1); + } + }; +}//namespace detail +}//namespace glm diff --git a/vendor/glm/glm/detail/setup.hpp b/vendor/glm/glm/detail/setup.hpp new file mode 100644 index 0000000..2c01e02 --- /dev/null +++ b/vendor/glm/glm/detail/setup.hpp @@ -0,0 +1,1135 @@ +#ifndef GLM_SETUP_INCLUDED + +#include +#include + +#define GLM_VERSION_MAJOR 0 +#define GLM_VERSION_MINOR 9 +#define GLM_VERSION_PATCH 9 +#define GLM_VERSION_REVISION 8 +#define GLM_VERSION 998 +#define GLM_VERSION_MESSAGE "GLM: version 0.9.9.8" + +#define GLM_SETUP_INCLUDED GLM_VERSION + +/////////////////////////////////////////////////////////////////////////////////// +// Active states + +#define GLM_DISABLE 0 +#define GLM_ENABLE 1 + +/////////////////////////////////////////////////////////////////////////////////// +// Messages + +#if defined(GLM_FORCE_MESSAGES) +# define GLM_MESSAGES GLM_ENABLE +#else +# define GLM_MESSAGES GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Detect the platform + +#include "../simd/platform.h" + +/////////////////////////////////////////////////////////////////////////////////// +// Build model + +#if defined(_M_ARM64) || defined(__LP64__) || defined(_M_X64) || defined(__ppc64__) || defined(__x86_64__) +# define GLM_MODEL GLM_MODEL_64 +#elif defined(__i386__) || defined(__ppc__) || defined(__ILP32__) || defined(_M_ARM) +# define GLM_MODEL GLM_MODEL_32 +#else +# define GLM_MODEL GLM_MODEL_32 +#endif// + +#if !defined(GLM_MODEL) && GLM_COMPILER != 0 +# error "GLM_MODEL undefined, your compiler may not be supported by GLM. Add #define GLM_MODEL 0 to ignore this message." +#endif//GLM_MODEL + +/////////////////////////////////////////////////////////////////////////////////// +// C++ Version + +// User defines: GLM_FORCE_CXX98, GLM_FORCE_CXX03, GLM_FORCE_CXX11, GLM_FORCE_CXX14, GLM_FORCE_CXX17, GLM_FORCE_CXX2A + +#define GLM_LANG_CXX98_FLAG (1 << 1) +#define GLM_LANG_CXX03_FLAG (1 << 2) +#define GLM_LANG_CXX0X_FLAG (1 << 3) +#define GLM_LANG_CXX11_FLAG (1 << 4) +#define GLM_LANG_CXX14_FLAG (1 << 5) +#define GLM_LANG_CXX17_FLAG (1 << 6) +#define GLM_LANG_CXX2A_FLAG (1 << 7) +#define GLM_LANG_CXXMS_FLAG (1 << 8) +#define GLM_LANG_CXXGNU_FLAG (1 << 9) + +#define GLM_LANG_CXX98 GLM_LANG_CXX98_FLAG +#define GLM_LANG_CXX03 (GLM_LANG_CXX98 | GLM_LANG_CXX03_FLAG) +#define GLM_LANG_CXX0X (GLM_LANG_CXX03 | GLM_LANG_CXX0X_FLAG) +#define GLM_LANG_CXX11 (GLM_LANG_CXX0X | GLM_LANG_CXX11_FLAG) +#define GLM_LANG_CXX14 (GLM_LANG_CXX11 | GLM_LANG_CXX14_FLAG) +#define GLM_LANG_CXX17 (GLM_LANG_CXX14 | GLM_LANG_CXX17_FLAG) +#define GLM_LANG_CXX2A (GLM_LANG_CXX17 | GLM_LANG_CXX2A_FLAG) +#define GLM_LANG_CXXMS GLM_LANG_CXXMS_FLAG +#define GLM_LANG_CXXGNU GLM_LANG_CXXGNU_FLAG + +#if (defined(_MSC_EXTENSIONS)) +# define GLM_LANG_EXT GLM_LANG_CXXMS_FLAG +#elif ((GLM_COMPILER & (GLM_COMPILER_CLANG | GLM_COMPILER_GCC)) && (GLM_ARCH & GLM_ARCH_SIMD_BIT)) +# define GLM_LANG_EXT GLM_LANG_CXXMS_FLAG +#else +# define GLM_LANG_EXT 0 +#endif + +#if (defined(GLM_FORCE_CXX_UNKNOWN)) +# define GLM_LANG 0 +#elif defined(GLM_FORCE_CXX2A) +# define GLM_LANG (GLM_LANG_CXX2A | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX17) +# define GLM_LANG (GLM_LANG_CXX17 | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX14) +# define GLM_LANG (GLM_LANG_CXX14 | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX11) +# define GLM_LANG (GLM_LANG_CXX11 | GLM_LANG_EXT) +# define GLM_LANG_STL11_FORCED +#elif defined(GLM_FORCE_CXX03) +# define GLM_LANG (GLM_LANG_CXX03 | GLM_LANG_EXT) +#elif defined(GLM_FORCE_CXX98) +# define GLM_LANG (GLM_LANG_CXX98 | GLM_LANG_EXT) +#else +# if GLM_COMPILER & GLM_COMPILER_VC && defined(_MSVC_LANG) +# if GLM_COMPILER >= GLM_COMPILER_VC15_7 +# define GLM_LANG_PLATFORM _MSVC_LANG +# elif GLM_COMPILER >= GLM_COMPILER_VC15 +# if _MSVC_LANG > 201402L +# define GLM_LANG_PLATFORM 201402L +# else +# define GLM_LANG_PLATFORM _MSVC_LANG +# endif +# else +# define GLM_LANG_PLATFORM 0 +# endif +# else +# define GLM_LANG_PLATFORM 0 +# endif + +# if __cplusplus > 201703L || GLM_LANG_PLATFORM > 201703L +# define GLM_LANG (GLM_LANG_CXX2A | GLM_LANG_EXT) +# elif __cplusplus == 201703L || GLM_LANG_PLATFORM == 201703L +# define GLM_LANG (GLM_LANG_CXX17 | GLM_LANG_EXT) +# elif __cplusplus == 201402L || __cplusplus == 201500L || GLM_LANG_PLATFORM == 201402L +# define GLM_LANG (GLM_LANG_CXX14 | GLM_LANG_EXT) +# elif __cplusplus == 201103L || GLM_LANG_PLATFORM == 201103L +# define GLM_LANG (GLM_LANG_CXX11 | GLM_LANG_EXT) +# elif defined(__INTEL_CXX11_MODE__) || defined(_MSC_VER) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define GLM_LANG (GLM_LANG_CXX0X | GLM_LANG_EXT) +# elif __cplusplus == 199711L +# define GLM_LANG (GLM_LANG_CXX98 | GLM_LANG_EXT) +# else +# define GLM_LANG (0 | GLM_LANG_EXT) +# endif +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Has of C++ features + +// http://clang.llvm.org/cxx_status.html +// http://gcc.gnu.org/projects/cxx0x.html +// http://msdn.microsoft.com/en-us/library/vstudio/hh567368(v=vs.120).aspx + +// Android has multiple STLs but C++11 STL detection doesn't always work #284 #564 +#if GLM_PLATFORM == GLM_PLATFORM_ANDROID && !defined(GLM_LANG_STL11_FORCED) +# define GLM_HAS_CXX11_STL 0 +#elif GLM_COMPILER & GLM_COMPILER_CLANG +# if (defined(_LIBCPP_VERSION) || (GLM_LANG & GLM_LANG_CXX11_FLAG) || defined(GLM_LANG_STL11_FORCED)) +# define GLM_HAS_CXX11_STL 1 +# else +# define GLM_HAS_CXX11_STL 0 +# endif +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_CXX11_STL 1 +#else +# define GLM_HAS_CXX11_STL ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC48)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_PLATFORM != GLM_PLATFORM_WINDOWS) && (GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL15)))) +#endif + +// N1720 +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_STATIC_ASSERT __has_feature(cxx_static_assert) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_STATIC_ASSERT 1 +#else +# define GLM_HAS_STATIC_ASSERT ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC)))) +#endif + +// N1988 +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_EXTENDED_INTEGER_TYPE 1 +#else +# define GLM_HAS_EXTENDED_INTEGER_TYPE (\ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_VC)) || \ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_CUDA)) || \ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_CLANG))) +#endif + +// N2672 Initializer lists http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_INITIALIZER_LISTS __has_feature(cxx_generalized_initializers) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_INITIALIZER_LISTS 1 +#else +# define GLM_HAS_INITIALIZER_LISTS ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC15)) || \ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL14)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)))) +#endif + +// N2544 Unrestricted unions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_UNRESTRICTED_UNIONS __has_feature(cxx_unrestricted_unions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_UNRESTRICTED_UNIONS 1 +#else +# define GLM_HAS_UNRESTRICTED_UNIONS (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + (GLM_COMPILER & GLM_COMPILER_VC) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA))) +#endif + +// N2346 +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_DEFAULTED_FUNCTIONS __has_feature(cxx_defaulted_functions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_DEFAULTED_FUNCTIONS 1 +#else +# define GLM_HAS_DEFAULTED_FUNCTIONS ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + (GLM_COMPILER & GLM_COMPILER_CUDA))) +#endif + +// N2118 +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_RVALUE_REFERENCES __has_feature(cxx_rvalue_references) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_RVALUE_REFERENCES 1 +#else +# define GLM_HAS_RVALUE_REFERENCES ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)))) +#endif + +// N2437 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS __has_feature(cxx_explicit_conversions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS 1 +#else +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL14)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)))) +#endif + +// N2258 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_TEMPLATE_ALIASES __has_feature(cxx_alias_templates) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_TEMPLATE_ALIASES 1 +#else +# define GLM_HAS_TEMPLATE_ALIASES ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)))) +#endif + +// N2930 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2930.html +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_RANGE_FOR __has_feature(cxx_range_for) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_RANGE_FOR 1 +#else +# define GLM_HAS_RANGE_FOR ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)))) +#endif + +// N2341 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf +#if GLM_COMPILER & GLM_COMPILER_CLANG +# define GLM_HAS_ALIGNOF __has_feature(cxx_alignas) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_ALIGNOF 1 +#else +# define GLM_HAS_ALIGNOF ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL15)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC14)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)))) +#endif + +// N2235 Generalized Constant Expressions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf +// N3652 Extended Constant Expressions http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3652.html +#if (GLM_ARCH & GLM_ARCH_SIMD_BIT) // Compiler SIMD intrinsics don't support constexpr... +# define GLM_HAS_CONSTEXPR 0 +#elif (GLM_COMPILER & GLM_COMPILER_CLANG) +# define GLM_HAS_CONSTEXPR __has_feature(cxx_relaxed_constexpr) +#elif (GLM_LANG & GLM_LANG_CXX14_FLAG) +# define GLM_HAS_CONSTEXPR 1 +#else +# define GLM_HAS_CONSTEXPR ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && GLM_HAS_INITIALIZER_LISTS && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL17)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC15)))) +#endif + +#if GLM_HAS_CONSTEXPR +# define GLM_CONSTEXPR constexpr +#else +# define GLM_CONSTEXPR +#endif + +// +#if GLM_HAS_CONSTEXPR +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# if __has_feature(cxx_if_constexpr) +# define GLM_HAS_IF_CONSTEXPR 1 +# else +# define GLM_HAS_IF_CONSTEXPR 0 +# endif +# elif (GLM_LANG & GLM_LANG_CXX17_FLAG) +# define GLM_HAS_IF_CONSTEXPR 1 +# else +# define GLM_HAS_IF_CONSTEXPR 0 +# endif +#else +# define GLM_HAS_IF_CONSTEXPR 0 +#endif + +#if GLM_HAS_IF_CONSTEXPR +# define GLM_IF_CONSTEXPR if constexpr +#else +# define GLM_IF_CONSTEXPR if +#endif + +// +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_ASSIGNABLE 1 +#else +# define GLM_HAS_ASSIGNABLE ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC15)) || \ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC49)))) +#endif + +// +#define GLM_HAS_TRIVIAL_QUERIES 0 + +// +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_MAKE_SIGNED 1 +#else +# define GLM_HAS_MAKE_SIGNED ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC12)) || \ + ((GLM_COMPILER & GLM_COMPILER_CUDA)))) +#endif + +// +#if defined(GLM_FORCE_INTRINSICS) +# define GLM_HAS_BITSCAN_WINDOWS ((GLM_PLATFORM & GLM_PLATFORM_WINDOWS) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC14) && (GLM_ARCH & GLM_ARCH_X86_BIT)))) +#else +# define GLM_HAS_BITSCAN_WINDOWS 0 +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// OpenMP +#ifdef _OPENMP +# if GLM_COMPILER & GLM_COMPILER_GCC +# if GLM_COMPILER >= GLM_COMPILER_GCC61 +# define GLM_HAS_OPENMP 45 +# elif GLM_COMPILER >= GLM_COMPILER_GCC49 +# define GLM_HAS_OPENMP 40 +# elif GLM_COMPILER >= GLM_COMPILER_GCC47 +# define GLM_HAS_OPENMP 31 +# else +# define GLM_HAS_OPENMP 0 +# endif +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# if GLM_COMPILER >= GLM_COMPILER_CLANG38 +# define GLM_HAS_OPENMP 31 +# else +# define GLM_HAS_OPENMP 0 +# endif +# elif GLM_COMPILER & GLM_COMPILER_VC +# define GLM_HAS_OPENMP 20 +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# if GLM_COMPILER >= GLM_COMPILER_INTEL16 +# define GLM_HAS_OPENMP 40 +# else +# define GLM_HAS_OPENMP 0 +# endif +# else +# define GLM_HAS_OPENMP 0 +# endif +#else +# define GLM_HAS_OPENMP 0 +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// nullptr + +#if GLM_LANG & GLM_LANG_CXX0X_FLAG +# define GLM_CONFIG_NULLPTR GLM_ENABLE +#else +# define GLM_CONFIG_NULLPTR GLM_DISABLE +#endif + +#if GLM_CONFIG_NULLPTR == GLM_ENABLE +# define GLM_NULLPTR nullptr +#else +# define GLM_NULLPTR 0 +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Static assert + +#if GLM_HAS_STATIC_ASSERT +# define GLM_STATIC_ASSERT(x, message) static_assert(x, message) +#elif GLM_COMPILER & GLM_COMPILER_VC +# define GLM_STATIC_ASSERT(x, message) typedef char __CASSERT__##__LINE__[(x) ? 1 : -1] +#else +# define GLM_STATIC_ASSERT(x, message) assert(x) +#endif//GLM_LANG + +/////////////////////////////////////////////////////////////////////////////////// +// Qualifiers + +#if GLM_COMPILER & GLM_COMPILER_CUDA +# define GLM_CUDA_FUNC_DEF __device__ __host__ +# define GLM_CUDA_FUNC_DECL __device__ __host__ +#else +# define GLM_CUDA_FUNC_DEF +# define GLM_CUDA_FUNC_DECL +#endif + +#if defined(GLM_FORCE_INLINE) +# if GLM_COMPILER & GLM_COMPILER_VC +# define GLM_INLINE __forceinline +# define GLM_NEVER_INLINE __declspec((noinline)) +# elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG) +# define GLM_INLINE inline __attribute__((__always_inline__)) +# define GLM_NEVER_INLINE __attribute__((__noinline__)) +# elif GLM_COMPILER & GLM_COMPILER_CUDA +# define GLM_INLINE __forceinline__ +# define GLM_NEVER_INLINE __noinline__ +# else +# define GLM_INLINE inline +# define GLM_NEVER_INLINE +# endif//GLM_COMPILER +#else +# define GLM_INLINE inline +# define GLM_NEVER_INLINE +#endif//defined(GLM_FORCE_INLINE) + +#define GLM_FUNC_DECL GLM_CUDA_FUNC_DECL +#define GLM_FUNC_QUALIFIER GLM_CUDA_FUNC_DEF GLM_INLINE + +/////////////////////////////////////////////////////////////////////////////////// +// Swizzle operators + +// User defines: GLM_FORCE_SWIZZLE + +#define GLM_SWIZZLE_DISABLED 0 +#define GLM_SWIZZLE_OPERATOR 1 +#define GLM_SWIZZLE_FUNCTION 2 + +#if defined(GLM_FORCE_XYZW_ONLY) +# undef GLM_FORCE_SWIZZLE +#endif + +#if defined(GLM_SWIZZLE) +# pragma message("GLM: GLM_SWIZZLE is deprecated, use GLM_FORCE_SWIZZLE instead.") +# define GLM_FORCE_SWIZZLE +#endif + +#if defined(GLM_FORCE_SWIZZLE) && (GLM_LANG & GLM_LANG_CXXMS_FLAG) +# define GLM_CONFIG_SWIZZLE GLM_SWIZZLE_OPERATOR +#elif defined(GLM_FORCE_SWIZZLE) +# define GLM_CONFIG_SWIZZLE GLM_SWIZZLE_FUNCTION +#else +# define GLM_CONFIG_SWIZZLE GLM_SWIZZLE_DISABLED +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Allows using not basic types as genType + +// #define GLM_FORCE_UNRESTRICTED_GENTYPE + +#ifdef GLM_FORCE_UNRESTRICTED_GENTYPE +# define GLM_CONFIG_UNRESTRICTED_GENTYPE GLM_ENABLE +#else +# define GLM_CONFIG_UNRESTRICTED_GENTYPE GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Clip control, define GLM_FORCE_DEPTH_ZERO_TO_ONE before including GLM +// to use a clip space between 0 to 1. +// Coordinate system, define GLM_FORCE_LEFT_HANDED before including GLM +// to use left handed coordinate system by default. + +#define GLM_CLIP_CONTROL_ZO_BIT (1 << 0) // ZERO_TO_ONE +#define GLM_CLIP_CONTROL_NO_BIT (1 << 1) // NEGATIVE_ONE_TO_ONE +#define GLM_CLIP_CONTROL_LH_BIT (1 << 2) // LEFT_HANDED, For DirectX, Metal, Vulkan +#define GLM_CLIP_CONTROL_RH_BIT (1 << 3) // RIGHT_HANDED, For OpenGL, default in GLM + +#define GLM_CLIP_CONTROL_LH_ZO (GLM_CLIP_CONTROL_LH_BIT | GLM_CLIP_CONTROL_ZO_BIT) +#define GLM_CLIP_CONTROL_LH_NO (GLM_CLIP_CONTROL_LH_BIT | GLM_CLIP_CONTROL_NO_BIT) +#define GLM_CLIP_CONTROL_RH_ZO (GLM_CLIP_CONTROL_RH_BIT | GLM_CLIP_CONTROL_ZO_BIT) +#define GLM_CLIP_CONTROL_RH_NO (GLM_CLIP_CONTROL_RH_BIT | GLM_CLIP_CONTROL_NO_BIT) + +#ifdef GLM_FORCE_DEPTH_ZERO_TO_ONE +# ifdef GLM_FORCE_LEFT_HANDED +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_LH_ZO +# else +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_RH_ZO +# endif +#else +# ifdef GLM_FORCE_LEFT_HANDED +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_LH_NO +# else +# define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_RH_NO +# endif +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Qualifiers + +#if (GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)) +# define GLM_DEPRECATED __declspec(deprecated) +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef __declspec(align(alignment)) type name +#elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_CLANG | GLM_COMPILER_INTEL) +# define GLM_DEPRECATED __attribute__((__deprecated__)) +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name __attribute__((aligned(alignment))) +#elif GLM_COMPILER & GLM_COMPILER_CUDA +# define GLM_DEPRECATED +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name __align__(x) +#else +# define GLM_DEPRECATED +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name +#endif + +/////////////////////////////////////////////////////////////////////////////////// + +#ifdef GLM_FORCE_EXPLICIT_CTOR +# define GLM_EXPLICIT explicit +#else +# define GLM_EXPLICIT +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// SYCL + +#if GLM_COMPILER==GLM_COMPILER_SYCL + +#include +#include + +namespace glm { +namespace std { + // Import SYCL's functions into the namespace glm::std to force their usages. + // It's important to use the math built-in function (sin, exp, ...) + // of SYCL instead the std ones. + using namespace cl::sycl; + + /////////////////////////////////////////////////////////////////////////////// + // Import some "harmless" std's stuffs used by glm into + // the new glm::std namespace. + template + using numeric_limits = ::std::numeric_limits; + + using ::std::size_t; + + using ::std::uint8_t; + using ::std::uint16_t; + using ::std::uint32_t; + using ::std::uint64_t; + + using ::std::int8_t; + using ::std::int16_t; + using ::std::int32_t; + using ::std::int64_t; + + using ::std::make_unsigned; + /////////////////////////////////////////////////////////////////////////////// +} //namespace std +} //namespace glm + +#endif + +/////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////// +// Length type: all length functions returns a length_t type. +// When GLM_FORCE_SIZE_T_LENGTH is defined, length_t is a typedef of size_t otherwise +// length_t is a typedef of int like GLSL defines it. + +#define GLM_LENGTH_INT 1 +#define GLM_LENGTH_SIZE_T 2 + +#ifdef GLM_FORCE_SIZE_T_LENGTH +# define GLM_CONFIG_LENGTH_TYPE GLM_LENGTH_SIZE_T +#else +# define GLM_CONFIG_LENGTH_TYPE GLM_LENGTH_INT +#endif + +namespace glm +{ + using std::size_t; +# if GLM_CONFIG_LENGTH_TYPE == GLM_LENGTH_SIZE_T + typedef size_t length_t; +# else + typedef int length_t; +# endif +}//namespace glm + +/////////////////////////////////////////////////////////////////////////////////// +// constexpr + +#if GLM_HAS_CONSTEXPR +# define GLM_CONFIG_CONSTEXP GLM_ENABLE + + namespace glm + { + template + constexpr std::size_t countof(T const (&)[N]) + { + return N; + } + }//namespace glm +# define GLM_COUNTOF(arr) glm::countof(arr) +#elif defined(_MSC_VER) +# define GLM_CONFIG_CONSTEXP GLM_DISABLE + +# define GLM_COUNTOF(arr) _countof(arr) +#else +# define GLM_CONFIG_CONSTEXP GLM_DISABLE + +# define GLM_COUNTOF(arr) sizeof(arr) / sizeof(arr[0]) +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// uint + +namespace glm{ +namespace detail +{ + template + struct is_int + { + enum test {value = 0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; +}//namespace detail + + typedef unsigned int uint; +}//namespace glm + +/////////////////////////////////////////////////////////////////////////////////// +// 64-bit int + +#if GLM_HAS_EXTENDED_INTEGER_TYPE +# include +#endif + +namespace glm{ +namespace detail +{ +# if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::uint64_t uint64; + typedef std::int64_t int64; +# elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) // C99 detected, 64 bit types available + typedef uint64_t uint64; + typedef int64_t int64; +# elif GLM_COMPILER & GLM_COMPILER_VC + typedef unsigned __int64 uint64; + typedef signed __int64 int64; +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic ignored "-Wlong-long" + __extension__ typedef unsigned long long uint64; + __extension__ typedef signed long long int64; +# elif (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic ignored "-Wc++11-long-long" + typedef unsigned long long uint64; + typedef signed long long int64; +# else//unknown compiler + typedef unsigned long long uint64; + typedef signed long long int64; +# endif +}//namespace detail +}//namespace glm + +/////////////////////////////////////////////////////////////////////////////////// +// make_unsigned + +#if GLM_HAS_MAKE_SIGNED +# include + +namespace glm{ +namespace detail +{ + using std::make_unsigned; +}//namespace detail +}//namespace glm + +#else + +namespace glm{ +namespace detail +{ + template + struct make_unsigned + {}; + + template<> + struct make_unsigned + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned + { + typedef unsigned short type; + }; + + template<> + struct make_unsigned + { + typedef unsigned int type; + }; + + template<> + struct make_unsigned + { + typedef unsigned long type; + }; + + template<> + struct make_unsigned + { + typedef uint64 type; + }; + + template<> + struct make_unsigned + { + typedef unsigned char type; + }; + + template<> + struct make_unsigned + { + typedef unsigned short type; + }; + + template<> + struct make_unsigned + { + typedef unsigned int type; + }; + + template<> + struct make_unsigned + { + typedef unsigned long type; + }; + + template<> + struct make_unsigned + { + typedef uint64 type; + }; +}//namespace detail +}//namespace glm +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Only use x, y, z, w as vector type components + +#ifdef GLM_FORCE_XYZW_ONLY +# define GLM_CONFIG_XYZW_ONLY GLM_ENABLE +#else +# define GLM_CONFIG_XYZW_ONLY GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of defaulted initialized types + +#define GLM_CTOR_INIT_DISABLE 0 +#define GLM_CTOR_INITIALIZER_LIST 1 +#define GLM_CTOR_INITIALISATION 2 + +#if defined(GLM_FORCE_CTOR_INIT) && GLM_HAS_INITIALIZER_LISTS +# define GLM_CONFIG_CTOR_INIT GLM_CTOR_INITIALIZER_LIST +#elif defined(GLM_FORCE_CTOR_INIT) && !GLM_HAS_INITIALIZER_LISTS +# define GLM_CONFIG_CTOR_INIT GLM_CTOR_INITIALISATION +#else +# define GLM_CONFIG_CTOR_INIT GLM_CTOR_INIT_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Use SIMD instruction sets + +#if GLM_HAS_ALIGNOF && (GLM_LANG & GLM_LANG_CXXMS_FLAG) && (GLM_ARCH & GLM_ARCH_SIMD_BIT) +# define GLM_CONFIG_SIMD GLM_ENABLE +#else +# define GLM_CONFIG_SIMD GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of defaulted function + +#if GLM_HAS_DEFAULTED_FUNCTIONS && GLM_CONFIG_CTOR_INIT == GLM_CTOR_INIT_DISABLE +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_ENABLE +# define GLM_DEFAULT = default +#else +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_DISABLE +# define GLM_DEFAULT +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of aligned gentypes + +#ifdef GLM_FORCE_ALIGNED // Legacy define +# define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +#endif + +#ifdef GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +# define GLM_FORCE_ALIGNED_GENTYPES +#endif + +#if GLM_HAS_ALIGNOF && (GLM_LANG & GLM_LANG_CXXMS_FLAG) && (defined(GLM_FORCE_ALIGNED_GENTYPES) || (GLM_CONFIG_SIMD == GLM_ENABLE)) +# define GLM_CONFIG_ALIGNED_GENTYPES GLM_ENABLE +#else +# define GLM_CONFIG_ALIGNED_GENTYPES GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Configure the use of anonymous structure as implementation detail + +#if ((GLM_CONFIG_SIMD == GLM_ENABLE) || (GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR) || (GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE)) +# define GLM_CONFIG_ANONYMOUS_STRUCT GLM_ENABLE +#else +# define GLM_CONFIG_ANONYMOUS_STRUCT GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Silent warnings + +#ifdef GLM_FORCE_SILENT_WARNINGS +# define GLM_SILENT_WARNINGS GLM_ENABLE +#else +# define GLM_SILENT_WARNINGS GLM_DISABLE +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Precision + +#define GLM_HIGHP 1 +#define GLM_MEDIUMP 2 +#define GLM_LOWP 3 + +#if defined(GLM_FORCE_PRECISION_HIGHP_BOOL) || defined(GLM_PRECISION_HIGHP_BOOL) +# define GLM_CONFIG_PRECISION_BOOL GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_BOOL) || defined(GLM_PRECISION_MEDIUMP_BOOL) +# define GLM_CONFIG_PRECISION_BOOL GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_BOOL) || defined(GLM_PRECISION_LOWP_BOOL) +# define GLM_CONFIG_PRECISION_BOOL GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_BOOL GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_INT) || defined(GLM_PRECISION_HIGHP_INT) +# define GLM_CONFIG_PRECISION_INT GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_INT) || defined(GLM_PRECISION_MEDIUMP_INT) +# define GLM_CONFIG_PRECISION_INT GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_INT) || defined(GLM_PRECISION_LOWP_INT) +# define GLM_CONFIG_PRECISION_INT GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_INT GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_UINT) || defined(GLM_PRECISION_HIGHP_UINT) +# define GLM_CONFIG_PRECISION_UINT GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_UINT) || defined(GLM_PRECISION_MEDIUMP_UINT) +# define GLM_CONFIG_PRECISION_UINT GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_UINT) || defined(GLM_PRECISION_LOWP_UINT) +# define GLM_CONFIG_PRECISION_UINT GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_UINT GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_FLOAT) || defined(GLM_PRECISION_HIGHP_FLOAT) +# define GLM_CONFIG_PRECISION_FLOAT GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_FLOAT) || defined(GLM_PRECISION_MEDIUMP_FLOAT) +# define GLM_CONFIG_PRECISION_FLOAT GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_FLOAT) || defined(GLM_PRECISION_LOWP_FLOAT) +# define GLM_CONFIG_PRECISION_FLOAT GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_FLOAT GLM_HIGHP +#endif + +#if defined(GLM_FORCE_PRECISION_HIGHP_DOUBLE) || defined(GLM_PRECISION_HIGHP_DOUBLE) +# define GLM_CONFIG_PRECISION_DOUBLE GLM_HIGHP +#elif defined(GLM_FORCE_PRECISION_MEDIUMP_DOUBLE) || defined(GLM_PRECISION_MEDIUMP_DOUBLE) +# define GLM_CONFIG_PRECISION_DOUBLE GLM_MEDIUMP +#elif defined(GLM_FORCE_PRECISION_LOWP_DOUBLE) || defined(GLM_PRECISION_LOWP_DOUBLE) +# define GLM_CONFIG_PRECISION_DOUBLE GLM_LOWP +#else +# define GLM_CONFIG_PRECISION_DOUBLE GLM_HIGHP +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Check inclusions of different versions of GLM + +#elif ((GLM_SETUP_INCLUDED != GLM_VERSION) && !defined(GLM_FORCE_IGNORE_VERSION)) +# error "GLM error: A different version of GLM is already included. Define GLM_FORCE_IGNORE_VERSION before including GLM headers to ignore this error." +#elif GLM_SETUP_INCLUDED == GLM_VERSION + +/////////////////////////////////////////////////////////////////////////////////// +// Messages + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_MESSAGE_DISPLAYED) +# define GLM_MESSAGE_DISPLAYED +# define GLM_STR_HELPER(x) #x +# define GLM_STR(x) GLM_STR_HELPER(x) + + // Report GLM version +# pragma message (GLM_STR(GLM_VERSION_MESSAGE)) + + // Report C++ language +# if (GLM_LANG & GLM_LANG_CXX2A_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 2A with extensions") +# elif (GLM_LANG & GLM_LANG_CXX2A_FLAG) +# pragma message("GLM: C++ 2A") +# elif (GLM_LANG & GLM_LANG_CXX17_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 17 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX17_FLAG) +# pragma message("GLM: C++ 17") +# elif (GLM_LANG & GLM_LANG_CXX14_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 14 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX14_FLAG) +# pragma message("GLM: C++ 14") +# elif (GLM_LANG & GLM_LANG_CXX11_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 11 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX11_FLAG) +# pragma message("GLM: C++ 11") +# elif (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 0x with extensions") +# elif (GLM_LANG & GLM_LANG_CXX0X_FLAG) +# pragma message("GLM: C++ 0x") +# elif (GLM_LANG & GLM_LANG_CXX03_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 03 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX03_FLAG) +# pragma message("GLM: C++ 03") +# elif (GLM_LANG & GLM_LANG_CXX98_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 98 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX98_FLAG) +# pragma message("GLM: C++ 98") +# else +# pragma message("GLM: C++ language undetected") +# endif//GLM_LANG + + // Report compiler detection +# if GLM_COMPILER & GLM_COMPILER_CUDA +# pragma message("GLM: CUDA compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma message("GLM: Visual C++ compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma message("GLM: Clang compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# pragma message("GLM: Intel Compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma message("GLM: GCC compiler detected") +# else +# pragma message("GLM: Compiler not detected") +# endif + + // Report build target +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with AVX2 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_AVX2_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with AVX2 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_AVX_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with AVX instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_AVX_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with AVX instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE42_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE4.2 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE42_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE4.2 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE41_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE4.1 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE41_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE4.1 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSSE3_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSSE3 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSSE3_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSSE3 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE3_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE3 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE3_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE3 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_SSE2_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits with SSE2 instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_SSE2_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits with SSE2 instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_X86_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: x86 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_X86_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: x86 32 bits build target") + +# elif (GLM_ARCH & GLM_ARCH_NEON_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: ARM 64 bits with Neon instruction set build target") +# elif (GLM_ARCH & GLM_ARCH_NEON_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: ARM 32 bits with Neon instruction set build target") + +# elif (GLM_ARCH & GLM_ARCH_ARM_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: ARM 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_ARM_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: ARM 32 bits build target") + +# elif (GLM_ARCH & GLM_ARCH_MIPS_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: MIPS 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_MIPS_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: MIPS 32 bits build target") + +# elif (GLM_ARCH & GLM_ARCH_PPC_BIT) && (GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: PowerPC 64 bits build target") +# elif (GLM_ARCH & GLM_ARCH_PPC_BIT) && (GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: PowerPC 32 bits build target") +# else +# pragma message("GLM: Unknown build target") +# endif//GLM_ARCH + + // Report platform name +# if(GLM_PLATFORM & GLM_PLATFORM_QNXNTO) +# pragma message("GLM: QNX platform detected") +//# elif(GLM_PLATFORM & GLM_PLATFORM_IOS) +//# pragma message("GLM: iOS platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_APPLE) +# pragma message("GLM: Apple platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_WINCE) +# pragma message("GLM: WinCE platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_WINDOWS) +# pragma message("GLM: Windows platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_CHROME_NACL) +# pragma message("GLM: Native Client detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) +# pragma message("GLM: Android platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_LINUX) +# pragma message("GLM: Linux platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_UNIX) +# pragma message("GLM: UNIX platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_UNKNOWN) +# pragma message("GLM: platform unknown") +# else +# pragma message("GLM: platform not detected") +# endif + + // Report whether only xyzw component are used +# if defined GLM_FORCE_XYZW_ONLY +# pragma message("GLM: GLM_FORCE_XYZW_ONLY is defined. Only x, y, z and w component are available in vector type. This define disables swizzle operators and SIMD instruction sets.") +# endif + + // Report swizzle operator support +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# pragma message("GLM: GLM_FORCE_SWIZZLE is defined, swizzling operators enabled.") +# elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# pragma message("GLM: GLM_FORCE_SWIZZLE is defined, swizzling functions enabled. Enable compiler C++ language extensions to enable swizzle operators.") +# else +# pragma message("GLM: GLM_FORCE_SWIZZLE is undefined. swizzling functions or operators are disabled.") +# endif + + // Report .length() type +# if GLM_CONFIG_LENGTH_TYPE == GLM_LENGTH_SIZE_T +# pragma message("GLM: GLM_FORCE_SIZE_T_LENGTH is defined. .length() returns a glm::length_t, a typedef of std::size_t.") +# else +# pragma message("GLM: GLM_FORCE_SIZE_T_LENGTH is undefined. .length() returns a glm::length_t, a typedef of int following GLSL.") +# endif + +# if GLM_CONFIG_UNRESTRICTED_GENTYPE == GLM_ENABLE +# pragma message("GLM: GLM_FORCE_UNRESTRICTED_GENTYPE is defined. Removes GLSL restrictions on valid function genTypes.") +# else +# pragma message("GLM: GLM_FORCE_UNRESTRICTED_GENTYPE is undefined. Follows strictly GLSL on valid function genTypes.") +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# pragma message("GLM: GLM_FORCE_SILENT_WARNINGS is defined. Ignores C++ warnings from using C++ language extensions.") +# else +# pragma message("GLM: GLM_FORCE_SILENT_WARNINGS is undefined. Shows C++ warnings from using C++ language extensions.") +# endif + +# ifdef GLM_FORCE_SINGLE_ONLY +# pragma message("GLM: GLM_FORCE_SINGLE_ONLY is defined. Using only single precision floating-point types.") +# endif + +# if defined(GLM_FORCE_ALIGNED_GENTYPES) && (GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE) +# undef GLM_FORCE_ALIGNED_GENTYPES +# pragma message("GLM: GLM_FORCE_ALIGNED_GENTYPES is defined, allowing aligned types. This prevents the use of C++ constexpr.") +# elif defined(GLM_FORCE_ALIGNED_GENTYPES) && (GLM_CONFIG_ALIGNED_GENTYPES == GLM_DISABLE) +# undef GLM_FORCE_ALIGNED_GENTYPES +# pragma message("GLM: GLM_FORCE_ALIGNED_GENTYPES is defined but is disabled. It requires C++11 and language extensions.") +# endif + +# if defined(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES) +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_DISABLE +# undef GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +# pragma message("GLM: GLM_FORCE_DEFAULT_ALIGNED_GENTYPES is defined but is disabled. It requires C++11 and language extensions.") +# elif GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +# pragma message("GLM: GLM_FORCE_DEFAULT_ALIGNED_GENTYPES is defined. All gentypes (e.g. vec3) will be aligned and padded by default.") +# endif +# endif + +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT +# pragma message("GLM: GLM_FORCE_DEPTH_ZERO_TO_ONE is defined. Using zero to one depth clip space.") +# else +# pragma message("GLM: GLM_FORCE_DEPTH_ZERO_TO_ONE is undefined. Using negative one to one depth clip space.") +# endif + +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT +# pragma message("GLM: GLM_FORCE_LEFT_HANDED is defined. Using left handed coordinate system.") +# else +# pragma message("GLM: GLM_FORCE_LEFT_HANDED is undefined. Using right handed coordinate system.") +# endif +#endif//GLM_MESSAGES + +#endif//GLM_SETUP_INCLUDED diff --git a/vendor/glm/glm/detail/type_float.hpp b/vendor/glm/glm/detail/type_float.hpp new file mode 100644 index 0000000..c8037eb --- /dev/null +++ b/vendor/glm/glm/detail/type_float.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "setup.hpp" + +#if GLM_COMPILER == GLM_COMPILER_VC12 +# pragma warning(push) +# pragma warning(disable: 4512) // assignment operator could not be generated +#endif + +namespace glm{ +namespace detail +{ + template + union float_t + {}; + + // https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ + template <> + union float_t + { + typedef int int_type; + typedef float float_type; + + GLM_CONSTEXPR float_t(float_type Num = 0.0f) : f(Num) {} + + GLM_CONSTEXPR float_t& operator=(float_t const& x) + { + f = x.f; + return *this; + } + + // Portable extraction of components. + GLM_CONSTEXPR bool negative() const { return i < 0; } + GLM_CONSTEXPR int_type mantissa() const { return i & ((1 << 23) - 1); } + GLM_CONSTEXPR int_type exponent() const { return (i >> 23) & ((1 << 8) - 1); } + + int_type i; + float_type f; + }; + + template <> + union float_t + { + typedef detail::int64 int_type; + typedef double float_type; + + GLM_CONSTEXPR float_t(float_type Num = static_cast(0)) : f(Num) {} + + GLM_CONSTEXPR float_t& operator=(float_t const& x) + { + f = x.f; + return *this; + } + + // Portable extraction of components. + GLM_CONSTEXPR bool negative() const { return i < 0; } + GLM_CONSTEXPR int_type mantissa() const { return i & ((int_type(1) << 52) - 1); } + GLM_CONSTEXPR int_type exponent() const { return (i >> 52) & ((int_type(1) << 11) - 1); } + + int_type i; + float_type f; + }; +}//namespace detail +}//namespace glm + +#if GLM_COMPILER == GLM_COMPILER_VC12 +# pragma warning(pop) +#endif diff --git a/vendor/glm/glm/detail/type_half.hpp b/vendor/glm/glm/detail/type_half.hpp new file mode 100644 index 0000000..40b8bec --- /dev/null +++ b/vendor/glm/glm/detail/type_half.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "setup.hpp" + +namespace glm{ +namespace detail +{ + typedef short hdata; + + GLM_FUNC_DECL float toFloat32(hdata value); + GLM_FUNC_DECL hdata toFloat16(float const& value); + +}//namespace detail +}//namespace glm + +#include "type_half.inl" diff --git a/vendor/glm/glm/detail/type_half.inl b/vendor/glm/glm/detail/type_half.inl new file mode 100644 index 0000000..b0723e3 --- /dev/null +++ b/vendor/glm/glm/detail/type_half.inl @@ -0,0 +1,241 @@ +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER float overflow() + { + volatile float f = 1e10; + + for(int i = 0; i < 10; ++i) + f *= f; // this will overflow before the for loop terminates + return f; + } + + union uif32 + { + GLM_FUNC_QUALIFIER uif32() : + i(0) + {} + + GLM_FUNC_QUALIFIER uif32(float f_) : + f(f_) + {} + + GLM_FUNC_QUALIFIER uif32(unsigned int i_) : + i(i_) + {} + + float f; + unsigned int i; + }; + + GLM_FUNC_QUALIFIER float toFloat32(hdata value) + { + int s = (value >> 15) & 0x00000001; + int e = (value >> 10) & 0x0000001f; + int m = value & 0x000003ff; + + if(e == 0) + { + if(m == 0) + { + // + // Plus or minus zero + // + + detail::uif32 result; + result.i = static_cast(s << 31); + return result.f; + } + else + { + // + // Denormalized number -- renormalize it + // + + while(!(m & 0x00000400)) + { + m <<= 1; + e -= 1; + } + + e += 1; + m &= ~0x00000400; + } + } + else if(e == 31) + { + if(m == 0) + { + // + // Positive or negative infinity + // + + uif32 result; + result.i = static_cast((s << 31) | 0x7f800000); + return result.f; + } + else + { + // + // Nan -- preserve sign and significand bits + // + + uif32 result; + result.i = static_cast((s << 31) | 0x7f800000 | (m << 13)); + return result.f; + } + } + + // + // Normalized number + // + + e = e + (127 - 15); + m = m << 13; + + // + // Assemble s, e and m. + // + + uif32 Result; + Result.i = static_cast((s << 31) | (e << 23) | m); + return Result.f; + } + + GLM_FUNC_QUALIFIER hdata toFloat16(float const& f) + { + uif32 Entry; + Entry.f = f; + int i = static_cast(Entry.i); + + // + // Our floating point number, f, is represented by the bit + // pattern in integer i. Disassemble that bit pattern into + // the sign, s, the exponent, e, and the significand, m. + // Shift s into the position where it will go in the + // resulting half number. + // Adjust e, accounting for the different exponent bias + // of float and half (127 versus 15). + // + + int s = (i >> 16) & 0x00008000; + int e = ((i >> 23) & 0x000000ff) - (127 - 15); + int m = i & 0x007fffff; + + // + // Now reassemble s, e and m into a half: + // + + if(e <= 0) + { + if(e < -10) + { + // + // E is less than -10. The absolute value of f is + // less than half_MIN (f may be a small normalized + // float, a denormalized float or a zero). + // + // We convert f to a half zero. + // + + return hdata(s); + } + + // + // E is between -10 and 0. F is a normalized float, + // whose magnitude is less than __half_NRM_MIN. + // + // We convert f to a denormalized half. + // + + m = (m | 0x00800000) >> (1 - e); + + // + // Round to nearest, round "0.5" up. + // + // Rounding may cause the significand to overflow and make + // our number normalized. Because of the way a half's bits + // are laid out, we don't have to treat this case separately; + // the code below will handle it correctly. + // + + if(m & 0x00001000) + m += 0x00002000; + + // + // Assemble the half from s, e (zero) and m. + // + + return hdata(s | (m >> 13)); + } + else if(e == 0xff - (127 - 15)) + { + if(m == 0) + { + // + // F is an infinity; convert f to a half + // infinity with the same sign as f. + // + + return hdata(s | 0x7c00); + } + else + { + // + // F is a NAN; we produce a half NAN that preserves + // the sign bit and the 10 leftmost bits of the + // significand of f, with one exception: If the 10 + // leftmost bits are all zero, the NAN would turn + // into an infinity, so we have to set at least one + // bit in the significand. + // + + m >>= 13; + + return hdata(s | 0x7c00 | m | (m == 0)); + } + } + else + { + // + // E is greater than zero. F is a normalized float. + // We try to convert f to a normalized half. + // + + // + // Round to nearest, round "0.5" up + // + + if(m & 0x00001000) + { + m += 0x00002000; + + if(m & 0x00800000) + { + m = 0; // overflow in significand, + e += 1; // adjust exponent + } + } + + // + // Handle exponent overflow + // + + if (e > 30) + { + overflow(); // Cause a hardware floating point overflow; + + return hdata(s | 0x7c00); + // if this returns, the half becomes an + } // infinity with the same sign as f. + + // + // Assemble the half from s, e and m. + // + + return hdata(s | (e << 10) | (m >> 13)); + } + } + +}//namespace detail +}//namespace glm diff --git a/vendor/glm/glm/detail/type_mat2x2.hpp b/vendor/glm/glm/detail/type_mat2x2.hpp new file mode 100644 index 0000000..033908f --- /dev/null +++ b/vendor/glm/glm/detail/type_mat2x2.hpp @@ -0,0 +1,177 @@ +/// @ref core +/// @file glm/detail/type_mat2x2.hpp + +#pragma once + +#include "type_vec2.hpp" +#include +#include + +namespace glm +{ + template + struct mat<2, 2, T, Q> + { + typedef vec<2, T, Q> col_type; + typedef vec<2, T, Q> row_type; + typedef mat<2, 2, T, Q> type; + typedef mat<2, 2, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[2]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 2; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<2, 2, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T const& x1, T const& y1, + T const& x2, T const& y2); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + U const& x1, V const& y1, + M const& x2, N const& y2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<2, U, Q> const& v1, + vec<2, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator+=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator-=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator*=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator/=(U s); + template + GLM_FUNC_DECL mat<2, 2, T, Q> & operator/=(mat<2, 2, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<2, 2, T, Q> & operator++ (); + GLM_FUNC_DECL mat<2, 2, T, Q> & operator-- (); + GLM_FUNC_DECL mat<2, 2, T, Q> operator++(int); + GLM_FUNC_DECL mat<2, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<2, 2, T, Q>::col_type operator*(mat<2, 2, T, Q> const& m, typename mat<2, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<2, 2, T, Q>::row_type operator*(typename mat<2, 2, T, Q>::col_type const& v, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator/(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<2, 2, T, Q>::col_type operator/(mat<2, 2, T, Q> const& m, typename mat<2, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<2, 2, T, Q>::row_type operator/(typename mat<2, 2, T, Q>::col_type const& v, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); +} //namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x2.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat2x2.inl b/vendor/glm/glm/detail/type_mat2x2.inl new file mode 100644 index 0000000..fe5d1aa --- /dev/null +++ b/vendor/glm/glm/detail/type_mat2x2.inl @@ -0,0 +1,536 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0), col_type(0, 1)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 2, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{m[0], m[1]} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(T scalar) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(scalar, 0), col_type(0, scalar)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(scalar, 0); + this->value[1] = col_type(0, scalar); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat + ( + T const& x0, T const& y0, + T const& x1, T const& y1 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(col_type const& v0, col_type const& v1) +# if GLM_HAS_INITIALIZER_LISTS + : value{v0, v1} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; +# endif + } + + // -- Conversion constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat + ( + X1 const& x1, Y1 const& y1, + X2 const& x2, Y2 const& y2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(static_cast(x1), value_type(y1)), col_type(static_cast(x2), value_type(y2)) } +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(static_cast(x1), value_type(y1)); + this->value[1] = col_type(static_cast(x2), value_type(y2)); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(vec<2, V1, Q> const& v1, vec<2, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); +# endif + } + + // -- mat2x2 matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 2, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<2, 2, T, Q>::col_type& mat<2, 2, T, Q>::operator[](typename mat<2, 2, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type const& mat<2, 2, T, Q>::operator[](typename mat<2, 2, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator=(mat<2, 2, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator+=(U scalar) + { + this->value[0] += scalar; + this->value[1] += scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator+=(mat<2, 2, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator-=(U scalar) + { + this->value[0] -= scalar; + this->value[1] -= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator-=(mat<2, 2, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator*=(U scalar) + { + this->value[0] *= scalar; + this->value[1] *= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator*=(mat<2, 2, U, Q> const& m) + { + return (*this = *this * m); + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator/=(U scalar) + { + this->value[0] /= scalar; + this->value[1] /= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator/=(mat<2, 2, U, Q> const& m) + { + return *this *= inverse(m); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> mat<2, 2, T, Q>::operator++(int) + { + mat<2, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> mat<2, 2, T, Q>::operator--(int) + { + mat<2, 2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + -m[0], + -m[1]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator+(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 2, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] - scalar, + m[1] - scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator-(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + scalar - m[0], + scalar - m[1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 2, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator*(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 2, T, Q>::col_type operator* + ( + mat<2, 2, T, Q> const& m, + typename mat<2, 2, T, Q>::row_type const& v + ) + { + return vec<2, T, Q>( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y); + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 2, T, Q>::row_type operator* + ( + typename mat<2, 2, T, Q>::col_type const& v, + mat<2, 2, T, Q> const& m + ) + { + return vec<2, T, Q>( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m, T scalar) + { + return mat<2, 2, T, Q>( + m[0] / scalar, + m[1] / scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator/(T scalar, mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + scalar / m[0], + scalar / m[1]); + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 2, T, Q>::col_type operator/(mat<2, 2, T, Q> const& m, typename mat<2, 2, T, Q>::row_type const& v) + { + return inverse(m) * v; + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 2, T, Q>::row_type operator/(typename mat<2, 2, T, Q>::col_type const& v, mat<2, 2, T, Q> const& m) + { + return v * inverse(m); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + mat<2, 2, T, Q> m1_copy(m1); + return m1_copy /= m2; + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat2x3.hpp b/vendor/glm/glm/detail/type_mat2x3.hpp new file mode 100644 index 0000000..d6596e4 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat2x3.hpp @@ -0,0 +1,159 @@ +/// @ref core +/// @file glm/detail/type_mat2x3.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include +#include + +namespace glm +{ + template + struct mat<2, 3, T, Q> + { + typedef vec<3, T, Q> col_type; + typedef vec<2, T, Q> row_type; + typedef mat<2, 3, T, Q> type; + typedef mat<3, 2, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[2]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 2; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<2, 3, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, T z0, + T x1, T y1, T z1); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1); + + // -- Conversions -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<3, U, Q> const& v1, + vec<3, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<2, 3, T, Q> & operator=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<2, 3, T, Q> & operator+=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<2, 3, T, Q> & operator-=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<2, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<2, 3, T, Q> & operator++ (); + GLM_FUNC_DECL mat<2, 3, T, Q> & operator-- (); + GLM_FUNC_DECL mat<2, 3, T, Q> operator++(int); + GLM_FUNC_DECL mat<2, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(T scalar, mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<2, 3, T, Q>::col_type operator*(mat<2, 3, T, Q> const& m, typename mat<2, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<2, 3, T, Q>::row_type operator*(typename mat<2, 3, T, Q>::col_type const& v, mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator/(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator/(T scalar, mat<2, 3, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x3.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat2x3.inl b/vendor/glm/glm/detail/type_mat2x3.inl new file mode 100644 index 0000000..5fec17e --- /dev/null +++ b/vendor/glm/glm/detail/type_mat2x3.inl @@ -0,0 +1,510 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0), col_type(0, 1, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 3, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{m.value[0], m.value[1]} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(T scalar) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(scalar, 0, 0), col_type(0, scalar, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(scalar, 0, 0); + this->value[1] = col_type(0, scalar, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat + ( + T x0, T y0, T z0, + T x1, T y1, T z1 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(col_type const& v0, col_type const& v1) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat + ( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x1, y1, z1), col_type(x2, y2, z2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1); + this->value[1] = col_type(x2, y2, z2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(vec<3, V1, Q> const& v1, vec<3, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 3, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<2, 3, T, Q>::col_type & mat<2, 3, T, Q>::operator[](typename mat<2, 3, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 3, T, Q>::col_type const& mat<2, 3, T, Q>::operator[](typename mat<2, 3, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator=(mat<2, 3, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator+=(mat<2, 3, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator-=(mat<2, 3, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q>& mat<2, 3, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> mat<2, 3, T, Q>::operator++(int) + { + mat<2, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> mat<2, 3, T, Q>::operator--(int) + { + mat<2, 3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m) + { + return mat<2, 3, T, Q>( + -m[0], + -m[1]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] - scalar, + m[1] - scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator*(T scalar, mat<2, 3, T, Q> const& m) + { + return mat<2, 3, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 3, T, Q>::col_type operator* + ( + mat<2, 3, T, Q> const& m, + typename mat<2, 3, T, Q>::row_type const& v) + { + return typename mat<2, 3, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y, + m[0][2] * v.x + m[1][2] * v.y); + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 3, T, Q>::row_type operator* + ( + typename mat<2, 3, T, Q>::col_type const& v, + mat<2, 3, T, Q> const& m) + { + return typename mat<2, 3, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + T SrcA00 = m1[0][0]; + T SrcA01 = m1[0][1]; + T SrcA02 = m1[0][2]; + T SrcA10 = m1[1][0]; + T SrcA11 = m1[1][1]; + T SrcA12 = m1[1][2]; + + T SrcB00 = m2[0][0]; + T SrcB01 = m2[0][1]; + T SrcB10 = m2[1][0]; + T SrcB11 = m2[1][1]; + T SrcB20 = m2[2][0]; + T SrcB21 = m2[2][1]; + + mat<3, 3, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator/(mat<2, 3, T, Q> const& m, T scalar) + { + return mat<2, 3, T, Q>( + m[0] / scalar, + m[1] / scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator/(T scalar, mat<2, 3, T, Q> const& m) + { + return mat<2, 3, T, Q>( + scalar / m[0], + scalar / m[1]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat2x4.hpp b/vendor/glm/glm/detail/type_mat2x4.hpp new file mode 100644 index 0000000..ff03e21 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat2x4.hpp @@ -0,0 +1,161 @@ +/// @ref core +/// @file glm/detail/type_mat2x4.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<2, 4, T, Q> + { + typedef vec<4, T, Q> col_type; + typedef vec<2, T, Q> row_type; + typedef mat<2, 4, T, Q> type; + typedef mat<4, 2, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[2]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 2; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<2, 4, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<4, U, Q> const& v1, + vec<4, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<2, 4, T, Q> & operator=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<2, 4, T, Q> & operator+=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<2, 4, T, Q> & operator-=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<2, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<2, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<2, 4, T, Q> & operator++ (); + GLM_FUNC_DECL mat<2, 4, T, Q> & operator-- (); + GLM_FUNC_DECL mat<2, 4, T, Q> operator++(int); + GLM_FUNC_DECL mat<2, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(T scalar, mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<2, 4, T, Q>::col_type operator*(mat<2, 4, T, Q> const& m, typename mat<2, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<2, 4, T, Q>::row_type operator*(typename mat<2, 4, T, Q>::col_type const& v, mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator/(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator/(T scalar, mat<2, 4, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x4.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat2x4.inl b/vendor/glm/glm/detail/type_mat2x4.inl new file mode 100644 index 0000000..b6d2b9d --- /dev/null +++ b/vendor/glm/glm/detail/type_mat2x4.inl @@ -0,0 +1,520 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0, 0), col_type(0, 1, 0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 4, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{m[0], m[1]} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0, 0), col_type(0, s, 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0, 0); + this->value[1] = col_type(0, s, 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat + ( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0, w0), col_type(x1, y1, z1, w1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(col_type const& v0, col_type const& v1) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat + ( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1, w1); + this->value[1] = col_type(x2, y2, z2, w2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(vec<4, V1, Q> const& v1, vec<4, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 4, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<2, 4, T, Q>::col_type & mat<2, 4, T, Q>::operator[](typename mat<2, 4, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<2, 4, T, Q>::col_type const& mat<2, 4, T, Q>::operator[](typename mat<2, 4, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator=(mat<2, 4, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator+=(mat<2, 4, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator-=(mat<2, 4, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> & mat<2, 4, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> mat<2, 4, T, Q>::operator++(int) + { + mat<2, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> mat<2, 4, T, Q>::operator--(int) + { + mat<2, 4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m) + { + return mat<2, 4, T, Q>( + -m[0], + -m[1]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] + scalar, + m[1] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] - scalar, + m[1] - scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator*(T scalar, mat<2, 4, T, Q> const& m) + { + return mat<2, 4, T, Q>( + m[0] * scalar, + m[1] * scalar); + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 4, T, Q>::col_type operator*(mat<2, 4, T, Q> const& m, typename mat<2, 4, T, Q>::row_type const& v) + { + return typename mat<2, 4, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y, + m[0][2] * v.x + m[1][2] * v.y, + m[0][3] * v.x + m[1][3] * v.y); + } + + template + GLM_FUNC_QUALIFIER typename mat<2, 4, T, Q>::row_type operator*(typename mat<2, 4, T, Q>::col_type const& v, mat<2, 4, T, Q> const& m) + { + return typename mat<2, 4, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + T SrcA00 = m1[0][0]; + T SrcA01 = m1[0][1]; + T SrcA02 = m1[0][2]; + T SrcA03 = m1[0][3]; + T SrcA10 = m1[1][0]; + T SrcA11 = m1[1][1]; + T SrcA12 = m1[1][2]; + T SrcA13 = m1[1][3]; + + T SrcB00 = m2[0][0]; + T SrcB01 = m2[0][1]; + T SrcB10 = m2[1][0]; + T SrcB11 = m2[1][1]; + T SrcB20 = m2[2][0]; + T SrcB21 = m2[2][1]; + T SrcB30 = m2[3][0]; + T SrcB31 = m2[3][1]; + + mat<4, 4, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01; + Result[0][3] = SrcA03 * SrcB00 + SrcA13 * SrcB01; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11; + Result[1][3] = SrcA03 * SrcB10 + SrcA13 * SrcB11; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21; + Result[2][3] = SrcA03 * SrcB20 + SrcA13 * SrcB21; + Result[3][0] = SrcA00 * SrcB30 + SrcA10 * SrcB31; + Result[3][1] = SrcA01 * SrcB30 + SrcA11 * SrcB31; + Result[3][2] = SrcA02 * SrcB30 + SrcA12 * SrcB31; + Result[3][3] = SrcA03 * SrcB30 + SrcA13 * SrcB31; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<2, 2, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator/(mat<2, 4, T, Q> const& m, T scalar) + { + return mat<2, 4, T, Q>( + m[0] / scalar, + m[1] / scalar); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator/(T scalar, mat<2, 4, T, Q> const& m) + { + return mat<2, 4, T, Q>( + scalar / m[0], + scalar / m[1]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat3x2.hpp b/vendor/glm/glm/detail/type_mat3x2.hpp new file mode 100644 index 0000000..e166581 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat3x2.hpp @@ -0,0 +1,167 @@ +/// @ref core +/// @file glm/detail/type_mat3x2.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include +#include + +namespace glm +{ + template + struct mat<3, 2, T, Q> + { + typedef vec<2, T, Q> col_type; + typedef vec<3, T, Q> row_type; + typedef mat<3, 2, T, Q> type; + typedef mat<2, 3, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[3]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 3; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<3, 2, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, + T x1, T y1, + T x2, T y2); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template< + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<2, V1, Q> const& v1, + vec<2, V2, Q> const& v2, + vec<2, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<3, 2, T, Q> & operator=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<3, 2, T, Q> & operator+=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<3, 2, T, Q> & operator-=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<3, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<3, 2, T, Q> & operator++ (); + GLM_FUNC_DECL mat<3, 2, T, Q> & operator-- (); + GLM_FUNC_DECL mat<3, 2, T, Q> operator++(int); + GLM_FUNC_DECL mat<3, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(T scalar, mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<3, 2, T, Q>::col_type operator*(mat<3, 2, T, Q> const& m, typename mat<3, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<3, 2, T, Q>::row_type operator*(typename mat<3, 2, T, Q>::col_type const& v, mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator/(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator/(T scalar, mat<3, 2, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x2.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat3x2.inl b/vendor/glm/glm/detail/type_mat3x2.inl new file mode 100644 index 0000000..b4b948b --- /dev/null +++ b/vendor/glm/glm/detail/type_mat3x2.inl @@ -0,0 +1,532 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0), col_type(0, 1), col_type(0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); + this->value[2] = col_type(0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 2, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0), col_type(0, s), col_type(0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0); + this->value[1] = col_type(0, s); + this->value[2] = col_type(0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat + ( + T x0, T y0, + T x1, T y1, + T x2, T y2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, + typename X1, typename Y1, + typename X2, typename Y2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat + ( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(vec<2, V0, Q> const& v0, vec<2, V1, Q> const& v1, vec<2, V2, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 2, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 2, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<3, 2, T, Q>::col_type & mat<3, 2, T, Q>::operator[](typename mat<3, 2, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 2, T, Q>::col_type const& mat<3, 2, T, Q>::operator[](typename mat<3, 2, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator=(mat<3, 2, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator+=(mat<3, 2, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator-=(mat<3, 2, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> & mat<3, 2, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q>& mat<3, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> mat<3, 2, T, Q>::operator++(int) + { + mat<3, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> mat<3, 2, T, Q>::operator--(int) + { + mat<3, 2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m) + { + return mat<3, 2, T, Q>( + -m[0], + -m[1], + -m[2]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator*(T scalar, mat<3, 2, T, Q> const& m) + { + return mat<3, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 2, T, Q>::col_type operator*(mat<3, 2, T, Q> const& m, typename mat<3, 2, T, Q>::row_type const& v) + { + return typename mat<3, 2, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z); + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 2, T, Q>::row_type operator*(typename mat<3, 2, T, Q>::col_type const& v, mat<3, 2, T, Q> const& m) + { + return typename mat<3, 2, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1], + v.x * m[2][0] + v.y * m[2][1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + const T SrcA00 = m1[0][0]; + const T SrcA01 = m1[0][1]; + const T SrcA10 = m1[1][0]; + const T SrcA11 = m1[1][1]; + const T SrcA20 = m1[2][0]; + const T SrcA21 = m1[2][1]; + + const T SrcB00 = m2[0][0]; + const T SrcB01 = m2[0][1]; + const T SrcB02 = m2[0][2]; + const T SrcB10 = m2[1][0]; + const T SrcB11 = m2[1][1]; + const T SrcB12 = m2[1][2]; + + mat<2, 2, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator/(mat<3, 2, T, Q> const& m, T scalar) + { + return mat<3, 2, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator/(T scalar, mat<3, 2, T, Q> const& m) + { + return mat<3, 2, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat3x3.hpp b/vendor/glm/glm/detail/type_mat3x3.hpp new file mode 100644 index 0000000..3174872 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat3x3.hpp @@ -0,0 +1,184 @@ +/// @ref core +/// @file glm/detail/type_mat3x3.hpp + +#pragma once + +#include "type_vec3.hpp" +#include +#include + +namespace glm +{ + template + struct mat<3, 3, T, Q> + { + typedef vec<3, T, Q> col_type; + typedef vec<3, T, Q> row_type; + typedef mat<3, 3, T, Q> type; + typedef mat<3, 3, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[3]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 3; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<3, 3, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, T z0, + T x1, T y1, T z1, + T x2, T y2, T z2); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2, + X3 x3, Y3 y3, Z3 z3); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<3, V1, Q> const& v1, + vec<3, V2, Q> const& v2, + vec<3, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator+=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator-=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator*=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator/=(U s); + template + GLM_FUNC_DECL mat<3, 3, T, Q> & operator/=(mat<3, 3, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<3, 3, T, Q> & operator++(); + GLM_FUNC_DECL mat<3, 3, T, Q> & operator--(); + GLM_FUNC_DECL mat<3, 3, T, Q> operator++(int); + GLM_FUNC_DECL mat<3, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<3, 3, T, Q>::col_type operator*(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<3, 3, T, Q>::row_type operator*(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator/(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<3, 3, T, Q>::col_type operator/(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<3, 3, T, Q>::row_type operator/(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x3.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat3x3.inl b/vendor/glm/glm/detail/type_mat3x3.inl new file mode 100644 index 0000000..1ddaf99 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat3x3.inl @@ -0,0 +1,601 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0), col_type(0, 1, 0), col_type(0, 0, 1)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); + this->value[2] = col_type(0, 0, 1); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 3, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0), col_type(0, s, 0), col_type(0, 0, s)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0); + this->value[1] = col_type(0, s, 0); + this->value[2] = col_type(0, 0, s); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat + ( + T x0, T y0, T z0, + T x1, T y1, T z1, + T x2, T y2, T z2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1), col_type(x2, y2, z2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat + ( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2, + X3 x3, Y3 y3, Z3 z3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x1, y1, z1), col_type(x2, y2, z2), col_type(x3, y3, z3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1); + this->value[1] = col_type(x2, y2, z2); + this->value[2] = col_type(x3, y3, z3); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(vec<3, V1, Q> const& v1, vec<3, V2, Q> const& v2, vec<3, V3, Q> const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 3, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 3, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<3, 3, T, Q>::col_type & mat<3, 3, T, Q>::operator[](typename mat<3, 3, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type const& mat<3, 3, T, Q>::operator[](typename mat<3, 3, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator=(mat<3, 3, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator+=(mat<3, 3, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator-=(mat<3, 3, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator*=(mat<3, 3, U, Q> const& m) + { + return (*this = *this * m); + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator/=(mat<3, 3, U, Q> const& m) + { + return *this *= inverse(m); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> & mat<3, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat<3, 3, T, Q>::operator++(int) + { + mat<3, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat<3, 3, T, Q>::operator--(int) + { + mat<3, 3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + -m[0], + -m[1], + -m[2]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator+(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 3, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator-(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + scalar - m[0], + scalar - m[1], + scalar - m[2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 3, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator*(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 3, T, Q>::col_type operator*(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v) + { + return typename mat<3, 3, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z); + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 3, T, Q>::row_type operator*(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m) + { + return typename mat<3, 3, T, Q>::row_type( + m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z, + m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z, + m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA02 = m1[0][2]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA12 = m1[1][2]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA22 = m1[2][2]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB20 = m2[2][0]; + T const SrcB21 = m2[2][1]; + T const SrcB22 = m2[2][2]; + + mat<3, 3, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1] + m1[2][2] * m2[3][2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m, T scalar) + { + return mat<3, 3, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator/(T scalar, mat<3, 3, T, Q> const& m) + { + return mat<3, 3, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2]); + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 3, T, Q>::col_type operator/(mat<3, 3, T, Q> const& m, typename mat<3, 3, T, Q>::row_type const& v) + { + return inverse(m) * v; + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 3, T, Q>::row_type operator/(typename mat<3, 3, T, Q>::col_type const& v, mat<3, 3, T, Q> const& m) + { + return v * inverse(m); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + mat<3, 3, T, Q> m1_copy(m1); + return m1_copy /= m2; + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat3x4.hpp b/vendor/glm/glm/detail/type_mat3x4.hpp new file mode 100644 index 0000000..6e40b90 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat3x4.hpp @@ -0,0 +1,166 @@ +/// @ref core +/// @file glm/detail/type_mat3x4.hpp + +#pragma once + +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<3, 4, T, Q> + { + typedef vec<4, T, Q> col_type; + typedef vec<3, T, Q> row_type; + typedef mat<3, 4, T, Q> type; + typedef mat<4, 3, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[3]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 3; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<3, 4, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1, + T x2, T y2, T z2, T w2); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2, + X3 x3, Y3 y3, Z3 z3, W3 w3); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<4, V1, Q> const& v1, + vec<4, V2, Q> const& v2, + vec<4, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<3, 4, T, Q> & operator=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<3, 4, T, Q> & operator+=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<3, 4, T, Q> & operator-=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<3, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<3, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<3, 4, T, Q> & operator++(); + GLM_FUNC_DECL mat<3, 4, T, Q> & operator--(); + GLM_FUNC_DECL mat<3, 4, T, Q> operator++(int); + GLM_FUNC_DECL mat<3, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(T scalar, mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<3, 4, T, Q>::col_type operator*(mat<3, 4, T, Q> const& m, typename mat<3, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<3, 4, T, Q>::row_type operator*(typename mat<3, 4, T, Q>::col_type const& v, mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator/(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator/(T scalar, mat<3, 4, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x4.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat3x4.inl b/vendor/glm/glm/detail/type_mat3x4.inl new file mode 100644 index 0000000..6ee416c --- /dev/null +++ b/vendor/glm/glm/detail/type_mat3x4.inl @@ -0,0 +1,578 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0, 0), col_type(0, 1, 0, 0), col_type(0, 0, 1, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 4, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0, 0), col_type(0, s, 0, 0), col_type(0, 0, s, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0, 0); + this->value[1] = col_type(0, s, 0, 0); + this->value[2] = col_type(0, 0, s, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat + ( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1, + T x2, T y2, T z2, T w2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x0, y0, z0, w0), + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, typename Z0, typename W0, + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat + ( + X0 x0, Y0 y0, Z0 z0, W0 w0, + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x0, y0, z0, w0), + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(vec<4, V1, Q> const& v0, vec<4, V2, Q> const& v1, vec<4, V3, Q> const& v2) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 4, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(0, 0, 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(m[2], 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(m[2], 1, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 1, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<3, 4, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<3, 4, T, Q>::col_type & mat<3, 4, T, Q>::operator[](typename mat<3, 4, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<3, 4, T, Q>::col_type const& mat<3, 4, T, Q>::operator[](typename mat<3, 4, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator=(mat<3, 4, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator+=(mat<3, 4, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator-=(mat<3, 4, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> & mat<3, 4, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q>& mat<3, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> mat<3, 4, T, Q>::operator++(int) + { + mat<3, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> mat<3, 4, T, Q>::operator--(int) + { + mat<3, 4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m) + { + return mat<3, 4, T, Q>( + -m[0], + -m[1], + -m[2]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator*(T scalar, mat<3, 4, T, Q> const& m) + { + return mat<3, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar); + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 4, T, Q>::col_type operator* + ( + mat<3, 4, T, Q> const& m, + typename mat<3, 4, T, Q>::row_type const& v + ) + { + return typename mat<3, 4, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z, + m[0][3] * v.x + m[1][3] * v.y + m[2][3] * v.z); + } + + template + GLM_FUNC_QUALIFIER typename mat<3, 4, T, Q>::row_type operator* + ( + typename mat<3, 4, T, Q>::col_type const& v, + mat<3, 4, T, Q> const& m + ) + { + return typename mat<3, 4, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3], + v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2] + v.w * m[2][3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + const T SrcA00 = m1[0][0]; + const T SrcA01 = m1[0][1]; + const T SrcA02 = m1[0][2]; + const T SrcA03 = m1[0][3]; + const T SrcA10 = m1[1][0]; + const T SrcA11 = m1[1][1]; + const T SrcA12 = m1[1][2]; + const T SrcA13 = m1[1][3]; + const T SrcA20 = m1[2][0]; + const T SrcA21 = m1[2][1]; + const T SrcA22 = m1[2][2]; + const T SrcA23 = m1[2][3]; + + const T SrcB00 = m2[0][0]; + const T SrcB01 = m2[0][1]; + const T SrcB02 = m2[0][2]; + const T SrcB10 = m2[1][0]; + const T SrcB11 = m2[1][1]; + const T SrcB12 = m2[1][2]; + const T SrcB20 = m2[2][0]; + const T SrcB21 = m2[2][1]; + const T SrcB22 = m2[2][2]; + const T SrcB30 = m2[3][0]; + const T SrcB31 = m2[3][1]; + const T SrcB32 = m2[3][2]; + + mat<4, 4, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02; + Result[0][3] = SrcA03 * SrcB00 + SrcA13 * SrcB01 + SrcA23 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12; + Result[1][3] = SrcA03 * SrcB10 + SrcA13 * SrcB11 + SrcA23 * SrcB12; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22; + Result[2][3] = SrcA03 * SrcB20 + SrcA13 * SrcB21 + SrcA23 * SrcB22; + Result[3][0] = SrcA00 * SrcB30 + SrcA10 * SrcB31 + SrcA20 * SrcB32; + Result[3][1] = SrcA01 * SrcB30 + SrcA11 * SrcB31 + SrcA21 * SrcB32; + Result[3][2] = SrcA02 * SrcB30 + SrcA12 * SrcB31 + SrcA22 * SrcB32; + Result[3][3] = SrcA03 * SrcB30 + SrcA13 * SrcB31 + SrcA23 * SrcB32; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<2, 3, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<3, 3, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator/(mat<3, 4, T, Q> const& m, T scalar) + { + return mat<3, 4, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator/(T scalar, mat<3, 4, T, Q> const& m) + { + return mat<3, 4, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat4x2.hpp b/vendor/glm/glm/detail/type_mat4x2.hpp new file mode 100644 index 0000000..8d34352 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat4x2.hpp @@ -0,0 +1,171 @@ +/// @ref core +/// @file glm/detail/type_mat4x2.hpp + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<4, 2, T, Q> + { + typedef vec<2, T, Q> col_type; + typedef vec<4, T, Q> row_type; + typedef mat<4, 2, T, Q> type; + typedef mat<2, 4, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[4]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 4; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<4, 2, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T x0, T y0, + T x1, T y1, + T x2, T y2, + T x3, T y3); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1, + col_type const& v2, + col_type const& v3); + + // -- Conversions -- + + template< + typename X0, typename Y0, + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<2, V1, Q> const& v1, + vec<2, V2, Q> const& v2, + vec<2, V3, Q> const& v3, + vec<2, V4, Q> const& v4); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<4, 2, T, Q> & operator=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<4, 2, T, Q> & operator+=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<4, 2, T, Q> & operator-=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<4, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<4, 2, T, Q> & operator++ (); + GLM_FUNC_DECL mat<4, 2, T, Q> & operator-- (); + GLM_FUNC_DECL mat<4, 2, T, Q> operator++(int); + GLM_FUNC_DECL mat<4, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(T scalar, mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<4, 2, T, Q>::col_type operator*(mat<4, 2, T, Q> const& m, typename mat<4, 2, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<4, 2, T, Q>::row_type operator*(typename mat<4, 2, T, Q>::col_type const& v, mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator/(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL mat<4, 2, T, Q> operator/(T scalar, mat<4, 2, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x2.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat4x2.inl b/vendor/glm/glm/detail/type_mat4x2.inl new file mode 100644 index 0000000..419c80c --- /dev/null +++ b/vendor/glm/glm/detail/type_mat4x2.inl @@ -0,0 +1,574 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0), col_type(0, 1), col_type(0, 0), col_type(0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); + this->value[2] = col_type(0, 0); + this->value[3] = col_type(0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 2, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(T s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0), col_type(0, s), col_type(0, 0), col_type(0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0); + this->value[1] = col_type(0, s); + this->value[2] = col_type(0, 0); + this->value[3] = col_type(0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat + ( + T x0, T y0, + T x1, T y1, + T x2, T y2, + T x3, T y3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2), col_type(x3, y3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); + this->value[3] = col_type(x3, y3); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2, col_type const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat + ( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0), col_type(x1, y1), col_type(x2, y2), col_type(x3, y3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); + this->value[3] = col_type(x3, y3); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(vec<2, V0, Q> const& v0, vec<2, V1, Q> const& v1, vec<2, V2, Q> const& v2, vec<2, V3, Q> const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v0); + this->value[1] = col_type(v1); + this->value[2] = col_type(v2); + this->value[3] = col_type(v3); +# endif + } + + // -- Conversion -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 2, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 2, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<4, 2, T, Q>::col_type & mat<4, 2, T, Q>::operator[](typename mat<4, 2, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 2, T, Q>::col_type const& mat<4, 2, T, Q>::operator[](typename mat<4, 2, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q>& mat<4, 2, T, Q>::operator=(mat<4, 2, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator+=(mat<4, 2, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator-=(mat<4, 2, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> & mat<4, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> mat<4, 2, T, Q>::operator++(int) + { + mat<4, 2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> mat<4, 2, T, Q>::operator--(int) + { + mat<4, 2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m) + { + return mat<4, 2, T, Q>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar, + m[3] - scalar); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator*(T scalar, mat<4, 2, T, Q> const& m) + { + return mat<4, 2, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 2, T, Q>::col_type operator*(mat<4, 2, T, Q> const& m, typename mat<4, 2, T, Q>::row_type const& v) + { + return typename mat<4, 2, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w); + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 2, T, Q>::row_type operator*(typename mat<4, 2, T, Q>::col_type const& v, mat<4, 2, T, Q> const& m) + { + return typename mat<4, 2, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1], + v.x * m[2][0] + v.y * m[2][1], + v.x * m[3][0] + v.y * m[3][1]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA30 = m1[3][0]; + T const SrcA31 = m1[3][1]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB03 = m2[0][3]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB13 = m2[1][3]; + + mat<2, 2, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02 + SrcA30 * SrcB03; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02 + SrcA31 * SrcB03; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12 + SrcA30 * SrcB13; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12 + SrcA31 * SrcB13; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 2, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2] + m1[3][0] * m2[3][3], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2] + m1[3][1] * m2[3][3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator/(mat<4, 2, T, Q> const& m, T scalar) + { + return mat<4, 2, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar, + m[3] / scalar); + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> operator/(T scalar, mat<4, 2, T, Q> const& m) + { + return mat<4, 2, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2], + scalar / m[3]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat4x3.hpp b/vendor/glm/glm/detail/type_mat4x3.hpp new file mode 100644 index 0000000..16e4270 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat4x3.hpp @@ -0,0 +1,171 @@ +/// @ref core +/// @file glm/detail/type_mat4x3.hpp + +#pragma once + +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<4, 3, T, Q> + { + typedef vec<3, T, Q> col_type; + typedef vec<4, T, Q> row_type; + typedef mat<4, 3, T, Q> type; + typedef mat<3, 4, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[4]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length() { return 4; } + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<4, 3, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T const& x); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T const& x0, T const& y0, T const& z0, + T const& x1, T const& y1, T const& z1, + T const& x2, T const& y2, T const& z2, + T const& x3, T const& y3, T const& z3); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1, + col_type const& v2, + col_type const& v3); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3, + typename X4, typename Y4, typename Z4> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 const& x1, Y1 const& y1, Z1 const& z1, + X2 const& x2, Y2 const& y2, Z2 const& z2, + X3 const& x3, Y3 const& y3, Z3 const& z3, + X4 const& x4, Y4 const& y4, Z4 const& z4); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<3, V1, Q> const& v1, + vec<3, V2, Q> const& v2, + vec<3, V3, Q> const& v3, + vec<3, V4, Q> const& v4); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<4, 3, T, Q> & operator=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<4, 3, T, Q> & operator+=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<4, 3, T, Q> & operator-=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<4, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<4, 3, T, Q>& operator++(); + GLM_FUNC_DECL mat<4, 3, T, Q>& operator--(); + GLM_FUNC_DECL mat<4, 3, T, Q> operator++(int); + GLM_FUNC_DECL mat<4, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(T const& s, mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<4, 3, T, Q>::col_type operator*(mat<4, 3, T, Q> const& m, typename mat<4, 3, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<4, 3, T, Q>::row_type operator*(typename mat<4, 3, T, Q>::col_type const& v, mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 3, T, Q> operator/(T const& s, mat<4, 3, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x3.inl" +#endif //GLM_EXTERNAL_TEMPLATE diff --git a/vendor/glm/glm/detail/type_mat4x3.inl b/vendor/glm/glm/detail/type_mat4x3.inl new file mode 100644 index 0000000..11b1ee3 --- /dev/null +++ b/vendor/glm/glm/detail/type_mat4x3.inl @@ -0,0 +1,598 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0), col_type(0, 1, 0), col_type(0, 0, 1), col_type(0, 0, 0)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0, 0, 0); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 3, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(T const& s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0), col_type(0, s, 0), col_type(0, 0, s), col_type(0, 0, 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0); + this->value[1] = col_type(0, s, 0); + this->value[2] = col_type(0, 0, s); + this->value[3] = col_type(0, 0, 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat + ( + T const& x0, T const& y0, T const& z0, + T const& x1, T const& y1, T const& z1, + T const& x2, T const& y2, T const& z2, + T const& x3, T const& y3, T const& z3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1), col_type(x2, y2, z2), col_type(x3, y3, z3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); + this->value[3] = col_type(x3, y3, z3); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2, col_type const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; +# endif + } + + // -- Conversion constructors -- + + template + template< + typename X0, typename Y0, typename Z0, + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat + ( + X0 const& x0, Y0 const& y0, Z0 const& z0, + X1 const& x1, Y1 const& y1, Z1 const& z1, + X2 const& x2, Y2 const& y2, Z2 const& z2, + X3 const& x3, Y3 const& y3, Z3 const& z3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x0, y0, z0), col_type(x1, y1, z1), col_type(x2, y2, z2), col_type(x3, y3, z3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); + this->value[3] = col_type(x3, y3, z3); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(vec<3, V1, Q> const& v1, vec<3, V2, Q> const& v2, vec<3, V3, Q> const& v3, vec<3, V4, Q> const& v4) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2), col_type(v3), col_type(v4)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); +# endif + } + + // -- Matrix conversions -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 3, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 1), col_type(m[3], 0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + this->value[3] = col_type(m[3], 0); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<4, 3, T, Q>::col_type & mat<4, 3, T, Q>::operator[](typename mat<4, 3, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 3, T, Q>::col_type const& mat<4, 3, T, Q>::operator[](typename mat<4, 3, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q>& mat<4, 3, T, Q>::operator=(mat<4, 3, U, Q> const& m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator+=(mat<4, 3, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator-=(mat<4, 3, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> & mat<4, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> mat<4, 3, T, Q>::operator++(int) + { + mat<4, 3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> mat<4, 3, T, Q>::operator--(int) + { + mat<4, 3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator*(T const& s, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 3, T, Q>::col_type operator* + ( + mat<4, 3, T, Q> const& m, + typename mat<4, 3, T, Q>::row_type const& v) + { + return typename mat<4, 3, T, Q>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z + m[3][2] * v.w); + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 3, T, Q>::row_type operator* + ( + typename mat<4, 3, T, Q>::col_type const& v, + mat<4, 3, T, Q> const& m) + { + return typename mat<4, 3, T, Q>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2], + v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2], + v.x * m[3][0] + v.y * m[3][1] + v.z * m[3][2]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA02 = m1[0][2]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA12 = m1[1][2]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA22 = m1[2][2]; + T const SrcA30 = m1[3][0]; + T const SrcA31 = m1[3][1]; + T const SrcA32 = m1[3][2]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB03 = m2[0][3]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB13 = m2[1][3]; + T const SrcB20 = m2[2][0]; + T const SrcB21 = m2[2][1]; + T const SrcB22 = m2[2][2]; + T const SrcB23 = m2[2][3]; + + mat<3, 3, T, Q> Result; + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02 + SrcA30 * SrcB03; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02 + SrcA31 * SrcB03; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02 + SrcA32 * SrcB03; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12 + SrcA30 * SrcB13; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12 + SrcA31 * SrcB13; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12 + SrcA32 * SrcB13; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22 + SrcA30 * SrcB23; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22 + SrcA31 * SrcB23; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22 + SrcA32 * SrcB23; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 3, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2] + m1[3][0] * m2[3][3], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2] + m1[3][1] * m2[3][3], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1] + m1[2][2] * m2[3][2] + m1[3][2] * m2[3][3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T const& s) + { + return mat<4, 3, T, Q>( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> operator/(T const& s, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +} //namespace glm diff --git a/vendor/glm/glm/detail/type_mat4x4.hpp b/vendor/glm/glm/detail/type_mat4x4.hpp new file mode 100644 index 0000000..3517f9f --- /dev/null +++ b/vendor/glm/glm/detail/type_mat4x4.hpp @@ -0,0 +1,189 @@ +/// @ref core +/// @file glm/detail/type_mat4x4.hpp + +#pragma once + +#include "type_vec4.hpp" +#include +#include + +namespace glm +{ + template + struct mat<4, 4, T, Q> + { + typedef vec<4, T, Q> col_type; + typedef vec<4, T, Q> row_type; + typedef mat<4, 4, T, Q> type; + typedef mat<4, 4, T, Q> transpose_type; + typedef T value_type; + + private: + col_type value[4]; + + public: + // -- Accesses -- + + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 4;} + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const; + + // -- Constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR mat() GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR mat(mat<4, 4, T, P> const& m); + + GLM_FUNC_DECL explicit GLM_CONSTEXPR mat(T const& x); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + T const& x0, T const& y0, T const& z0, T const& w0, + T const& x1, T const& y1, T const& z1, T const& w1, + T const& x2, T const& y2, T const& z2, T const& w2, + T const& x3, T const& y3, T const& z3, T const& w3); + GLM_FUNC_DECL GLM_CONSTEXPR mat( + col_type const& v0, + col_type const& v1, + col_type const& v2, + col_type const& v3); + + // -- Conversions -- + + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3, + typename X4, typename Y4, typename Z4, typename W4> + GLM_FUNC_DECL GLM_CONSTEXPR mat( + X1 const& x1, Y1 const& y1, Z1 const& z1, W1 const& w1, + X2 const& x2, Y2 const& y2, Z2 const& z2, W2 const& w2, + X3 const& x3, Y3 const& y3, Z3 const& z3, W3 const& w3, + X4 const& x4, Y4 const& y4, Z4 const& z4, W4 const& w4); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat( + vec<4, V1, Q> const& v1, + vec<4, V2, Q> const& v2, + vec<4, V3, Q> const& v3, + vec<4, V4, Q> const& v4); + + // -- Matrix conversions -- + + template + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 4, U, P> const& m); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 3, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<2, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 2, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<3, 4, T, Q> const& x); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator+=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator-=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator*=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator/=(U s); + template + GLM_FUNC_DECL mat<4, 4, T, Q> & operator/=(mat<4, 4, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL mat<4, 4, T, Q> & operator++(); + GLM_FUNC_DECL mat<4, 4, T, Q> & operator--(); + GLM_FUNC_DECL mat<4, 4, T, Q> operator++(int); + GLM_FUNC_DECL mat<4, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(T const& s, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(T const& s, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(T const& s, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<4, 4, T, Q>::col_type operator*(mat<4, 4, T, Q> const& m, typename mat<4, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<4, 4, T, Q>::row_type operator*(typename mat<4, 4, T, Q>::col_type const& v, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<2, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<3, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T const& s); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator/(T const& s, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL typename mat<4, 4, T, Q>::col_type operator/(mat<4, 4, T, Q> const& m, typename mat<4, 4, T, Q>::row_type const& v); + + template + GLM_FUNC_DECL typename mat<4, 4, T, Q>::row_type operator/(typename mat<4, 4, T, Q>::col_type const& v, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL bool operator!=(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x4.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/vendor/glm/glm/detail/type_mat4x4.inl b/vendor/glm/glm/detail/type_mat4x4.inl new file mode 100644 index 0000000..e38b87f --- /dev/null +++ b/vendor/glm/glm/detail/type_mat4x4.inl @@ -0,0 +1,706 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat() +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALIZER_LIST + : value{col_type(1, 0, 0, 0), col_type(0, 1, 0, 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INITIALISATION + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 4, T, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(T const& s) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(s, 0, 0, 0), col_type(0, s, 0, 0), col_type(0, 0, s, 0), col_type(0, 0, 0, s)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(s, 0, 0, 0); + this->value[1] = col_type(0, s, 0, 0); + this->value[2] = col_type(0, 0, s, 0); + this->value[3] = col_type(0, 0, 0, s); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat + ( + T const& x0, T const& y0, T const& z0, T const& w0, + T const& x1, T const& y1, T const& z1, T const& w1, + T const& x2, T const& y2, T const& z2, T const& w2, + T const& x3, T const& y3, T const& z3, T const& w3 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{ + col_type(x0, y0, z0, w0), + col_type(x1, y1, z1, w1), + col_type(x2, y2, z2, w2), + col_type(x3, y3, z3, w3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); + this->value[3] = col_type(x3, y3, z3, w3); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(col_type const& v0, col_type const& v1, col_type const& v2, col_type const& v3) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v0), col_type(v1), col_type(v2), col_type(v3)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 4, U, P> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(m[3])} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); +# endif + } + + // -- Conversions -- + + template + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3, + typename X4, typename Y4, typename Z4, typename W4> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat + ( + X1 const& x1, Y1 const& y1, Z1 const& z1, W1 const& w1, + X2 const& x2, Y2 const& y2, Z2 const& z2, W2 const& w2, + X3 const& x3, Y3 const& y3, Z3 const& z3, W3 const& w3, + X4 const& x4, Y4 const& y4, Z4 const& z4, W4 const& w4 + ) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(x1, y1, z1, w1), col_type(x2, y2, z2, w2), col_type(x3, y3, z3, w3), col_type(x4, y4, z4, w4)} +# endif + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 5th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 6th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 7th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 8th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 9th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 10th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 11th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 12th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 13th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 14th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 15th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 16th parameter type invalid."); + +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(x1, y1, z1, w1); + this->value[1] = col_type(x2, y2, z2, w2); + this->value[2] = col_type(x3, y3, z3, w3); + this->value[3] = col_type(x4, y4, z4, w4); +# endif + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(vec<4, V1, Q> const& v1, vec<4, V2, Q> const& v2, vec<4, V3, Q> const& v3, vec<4, V4, Q> const& v4) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(v1), col_type(v2), col_type(v3), col_type(v4)} +# endif + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || std::numeric_limits::is_integer || GLM_CONFIG_UNRESTRICTED_GENTYPE, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid."); + +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); +# endif + } + + // -- Matrix conversions -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<2, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<3, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<2, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<3, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(m[2], 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<2, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 2, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0, 0), col_type(m[1], 0, 0), col_type(0, 0, 1, 0), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<3, 4, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0]), col_type(m[1]), col_type(m[2]), col_type(0, 0, 0, 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q>::mat(mat<4, 3, T, Q> const& m) +# if GLM_HAS_INITIALIZER_LISTS + : value{col_type(m[0], 0), col_type(m[1], 0), col_type(m[2], 0), col_type(m[3], 1)} +# endif + { +# if !GLM_HAS_INITIALIZER_LISTS + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + this->value[3] = col_type(m[3], 1); +# endif + } + + // -- Accesses -- + + template + GLM_FUNC_QUALIFIER typename mat<4, 4, T, Q>::col_type & mat<4, 4, T, Q>::operator[](typename mat<4, 4, T, Q>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type const& mat<4, 4, T, Q>::operator[](typename mat<4, 4, T, Q>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } + + // -- Unary arithmetic operators -- + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q>& mat<4, 4, T, Q>::operator=(mat<4, 4, U, Q> const& m) + { + //memcpy could be faster + //memcpy(&this->value, &m.value, 16 * sizeof(valType)); + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q>& mat<4, 4, T, Q>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q>& mat<4, 4, T, Q>::operator+=(mat<4, 4, U, Q> const& m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator-=(mat<4, 4, U, Q> const& m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator*=(mat<4, 4, U, Q> const& m) + { + return (*this = *this * m); + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator/=(mat<4, 4, U, Q> const& m) + { + return *this *= inverse(m); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> & mat<4, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat<4, 4, T, Q>::operator++(int) + { + mat<4, 4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat<4, 4, T, Q>::operator--(int) + { + mat<4, 4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary constant operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T const& s) + { + return mat<4, 4, T, Q>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator+(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 4, T, Q>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T const& s) + { + return mat<4, 4, T, Q>( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator-(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + s - m[0], + s - m[1], + s - m[2], + s - m[3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return mat<4, 4, T, Q>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T const & s) + { + return mat<4, 4, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator*(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 4, T, Q>::col_type operator* + ( + mat<4, 4, T, Q> const& m, + typename mat<4, 4, T, Q>::row_type const& v + ) + { +/* + __m128 v0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 v1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 v2 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 v3 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(m[0].data, v0); + __m128 m1 = _mm_mul_ps(m[1].data, v1); + __m128 a0 = _mm_add_ps(m0, m1); + + __m128 m2 = _mm_mul_ps(m[2].data, v2); + __m128 m3 = _mm_mul_ps(m[3].data, v3); + __m128 a1 = _mm_add_ps(m2, m3); + + __m128 a2 = _mm_add_ps(a0, a1); + + return typename mat<4, 4, T, Q>::col_type(a2); +*/ + + typename mat<4, 4, T, Q>::col_type const Mov0(v[0]); + typename mat<4, 4, T, Q>::col_type const Mov1(v[1]); + typename mat<4, 4, T, Q>::col_type const Mul0 = m[0] * Mov0; + typename mat<4, 4, T, Q>::col_type const Mul1 = m[1] * Mov1; + typename mat<4, 4, T, Q>::col_type const Add0 = Mul0 + Mul1; + typename mat<4, 4, T, Q>::col_type const Mov2(v[2]); + typename mat<4, 4, T, Q>::col_type const Mov3(v[3]); + typename mat<4, 4, T, Q>::col_type const Mul2 = m[2] * Mov2; + typename mat<4, 4, T, Q>::col_type const Mul3 = m[3] * Mov3; + typename mat<4, 4, T, Q>::col_type const Add1 = Mul2 + Mul3; + typename mat<4, 4, T, Q>::col_type const Add2 = Add0 + Add1; + return Add2; + +/* + return typename mat<4, 4, T, Q>::col_type( + m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3], + m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3], + m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3], + m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]); +*/ + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 4, T, Q>::row_type operator* + ( + typename mat<4, 4, T, Q>::col_type const& v, + mat<4, 4, T, Q> const& m + ) + { + return typename mat<4, 4, T, Q>::row_type( + m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], + m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], + m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], + m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2) + { + return mat<2, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2) + { + return mat<3, 4, T, Q>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2] + m1[3][3] * m2[2][3]); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + typename mat<4, 4, T, Q>::col_type const SrcA0 = m1[0]; + typename mat<4, 4, T, Q>::col_type const SrcA1 = m1[1]; + typename mat<4, 4, T, Q>::col_type const SrcA2 = m1[2]; + typename mat<4, 4, T, Q>::col_type const SrcA3 = m1[3]; + + typename mat<4, 4, T, Q>::col_type const SrcB0 = m2[0]; + typename mat<4, 4, T, Q>::col_type const SrcB1 = m2[1]; + typename mat<4, 4, T, Q>::col_type const SrcB2 = m2[2]; + typename mat<4, 4, T, Q>::col_type const SrcB3 = m2[3]; + + mat<4, 4, T, Q> Result; + Result[0] = SrcA0 * SrcB0[0] + SrcA1 * SrcB0[1] + SrcA2 * SrcB0[2] + SrcA3 * SrcB0[3]; + Result[1] = SrcA0 * SrcB1[0] + SrcA1 * SrcB1[1] + SrcA2 * SrcB1[2] + SrcA3 * SrcB1[3]; + Result[2] = SrcA0 * SrcB2[0] + SrcA1 * SrcB2[1] + SrcA2 * SrcB2[2] + SrcA3 * SrcB2[3]; + Result[3] = SrcA0 * SrcB3[0] + SrcA1 * SrcB3[1] + SrcA2 * SrcB3[2] + SrcA3 * SrcB3[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T const& s) + { + return mat<4, 4, T, Q>( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator/(T const& s, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 4, T, Q>::col_type operator/(mat<4, 4, T, Q> const& m, typename mat<4, 4, T, Q>::row_type const& v) + { + return inverse(m) * v; + } + + template + GLM_FUNC_QUALIFIER typename mat<4, 4, T, Q>::row_type operator/(typename mat<4, 4, T, Q>::col_type const& v, mat<4, 4, T, Q> const& m) + { + return v * inverse(m); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + mat<4, 4, T, Q> m1_copy(m1); + return m1_copy /= m2; + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "type_mat4x4_simd.inl" +#endif diff --git a/vendor/glm/glm/detail/type_mat4x4_simd.inl b/vendor/glm/glm/detail/type_mat4x4_simd.inl new file mode 100644 index 0000000..fb3a16f --- /dev/null +++ b/vendor/glm/glm/detail/type_mat4x4_simd.inl @@ -0,0 +1,6 @@ +/// @ref core + +namespace glm +{ + +}//namespace glm diff --git a/vendor/glm/glm/detail/type_quat.hpp b/vendor/glm/glm/detail/type_quat.hpp new file mode 100644 index 0000000..0e60bc3 --- /dev/null +++ b/vendor/glm/glm/detail/type_quat.hpp @@ -0,0 +1,186 @@ +/// @ref core +/// @file glm/detail/type_quat.hpp + +#pragma once + +// Dependency: +#include "../detail/type_mat3x3.hpp" +#include "../detail/type_mat4x4.hpp" +#include "../detail/type_vec3.hpp" +#include "../detail/type_vec4.hpp" +#include "../ext/vector_relational.hpp" +#include "../ext/quaternion_relational.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/matrix_transform.hpp" + +namespace glm +{ + template + struct qua + { + // -- Implementation detail -- + + typedef qua type; + typedef T value_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + +# if GLM_LANG & GLM_LANG_CXXMS_FLAG + union + { +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + struct { T w, x, y, z; }; +# else + struct { T x, y, z, w; }; +# endif + + typename detail::storage<4, T, detail::is_aligned::value>::type data; + }; +# else +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + T w, x, y, z; +# else + T x, y, z, w; +# endif +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + typedef length_t length_type; + + /// Return the count of components of a quaternion + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 4;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR qua() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR qua(qua const& q) GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR qua(qua const& q); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR qua(T s, vec<3, T, Q> const& v); + GLM_FUNC_DECL GLM_CONSTEXPR qua(T w, T x, T y, T z); + + // -- Conversion constructors -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT qua(qua const& q); + + /// Explicit conversion operators +# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + GLM_FUNC_DECL explicit operator mat<3, 3, T, Q>() const; + GLM_FUNC_DECL explicit operator mat<4, 4, T, Q>() const; +# endif + + /// Create a quaternion from two normalized axis + /// + /// @param u A first normalized axis + /// @param v A second normalized axis + /// @see gtc_quaternion + /// @see http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors + GLM_FUNC_DECL qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v); + + /// Build a quaternion from euler angles (pitch, yaw, roll), in radians. + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT qua(vec<3, T, Q> const& eulerAngles); + GLM_FUNC_DECL GLM_EXPLICIT qua(mat<3, 3, T, Q> const& q); + GLM_FUNC_DECL GLM_EXPLICIT qua(mat<4, 4, T, Q> const& q); + + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR qua& operator=(qua const& q) GLM_DEFAULT; + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua& operator=(qua const& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR qua& operator+=(qua const& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR qua& operator-=(qua const& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR qua& operator*=(qua const& q); + template + GLM_FUNC_DECL GLM_CONSTEXPR qua& operator*=(U s); + template + GLM_FUNC_DECL GLM_CONSTEXPR qua& operator/=(U s); + }; + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator+(qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator-(qua const& q); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator+(qua const& q, qua const& p); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator-(qua const& q, qua const& p); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator*(qua const& q, qua const& p); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(qua const& q, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(qua const& q, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator*(qua const& q, T const& s); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator*(T const& s, qua const& q); + + template + GLM_FUNC_DECL GLM_CONSTEXPR qua operator/(qua const& q, T const& s); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(qua const& q1, qua const& q2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(qua const& q1, qua const& q2); +} //namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_quat.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/vendor/glm/glm/detail/type_quat.inl b/vendor/glm/glm/detail/type_quat.inl new file mode 100644 index 0000000..67b9310 --- /dev/null +++ b/vendor/glm/glm/detail/type_quat.inl @@ -0,0 +1,408 @@ +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include "../ext/quaternion_geometric.hpp" +#include + +namespace glm{ +namespace detail +{ + template + struct genTypeTrait > + { + static const genTypeEnum GENTYPE = GENTYPE_QUAT; + }; + + template + struct compute_dot, T, Aligned> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(qua const& a, qua const& b) + { + vec<4, T, Q> tmp(a.w * b.w, a.x * b.x, a.y * b.y, a.z * b.z); + return (tmp.x + tmp.y) + (tmp.z + tmp.w); + } + }; + + template + struct compute_quat_add + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, qua const& p) + { + return qua(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z); + } + }; + + template + struct compute_quat_sub + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, qua const& p) + { + return qua(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z); + } + }; + + template + struct compute_quat_mul_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, T s) + { + return qua(q.w * s, q.x * s, q.y * s, q.z * s); + } + }; + + template + struct compute_quat_div_scalar + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua call(qua const& q, T s) + { + return qua(q.w / s, q.x / s, q.y / s, q.z / s); + } + }; + + template + struct compute_quat_mul_vec4 + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(qua const& q, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w); + } + }; +}//namespace detail + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & qua::operator[](typename qua::length_type i) + { + assert(i >= 0 && i < this->length()); +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + return (&w)[i]; +# else + return (&x)[i]; +# endif + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& qua::operator[](typename qua::length_type i) const + { + assert(i >= 0 && i < this->length()); +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + return (&w)[i]; +# else + return (&x)[i]; +# endif + } + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(1), x(0), y(0), z(0) +# else + : x(0), y(0), z(0), w(1) +# endif +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(qua const& q) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(q.w), x(q.x), y(q.y), z(q.z) +# else + : x(q.x), y(q.y), z(q.z), w(q.w) +# endif + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(qua const& q) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(q.w), x(q.x), y(q.y), z(q.z) +# else + : x(q.x), y(q.y), z(q.z), w(q.w) +# endif + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(T s, vec<3, T, Q> const& v) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(s), x(v.x), y(v.y), z(v.z) +# else + : x(v.x), y(v.y), z(v.z), w(s) +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(T _w, T _x, T _y, T _z) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(_w), x(_x), y(_y), z(_z) +# else + : x(_x), y(_y), z(_z), w(_w) +# endif + {} + + // -- Conversion constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(qua const& q) +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(static_cast(q.w)), x(static_cast(q.x)), y(static_cast(q.y)), z(static_cast(q.z)) +# else + : x(static_cast(q.x)), y(static_cast(q.y)), z(static_cast(q.z)), w(static_cast(q.w)) +# endif + {} + + //template + //GLM_FUNC_QUALIFIER qua::qua + //( + // valType const& pitch, + // valType const& yaw, + // valType const& roll + //) + //{ + // vec<3, valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5)); + // vec<3, valType> c = glm::cos(eulerAngle * valType(0.5)); + // vec<3, valType> s = glm::sin(eulerAngle * valType(0.5)); + // + // this->w = c.x * c.y * c.z + s.x * s.y * s.z; + // this->x = s.x * c.y * c.z - c.x * s.y * s.z; + // this->y = c.x * s.y * c.z + s.x * c.y * s.z; + // this->z = c.x * c.y * s.z - s.x * s.y * c.z; + //} + + template + GLM_FUNC_QUALIFIER qua::qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v) + { + T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v)); + T real_part = norm_u_norm_v + dot(u, v); + vec<3, T, Q> t; + + if(real_part < static_cast(1.e-6f) * norm_u_norm_v) + { + // If u and v are exactly opposite, rotate 180 degrees + // around an arbitrary orthogonal axis. Axis normalisation + // can happen later, when we normalise the quaternion. + real_part = static_cast(0); + t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast(0)) : vec<3, T, Q>(static_cast(0), -u.z, u.y); + } + else + { + // Otherwise, build quaternion the standard way. + t = cross(u, v); + } + + *this = normalize(qua(real_part, t.x, t.y, t.z)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(vec<3, T, Q> const& eulerAngle) + { + vec<3, T, Q> c = glm::cos(eulerAngle * T(0.5)); + vec<3, T, Q> s = glm::sin(eulerAngle * T(0.5)); + + this->w = c.x * c.y * c.z + s.x * s.y * s.z; + this->x = s.x * c.y * c.z - c.x * s.y * s.z; + this->y = c.x * s.y * c.z + s.x * c.y * s.z; + this->z = c.x * c.y * s.z - s.x * s.y * c.z; + } + + template + GLM_FUNC_QUALIFIER qua::qua(mat<3, 3, T, Q> const& m) + { + *this = quat_cast(m); + } + + template + GLM_FUNC_QUALIFIER qua::qua(mat<4, 4, T, Q> const& m) + { + *this = quat_cast(m); + } + +# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + template + GLM_FUNC_QUALIFIER qua::operator mat<3, 3, T, Q>() const + { + return mat3_cast(*this); + } + + template + GLM_FUNC_QUALIFIER qua::operator mat<4, 4, T, Q>() const + { + return mat4_cast(*this); + } +# endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator=(qua const& q) + { + this->w = q.w; + this->x = q.x; + this->y = q.y; + this->z = q.z; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator=(qua const& q) + { + this->w = static_cast(q.w); + this->x = static_cast(q.x); + this->y = static_cast(q.y); + this->z = static_cast(q.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator+=(qua const& q) + { + return (*this = detail::compute_quat_add::value>::call(*this, qua(q))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator-=(qua const& q) + { + return (*this = detail::compute_quat_sub::value>::call(*this, qua(q))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator*=(qua const& r) + { + qua const p(*this); + qua const q(r); + + this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z; + this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y; + this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z; + this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator*=(U s) + { + return (*this = detail::compute_quat_mul_scalar::value>::call(*this, static_cast(s))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua & qua::operator/=(U s) + { + return (*this = detail::compute_quat_div_scalar::value>::call(*this, static_cast(s))); + } + + // -- Unary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator+(qua const& q) + { + return q; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator-(qua const& q) + { + return qua(-q.w, -q.x, -q.y, -q.z); + } + + // -- Binary operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator+(qua const& q, qua const& p) + { + return qua(q) += p; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator-(qua const& q, qua const& p) + { + return qua(q) -= p; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator*(qua const& q, qua const& p) + { + return qua(q) *= p; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua const& q, vec<3, T, Q> const& v) + { + vec<3, T, Q> const QuatVector(q.x, q.y, q.z); + vec<3, T, Q> const uv(glm::cross(QuatVector, v)); + vec<3, T, Q> const uuv(glm::cross(QuatVector, uv)); + + return v + ((uv * q.w) + uuv) * static_cast(2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(qua const& q, vec<4, T, Q> const& v) + { + return detail::compute_quat_mul_vec4::value>::call(q, v); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator*(qua const& q, T const& s) + { + return qua( + q.w * s, q.x * s, q.y * s, q.z * s); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator*(T const& s, qua const& q) + { + return q * s; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua operator/(qua const& q, T const& s) + { + return qua( + q.w / s, q.x / s, q.y / s, q.z / s); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(qua const& q1, qua const& q2) + { + return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(qua const& q1, qua const& q2) + { + return q1.x != q2.x || q1.y != q2.y || q1.z != q2.z || q1.w != q2.w; + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "type_quat_simd.inl" +#endif + diff --git a/vendor/glm/glm/detail/type_quat_simd.inl b/vendor/glm/glm/detail/type_quat_simd.inl new file mode 100644 index 0000000..3333e59 --- /dev/null +++ b/vendor/glm/glm/detail/type_quat_simd.inl @@ -0,0 +1,188 @@ +/// @ref core + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ +/* + template + struct compute_quat_mul + { + static qua call(qua const& q1, qua const& q2) + { + // SSE2 STATS: 11 shuffle, 8 mul, 8 add + // SSE4 STATS: 3 shuffle, 4 mul, 4 dpps + + __m128 const mul0 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(0, 1, 2, 3))); + __m128 const mul1 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(1, 0, 3, 2))); + __m128 const mul2 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(2, 3, 0, 1))); + __m128 const mul3 = _mm_mul_ps(q1.Data, q2.Data); + +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + __m128 const add0 = _mm_dp_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f), 0xff); + __m128 const add1 = _mm_dp_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f), 0xff); + __m128 const add2 = _mm_dp_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f), 0xff); + __m128 const add3 = _mm_dp_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f), 0xff); +# else + __m128 const mul4 = _mm_mul_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f)); + __m128 const add0 = _mm_add_ps(mul0, _mm_movehl_ps(mul4, mul4)); + __m128 const add4 = _mm_add_ss(add0, _mm_shuffle_ps(add0, add0, 1)); + + __m128 const mul5 = _mm_mul_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f)); + __m128 const add1 = _mm_add_ps(mul1, _mm_movehl_ps(mul5, mul5)); + __m128 const add5 = _mm_add_ss(add1, _mm_shuffle_ps(add1, add1, 1)); + + __m128 const mul6 = _mm_mul_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f)); + __m128 const add2 = _mm_add_ps(mul6, _mm_movehl_ps(mul6, mul6)); + __m128 const add6 = _mm_add_ss(add2, _mm_shuffle_ps(add2, add2, 1)); + + __m128 const mul7 = _mm_mul_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f)); + __m128 const add3 = _mm_add_ps(mul3, _mm_movehl_ps(mul7, mul7)); + __m128 const add7 = _mm_add_ss(add3, _mm_shuffle_ps(add3, add3, 1)); + #endif + + // This SIMD code is a politically correct way of doing this, but in every test I've tried it has been slower than + // the final code below. I'll keep this here for reference - maybe somebody else can do something better... + // + //__m128 xxyy = _mm_shuffle_ps(add4, add5, _MM_SHUFFLE(0, 0, 0, 0)); + //__m128 zzww = _mm_shuffle_ps(add6, add7, _MM_SHUFFLE(0, 0, 0, 0)); + // + //return _mm_shuffle_ps(xxyy, zzww, _MM_SHUFFLE(2, 0, 2, 0)); + + qua Result; + _mm_store_ss(&Result.x, add4); + _mm_store_ss(&Result.y, add5); + _mm_store_ss(&Result.z, add6); + _mm_store_ss(&Result.w, add7); + return Result; + } + }; +*/ + + template + struct compute_quat_add + { + static qua call(qua const& q, qua const& p) + { + qua Result; + Result.data = _mm_add_ps(q.data, p.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_add + { + static qua call(qua const& a, qua const& b) + { + qua Result; + Result.data = _mm256_add_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_quat_sub + { + static qua call(qua const& q, qua const& p) + { + vec<4, float, Q> Result; + Result.data = _mm_sub_ps(q.data, p.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_sub + { + static qua call(qua const& a, qua const& b) + { + qua Result; + Result.data = _mm256_sub_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_quat_mul_scalar + { + static qua call(qua const& q, float s) + { + vec<4, float, Q> Result; + Result.data = _mm_mul_ps(q.data, _mm_set_ps1(s)); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_mul_scalar + { + static qua call(qua const& q, double s) + { + qua Result; + Result.data = _mm256_mul_pd(q.data, _mm_set_ps1(s)); + return Result; + } + }; +# endif + + template + struct compute_quat_div_scalar + { + static qua call(qua const& q, float s) + { + vec<4, float, Q> Result; + Result.data = _mm_div_ps(q.data, _mm_set_ps1(s)); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_quat_div_scalar + { + static qua call(qua const& q, double s) + { + qua Result; + Result.data = _mm256_div_pd(q.data, _mm_set_ps1(s)); + return Result; + } + }; +# endif + + template + struct compute_quat_mul_vec4 + { + static vec<4, float, Q> call(qua const& q, vec<4, float, Q> const& v) + { + __m128 const q_wwww = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 3, 3, 3)); + __m128 const q_swp0 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const q_swp1 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 const v_swp0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 const v_swp1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 1, 0, 2)); + + __m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); + __m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); + + __m128 const two = _mm_set1_ps(2.0f); + uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); + uuv = _mm_mul_ps(uuv, two); + + vec<4, float, Q> Result; + Result.data = _mm_add_ps(v.Data, _mm_add_ps(uv, uuv)); + return Result; + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + diff --git a/vendor/glm/glm/detail/type_vec1.hpp b/vendor/glm/glm/detail/type_vec1.hpp new file mode 100644 index 0000000..51163f1 --- /dev/null +++ b/vendor/glm/glm/detail/type_vec1.hpp @@ -0,0 +1,308 @@ +/// @ref core +/// @file glm/detail/type_vec1.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<1, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<1, T, Q> type; + typedef vec<1, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x; +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + T x; + T r; + T s; + + typename detail::storage<1, T, detail::is_aligned::value>::type data; +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + _GLM_SWIZZLE1_2_MEMBERS(T, Q, x) + _GLM_SWIZZLE1_2_MEMBERS(T, Q, r) + _GLM_SWIZZLE1_2_MEMBERS(T, Q, s) + _GLM_SWIZZLE1_3_MEMBERS(T, Q, x) + _GLM_SWIZZLE1_3_MEMBERS(T, Q, r) + _GLM_SWIZZLE1_3_MEMBERS(T, Q, s) + _GLM_SWIZZLE1_4_MEMBERS(T, Q, x) + _GLM_SWIZZLE1_4_MEMBERS(T, Q, r) + _GLM_SWIZZLE1_4_MEMBERS(T, Q, s) +# endif +*/ + }; +# else + union {T x, r, s;}; +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC1(T, Q) +# endif +*/ +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 1;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(T scalar); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<2, U, P> const& v); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<3, U, P> const& v); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<4, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<1, U, P> const& v); + + // -- Swizzle constructors -- +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<1, T, Q, E0, -1,-2,-3> const& that) + { + *this = that(); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +*/ + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(vec<1, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator++(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator>>=(vec<1, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(T scalar, vec<1, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> operator~(vec<1, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, bool, Q> operator&&(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<1, bool, Q> operator||(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec1.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/vendor/glm/glm/detail/type_vec1.inl b/vendor/glm/glm/detail/type_vec1.inl new file mode 100644 index 0000000..c5883ce --- /dev/null +++ b/vendor/glm/glm/detail/type_vec1.inl @@ -0,0 +1,551 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0) +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, T, Q> const& v) + : x(v.x) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, T, P> const& v) + : x(v.x) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(T scalar) + : x(scalar) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<2, U, P> const& v) + : x(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<1, T, Q>::operator[](typename vec<1, T, Q>::length_type) + { + return x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<1, T, Q>::operator[](typename vec<1, T, Q>::length_type) const + { + return x; + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator=(vec<1, T, Q> const& v) + { + this->x = v.x; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator=(vec<1, U, Q> const& v) + { + this->x = static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator+=(U scalar) + { + this->x += static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator-=(U scalar) + { + this->x -= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator*=(U scalar) + { + this->x *= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator/=(U scalar) + { + this->x /= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast(v.x); + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator++() + { + ++this->x; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator--() + { + --this->x; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> vec<1, T, Q>::operator++(int) + { + vec<1, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> vec<1, T, Q>::operator--(int) + { + vec<1, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator%=(U scalar) + { + this->x %= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator&=(U scalar) + { + this->x &= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator|=(U scalar) + { + this->x |= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= U(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator^=(U scalar) + { + this->x ^= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator<<=(U scalar) + { + this->x <<= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> & vec<1, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast(v.x); + return *this; + } + + // -- Unary constant operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + -v.x); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar + v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator+(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x + v2.x); + } + + //operator- + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar - v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator-(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x - v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator*(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar * v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator*(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x * v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator/(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar / v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator/(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x / v2.x); + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x % scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator%(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar % v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator%(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x % v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x & scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator&(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar & v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator&(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x & v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x | scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator|(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar | v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator|(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x | v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + v.x ^ scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator^(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + scalar ^ v.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator^(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + v1.x ^ v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + static_cast(v.x << scalar)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator<<(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + static_cast(scalar << v.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator<<(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + static_cast(v1.x << v2.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v, T scalar) + { + return vec<1, T, Q>( + static_cast(v.x >> scalar)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator>>(T scalar, vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + static_cast(scalar >> v.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator>>(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<1, T, Q>( + static_cast(v1.x >> v2.x)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, T, Q> operator~(vec<1, T, Q> const& v) + { + return vec<1, T, Q>( + ~v.x); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return detail::compute_equal::is_iec559>::call(v1.x, v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<1, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return !(v1 == v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, bool, Q> operator&&(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2) + { + return vec<1, bool, Q>(v1.x && v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<1, bool, Q> operator||(vec<1, bool, Q> const& v1, vec<1, bool, Q> const& v2) + { + return vec<1, bool, Q>(v1.x || v2.x); + } +}//namespace glm diff --git a/vendor/glm/glm/detail/type_vec2.hpp b/vendor/glm/glm/detail/type_vec2.hpp new file mode 100644 index 0000000..52ef408 --- /dev/null +++ b/vendor/glm/glm/detail/type_vec2.hpp @@ -0,0 +1,399 @@ +/// @ref core +/// @file glm/detail/type_vec2.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<2, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<2, T, Q> type; + typedef vec<2, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x, y; +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + struct{ T x, y; }; + struct{ T r, g; }; + struct{ T s, t; }; + + typename detail::storage<2, T, detail::is_aligned::value>::type data; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + GLM_SWIZZLE2_2_MEMBERS(T, Q, x, y) + GLM_SWIZZLE2_2_MEMBERS(T, Q, r, g) + GLM_SWIZZLE2_2_MEMBERS(T, Q, s, t) + GLM_SWIZZLE2_3_MEMBERS(T, Q, x, y) + GLM_SWIZZLE2_3_MEMBERS(T, Q, r, g) + GLM_SWIZZLE2_3_MEMBERS(T, Q, s, t) + GLM_SWIZZLE2_4_MEMBERS(T, Q, x, y) + GLM_SWIZZLE2_4_MEMBERS(T, Q, r, g) + GLM_SWIZZLE2_4_MEMBERS(T, Q, s, t) +# endif + }; +# else + union {T x, r, s;}; + union {T y, g, t;}; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC2(T, Q) +# endif//GLM_CONFIG_SWIZZLE +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 2;} + + GLM_FUNC_DECL GLM_CONSTEXPR T& operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR vec(T x, T y); + + // -- Conversion constructors -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(vec<1, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A x, B y); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, Q> const& x, B y); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A x, vec<1, B, Q> const& y); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, Q> const& x, vec<1, B, Q> const& y); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<3, U, P> const& v); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<4, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<2, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<2, T, Q, E0, E1,-1,-2> const& that) + { + *this = that(); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<2, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator++(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<2, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(vec<2, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(T scalar, vec<2, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> operator~(vec<2, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, bool, Q> operator&&(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<2, bool, Q> operator||(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec2.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/vendor/glm/glm/detail/type_vec2.inl b/vendor/glm/glm/detail/type_vec2.inl new file mode 100644 index 0000000..8e65d6b --- /dev/null +++ b/vendor/glm/glm/detail/type_vec2.inl @@ -0,0 +1,913 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0) +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, T, Q> const& v) + : x(v.x), y(v.y) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, T, P> const& v) + : x(v.x), y(v.y) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(T scalar) + : x(scalar), y(scalar) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(T _x, T _y) + : x(_x), y(_y) + {} + + // -- Conversion scalar constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(A _x, B _y) + : x(static_cast(_x)) + , y(static_cast(_y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, A, Q> const& _x, B _y) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(A _x, vec<1, B, Q> const& _y) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<1, A, Q> const& _x, vec<1, B, Q> const& _y) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<2, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<2, T, Q>::operator[](typename vec<2, T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<2, T, Q>::operator[](typename vec<2, T, Q>::length_type i) const + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + } + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator=(vec<2, T, Q> const& v) + { + this->x = v.x; + this->y = v.y; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator=(vec<2, U, Q> const& v) + { + this->x = static_cast(v.x); + this->y = static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(U scalar) + { + this->x += static_cast(scalar); + this->y += static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator+=(vec<2, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(U scalar) + { + this->x -= static_cast(scalar); + this->y -= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator-=(vec<2, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(U scalar) + { + this->x *= static_cast(scalar); + this->y *= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator*=(vec<2, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(U scalar) + { + this->x /= static_cast(scalar); + this->y /= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator/=(vec<2, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.y); + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator++() + { + ++this->x; + ++this->y; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator--() + { + --this->x; + --this->y; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> vec<2, T, Q>::operator++(int) + { + vec<2, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> vec<2, T, Q>::operator--(int) + { + vec<2, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(U scalar) + { + this->x %= static_cast(scalar); + this->y %= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= static_cast(v.x); + this->y %= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator%=(vec<2, U, Q> const& v) + { + this->x %= static_cast(v.x); + this->y %= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(U scalar) + { + this->x &= static_cast(scalar); + this->y &= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= static_cast(v.x); + this->y &= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator&=(vec<2, U, Q> const& v) + { + this->x &= static_cast(v.x); + this->y &= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(U scalar) + { + this->x |= static_cast(scalar); + this->y |= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= static_cast(v.x); + this->y |= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator|=(vec<2, U, Q> const& v) + { + this->x |= static_cast(v.x); + this->y |= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(U scalar) + { + this->x ^= static_cast(scalar); + this->y ^= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= static_cast(v.x); + this->y ^= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator^=(vec<2, U, Q> const& v) + { + this->x ^= static_cast(v.x); + this->y ^= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(U scalar) + { + this->x <<= static_cast(scalar); + this->y <<= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator<<=(vec<2, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.y); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast(scalar); + this->y >>= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> & vec<2, T, Q>::operator>>=(vec<2, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.y); + return *this; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + -v.x, + -v.y); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x + scalar, + v.y + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x + v2.x, + v1.y + v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar + v.x, + scalar + v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x + v2.x, + v1.x + v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator+(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x + v2.x, + v1.y + v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x - scalar, + v.y - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x - v2.x, + v1.y - v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar - v.x, + scalar - v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x - v2.x, + v1.x - v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator-(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x - v2.x, + v1.y - v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x * scalar, + v.y * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x * v2.x, + v1.y * v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar * v.x, + scalar * v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x * v2.x, + v1.x * v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator*(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x * v2.x, + v1.y * v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x / scalar, + v.y / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x / v2.x, + v1.y / v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar / v.x, + scalar / v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x / v2.x, + v1.x / v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator/(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x / v2.x, + v1.y / v2.y); + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x % scalar, + v.y % scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x % v2.x, + v1.y % v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar % v.x, + scalar % v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x % v2.x, + v1.x % v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator%(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x % v2.x, + v1.y % v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x & scalar, + v.y & scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x & v2.x, + v1.y & v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar & v.x, + scalar & v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x & v2.x, + v1.x & v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator&(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x & v2.x, + v1.y & v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x | scalar, + v.y | scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x | v2.x, + v1.y | v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar | v.x, + scalar | v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x | v2.x, + v1.x | v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator|(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x | v2.x, + v1.y | v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x ^ scalar, + v.y ^ scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x ^ v2.x, + v1.y ^ v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar ^ v.x, + scalar ^ v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x ^ v2.x, + v1.x ^ v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator^(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x ^ v2.x, + v1.y ^ v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x << scalar, + v.y << scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x << v2.x, + v1.y << v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar << v.x, + scalar << v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x << v2.x, + v1.x << v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator<<(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x << v2.x, + v1.y << v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v, T scalar) + { + return vec<2, T, Q>( + v.x >> scalar, + v.y >> scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x >> v2.x, + v1.y >> v2.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(T scalar, vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + scalar >> v.x, + scalar >> v.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<1, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x >> v2.x, + v1.x >> v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator>>(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return vec<2, T, Q>( + v1.x >> v2.x, + v1.y >> v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, T, Q> operator~(vec<2, T, Q> const& v) + { + return vec<2, T, Q>( + ~v.x, + ~v.y); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return + detail::compute_equal::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal::is_iec559>::call(v1.y, v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<2, T, Q> const& v1, vec<2, T, Q> const& v2) + { + return !(v1 == v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, bool, Q> operator&&(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2) + { + return vec<2, bool, Q>(v1.x && v2.x, v1.y && v2.y); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<2, bool, Q> operator||(vec<2, bool, Q> const& v1, vec<2, bool, Q> const& v2) + { + return vec<2, bool, Q>(v1.x || v2.x, v1.y || v2.y); + } +}//namespace glm diff --git a/vendor/glm/glm/detail/type_vec3.hpp b/vendor/glm/glm/detail/type_vec3.hpp new file mode 100644 index 0000000..d83cde6 --- /dev/null +++ b/vendor/glm/glm/detail/type_vec3.hpp @@ -0,0 +1,432 @@ +/// @ref core +/// @file glm/detail/type_vec3.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<3, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<3, T, Q> type; + typedef vec<3, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +# pragma warning(disable: 4324) // structure was padded due to alignment specifier +# endif +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x, y, z; +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + struct{ T x, y, z; }; + struct{ T r, g, b; }; + struct{ T s, t, p; }; + + typename detail::storage<3, T, detail::is_aligned::value>::type data; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + GLM_SWIZZLE3_2_MEMBERS(T, Q, x, y, z) + GLM_SWIZZLE3_2_MEMBERS(T, Q, r, g, b) + GLM_SWIZZLE3_2_MEMBERS(T, Q, s, t, p) + GLM_SWIZZLE3_3_MEMBERS(T, Q, x, y, z) + GLM_SWIZZLE3_3_MEMBERS(T, Q, r, g, b) + GLM_SWIZZLE3_3_MEMBERS(T, Q, s, t, p) + GLM_SWIZZLE3_4_MEMBERS(T, Q, x, y, z) + GLM_SWIZZLE3_4_MEMBERS(T, Q, r, g, b) + GLM_SWIZZLE3_4_MEMBERS(T, Q, s, t, p) +# endif + }; +# else + union { T x, r, s; }; + union { T y, g, t; }; + union { T z, b, p; }; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC3(T, Q) +# endif//GLM_CONFIG_SWIZZLE +# endif//GLM_LANG + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 3;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<3, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR vec(T a, T b, T c); + + // -- Conversion scalar constructors -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(vec<1, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X x, Y y, Z z); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, Z _z); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, Z _z); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, vec<1, Z, Q> const& _z); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, A, P> const& _xy, B _z); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A _x, vec<2, B, P> const& _yz); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<4, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<3, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& that) + { + *this = that(); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, T const& scalar) + { + *this = vec(v(), scalar); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(T const& scalar, detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v) + { + *this = vec(scalar, v()); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q>& operator=(vec<3, T, Q> const& v) GLM_DEFAULT; + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<3, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator++(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<3, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(vec<3, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(T scalar, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<1, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q> operator~(vec<3, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, bool, Q> operator&&(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<3, bool, Q> operator||(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec3.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/vendor/glm/glm/detail/type_vec3.inl b/vendor/glm/glm/detail/type_vec3.inl new file mode 100644 index 0000000..6532c9e --- /dev/null +++ b/vendor/glm/glm/detail/type_vec3.inl @@ -0,0 +1,1068 @@ +/// @ref core + +#include "compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0), z(0) +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<3, T, Q> const& v) + : x(v.x), y(v.y), z(v.z) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<3, T, P> const& v) + : x(v.x), y(v.y), z(v.z) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(T scalar) + : x(scalar), y(scalar), z(scalar) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(T _x, T _y, T _z) + : x(_x), y(_y), z(_z) + {} + + // -- Conversion scalar constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.x)) + , z(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, Y _y, Z _z) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, Z _z) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, Z _z) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, Y _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<2, A, P> const& _xy, B _z) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(A _x, vec<2, B, P> const& _yz) + : x(static_cast(_x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz) + : x(static_cast(_x.x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<3, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + , z(static_cast(v.z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + , z(static_cast(v.z)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & vec<3, T, Q>::operator[](typename vec<3, T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<3, T, Q>::operator[](typename vec<3, T, Q>::length_type i) const + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + } + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>& vec<3, T, Q>::operator=(vec<3, T, Q> const& v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>& vec<3, T, Q>::operator=(vec<3, U, Q> const& v) + { + this->x = static_cast(v.x); + this->y = static_cast(v.y); + this->z = static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(U scalar) + { + this->x += static_cast(scalar); + this->y += static_cast(scalar); + this->z += static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(vec<1, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.x); + this->z += static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator+=(vec<3, U, Q> const& v) + { + this->x += static_cast(v.x); + this->y += static_cast(v.y); + this->z += static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(U scalar) + { + this->x -= static_cast(scalar); + this->y -= static_cast(scalar); + this->z -= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(vec<1, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.x); + this->z -= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator-=(vec<3, U, Q> const& v) + { + this->x -= static_cast(v.x); + this->y -= static_cast(v.y); + this->z -= static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(U scalar) + { + this->x *= static_cast(scalar); + this->y *= static_cast(scalar); + this->z *= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(vec<1, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.x); + this->z *= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator*=(vec<3, U, Q> const& v) + { + this->x *= static_cast(v.x); + this->y *= static_cast(v.y); + this->z *= static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(U v) + { + this->x /= static_cast(v); + this->y /= static_cast(v); + this->z /= static_cast(v); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(vec<1, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.x); + this->z /= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator/=(vec<3, U, Q> const& v) + { + this->x /= static_cast(v.x); + this->y /= static_cast(v.y); + this->z /= static_cast(v.z); + return *this; + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator++() + { + ++this->x; + ++this->y; + ++this->z; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator--() + { + --this->x; + --this->y; + --this->z; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> vec<3, T, Q>::operator++(int) + { + vec<3, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> vec<3, T, Q>::operator--(int) + { + vec<3, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator%=(U scalar) + { + this->x %= scalar; + this->y %= scalar; + this->z %= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator%=(vec<1, U, Q> const& v) + { + this->x %= v.x; + this->y %= v.x; + this->z %= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator%=(vec<3, U, Q> const& v) + { + this->x %= v.x; + this->y %= v.y; + this->z %= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator&=(U scalar) + { + this->x &= scalar; + this->y &= scalar; + this->z &= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator&=(vec<1, U, Q> const& v) + { + this->x &= v.x; + this->y &= v.x; + this->z &= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator&=(vec<3, U, Q> const& v) + { + this->x &= v.x; + this->y &= v.y; + this->z &= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator|=(U scalar) + { + this->x |= scalar; + this->y |= scalar; + this->z |= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator|=(vec<1, U, Q> const& v) + { + this->x |= v.x; + this->y |= v.x; + this->z |= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator|=(vec<3, U, Q> const& v) + { + this->x |= v.x; + this->y |= v.y; + this->z |= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator^=(U scalar) + { + this->x ^= scalar; + this->y ^= scalar; + this->z ^= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator^=(vec<1, U, Q> const& v) + { + this->x ^= v.x; + this->y ^= v.x; + this->z ^= v.x; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator^=(vec<3, U, Q> const& v) + { + this->x ^= v.x; + this->y ^= v.y; + this->z ^= v.z; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(U scalar) + { + this->x <<= scalar; + this->y <<= scalar; + this->z <<= scalar; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.x); + this->z <<= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator<<=(vec<3, U, Q> const& v) + { + this->x <<= static_cast(v.x); + this->y <<= static_cast(v.y); + this->z <<= static_cast(v.z); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(U scalar) + { + this->x >>= static_cast(scalar); + this->y >>= static_cast(scalar); + this->z >>= static_cast(scalar); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.x); + this->z >>= static_cast(v.x); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> & vec<3, T, Q>::operator>>=(vec<3, U, Q> const& v) + { + this->x >>= static_cast(v.x); + this->y >>= static_cast(v.y); + this->z >>= static_cast(v.z); + return *this; + } + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + -v.x, + -v.y, + -v.z); + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x + scalar, + v.y + scalar, + v.z + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x + scalar.x, + v.y + scalar.x, + v.z + scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar + v.x, + scalar + v.y, + scalar + v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x + v.x, + scalar.x + v.y, + scalar.x + v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator+(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x + v2.x, + v1.y + v2.y, + v1.z + v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x - scalar, + v.y - scalar, + v.z - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x - scalar.x, + v.y - scalar.x, + v.z - scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar - v.x, + scalar - v.y, + scalar - v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x - v.x, + scalar.x - v.y, + scalar.x - v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator-(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x - v2.x, + v1.y - v2.y, + v1.z - v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x * scalar, + v.y * scalar, + v.z * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x * scalar.x, + v.y * scalar.x, + v.z * scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar * v.x, + scalar * v.y, + scalar * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x * v.x, + scalar.x * v.y, + scalar.x * v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x * v2.x, + v1.y * v2.y, + v1.z * v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x / scalar, + v.y / scalar, + v.z / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x / scalar.x, + v.y / scalar.x, + v.z / scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar / v.x, + scalar / v.y, + scalar / v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x / v.x, + scalar.x / v.y, + scalar.x / v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator/(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x / v2.x, + v1.y / v2.y, + v1.z / v2.z); + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x % scalar, + v.y % scalar, + v.z % scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x % scalar.x, + v.y % scalar.x, + v.z % scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar % v.x, + scalar % v.y, + scalar % v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x % v.x, + scalar.x % v.y, + scalar.x % v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator%(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x % v2.x, + v1.y % v2.y, + v1.z % v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x & scalar, + v.y & scalar, + v.z & scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x & scalar.x, + v.y & scalar.x, + v.z & scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar & v.x, + scalar & v.y, + scalar & v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x & v.x, + scalar.x & v.y, + scalar.x & v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator&(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x & v2.x, + v1.y & v2.y, + v1.z & v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x | scalar, + v.y | scalar, + v.z | scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x | scalar.x, + v.y | scalar.x, + v.z | scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar | v.x, + scalar | v.y, + scalar | v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x | v.x, + scalar.x | v.y, + scalar.x | v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator|(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x | v2.x, + v1.y | v2.y, + v1.z | v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x ^ scalar, + v.y ^ scalar, + v.z ^ scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x ^ scalar.x, + v.y ^ scalar.x, + v.z ^ scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar ^ v.x, + scalar ^ v.y, + scalar ^ v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x ^ v.x, + scalar.x ^ v.y, + scalar.x ^ v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator^(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x ^ v2.x, + v1.y ^ v2.y, + v1.z ^ v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x << scalar, + v.y << scalar, + v.z << scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x << scalar.x, + v.y << scalar.x, + v.z << scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar << v.x, + scalar << v.y, + scalar << v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x << v.x, + scalar.x << v.y, + scalar.x << v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator<<(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x << v2.x, + v1.y << v2.y, + v1.z << v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v, T scalar) + { + return vec<3, T, Q>( + v.x >> scalar, + v.y >> scalar, + v.z >> scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<3, T, Q>( + v.x >> scalar.x, + v.y >> scalar.x, + v.z >> scalar.x); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(T scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar >> v.x, + scalar >> v.y, + scalar >> v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<1, T, Q> const& scalar, vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + scalar.x >> v.x, + scalar.x >> v.y, + scalar.x >> v.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator>>(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return vec<3, T, Q>( + v1.x >> v2.x, + v1.y >> v2.y, + v1.z >> v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator~(vec<3, T, Q> const& v) + { + return vec<3, T, Q>( + ~v.x, + ~v.y, + ~v.z); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return + detail::compute_equal::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal::is_iec559>::call(v1.y, v2.y) && + detail::compute_equal::is_iec559>::call(v1.z, v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<3, T, Q> const& v1, vec<3, T, Q> const& v2) + { + return !(v1 == v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, bool, Q> operator&&(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2) + { + return vec<3, bool, Q>(v1.x && v2.x, v1.y && v2.y, v1.z && v2.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, bool, Q> operator||(vec<3, bool, Q> const& v1, vec<3, bool, Q> const& v2) + { + return vec<3, bool, Q>(v1.x || v2.x, v1.y || v2.y, v1.z || v2.z); + } +}//namespace glm diff --git a/vendor/glm/glm/detail/type_vec4.hpp b/vendor/glm/glm/detail/type_vec4.hpp new file mode 100644 index 0000000..4a36434 --- /dev/null +++ b/vendor/glm/glm/detail/type_vec4.hpp @@ -0,0 +1,505 @@ +/// @ref core +/// @file glm/detail/type_vec4.hpp + +#pragma once + +#include "qualifier.hpp" +#if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR +# include "_swizzle.hpp" +#elif GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION +# include "_swizzle_func.hpp" +#endif +#include + +namespace glm +{ + template + struct vec<4, T, Q> + { + // -- Implementation detail -- + + typedef T value_type; + typedef vec<4, T, Q> type; + typedef vec<4, bool, Q> bool_type; + + // -- Data -- + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wpedantic" +# elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wgnu-anonymous-struct" +# pragma clang diagnostic ignored "-Wnested-anon-types" +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable: 4201) // nonstandard extension used : nameless struct/union +# endif +# endif + +# if GLM_CONFIG_XYZW_ONLY + T x, y, z, w; +# elif GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE + union + { + struct { T x, y, z, w; }; + struct { T r, g, b, a; }; + struct { T s, t, p, q; }; + + typename detail::storage<4, T, detail::is_aligned::value>::type data; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + GLM_SWIZZLE4_2_MEMBERS(T, Q, x, y, z, w) + GLM_SWIZZLE4_2_MEMBERS(T, Q, r, g, b, a) + GLM_SWIZZLE4_2_MEMBERS(T, Q, s, t, p, q) + GLM_SWIZZLE4_3_MEMBERS(T, Q, x, y, z, w) + GLM_SWIZZLE4_3_MEMBERS(T, Q, r, g, b, a) + GLM_SWIZZLE4_3_MEMBERS(T, Q, s, t, p, q) + GLM_SWIZZLE4_4_MEMBERS(T, Q, x, y, z, w) + GLM_SWIZZLE4_4_MEMBERS(T, Q, r, g, b, a) + GLM_SWIZZLE4_4_MEMBERS(T, Q, s, t, p, q) +# endif + }; +# else + union { T x, r, s; }; + union { T y, g, t; }; + union { T z, b, p; }; + union { T w, a, q; }; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC4(T, Q) +# endif +# endif + +# if GLM_SILENT_WARNINGS == GLM_ENABLE +# if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif +# endif + + // -- Component accesses -- + + typedef length_t length_type; + + /// Return the count of components of the vector + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 4;} + + GLM_FUNC_DECL GLM_CONSTEXPR T & operator[](length_type i); + GLM_FUNC_DECL GLM_CONSTEXPR T const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<4, T, Q> const& v) GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<4, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(T scalar); + GLM_FUNC_DECL GLM_CONSTEXPR vec(T x, T y, T z, T w); + + // -- Conversion scalar constructors -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR explicit vec(vec<1, U, P> const& v); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, Z _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, Z _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _Y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + + // -- Conversion vector constructors -- + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, A, P> const& _xy, B _z, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, A, P> const& _xy, B _z, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A _x, vec<2, B, P> const& _yz, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, C _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A _x, B _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, P> const& _x, B _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, P> const& _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<3, A, P> const& _xyz, B _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<3, A, P> const& _xyz, vec<1, B, P> const& _w); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(A _x, vec<3, B, P> const& _yzw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<1, A, P> const& _x, vec<3, B, P> const& _yzw); + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(vec<2, A, P> const& _xy, vec<2, B, P> const& _zw); + + /// Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT vec(vec<4, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<4, T, Q, E0, E1, E2, E3> const& that) + { + *this = that(); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, detail::_swizzle<2, T, Q, F0, F1, -1, -2> const& u) + { + *this = vec<4, T, Q>(v(), u()); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(T const& x, T const& y, detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v) + { + *this = vec<4, T, Q>(x, y, v()); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(T const& x, detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, T const& w) + { + *this = vec<4, T, Q>(x, v(), w); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<2, T, Q, E0, E1, -1, -2> const& v, T const& z, T const& w) + { + *this = vec<4, T, Q>(v(), z, w); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& v, T const& w) + { + *this = vec<4, T, Q>(v(), w); + } + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec(T const& x, detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& v) + { + *this = vec<4, T, Q>(x, v()); + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, T, Q> const& v) GLM_DEFAULT; + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<4, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator++(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator--(int); + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator%=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator&=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator|=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator^=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator<<=(vec<4, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> & operator>>=(vec<4, U, Q> const& v); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v, T const & scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v, T const & scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, T const & scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v, T const & scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(T scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q> operator~(vec<4, T, Q> const& v); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator!=(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> operator&&(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec<4, bool, Q> operator||(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec4.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/vendor/glm/glm/detail/type_vec4.inl b/vendor/glm/glm/detail/type_vec4.inl new file mode 100644 index 0000000..3c212d9 --- /dev/null +++ b/vendor/glm/glm/detail/type_vec4.inl @@ -0,0 +1,1140 @@ +/// @ref core + +#include "compute_vector_relational.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_vec4_add + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w); + } + }; + + template + struct compute_vec4_sub + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w); + } + }; + + template + struct compute_vec4_mul + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w); + } + }; + + template + struct compute_vec4_div + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w); + } + }; + + template + struct compute_vec4_mod + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x % b.x, a.y % b.y, a.z % b.z, a.w % b.w); + } + }; + + template + struct compute_vec4_and + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x & b.x, a.y & b.y, a.z & b.z, a.w & b.w); + } + }; + + template + struct compute_vec4_or + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x | b.x, a.y | b.y, a.z | b.z, a.w | b.w); + } + }; + + template + struct compute_vec4_xor + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x ^ b.x, a.y ^ b.y, a.z ^ b.z, a.w ^ b.w); + } + }; + + template + struct compute_vec4_shift_left + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x << b.x, a.y << b.y, a.z << b.z, a.w << b.w); + } + }; + + template + struct compute_vec4_shift_right + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + return vec<4, T, Q>(a.x >> b.x, a.y >> b.y, a.z >> b.z, a.w >> b.w); + } + }; + + template + struct compute_vec4_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return + detail::compute_equal::is_iec559>::call(v1.x, v2.x) && + detail::compute_equal::is_iec559>::call(v1.y, v2.y) && + detail::compute_equal::is_iec559>::call(v1.z, v2.z) && + detail::compute_equal::is_iec559>::call(v1.w, v2.w); + } + }; + + template + struct compute_vec4_nequal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return !compute_vec4_equal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + }; + + template + struct compute_vec4_bitwise_not + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(vec<4, T, Q> const& v) + { + return vec<4, T, Q>(~v.x, ~v.y, ~v.z, ~v.w); + } + }; +}//namespace detail + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0), z(0), w(0) +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<4, T, Q> const& v) + : x(v.x), y(v.y), z(v.z), w(v.w) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<4, T, P> const& v) + : x(v.x), y(v.y), z(v.z), w(v.w) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(T scalar) + : x(scalar), y(scalar), z(scalar), w(scalar) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(T _x, T _y, T _z, T _w) + : x(_x), y(_y), z(_z), w(_w) + {} + + // -- Conversion scalar constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.x)) + , z(static_cast(v.x)) + , w(static_cast(v.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, Y _y, Z _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, Z _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, Z _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, Y _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, Z _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + // -- Conversion vector constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, B _z, C _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, C _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z.x)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, B _z, vec<1, C, P> const& _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, vec<1, B, P> const& _z, vec<1, C, P> const& _w) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_z.x)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<2, B, P> const& _yz, C _w) + : x(static_cast(_x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, C _w) + : x(static_cast(_x.x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w) + : x(static_cast(_x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<2, B, P> const& _yz, vec<1, C, P> const& _w) + : x(static_cast(_x.x)) + , y(static_cast(_yz.x)) + , z(static_cast(_yz.y)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, B _y, vec<2, C, P> const& _zw) + : x(static_cast(_x)) + , y(static_cast(_y)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, B _y, vec<2, C, P> const& _zw) + : x(static_cast(_x.x)) + , y(static_cast(_y)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw) + : x(static_cast(_x)) + , y(static_cast(_y.x)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<1, B, P> const& _y, vec<2, C, P> const& _zw) + : x(static_cast(_x.x)) + , y(static_cast(_y.x)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<3, A, P> const& _xyz, B _w) + : x(static_cast(_xyz.x)) + , y(static_cast(_xyz.y)) + , z(static_cast(_xyz.z)) + , w(static_cast(_w)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<3, A, P> const& _xyz, vec<1, B, P> const& _w) + : x(static_cast(_xyz.x)) + , y(static_cast(_xyz.y)) + , z(static_cast(_xyz.z)) + , w(static_cast(_w.x)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(A _x, vec<3, B, P> const& _yzw) + : x(static_cast(_x)) + , y(static_cast(_yzw.x)) + , z(static_cast(_yzw.y)) + , w(static_cast(_yzw.z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<1, A, P> const& _x, vec<3, B, P> const& _yzw) + : x(static_cast(_x.x)) + , y(static_cast(_yzw.x)) + , z(static_cast(_yzw.y)) + , w(static_cast(_yzw.z)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<2, A, P> const& _xy, vec<2, B, P> const& _zw) + : x(static_cast(_xy.x)) + , y(static_cast(_xy.y)) + , z(static_cast(_zw.x)) + , w(static_cast(_zw.y)) + {} + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>::vec(vec<4, U, P> const& v) + : x(static_cast(v.x)) + , y(static_cast(v.y)) + , z(static_cast(v.z)) + , w(static_cast(v.w)) + {} + + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T& vec<4, T, Q>::operator[](typename vec<4, T, Q>::length_type i) + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& vec<4, T, Q>::operator[](typename vec<4, T, Q>::length_type i) const + { + assert(i >= 0 && i < this->length()); + switch(i) + { + default: + case 0: + return x; + case 1: + return y; + case 2: + return z; + case 3: + return w; + } + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>& vec<4, T, Q>::operator=(vec<4, T, Q> const& v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + this->w = v.w; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q>& vec<4, T, Q>::operator=(vec<4, U, Q> const& v) + { + this->x = static_cast(v.x); + this->y = static_cast(v.y); + this->z = static_cast(v.z); + this->w = static_cast(v.w); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator+=(U scalar) + { + return (*this = detail::compute_vec4_add::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator+=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_add::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator+=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_add::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator-=(U scalar) + { + return (*this = detail::compute_vec4_sub::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator-=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_sub::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator-=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_sub::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator*=(U scalar) + { + return (*this = detail::compute_vec4_mul::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator*=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_mul::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator*=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_mul::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator/=(U scalar) + { + return (*this = detail::compute_vec4_div::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator/=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_div::value>::call(*this, vec<4, T, Q>(v.x))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator/=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_div::value>::call(*this, vec<4, T, Q>(v))); + } + + // -- Increment and decrement operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator++() + { + ++this->x; + ++this->y; + ++this->z; + ++this->w; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator--() + { + --this->x; + --this->y; + --this->z; + --this->w; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> vec<4, T, Q>::operator++(int) + { + vec<4, T, Q> Result(*this); + ++*this; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> vec<4, T, Q>::operator--(int) + { + vec<4, T, Q> Result(*this); + --*this; + return Result; + } + + // -- Unary bit operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator%=(U scalar) + { + return (*this = detail::compute_vec4_mod::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator%=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_mod::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator%=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_mod::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator&=(U scalar) + { + return (*this = detail::compute_vec4_and::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator&=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_and::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator&=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_and::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator|=(U scalar) + { + return (*this = detail::compute_vec4_or::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator|=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_or::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator|=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_or::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator^=(U scalar) + { + return (*this = detail::compute_vec4_xor::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator^=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_xor::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator^=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_xor::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator<<=(U scalar) + { + return (*this = detail::compute_vec4_shift_left::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator<<=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_left::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator<<=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_left::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator>>=(U scalar) + { + return (*this = detail::compute_vec4_shift_right::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(scalar))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator>>=(vec<1, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_right::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> & vec<4, T, Q>::operator>>=(vec<4, U, Q> const& v) + { + return (*this = detail::compute_vec4_shift_right::value, sizeof(T) * 8, detail::is_aligned::value>::call(*this, vec<4, T, Q>(v))); + } + + // -- Unary constant operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v) + { + return vec<4, T, Q>(0) -= v; + } + + // -- Binary arithmetic operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) += scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) += v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(v) += scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v2) += v1; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator+(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) += v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) -= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) -= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) -= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) -= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator-(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) -= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) *= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) *= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(v) *= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v2) *= v1; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) *= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v, T const & scalar) + { + return vec<4, T, Q>(v) /= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) /= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) /= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) /= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator/(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) /= v2; + } + + // -- Binary bit operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) %= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) %= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) %= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<1, T, Q> const& scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar.x) %= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator%(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) %= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) &= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v, vec<1, T, Q> const& scalar) + { + return vec<4, T, Q>(v) &= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) &= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) &= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator&(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) &= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) |= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) |= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) |= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) |= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator|(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) |= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) ^= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) ^= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) ^= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) ^= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator^(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) ^= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) <<= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) <<= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) <<= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) <<= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator<<(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) <<= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v, T scalar) + { + return vec<4, T, Q>(v) >>= scalar; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v1, vec<1, T, Q> const& v2) + { + return vec<4, T, Q>(v1) >>= v2.x; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(T scalar, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(scalar) >>= v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<1, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1.x) >>= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator>>(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return vec<4, T, Q>(v1) >>= v2; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator~(vec<4, T, Q> const& v) + { + return detail::compute_vec4_bitwise_not::value, sizeof(T) * 8, detail::is_aligned::value>::call(v); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return detail::compute_vec4_equal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return detail::compute_vec4_nequal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> operator&&(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2) + { + return vec<4, bool, Q>(v1.x && v2.x, v1.y && v2.y, v1.z && v2.z, v1.w && v2.w); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> operator||(vec<4, bool, Q> const& v1, vec<4, bool, Q> const& v2) + { + return vec<4, bool, Q>(v1.x || v2.x, v1.y || v2.y, v1.z || v2.z, v1.w || v2.w); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "type_vec4_simd.inl" +#endif diff --git a/vendor/glm/glm/detail/type_vec4_simd.inl b/vendor/glm/glm/detail/type_vec4_simd.inl new file mode 100644 index 0000000..29559b5 --- /dev/null +++ b/vendor/glm/glm/detail/type_vec4_simd.inl @@ -0,0 +1,775 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + struct _swizzle_base1<4, float, Q, E0,E1,E2,E3, true> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, float, Q> operator ()() const + { + __m128 data = *reinterpret_cast<__m128 const*>(&this->_buffer); + + vec<4, float, Q> Result; +# if GLM_ARCH & GLM_ARCH_AVX_BIT + Result.data = _mm_permute_ps(data, _MM_SHUFFLE(E3, E2, E1, E0)); +# else + Result.data = _mm_shuffle_ps(data, data, _MM_SHUFFLE(E3, E2, E1, E0)); +# endif + return Result; + } + }; + + template + struct _swizzle_base1<4, int, Q, E0,E1,E2,E3, true> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, int, Q> operator ()() const + { + __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer); + + vec<4, int, Q> Result; + Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0)); + return Result; + } + }; + + template + struct _swizzle_base1<4, uint, Q, E0,E1,E2,E3, true> : public _swizzle_base0 + { + GLM_FUNC_QUALIFIER vec<4, uint, Q> operator ()() const + { + __m128i data = *reinterpret_cast<__m128i const*>(&this->_buffer); + + vec<4, uint, Q> Result; + Result.data = _mm_shuffle_epi32(data, _MM_SHUFFLE(E3, E2, E1, E0)); + return Result; + } + }; +# endif// GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + template + struct compute_vec4_add + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_add_ps(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_add + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_add_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_sub + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_sub_ps(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_sub + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_sub_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_mul + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_mul_ps(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_mul + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_mul_pd(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_div + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = _mm_div_ps(a.data, b.data); + return Result; + } + }; + + # if GLM_ARCH & GLM_ARCH_AVX_BIT + template + struct compute_vec4_div + { + static vec<4, double, Q> call(vec<4, double, Q> const& a, vec<4, double, Q> const& b) + { + vec<4, double, Q> Result; + Result.data = _mm256_div_pd(a.data, b.data); + return Result; + } + }; +# endif + + template<> + struct compute_vec4_div + { + static vec<4, float, aligned_lowp> call(vec<4, float, aligned_lowp> const& a, vec<4, float, aligned_lowp> const& b) + { + vec<4, float, aligned_lowp> Result; + Result.data = _mm_mul_ps(a.data, _mm_rcp_ps(b.data)); + return Result; + } + }; + + template + struct compute_vec4_and + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_and_si128(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_and + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_and_si256(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_or + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_or_si128(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_or + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_or_si256(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_xor + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_xor_si128(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_xor + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_xor_si256(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_shift_left + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_sll_epi32(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_shift_left + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_sll_epi64(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_shift_right + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm_srl_epi32(a.data, b.data); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_shift_right + { + static vec<4, T, Q> call(vec<4, T, Q> const& a, vec<4, T, Q> const& b) + { + vec<4, T, Q> Result; + Result.data = _mm256_srl_epi64(a.data, b.data); + return Result; + } + }; +# endif + + template + struct compute_vec4_bitwise_not + { + static vec<4, T, Q> call(vec<4, T, Q> const& v) + { + vec<4, T, Q> Result; + Result.data = _mm_xor_si128(v.data, _mm_set1_epi32(-1)); + return Result; + } + }; + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template + struct compute_vec4_bitwise_not + { + static vec<4, T, Q> call(vec<4, T, Q> const& v) + { + vec<4, T, Q> Result; + Result.data = _mm256_xor_si256(v.data, _mm_set1_epi32(-1)); + return Result; + } + }; +# endif + + template + struct compute_vec4_equal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return _mm_movemask_ps(_mm_cmpeq_ps(v1.data, v2.data)) != 0; + } + }; + +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + template + struct compute_vec4_equal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + //return _mm_movemask_epi8(_mm_cmpeq_epi32(v1.data, v2.data)) != 0; + __m128i neq = _mm_xor_si128(v1.data, v2.data); + return _mm_test_all_zeros(neq, neq) == 0; + } + }; +# endif + + template + struct compute_vec4_nequal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return _mm_movemask_ps(_mm_cmpneq_ps(v1.data, v2.data)) != 0; + } + }; + +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + template + struct compute_vec4_nequal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + //return _mm_movemask_epi8(_mm_cmpneq_epi32(v1.data, v2.data)) != 0; + __m128i neq = _mm_xor_si128(v1.data, v2.data); + return _mm_test_all_zeros(neq, neq) != 0; + } + }; +# endif +}//namespace detail + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(float _s) : + data(_mm_set1_ps(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(float _s) : + data(_mm_set1_ps(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(float _s) : + data(_mm_set1_ps(_s)) + {} + +# if GLM_ARCH & GLM_ARCH_AVX_BIT + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, double, aligned_lowp>::vec(double _s) : + data(_mm256_set1_pd(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, double, aligned_mediump>::vec(double _s) : + data(_mm256_set1_pd(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, double, aligned_highp>::vec(double _s) : + data(_mm256_set1_pd(_s)) + {} +# endif + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_lowp>::vec(int _s) : + data(_mm_set1_epi32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_mediump>::vec(int _s) : + data(_mm_set1_epi32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_highp>::vec(int _s) : + data(_mm_set1_epi32(_s)) + {} + +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, detail::int64, aligned_lowp>::vec(detail::int64 _s) : + data(_mm256_set1_epi64x(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, detail::int64, aligned_mediump>::vec(detail::int64 _s) : + data(_mm256_set1_epi64x(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, detail::int64, aligned_highp>::vec(detail::int64 _s) : + data(_mm256_set1_epi64x(_s)) + {} +# endif + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(float _x, float _y, float _z, float _w) : + data(_mm_set_ps(_w, _z, _y, _x)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(float _x, float _y, float _z, float _w) : + data(_mm_set_ps(_w, _z, _y, _x)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(float _x, float _y, float _z, float _w) : + data(_mm_set_ps(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_lowp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_set_epi32(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_mediump>::vec(int _x, int _y, int _z, int _w) : + data(_mm_set_epi32(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_highp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_set_epi32(_w, _z, _y, _x)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x))) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(int _x, int _y, int _z, int _w) : + data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x))) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(int _x, int _y, int _z, int _w) : + data(_mm_cvtepi32_ps(_mm_set_epi32(_w, _z, _y, _x))) + {} +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + +#if GLM_ARCH & GLM_ARCH_NEON_BIT +namespace glm { +namespace detail { + + template + struct compute_vec4_add + { + static + vec<4, float, Q> + call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = vaddq_f32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_add + { + static + vec<4, uint, Q> + call(vec<4, uint, Q> const& a, vec<4, uint, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vaddq_u32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_add + { + static + vec<4, int, Q> + call(vec<4, int, Q> const& a, vec<4, int, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vaddq_s32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_sub + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = vsubq_f32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_sub + { + static vec<4, uint, Q> call(vec<4, uint, Q> const& a, vec<4, uint, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vsubq_u32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_sub + { + static vec<4, int, Q> call(vec<4, int, Q> const& a, vec<4, int, Q> const& b) + { + vec<4, int, Q> Result; + Result.data = vsubq_s32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_mul + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = vmulq_f32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_mul + { + static vec<4, uint, Q> call(vec<4, uint, Q> const& a, vec<4, uint, Q> const& b) + { + vec<4, uint, Q> Result; + Result.data = vmulq_u32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_mul + { + static vec<4, int, Q> call(vec<4, int, Q> const& a, vec<4, int, Q> const& b) + { + vec<4, int, Q> Result; + Result.data = vmulq_s32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_div + { + static vec<4, float, Q> call(vec<4, float, Q> const& a, vec<4, float, Q> const& b) + { + vec<4, float, Q> Result; + Result.data = vdivq_f32(a.data, b.data); + return Result; + } + }; + + template + struct compute_vec4_equal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + uint32x4_t cmp = vceqq_f32(v1.data, v2.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + cmp = vpminq_u32(cmp, cmp); + cmp = vpminq_u32(cmp, cmp); + uint32_t r = cmp[0]; +#else + uint32x2_t cmpx2 = vpmin_u32(vget_low_f32(cmp), vget_high_f32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template + struct compute_vec4_equal + { + static bool call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + uint32x4_t cmp = vceqq_u32(v1.data, v2.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + cmp = vpminq_u32(cmp, cmp); + cmp = vpminq_u32(cmp, cmp); + uint32_t r = cmp[0]; +#else + uint32x2_t cmpx2 = vpmin_u32(vget_low_f32(cmp), vget_high_f32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template + struct compute_vec4_equal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + uint32x4_t cmp = vceqq_s32(v1.data, v2.data); +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + cmp = vpminq_u32(cmp, cmp); + cmp = vpminq_u32(cmp, cmp); + uint32_t r = cmp[0]; +#else + uint32x2_t cmpx2 = vpmin_u32(vget_low_f32(cmp), vget_high_f32(cmp)); + cmpx2 = vpmin_u32(cmpx2, cmpx2); + uint32_t r = cmpx2[0]; +#endif + return r == ~0u; + } + }; + + template + struct compute_vec4_nequal + { + static bool call(vec<4, float, Q> const& v1, vec<4, float, Q> const& v2) + { + return !compute_vec4_equal::call(v1, v2); + } + }; + + template + struct compute_vec4_nequal + { + static bool call(vec<4, uint, Q> const& v1, vec<4, uint, Q> const& v2) + { + return !compute_vec4_equal::call(v1, v2); + } + }; + + template + struct compute_vec4_nequal + { + static bool call(vec<4, int, Q> const& v1, vec<4, int, Q> const& v2) + { + return !compute_vec4_equal::call(v1, v2); + } + }; + +}//namespace detail + +#if !GLM_CONFIG_XYZW_ONLY + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(float _s) : + data(vdupq_n_f32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(float _s) : + data(vdupq_n_f32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(float _s) : + data(vdupq_n_f32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_lowp>::vec(int _s) : + data(vdupq_n_s32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_mediump>::vec(int _s) : + data(vdupq_n_s32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, int, aligned_highp>::vec(int _s) : + data(vdupq_n_s32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, uint, aligned_lowp>::vec(uint _s) : + data(vdupq_n_u32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, uint, aligned_mediump>::vec(uint _s) : + data(vdupq_n_u32(_s)) + {} + + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, uint, aligned_highp>::vec(uint _s) : + data(vdupq_n_u32(_s)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(const vec<4, float, aligned_highp>& rhs) : + data(rhs.data) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(const vec<4, int, aligned_highp>& rhs) : + data(vcvtq_f32_s32(rhs.data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(const vec<4, uint, aligned_highp>& rhs) : + data(vcvtq_f32_u32(rhs.data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(int _x, int _y, int _z, int _w) : + data(vcvtq_f32_s32(vec<4, int, aligned_lowp>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(int _x, int _y, int _z, int _w) : + data(vcvtq_f32_s32(vec<4, int, aligned_mediump>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(int _x, int _y, int _z, int _w) : + data(vcvtq_f32_s32(vec<4, int, aligned_highp>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_lowp>::vec(uint _x, uint _y, uint _z, uint _w) : + data(vcvtq_f32_u32(vec<4, uint, aligned_lowp>(_x, _y, _z, _w).data)) + {} + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_mediump>::vec(uint _x, uint _y, uint _z, uint _w) : + data(vcvtq_f32_u32(vec<4, uint, aligned_mediump>(_x, _y, _z, _w).data)) + {} + + + template<> + template<> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, float, aligned_highp>::vec(uint _x, uint _y, uint _z, uint _w) : + data(vcvtq_f32_u32(vec<4, uint, aligned_highp>(_x, _y, _z, _w).data)) + {} + +#endif +}//namespace glm + +#endif diff --git a/vendor/glm/glm/exponential.hpp b/vendor/glm/glm/exponential.hpp new file mode 100644 index 0000000..f8fb886 --- /dev/null +++ b/vendor/glm/glm/exponential.hpp @@ -0,0 +1,110 @@ +/// @ref core +/// @file glm/exponential.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions +/// +/// @defgroup core_func_exponential Exponential functions +/// @ingroup core +/// +/// Provides GLSL exponential functions +/// +/// These all operate component-wise. The description is per component. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/type_vec1.hpp" +#include "detail/type_vec2.hpp" +#include "detail/type_vec3.hpp" +#include "detail/type_vec4.hpp" +#include + +namespace glm +{ + /// @addtogroup core_func_exponential + /// @{ + + /// Returns 'base' raised to the power 'exponent'. + /// + /// @param base Floating point value. pow function is defined for input values of 'base' defined in the range (inf-, inf+) in the limit of the type qualifier. + /// @param exponent Floating point value representing the 'exponent'. + /// + /// @see GLSL pow man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec pow(vec const& base, vec const& exponent); + + /// Returns the natural exponentiation of x, i.e., e^x. + /// + /// @param v exp function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL exp man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec exp(vec const& v); + + /// Returns the natural logarithm of v, i.e., + /// returns the value y which satisfies the equation x = e^y. + /// Results are undefined if v <= 0. + /// + /// @param v log function is defined for input values of v defined in the range (0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL log man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec log(vec const& v); + + /// Returns 2 raised to the v power. + /// + /// @param v exp2 function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL exp2 man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec exp2(vec const& v); + + /// Returns the base 2 log of x, i.e., returns the value y, + /// which satisfies the equation x = 2 ^ y. + /// + /// @param v log2 function is defined for input values of v defined in the range (0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL log2 man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec log2(vec const& v); + + /// Returns the positive square root of v. + /// + /// @param v sqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL sqrt man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec sqrt(vec const& v); + + /// Returns the reciprocal of the positive square root of v. + /// + /// @param v inversesqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type qualifier. + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL inversesqrt man page + /// @see GLSL 4.20.8 specification, section 8.2 Exponential Functions + template + GLM_FUNC_DECL vec inversesqrt(vec const& v); + + /// @} +}//namespace glm + +#include "detail/func_exponential.inl" diff --git a/vendor/glm/glm/ext.hpp b/vendor/glm/glm/ext.hpp new file mode 100644 index 0000000..3249fb9 --- /dev/null +++ b/vendor/glm/glm/ext.hpp @@ -0,0 +1,253 @@ +/// @file glm/ext.hpp +/// +/// @ref core (Dependence) + +#include "detail/setup.hpp" + +#pragma once + +#include "glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_MESSAGE_EXT_INCLUDED_DISPLAYED) +# define GLM_MESSAGE_EXT_INCLUDED_DISPLAYED +# pragma message("GLM: All extensions included (not recommended)") +#endif//GLM_MESSAGES + +#include "./ext/matrix_clip_space.hpp" +#include "./ext/matrix_common.hpp" + +#include "./ext/matrix_double2x2.hpp" +#include "./ext/matrix_double2x2_precision.hpp" +#include "./ext/matrix_double2x3.hpp" +#include "./ext/matrix_double2x3_precision.hpp" +#include "./ext/matrix_double2x4.hpp" +#include "./ext/matrix_double2x4_precision.hpp" +#include "./ext/matrix_double3x2.hpp" +#include "./ext/matrix_double3x2_precision.hpp" +#include "./ext/matrix_double3x3.hpp" +#include "./ext/matrix_double3x3_precision.hpp" +#include "./ext/matrix_double3x4.hpp" +#include "./ext/matrix_double3x4_precision.hpp" +#include "./ext/matrix_double4x2.hpp" +#include "./ext/matrix_double4x2_precision.hpp" +#include "./ext/matrix_double4x3.hpp" +#include "./ext/matrix_double4x3_precision.hpp" +#include "./ext/matrix_double4x4.hpp" +#include "./ext/matrix_double4x4_precision.hpp" + +#include "./ext/matrix_float2x2.hpp" +#include "./ext/matrix_float2x2_precision.hpp" +#include "./ext/matrix_float2x3.hpp" +#include "./ext/matrix_float2x3_precision.hpp" +#include "./ext/matrix_float2x4.hpp" +#include "./ext/matrix_float2x4_precision.hpp" +#include "./ext/matrix_float3x2.hpp" +#include "./ext/matrix_float3x2_precision.hpp" +#include "./ext/matrix_float3x3.hpp" +#include "./ext/matrix_float3x3_precision.hpp" +#include "./ext/matrix_float3x4.hpp" +#include "./ext/matrix_float3x4_precision.hpp" +#include "./ext/matrix_float4x2.hpp" +#include "./ext/matrix_float4x2_precision.hpp" +#include "./ext/matrix_float4x3.hpp" +#include "./ext/matrix_float4x3_precision.hpp" +#include "./ext/matrix_float4x4.hpp" +#include "./ext/matrix_float4x4_precision.hpp" + +#include "./ext/matrix_int2x2.hpp" +#include "./ext/matrix_int2x2_sized.hpp" +#include "./ext/matrix_int2x3.hpp" +#include "./ext/matrix_int2x3_sized.hpp" +#include "./ext/matrix_int2x4.hpp" +#include "./ext/matrix_int2x4_sized.hpp" +#include "./ext/matrix_int3x2.hpp" +#include "./ext/matrix_int3x2_sized.hpp" +#include "./ext/matrix_int3x3.hpp" +#include "./ext/matrix_int3x3_sized.hpp" +#include "./ext/matrix_int3x4.hpp" +#include "./ext/matrix_int3x4_sized.hpp" +#include "./ext/matrix_int4x2.hpp" +#include "./ext/matrix_int4x2_sized.hpp" +#include "./ext/matrix_int4x3.hpp" +#include "./ext/matrix_int4x3_sized.hpp" +#include "./ext/matrix_int4x4.hpp" +#include "./ext/matrix_int4x4_sized.hpp" + +#include "./ext/matrix_uint2x2.hpp" +#include "./ext/matrix_uint2x2_sized.hpp" +#include "./ext/matrix_uint2x3.hpp" +#include "./ext/matrix_uint2x3_sized.hpp" +#include "./ext/matrix_uint2x4.hpp" +#include "./ext/matrix_uint2x4_sized.hpp" +#include "./ext/matrix_uint3x2.hpp" +#include "./ext/matrix_uint3x2_sized.hpp" +#include "./ext/matrix_uint3x3.hpp" +#include "./ext/matrix_uint3x3_sized.hpp" +#include "./ext/matrix_uint3x4.hpp" +#include "./ext/matrix_uint3x4_sized.hpp" +#include "./ext/matrix_uint4x2.hpp" +#include "./ext/matrix_uint4x2_sized.hpp" +#include "./ext/matrix_uint4x3.hpp" +#include "./ext/matrix_uint4x3_sized.hpp" +#include "./ext/matrix_uint4x4.hpp" +#include "./ext/matrix_uint4x4_sized.hpp" + +#include "./ext/matrix_projection.hpp" +#include "./ext/matrix_relational.hpp" +#include "./ext/matrix_transform.hpp" + +#include "./ext/quaternion_common.hpp" +#include "./ext/quaternion_double.hpp" +#include "./ext/quaternion_double_precision.hpp" +#include "./ext/quaternion_float.hpp" +#include "./ext/quaternion_float_precision.hpp" +#include "./ext/quaternion_exponential.hpp" +#include "./ext/quaternion_geometric.hpp" +#include "./ext/quaternion_relational.hpp" +#include "./ext/quaternion_transform.hpp" +#include "./ext/quaternion_trigonometric.hpp" + +#include "./ext/scalar_common.hpp" +#include "./ext/scalar_constants.hpp" +#include "./ext/scalar_integer.hpp" +#include "./ext/scalar_packing.hpp" +#include "./ext/scalar_relational.hpp" +#include "./ext/scalar_ulp.hpp" + +#include "./ext/scalar_int_sized.hpp" +#include "./ext/scalar_uint_sized.hpp" + +#include "./ext/vector_common.hpp" +#include "./ext/vector_integer.hpp" +#include "./ext/vector_packing.hpp" +#include "./ext/vector_relational.hpp" +#include "./ext/vector_ulp.hpp" + +#include "./ext/vector_bool1.hpp" +#include "./ext/vector_bool1_precision.hpp" +#include "./ext/vector_bool2.hpp" +#include "./ext/vector_bool2_precision.hpp" +#include "./ext/vector_bool3.hpp" +#include "./ext/vector_bool3_precision.hpp" +#include "./ext/vector_bool4.hpp" +#include "./ext/vector_bool4_precision.hpp" + +#include "./ext/vector_double1.hpp" +#include "./ext/vector_double1_precision.hpp" +#include "./ext/vector_double2.hpp" +#include "./ext/vector_double2_precision.hpp" +#include "./ext/vector_double3.hpp" +#include "./ext/vector_double3_precision.hpp" +#include "./ext/vector_double4.hpp" +#include "./ext/vector_double4_precision.hpp" + +#include "./ext/vector_float1.hpp" +#include "./ext/vector_float1_precision.hpp" +#include "./ext/vector_float2.hpp" +#include "./ext/vector_float2_precision.hpp" +#include "./ext/vector_float3.hpp" +#include "./ext/vector_float3_precision.hpp" +#include "./ext/vector_float4.hpp" +#include "./ext/vector_float4_precision.hpp" + +#include "./ext/vector_int1.hpp" +#include "./ext/vector_int1_sized.hpp" +#include "./ext/vector_int2.hpp" +#include "./ext/vector_int2_sized.hpp" +#include "./ext/vector_int3.hpp" +#include "./ext/vector_int3_sized.hpp" +#include "./ext/vector_int4.hpp" +#include "./ext/vector_int4_sized.hpp" + +#include "./ext/vector_uint1.hpp" +#include "./ext/vector_uint1_sized.hpp" +#include "./ext/vector_uint2.hpp" +#include "./ext/vector_uint2_sized.hpp" +#include "./ext/vector_uint3.hpp" +#include "./ext/vector_uint3_sized.hpp" +#include "./ext/vector_uint4.hpp" +#include "./ext/vector_uint4_sized.hpp" + +#include "./gtc/bitfield.hpp" +#include "./gtc/color_space.hpp" +#include "./gtc/constants.hpp" +#include "./gtc/epsilon.hpp" +#include "./gtc/integer.hpp" +#include "./gtc/matrix_access.hpp" +#include "./gtc/matrix_integer.hpp" +#include "./gtc/matrix_inverse.hpp" +#include "./gtc/matrix_transform.hpp" +#include "./gtc/noise.hpp" +#include "./gtc/packing.hpp" +#include "./gtc/quaternion.hpp" +#include "./gtc/random.hpp" +#include "./gtc/reciprocal.hpp" +#include "./gtc/round.hpp" +#include "./gtc/type_precision.hpp" +#include "./gtc/type_ptr.hpp" +#include "./gtc/ulp.hpp" +#include "./gtc/vec1.hpp" +#if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +# include "./gtc/type_aligned.hpp" +#endif + +#ifdef GLM_ENABLE_EXPERIMENTAL +#include "./gtx/associated_min_max.hpp" +#include "./gtx/bit.hpp" +#include "./gtx/closest_point.hpp" +#include "./gtx/color_encoding.hpp" +#include "./gtx/color_space.hpp" +#include "./gtx/color_space_YCoCg.hpp" +#include "./gtx/compatibility.hpp" +#include "./gtx/component_wise.hpp" +#include "./gtx/dual_quaternion.hpp" +#include "./gtx/euler_angles.hpp" +#include "./gtx/extend.hpp" +#include "./gtx/extended_min_max.hpp" +#include "./gtx/fast_exponential.hpp" +#include "./gtx/fast_square_root.hpp" +#include "./gtx/fast_trigonometry.hpp" +#include "./gtx/functions.hpp" +#include "./gtx/gradient_paint.hpp" +#include "./gtx/handed_coordinate_space.hpp" +#include "./gtx/integer.hpp" +#include "./gtx/intersect.hpp" +#include "./gtx/log_base.hpp" +#include "./gtx/matrix_cross_product.hpp" +#include "./gtx/matrix_interpolation.hpp" +#include "./gtx/matrix_major_storage.hpp" +#include "./gtx/matrix_operation.hpp" +#include "./gtx/matrix_query.hpp" +#include "./gtx/mixed_product.hpp" +#include "./gtx/norm.hpp" +#include "./gtx/normal.hpp" +#include "./gtx/normalize_dot.hpp" +#include "./gtx/number_precision.hpp" +#include "./gtx/optimum_pow.hpp" +#include "./gtx/orthonormalize.hpp" +#include "./gtx/perpendicular.hpp" +#include "./gtx/polar_coordinates.hpp" +#include "./gtx/projection.hpp" +#include "./gtx/quaternion.hpp" +#include "./gtx/raw_data.hpp" +#include "./gtx/rotate_vector.hpp" +#include "./gtx/spline.hpp" +#include "./gtx/std_based_type.hpp" +#if !(GLM_COMPILER & GLM_COMPILER_CUDA) +# include "./gtx/string_cast.hpp" +#endif +#include "./gtx/transform.hpp" +#include "./gtx/transform2.hpp" +#include "./gtx/vec_swizzle.hpp" +#include "./gtx/vector_angle.hpp" +#include "./gtx/vector_query.hpp" +#include "./gtx/wrap.hpp" + +#if GLM_HAS_TEMPLATE_ALIASES +# include "./gtx/scalar_multiplication.hpp" +#endif + +#if GLM_HAS_RANGE_FOR +# include "./gtx/range.hpp" +#endif +#endif//GLM_ENABLE_EXPERIMENTAL diff --git a/vendor/glm/glm/ext/matrix_clip_space.hpp b/vendor/glm/glm/ext/matrix_clip_space.hpp new file mode 100644 index 0000000..c3874f2 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_clip_space.hpp @@ -0,0 +1,522 @@ +/// @ref ext_matrix_clip_space +/// @file glm/ext/matrix_clip_space.hpp +/// +/// @defgroup ext_matrix_clip_space GLM_EXT_matrix_clip_space +/// @ingroup ext +/// +/// Defines functions that generate clip space transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_transform +/// @see ext_matrix_projection + +#pragma once + +// Dependencies +#include "../ext/scalar_constants.hpp" +#include "../geometric.hpp" +#include "../trigonometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_clip_space extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_clip_space + /// @{ + + /// Creates a matrix for projecting two-dimensional coordinates onto the screen. + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top, T const& zNear, T const& zFar) + /// @see gluOrtho2D man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> ortho( + T left, T right, T bottom, T top); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoLH_ZO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoLH_NO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoRH_ZO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoRH_NO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoZO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoNO( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using left-handed coordinates. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoLH( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using right-handed coordinates. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> orthoRH( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a matrix for an orthographic parallel viewing volume, using the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @tparam T A floating-point scalar type + /// + /// @see - glm::ortho(T const& left, T const& right, T const& bottom, T const& top) + /// @see glOrtho man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> ortho( + T left, T right, T bottom, T top, T zNear, T zFar); + + /// Creates a left handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumLH_ZO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a left handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumLH_NO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a right handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumRH_ZO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a right handed frustum matrix. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumRH_NO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a frustum matrix using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumZO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a frustum matrix using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumNO( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a left handed frustum matrix. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumLH( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a right handed frustum matrix. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustumRH( + T left, T right, T bottom, T top, T near, T far); + + /// Creates a frustum matrix with default handedness, using the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @tparam T A floating-point scalar type + /// @see glFrustum man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> frustum( + T left, T right, T bottom, T top, T near, T far); + + + /// Creates a matrix for a right handed, symetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveRH_ZO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a right handed, symetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveRH_NO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a left handed, symetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH_ZO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a left handed, symetric perspective-view frustum. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH_NO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symetric perspective-view frustum using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveZO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symetric perspective-view frustum using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveNO( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a right handed, symetric perspective-view frustum. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveRH( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a left handed, symetric perspective-view frustum. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveLH( + T fovy, T aspect, T near, T far); + + /// Creates a matrix for a symetric perspective-view frustum based on the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param fovy Specifies the field of view angle in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + /// @see gluPerspective man page + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspective( + T fovy, T aspect, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovRH_ZO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using right-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovRH_NO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovLH_ZO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovLH_NO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovZO( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view using left-handed coordinates if GLM_FORCE_LEFT_HANDED if defined or right-handed coordinates otherwise. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovNO( + T fov, T width, T height, T near, T far); + + /// Builds a right handed perspective projection matrix based on a field of view. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovRH( + T fov, T width, T height, T near, T far); + + /// Builds a left handed perspective projection matrix based on a field of view. + /// If GLM_FORCE_DEPTH_ZERO_TO_ONE is defined, the near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// Otherwise, the near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFovLH( + T fov, T width, T height, T near, T far); + + /// Builds a perspective projection matrix based on a field of view and the default handedness and default near and far clip planes definition. + /// To change default handedness use GLM_FORCE_LEFT_HANDED. To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param fov Expressed in radians. + /// @param width Width of the viewport + /// @param height Height of the viewport + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> perspectiveFov( + T fov, T width, T height, T near, T far); + + /// Creates a matrix for a left handed, symmetric perspective-view frustum with far plane at infinite. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> infinitePerspectiveLH( + T fovy, T aspect, T near); + + /// Creates a matrix for a right handed, symmetric perspective-view frustum with far plane at infinite. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> infinitePerspectiveRH( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite with default handedness. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> infinitePerspective( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics hardware that doesn't support depth clamping. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> tweakedInfinitePerspective( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics hardware that doesn't support depth clamping. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param ep Epsilon + /// + /// @tparam T A floating-point scalar type + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> tweakedInfinitePerspective( + T fovy, T aspect, T near, T ep); + + /// @} +}//namespace glm + +#include "matrix_clip_space.inl" diff --git a/vendor/glm/glm/ext/matrix_clip_space.inl b/vendor/glm/glm/ext/matrix_clip_space.inl new file mode 100644 index 0000000..7e4df33 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_clip_space.inl @@ -0,0 +1,555 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> ortho(T left, T right, T bottom, T top) + { + mat<4, 4, T, defaultp> Result(static_cast(1)); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = - static_cast(1); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoLH_ZO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = static_cast(1) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - zNear / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoLH_NO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = static_cast(2) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - (zFar + zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH_ZO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = - static_cast(1) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - zNear / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH_NO(T left, T right, T bottom, T top, T zNear, T zFar) + { + mat<4, 4, T, defaultp> Result(1); + Result[0][0] = static_cast(2) / (right - left); + Result[1][1] = static_cast(2) / (top - bottom); + Result[2][2] = - static_cast(2) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - (zFar + zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoZO(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return orthoLH_ZO(left, right, bottom, top, zNear, zFar); +# else + return orthoRH_ZO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoNO(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return orthoLH_NO(left, right, bottom, top, zNear, zFar); +# else + return orthoRH_NO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoLH(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return orthoLH_ZO(left, right, bottom, top, zNear, zFar); +# else + return orthoLH_NO(left, right, bottom, top, zNear, zFar); +# endif + + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> orthoRH(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return orthoRH_ZO(left, right, bottom, top, zNear, zFar); +# else + return orthoRH_NO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> ortho(T left, T right, T bottom, T top, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return orthoLH_ZO(left, right, bottom, top, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return orthoLH_NO(left, right, bottom, top, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return orthoRH_ZO(left, right, bottom, top, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return orthoRH_NO(left, right, bottom, top, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumLH_ZO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][2] = farVal / (farVal - nearVal); + Result[2][3] = static_cast(1); + Result[3][2] = -(farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumLH_NO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][2] = (farVal + nearVal) / (farVal - nearVal); + Result[2][3] = static_cast(1); + Result[3][2] = - (static_cast(2) * farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumRH_ZO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][2] = farVal / (nearVal - farVal); + Result[2][3] = static_cast(-1); + Result[3][2] = -(farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumRH_NO(T left, T right, T bottom, T top, T nearVal, T farVal) + { + mat<4, 4, T, defaultp> Result(0); + Result[0][0] = (static_cast(2) * nearVal) / (right - left); + Result[1][1] = (static_cast(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][2] = - (farVal + nearVal) / (farVal - nearVal); + Result[2][3] = static_cast(-1); + Result[3][2] = - (static_cast(2) * farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumZO(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return frustumLH_ZO(left, right, bottom, top, nearVal, farVal); +# else + return frustumRH_ZO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumNO(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return frustumLH_NO(left, right, bottom, top, nearVal, farVal); +# else + return frustumRH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumLH(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return frustumLH_ZO(left, right, bottom, top, nearVal, farVal); +# else + return frustumLH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustumRH(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return frustumRH_ZO(left, right, bottom, top, nearVal, farVal); +# else + return frustumRH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> frustum(T left, T right, T bottom, T top, T nearVal, T farVal) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return frustumLH_ZO(left, right, bottom, top, nearVal, farVal); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return frustumLH_NO(left, right, bottom, top, nearVal, farVal); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return frustumRH_ZO(left, right, bottom, top, nearVal, farVal); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return frustumRH_NO(left, right, bottom, top, nearVal, farVal); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH_ZO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = zFar / (zNear - zFar); + Result[2][3] = - static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH_NO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH_ZO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = zFar / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH_NO(T fovy, T aspect, T zNear, T zFar) + { + assert(abs(aspect - std::numeric_limits::epsilon()) > static_cast(0)); + + T const tanHalfFovy = tan(fovy / static_cast(2)); + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = static_cast(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast(1) / (tanHalfFovy); + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveZO(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveLH_ZO(fovy, aspect, zNear, zFar); +# else + return perspectiveRH_ZO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveNO(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveLH_NO(fovy, aspect, zNear, zFar); +# else + return perspectiveRH_NO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveLH(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveLH_ZO(fovy, aspect, zNear, zFar); +# else + return perspectiveLH_NO(fovy, aspect, zNear, zFar); +# endif + + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveRH(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveRH_ZO(fovy, aspect, zNear, zFar); +# else + return perspectiveRH_NO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspective(T fovy, T aspect, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return perspectiveLH_ZO(fovy, aspect, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return perspectiveLH_NO(fovy, aspect, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return perspectiveRH_ZO(fovy, aspect, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return perspectiveRH_NO(fovy, aspect, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH_ZO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = zFar / (zNear - zFar); + Result[2][3] = - static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH_NO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH_ZO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = zFar / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = -(zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH_NO(T fov, T width, T height, T zNear, T zFar) + { + assert(width > static_cast(0)); + assert(height > static_cast(0)); + assert(fov > static_cast(0)); + + T const rad = fov; + T const h = glm::cos(static_cast(0.5) * rad) / glm::sin(static_cast(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = (zFar + zNear) / (zFar - zNear); + Result[2][3] = static_cast(1); + Result[3][2] = - (static_cast(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovZO(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveFovLH_ZO(fov, width, height, zNear, zFar); +# else + return perspectiveFovRH_ZO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovNO(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return perspectiveFovLH_NO(fov, width, height, zNear, zFar); +# else + return perspectiveFovRH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovLH(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveFovLH_ZO(fov, width, height, zNear, zFar); +# else + return perspectiveFovLH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFovRH(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return perspectiveFovRH_ZO(fov, width, height, zNear, zFar); +# else + return perspectiveFovRH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> perspectiveFov(T fov, T width, T height, T zNear, T zFar) + { +# if GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_ZO + return perspectiveFovLH_ZO(fov, width, height, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return perspectiveFovLH_NO(fov, width, height, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return perspectiveFovRH_ZO(fov, width, height, zNear, zFar); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return perspectiveFovRH_NO(fov, width, height, zNear, zFar); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveRH(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = - static_cast(1); + Result[2][3] = - static_cast(1); + Result[3][2] = - static_cast(2) * zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveLH(T fovy, T aspect, T zNear) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(T(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = static_cast(1); + Result[2][3] = static_cast(1); + Result[3][2] = - static_cast(2) * zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspective(T fovy, T aspect, T zNear) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return infinitePerspectiveLH(fovy, aspect, zNear); +# else + return infinitePerspectiveRH(fovy, aspect, zNear); +# endif + } + + // Infinite projection matrix: http://www.terathon.com/gdc07_lengyel.pdf + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear, T ep) + { + T const range = tan(fovy / static_cast(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + mat<4, 4, T, defaultp> Result(static_cast(0)); + Result[0][0] = (static_cast(2) * zNear) / (right - left); + Result[1][1] = (static_cast(2) * zNear) / (top - bottom); + Result[2][2] = ep - static_cast(1); + Result[2][3] = static_cast(-1); + Result[3][2] = (ep - static_cast(2)) * zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear) + { + return tweakedInfinitePerspective(fovy, aspect, zNear, epsilon()); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_common.hpp b/vendor/glm/glm/ext/matrix_common.hpp new file mode 100644 index 0000000..05c3799 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_common.hpp @@ -0,0 +1,36 @@ +/// @ref ext_matrix_common +/// @file glm/ext/matrix_common.hpp +/// +/// @defgroup ext_matrix_common GLM_EXT_matrix_common +/// @ingroup ext +/// +/// Defines functions for common matrix operations. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_common + +#pragma once + +#include "../detail/qualifier.hpp" +#include "../detail/_fixes.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_common + /// @{ + + template + GLM_FUNC_DECL mat mix(mat const& x, mat const& y, mat const& a); + + template + GLM_FUNC_DECL mat mix(mat const& x, mat const& y, U a); + + /// @} +}//namespace glm + +#include "matrix_common.inl" diff --git a/vendor/glm/glm/ext/matrix_common.inl b/vendor/glm/glm/ext/matrix_common.inl new file mode 100644 index 0000000..9d50848 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_common.inl @@ -0,0 +1,16 @@ +#include "../matrix.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat mix(mat const& x, mat const& y, U a) + { + return mat(x) * (static_cast(1) - a) + mat(y) * a; + } + + template + GLM_FUNC_QUALIFIER mat mix(mat const& x, mat const& y, mat const& a) + { + return matrixCompMult(mat(x), static_cast(1) - a) + matrixCompMult(mat(y), a); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double2x2.hpp b/vendor/glm/glm/ext/matrix_double2x2.hpp new file mode 100644 index 0000000..94dca54 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double2x2.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_double2x2.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, double, defaultp> dmat2x2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, double, defaultp> dmat2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double2x2_precision.hpp b/vendor/glm/glm/ext/matrix_double2x2_precision.hpp new file mode 100644 index 0000000..9e2c174 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double2x2_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_double2x2_precision.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, lowp> lowp_dmat2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, mediump> mediump_dmat2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, highp> highp_dmat2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, lowp> lowp_dmat2x2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, mediump> mediump_dmat2x2; + + /// 2 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, double, highp> highp_dmat2x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double2x3.hpp b/vendor/glm/glm/ext/matrix_double2x3.hpp new file mode 100644 index 0000000..bfef87a --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double2x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double2x3.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 3, double, defaultp> dmat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double2x3_precision.hpp b/vendor/glm/glm/ext/matrix_double2x3_precision.hpp new file mode 100644 index 0000000..098fb60 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double2x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double2x3_precision.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, double, lowp> lowp_dmat2x3; + + /// 2 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, double, mediump> mediump_dmat2x3; + + /// 2 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, double, highp> highp_dmat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double2x4.hpp b/vendor/glm/glm/ext/matrix_double2x4.hpp new file mode 100644 index 0000000..499284b --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double2x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double2x4.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 4, double, defaultp> dmat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double2x4_precision.hpp b/vendor/glm/glm/ext/matrix_double2x4_precision.hpp new file mode 100644 index 0000000..9b61ebc --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double2x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double2x4_precision.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, double, lowp> lowp_dmat2x4; + + /// 2 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, double, mediump> mediump_dmat2x4; + + /// 2 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, double, highp> highp_dmat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double3x2.hpp b/vendor/glm/glm/ext/matrix_double3x2.hpp new file mode 100644 index 0000000..dd23f36 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double3x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double3x2.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 2, double, defaultp> dmat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double3x2_precision.hpp b/vendor/glm/glm/ext/matrix_double3x2_precision.hpp new file mode 100644 index 0000000..068d9e9 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double3x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double3x2_precision.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, double, lowp> lowp_dmat3x2; + + /// 3 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, double, mediump> mediump_dmat3x2; + + /// 3 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, double, highp> highp_dmat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double3x3.hpp b/vendor/glm/glm/ext/matrix_double3x3.hpp new file mode 100644 index 0000000..53572b7 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double3x3.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_double3x3.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, double, defaultp> dmat3x3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, double, defaultp> dmat3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double3x3_precision.hpp b/vendor/glm/glm/ext/matrix_double3x3_precision.hpp new file mode 100644 index 0000000..8691e78 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double3x3_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_double3x3_precision.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, lowp> lowp_dmat3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, mediump> mediump_dmat3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, highp> highp_dmat3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, lowp> lowp_dmat3x3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, mediump> mediump_dmat3x3; + + /// 3 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, double, highp> highp_dmat3x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double3x4.hpp b/vendor/glm/glm/ext/matrix_double3x4.hpp new file mode 100644 index 0000000..c572d63 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double3x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double3x4.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 4, double, defaultp> dmat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double3x4_precision.hpp b/vendor/glm/glm/ext/matrix_double3x4_precision.hpp new file mode 100644 index 0000000..f040217 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double3x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double3x4_precision.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, double, lowp> lowp_dmat3x4; + + /// 3 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, double, mediump> mediump_dmat3x4; + + /// 3 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, double, highp> highp_dmat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double4x2.hpp b/vendor/glm/glm/ext/matrix_double4x2.hpp new file mode 100644 index 0000000..9b229f4 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double4x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double4x2.hpp + +#pragma once +#include "../detail/type_mat4x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 2 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 2, double, defaultp> dmat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double4x2_precision.hpp b/vendor/glm/glm/ext/matrix_double4x2_precision.hpp new file mode 100644 index 0000000..6ad18ba --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double4x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double4x2_precision.hpp + +#pragma once +#include "../detail/type_mat4x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 2 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, double, lowp> lowp_dmat4x2; + + /// 4 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, double, mediump> mediump_dmat4x2; + + /// 4 columns of 2 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, double, highp> highp_dmat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double4x3.hpp b/vendor/glm/glm/ext/matrix_double4x3.hpp new file mode 100644 index 0000000..dca4cf9 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double4x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_double4x3.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 3 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 3, double, defaultp> dmat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double4x3_precision.hpp b/vendor/glm/glm/ext/matrix_double4x3_precision.hpp new file mode 100644 index 0000000..f7371de --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double4x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_double4x3_precision.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 3 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, double, lowp> lowp_dmat4x3; + + /// 4 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, double, mediump> mediump_dmat4x3; + + /// 4 columns of 3 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, double, highp> highp_dmat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double4x4.hpp b/vendor/glm/glm/ext/matrix_double4x4.hpp new file mode 100644 index 0000000..81e1bf6 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double4x4.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_double4x4.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, double, defaultp> dmat4x4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, double, defaultp> dmat4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_double4x4_precision.hpp b/vendor/glm/glm/ext/matrix_double4x4_precision.hpp new file mode 100644 index 0000000..4c36a84 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_double4x4_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_double4x4_precision.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, lowp> lowp_dmat4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, mediump> mediump_dmat4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, highp> highp_dmat4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, lowp> lowp_dmat4x4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, mediump> mediump_dmat4x4; + + /// 4 columns of 4 components matrix of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, double, highp> highp_dmat4x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float2x2.hpp b/vendor/glm/glm/ext/matrix_float2x2.hpp new file mode 100644 index 0000000..53df921 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float2x2.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_float2x2.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, float, defaultp> mat2x2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 2, float, defaultp> mat2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float2x2_precision.hpp b/vendor/glm/glm/ext/matrix_float2x2_precision.hpp new file mode 100644 index 0000000..898b6db --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float2x2_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_float2x2_precision.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, lowp> lowp_mat2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, mediump> mediump_mat2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, highp> highp_mat2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, lowp> lowp_mat2x2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, mediump> mediump_mat2x2; + + /// 2 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 2, float, highp> highp_mat2x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float2x3.hpp b/vendor/glm/glm/ext/matrix_float2x3.hpp new file mode 100644 index 0000000..6f68822 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float2x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float2x3.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 3, float, defaultp> mat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float2x3_precision.hpp b/vendor/glm/glm/ext/matrix_float2x3_precision.hpp new file mode 100644 index 0000000..50c1032 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float2x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float2x3_precision.hpp + +#pragma once +#include "../detail/type_mat2x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, float, lowp> lowp_mat2x3; + + /// 2 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, float, mediump> mediump_mat2x3; + + /// 2 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 3, float, highp> highp_mat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float2x4.hpp b/vendor/glm/glm/ext/matrix_float2x4.hpp new file mode 100644 index 0000000..30f30de --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float2x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float2x4.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 2 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<2, 4, float, defaultp> mat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float2x4_precision.hpp b/vendor/glm/glm/ext/matrix_float2x4_precision.hpp new file mode 100644 index 0000000..079d638 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float2x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float2x4_precision.hpp + +#pragma once +#include "../detail/type_mat2x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 2 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, float, lowp> lowp_mat2x4; + + /// 2 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, float, mediump> mediump_mat2x4; + + /// 2 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<2, 4, float, highp> highp_mat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float3x2.hpp b/vendor/glm/glm/ext/matrix_float3x2.hpp new file mode 100644 index 0000000..d39dd2f --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float3x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float3x2.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core + /// @{ + + /// 3 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 2, float, defaultp> mat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float3x2_precision.hpp b/vendor/glm/glm/ext/matrix_float3x2_precision.hpp new file mode 100644 index 0000000..8572c2a --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float3x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float3x2_precision.hpp + +#pragma once +#include "../detail/type_mat3x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, float, lowp> lowp_mat3x2; + + /// 3 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, float, mediump> mediump_mat3x2; + + /// 3 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 2, float, highp> highp_mat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float3x3.hpp b/vendor/glm/glm/ext/matrix_float3x3.hpp new file mode 100644 index 0000000..177d809 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float3x3.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_float3x3.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, float, defaultp> mat3x3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 3, float, defaultp> mat3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float3x3_precision.hpp b/vendor/glm/glm/ext/matrix_float3x3_precision.hpp new file mode 100644 index 0000000..8a900c1 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float3x3_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_float3x3_precision.hpp + +#pragma once +#include "../detail/type_mat3x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, lowp> lowp_mat3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, mediump> mediump_mat3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, highp> highp_mat3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, lowp> lowp_mat3x3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, mediump> mediump_mat3x3; + + /// 3 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 3, float, highp> highp_mat3x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float3x4.hpp b/vendor/glm/glm/ext/matrix_float3x4.hpp new file mode 100644 index 0000000..64b8459 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float3x4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float3x4.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 3 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<3, 4, float, defaultp> mat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float3x4_precision.hpp b/vendor/glm/glm/ext/matrix_float3x4_precision.hpp new file mode 100644 index 0000000..bc36bf1 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float3x4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float3x4_precision.hpp + +#pragma once +#include "../detail/type_mat3x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 3 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, float, lowp> lowp_mat3x4; + + /// 3 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, float, mediump> mediump_mat3x4; + + /// 3 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<3, 4, float, highp> highp_mat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float4x2.hpp b/vendor/glm/glm/ext/matrix_float4x2.hpp new file mode 100644 index 0000000..1ed5227 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float4x2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float4x2.hpp + +#pragma once +#include "../detail/type_mat4x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 2 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 2, float, defaultp> mat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float4x2_precision.hpp b/vendor/glm/glm/ext/matrix_float4x2_precision.hpp new file mode 100644 index 0000000..88fd069 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float4x2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float2x2_precision.hpp + +#pragma once +#include "../detail/type_mat2x2.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 2 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, float, lowp> lowp_mat4x2; + + /// 4 columns of 2 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, float, mediump> mediump_mat4x2; + + /// 4 columns of 2 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 2, float, highp> highp_mat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float4x3.hpp b/vendor/glm/glm/ext/matrix_float4x3.hpp new file mode 100644 index 0000000..5dbe765 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float4x3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/matrix_float4x3.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix + /// @{ + + /// 4 columns of 3 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 3, float, defaultp> mat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float4x3_precision.hpp b/vendor/glm/glm/ext/matrix_float4x3_precision.hpp new file mode 100644 index 0000000..846ed4f --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float4x3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/matrix_float4x3_precision.hpp + +#pragma once +#include "../detail/type_mat4x3.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 3 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, float, lowp> lowp_mat4x3; + + /// 4 columns of 3 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, float, mediump> mediump_mat4x3; + + /// 4 columns of 3 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 3, float, highp> highp_mat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float4x4.hpp b/vendor/glm/glm/ext/matrix_float4x4.hpp new file mode 100644 index 0000000..5ba111d --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float4x4.hpp @@ -0,0 +1,23 @@ +/// @ref core +/// @file glm/ext/matrix_float4x4.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @ingroup core_matrix + /// @{ + + /// 4 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, float, defaultp> mat4x4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + typedef mat<4, 4, float, defaultp> mat4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_float4x4_precision.hpp b/vendor/glm/glm/ext/matrix_float4x4_precision.hpp new file mode 100644 index 0000000..597149b --- /dev/null +++ b/vendor/glm/glm/ext/matrix_float4x4_precision.hpp @@ -0,0 +1,49 @@ +/// @ref core +/// @file glm/ext/matrix_float4x4_precision.hpp + +#pragma once +#include "../detail/type_mat4x4.hpp" + +namespace glm +{ + /// @addtogroup core_matrix_precision + /// @{ + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, lowp> lowp_mat4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, mediump> mediump_mat4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, highp> highp_mat4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, lowp> lowp_mat4x4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, mediump> mediump_mat4x4; + + /// 4 columns of 4 components matrix of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see GLSL 4.20.8 specification, section 4.1.6 Matrices + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef mat<4, 4, float, highp> highp_mat4x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int2x2.hpp b/vendor/glm/glm/ext/matrix_int2x2.hpp new file mode 100644 index 0000000..c6aa068 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int2x2.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_int2x2 +/// @file glm/ext/matrix_int2x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x2 GLM_EXT_matrix_int2x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x2 + /// @{ + + /// Signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2 + typedef mat<2, 2, int, defaultp> imat2x2; + + /// Signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2 + typedef mat<2, 2, int, defaultp> imat2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int2x2_sized.hpp b/vendor/glm/glm/ext/matrix_int2x2_sized.hpp new file mode 100644 index 0000000..70c0c21 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int2x2_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_int2x2_sized +/// @file glm/ext/matrix_int2x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x2_sized GLM_EXT_matrix_int2x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x2_sized + /// @{ + + /// 8 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int8, defaultp> i8mat2x2; + + /// 16 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int16, defaultp> i16mat2x2; + + /// 32 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int32, defaultp> i32mat2x2; + + /// 64 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int64, defaultp> i64mat2x2; + + + /// 8 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int8, defaultp> i8mat2; + + /// 16 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int16, defaultp> i16mat2; + + /// 32 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int32, defaultp> i32mat2; + + /// 64 bit signed integer 2x2 matrix. + /// + /// @see ext_matrix_int2x2_sized + typedef mat<2, 2, int64, defaultp> i64mat2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int2x3.hpp b/vendor/glm/glm/ext/matrix_int2x3.hpp new file mode 100644 index 0000000..aee415c --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int2x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int2x3 +/// @file glm/ext/matrix_int2x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x3 GLM_EXT_matrix_int2x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x3 + /// @{ + + /// Signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3 + typedef mat<2, 3, int, defaultp> imat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int2x3_sized.hpp b/vendor/glm/glm/ext/matrix_int2x3_sized.hpp new file mode 100644 index 0000000..b5526fe --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int2x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int2x3_sized +/// @file glm/ext/matrix_int2x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x3_sized GLM_EXT_matrix_int2x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x3_sized + /// @{ + + /// 8 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int8, defaultp> i8mat2x3; + + /// 16 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int16, defaultp> i16mat2x3; + + /// 32 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int32, defaultp> i32mat2x3; + + /// 64 bit signed integer 2x3 matrix. + /// + /// @see ext_matrix_int2x3_sized + typedef mat<2, 3, int64, defaultp> i64mat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int2x4.hpp b/vendor/glm/glm/ext/matrix_int2x4.hpp new file mode 100644 index 0000000..4f36331 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int2x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int2x4 +/// @file glm/ext/matrix_int2x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x4 GLM_EXT_matrix_int2x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x4 + /// @{ + + /// Signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4 + typedef mat<2, 4, int, defaultp> imat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int2x4_sized.hpp b/vendor/glm/glm/ext/matrix_int2x4_sized.hpp new file mode 100644 index 0000000..a66a5e7 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int2x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int2x4_sized +/// @file glm/ext/matrix_int2x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x4_sized GLM_EXT_matrix_int2x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int2x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int2x4_sized + /// @{ + + /// 8 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int8, defaultp> i8mat2x4; + + /// 16 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int16, defaultp> i16mat2x4; + + /// 32 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int32, defaultp> i32mat2x4; + + /// 64 bit signed integer 2x4 matrix. + /// + /// @see ext_matrix_int2x4_sized + typedef mat<2, 4, int64, defaultp> i64mat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int3x2.hpp b/vendor/glm/glm/ext/matrix_int3x2.hpp new file mode 100644 index 0000000..3bd563b --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int3x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int3x2 +/// @file glm/ext/matrix_int3x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x2 GLM_EXT_matrix_int3x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x2 + /// @{ + + /// Signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2 + typedef mat<3, 2, int, defaultp> imat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int3x2_sized.hpp b/vendor/glm/glm/ext/matrix_int3x2_sized.hpp new file mode 100644 index 0000000..7e34c52 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int3x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int3x2_sized +/// @file glm/ext/matrix_int3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x2_sized GLM_EXT_matrix_int3x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x2_sized + /// @{ + + /// 8 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int8, defaultp> i8mat3x2; + + /// 16 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int16, defaultp> i16mat3x2; + + /// 32 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int32, defaultp> i32mat3x2; + + /// 64 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_int3x2_sized + typedef mat<3, 2, int64, defaultp> i64mat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int3x3.hpp b/vendor/glm/glm/ext/matrix_int3x3.hpp new file mode 100644 index 0000000..287488d --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int3x3.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_int3x3 +/// @file glm/ext/matrix_int3x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x3 GLM_EXT_matrix_int3x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x3 + /// @{ + + /// Signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3 + typedef mat<3, 3, int, defaultp> imat3x3; + + /// Signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3 + typedef mat<3, 3, int, defaultp> imat3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int3x3_sized.hpp b/vendor/glm/glm/ext/matrix_int3x3_sized.hpp new file mode 100644 index 0000000..577e305 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int3x3_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_int3x3_sized +/// @file glm/ext/matrix_int3x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x3_sized GLM_EXT_matrix_int3x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x3_sized + /// @{ + + /// 8 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int8, defaultp> i8mat3x3; + + /// 16 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int16, defaultp> i16mat3x3; + + /// 32 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int32, defaultp> i32mat3x3; + + /// 64 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int64, defaultp> i64mat3x3; + + + /// 8 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int8, defaultp> i8mat3; + + /// 16 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int16, defaultp> i16mat3; + + /// 32 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int32, defaultp> i32mat3; + + /// 64 bit signed integer 3x3 matrix. + /// + /// @see ext_matrix_int3x3_sized + typedef mat<3, 3, int64, defaultp> i64mat3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int3x4.hpp b/vendor/glm/glm/ext/matrix_int3x4.hpp new file mode 100644 index 0000000..08e534d --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int3x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int3x4 +/// @file glm/ext/matrix_int3x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x4 GLM_EXT_matrix_int3x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x4 + /// @{ + + /// Signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4 + typedef mat<3, 4, int, defaultp> imat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int3x4_sized.hpp b/vendor/glm/glm/ext/matrix_int3x4_sized.hpp new file mode 100644 index 0000000..692c48c --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int3x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int3x4_sized +/// @file glm/ext/matrix_int3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x4_sized GLM_EXT_matrix_int3x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int3x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int3x4_sized + /// @{ + + /// 8 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int8, defaultp> i8mat3x4; + + /// 16 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int16, defaultp> i16mat3x4; + + /// 32 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int32, defaultp> i32mat3x4; + + /// 64 bit signed integer 3x4 matrix. + /// + /// @see ext_matrix_int3x4_sized + typedef mat<3, 4, int64, defaultp> i64mat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int4x2.hpp b/vendor/glm/glm/ext/matrix_int4x2.hpp new file mode 100644 index 0000000..f756ef2 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int4x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int4x2 +/// @file glm/ext/matrix_int4x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x2 GLM_EXT_matrix_int4x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x2 + /// @{ + + /// Signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2 + typedef mat<4, 2, int, defaultp> imat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int4x2_sized.hpp b/vendor/glm/glm/ext/matrix_int4x2_sized.hpp new file mode 100644 index 0000000..63a99d6 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int4x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int4x2_sized +/// @file glm/ext/matrix_int4x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x2_sized GLM_EXT_matrix_int4x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x2_sized + /// @{ + + /// 8 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int8, defaultp> i8mat4x2; + + /// 16 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int16, defaultp> i16mat4x2; + + /// 32 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int32, defaultp> i32mat4x2; + + /// 64 bit signed integer 4x2 matrix. + /// + /// @see ext_matrix_int4x2_sized + typedef mat<4, 2, int64, defaultp> i64mat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int4x3.hpp b/vendor/glm/glm/ext/matrix_int4x3.hpp new file mode 100644 index 0000000..d5d97a7 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int4x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_int4x3 +/// @file glm/ext/matrix_int4x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x3 GLM_EXT_matrix_int4x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x3 + /// @{ + + /// Signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3 + typedef mat<4, 3, int, defaultp> imat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int4x3_sized.hpp b/vendor/glm/glm/ext/matrix_int4x3_sized.hpp new file mode 100644 index 0000000..55078fa --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int4x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_int4x3_sized +/// @file glm/ext/matrix_int4x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x3_sized GLM_EXT_matrix_int4x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x3_sized + /// @{ + + /// 8 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int8, defaultp> i8mat4x3; + + /// 16 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int16, defaultp> i16mat4x3; + + /// 32 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int32, defaultp> i32mat4x3; + + /// 64 bit signed integer 4x3 matrix. + /// + /// @see ext_matrix_int4x3_sized + typedef mat<4, 3, int64, defaultp> i64mat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int4x4.hpp b/vendor/glm/glm/ext/matrix_int4x4.hpp new file mode 100644 index 0000000..e17cff1 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int4x4.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_int4x4 +/// @file glm/ext/matrix_int4x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x4 GLM_EXT_matrix_int4x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x4 + /// @{ + + /// Signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4 + typedef mat<4, 4, int, defaultp> imat4x4; + + /// Signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4 + typedef mat<4, 4, int, defaultp> imat4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_int4x4_sized.hpp b/vendor/glm/glm/ext/matrix_int4x4_sized.hpp new file mode 100644 index 0000000..4a11203 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_int4x4_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_int4x4_sized +/// @file glm/ext/matrix_int4x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int4x4_sized GLM_EXT_matrix_int4x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_int4x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_int4x4_sized + /// @{ + + /// 8 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int8, defaultp> i8mat4x4; + + /// 16 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int16, defaultp> i16mat4x4; + + /// 32 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int32, defaultp> i32mat4x4; + + /// 64 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int64, defaultp> i64mat4x4; + + + /// 8 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int8, defaultp> i8mat4; + + /// 16 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int16, defaultp> i16mat4; + + /// 32 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int32, defaultp> i32mat4; + + /// 64 bit signed integer 4x4 matrix. + /// + /// @see ext_matrix_int4x4_sized + typedef mat<4, 4, int64, defaultp> i64mat4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_projection.hpp b/vendor/glm/glm/ext/matrix_projection.hpp new file mode 100644 index 0000000..51fd01b --- /dev/null +++ b/vendor/glm/glm/ext/matrix_projection.hpp @@ -0,0 +1,149 @@ +/// @ref ext_matrix_projection +/// @file glm/ext/matrix_projection.hpp +/// +/// @defgroup ext_matrix_projection GLM_EXT_matrix_projection +/// @ingroup ext +/// +/// Functions that generate common projection transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_transform +/// @see ext_matrix_clip_space + +#pragma once + +// Dependencies +#include "../gtc/constants.hpp" +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_projection extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_projection + /// @{ + + /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param obj Specify the object coordinates. + /// @param model Specifies the current modelview matrix + /// @param proj Specifies the current projection matrix + /// @param viewport Specifies the current viewport + /// @return Return the computed window coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluProject man page + template + GLM_FUNC_DECL vec<3, T, Q> projectZO( + vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param obj Specify the object coordinates. + /// @param model Specifies the current modelview matrix + /// @param proj Specifies the current projection matrix + /// @param viewport Specifies the current viewport + /// @return Return the computed window coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluProject man page + template + GLM_FUNC_DECL vec<3, T, Q> projectNO( + vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates using default near and far clip planes definition. + /// To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param obj Specify the object coordinates. + /// @param model Specifies the current modelview matrix + /// @param proj Specifies the current projection matrix + /// @param viewport Specifies the current viewport + /// @return Return the computed window coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluProject man page + template + GLM_FUNC_DECL vec<3, T, Q> project( + vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of 0 and +1 respectively. (Direct3D clip volume definition) + /// + /// @param win Specify the window coordinates to be mapped. + /// @param model Specifies the modelview matrix + /// @param proj Specifies the projection matrix + /// @param viewport Specifies the viewport + /// @return Returns the computed object coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluUnProject man page + template + GLM_FUNC_DECL vec<3, T, Q> unProjectZO( + vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. + /// The near and far clip planes correspond to z normalized device coordinates of -1 and +1 respectively. (OpenGL clip volume definition) + /// + /// @param win Specify the window coordinates to be mapped. + /// @param model Specifies the modelview matrix + /// @param proj Specifies the projection matrix + /// @param viewport Specifies the viewport + /// @return Returns the computed object coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluUnProject man page + template + GLM_FUNC_DECL vec<3, T, Q> unProjectNO( + vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates using default near and far clip planes definition. + /// To change default near and far clip planes definition use GLM_FORCE_DEPTH_ZERO_TO_ONE. + /// + /// @param win Specify the window coordinates to be mapped. + /// @param model Specifies the modelview matrix + /// @param proj Specifies the projection matrix + /// @param viewport Specifies the viewport + /// @return Returns the computed object coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluUnProject man page + template + GLM_FUNC_DECL vec<3, T, Q> unProject( + vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport); + + /// Define a picking region + /// + /// @param center Specify the center of a picking region in window coordinates. + /// @param delta Specify the width and height, respectively, of the picking region in window coordinates. + /// @param viewport Rendering viewport + /// @tparam T Native type used for the computation. Currently supported: half (not recommended), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// + /// @see gluPickMatrix man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> pickMatrix( + vec<2, T, Q> const& center, vec<2, T, Q> const& delta, vec<4, U, Q> const& viewport); + + /// @} +}//namespace glm + +#include "matrix_projection.inl" diff --git a/vendor/glm/glm/ext/matrix_projection.inl b/vendor/glm/glm/ext/matrix_projection.inl new file mode 100644 index 0000000..2f2c196 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_projection.inl @@ -0,0 +1,106 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> projectZO(vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + vec<4, T, Q> tmp = vec<4, T, Q>(obj, static_cast(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp.x = tmp.x * static_cast(0.5) + static_cast(0.5); + tmp.y = tmp.y * static_cast(0.5) + static_cast(0.5); + + tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]); + tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]); + + return vec<3, T, Q>(tmp); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> projectNO(vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + vec<4, T, Q> tmp = vec<4, T, Q>(obj, static_cast(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp = tmp * static_cast(0.5) + static_cast(0.5); + tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]); + tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]); + + return vec<3, T, Q>(tmp); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> project(vec<3, T, Q> const& obj, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return projectZO(obj, model, proj, viewport); +# else + return projectNO(obj, model, proj, viewport); +# endif + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unProjectZO(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + mat<4, 4, T, Q> Inverse = inverse(proj * model); + + vec<4, T, Q> tmp = vec<4, T, Q>(win, T(1)); + tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]); + tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]); + tmp.x = tmp.x * static_cast(2) - static_cast(1); + tmp.y = tmp.y * static_cast(2) - static_cast(1); + + vec<4, T, Q> obj = Inverse * tmp; + obj /= obj.w; + + return vec<3, T, Q>(obj); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unProjectNO(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { + mat<4, 4, T, Q> Inverse = inverse(proj * model); + + vec<4, T, Q> tmp = vec<4, T, Q>(win, T(1)); + tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]); + tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]); + tmp = tmp * static_cast(2) - static_cast(1); + + vec<4, T, Q> obj = Inverse * tmp; + obj /= obj.w; + + return vec<3, T, Q>(obj); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unProject(vec<3, T, Q> const& win, mat<4, 4, T, Q> const& model, mat<4, 4, T, Q> const& proj, vec<4, U, Q> const& viewport) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_ZO_BIT + return unProjectZO(win, model, proj, viewport); +# else + return unProjectNO(win, model, proj, viewport); +# endif + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> pickMatrix(vec<2, T, Q> const& center, vec<2, T, Q> const& delta, vec<4, U, Q> const& viewport) + { + assert(delta.x > static_cast(0) && delta.y > static_cast(0)); + mat<4, 4, T, Q> Result(static_cast(1)); + + if(!(delta.x > static_cast(0) && delta.y > static_cast(0))) + return Result; // Error + + vec<3, T, Q> Temp( + (static_cast(viewport[2]) - static_cast(2) * (center.x - static_cast(viewport[0]))) / delta.x, + (static_cast(viewport[3]) - static_cast(2) * (center.y - static_cast(viewport[1]))) / delta.y, + static_cast(0)); + + // Translate and scale the picked region to the entire window + Result = translate(Result, Temp); + return scale(Result, vec<3, T, Q>(static_cast(viewport[2]) / delta.x, static_cast(viewport[3]) / delta.y, static_cast(1))); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_relational.hpp b/vendor/glm/glm/ext/matrix_relational.hpp new file mode 100644 index 0000000..20023ad --- /dev/null +++ b/vendor/glm/glm/ext/matrix_relational.hpp @@ -0,0 +1,132 @@ +/// @ref ext_matrix_relational +/// @file glm/ext/matrix_relational.hpp +/// +/// @defgroup ext_matrix_relational GLM_EXT_matrix_relational +/// @ingroup ext +/// +/// Exposes comparison functions for matrix types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_relational +/// @see ext_scalar_relational +/// @see ext_quaternion_relational + +#pragma once + +// Dependencies +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_relational + /// @{ + + /// Perform a component-wise equal-to comparison of two matrices. + /// Return a boolean vector which components value is True if this expression is satisfied per column of the matrices. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y); + + /// Perform a component-wise not-equal-to comparison of two matrices. + /// Return a boolean vector which components value is True if this expression is satisfied per column of the matrices. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, vec const& epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, vec const& epsilon); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(mat const& x, mat const& y, vec const& ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number of columns of the matrix + /// @tparam R Integer between 1 and 4 included that qualify the number of rows of the matrix + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, vec const& ULPs); + + /// @} +}//namespace glm + +#include "matrix_relational.inl" diff --git a/vendor/glm/glm/ext/matrix_relational.inl b/vendor/glm/glm/ext/matrix_relational.inl new file mode 100644 index 0000000..b2b8753 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_relational.inl @@ -0,0 +1,82 @@ +/// @ref ext_vector_relational +/// @file glm/ext/vector_relational.inl + +// Dependency: +#include "../ext/vector_relational.hpp" +#include "../common.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b) + { + return equal(a, b, static_cast(0)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, T Epsilon) + { + return equal(a, b, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, vec const& Epsilon) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i], Epsilon[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y) + { + return notEqual(x, y, static_cast(0)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, T Epsilon) + { + return notEqual(x, y, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b, vec const& Epsilon) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = any(notEqual(a[i], b[i], Epsilon[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, int MaxULPs) + { + return equal(a, b, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(mat const& a, mat const& b, vec const& MaxULPs) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i], MaxULPs[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& x, mat const& y, int MaxULPs) + { + return notEqual(x, y, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b, vec const& MaxULPs) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = any(notEqual(a[i], b[i], MaxULPs[i])); + return Result; + } + +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_transform.hpp b/vendor/glm/glm/ext/matrix_transform.hpp new file mode 100644 index 0000000..cbd187e --- /dev/null +++ b/vendor/glm/glm/ext/matrix_transform.hpp @@ -0,0 +1,144 @@ +/// @ref ext_matrix_transform +/// @file glm/ext/matrix_transform.hpp +/// +/// @defgroup ext_matrix_transform GLM_EXT_matrix_transform +/// @ingroup ext +/// +/// Defines functions that generate common transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// Include to use the features of this extension. +/// +/// @see ext_matrix_projection +/// @see ext_matrix_clip_space + +#pragma once + +// Dependencies +#include "../gtc/constants.hpp" +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_transform + /// @{ + + /// Builds an identity matrix. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType identity(); + + /// Builds a translation 4 * 4 matrix created from a vector of 3 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a translation vector. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @code + /// #include + /// #include + /// ... + /// glm::mat4 m = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f)); + /// // m[0][0] == 1.0f, m[0][1] == 0.0f, m[0][2] == 0.0f, m[0][3] == 0.0f + /// // m[1][0] == 0.0f, m[1][1] == 1.0f, m[1][2] == 0.0f, m[1][3] == 0.0f + /// // m[2][0] == 0.0f, m[2][1] == 0.0f, m[2][2] == 1.0f, m[2][3] == 0.0f + /// // m[3][0] == 1.0f, m[3][1] == 1.0f, m[3][2] == 1.0f, m[3][3] == 1.0f + /// @endcode + /// + /// @see - translate(mat<4, 4, T, Q> const& m, T x, T y, T z) + /// @see - translate(vec<3, T, Q> const& v) + /// @see glTranslate man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> translate( + mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v); + + /// Builds a rotation 4 * 4 matrix created from an axis vector and an angle. + /// + /// @param m Input matrix multiplied by this rotation matrix. + /// @param angle Rotation angle expressed in radians. + /// @param axis Rotation axis, recommended to be normalized. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - rotate(mat<4, 4, T, Q> const& m, T angle, T x, T y, T z) + /// @see - rotate(T angle, vec<3, T, Q> const& v) + /// @see glRotate man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> rotate( + mat<4, 4, T, Q> const& m, T angle, vec<3, T, Q> const& axis); + + /// Builds a scale 4 * 4 matrix created from 3 scalars. + /// + /// @param m Input matrix multiplied by this scale matrix. + /// @param v Ratio of scaling for each axis. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - scale(mat<4, 4, T, Q> const& m, T x, T y, T z) + /// @see - scale(vec<3, T, Q> const& v) + /// @see glScale man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> scale( + mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v); + + /// Build a right handed look at view matrix. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) + template + GLM_FUNC_DECL mat<4, 4, T, Q> lookAtRH( + vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up); + + /// Build a left handed look at view matrix. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) + template + GLM_FUNC_DECL mat<4, 4, T, Q> lookAtLH( + vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up); + + /// Build a look at view matrix based on the default handedness. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) frustum(T const& left, T const& right, T const& bottom, T const& top, T const& nearVal, T const& farVal) + /// @see gluLookAt man page + template + GLM_FUNC_DECL mat<4, 4, T, Q> lookAt( + vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up); + + /// @} +}//namespace glm + +#include "matrix_transform.inl" diff --git a/vendor/glm/glm/ext/matrix_transform.inl b/vendor/glm/glm/ext/matrix_transform.inl new file mode 100644 index 0000000..a415157 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_transform.inl @@ -0,0 +1,152 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType identity() + { + return detail::init_gentype::GENTYPE>::identity(); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> translate(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v) + { + mat<4, 4, T, Q> Result(m); + Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotate(mat<4, 4, T, Q> const& m, T angle, vec<3, T, Q> const& v) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + vec<3, T, Q> axis(normalize(v)); + vec<3, T, Q> temp((T(1) - c) * axis); + + mat<4, 4, T, Q> Rotate; + Rotate[0][0] = c + temp[0] * axis[0]; + Rotate[0][1] = temp[0] * axis[1] + s * axis[2]; + Rotate[0][2] = temp[0] * axis[2] - s * axis[1]; + + Rotate[1][0] = temp[1] * axis[0] - s * axis[2]; + Rotate[1][1] = c + temp[1] * axis[1]; + Rotate[1][2] = temp[1] * axis[2] + s * axis[0]; + + Rotate[2][0] = temp[2] * axis[0] + s * axis[1]; + Rotate[2][1] = temp[2] * axis[1] - s * axis[0]; + Rotate[2][2] = c + temp[2] * axis[2]; + + mat<4, 4, T, Q> Result; + Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + Result[3] = m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotate_slow(mat<4, 4, T, Q> const& m, T angle, vec<3, T, Q> const& v) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + mat<4, 4, T, Q> Result; + + vec<3, T, Q> axis = normalize(v); + + Result[0][0] = c + (static_cast(1) - c) * axis.x * axis.x; + Result[0][1] = (static_cast(1) - c) * axis.x * axis.y + s * axis.z; + Result[0][2] = (static_cast(1) - c) * axis.x * axis.z - s * axis.y; + Result[0][3] = static_cast(0); + + Result[1][0] = (static_cast(1) - c) * axis.y * axis.x - s * axis.z; + Result[1][1] = c + (static_cast(1) - c) * axis.y * axis.y; + Result[1][2] = (static_cast(1) - c) * axis.y * axis.z + s * axis.x; + Result[1][3] = static_cast(0); + + Result[2][0] = (static_cast(1) - c) * axis.z * axis.x + s * axis.y; + Result[2][1] = (static_cast(1) - c) * axis.z * axis.y - s * axis.x; + Result[2][2] = c + (static_cast(1) - c) * axis.z * axis.z; + Result[2][3] = static_cast(0); + + Result[3] = vec<4, T, Q>(0, 0, 0, 1); + return m * Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scale(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v) + { + mat<4, 4, T, Q> Result; + Result[0] = m[0] * v[0]; + Result[1] = m[1] * v[1]; + Result[2] = m[2] * v[2]; + Result[3] = m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scale_slow(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& v) + { + mat<4, 4, T, Q> Result(T(1)); + Result[0][0] = v.x; + Result[1][1] = v.y; + Result[2][2] = v.z; + return m * Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtRH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up) + { + vec<3, T, Q> const f(normalize(center - eye)); + vec<3, T, Q> const s(normalize(cross(f, up))); + vec<3, T, Q> const u(cross(s, f)); + + mat<4, 4, T, Q> Result(1); + Result[0][0] = s.x; + Result[1][0] = s.y; + Result[2][0] = s.z; + Result[0][1] = u.x; + Result[1][1] = u.y; + Result[2][1] = u.z; + Result[0][2] =-f.x; + Result[1][2] =-f.y; + Result[2][2] =-f.z; + Result[3][0] =-dot(s, eye); + Result[3][1] =-dot(u, eye); + Result[3][2] = dot(f, eye); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAtLH(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up) + { + vec<3, T, Q> const f(normalize(center - eye)); + vec<3, T, Q> const s(normalize(cross(up, f))); + vec<3, T, Q> const u(cross(f, s)); + + mat<4, 4, T, Q> Result(1); + Result[0][0] = s.x; + Result[1][0] = s.y; + Result[2][0] = s.z; + Result[0][1] = u.x; + Result[1][1] = u.y; + Result[2][1] = u.z; + Result[0][2] = f.x; + Result[1][2] = f.y; + Result[2][2] = f.z; + Result[3][0] = -dot(s, eye); + Result[3][1] = -dot(u, eye); + Result[3][2] = -dot(f, eye); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAt(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up) + { + GLM_IF_CONSTEXPR(GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT) + return lookAtLH(eye, center, up); + else + return lookAtRH(eye, center, up); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint2x2.hpp b/vendor/glm/glm/ext/matrix_uint2x2.hpp new file mode 100644 index 0000000..034771a --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint2x2.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_uint2x2 +/// @file glm/ext/matrix_uint2x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x2 GLM_EXT_matrix_uint2x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x2 + /// @{ + + /// Unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2 + typedef mat<2, 2, uint, defaultp> umat2x2; + + /// Unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2 + typedef mat<2, 2, uint, defaultp> umat2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint2x2_sized.hpp b/vendor/glm/glm/ext/matrix_uint2x2_sized.hpp new file mode 100644 index 0000000..4555324 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint2x2_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_uint2x2_sized +/// @file glm/ext/matrix_uint2x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x2_sized GLM_EXT_matrix_uint2x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x2_sized + /// @{ + + /// 8 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint8, defaultp> u8mat2x2; + + /// 16 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint16, defaultp> u16mat2x2; + + /// 32 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint32, defaultp> u32mat2x2; + + /// 64 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint64, defaultp> u64mat2x2; + + + /// 8 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint8, defaultp> u8mat2; + + /// 16 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint16, defaultp> u16mat2; + + /// 32 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint32, defaultp> u32mat2; + + /// 64 bit unsigned integer 2x2 matrix. + /// + /// @see ext_matrix_uint2x2_sized + typedef mat<2, 2, uint64, defaultp> u64mat2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint2x3.hpp b/vendor/glm/glm/ext/matrix_uint2x3.hpp new file mode 100644 index 0000000..7de62f6 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint2x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint2x3 +/// @file glm/ext/matrix_uint2x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int2x3 GLM_EXT_matrix_uint2x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x3 + /// @{ + + /// Unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3 + typedef mat<2, 3, uint, defaultp> umat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint2x3_sized.hpp b/vendor/glm/glm/ext/matrix_uint2x3_sized.hpp new file mode 100644 index 0000000..db7939c --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint2x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint2x3_sized +/// @file glm/ext/matrix_uint2x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x3_sized GLM_EXT_matrix_uint2x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x3_sized + /// @{ + + /// 8 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint8, defaultp> u8mat2x3; + + /// 16 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint16, defaultp> u16mat2x3; + + /// 32 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint32, defaultp> u32mat2x3; + + /// 64 bit unsigned integer 2x3 matrix. + /// + /// @see ext_matrix_uint2x3_sized + typedef mat<2, 3, uint64, defaultp> u64mat2x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint2x4.hpp b/vendor/glm/glm/ext/matrix_uint2x4.hpp new file mode 100644 index 0000000..0f99350 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint2x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint2x4 +/// @file glm/ext/matrix_uint2x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x4 GLM_EXT_matrix_int2x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x4 + /// @{ + + /// Unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4 + typedef mat<2, 4, uint, defaultp> umat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint2x4_sized.hpp b/vendor/glm/glm/ext/matrix_uint2x4_sized.hpp new file mode 100644 index 0000000..5cb8e54 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint2x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint2x4_sized +/// @file glm/ext/matrixu_uint2x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint2x4_sized GLM_EXT_matrix_uint2x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint2x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint2x4_sized + /// @{ + + /// 8 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint8, defaultp> u8mat2x4; + + /// 16 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint16, defaultp> u16mat2x4; + + /// 32 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint32, defaultp> u32mat2x4; + + /// 64 bit unsigned integer 2x4 matrix. + /// + /// @see ext_matrix_uint2x4_sized + typedef mat<2, 4, uint64, defaultp> u64mat2x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint3x2.hpp b/vendor/glm/glm/ext/matrix_uint3x2.hpp new file mode 100644 index 0000000..47f4873 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint3x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint3x2 +/// @file glm/ext/matrix_uint3x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_int3x2 GLM_EXT_matrix_uint3x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x2 + /// @{ + + /// Unsigned integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2 + typedef mat<3, 2, uint, defaultp> umat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint3x2_sized.hpp b/vendor/glm/glm/ext/matrix_uint3x2_sized.hpp new file mode 100644 index 0000000..c81af8f --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint3x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint3x2_sized +/// @file glm/ext/matrix_uint3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x2_sized GLM_EXT_matrix_uint3x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x2_sized + /// @{ + + /// 8 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint8, defaultp> u8mat3x2; + + /// 16 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint16, defaultp> u16mat3x2; + + /// 32 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint32, defaultp> u32mat3x2; + + /// 64 bit signed integer 3x2 matrix. + /// + /// @see ext_matrix_uint3x2_sized + typedef mat<3, 2, uint64, defaultp> u64mat3x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint3x3.hpp b/vendor/glm/glm/ext/matrix_uint3x3.hpp new file mode 100644 index 0000000..1004c0d --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint3x3.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_uint3x3 +/// @file glm/ext/matrix_uint3x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x3 GLM_EXT_matrix_uint3x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x3 + /// @{ + + /// Unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3 + typedef mat<3, 3, uint, defaultp> umat3x3; + + /// Unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3 + typedef mat<3, 3, uint, defaultp> umat3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint3x3_sized.hpp b/vendor/glm/glm/ext/matrix_uint3x3_sized.hpp new file mode 100644 index 0000000..41a8be7 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint3x3_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_uint3x3_sized +/// @file glm/ext/matrix_uint3x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x3_sized GLM_EXT_matrix_uint3x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x3_sized + /// @{ + + /// 8 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint8, defaultp> u8mat3x3; + + /// 16 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint16, defaultp> u16mat3x3; + + /// 32 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint32, defaultp> u32mat3x3; + + /// 64 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint64, defaultp> u64mat3x3; + + + /// 8 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint8, defaultp> u8mat3; + + /// 16 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint16, defaultp> u16mat3; + + /// 32 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint32, defaultp> u32mat3; + + /// 64 bit unsigned integer 3x3 matrix. + /// + /// @see ext_matrix_uint3x3_sized + typedef mat<3, 3, uint64, defaultp> u64mat3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint3x4.hpp b/vendor/glm/glm/ext/matrix_uint3x4.hpp new file mode 100644 index 0000000..c6dd78c --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint3x4.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint3x4 +/// @file glm/ext/matrix_uint3x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x4 GLM_EXT_matrix_uint3x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x4 + /// @{ + + /// Signed integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4 + typedef mat<3, 4, uint, defaultp> umat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint3x4_sized.hpp b/vendor/glm/glm/ext/matrix_uint3x4_sized.hpp new file mode 100644 index 0000000..2ce28ad --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint3x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint3x4_sized +/// @file glm/ext/matrix_uint3x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint3x4_sized GLM_EXT_matrix_uint3x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat3x4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint3x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint3x4_sized + /// @{ + + /// 8 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint8, defaultp> u8mat3x4; + + /// 16 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint16, defaultp> u16mat3x4; + + /// 32 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint32, defaultp> u32mat3x4; + + /// 64 bit unsigned integer 3x4 matrix. + /// + /// @see ext_matrix_uint3x4_sized + typedef mat<3, 4, uint64, defaultp> u64mat3x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint4x2.hpp b/vendor/glm/glm/ext/matrix_uint4x2.hpp new file mode 100644 index 0000000..0446f57 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint4x2.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint4x2 +/// @file glm/ext/matrix_uint4x2.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x2 GLM_EXT_matrix_uint4x2 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x2 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x2 + /// @{ + + /// Unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2 + typedef mat<4, 2, uint, defaultp> umat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint4x2_sized.hpp b/vendor/glm/glm/ext/matrix_uint4x2_sized.hpp new file mode 100644 index 0000000..57a66bf --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint4x2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint4x2_sized +/// @file glm/ext/matrix_uint4x2_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x2_sized GLM_EXT_matrix_uint4x2_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x2_sized + /// @{ + + /// 8 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint8, defaultp> u8mat4x2; + + /// 16 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint16, defaultp> u16mat4x2; + + /// 32 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint32, defaultp> u32mat4x2; + + /// 64 bit unsigned integer 4x2 matrix. + /// + /// @see ext_matrix_uint4x2_sized + typedef mat<4, 2, uint64, defaultp> u64mat4x2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint4x3.hpp b/vendor/glm/glm/ext/matrix_uint4x3.hpp new file mode 100644 index 0000000..54c24e4 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint4x3.hpp @@ -0,0 +1,33 @@ +/// @ref ext_matrix_uint4x3 +/// @file glm/ext/matrix_uint4x3.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x3 GLM_EXT_matrix_uint4x3 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x3 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x3 + /// @{ + + /// Unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3 + typedef mat<4, 3, uint, defaultp> umat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint4x3_sized.hpp b/vendor/glm/glm/ext/matrix_uint4x3_sized.hpp new file mode 100644 index 0000000..2e61124 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint4x3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint4x3_sized +/// @file glm/ext/matrix_uint4x3_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x3_sized GLM_EXT_matrix_uint4x3_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x3_sized + /// @{ + + /// 8 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint8, defaultp> u8mat4x3; + + /// 16 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint16, defaultp> u16mat4x3; + + /// 32 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint32, defaultp> u32mat4x3; + + /// 64 bit unsigned integer 4x3 matrix. + /// + /// @see ext_matrix_uint4x3_sized + typedef mat<4, 3, uint64, defaultp> u64mat4x3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint4x4.hpp b/vendor/glm/glm/ext/matrix_uint4x4.hpp new file mode 100644 index 0000000..5cc8455 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint4x4.hpp @@ -0,0 +1,38 @@ +/// @ref ext_matrix_uint4x4 +/// @file glm/ext/matrix_uint4x4.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x4 GLM_EXT_matrix_uint4x4 +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x4 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x4 + /// @{ + + /// Unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4 + typedef mat<4, 4, uint, defaultp> umat4x4; + + /// Unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4 + typedef mat<4, 4, uint, defaultp> umat4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/matrix_uint4x4_sized.hpp b/vendor/glm/glm/ext/matrix_uint4x4_sized.hpp new file mode 100644 index 0000000..bb10bd2 --- /dev/null +++ b/vendor/glm/glm/ext/matrix_uint4x4_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_matrix_uint4x4_sized +/// @file glm/ext/matrix_uint4x4_sized.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_matrix_uint4x4_sized GLM_EXT_matrix_uint4x4_sized +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat4x4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_matrix_uint4x4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_uint4x4_sized + /// @{ + + /// 8 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint8, defaultp> u8mat4x4; + + /// 16 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint16, defaultp> u16mat4x4; + + /// 32 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint32, defaultp> u32mat4x4; + + /// 64 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint64, defaultp> u64mat4x4; + + + /// 8 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint8, defaultp> u8mat4; + + /// 16 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint16, defaultp> u16mat4; + + /// 32 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint32, defaultp> u32mat4; + + /// 64 bit unsigned integer 4x4 matrix. + /// + /// @see ext_matrix_uint4x4_sized + typedef mat<4, 4, uint64, defaultp> u64mat4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/quaternion_common.hpp b/vendor/glm/glm/ext/quaternion_common.hpp new file mode 100644 index 0000000..f519d55 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_common.hpp @@ -0,0 +1,135 @@ +/// @ref ext_quaternion_common +/// @file glm/ext/quaternion_common.hpp +/// +/// @defgroup ext_quaternion_common GLM_EXT_quaternion_common +/// @ingroup ext +/// +/// Provides common functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_common +/// @see ext_vector_common +/// @see ext_quaternion_float +/// @see ext_quaternion_double +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_trigonometric +/// @see ext_quaternion_transform + +#pragma once + +// Dependency: +#include "../ext/scalar_constants.hpp" +#include "../ext/quaternion_geometric.hpp" +#include "../common.hpp" +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_common extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_common + /// @{ + + /// Spherical linear interpolation of two quaternions. + /// The interpolation is oriented and the rotation is performed at constant speed. + /// For short path spherical linear interpolation, use the slerp function. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + /// + /// @see - slerp(qua const& x, qua const& y, T const& a) + template + GLM_FUNC_DECL qua mix(qua const& x, qua const& y, T a); + + /// Linear interpolation of two quaternions. + /// The interpolation is oriented. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined in the range [0, 1]. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua lerp(qua const& x, qua const& y, T a); + + /// Spherical linear interpolation of two quaternions. + /// The interpolation always take the short path and the rotation is performed at constant speed. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua slerp(qua const& x, qua const& y, T a); + + /// Spherical linear interpolation of two quaternions with multiple spins over rotation axis. + /// The interpolation always take the short path when the spin count is positive and long path + /// when count is negative. Rotation is performed at constant speed. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// @param k Additional spin count. If Value is negative interpolation will be on "long" path. + /// + /// @tparam T A floating-point scalar type + /// @tparam S An integer scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua slerp(qua const& x, qua const& y, T a, S k); + + /// Returns the q conjugate. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua conjugate(qua const& q); + + /// Returns the q inverse. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua inverse(qua const& q); + + /// Returns true if x holds a NaN (not a number) + /// representation in the underlying implementation's set of + /// floating point representations. Returns false otherwise, + /// including for implementations with no NaN + /// representations. + /// + /// /!\ When using compiler fast math, this function may fail. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> isnan(qua const& x); + + /// Returns true if x holds a positive infinity or negative + /// infinity representation in the underlying implementation's + /// set of floating point representations. Returns false + /// otherwise, including for implementations with no infinity + /// representations. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> isinf(qua const& x); + + /// @} +} //namespace glm + +#include "quaternion_common.inl" diff --git a/vendor/glm/glm/ext/quaternion_common.inl b/vendor/glm/glm/ext/quaternion_common.inl new file mode 100644 index 0000000..0e4a3bb --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_common.inl @@ -0,0 +1,144 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER qua mix(qua const& x, qua const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'mix' only accept floating-point inputs"); + + T const cosTheta = dot(x, y); + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if(cosTheta > static_cast(1) - epsilon()) + { + // Linear interpolation + return qua( + mix(x.w, y.w, a), + mix(x.x, y.x, a), + mix(x.y, y.y, a), + mix(x.z, y.z, a)); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((static_cast(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle); + } + } + + template + GLM_FUNC_QUALIFIER qua lerp(qua const& x, qua const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'lerp' only accept floating-point inputs"); + + // Lerp is only defined in [0, 1] + assert(a >= static_cast(0)); + assert(a <= static_cast(1)); + + return x * (static_cast(1) - a) + (y * a); + } + + template + GLM_FUNC_QUALIFIER qua slerp(qua const& x, qua const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'slerp' only accept floating-point inputs"); + + qua z = y; + + T cosTheta = dot(x, y); + + // If cosTheta < 0, the interpolation will take the long way around the sphere. + // To fix this, one quat must be negated. + if(cosTheta < static_cast(0)) + { + z = -y; + cosTheta = -cosTheta; + } + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if(cosTheta > static_cast(1) - epsilon()) + { + // Linear interpolation + return qua( + mix(x.w, z.w, a), + mix(x.x, z.x, a), + mix(x.y, z.y, a), + mix(x.z, z.z, a)); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((static_cast(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle); + } + } + + template + GLM_FUNC_QUALIFIER qua slerp(qua const& x, qua const& y, T a, S k) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'slerp' only accept floating-point inputs"); + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'slerp' only accept integer for spin count"); + + qua z = y; + + T cosTheta = dot(x, y); + + // If cosTheta < 0, the interpolation will take the long way around the sphere. + // To fix this, one quat must be negated. + if (cosTheta < static_cast(0)) + { + z = -y; + cosTheta = -cosTheta; + } + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if (cosTheta > static_cast(1) - epsilon()) + { + // Linear interpolation + return qua( + mix(x.w, z.w, a), + mix(x.x, z.x, a), + mix(x.y, z.y, a), + mix(x.z, z.z, a)); + } + else + { + // Graphics Gems III, page 96 + T angle = acos(cosTheta); + T phi = angle + k * glm::pi(); + return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle); + } + } + + template + GLM_FUNC_QUALIFIER qua conjugate(qua const& q) + { + return qua(q.w, -q.x, -q.y, -q.z); + } + + template + GLM_FUNC_QUALIFIER qua inverse(qua const& q) + { + return conjugate(q) / dot(q, q); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isnan(qua const& q) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isnan' only accept floating-point inputs"); + + return vec<4, bool, Q>(isnan(q.x), isnan(q.y), isnan(q.z), isnan(q.w)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isinf(qua const& q) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isinf' only accept floating-point inputs"); + + return vec<4, bool, Q>(isinf(q.x), isinf(q.y), isinf(q.z), isinf(q.w)); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "quaternion_common_simd.inl" +#endif + diff --git a/vendor/glm/glm/ext/quaternion_common_simd.inl b/vendor/glm/glm/ext/quaternion_common_simd.inl new file mode 100644 index 0000000..ddfc8a4 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_common_simd.inl @@ -0,0 +1,18 @@ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +namespace glm{ +namespace detail +{ + template + struct compute_dot, float, true> + { + static GLM_FUNC_QUALIFIER float call(qua const& x, qua const& y) + { + return _mm_cvtss_f32(glm_vec1_dot(x.data, y.data)); + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + diff --git a/vendor/glm/glm/ext/quaternion_double.hpp b/vendor/glm/glm/ext/quaternion_double.hpp new file mode 100644 index 0000000..63b24de --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_double.hpp @@ -0,0 +1,39 @@ +/// @ref ext_quaternion_double +/// @file glm/ext/quaternion_double.hpp +/// +/// @defgroup ext_quaternion_double GLM_EXT_quaternion_double +/// @ingroup ext +/// +/// Exposes double-precision floating point quaternion type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_float +/// @see ext_quaternion_double_precision +/// @see ext_quaternion_common +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_transform +/// @see ext_quaternion_trigonometric + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_double extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_double + /// @{ + + /// Quaternion of double-precision floating-point numbers. + typedef qua dquat; + + /// @} +} //namespace glm + diff --git a/vendor/glm/glm/ext/quaternion_double_precision.hpp b/vendor/glm/glm/ext/quaternion_double_precision.hpp new file mode 100644 index 0000000..8aa24a1 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_double_precision.hpp @@ -0,0 +1,42 @@ +/// @ref ext_quaternion_double_precision +/// @file glm/ext/quaternion_double_precision.hpp +/// +/// @defgroup ext_quaternion_double_precision GLM_EXT_quaternion_double_precision +/// @ingroup ext +/// +/// Exposes double-precision floating point quaternion type with various precision in term of ULPs. +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_double_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_double_precision + /// @{ + + /// Quaternion of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see ext_quaternion_double_precision + typedef qua lowp_dquat; + + /// Quaternion of medium double-qualifier floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see ext_quaternion_double_precision + typedef qua mediump_dquat; + + /// Quaternion of high double-qualifier floating-point numbers using high precision arithmetic in term of ULPs. + /// + /// @see ext_quaternion_double_precision + typedef qua highp_dquat; + + /// @} +} //namespace glm + diff --git a/vendor/glm/glm/ext/quaternion_exponential.hpp b/vendor/glm/glm/ext/quaternion_exponential.hpp new file mode 100644 index 0000000..affe297 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_exponential.hpp @@ -0,0 +1,63 @@ +/// @ref ext_quaternion_exponential +/// @file glm/ext/quaternion_exponential.hpp +/// +/// @defgroup ext_quaternion_exponential GLM_EXT_quaternion_exponential +/// @ingroup ext +/// +/// Provides exponential functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see core_exponential +/// @see ext_quaternion_float +/// @see ext_quaternion_double + +#pragma once + +// Dependency: +#include "../common.hpp" +#include "../trigonometric.hpp" +#include "../geometric.hpp" +#include "../ext/scalar_constants.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_exponential extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_transform + /// @{ + + /// Returns a exponential of a quaternion. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua exp(qua const& q); + + /// Returns a logarithm of a quaternion + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua log(qua const& q); + + /// Returns a quaternion raised to a power. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua pow(qua const& q, T y); + + /// Returns the square root of a quaternion + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua sqrt(qua const& q); + + /// @} +} //namespace glm + +#include "quaternion_exponential.inl" diff --git a/vendor/glm/glm/ext/quaternion_exponential.inl b/vendor/glm/glm/ext/quaternion_exponential.inl new file mode 100644 index 0000000..8456c00 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_exponential.inl @@ -0,0 +1,85 @@ +#include "scalar_constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER qua exp(qua const& q) + { + vec<3, T, Q> u(q.x, q.y, q.z); + T const Angle = glm::length(u); + if (Angle < epsilon()) + return qua(); + + vec<3, T, Q> const v(u / Angle); + return qua(cos(Angle), sin(Angle) * v); + } + + template + GLM_FUNC_QUALIFIER qua log(qua const& q) + { + vec<3, T, Q> u(q.x, q.y, q.z); + T Vec3Len = length(u); + + if (Vec3Len < epsilon()) + { + if(q.w > static_cast(0)) + return qua(log(q.w), static_cast(0), static_cast(0), static_cast(0)); + else if(q.w < static_cast(0)) + return qua(log(-q.w), pi(), static_cast(0), static_cast(0)); + else + return qua(std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity(), std::numeric_limits::infinity()); + } + else + { + T t = atan(Vec3Len, T(q.w)) / Vec3Len; + T QuatLen2 = Vec3Len * Vec3Len + q.w * q.w; + return qua(static_cast(0.5) * log(QuatLen2), t * q.x, t * q.y, t * q.z); + } + } + + template + GLM_FUNC_QUALIFIER qua pow(qua const& x, T y) + { + //Raising to the power of 0 should yield 1 + //Needed to prevent a division by 0 error later on + if(y > -epsilon() && y < epsilon()) + return qua(1,0,0,0); + + //To deal with non-unit quaternions + T magnitude = sqrt(x.x * x.x + x.y * x.y + x.z * x.z + x.w *x.w); + + T Angle; + if(abs(x.w / magnitude) > cos_one_over_two()) + { + //Scalar component is close to 1; using it to recover angle would lose precision + //Instead, we use the non-scalar components since sin() is accurate around 0 + + //Prevent a division by 0 error later on + T VectorMagnitude = x.x * x.x + x.y * x.y + x.z * x.z; + if (glm::abs(VectorMagnitude - static_cast(0)) < glm::epsilon()) { + //Equivalent to raising a real number to a power + return qua(pow(x.w, y), 0, 0, 0); + } + + Angle = asin(sqrt(VectorMagnitude) / magnitude); + } + else + { + //Scalar component is small, shouldn't cause loss of precision + Angle = acos(x.w / magnitude); + } + + T NewAngle = Angle * y; + T Div = sin(NewAngle) / sin(Angle); + T Mag = pow(magnitude, y - static_cast(1)); + return qua(cos(NewAngle) * magnitude * Mag, x.x * Div * Mag, x.y * Div * Mag, x.z * Div * Mag); + } + + template + GLM_FUNC_QUALIFIER qua sqrt(qua const& x) + { + return pow(x, static_cast(0.5)); + } +}//namespace glm + + diff --git a/vendor/glm/glm/ext/quaternion_float.hpp b/vendor/glm/glm/ext/quaternion_float.hpp new file mode 100644 index 0000000..ca42a60 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_float.hpp @@ -0,0 +1,39 @@ +/// @ref ext_quaternion_float +/// @file glm/ext/quaternion_float.hpp +/// +/// @defgroup ext_quaternion_float GLM_EXT_quaternion_float +/// @ingroup ext +/// +/// Exposes single-precision floating point quaternion type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_double +/// @see ext_quaternion_float_precision +/// @see ext_quaternion_common +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_transform +/// @see ext_quaternion_trigonometric + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_float extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_float + /// @{ + + /// Quaternion of single-precision floating-point numbers. + typedef qua quat; + + /// @} +} //namespace glm + diff --git a/vendor/glm/glm/ext/quaternion_float_precision.hpp b/vendor/glm/glm/ext/quaternion_float_precision.hpp new file mode 100644 index 0000000..f9e4f5c --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_float_precision.hpp @@ -0,0 +1,36 @@ +/// @ref ext_quaternion_float_precision +/// @file glm/ext/quaternion_float_precision.hpp +/// +/// @defgroup ext_quaternion_float_precision GLM_EXT_quaternion_float_precision +/// @ingroup ext +/// +/// Exposes single-precision floating point quaternion type with various precision in term of ULPs. +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependency: +#include "../detail/type_quat.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_float_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_float_precision + /// @{ + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua lowp_quat; + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua mediump_quat; + + /// Quaternion of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef qua highp_quat; + + /// @} +} //namespace glm + diff --git a/vendor/glm/glm/ext/quaternion_geometric.hpp b/vendor/glm/glm/ext/quaternion_geometric.hpp new file mode 100644 index 0000000..6d98bbe --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_geometric.hpp @@ -0,0 +1,70 @@ +/// @ref ext_quaternion_geometric +/// @file glm/ext/quaternion_geometric.hpp +/// +/// @defgroup ext_quaternion_geometric GLM_EXT_quaternion_geometric +/// @ingroup ext +/// +/// Provides geometric functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see core_geometric +/// @see ext_quaternion_float +/// @see ext_quaternion_double + +#pragma once + +// Dependency: +#include "../geometric.hpp" +#include "../exponential.hpp" +#include "../ext/vector_relational.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_geometric extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_geometric + /// @{ + + /// Returns the norm of a quaternions + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_DECL T length(qua const& q); + + /// Returns the normalized quaternion. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_DECL qua normalize(qua const& q); + + /// Returns dot product of q1 and q2, i.e., q1[0] * q2[0] + q1[1] * q2[1] + ... + /// + /// @tparam T Floating-point scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_DECL T dot(qua const& x, qua const& y); + + /// Compute a cross product. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_geometric + template + GLM_FUNC_QUALIFIER qua cross(qua const& q1, qua const& q2); + + /// @} +} //namespace glm + +#include "quaternion_geometric.inl" diff --git a/vendor/glm/glm/ext/quaternion_geometric.inl b/vendor/glm/glm/ext/quaternion_geometric.inl new file mode 100644 index 0000000..e155ac5 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_geometric.inl @@ -0,0 +1,36 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER T dot(qua const& x, qua const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'dot' accepts only floating-point inputs"); + return detail::compute_dot, T, detail::is_aligned::value>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER T length(qua const& q) + { + return glm::sqrt(dot(q, q)); + } + + template + GLM_FUNC_QUALIFIER qua normalize(qua const& q) + { + T len = length(q); + if(len <= static_cast(0)) // Problem + return qua(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + T oneOverLen = static_cast(1) / len; + return qua(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); + } + + template + GLM_FUNC_QUALIFIER qua cross(qua const& q1, qua const& q2) + { + return qua( + q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z, + q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, + q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, + q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x); + } +}//namespace glm + diff --git a/vendor/glm/glm/ext/quaternion_relational.hpp b/vendor/glm/glm/ext/quaternion_relational.hpp new file mode 100644 index 0000000..7aa121d --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_relational.hpp @@ -0,0 +1,62 @@ +/// @ref ext_quaternion_relational +/// @file glm/ext/quaternion_relational.hpp +/// +/// @defgroup ext_quaternion_relational GLM_EXT_quaternion_relational +/// @ingroup ext +/// +/// Exposes comparison functions for quaternion types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see core_vector_relational +/// @see ext_vector_relational +/// @see ext_matrix_relational +/// @see ext_quaternion_float +/// @see ext_quaternion_double + +#pragma once + +// Dependency: +#include "../vector_relational.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_relational + /// @{ + + /// Returns the component-wise comparison of result x == y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> equal(qua const& x, qua const& y); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> equal(qua const& x, qua const& y, T epsilon); + + /// Returns the component-wise comparison of result x != y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> notEqual(qua const& x, qua const& y); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL vec<4, bool, Q> notEqual(qua const& x, qua const& y, T epsilon); + + /// @} +} //namespace glm + +#include "quaternion_relational.inl" diff --git a/vendor/glm/glm/ext/quaternion_relational.inl b/vendor/glm/glm/ext/quaternion_relational.inl new file mode 100644 index 0000000..b1713e9 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_relational.inl @@ -0,0 +1,35 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> equal(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] == y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> equal(qua const& x, qua const& y, T epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return lessThan(abs(v), vec<4, T, Q>(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> notEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] != y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> notEqual(qua const& x, qua const& y, T epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return greaterThanEqual(abs(v), vec<4, T, Q>(epsilon)); + } +}//namespace glm + diff --git a/vendor/glm/glm/ext/quaternion_transform.hpp b/vendor/glm/glm/ext/quaternion_transform.hpp new file mode 100644 index 0000000..a9cc5c2 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_transform.hpp @@ -0,0 +1,47 @@ +/// @ref ext_quaternion_transform +/// @file glm/ext/quaternion_transform.hpp +/// +/// @defgroup ext_quaternion_transform GLM_EXT_quaternion_transform +/// @ingroup ext +/// +/// Provides transformation functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_float +/// @see ext_quaternion_double +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_trigonometric + +#pragma once + +// Dependency: +#include "../common.hpp" +#include "../trigonometric.hpp" +#include "../geometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_transform + /// @{ + + /// Rotates a quaternion from a vector of 3 components axis and an angle. + /// + /// @param q Source orientation + /// @param angle Angle expressed in radians. + /// @param axis Axis of the rotation + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL qua rotate(qua const& q, T const& angle, vec<3, T, Q> const& axis); + /// @} +} //namespace glm + +#include "quaternion_transform.inl" diff --git a/vendor/glm/glm/ext/quaternion_transform.inl b/vendor/glm/glm/ext/quaternion_transform.inl new file mode 100644 index 0000000..b87ecb6 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_transform.inl @@ -0,0 +1,24 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER qua rotate(qua const& q, T const& angle, vec<3, T, Q> const& v) + { + vec<3, T, Q> Tmp = v; + + // Axis of rotation must be normalised + T len = glm::length(Tmp); + if(abs(len - static_cast(1)) > static_cast(0.001)) + { + T oneOverLen = static_cast(1) / len; + Tmp.x *= oneOverLen; + Tmp.y *= oneOverLen; + Tmp.z *= oneOverLen; + } + + T const AngleRad(angle); + T const Sin = sin(AngleRad * static_cast(0.5)); + + return q * qua(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + } +}//namespace glm + diff --git a/vendor/glm/glm/ext/quaternion_trigonometric.hpp b/vendor/glm/glm/ext/quaternion_trigonometric.hpp new file mode 100644 index 0000000..76cea27 --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_trigonometric.hpp @@ -0,0 +1,63 @@ +/// @ref ext_quaternion_trigonometric +/// @file glm/ext/quaternion_trigonometric.hpp +/// +/// @defgroup ext_quaternion_trigonometric GLM_EXT_quaternion_trigonometric +/// @ingroup ext +/// +/// Provides trigonometric functions for quaternion types +/// +/// Include to use the features of this extension. +/// +/// @see ext_quaternion_float +/// @see ext_quaternion_double +/// @see ext_quaternion_exponential +/// @see ext_quaternion_geometric +/// @see ext_quaternion_relational +/// @see ext_quaternion_transform + +#pragma once + +// Dependency: +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include "scalar_constants.hpp" +#include "vector_relational.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_quaternion_trigonometric extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_quaternion_trigonometric + /// @{ + + /// Returns the quaternion rotation angle. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL T angle(qua const& x); + + /// Returns the q rotation axis. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL vec<3, T, Q> axis(qua const& x); + + /// Build a quaternion from an angle and a normalized axis. + /// + /// @param angle Angle expressed in radians. + /// @param axis Axis of the quaternion, must be normalized. + /// + /// @tparam T A floating-point scalar type + /// @tparam Q A value from qualifier enum + template + GLM_FUNC_DECL qua angleAxis(T const& angle, vec<3, T, Q> const& axis); + + /// @} +} //namespace glm + +#include "quaternion_trigonometric.inl" diff --git a/vendor/glm/glm/ext/quaternion_trigonometric.inl b/vendor/glm/glm/ext/quaternion_trigonometric.inl new file mode 100644 index 0000000..06b7c4c --- /dev/null +++ b/vendor/glm/glm/ext/quaternion_trigonometric.inl @@ -0,0 +1,34 @@ +#include "scalar_constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T angle(qua const& x) + { + if (abs(x.w) > cos_one_over_two()) + { + return asin(sqrt(x.x * x.x + x.y * x.y + x.z * x.z)) * static_cast(2); + } + + return acos(x.w) * static_cast(2); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> axis(qua const& x) + { + T const tmp1 = static_cast(1) - x.w * x.w; + if(tmp1 <= static_cast(0)) + return vec<3, T, Q>(0, 0, 1); + T const tmp2 = static_cast(1) / sqrt(tmp1); + return vec<3, T, Q>(x.x * tmp2, x.y * tmp2, x.z * tmp2); + } + + template + GLM_FUNC_QUALIFIER qua angleAxis(T const& angle, vec<3, T, Q> const& v) + { + T const a(angle); + T const s = glm::sin(a * static_cast(0.5)); + + return qua(glm::cos(a * static_cast(0.5)), v * s); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/scalar_common.hpp b/vendor/glm/glm/ext/scalar_common.hpp new file mode 100644 index 0000000..aa5a180 --- /dev/null +++ b/vendor/glm/glm/ext/scalar_common.hpp @@ -0,0 +1,157 @@ +/// @ref ext_scalar_common +/// @file glm/ext/scalar_common.hpp +/// +/// @defgroup ext_scalar_common GLM_EXT_scalar_common +/// @ingroup ext +/// +/// Exposes min and max functions for 3 to 4 scalar parameters. +/// +/// Include to use the features of this extension. +/// +/// @see core_func_common +/// @see ext_vector_common + +#pragma once + +// Dependency: +#include "../common.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_common extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_common + /// @{ + + /// Returns the minimum component-wise values of 3 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T min(T a, T b, T c); + + /// Returns the minimum component-wise values of 4 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T min(T a, T b, T c, T d); + + /// Returns the maximum component-wise values of 3 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T max(T a, T b, T c); + + /// Returns the maximum component-wise values of 4 inputs + /// + /// @tparam T A floating-point scalar type. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL T max(T a, T b, T c, T d); + + /// Returns the minimum component-wise values of 2 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmin documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmin(T a, T b); + + /// Returns the minimum component-wise values of 3 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmin documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmin(T a, T b, T c); + + /// Returns the minimum component-wise values of 4 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmin documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmin(T a, T b, T c, T d); + + /// Returns the maximum component-wise values of 2 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmax documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmax(T a, T b); + + /// Returns the maximum component-wise values of 3 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmax documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmax(T a, T b, T C); + + /// Returns the maximum component-wise values of 4 inputs. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam T A floating-point scalar type. + /// + /// @see std::fmax documentation + /// @see ext_scalar_common + template + GLM_FUNC_DECL T fmax(T a, T b, T C, T D); + + /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common + template + GLM_FUNC_DECL genType fclamp(genType x, genType minVal, genType maxVal); + + /// Simulate GL_CLAMP OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType clamp(genType const& Texcoord); + + /// Simulate GL_REPEAT OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType repeat(genType const& Texcoord); + + /// Simulate GL_MIRRORED_REPEAT OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType mirrorClamp(genType const& Texcoord); + + /// Simulate GL_MIRROR_REPEAT OpenGL wrap mode + /// + /// @tparam genType Floating-point scalar types. + /// + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL genType mirrorRepeat(genType const& Texcoord); + + /// @} +}//namespace glm + +#include "scalar_common.inl" diff --git a/vendor/glm/glm/ext/scalar_common.inl b/vendor/glm/glm/ext/scalar_common.inl new file mode 100644 index 0000000..7d9207a --- /dev/null +++ b/vendor/glm/glm/ext/scalar_common.inl @@ -0,0 +1,152 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER T min(T a, T b, T c) + { + return glm::min(glm::min(a, b), c); + } + + template + GLM_FUNC_QUALIFIER T min(T a, T b, T c, T d) + { + return glm::min(glm::min(a, b), glm::min(c, d)); + } + + template + GLM_FUNC_QUALIFIER T max(T a, T b, T c) + { + return glm::max(glm::max(a, b), c); + } + + template + GLM_FUNC_QUALIFIER T max(T a, T b, T c, T d) + { + return glm::max(glm::max(a, b), glm::max(c, d)); + } + +# if GLM_HAS_CXX11_STL + using std::fmin; +# else + template + GLM_FUNC_QUALIFIER T fmin(T a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point input"); + + if (isnan(a)) + return b; + return min(a, b); + } +# endif + + template + GLM_FUNC_QUALIFIER T fmin(T a, T b, T c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point input"); + + if (isnan(a)) + return fmin(b, c); + if (isnan(b)) + return fmin(a, c); + if (isnan(c)) + return min(a, b); + return min(a, b, c); + } + + template + GLM_FUNC_QUALIFIER T fmin(T a, T b, T c, T d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point input"); + + if (isnan(a)) + return fmin(b, c, d); + if (isnan(b)) + return min(a, fmin(c, d)); + if (isnan(c)) + return fmin(min(a, b), d); + if (isnan(d)) + return min(a, b, c); + return min(a, b, c, d); + } + + +# if GLM_HAS_CXX11_STL + using std::fmax; +# else + template + GLM_FUNC_QUALIFIER T fmax(T a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point input"); + + if (isnan(a)) + return b; + return max(a, b); + } +# endif + + template + GLM_FUNC_QUALIFIER T fmax(T a, T b, T c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point input"); + + if (isnan(a)) + return fmax(b, c); + if (isnan(b)) + return fmax(a, c); + if (isnan(c)) + return max(a, b); + return max(a, b, c); + } + + template + GLM_FUNC_QUALIFIER T fmax(T a, T b, T c, T d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point input"); + + if (isnan(a)) + return fmax(b, c, d); + if (isnan(b)) + return max(a, fmax(c, d)); + if (isnan(c)) + return fmax(max(a, b), d); + if (isnan(d)) + return max(a, b, c); + return max(a, b, c, d); + } + + // fclamp + template + GLM_FUNC_QUALIFIER genType fclamp(genType x, genType minVal, genType maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fclamp' only accept floating-point or integer inputs"); + return fmin(fmax(x, minVal), maxVal); + } + + template + GLM_FUNC_QUALIFIER genType clamp(genType const& Texcoord) + { + return glm::clamp(Texcoord, static_cast(0), static_cast(1)); + } + + template + GLM_FUNC_QUALIFIER genType repeat(genType const& Texcoord) + { + return glm::fract(Texcoord); + } + + template + GLM_FUNC_QUALIFIER genType mirrorClamp(genType const& Texcoord) + { + return glm::fract(glm::abs(Texcoord)); + } + + template + GLM_FUNC_QUALIFIER genType mirrorRepeat(genType const& Texcoord) + { + genType const Abs = glm::abs(Texcoord); + genType const Clamp = glm::mod(glm::floor(Abs), static_cast(2)); + genType const Floor = glm::floor(Abs); + genType const Rest = Abs - Floor; + genType const Mirror = Clamp + Rest; + return mix(Rest, static_cast(1) - Rest, Mirror >= static_cast(1)); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/scalar_constants.hpp b/vendor/glm/glm/ext/scalar_constants.hpp new file mode 100644 index 0000000..74e210d --- /dev/null +++ b/vendor/glm/glm/ext/scalar_constants.hpp @@ -0,0 +1,40 @@ +/// @ref ext_scalar_constants +/// @file glm/ext/scalar_constants.hpp +/// +/// @defgroup ext_scalar_constants GLM_EXT_scalar_constants +/// @ingroup ext +/// +/// Provides a list of constants and precomputed useful values. +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_constants extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_constants + /// @{ + + /// Return the epsilon constant for floating point types. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType epsilon(); + + /// Return the pi constant for floating point types. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType pi(); + + /// Return the value of cos(1 / 2) for floating point types. + template + GLM_FUNC_DECL GLM_CONSTEXPR genType cos_one_over_two(); + + /// @} +} //namespace glm + +#include "scalar_constants.inl" diff --git a/vendor/glm/glm/ext/scalar_constants.inl b/vendor/glm/glm/ext/scalar_constants.inl new file mode 100644 index 0000000..b475adf --- /dev/null +++ b/vendor/glm/glm/ext/scalar_constants.inl @@ -0,0 +1,24 @@ +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType epsilon() + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'epsilon' only accepts floating-point inputs"); + return std::numeric_limits::epsilon(); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType pi() + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'pi' only accepts floating-point inputs"); + return static_cast(3.14159265358979323846264338327950288); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType cos_one_over_two() + { + return genType(0.877582561890372716130286068203503191); + } +} //namespace glm diff --git a/vendor/glm/glm/ext/scalar_int_sized.hpp b/vendor/glm/glm/ext/scalar_int_sized.hpp new file mode 100644 index 0000000..8e9c511 --- /dev/null +++ b/vendor/glm/glm/ext/scalar_int_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_scalar_int_sized +/// @file glm/ext/scalar_int_sized.hpp +/// +/// @defgroup ext_scalar_int_sized GLM_EXT_scalar_int_sized +/// @ingroup ext +/// +/// Exposes sized signed integer scalar types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized + +#pragma once + +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_int_sized extension included") +#endif + +namespace glm{ +namespace detail +{ +# if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::int8_t int8; + typedef std::int16_t int16; + typedef std::int32_t int32; +# else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; +#endif// + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; +}//namespace detail + + + /// @addtogroup ext_scalar_int_sized + /// @{ + + /// 8 bit signed integer type. + typedef detail::int8 int8; + + /// 16 bit signed integer type. + typedef detail::int16 int16; + + /// 32 bit signed integer type. + typedef detail::int32 int32; + + /// 64 bit signed integer type. + typedef detail::int64 int64; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/scalar_integer.hpp b/vendor/glm/glm/ext/scalar_integer.hpp new file mode 100644 index 0000000..a2ca8a2 --- /dev/null +++ b/vendor/glm/glm/ext/scalar_integer.hpp @@ -0,0 +1,92 @@ +/// @ref ext_scalar_integer +/// @file glm/ext/scalar_integer.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_scalar_integer GLM_EXT_scalar_integer +/// @ingroup ext +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../detail/type_float.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_integer + /// @{ + + /// Return true if the value is a power of two number. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL bool isPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType nextPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType prevPowerOfTwo(genIUType v); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL bool isMultiple(genIUType v, genIUType Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam genIUType Integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType nextMultiple(genIUType v, genIUType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genIUType Integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL genIUType prevMultiple(genIUType v, genIUType Multiple); + + /// Returns the bit number of the Nth significant bit set to + /// 1 in the binary representation of value. + /// If value bitcount is less than the Nth significant bit, -1 will be returned. + /// + /// @tparam genIUType Signed or unsigned integer scalar types. + /// + /// @see ext_scalar_integer + template + GLM_FUNC_DECL int findNSB(genIUType x, int significantBitCount); + + /// @} +} //namespace glm + +#include "scalar_integer.inl" diff --git a/vendor/glm/glm/ext/scalar_integer.inl b/vendor/glm/glm/ext/scalar_integer.inl new file mode 100644 index 0000000..efba960 --- /dev/null +++ b/vendor/glm/glm/ext/scalar_integer.inl @@ -0,0 +1,243 @@ +#include "../integer.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T) + { + return v; + } + }; + + template + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vec call(vec const& v, T Shift) + { + return v | (v >> Shift); + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec const Sign(sign(x)); + + vec v(abs(x)); + + v = v - static_cast(1); + v = v | (v >> static_cast(1)); + v = v | (v >> static_cast(2)); + v = v | (v >> static_cast(4)); + v = compute_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return (v + static_cast(1)) * Sign; + } + }; + + template + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vec call(vec const& x) + { + GLM_STATIC_ASSERT(!std::numeric_limits::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vec v(x); + + v = v - static_cast(1); + v = v | (v >> static_cast(1)); + v = v | (v >> static_cast(2)); + v = v | (v >> static_cast(4)); + v = compute_ceilShift= 2>::call(v, 8); + v = compute_ceilShift= 4>::call(v, 16); + v = compute_ceilShift= 8>::call(v, 32); + return v + static_cast(1); + } + }; + + template + struct compute_ceilMultiple{}; + + template<> + struct compute_ceilMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source > genType(0)) + return Source + (Multiple - std::fmod(Source, Multiple)); + else + return Source + std::fmod(-Source, Multiple); + } + }; + + template<> + struct compute_ceilMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + }; + + template<> + struct compute_ceilMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + assert(Multiple > genType(0)); + if(Source > genType(0)) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + else + return Source + (-Source % Multiple); + } + }; + + template + struct compute_floorMultiple{}; + + template<> + struct compute_floorMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - std::fmod(Source, Multiple); + else + return Source - std::fmod(Source, Multiple) - Multiple; + } + }; + + template<> + struct compute_floorMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; + + template<> + struct compute_floorMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER bool isPowerOfTwo(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isPowerOfTwo' only accept integer inputs"); + + genIUType const Result = glm::abs(Value); + return !(Result & (Result - 1)); + } + + template + GLM_FUNC_QUALIFIER genIUType nextPowerOfTwo(genIUType value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextPowerOfTwo' only accept integer inputs"); + + return detail::compute_ceilPowerOfTwo<1, genIUType, defaultp, std::numeric_limits::is_signed>::call(vec<1, genIUType, defaultp>(value)).x; + } + + template + GLM_FUNC_QUALIFIER genIUType prevPowerOfTwo(genIUType value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevPowerOfTwo' only accept integer inputs"); + + return isPowerOfTwo(value) ? value : static_cast(static_cast(1) << static_cast(findMSB(value))); + } + + template + GLM_FUNC_QUALIFIER bool isMultiple(genIUType Value, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isMultiple' only accept integer inputs"); + + return isMultiple(vec<1, genIUType>(Value), vec<1, genIUType>(Multiple)).x; + } + + template + GLM_FUNC_QUALIFIER genIUType nextMultiple(genIUType Source, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::compute_ceilMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER genIUType prevMultiple(genIUType Source, genIUType Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::compute_floorMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER int findNSB(genIUType x, int significantBitCount) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findNSB' only accept integer inputs"); + + if(bitCount(x) < significantBitCount) + return -1; + + genIUType const One = static_cast(1); + int bitPos = 0; + + genIUType key = x; + int nBitCount = significantBitCount; + int Step = sizeof(x) * 8 / 2; + while (key > One) + { + genIUType Mask = static_cast((One << Step) - One); + genIUType currentKey = key & Mask; + int currentBitCount = bitCount(currentKey); + if (nBitCount > currentBitCount) + { + nBitCount -= currentBitCount; + bitPos += Step; + key >>= static_cast(Step); + } + else + { + key = key & Mask; + } + + Step >>= 1; + } + + return static_cast(bitPos); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/scalar_packing.hpp b/vendor/glm/glm/ext/scalar_packing.hpp new file mode 100644 index 0000000..18b85b7 --- /dev/null +++ b/vendor/glm/glm/ext/scalar_packing.hpp @@ -0,0 +1,32 @@ +/// @ref ext_scalar_packing +/// @file glm/ext/scalar_packing.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_scalar_packing GLM_EXT_scalar_packing +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// This extension provides a set of function to convert scalar values to packed +/// formats. + +#pragma once + +// Dependency: +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_packing extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_packing + /// @{ + + + /// @} +}// namespace glm + +#include "scalar_packing.inl" diff --git a/vendor/glm/glm/ext/scalar_packing.inl b/vendor/glm/glm/ext/scalar_packing.inl new file mode 100644 index 0000000..e69de29 diff --git a/vendor/glm/glm/ext/scalar_relational.hpp b/vendor/glm/glm/ext/scalar_relational.hpp new file mode 100644 index 0000000..3076a5e --- /dev/null +++ b/vendor/glm/glm/ext/scalar_relational.hpp @@ -0,0 +1,65 @@ +/// @ref ext_scalar_relational +/// @file glm/ext/scalar_relational.hpp +/// +/// @defgroup ext_scalar_relational GLM_EXT_scalar_relational +/// @ingroup ext +/// +/// Exposes comparison functions for scalar types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see core_vector_relational +/// @see ext_vector_relational +/// @see ext_matrix_relational + +#pragma once + +// Dependencies +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_relational extension included") +#endif + +namespace glm +{ + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool equal(genType const& x, genType const& y, genType const& epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, genType const& epsilon); + + /// Returns the component-wise comparison between two scalars in term of ULPs. + /// True if this expression is satisfied. + /// + /// @param x First operand. + /// @param y Second operand. + /// @param ULPs Maximum difference in ULPs between the two operators to consider them equal. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool equal(genType const& x, genType const& y, int ULPs); + + /// Returns the component-wise comparison between two scalars in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @param x First operand. + /// @param y Second operand. + /// @param ULPs Maximum difference in ULPs between the two operators to consider them not equal. + /// + /// @tparam genType Floating-point or integer scalar types + template + GLM_FUNC_DECL GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, int ULPs); + + /// @} +}//namespace glm + +#include "scalar_relational.inl" diff --git a/vendor/glm/glm/ext/scalar_relational.inl b/vendor/glm/glm/ext/scalar_relational.inl new file mode 100644 index 0000000..c85583e --- /dev/null +++ b/vendor/glm/glm/ext/scalar_relational.inl @@ -0,0 +1,40 @@ +#include "../common.hpp" +#include "../ext/scalar_int_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/type_float.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool equal(genType const& x, genType const& y, genType const& epsilon) + { + return abs(x - y) <= epsilon; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, genType const& epsilon) + { + return abs(x - y) > epsilon; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool equal(genType const& x, genType const& y, int MaxULPs) + { + detail::float_t const a(x); + detail::float_t const b(y); + + // Different signs means they do not match. + if(a.negative() != b.negative()) + return false; + + // Find the difference in ULPs. + typename detail::float_t::int_type const DiffULPs = abs(a.i - b.i); + return DiffULPs <= MaxULPs; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool notEqual(genType const& x, genType const& y, int ULPs) + { + return !equal(x, y, ULPs); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/scalar_uint_sized.hpp b/vendor/glm/glm/ext/scalar_uint_sized.hpp new file mode 100644 index 0000000..fd5267f --- /dev/null +++ b/vendor/glm/glm/ext/scalar_uint_sized.hpp @@ -0,0 +1,70 @@ +/// @ref ext_scalar_uint_sized +/// @file glm/ext/scalar_uint_sized.hpp +/// +/// @defgroup ext_scalar_uint_sized GLM_EXT_scalar_uint_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer scalar types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized + +#pragma once + +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_uint_sized extension included") +#endif + +namespace glm{ +namespace detail +{ +# if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::uint8_t uint8; + typedef std::uint16_t uint16; + typedef std::uint32_t uint32; +# else + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; +#endif + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; + + template<> + struct is_int + { + enum test {value = ~0}; + }; +}//namespace detail + + + /// @addtogroup ext_scalar_uint_sized + /// @{ + + /// 8 bit unsigned integer type. + typedef detail::uint8 uint8; + + /// 16 bit unsigned integer type. + typedef detail::uint16 uint16; + + /// 32 bit unsigned integer type. + typedef detail::uint32 uint32; + + /// 64 bit unsigned integer type. + typedef detail::uint64 uint64; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/scalar_ulp.hpp b/vendor/glm/glm/ext/scalar_ulp.hpp new file mode 100644 index 0000000..941ada3 --- /dev/null +++ b/vendor/glm/glm/ext/scalar_ulp.hpp @@ -0,0 +1,74 @@ +/// @ref ext_scalar_ulp +/// @file glm/ext/scalar_ulp.hpp +/// +/// @defgroup ext_scalar_ulp GLM_EXT_scalar_ulp +/// @ingroup ext +/// +/// Allow the measurement of the accuracy of a function against a reference +/// implementation. This extension works on floating-point data and provide results +/// in ULP. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_ulp +/// @see ext_scalar_relational + +#pragma once + +// Dependencies +#include "../ext/scalar_int_sized.hpp" +#include "../common.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_scalar_ulp extension included") +#endif + +namespace glm +{ + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType nextFloat(genType x); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType prevFloat(genType x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType nextFloat(genType x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL genType prevFloat(genType x, int ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @see ext_scalar_ulp + GLM_FUNC_DECL int floatDistance(float x, float y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @see ext_scalar_ulp + GLM_FUNC_DECL int64 floatDistance(double x, double y); + + /// @} +}//namespace glm + +#include "scalar_ulp.inl" diff --git a/vendor/glm/glm/ext/scalar_ulp.inl b/vendor/glm/glm/ext/scalar_ulp.inl new file mode 100644 index 0000000..308df15 --- /dev/null +++ b/vendor/glm/glm/ext/scalar_ulp.inl @@ -0,0 +1,284 @@ +/// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +/// +/// Developed at SunPro, a Sun Microsystems, Inc. business. +/// Permission to use, copy, modify, and distribute this +/// software is freely granted, provided that this notice +/// is preserved. + +#include "../detail/type_float.hpp" +#include "../ext/scalar_constants.hpp" +#include +#include + +#if(GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(push) +# pragma warning(disable : 4127) +#endif + +typedef union +{ + float value; + /* FIXME: Assumes 32 bit int. */ + unsigned int word; +} ieee_float_shape_type; + +typedef union +{ + double value; + struct + { + int lsw; + int msw; + } parts; +} ieee_double_shape_type; + +#define GLM_EXTRACT_WORDS(ix0,ix1,d) \ + do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ + } while (0) + +#define GLM_GET_FLOAT_WORD(i,d) \ + do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ + } while (0) + +#define GLM_SET_FLOAT_WORD(d,i) \ + do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ + } while (0) + +#define GLM_INSERT_WORDS(d,ix0,ix1) \ + do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ + } while (0) + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER float nextafterf(float x, float y) + { + volatile float t; + int hx, hy, ix, iy; + + GLM_GET_FLOAT_WORD(hx, x); + GLM_GET_FLOAT_WORD(hy, y); + ix = hx & 0x7fffffff; // |x| + iy = hy & 0x7fffffff; // |y| + + if((ix > 0x7f800000) || // x is nan + (iy > 0x7f800000)) // y is nan + return x + y; + if(abs(y - x) <= epsilon()) + return y; // x=y, return y + if(ix == 0) + { // x == 0 + GLM_SET_FLOAT_WORD(x, (hy & 0x80000000) | 1);// return +-minsubnormal + t = x * x; + if(abs(t - x) <= epsilon()) + return t; + else + return x; // raise underflow flag + } + if(hx >= 0) + { // x > 0 + if(hx > hy) // x > y, x -= ulp + hx -= 1; + else // x < y, x += ulp + hx += 1; + } + else + { // x < 0 + if(hy >= 0 || hx > hy) // x < y, x -= ulp + hx -= 1; + else // x > y, x += ulp + hx += 1; + } + hy = hx & 0x7f800000; + if(hy >= 0x7f800000) + return x + x; // overflow + if(hy < 0x00800000) // underflow + { + t = x * x; + if(abs(t - x) > epsilon()) + { // raise underflow flag + GLM_SET_FLOAT_WORD(y, hx); + return y; + } + } + GLM_SET_FLOAT_WORD(x, hx); + return x; + } + + GLM_FUNC_QUALIFIER double nextafter(double x, double y) + { + volatile double t; + int hx, hy, ix, iy; + unsigned int lx, ly; + + GLM_EXTRACT_WORDS(hx, lx, x); + GLM_EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; // |x| + iy = hy & 0x7fffffff; // |y| + + if(((ix >= 0x7ff00000) && ((ix - 0x7ff00000) | lx) != 0) || // x is nan + ((iy >= 0x7ff00000) && ((iy - 0x7ff00000) | ly) != 0)) // y is nan + return x + y; + if(abs(y - x) <= epsilon()) + return y; // x=y, return y + if((ix | lx) == 0) + { // x == 0 + GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal + t = x * x; + if(abs(t - x) <= epsilon()) + return t; + else + return x; // raise underflow flag + } + if(hx >= 0) { // x > 0 + if(hx > hy || ((hx == hy) && (lx > ly))) { // x > y, x -= ulp + if(lx == 0) hx -= 1; + lx -= 1; + } + else { // x < y, x += ulp + lx += 1; + if(lx == 0) hx += 1; + } + } + else { // x < 0 + if(hy >= 0 || hx > hy || ((hx == hy) && (lx > ly))){// x < y, x -= ulp + if(lx == 0) hx -= 1; + lx -= 1; + } + else { // x > y, x += ulp + lx += 1; + if(lx == 0) hx += 1; + } + } + hy = hx & 0x7ff00000; + if(hy >= 0x7ff00000) + return x + x; // overflow + if(hy < 0x00100000) + { // underflow + t = x * x; + if(abs(t - x) > epsilon()) + { // raise underflow flag + GLM_INSERT_WORDS(y, hx, lx); + return y; + } + } + GLM_INSERT_WORDS(x, hx, lx); + return x; + } +}//namespace detail +}//namespace glm + +#if(GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(pop) +#endif + +namespace glm +{ + template<> + GLM_FUNC_QUALIFIER float nextFloat(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MAX); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MAX); +# else + return nextafterf(x, FLT_MAX); +# endif + } + + template<> + GLM_FUNC_QUALIFIER double nextFloat(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafter(x, std::numeric_limits::max()); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MAX); +# else + return nextafter(x, DBL_MAX); +# endif + } + + template + GLM_FUNC_QUALIFIER T nextFloat(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'next_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for(int i = 0; i < ULPs; ++i) + temp = nextFloat(temp); + return temp; + } + + GLM_FUNC_QUALIFIER float prevFloat(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MIN); +# else + return nextafterf(x, FLT_MIN); +# endif + } + + GLM_FUNC_QUALIFIER double prevFloat(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return _nextafter(x, DBL_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MIN); +# else + return nextafter(x, DBL_MIN); +# endif + } + + template + GLM_FUNC_QUALIFIER T prevFloat(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'prev_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for(int i = 0; i < ULPs; ++i) + temp = prevFloat(temp); + return temp; + } + + GLM_FUNC_QUALIFIER int floatDistance(float x, float y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } + + GLM_FUNC_QUALIFIER int64 floatDistance(double x, double y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool1.hpp b/vendor/glm/glm/ext/vector_bool1.hpp new file mode 100644 index 0000000..002c320 --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool1.hpp @@ -0,0 +1,30 @@ +/// @ref ext_vector_bool1 +/// @file glm/ext/vector_bool1.hpp +/// +/// @defgroup ext_vector_bool1 GLM_EXT_vector_bool1 +/// @ingroup ext +/// +/// Exposes bvec1 vector type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_bool1_precision extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_bool1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_bool1 + /// @{ + + /// 1 components vector of boolean. + typedef vec<1, bool, defaultp> bvec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool1_precision.hpp b/vendor/glm/glm/ext/vector_bool1_precision.hpp new file mode 100644 index 0000000..e62d3cf --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool1_precision.hpp @@ -0,0 +1,34 @@ +/// @ref ext_vector_bool1_precision +/// @file glm/ext/vector_bool1_precision.hpp +/// +/// @defgroup ext_vector_bool1_precision GLM_EXT_vector_bool1_precision +/// @ingroup ext +/// +/// Exposes highp_bvec1, mediump_bvec1 and lowp_bvec1 types. +/// +/// Include to use the features of this extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_bool1_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_bool1_precision + /// @{ + + /// 1 component vector of bool values. + typedef vec<1, bool, highp> highp_bvec1; + + /// 1 component vector of bool values. + typedef vec<1, bool, mediump> mediump_bvec1; + + /// 1 component vector of bool values. + typedef vec<1, bool, lowp> lowp_bvec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool2.hpp b/vendor/glm/glm/ext/vector_bool2.hpp new file mode 100644 index 0000000..52288b7 --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_bool2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of boolean. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, bool, defaultp> bvec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool2_precision.hpp b/vendor/glm/glm/ext/vector_bool2_precision.hpp new file mode 100644 index 0000000..4370933 --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_bool2_precision.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 2 components vector of high qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, bool, highp> highp_bvec2; + + /// 2 components vector of medium qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, bool, mediump> mediump_bvec2; + + /// 2 components vector of low qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, bool, lowp> lowp_bvec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool3.hpp b/vendor/glm/glm/ext/vector_bool3.hpp new file mode 100644 index 0000000..90a0b7e --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_bool3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of boolean. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, bool, defaultp> bvec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool3_precision.hpp b/vendor/glm/glm/ext/vector_bool3_precision.hpp new file mode 100644 index 0000000..89cd2d3 --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_bool3_precision.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 3 components vector of high qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, bool, highp> highp_bvec3; + + /// 3 components vector of medium qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, bool, mediump> mediump_bvec3; + + /// 3 components vector of low qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, bool, lowp> lowp_bvec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool4.hpp b/vendor/glm/glm/ext/vector_bool4.hpp new file mode 100644 index 0000000..18aa71b --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_bool4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of boolean. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, bool, defaultp> bvec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_bool4_precision.hpp b/vendor/glm/glm/ext/vector_bool4_precision.hpp new file mode 100644 index 0000000..79786e5 --- /dev/null +++ b/vendor/glm/glm/ext/vector_bool4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_bool4_precision.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 4 components vector of high qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, bool, highp> highp_bvec4; + + /// 4 components vector of medium qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, bool, mediump> mediump_bvec4; + + /// 4 components vector of low qualifier bool numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, bool, lowp> lowp_bvec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_common.hpp b/vendor/glm/glm/ext/vector_common.hpp new file mode 100644 index 0000000..521ec01 --- /dev/null +++ b/vendor/glm/glm/ext/vector_common.hpp @@ -0,0 +1,204 @@ +/// @ref ext_vector_common +/// @file glm/ext/vector_common.hpp +/// +/// @defgroup ext_vector_common GLM_EXT_vector_common +/// @ingroup ext +/// +/// Exposes min and max functions for 3 to 4 vector parameters. +/// +/// Include to use the features of this extension. +/// +/// @see core_common +/// @see ext_scalar_common + +#pragma once + +// Dependency: +#include "../ext/scalar_common.hpp" +#include "../common.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_common extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_common + /// @{ + + /// Return the minimum component-wise values of 3 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& a, vec const& b, vec const& c); + + /// Return the minimum component-wise values of 4 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec min(vec const& a, vec const& b, vec const& c, vec const& d); + + /// Return the maximum component-wise values of 3 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max(vec const& x, vec const& y, vec const& z); + + /// Return the maximum component-wise values of 4 inputs + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec max( vec const& x, vec const& y, vec const& z, vec const& w); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& x, T y); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& x, vec const& y); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& a, vec const& b, vec const& c); + + /// Returns y if y < x; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmin documentation + template + GLM_FUNC_DECL vec fmin(vec const& a, vec const& b, vec const& c, vec const& d); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, T b); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b, vec const& c); + + /// Returns y if x < y; otherwise, it returns x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see std::fmax documentation + template + GLM_FUNC_DECL vec fmax(vec const& a, vec const& b, vec const& c, vec const& d); + + /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common + template + GLM_FUNC_DECL vec fclamp(vec const& x, T minVal, T maxVal); + + /// Returns min(max(x, minVal), maxVal) for each component in x. If one of the two arguments is NaN, the value of the other argument is returned. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common + template + GLM_FUNC_DECL vec fclamp(vec const& x, vec const& minVal, vec const& maxVal); + + /// Simulate GL_CLAMP OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec clamp(vec const& Texcoord); + + /// Simulate GL_REPEAT OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec repeat(vec const& Texcoord); + + /// Simulate GL_MIRRORED_REPEAT OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec mirrorClamp(vec const& Texcoord); + + /// Simulate GL_MIRROR_REPEAT OpenGL wrap mode + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_common extension. + template + GLM_FUNC_DECL vec mirrorRepeat(vec const& Texcoord); + + /// @} +}//namespace glm + +#include "vector_common.inl" diff --git a/vendor/glm/glm/ext/vector_common.inl b/vendor/glm/glm/ext/vector_common.inl new file mode 100644 index 0000000..e2747be --- /dev/null +++ b/vendor/glm/glm/ext/vector_common.inl @@ -0,0 +1,129 @@ +#include "../detail/_vectorize.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& x, vec const& y, vec const& z) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'min' only accept floating-point or integer inputs"); + return glm::min(glm::min(x, y), z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec min(vec const& x, vec const& y, vec const& z, vec const& w) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'min' only accept floating-point or integer inputs"); + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& x, vec const& y, vec const& z) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'max' only accept floating-point or integer inputs"); + return glm::max(glm::max(x, y), z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec max(vec const& x, vec const& y, vec const& z, vec const& w) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'max' only accept floating-point or integer inputs"); + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return detail::functor2::call(fmin, a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return detail::functor2::call(fmin, a, b); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b, vec const& c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), c); + } + + template + GLM_FUNC_QUALIFIER vec fmin(vec const& a, vec const& b, vec const& c, vec const& d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmin' only accept floating-point inputs"); + return fmin(fmin(a, b), fmin(c, d)); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, T b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return detail::functor2::call(fmax, a, vec(b)); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return detail::functor2::call(fmax, a, b); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b, vec const& c) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), c); + } + + template + GLM_FUNC_QUALIFIER vec fmax(vec const& a, vec const& b, vec const& c, vec const& d) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fmax' only accept floating-point inputs"); + return fmax(fmax(a, b), fmax(c, d)); + } + + template + GLM_FUNC_QUALIFIER vec fclamp(vec const& x, T minVal, T maxVal) + { + return fmin(fmax(x, vec(minVal)), vec(maxVal)); + } + + template + GLM_FUNC_QUALIFIER vec fclamp(vec const& x, vec const& minVal, vec const& maxVal) + { + return fmin(fmax(x, minVal), maxVal); + } + + template + GLM_FUNC_QUALIFIER vec clamp(vec const& Texcoord) + { + return glm::clamp(Texcoord, vec(0), vec(1)); + } + + template + GLM_FUNC_QUALIFIER vec repeat(vec const& Texcoord) + { + return glm::fract(Texcoord); + } + + template + GLM_FUNC_QUALIFIER vec mirrorClamp(vec const& Texcoord) + { + return glm::fract(glm::abs(Texcoord)); + } + + template + GLM_FUNC_QUALIFIER vec mirrorRepeat(vec const& Texcoord) + { + vec const Abs = glm::abs(Texcoord); + vec const Clamp = glm::mod(glm::floor(Abs), vec(2)); + vec const Floor = glm::floor(Abs); + vec const Rest = Abs - Floor; + vec const Mirror = Clamp + Rest; + return mix(Rest, vec(1) - Rest, glm::greaterThanEqual(Mirror, vec(1))); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double1.hpp b/vendor/glm/glm/ext/vector_double1.hpp new file mode 100644 index 0000000..3882667 --- /dev/null +++ b/vendor/glm/glm/ext/vector_double1.hpp @@ -0,0 +1,31 @@ +/// @ref ext_vector_double1 +/// @file glm/ext/vector_double1.hpp +/// +/// @defgroup ext_vector_double1 GLM_EXT_vector_double1 +/// @ingroup ext +/// +/// Exposes double-precision floating point vector type with one component. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_double1_precision extension. +/// @see ext_vector_float1 extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_double1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_double1 + /// @{ + + /// 1 components vector of double-precision floating-point numbers. + typedef vec<1, double, defaultp> dvec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double1_precision.hpp b/vendor/glm/glm/ext/vector_double1_precision.hpp new file mode 100644 index 0000000..1d47195 --- /dev/null +++ b/vendor/glm/glm/ext/vector_double1_precision.hpp @@ -0,0 +1,36 @@ +/// @ref ext_vector_double1_precision +/// @file glm/ext/vector_double1_precision.hpp +/// +/// @defgroup ext_vector_double1_precision GLM_EXT_vector_double1_precision +/// @ingroup ext +/// +/// Exposes highp_dvec1, mediump_dvec1 and lowp_dvec1 types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_double1 + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_double1_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_double1_precision + /// @{ + + /// 1 component vector of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, double, highp> highp_dvec1; + + /// 1 component vector of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, double, mediump> mediump_dvec1; + + /// 1 component vector of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, double, lowp> lowp_dvec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double2.hpp b/vendor/glm/glm/ext/vector_double2.hpp new file mode 100644 index 0000000..60e3577 --- /dev/null +++ b/vendor/glm/glm/ext/vector_double2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_double2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, double, defaultp> dvec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double2_precision.hpp b/vendor/glm/glm/ext/vector_double2_precision.hpp new file mode 100644 index 0000000..fa53940 --- /dev/null +++ b/vendor/glm/glm/ext/vector_double2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_double2_precision.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 2 components vector of high double-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, double, highp> highp_dvec2; + + /// 2 components vector of medium double-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, double, mediump> mediump_dvec2; + + /// 2 components vector of low double-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, double, lowp> lowp_dvec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double3.hpp b/vendor/glm/glm/ext/vector_double3.hpp new file mode 100644 index 0000000..6dfe4c6 --- /dev/null +++ b/vendor/glm/glm/ext/vector_double3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_double3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, double, defaultp> dvec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double3_precision.hpp b/vendor/glm/glm/ext/vector_double3_precision.hpp new file mode 100644 index 0000000..a8cfa37 --- /dev/null +++ b/vendor/glm/glm/ext/vector_double3_precision.hpp @@ -0,0 +1,34 @@ +/// @ref core +/// @file glm/ext/vector_double3_precision.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 3 components vector of high double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, double, highp> highp_dvec3; + + /// 3 components vector of medium double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, double, mediump> mediump_dvec3; + + /// 3 components vector of low double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, double, lowp> lowp_dvec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double4.hpp b/vendor/glm/glm/ext/vector_double4.hpp new file mode 100644 index 0000000..87f225f --- /dev/null +++ b/vendor/glm/glm/ext/vector_double4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_double4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of double-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, double, defaultp> dvec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_double4_precision.hpp b/vendor/glm/glm/ext/vector_double4_precision.hpp new file mode 100644 index 0000000..09cafa1 --- /dev/null +++ b/vendor/glm/glm/ext/vector_double4_precision.hpp @@ -0,0 +1,35 @@ +/// @ref core +/// @file glm/ext/vector_double4_precision.hpp + +#pragma once +#include "../detail/setup.hpp" +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 4 components vector of high double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, double, highp> highp_dvec4; + + /// 4 components vector of medium double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, double, mediump> mediump_dvec4; + + /// 4 components vector of low double-qualifier floating-point numbers. + /// There is no guarantee on the actual qualifier. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, double, lowp> lowp_dvec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float1.hpp b/vendor/glm/glm/ext/vector_float1.hpp new file mode 100644 index 0000000..28acc2c --- /dev/null +++ b/vendor/glm/glm/ext/vector_float1.hpp @@ -0,0 +1,31 @@ +/// @ref ext_vector_float1 +/// @file glm/ext/vector_float1.hpp +/// +/// @defgroup ext_vector_float1 GLM_EXT_vector_float1 +/// @ingroup ext +/// +/// Exposes single-precision floating point vector type with one component. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_float1_precision extension. +/// @see ext_vector_double1 extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_float1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_float1 + /// @{ + + /// 1 components vector of single-precision floating-point numbers. + typedef vec<1, float, defaultp> vec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float1_precision.hpp b/vendor/glm/glm/ext/vector_float1_precision.hpp new file mode 100644 index 0000000..6e8dad8 --- /dev/null +++ b/vendor/glm/glm/ext/vector_float1_precision.hpp @@ -0,0 +1,36 @@ +/// @ref ext_vector_float1_precision +/// @file glm/ext/vector_float1_precision.hpp +/// +/// @defgroup ext_vector_float1_precision GLM_EXT_vector_float1_precision +/// @ingroup ext +/// +/// Exposes highp_vec1, mediump_vec1 and lowp_vec1 types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_float1 extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_float1_precision extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_float1_precision + /// @{ + + /// 1 component vector of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, float, highp> highp_vec1; + + /// 1 component vector of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, float, mediump> mediump_vec1; + + /// 1 component vector of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, float, lowp> lowp_vec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float2.hpp b/vendor/glm/glm/ext/vector_float2.hpp new file mode 100644 index 0000000..d31545d --- /dev/null +++ b/vendor/glm/glm/ext/vector_float2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_float2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, float, defaultp> vec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float2_precision.hpp b/vendor/glm/glm/ext/vector_float2_precision.hpp new file mode 100644 index 0000000..23c0820 --- /dev/null +++ b/vendor/glm/glm/ext/vector_float2_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_float2_precision.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 2 components vector of high single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, float, highp> highp_vec2; + + /// 2 components vector of medium single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, float, mediump> mediump_vec2; + + /// 2 components vector of low single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<2, float, lowp> lowp_vec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float3.hpp b/vendor/glm/glm/ext/vector_float3.hpp new file mode 100644 index 0000000..cd79a62 --- /dev/null +++ b/vendor/glm/glm/ext/vector_float3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_float3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, float, defaultp> vec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float3_precision.hpp b/vendor/glm/glm/ext/vector_float3_precision.hpp new file mode 100644 index 0000000..be640b5 --- /dev/null +++ b/vendor/glm/glm/ext/vector_float3_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_float3_precision.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 3 components vector of high single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, float, highp> highp_vec3; + + /// 3 components vector of medium single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, float, mediump> mediump_vec3; + + /// 3 components vector of low single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<3, float, lowp> lowp_vec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float4.hpp b/vendor/glm/glm/ext/vector_float4.hpp new file mode 100644 index 0000000..d84adcc --- /dev/null +++ b/vendor/glm/glm/ext/vector_float4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_float4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of single-precision floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, float, defaultp> vec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_float4_precision.hpp b/vendor/glm/glm/ext/vector_float4_precision.hpp new file mode 100644 index 0000000..aede838 --- /dev/null +++ b/vendor/glm/glm/ext/vector_float4_precision.hpp @@ -0,0 +1,31 @@ +/// @ref core +/// @file glm/ext/vector_float4_precision.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector_precision + /// @{ + + /// 4 components vector of high single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, float, highp> highp_vec4; + + /// 4 components vector of medium single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, float, mediump> mediump_vec4; + + /// 4 components vector of low single-qualifier floating-point numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + /// @see GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier + typedef vec<4, float, lowp> lowp_vec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_int1.hpp b/vendor/glm/glm/ext/vector_int1.hpp new file mode 100644 index 0000000..dc86038 --- /dev/null +++ b/vendor/glm/glm/ext/vector_int1.hpp @@ -0,0 +1,32 @@ +/// @ref ext_vector_int1 +/// @file glm/ext/vector_int1.hpp +/// +/// @defgroup ext_vector_int1 GLM_EXT_vector_int1 +/// @ingroup ext +/// +/// Exposes ivec1 vector type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_uint1 extension. +/// @see ext_vector_int1_precision extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int1 + /// @{ + + /// 1 component vector of signed integer numbers. + typedef vec<1, int, defaultp> ivec1; + + /// @} +}//namespace glm + diff --git a/vendor/glm/glm/ext/vector_int1_sized.hpp b/vendor/glm/glm/ext/vector_int1_sized.hpp new file mode 100644 index 0000000..de0d4cf --- /dev/null +++ b/vendor/glm/glm/ext/vector_int1_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int1_sized +/// @file glm/ext/vector_int1_sized.hpp +/// +/// @defgroup ext_vector_int1_sized GLM_EXT_vector_int1_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint1_sized + +#pragma once + +#include "../ext/vector_int1.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int1_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int1_sized + /// @{ + + /// 8 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int8, defaultp> i8vec1; + + /// 16 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int16, defaultp> i16vec1; + + /// 32 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int32, defaultp> i32vec1; + + /// 64 bit signed integer vector of 1 component type. + /// + /// @see ext_vector_int1_sized + typedef vec<1, int64, defaultp> i64vec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_int2.hpp b/vendor/glm/glm/ext/vector_int2.hpp new file mode 100644 index 0000000..aef803e --- /dev/null +++ b/vendor/glm/glm/ext/vector_int2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_int2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of signed integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, int, defaultp> ivec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_int2_sized.hpp b/vendor/glm/glm/ext/vector_int2_sized.hpp new file mode 100644 index 0000000..1fd57ee --- /dev/null +++ b/vendor/glm/glm/ext/vector_int2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int2_sized +/// @file glm/ext/vector_int2_sized.hpp +/// +/// @defgroup ext_vector_int2_sized GLM_EXT_vector_int2_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector of 2 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint2_sized + +#pragma once + +#include "../ext/vector_int2.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int2_sized + /// @{ + + /// 8 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int8, defaultp> i8vec2; + + /// 16 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int16, defaultp> i16vec2; + + /// 32 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int32, defaultp> i32vec2; + + /// 64 bit signed integer vector of 2 components type. + /// + /// @see ext_vector_int2_sized + typedef vec<2, int64, defaultp> i64vec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_int3.hpp b/vendor/glm/glm/ext/vector_int3.hpp new file mode 100644 index 0000000..4767e61 --- /dev/null +++ b/vendor/glm/glm/ext/vector_int3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_int3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of signed integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, int, defaultp> ivec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_int3_sized.hpp b/vendor/glm/glm/ext/vector_int3_sized.hpp new file mode 100644 index 0000000..085a3fe --- /dev/null +++ b/vendor/glm/glm/ext/vector_int3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int3_sized +/// @file glm/ext/vector_int3_sized.hpp +/// +/// @defgroup ext_vector_int3_sized GLM_EXT_vector_int3_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector of 3 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint3_sized + +#pragma once + +#include "../ext/vector_int3.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int3_sized + /// @{ + + /// 8 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int8, defaultp> i8vec3; + + /// 16 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int16, defaultp> i16vec3; + + /// 32 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int32, defaultp> i32vec3; + + /// 64 bit signed integer vector of 3 components type. + /// + /// @see ext_vector_int3_sized + typedef vec<3, int64, defaultp> i64vec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_int4.hpp b/vendor/glm/glm/ext/vector_int4.hpp new file mode 100644 index 0000000..bb23adf --- /dev/null +++ b/vendor/glm/glm/ext/vector_int4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_int4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of signed integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, int, defaultp> ivec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_int4_sized.hpp b/vendor/glm/glm/ext/vector_int4_sized.hpp new file mode 100644 index 0000000..c63d465 --- /dev/null +++ b/vendor/glm/glm/ext/vector_int4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_int4_sized +/// @file glm/ext/vector_int4_sized.hpp +/// +/// @defgroup ext_vector_int4_sized GLM_EXT_vector_int4_sized +/// @ingroup ext +/// +/// Exposes sized signed integer vector of 4 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_int_sized +/// @see ext_vector_uint4_sized + +#pragma once + +#include "../ext/vector_int4.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_int4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_int4_sized + /// @{ + + /// 8 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int8, defaultp> i8vec4; + + /// 16 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int16, defaultp> i16vec4; + + /// 32 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int32, defaultp> i32vec4; + + /// 64 bit signed integer vector of 4 components type. + /// + /// @see ext_vector_int4_sized + typedef vec<4, int64, defaultp> i64vec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_integer.hpp b/vendor/glm/glm/ext/vector_integer.hpp new file mode 100644 index 0000000..1304dd8 --- /dev/null +++ b/vendor/glm/glm/ext/vector_integer.hpp @@ -0,0 +1,149 @@ +/// @ref ext_vector_integer +/// @file glm/ext/vector_integer.hpp +/// +/// @see core (dependence) +/// @see ext_vector_integer (dependence) +/// +/// @defgroup ext_vector_integer GLM_EXT_vector_integer +/// @ingroup ext +/// +/// Include to use the features of this extension. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_integer + /// @{ + + /// Return true if the value is a power of two number. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec isPowerOfTwo(vec const& v); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec nextPowerOfTwo(vec const& v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec prevPowerOfTwo(vec const& v); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec isMultiple(vec const& v, T Multiple); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec isMultiple(vec const& v, vec const& Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec nextMultiple(vec const& v, T Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec nextMultiple(vec const& v, vec const& Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec prevMultiple(vec const& v, T Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed or unsigned integer scalar types. + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec prevMultiple(vec const& v, vec const& Multiple); + + /// Returns the bit number of the Nth significant bit set to + /// 1 in the binary representation of value. + /// If value bitcount is less than the Nth significant bit, -1 will be returned. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see ext_vector_integer + template + GLM_FUNC_DECL vec findNSB(vec const& Source, vec SignificantBitCount); + + /// @} +} //namespace glm + +#include "vector_integer.inl" diff --git a/vendor/glm/glm/ext/vector_integer.inl b/vendor/glm/glm/ext/vector_integer.inl new file mode 100644 index 0000000..939ff5e --- /dev/null +++ b/vendor/glm/glm/ext/vector_integer.inl @@ -0,0 +1,85 @@ +#include "scalar_integer.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec isPowerOfTwo(vec const& Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isPowerOfTwo' only accept integer inputs"); + + vec const Result(abs(Value)); + return equal(Result & (Result - vec(1)), vec(0)); + } + + template + GLM_FUNC_QUALIFIER vec nextPowerOfTwo(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextPowerOfTwo' only accept integer inputs"); + + return detail::compute_ceilPowerOfTwo::is_signed>::call(v); + } + + template + GLM_FUNC_QUALIFIER vec prevPowerOfTwo(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevPowerOfTwo' only accept integer inputs"); + + return detail::functor1::call(prevPowerOfTwo, v); + } + + template + GLM_FUNC_QUALIFIER vec isMultiple(vec const& Value, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isMultiple' only accept integer inputs"); + + return (Value % Multiple) == vec(0); + } + + template + GLM_FUNC_QUALIFIER vec isMultiple(vec const& Value, vec const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'isMultiple' only accept integer inputs"); + + return (Value % Multiple) == vec(0); + } + + template + GLM_FUNC_QUALIFIER vec nextMultiple(vec const& Source, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::functor2::call(nextMultiple, Source, vec(Multiple)); + } + + template + GLM_FUNC_QUALIFIER vec nextMultiple(vec const& Source, vec const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'nextMultiple' only accept integer inputs"); + + return detail::functor2::call(nextMultiple, Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec prevMultiple(vec const& Source, T Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::functor2::call(prevMultiple, Source, vec(Multiple)); + } + + template + GLM_FUNC_QUALIFIER vec prevMultiple(vec const& Source, vec const& Multiple) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'prevMultiple' only accept integer inputs"); + + return detail::functor2::call(prevMultiple, Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec findNSB(vec const& Source, vec SignificantBitCount) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findNSB' only accept integer inputs"); + + return detail::functor2_vec_int::call(findNSB, Source, SignificantBitCount); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_packing.hpp b/vendor/glm/glm/ext/vector_packing.hpp new file mode 100644 index 0000000..76e5d0c --- /dev/null +++ b/vendor/glm/glm/ext/vector_packing.hpp @@ -0,0 +1,32 @@ +/// @ref ext_vector_packing +/// @file glm/ext/vector_packing.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_vector_packing GLM_EXT_vector_packing +/// @ingroup ext +/// +/// Include to use the features of this extension. +/// +/// This extension provides a set of function to convert vectors to packed +/// formats. + +#pragma once + +// Dependency: +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_packing extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_packing + /// @{ + + + /// @} +}// namespace glm + +#include "vector_packing.inl" diff --git a/vendor/glm/glm/ext/vector_packing.inl b/vendor/glm/glm/ext/vector_packing.inl new file mode 100644 index 0000000..e69de29 diff --git a/vendor/glm/glm/ext/vector_relational.hpp b/vendor/glm/glm/ext/vector_relational.hpp new file mode 100644 index 0000000..1c2367d --- /dev/null +++ b/vendor/glm/glm/ext/vector_relational.hpp @@ -0,0 +1,107 @@ +/// @ref ext_vector_relational +/// @file glm/ext/vector_relational.hpp +/// +/// @see core (dependence) +/// @see ext_scalar_integer (dependence) +/// +/// @defgroup ext_vector_relational GLM_EXT_vector_relational +/// @ingroup ext +/// +/// Exposes comparison functions for vector types that take a user defined epsilon values. +/// +/// Include to use the features of this extension. +/// +/// @see core_vector_relational +/// @see ext_scalar_relational +/// @see ext_matrix_relational + +#pragma once + +// Dependencies +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_relational + /// @{ + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, T epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& epsilon); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, int ULPs); + + /// Returns the component-wise comparison between two vectors in term of ULPs. + /// True if this expression is not satisfied. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& ULPs); + + /// @} +}//namespace glm + +#include "vector_relational.inl" diff --git a/vendor/glm/glm/ext/vector_relational.inl b/vendor/glm/glm/ext/vector_relational.inl new file mode 100644 index 0000000..7a39ab5 --- /dev/null +++ b/vendor/glm/glm/ext/vector_relational.inl @@ -0,0 +1,75 @@ +#include "../vector_relational.hpp" +#include "../common.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/type_float.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, T Epsilon) + { + return equal(x, y, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& Epsilon) + { + return lessThanEqual(abs(x - y), Epsilon); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, T Epsilon) + { + return notEqual(x, y, vec(Epsilon)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& Epsilon) + { + return greaterThan(abs(x - y), Epsilon); + } + + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, int MaxULPs) + { + return equal(x, y, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec equal(vec const& x, vec const& y, vec const& MaxULPs) + { + vec Result(false); + for(length_t i = 0; i < L; ++i) + { + detail::float_t const a(x[i]); + detail::float_t const b(y[i]); + + // Different signs means they do not match. + if(a.negative() != b.negative()) + { + // Check for equality to make sure +0==-0 + Result[i] = a.mantissa() == b.mantissa() && a.exponent() == b.exponent(); + } + else + { + // Find the difference in ULPs. + typename detail::float_t::int_type const DiffULPs = abs(a.i - b.i); + Result[i] = DiffULPs <= MaxULPs[i]; + } + } + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, int MaxULPs) + { + return notEqual(x, y, vec(MaxULPs)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y, vec const& MaxULPs) + { + return not_(equal(x, y, MaxULPs)); + } +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_uint1.hpp b/vendor/glm/glm/ext/vector_uint1.hpp new file mode 100644 index 0000000..eb8a704 --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint1.hpp @@ -0,0 +1,32 @@ +/// @ref ext_vector_uint1 +/// @file glm/ext/vector_uint1.hpp +/// +/// @defgroup ext_vector_uint1 GLM_EXT_vector_uint1 +/// @ingroup ext +/// +/// Exposes uvec1 vector type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_vector_int1 extension. +/// @see ext_vector_uint1_precision extension. + +#pragma once + +#include "../detail/type_vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint1 extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint1 + /// @{ + + /// 1 component vector of unsigned integer numbers. + typedef vec<1, unsigned int, defaultp> uvec1; + + /// @} +}//namespace glm + diff --git a/vendor/glm/glm/ext/vector_uint1_sized.hpp b/vendor/glm/glm/ext/vector_uint1_sized.hpp new file mode 100644 index 0000000..2a938bb --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint1_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint1_sized +/// @file glm/ext/vector_uint1_sized.hpp +/// +/// @defgroup ext_vector_uint1_sized GLM_EXT_vector_uint1_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector types. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int1_sized + +#pragma once + +#include "../ext/vector_uint1.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint1_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint1_sized + /// @{ + + /// 8 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint8, defaultp> u8vec1; + + /// 16 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint16, defaultp> u16vec1; + + /// 32 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint32, defaultp> u32vec1; + + /// 64 bit unsigned integer vector of 1 component type. + /// + /// @see ext_vector_uint1_sized + typedef vec<1, uint64, defaultp> u64vec1; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_uint2.hpp b/vendor/glm/glm/ext/vector_uint2.hpp new file mode 100644 index 0000000..03c00f5 --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint2.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_uint2.hpp + +#pragma once +#include "../detail/type_vec2.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 2 components vector of unsigned integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<2, unsigned int, defaultp> uvec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_uint2_sized.hpp b/vendor/glm/glm/ext/vector_uint2_sized.hpp new file mode 100644 index 0000000..620fdc6 --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint2_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint2_sized +/// @file glm/ext/vector_uint2_sized.hpp +/// +/// @defgroup ext_vector_uint2_sized GLM_EXT_vector_uint2_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector of 2 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int2_sized + +#pragma once + +#include "../ext/vector_uint2.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint2_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint2_sized + /// @{ + + /// 8 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint8, defaultp> u8vec2; + + /// 16 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint16, defaultp> u16vec2; + + /// 32 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint32, defaultp> u32vec2; + + /// 64 bit unsigned integer vector of 2 components type. + /// + /// @see ext_vector_uint2_sized + typedef vec<2, uint64, defaultp> u64vec2; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_uint3.hpp b/vendor/glm/glm/ext/vector_uint3.hpp new file mode 100644 index 0000000..f5b41c4 --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint3.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_uint3.hpp + +#pragma once +#include "../detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 3 components vector of unsigned integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<3, unsigned int, defaultp> uvec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_uint3_sized.hpp b/vendor/glm/glm/ext/vector_uint3_sized.hpp new file mode 100644 index 0000000..6f96b98 --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint3_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint3_sized +/// @file glm/ext/vector_uint3_sized.hpp +/// +/// @defgroup ext_vector_uint3_sized GLM_EXT_vector_uint3_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector of 3 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int3_sized + +#pragma once + +#include "../ext/vector_uint3.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint3_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint3_sized + /// @{ + + /// 8 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint8, defaultp> u8vec3; + + /// 16 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint16, defaultp> u16vec3; + + /// 32 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint32, defaultp> u32vec3; + + /// 64 bit unsigned integer vector of 3 components type. + /// + /// @see ext_vector_uint3_sized + typedef vec<3, uint64, defaultp> u64vec3; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_uint4.hpp b/vendor/glm/glm/ext/vector_uint4.hpp new file mode 100644 index 0000000..32ced58 --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint4.hpp @@ -0,0 +1,18 @@ +/// @ref core +/// @file glm/ext/vector_uint4.hpp + +#pragma once +#include "../detail/type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_vector + /// @{ + + /// 4 components vector of unsigned integer numbers. + /// + /// @see GLSL 4.20.8 specification, section 4.1.5 Vectors + typedef vec<4, unsigned int, defaultp> uvec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_uint4_sized.hpp b/vendor/glm/glm/ext/vector_uint4_sized.hpp new file mode 100644 index 0000000..da992ea --- /dev/null +++ b/vendor/glm/glm/ext/vector_uint4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_vector_uint4_sized +/// @file glm/ext/vector_uint4_sized.hpp +/// +/// @defgroup ext_vector_uint4_sized GLM_EXT_vector_uint4_sized +/// @ingroup ext +/// +/// Exposes sized unsigned integer vector of 4 components type. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_uint_sized +/// @see ext_vector_int4_sized + +#pragma once + +#include "../ext/vector_uint4.hpp" +#include "../ext/scalar_uint_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_uint4_sized extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_uint4_sized + /// @{ + + /// 8 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint8, defaultp> u8vec4; + + /// 16 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint16, defaultp> u16vec4; + + /// 32 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint32, defaultp> u32vec4; + + /// 64 bit unsigned integer vector of 4 components type. + /// + /// @see ext_vector_uint4_sized + typedef vec<4, uint64, defaultp> u64vec4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/ext/vector_ulp.hpp b/vendor/glm/glm/ext/vector_ulp.hpp new file mode 100644 index 0000000..6210396 --- /dev/null +++ b/vendor/glm/glm/ext/vector_ulp.hpp @@ -0,0 +1,109 @@ +/// @ref ext_vector_ulp +/// @file glm/ext/vector_ulp.hpp +/// +/// @defgroup ext_vector_ulp GLM_EXT_vector_ulp +/// @ingroup ext +/// +/// Allow the measurement of the accuracy of a function against a reference +/// implementation. This extension works on floating-point data and provide results +/// in ULP. +/// +/// Include to use the features of this extension. +/// +/// @see ext_scalar_ulp +/// @see ext_scalar_relational +/// @see ext_vector_relational + +#pragma once + +// Dependencies +#include "../ext/scalar_ulp.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_EXT_vector_ulp extension included") +#endif + +namespace glm +{ + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec nextFloat(vec const& x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec nextFloat(vec const& x, int ULPs); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec nextFloat(vec const& x, vec const& ULPs); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec prevFloat(vec const& x); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec prevFloat(vec const& x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec prevFloat(vec const& x, vec const& ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec floatDistance(vec const& x, vec const& y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see ext_scalar_ulp + template + GLM_FUNC_DECL vec floatDistance(vec const& x, vec const& y); + + /// @} +}//namespace glm + +#include "vector_ulp.inl" diff --git a/vendor/glm/glm/ext/vector_ulp.inl b/vendor/glm/glm/ext/vector_ulp.inl new file mode 100644 index 0000000..91565ce --- /dev/null +++ b/vendor/glm/glm/ext/vector_ulp.inl @@ -0,0 +1,74 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec nextFloat(vec const& x) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec nextFloat(vec const& x, int ULPs) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec nextFloat(vec const& x, vec const& ULPs) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = nextFloat(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prevFloat(vec const& x) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prevFloat(vec const& x, int ULPs) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prevFloat(vec const& x, vec const& ULPs) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prevFloat(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec floatDistance(vec const& x, vec const& y) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = floatDistance(x[i], y[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec floatDistance(vec const& x, vec const& y) + { + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = floatDistance(x[i], y[i]); + return Result; + } +}//namespace glm diff --git a/vendor/glm/glm/fwd.hpp b/vendor/glm/glm/fwd.hpp new file mode 100644 index 0000000..89177f4 --- /dev/null +++ b/vendor/glm/glm/fwd.hpp @@ -0,0 +1,1233 @@ +#pragma once + +#include "detail/qualifier.hpp" + +namespace glm +{ +#if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::int8_t int8; + typedef std::int16_t int16; + typedef std::int32_t int32; + typedef std::int64_t int64; + + typedef std::uint8_t uint8; + typedef std::uint16_t uint16; + typedef std::uint32_t uint32; + typedef std::uint64_t uint64; +#else + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + typedef detail::int64 int64; + + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; + typedef detail::uint64 uint64; +#endif + + // Scalar int + + typedef int8 lowp_i8; + typedef int8 mediump_i8; + typedef int8 highp_i8; + typedef int8 i8; + + typedef int8 lowp_int8; + typedef int8 mediump_int8; + typedef int8 highp_int8; + + typedef int8 lowp_int8_t; + typedef int8 mediump_int8_t; + typedef int8 highp_int8_t; + typedef int8 int8_t; + + typedef int16 lowp_i16; + typedef int16 mediump_i16; + typedef int16 highp_i16; + typedef int16 i16; + + typedef int16 lowp_int16; + typedef int16 mediump_int16; + typedef int16 highp_int16; + + typedef int16 lowp_int16_t; + typedef int16 mediump_int16_t; + typedef int16 highp_int16_t; + typedef int16 int16_t; + + typedef int32 lowp_i32; + typedef int32 mediump_i32; + typedef int32 highp_i32; + typedef int32 i32; + + typedef int32 lowp_int32; + typedef int32 mediump_int32; + typedef int32 highp_int32; + + typedef int32 lowp_int32_t; + typedef int32 mediump_int32_t; + typedef int32 highp_int32_t; + typedef int32 int32_t; + + typedef int64 lowp_i64; + typedef int64 mediump_i64; + typedef int64 highp_i64; + typedef int64 i64; + + typedef int64 lowp_int64; + typedef int64 mediump_int64; + typedef int64 highp_int64; + + typedef int64 lowp_int64_t; + typedef int64 mediump_int64_t; + typedef int64 highp_int64_t; + typedef int64 int64_t; + + // Scalar uint + + typedef unsigned int uint; + + typedef uint8 lowp_u8; + typedef uint8 mediump_u8; + typedef uint8 highp_u8; + typedef uint8 u8; + + typedef uint8 lowp_uint8; + typedef uint8 mediump_uint8; + typedef uint8 highp_uint8; + + typedef uint8 lowp_uint8_t; + typedef uint8 mediump_uint8_t; + typedef uint8 highp_uint8_t; + typedef uint8 uint8_t; + + typedef uint16 lowp_u16; + typedef uint16 mediump_u16; + typedef uint16 highp_u16; + typedef uint16 u16; + + typedef uint16 lowp_uint16; + typedef uint16 mediump_uint16; + typedef uint16 highp_uint16; + + typedef uint16 lowp_uint16_t; + typedef uint16 mediump_uint16_t; + typedef uint16 highp_uint16_t; + typedef uint16 uint16_t; + + typedef uint32 lowp_u32; + typedef uint32 mediump_u32; + typedef uint32 highp_u32; + typedef uint32 u32; + + typedef uint32 lowp_uint32; + typedef uint32 mediump_uint32; + typedef uint32 highp_uint32; + + typedef uint32 lowp_uint32_t; + typedef uint32 mediump_uint32_t; + typedef uint32 highp_uint32_t; + typedef uint32 uint32_t; + + typedef uint64 lowp_u64; + typedef uint64 mediump_u64; + typedef uint64 highp_u64; + typedef uint64 u64; + + typedef uint64 lowp_uint64; + typedef uint64 mediump_uint64; + typedef uint64 highp_uint64; + + typedef uint64 lowp_uint64_t; + typedef uint64 mediump_uint64_t; + typedef uint64 highp_uint64_t; + typedef uint64 uint64_t; + + // Scalar float + + typedef float lowp_f32; + typedef float mediump_f32; + typedef float highp_f32; + typedef float f32; + + typedef float lowp_float32; + typedef float mediump_float32; + typedef float highp_float32; + typedef float float32; + + typedef float lowp_float32_t; + typedef float mediump_float32_t; + typedef float highp_float32_t; + typedef float float32_t; + + + typedef double lowp_f64; + typedef double mediump_f64; + typedef double highp_f64; + typedef double f64; + + typedef double lowp_float64; + typedef double mediump_float64; + typedef double highp_float64; + typedef double float64; + + typedef double lowp_float64_t; + typedef double mediump_float64_t; + typedef double highp_float64_t; + typedef double float64_t; + + // Vector bool + + typedef vec<1, bool, lowp> lowp_bvec1; + typedef vec<2, bool, lowp> lowp_bvec2; + typedef vec<3, bool, lowp> lowp_bvec3; + typedef vec<4, bool, lowp> lowp_bvec4; + + typedef vec<1, bool, mediump> mediump_bvec1; + typedef vec<2, bool, mediump> mediump_bvec2; + typedef vec<3, bool, mediump> mediump_bvec3; + typedef vec<4, bool, mediump> mediump_bvec4; + + typedef vec<1, bool, highp> highp_bvec1; + typedef vec<2, bool, highp> highp_bvec2; + typedef vec<3, bool, highp> highp_bvec3; + typedef vec<4, bool, highp> highp_bvec4; + + typedef vec<1, bool, defaultp> bvec1; + typedef vec<2, bool, defaultp> bvec2; + typedef vec<3, bool, defaultp> bvec3; + typedef vec<4, bool, defaultp> bvec4; + + // Vector int + + typedef vec<1, int, lowp> lowp_ivec1; + typedef vec<2, int, lowp> lowp_ivec2; + typedef vec<3, int, lowp> lowp_ivec3; + typedef vec<4, int, lowp> lowp_ivec4; + + typedef vec<1, int, mediump> mediump_ivec1; + typedef vec<2, int, mediump> mediump_ivec2; + typedef vec<3, int, mediump> mediump_ivec3; + typedef vec<4, int, mediump> mediump_ivec4; + + typedef vec<1, int, highp> highp_ivec1; + typedef vec<2, int, highp> highp_ivec2; + typedef vec<3, int, highp> highp_ivec3; + typedef vec<4, int, highp> highp_ivec4; + + typedef vec<1, int, defaultp> ivec1; + typedef vec<2, int, defaultp> ivec2; + typedef vec<3, int, defaultp> ivec3; + typedef vec<4, int, defaultp> ivec4; + + typedef vec<1, i8, lowp> lowp_i8vec1; + typedef vec<2, i8, lowp> lowp_i8vec2; + typedef vec<3, i8, lowp> lowp_i8vec3; + typedef vec<4, i8, lowp> lowp_i8vec4; + + typedef vec<1, i8, mediump> mediump_i8vec1; + typedef vec<2, i8, mediump> mediump_i8vec2; + typedef vec<3, i8, mediump> mediump_i8vec3; + typedef vec<4, i8, mediump> mediump_i8vec4; + + typedef vec<1, i8, highp> highp_i8vec1; + typedef vec<2, i8, highp> highp_i8vec2; + typedef vec<3, i8, highp> highp_i8vec3; + typedef vec<4, i8, highp> highp_i8vec4; + + typedef vec<1, i8, defaultp> i8vec1; + typedef vec<2, i8, defaultp> i8vec2; + typedef vec<3, i8, defaultp> i8vec3; + typedef vec<4, i8, defaultp> i8vec4; + + typedef vec<1, i16, lowp> lowp_i16vec1; + typedef vec<2, i16, lowp> lowp_i16vec2; + typedef vec<3, i16, lowp> lowp_i16vec3; + typedef vec<4, i16, lowp> lowp_i16vec4; + + typedef vec<1, i16, mediump> mediump_i16vec1; + typedef vec<2, i16, mediump> mediump_i16vec2; + typedef vec<3, i16, mediump> mediump_i16vec3; + typedef vec<4, i16, mediump> mediump_i16vec4; + + typedef vec<1, i16, highp> highp_i16vec1; + typedef vec<2, i16, highp> highp_i16vec2; + typedef vec<3, i16, highp> highp_i16vec3; + typedef vec<4, i16, highp> highp_i16vec4; + + typedef vec<1, i16, defaultp> i16vec1; + typedef vec<2, i16, defaultp> i16vec2; + typedef vec<3, i16, defaultp> i16vec3; + typedef vec<4, i16, defaultp> i16vec4; + + typedef vec<1, i32, lowp> lowp_i32vec1; + typedef vec<2, i32, lowp> lowp_i32vec2; + typedef vec<3, i32, lowp> lowp_i32vec3; + typedef vec<4, i32, lowp> lowp_i32vec4; + + typedef vec<1, i32, mediump> mediump_i32vec1; + typedef vec<2, i32, mediump> mediump_i32vec2; + typedef vec<3, i32, mediump> mediump_i32vec3; + typedef vec<4, i32, mediump> mediump_i32vec4; + + typedef vec<1, i32, highp> highp_i32vec1; + typedef vec<2, i32, highp> highp_i32vec2; + typedef vec<3, i32, highp> highp_i32vec3; + typedef vec<4, i32, highp> highp_i32vec4; + + typedef vec<1, i32, defaultp> i32vec1; + typedef vec<2, i32, defaultp> i32vec2; + typedef vec<3, i32, defaultp> i32vec3; + typedef vec<4, i32, defaultp> i32vec4; + + typedef vec<1, i64, lowp> lowp_i64vec1; + typedef vec<2, i64, lowp> lowp_i64vec2; + typedef vec<3, i64, lowp> lowp_i64vec3; + typedef vec<4, i64, lowp> lowp_i64vec4; + + typedef vec<1, i64, mediump> mediump_i64vec1; + typedef vec<2, i64, mediump> mediump_i64vec2; + typedef vec<3, i64, mediump> mediump_i64vec3; + typedef vec<4, i64, mediump> mediump_i64vec4; + + typedef vec<1, i64, highp> highp_i64vec1; + typedef vec<2, i64, highp> highp_i64vec2; + typedef vec<3, i64, highp> highp_i64vec3; + typedef vec<4, i64, highp> highp_i64vec4; + + typedef vec<1, i64, defaultp> i64vec1; + typedef vec<2, i64, defaultp> i64vec2; + typedef vec<3, i64, defaultp> i64vec3; + typedef vec<4, i64, defaultp> i64vec4; + + // Vector uint + + typedef vec<1, uint, lowp> lowp_uvec1; + typedef vec<2, uint, lowp> lowp_uvec2; + typedef vec<3, uint, lowp> lowp_uvec3; + typedef vec<4, uint, lowp> lowp_uvec4; + + typedef vec<1, uint, mediump> mediump_uvec1; + typedef vec<2, uint, mediump> mediump_uvec2; + typedef vec<3, uint, mediump> mediump_uvec3; + typedef vec<4, uint, mediump> mediump_uvec4; + + typedef vec<1, uint, highp> highp_uvec1; + typedef vec<2, uint, highp> highp_uvec2; + typedef vec<3, uint, highp> highp_uvec3; + typedef vec<4, uint, highp> highp_uvec4; + + typedef vec<1, uint, defaultp> uvec1; + typedef vec<2, uint, defaultp> uvec2; + typedef vec<3, uint, defaultp> uvec3; + typedef vec<4, uint, defaultp> uvec4; + + typedef vec<1, u8, lowp> lowp_u8vec1; + typedef vec<2, u8, lowp> lowp_u8vec2; + typedef vec<3, u8, lowp> lowp_u8vec3; + typedef vec<4, u8, lowp> lowp_u8vec4; + + typedef vec<1, u8, mediump> mediump_u8vec1; + typedef vec<2, u8, mediump> mediump_u8vec2; + typedef vec<3, u8, mediump> mediump_u8vec3; + typedef vec<4, u8, mediump> mediump_u8vec4; + + typedef vec<1, u8, highp> highp_u8vec1; + typedef vec<2, u8, highp> highp_u8vec2; + typedef vec<3, u8, highp> highp_u8vec3; + typedef vec<4, u8, highp> highp_u8vec4; + + typedef vec<1, u8, defaultp> u8vec1; + typedef vec<2, u8, defaultp> u8vec2; + typedef vec<3, u8, defaultp> u8vec3; + typedef vec<4, u8, defaultp> u8vec4; + + typedef vec<1, u16, lowp> lowp_u16vec1; + typedef vec<2, u16, lowp> lowp_u16vec2; + typedef vec<3, u16, lowp> lowp_u16vec3; + typedef vec<4, u16, lowp> lowp_u16vec4; + + typedef vec<1, u16, mediump> mediump_u16vec1; + typedef vec<2, u16, mediump> mediump_u16vec2; + typedef vec<3, u16, mediump> mediump_u16vec3; + typedef vec<4, u16, mediump> mediump_u16vec4; + + typedef vec<1, u16, highp> highp_u16vec1; + typedef vec<2, u16, highp> highp_u16vec2; + typedef vec<3, u16, highp> highp_u16vec3; + typedef vec<4, u16, highp> highp_u16vec4; + + typedef vec<1, u16, defaultp> u16vec1; + typedef vec<2, u16, defaultp> u16vec2; + typedef vec<3, u16, defaultp> u16vec3; + typedef vec<4, u16, defaultp> u16vec4; + + typedef vec<1, u32, lowp> lowp_u32vec1; + typedef vec<2, u32, lowp> lowp_u32vec2; + typedef vec<3, u32, lowp> lowp_u32vec3; + typedef vec<4, u32, lowp> lowp_u32vec4; + + typedef vec<1, u32, mediump> mediump_u32vec1; + typedef vec<2, u32, mediump> mediump_u32vec2; + typedef vec<3, u32, mediump> mediump_u32vec3; + typedef vec<4, u32, mediump> mediump_u32vec4; + + typedef vec<1, u32, highp> highp_u32vec1; + typedef vec<2, u32, highp> highp_u32vec2; + typedef vec<3, u32, highp> highp_u32vec3; + typedef vec<4, u32, highp> highp_u32vec4; + + typedef vec<1, u32, defaultp> u32vec1; + typedef vec<2, u32, defaultp> u32vec2; + typedef vec<3, u32, defaultp> u32vec3; + typedef vec<4, u32, defaultp> u32vec4; + + typedef vec<1, u64, lowp> lowp_u64vec1; + typedef vec<2, u64, lowp> lowp_u64vec2; + typedef vec<3, u64, lowp> lowp_u64vec3; + typedef vec<4, u64, lowp> lowp_u64vec4; + + typedef vec<1, u64, mediump> mediump_u64vec1; + typedef vec<2, u64, mediump> mediump_u64vec2; + typedef vec<3, u64, mediump> mediump_u64vec3; + typedef vec<4, u64, mediump> mediump_u64vec4; + + typedef vec<1, u64, highp> highp_u64vec1; + typedef vec<2, u64, highp> highp_u64vec2; + typedef vec<3, u64, highp> highp_u64vec3; + typedef vec<4, u64, highp> highp_u64vec4; + + typedef vec<1, u64, defaultp> u64vec1; + typedef vec<2, u64, defaultp> u64vec2; + typedef vec<3, u64, defaultp> u64vec3; + typedef vec<4, u64, defaultp> u64vec4; + + // Vector float + + typedef vec<1, float, lowp> lowp_vec1; + typedef vec<2, float, lowp> lowp_vec2; + typedef vec<3, float, lowp> lowp_vec3; + typedef vec<4, float, lowp> lowp_vec4; + + typedef vec<1, float, mediump> mediump_vec1; + typedef vec<2, float, mediump> mediump_vec2; + typedef vec<3, float, mediump> mediump_vec3; + typedef vec<4, float, mediump> mediump_vec4; + + typedef vec<1, float, highp> highp_vec1; + typedef vec<2, float, highp> highp_vec2; + typedef vec<3, float, highp> highp_vec3; + typedef vec<4, float, highp> highp_vec4; + + typedef vec<1, float, defaultp> vec1; + typedef vec<2, float, defaultp> vec2; + typedef vec<3, float, defaultp> vec3; + typedef vec<4, float, defaultp> vec4; + + typedef vec<1, float, lowp> lowp_fvec1; + typedef vec<2, float, lowp> lowp_fvec2; + typedef vec<3, float, lowp> lowp_fvec3; + typedef vec<4, float, lowp> lowp_fvec4; + + typedef vec<1, float, mediump> mediump_fvec1; + typedef vec<2, float, mediump> mediump_fvec2; + typedef vec<3, float, mediump> mediump_fvec3; + typedef vec<4, float, mediump> mediump_fvec4; + + typedef vec<1, float, highp> highp_fvec1; + typedef vec<2, float, highp> highp_fvec2; + typedef vec<3, float, highp> highp_fvec3; + typedef vec<4, float, highp> highp_fvec4; + + typedef vec<1, f32, defaultp> fvec1; + typedef vec<2, f32, defaultp> fvec2; + typedef vec<3, f32, defaultp> fvec3; + typedef vec<4, f32, defaultp> fvec4; + + typedef vec<1, f32, lowp> lowp_f32vec1; + typedef vec<2, f32, lowp> lowp_f32vec2; + typedef vec<3, f32, lowp> lowp_f32vec3; + typedef vec<4, f32, lowp> lowp_f32vec4; + + typedef vec<1, f32, mediump> mediump_f32vec1; + typedef vec<2, f32, mediump> mediump_f32vec2; + typedef vec<3, f32, mediump> mediump_f32vec3; + typedef vec<4, f32, mediump> mediump_f32vec4; + + typedef vec<1, f32, highp> highp_f32vec1; + typedef vec<2, f32, highp> highp_f32vec2; + typedef vec<3, f32, highp> highp_f32vec3; + typedef vec<4, f32, highp> highp_f32vec4; + + typedef vec<1, f32, defaultp> f32vec1; + typedef vec<2, f32, defaultp> f32vec2; + typedef vec<3, f32, defaultp> f32vec3; + typedef vec<4, f32, defaultp> f32vec4; + + typedef vec<1, f64, lowp> lowp_dvec1; + typedef vec<2, f64, lowp> lowp_dvec2; + typedef vec<3, f64, lowp> lowp_dvec3; + typedef vec<4, f64, lowp> lowp_dvec4; + + typedef vec<1, f64, mediump> mediump_dvec1; + typedef vec<2, f64, mediump> mediump_dvec2; + typedef vec<3, f64, mediump> mediump_dvec3; + typedef vec<4, f64, mediump> mediump_dvec4; + + typedef vec<1, f64, highp> highp_dvec1; + typedef vec<2, f64, highp> highp_dvec2; + typedef vec<3, f64, highp> highp_dvec3; + typedef vec<4, f64, highp> highp_dvec4; + + typedef vec<1, f64, defaultp> dvec1; + typedef vec<2, f64, defaultp> dvec2; + typedef vec<3, f64, defaultp> dvec3; + typedef vec<4, f64, defaultp> dvec4; + + typedef vec<1, f64, lowp> lowp_f64vec1; + typedef vec<2, f64, lowp> lowp_f64vec2; + typedef vec<3, f64, lowp> lowp_f64vec3; + typedef vec<4, f64, lowp> lowp_f64vec4; + + typedef vec<1, f64, mediump> mediump_f64vec1; + typedef vec<2, f64, mediump> mediump_f64vec2; + typedef vec<3, f64, mediump> mediump_f64vec3; + typedef vec<4, f64, mediump> mediump_f64vec4; + + typedef vec<1, f64, highp> highp_f64vec1; + typedef vec<2, f64, highp> highp_f64vec2; + typedef vec<3, f64, highp> highp_f64vec3; + typedef vec<4, f64, highp> highp_f64vec4; + + typedef vec<1, f64, defaultp> f64vec1; + typedef vec<2, f64, defaultp> f64vec2; + typedef vec<3, f64, defaultp> f64vec3; + typedef vec<4, f64, defaultp> f64vec4; + + // Matrix NxN + + typedef mat<2, 2, f32, lowp> lowp_mat2; + typedef mat<3, 3, f32, lowp> lowp_mat3; + typedef mat<4, 4, f32, lowp> lowp_mat4; + + typedef mat<2, 2, f32, mediump> mediump_mat2; + typedef mat<3, 3, f32, mediump> mediump_mat3; + typedef mat<4, 4, f32, mediump> mediump_mat4; + + typedef mat<2, 2, f32, highp> highp_mat2; + typedef mat<3, 3, f32, highp> highp_mat3; + typedef mat<4, 4, f32, highp> highp_mat4; + + typedef mat<2, 2, f32, defaultp> mat2; + typedef mat<3, 3, f32, defaultp> mat3; + typedef mat<4, 4, f32, defaultp> mat4; + + typedef mat<2, 2, f32, lowp> lowp_fmat2; + typedef mat<3, 3, f32, lowp> lowp_fmat3; + typedef mat<4, 4, f32, lowp> lowp_fmat4; + + typedef mat<2, 2, f32, mediump> mediump_fmat2; + typedef mat<3, 3, f32, mediump> mediump_fmat3; + typedef mat<4, 4, f32, mediump> mediump_fmat4; + + typedef mat<2, 2, f32, highp> highp_fmat2; + typedef mat<3, 3, f32, highp> highp_fmat3; + typedef mat<4, 4, f32, highp> highp_fmat4; + + typedef mat<2, 2, f32, defaultp> fmat2; + typedef mat<3, 3, f32, defaultp> fmat3; + typedef mat<4, 4, f32, defaultp> fmat4; + + typedef mat<2, 2, f32, lowp> lowp_f32mat2; + typedef mat<3, 3, f32, lowp> lowp_f32mat3; + typedef mat<4, 4, f32, lowp> lowp_f32mat4; + + typedef mat<2, 2, f32, mediump> mediump_f32mat2; + typedef mat<3, 3, f32, mediump> mediump_f32mat3; + typedef mat<4, 4, f32, mediump> mediump_f32mat4; + + typedef mat<2, 2, f32, highp> highp_f32mat2; + typedef mat<3, 3, f32, highp> highp_f32mat3; + typedef mat<4, 4, f32, highp> highp_f32mat4; + + typedef mat<2, 2, f32, defaultp> f32mat2; + typedef mat<3, 3, f32, defaultp> f32mat3; + typedef mat<4, 4, f32, defaultp> f32mat4; + + typedef mat<2, 2, f64, lowp> lowp_dmat2; + typedef mat<3, 3, f64, lowp> lowp_dmat3; + typedef mat<4, 4, f64, lowp> lowp_dmat4; + + typedef mat<2, 2, f64, mediump> mediump_dmat2; + typedef mat<3, 3, f64, mediump> mediump_dmat3; + typedef mat<4, 4, f64, mediump> mediump_dmat4; + + typedef mat<2, 2, f64, highp> highp_dmat2; + typedef mat<3, 3, f64, highp> highp_dmat3; + typedef mat<4, 4, f64, highp> highp_dmat4; + + typedef mat<2, 2, f64, defaultp> dmat2; + typedef mat<3, 3, f64, defaultp> dmat3; + typedef mat<4, 4, f64, defaultp> dmat4; + + typedef mat<2, 2, f64, lowp> lowp_f64mat2; + typedef mat<3, 3, f64, lowp> lowp_f64mat3; + typedef mat<4, 4, f64, lowp> lowp_f64mat4; + + typedef mat<2, 2, f64, mediump> mediump_f64mat2; + typedef mat<3, 3, f64, mediump> mediump_f64mat3; + typedef mat<4, 4, f64, mediump> mediump_f64mat4; + + typedef mat<2, 2, f64, highp> highp_f64mat2; + typedef mat<3, 3, f64, highp> highp_f64mat3; + typedef mat<4, 4, f64, highp> highp_f64mat4; + + typedef mat<2, 2, f64, defaultp> f64mat2; + typedef mat<3, 3, f64, defaultp> f64mat3; + typedef mat<4, 4, f64, defaultp> f64mat4; + + // Matrix MxN + + typedef mat<2, 2, f32, lowp> lowp_mat2x2; + typedef mat<2, 3, f32, lowp> lowp_mat2x3; + typedef mat<2, 4, f32, lowp> lowp_mat2x4; + typedef mat<3, 2, f32, lowp> lowp_mat3x2; + typedef mat<3, 3, f32, lowp> lowp_mat3x3; + typedef mat<3, 4, f32, lowp> lowp_mat3x4; + typedef mat<4, 2, f32, lowp> lowp_mat4x2; + typedef mat<4, 3, f32, lowp> lowp_mat4x3; + typedef mat<4, 4, f32, lowp> lowp_mat4x4; + + typedef mat<2, 2, f32, mediump> mediump_mat2x2; + typedef mat<2, 3, f32, mediump> mediump_mat2x3; + typedef mat<2, 4, f32, mediump> mediump_mat2x4; + typedef mat<3, 2, f32, mediump> mediump_mat3x2; + typedef mat<3, 3, f32, mediump> mediump_mat3x3; + typedef mat<3, 4, f32, mediump> mediump_mat3x4; + typedef mat<4, 2, f32, mediump> mediump_mat4x2; + typedef mat<4, 3, f32, mediump> mediump_mat4x3; + typedef mat<4, 4, f32, mediump> mediump_mat4x4; + + typedef mat<2, 2, f32, highp> highp_mat2x2; + typedef mat<2, 3, f32, highp> highp_mat2x3; + typedef mat<2, 4, f32, highp> highp_mat2x4; + typedef mat<3, 2, f32, highp> highp_mat3x2; + typedef mat<3, 3, f32, highp> highp_mat3x3; + typedef mat<3, 4, f32, highp> highp_mat3x4; + typedef mat<4, 2, f32, highp> highp_mat4x2; + typedef mat<4, 3, f32, highp> highp_mat4x3; + typedef mat<4, 4, f32, highp> highp_mat4x4; + + typedef mat<2, 2, f32, defaultp> mat2x2; + typedef mat<3, 2, f32, defaultp> mat3x2; + typedef mat<4, 2, f32, defaultp> mat4x2; + typedef mat<2, 3, f32, defaultp> mat2x3; + typedef mat<3, 3, f32, defaultp> mat3x3; + typedef mat<4, 3, f32, defaultp> mat4x3; + typedef mat<2, 4, f32, defaultp> mat2x4; + typedef mat<3, 4, f32, defaultp> mat3x4; + typedef mat<4, 4, f32, defaultp> mat4x4; + + typedef mat<2, 2, f32, lowp> lowp_fmat2x2; + typedef mat<2, 3, f32, lowp> lowp_fmat2x3; + typedef mat<2, 4, f32, lowp> lowp_fmat2x4; + typedef mat<3, 2, f32, lowp> lowp_fmat3x2; + typedef mat<3, 3, f32, lowp> lowp_fmat3x3; + typedef mat<3, 4, f32, lowp> lowp_fmat3x4; + typedef mat<4, 2, f32, lowp> lowp_fmat4x2; + typedef mat<4, 3, f32, lowp> lowp_fmat4x3; + typedef mat<4, 4, f32, lowp> lowp_fmat4x4; + + typedef mat<2, 2, f32, mediump> mediump_fmat2x2; + typedef mat<2, 3, f32, mediump> mediump_fmat2x3; + typedef mat<2, 4, f32, mediump> mediump_fmat2x4; + typedef mat<3, 2, f32, mediump> mediump_fmat3x2; + typedef mat<3, 3, f32, mediump> mediump_fmat3x3; + typedef mat<3, 4, f32, mediump> mediump_fmat3x4; + typedef mat<4, 2, f32, mediump> mediump_fmat4x2; + typedef mat<4, 3, f32, mediump> mediump_fmat4x3; + typedef mat<4, 4, f32, mediump> mediump_fmat4x4; + + typedef mat<2, 2, f32, highp> highp_fmat2x2; + typedef mat<2, 3, f32, highp> highp_fmat2x3; + typedef mat<2, 4, f32, highp> highp_fmat2x4; + typedef mat<3, 2, f32, highp> highp_fmat3x2; + typedef mat<3, 3, f32, highp> highp_fmat3x3; + typedef mat<3, 4, f32, highp> highp_fmat3x4; + typedef mat<4, 2, f32, highp> highp_fmat4x2; + typedef mat<4, 3, f32, highp> highp_fmat4x3; + typedef mat<4, 4, f32, highp> highp_fmat4x4; + + typedef mat<2, 2, f32, defaultp> fmat2x2; + typedef mat<3, 2, f32, defaultp> fmat3x2; + typedef mat<4, 2, f32, defaultp> fmat4x2; + typedef mat<2, 3, f32, defaultp> fmat2x3; + typedef mat<3, 3, f32, defaultp> fmat3x3; + typedef mat<4, 3, f32, defaultp> fmat4x3; + typedef mat<2, 4, f32, defaultp> fmat2x4; + typedef mat<3, 4, f32, defaultp> fmat3x4; + typedef mat<4, 4, f32, defaultp> fmat4x4; + + typedef mat<2, 2, f32, lowp> lowp_f32mat2x2; + typedef mat<2, 3, f32, lowp> lowp_f32mat2x3; + typedef mat<2, 4, f32, lowp> lowp_f32mat2x4; + typedef mat<3, 2, f32, lowp> lowp_f32mat3x2; + typedef mat<3, 3, f32, lowp> lowp_f32mat3x3; + typedef mat<3, 4, f32, lowp> lowp_f32mat3x4; + typedef mat<4, 2, f32, lowp> lowp_f32mat4x2; + typedef mat<4, 3, f32, lowp> lowp_f32mat4x3; + typedef mat<4, 4, f32, lowp> lowp_f32mat4x4; + + typedef mat<2, 2, f32, mediump> mediump_f32mat2x2; + typedef mat<2, 3, f32, mediump> mediump_f32mat2x3; + typedef mat<2, 4, f32, mediump> mediump_f32mat2x4; + typedef mat<3, 2, f32, mediump> mediump_f32mat3x2; + typedef mat<3, 3, f32, mediump> mediump_f32mat3x3; + typedef mat<3, 4, f32, mediump> mediump_f32mat3x4; + typedef mat<4, 2, f32, mediump> mediump_f32mat4x2; + typedef mat<4, 3, f32, mediump> mediump_f32mat4x3; + typedef mat<4, 4, f32, mediump> mediump_f32mat4x4; + + typedef mat<2, 2, f32, highp> highp_f32mat2x2; + typedef mat<2, 3, f32, highp> highp_f32mat2x3; + typedef mat<2, 4, f32, highp> highp_f32mat2x4; + typedef mat<3, 2, f32, highp> highp_f32mat3x2; + typedef mat<3, 3, f32, highp> highp_f32mat3x3; + typedef mat<3, 4, f32, highp> highp_f32mat3x4; + typedef mat<4, 2, f32, highp> highp_f32mat4x2; + typedef mat<4, 3, f32, highp> highp_f32mat4x3; + typedef mat<4, 4, f32, highp> highp_f32mat4x4; + + typedef mat<2, 2, f32, defaultp> f32mat2x2; + typedef mat<3, 2, f32, defaultp> f32mat3x2; + typedef mat<4, 2, f32, defaultp> f32mat4x2; + typedef mat<2, 3, f32, defaultp> f32mat2x3; + typedef mat<3, 3, f32, defaultp> f32mat3x3; + typedef mat<4, 3, f32, defaultp> f32mat4x3; + typedef mat<2, 4, f32, defaultp> f32mat2x4; + typedef mat<3, 4, f32, defaultp> f32mat3x4; + typedef mat<4, 4, f32, defaultp> f32mat4x4; + + typedef mat<2, 2, double, lowp> lowp_dmat2x2; + typedef mat<2, 3, double, lowp> lowp_dmat2x3; + typedef mat<2, 4, double, lowp> lowp_dmat2x4; + typedef mat<3, 2, double, lowp> lowp_dmat3x2; + typedef mat<3, 3, double, lowp> lowp_dmat3x3; + typedef mat<3, 4, double, lowp> lowp_dmat3x4; + typedef mat<4, 2, double, lowp> lowp_dmat4x2; + typedef mat<4, 3, double, lowp> lowp_dmat4x3; + typedef mat<4, 4, double, lowp> lowp_dmat4x4; + + typedef mat<2, 2, double, mediump> mediump_dmat2x2; + typedef mat<2, 3, double, mediump> mediump_dmat2x3; + typedef mat<2, 4, double, mediump> mediump_dmat2x4; + typedef mat<3, 2, double, mediump> mediump_dmat3x2; + typedef mat<3, 3, double, mediump> mediump_dmat3x3; + typedef mat<3, 4, double, mediump> mediump_dmat3x4; + typedef mat<4, 2, double, mediump> mediump_dmat4x2; + typedef mat<4, 3, double, mediump> mediump_dmat4x3; + typedef mat<4, 4, double, mediump> mediump_dmat4x4; + + typedef mat<2, 2, double, highp> highp_dmat2x2; + typedef mat<2, 3, double, highp> highp_dmat2x3; + typedef mat<2, 4, double, highp> highp_dmat2x4; + typedef mat<3, 2, double, highp> highp_dmat3x2; + typedef mat<3, 3, double, highp> highp_dmat3x3; + typedef mat<3, 4, double, highp> highp_dmat3x4; + typedef mat<4, 2, double, highp> highp_dmat4x2; + typedef mat<4, 3, double, highp> highp_dmat4x3; + typedef mat<4, 4, double, highp> highp_dmat4x4; + + typedef mat<2, 2, double, defaultp> dmat2x2; + typedef mat<3, 2, double, defaultp> dmat3x2; + typedef mat<4, 2, double, defaultp> dmat4x2; + typedef mat<2, 3, double, defaultp> dmat2x3; + typedef mat<3, 3, double, defaultp> dmat3x3; + typedef mat<4, 3, double, defaultp> dmat4x3; + typedef mat<2, 4, double, defaultp> dmat2x4; + typedef mat<3, 4, double, defaultp> dmat3x4; + typedef mat<4, 4, double, defaultp> dmat4x4; + + typedef mat<2, 2, f64, lowp> lowp_f64mat2x2; + typedef mat<2, 3, f64, lowp> lowp_f64mat2x3; + typedef mat<2, 4, f64, lowp> lowp_f64mat2x4; + typedef mat<3, 2, f64, lowp> lowp_f64mat3x2; + typedef mat<3, 3, f64, lowp> lowp_f64mat3x3; + typedef mat<3, 4, f64, lowp> lowp_f64mat3x4; + typedef mat<4, 2, f64, lowp> lowp_f64mat4x2; + typedef mat<4, 3, f64, lowp> lowp_f64mat4x3; + typedef mat<4, 4, f64, lowp> lowp_f64mat4x4; + + typedef mat<2, 2, f64, mediump> mediump_f64mat2x2; + typedef mat<2, 3, f64, mediump> mediump_f64mat2x3; + typedef mat<2, 4, f64, mediump> mediump_f64mat2x4; + typedef mat<3, 2, f64, mediump> mediump_f64mat3x2; + typedef mat<3, 3, f64, mediump> mediump_f64mat3x3; + typedef mat<3, 4, f64, mediump> mediump_f64mat3x4; + typedef mat<4, 2, f64, mediump> mediump_f64mat4x2; + typedef mat<4, 3, f64, mediump> mediump_f64mat4x3; + typedef mat<4, 4, f64, mediump> mediump_f64mat4x4; + + typedef mat<2, 2, f64, highp> highp_f64mat2x2; + typedef mat<2, 3, f64, highp> highp_f64mat2x3; + typedef mat<2, 4, f64, highp> highp_f64mat2x4; + typedef mat<3, 2, f64, highp> highp_f64mat3x2; + typedef mat<3, 3, f64, highp> highp_f64mat3x3; + typedef mat<3, 4, f64, highp> highp_f64mat3x4; + typedef mat<4, 2, f64, highp> highp_f64mat4x2; + typedef mat<4, 3, f64, highp> highp_f64mat4x3; + typedef mat<4, 4, f64, highp> highp_f64mat4x4; + + typedef mat<2, 2, f64, defaultp> f64mat2x2; + typedef mat<3, 2, f64, defaultp> f64mat3x2; + typedef mat<4, 2, f64, defaultp> f64mat4x2; + typedef mat<2, 3, f64, defaultp> f64mat2x3; + typedef mat<3, 3, f64, defaultp> f64mat3x3; + typedef mat<4, 3, f64, defaultp> f64mat4x3; + typedef mat<2, 4, f64, defaultp> f64mat2x4; + typedef mat<3, 4, f64, defaultp> f64mat3x4; + typedef mat<4, 4, f64, defaultp> f64mat4x4; + + // Signed integer matrix MxN + + typedef mat<2, 2, int, lowp> lowp_imat2x2; + typedef mat<2, 3, int, lowp> lowp_imat2x3; + typedef mat<2, 4, int, lowp> lowp_imat2x4; + typedef mat<3, 2, int, lowp> lowp_imat3x2; + typedef mat<3, 3, int, lowp> lowp_imat3x3; + typedef mat<3, 4, int, lowp> lowp_imat3x4; + typedef mat<4, 2, int, lowp> lowp_imat4x2; + typedef mat<4, 3, int, lowp> lowp_imat4x3; + typedef mat<4, 4, int, lowp> lowp_imat4x4; + + typedef mat<2, 2, int, mediump> mediump_imat2x2; + typedef mat<2, 3, int, mediump> mediump_imat2x3; + typedef mat<2, 4, int, mediump> mediump_imat2x4; + typedef mat<3, 2, int, mediump> mediump_imat3x2; + typedef mat<3, 3, int, mediump> mediump_imat3x3; + typedef mat<3, 4, int, mediump> mediump_imat3x4; + typedef mat<4, 2, int, mediump> mediump_imat4x2; + typedef mat<4, 3, int, mediump> mediump_imat4x3; + typedef mat<4, 4, int, mediump> mediump_imat4x4; + + typedef mat<2, 2, int, highp> highp_imat2x2; + typedef mat<2, 3, int, highp> highp_imat2x3; + typedef mat<2, 4, int, highp> highp_imat2x4; + typedef mat<3, 2, int, highp> highp_imat3x2; + typedef mat<3, 3, int, highp> highp_imat3x3; + typedef mat<3, 4, int, highp> highp_imat3x4; + typedef mat<4, 2, int, highp> highp_imat4x2; + typedef mat<4, 3, int, highp> highp_imat4x3; + typedef mat<4, 4, int, highp> highp_imat4x4; + + typedef mat<2, 2, int, defaultp> imat2x2; + typedef mat<3, 2, int, defaultp> imat3x2; + typedef mat<4, 2, int, defaultp> imat4x2; + typedef mat<2, 3, int, defaultp> imat2x3; + typedef mat<3, 3, int, defaultp> imat3x3; + typedef mat<4, 3, int, defaultp> imat4x3; + typedef mat<2, 4, int, defaultp> imat2x4; + typedef mat<3, 4, int, defaultp> imat3x4; + typedef mat<4, 4, int, defaultp> imat4x4; + + + typedef mat<2, 2, int8, lowp> lowp_i8mat2x2; + typedef mat<2, 3, int8, lowp> lowp_i8mat2x3; + typedef mat<2, 4, int8, lowp> lowp_i8mat2x4; + typedef mat<3, 2, int8, lowp> lowp_i8mat3x2; + typedef mat<3, 3, int8, lowp> lowp_i8mat3x3; + typedef mat<3, 4, int8, lowp> lowp_i8mat3x4; + typedef mat<4, 2, int8, lowp> lowp_i8mat4x2; + typedef mat<4, 3, int8, lowp> lowp_i8mat4x3; + typedef mat<4, 4, int8, lowp> lowp_i8mat4x4; + + typedef mat<2, 2, int8, mediump> mediump_i8mat2x2; + typedef mat<2, 3, int8, mediump> mediump_i8mat2x3; + typedef mat<2, 4, int8, mediump> mediump_i8mat2x4; + typedef mat<3, 2, int8, mediump> mediump_i8mat3x2; + typedef mat<3, 3, int8, mediump> mediump_i8mat3x3; + typedef mat<3, 4, int8, mediump> mediump_i8mat3x4; + typedef mat<4, 2, int8, mediump> mediump_i8mat4x2; + typedef mat<4, 3, int8, mediump> mediump_i8mat4x3; + typedef mat<4, 4, int8, mediump> mediump_i8mat4x4; + + typedef mat<2, 2, int8, highp> highp_i8mat2x2; + typedef mat<2, 3, int8, highp> highp_i8mat2x3; + typedef mat<2, 4, int8, highp> highp_i8mat2x4; + typedef mat<3, 2, int8, highp> highp_i8mat3x2; + typedef mat<3, 3, int8, highp> highp_i8mat3x3; + typedef mat<3, 4, int8, highp> highp_i8mat3x4; + typedef mat<4, 2, int8, highp> highp_i8mat4x2; + typedef mat<4, 3, int8, highp> highp_i8mat4x3; + typedef mat<4, 4, int8, highp> highp_i8mat4x4; + + typedef mat<2, 2, int8, defaultp> i8mat2x2; + typedef mat<3, 2, int8, defaultp> i8mat3x2; + typedef mat<4, 2, int8, defaultp> i8mat4x2; + typedef mat<2, 3, int8, defaultp> i8mat2x3; + typedef mat<3, 3, int8, defaultp> i8mat3x3; + typedef mat<4, 3, int8, defaultp> i8mat4x3; + typedef mat<2, 4, int8, defaultp> i8mat2x4; + typedef mat<3, 4, int8, defaultp> i8mat3x4; + typedef mat<4, 4, int8, defaultp> i8mat4x4; + + + typedef mat<2, 2, int16, lowp> lowp_i16mat2x2; + typedef mat<2, 3, int16, lowp> lowp_i16mat2x3; + typedef mat<2, 4, int16, lowp> lowp_i16mat2x4; + typedef mat<3, 2, int16, lowp> lowp_i16mat3x2; + typedef mat<3, 3, int16, lowp> lowp_i16mat3x3; + typedef mat<3, 4, int16, lowp> lowp_i16mat3x4; + typedef mat<4, 2, int16, lowp> lowp_i16mat4x2; + typedef mat<4, 3, int16, lowp> lowp_i16mat4x3; + typedef mat<4, 4, int16, lowp> lowp_i16mat4x4; + + typedef mat<2, 2, int16, mediump> mediump_i16mat2x2; + typedef mat<2, 3, int16, mediump> mediump_i16mat2x3; + typedef mat<2, 4, int16, mediump> mediump_i16mat2x4; + typedef mat<3, 2, int16, mediump> mediump_i16mat3x2; + typedef mat<3, 3, int16, mediump> mediump_i16mat3x3; + typedef mat<3, 4, int16, mediump> mediump_i16mat3x4; + typedef mat<4, 2, int16, mediump> mediump_i16mat4x2; + typedef mat<4, 3, int16, mediump> mediump_i16mat4x3; + typedef mat<4, 4, int16, mediump> mediump_i16mat4x4; + + typedef mat<2, 2, int16, highp> highp_i16mat2x2; + typedef mat<2, 3, int16, highp> highp_i16mat2x3; + typedef mat<2, 4, int16, highp> highp_i16mat2x4; + typedef mat<3, 2, int16, highp> highp_i16mat3x2; + typedef mat<3, 3, int16, highp> highp_i16mat3x3; + typedef mat<3, 4, int16, highp> highp_i16mat3x4; + typedef mat<4, 2, int16, highp> highp_i16mat4x2; + typedef mat<4, 3, int16, highp> highp_i16mat4x3; + typedef mat<4, 4, int16, highp> highp_i16mat4x4; + + typedef mat<2, 2, int16, defaultp> i16mat2x2; + typedef mat<3, 2, int16, defaultp> i16mat3x2; + typedef mat<4, 2, int16, defaultp> i16mat4x2; + typedef mat<2, 3, int16, defaultp> i16mat2x3; + typedef mat<3, 3, int16, defaultp> i16mat3x3; + typedef mat<4, 3, int16, defaultp> i16mat4x3; + typedef mat<2, 4, int16, defaultp> i16mat2x4; + typedef mat<3, 4, int16, defaultp> i16mat3x4; + typedef mat<4, 4, int16, defaultp> i16mat4x4; + + + typedef mat<2, 2, int32, lowp> lowp_i32mat2x2; + typedef mat<2, 3, int32, lowp> lowp_i32mat2x3; + typedef mat<2, 4, int32, lowp> lowp_i32mat2x4; + typedef mat<3, 2, int32, lowp> lowp_i32mat3x2; + typedef mat<3, 3, int32, lowp> lowp_i32mat3x3; + typedef mat<3, 4, int32, lowp> lowp_i32mat3x4; + typedef mat<4, 2, int32, lowp> lowp_i32mat4x2; + typedef mat<4, 3, int32, lowp> lowp_i32mat4x3; + typedef mat<4, 4, int32, lowp> lowp_i32mat4x4; + + typedef mat<2, 2, int32, mediump> mediump_i32mat2x2; + typedef mat<2, 3, int32, mediump> mediump_i32mat2x3; + typedef mat<2, 4, int32, mediump> mediump_i32mat2x4; + typedef mat<3, 2, int32, mediump> mediump_i32mat3x2; + typedef mat<3, 3, int32, mediump> mediump_i32mat3x3; + typedef mat<3, 4, int32, mediump> mediump_i32mat3x4; + typedef mat<4, 2, int32, mediump> mediump_i32mat4x2; + typedef mat<4, 3, int32, mediump> mediump_i32mat4x3; + typedef mat<4, 4, int32, mediump> mediump_i32mat4x4; + + typedef mat<2, 2, int32, highp> highp_i32mat2x2; + typedef mat<2, 3, int32, highp> highp_i32mat2x3; + typedef mat<2, 4, int32, highp> highp_i32mat2x4; + typedef mat<3, 2, int32, highp> highp_i32mat3x2; + typedef mat<3, 3, int32, highp> highp_i32mat3x3; + typedef mat<3, 4, int32, highp> highp_i32mat3x4; + typedef mat<4, 2, int32, highp> highp_i32mat4x2; + typedef mat<4, 3, int32, highp> highp_i32mat4x3; + typedef mat<4, 4, int32, highp> highp_i32mat4x4; + + typedef mat<2, 2, int32, defaultp> i32mat2x2; + typedef mat<3, 2, int32, defaultp> i32mat3x2; + typedef mat<4, 2, int32, defaultp> i32mat4x2; + typedef mat<2, 3, int32, defaultp> i32mat2x3; + typedef mat<3, 3, int32, defaultp> i32mat3x3; + typedef mat<4, 3, int32, defaultp> i32mat4x3; + typedef mat<2, 4, int32, defaultp> i32mat2x4; + typedef mat<3, 4, int32, defaultp> i32mat3x4; + typedef mat<4, 4, int32, defaultp> i32mat4x4; + + + typedef mat<2, 2, int64, lowp> lowp_i64mat2x2; + typedef mat<2, 3, int64, lowp> lowp_i64mat2x3; + typedef mat<2, 4, int64, lowp> lowp_i64mat2x4; + typedef mat<3, 2, int64, lowp> lowp_i64mat3x2; + typedef mat<3, 3, int64, lowp> lowp_i64mat3x3; + typedef mat<3, 4, int64, lowp> lowp_i64mat3x4; + typedef mat<4, 2, int64, lowp> lowp_i64mat4x2; + typedef mat<4, 3, int64, lowp> lowp_i64mat4x3; + typedef mat<4, 4, int64, lowp> lowp_i64mat4x4; + + typedef mat<2, 2, int64, mediump> mediump_i64mat2x2; + typedef mat<2, 3, int64, mediump> mediump_i64mat2x3; + typedef mat<2, 4, int64, mediump> mediump_i64mat2x4; + typedef mat<3, 2, int64, mediump> mediump_i64mat3x2; + typedef mat<3, 3, int64, mediump> mediump_i64mat3x3; + typedef mat<3, 4, int64, mediump> mediump_i64mat3x4; + typedef mat<4, 2, int64, mediump> mediump_i64mat4x2; + typedef mat<4, 3, int64, mediump> mediump_i64mat4x3; + typedef mat<4, 4, int64, mediump> mediump_i64mat4x4; + + typedef mat<2, 2, int64, highp> highp_i64mat2x2; + typedef mat<2, 3, int64, highp> highp_i64mat2x3; + typedef mat<2, 4, int64, highp> highp_i64mat2x4; + typedef mat<3, 2, int64, highp> highp_i64mat3x2; + typedef mat<3, 3, int64, highp> highp_i64mat3x3; + typedef mat<3, 4, int64, highp> highp_i64mat3x4; + typedef mat<4, 2, int64, highp> highp_i64mat4x2; + typedef mat<4, 3, int64, highp> highp_i64mat4x3; + typedef mat<4, 4, int64, highp> highp_i64mat4x4; + + typedef mat<2, 2, int64, defaultp> i64mat2x2; + typedef mat<3, 2, int64, defaultp> i64mat3x2; + typedef mat<4, 2, int64, defaultp> i64mat4x2; + typedef mat<2, 3, int64, defaultp> i64mat2x3; + typedef mat<3, 3, int64, defaultp> i64mat3x3; + typedef mat<4, 3, int64, defaultp> i64mat4x3; + typedef mat<2, 4, int64, defaultp> i64mat2x4; + typedef mat<3, 4, int64, defaultp> i64mat3x4; + typedef mat<4, 4, int64, defaultp> i64mat4x4; + + + // Unsigned integer matrix MxN + + typedef mat<2, 2, uint, lowp> lowp_umat2x2; + typedef mat<2, 3, uint, lowp> lowp_umat2x3; + typedef mat<2, 4, uint, lowp> lowp_umat2x4; + typedef mat<3, 2, uint, lowp> lowp_umat3x2; + typedef mat<3, 3, uint, lowp> lowp_umat3x3; + typedef mat<3, 4, uint, lowp> lowp_umat3x4; + typedef mat<4, 2, uint, lowp> lowp_umat4x2; + typedef mat<4, 3, uint, lowp> lowp_umat4x3; + typedef mat<4, 4, uint, lowp> lowp_umat4x4; + + typedef mat<2, 2, uint, mediump> mediump_umat2x2; + typedef mat<2, 3, uint, mediump> mediump_umat2x3; + typedef mat<2, 4, uint, mediump> mediump_umat2x4; + typedef mat<3, 2, uint, mediump> mediump_umat3x2; + typedef mat<3, 3, uint, mediump> mediump_umat3x3; + typedef mat<3, 4, uint, mediump> mediump_umat3x4; + typedef mat<4, 2, uint, mediump> mediump_umat4x2; + typedef mat<4, 3, uint, mediump> mediump_umat4x3; + typedef mat<4, 4, uint, mediump> mediump_umat4x4; + + typedef mat<2, 2, uint, highp> highp_umat2x2; + typedef mat<2, 3, uint, highp> highp_umat2x3; + typedef mat<2, 4, uint, highp> highp_umat2x4; + typedef mat<3, 2, uint, highp> highp_umat3x2; + typedef mat<3, 3, uint, highp> highp_umat3x3; + typedef mat<3, 4, uint, highp> highp_umat3x4; + typedef mat<4, 2, uint, highp> highp_umat4x2; + typedef mat<4, 3, uint, highp> highp_umat4x3; + typedef mat<4, 4, uint, highp> highp_umat4x4; + + typedef mat<2, 2, uint, defaultp> umat2x2; + typedef mat<3, 2, uint, defaultp> umat3x2; + typedef mat<4, 2, uint, defaultp> umat4x2; + typedef mat<2, 3, uint, defaultp> umat2x3; + typedef mat<3, 3, uint, defaultp> umat3x3; + typedef mat<4, 3, uint, defaultp> umat4x3; + typedef mat<2, 4, uint, defaultp> umat2x4; + typedef mat<3, 4, uint, defaultp> umat3x4; + typedef mat<4, 4, uint, defaultp> umat4x4; + + + typedef mat<2, 2, uint8, lowp> lowp_u8mat2x2; + typedef mat<2, 3, uint8, lowp> lowp_u8mat2x3; + typedef mat<2, 4, uint8, lowp> lowp_u8mat2x4; + typedef mat<3, 2, uint8, lowp> lowp_u8mat3x2; + typedef mat<3, 3, uint8, lowp> lowp_u8mat3x3; + typedef mat<3, 4, uint8, lowp> lowp_u8mat3x4; + typedef mat<4, 2, uint8, lowp> lowp_u8mat4x2; + typedef mat<4, 3, uint8, lowp> lowp_u8mat4x3; + typedef mat<4, 4, uint8, lowp> lowp_u8mat4x4; + + typedef mat<2, 2, uint8, mediump> mediump_u8mat2x2; + typedef mat<2, 3, uint8, mediump> mediump_u8mat2x3; + typedef mat<2, 4, uint8, mediump> mediump_u8mat2x4; + typedef mat<3, 2, uint8, mediump> mediump_u8mat3x2; + typedef mat<3, 3, uint8, mediump> mediump_u8mat3x3; + typedef mat<3, 4, uint8, mediump> mediump_u8mat3x4; + typedef mat<4, 2, uint8, mediump> mediump_u8mat4x2; + typedef mat<4, 3, uint8, mediump> mediump_u8mat4x3; + typedef mat<4, 4, uint8, mediump> mediump_u8mat4x4; + + typedef mat<2, 2, uint8, highp> highp_u8mat2x2; + typedef mat<2, 3, uint8, highp> highp_u8mat2x3; + typedef mat<2, 4, uint8, highp> highp_u8mat2x4; + typedef mat<3, 2, uint8, highp> highp_u8mat3x2; + typedef mat<3, 3, uint8, highp> highp_u8mat3x3; + typedef mat<3, 4, uint8, highp> highp_u8mat3x4; + typedef mat<4, 2, uint8, highp> highp_u8mat4x2; + typedef mat<4, 3, uint8, highp> highp_u8mat4x3; + typedef mat<4, 4, uint8, highp> highp_u8mat4x4; + + typedef mat<2, 2, uint8, defaultp> u8mat2x2; + typedef mat<3, 2, uint8, defaultp> u8mat3x2; + typedef mat<4, 2, uint8, defaultp> u8mat4x2; + typedef mat<2, 3, uint8, defaultp> u8mat2x3; + typedef mat<3, 3, uint8, defaultp> u8mat3x3; + typedef mat<4, 3, uint8, defaultp> u8mat4x3; + typedef mat<2, 4, uint8, defaultp> u8mat2x4; + typedef mat<3, 4, uint8, defaultp> u8mat3x4; + typedef mat<4, 4, uint8, defaultp> u8mat4x4; + + + typedef mat<2, 2, uint16, lowp> lowp_u16mat2x2; + typedef mat<2, 3, uint16, lowp> lowp_u16mat2x3; + typedef mat<2, 4, uint16, lowp> lowp_u16mat2x4; + typedef mat<3, 2, uint16, lowp> lowp_u16mat3x2; + typedef mat<3, 3, uint16, lowp> lowp_u16mat3x3; + typedef mat<3, 4, uint16, lowp> lowp_u16mat3x4; + typedef mat<4, 2, uint16, lowp> lowp_u16mat4x2; + typedef mat<4, 3, uint16, lowp> lowp_u16mat4x3; + typedef mat<4, 4, uint16, lowp> lowp_u16mat4x4; + + typedef mat<2, 2, uint16, mediump> mediump_u16mat2x2; + typedef mat<2, 3, uint16, mediump> mediump_u16mat2x3; + typedef mat<2, 4, uint16, mediump> mediump_u16mat2x4; + typedef mat<3, 2, uint16, mediump> mediump_u16mat3x2; + typedef mat<3, 3, uint16, mediump> mediump_u16mat3x3; + typedef mat<3, 4, uint16, mediump> mediump_u16mat3x4; + typedef mat<4, 2, uint16, mediump> mediump_u16mat4x2; + typedef mat<4, 3, uint16, mediump> mediump_u16mat4x3; + typedef mat<4, 4, uint16, mediump> mediump_u16mat4x4; + + typedef mat<2, 2, uint16, highp> highp_u16mat2x2; + typedef mat<2, 3, uint16, highp> highp_u16mat2x3; + typedef mat<2, 4, uint16, highp> highp_u16mat2x4; + typedef mat<3, 2, uint16, highp> highp_u16mat3x2; + typedef mat<3, 3, uint16, highp> highp_u16mat3x3; + typedef mat<3, 4, uint16, highp> highp_u16mat3x4; + typedef mat<4, 2, uint16, highp> highp_u16mat4x2; + typedef mat<4, 3, uint16, highp> highp_u16mat4x3; + typedef mat<4, 4, uint16, highp> highp_u16mat4x4; + + typedef mat<2, 2, uint16, defaultp> u16mat2x2; + typedef mat<3, 2, uint16, defaultp> u16mat3x2; + typedef mat<4, 2, uint16, defaultp> u16mat4x2; + typedef mat<2, 3, uint16, defaultp> u16mat2x3; + typedef mat<3, 3, uint16, defaultp> u16mat3x3; + typedef mat<4, 3, uint16, defaultp> u16mat4x3; + typedef mat<2, 4, uint16, defaultp> u16mat2x4; + typedef mat<3, 4, uint16, defaultp> u16mat3x4; + typedef mat<4, 4, uint16, defaultp> u16mat4x4; + + + typedef mat<2, 2, uint32, lowp> lowp_u32mat2x2; + typedef mat<2, 3, uint32, lowp> lowp_u32mat2x3; + typedef mat<2, 4, uint32, lowp> lowp_u32mat2x4; + typedef mat<3, 2, uint32, lowp> lowp_u32mat3x2; + typedef mat<3, 3, uint32, lowp> lowp_u32mat3x3; + typedef mat<3, 4, uint32, lowp> lowp_u32mat3x4; + typedef mat<4, 2, uint32, lowp> lowp_u32mat4x2; + typedef mat<4, 3, uint32, lowp> lowp_u32mat4x3; + typedef mat<4, 4, uint32, lowp> lowp_u32mat4x4; + + typedef mat<2, 2, uint32, mediump> mediump_u32mat2x2; + typedef mat<2, 3, uint32, mediump> mediump_u32mat2x3; + typedef mat<2, 4, uint32, mediump> mediump_u32mat2x4; + typedef mat<3, 2, uint32, mediump> mediump_u32mat3x2; + typedef mat<3, 3, uint32, mediump> mediump_u32mat3x3; + typedef mat<3, 4, uint32, mediump> mediump_u32mat3x4; + typedef mat<4, 2, uint32, mediump> mediump_u32mat4x2; + typedef mat<4, 3, uint32, mediump> mediump_u32mat4x3; + typedef mat<4, 4, uint32, mediump> mediump_u32mat4x4; + + typedef mat<2, 2, uint32, highp> highp_u32mat2x2; + typedef mat<2, 3, uint32, highp> highp_u32mat2x3; + typedef mat<2, 4, uint32, highp> highp_u32mat2x4; + typedef mat<3, 2, uint32, highp> highp_u32mat3x2; + typedef mat<3, 3, uint32, highp> highp_u32mat3x3; + typedef mat<3, 4, uint32, highp> highp_u32mat3x4; + typedef mat<4, 2, uint32, highp> highp_u32mat4x2; + typedef mat<4, 3, uint32, highp> highp_u32mat4x3; + typedef mat<4, 4, uint32, highp> highp_u32mat4x4; + + typedef mat<2, 2, uint32, defaultp> u32mat2x2; + typedef mat<3, 2, uint32, defaultp> u32mat3x2; + typedef mat<4, 2, uint32, defaultp> u32mat4x2; + typedef mat<2, 3, uint32, defaultp> u32mat2x3; + typedef mat<3, 3, uint32, defaultp> u32mat3x3; + typedef mat<4, 3, uint32, defaultp> u32mat4x3; + typedef mat<2, 4, uint32, defaultp> u32mat2x4; + typedef mat<3, 4, uint32, defaultp> u32mat3x4; + typedef mat<4, 4, uint32, defaultp> u32mat4x4; + + + typedef mat<2, 2, uint64, lowp> lowp_u64mat2x2; + typedef mat<2, 3, uint64, lowp> lowp_u64mat2x3; + typedef mat<2, 4, uint64, lowp> lowp_u64mat2x4; + typedef mat<3, 2, uint64, lowp> lowp_u64mat3x2; + typedef mat<3, 3, uint64, lowp> lowp_u64mat3x3; + typedef mat<3, 4, uint64, lowp> lowp_u64mat3x4; + typedef mat<4, 2, uint64, lowp> lowp_u64mat4x2; + typedef mat<4, 3, uint64, lowp> lowp_u64mat4x3; + typedef mat<4, 4, uint64, lowp> lowp_u64mat4x4; + + typedef mat<2, 2, uint64, mediump> mediump_u64mat2x2; + typedef mat<2, 3, uint64, mediump> mediump_u64mat2x3; + typedef mat<2, 4, uint64, mediump> mediump_u64mat2x4; + typedef mat<3, 2, uint64, mediump> mediump_u64mat3x2; + typedef mat<3, 3, uint64, mediump> mediump_u64mat3x3; + typedef mat<3, 4, uint64, mediump> mediump_u64mat3x4; + typedef mat<4, 2, uint64, mediump> mediump_u64mat4x2; + typedef mat<4, 3, uint64, mediump> mediump_u64mat4x3; + typedef mat<4, 4, uint64, mediump> mediump_u64mat4x4; + + typedef mat<2, 2, uint64, highp> highp_u64mat2x2; + typedef mat<2, 3, uint64, highp> highp_u64mat2x3; + typedef mat<2, 4, uint64, highp> highp_u64mat2x4; + typedef mat<3, 2, uint64, highp> highp_u64mat3x2; + typedef mat<3, 3, uint64, highp> highp_u64mat3x3; + typedef mat<3, 4, uint64, highp> highp_u64mat3x4; + typedef mat<4, 2, uint64, highp> highp_u64mat4x2; + typedef mat<4, 3, uint64, highp> highp_u64mat4x3; + typedef mat<4, 4, uint64, highp> highp_u64mat4x4; + + typedef mat<2, 2, uint64, defaultp> u64mat2x2; + typedef mat<3, 2, uint64, defaultp> u64mat3x2; + typedef mat<4, 2, uint64, defaultp> u64mat4x2; + typedef mat<2, 3, uint64, defaultp> u64mat2x3; + typedef mat<3, 3, uint64, defaultp> u64mat3x3; + typedef mat<4, 3, uint64, defaultp> u64mat4x3; + typedef mat<2, 4, uint64, defaultp> u64mat2x4; + typedef mat<3, 4, uint64, defaultp> u64mat3x4; + typedef mat<4, 4, uint64, defaultp> u64mat4x4; + + // Quaternion + + typedef qua lowp_quat; + typedef qua mediump_quat; + typedef qua highp_quat; + typedef qua quat; + + typedef qua lowp_fquat; + typedef qua mediump_fquat; + typedef qua highp_fquat; + typedef qua fquat; + + typedef qua lowp_f32quat; + typedef qua mediump_f32quat; + typedef qua highp_f32quat; + typedef qua f32quat; + + typedef qua lowp_dquat; + typedef qua mediump_dquat; + typedef qua highp_dquat; + typedef qua dquat; + + typedef qua lowp_f64quat; + typedef qua mediump_f64quat; + typedef qua highp_f64quat; + typedef qua f64quat; +}//namespace glm + + diff --git a/vendor/glm/glm/geometric.hpp b/vendor/glm/glm/geometric.hpp new file mode 100644 index 0000000..c068a3c --- /dev/null +++ b/vendor/glm/glm/geometric.hpp @@ -0,0 +1,116 @@ +/// @ref core +/// @file glm/geometric.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions +/// +/// @defgroup core_func_geometric Geometric functions +/// @ingroup core +/// +/// These operate on vectors as vectors, not component-wise. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_func_geometric + /// @{ + + /// Returns the length of x, i.e., sqrt(x * x). + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL length man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL T length(vec const& x); + + /// Returns the distance betwwen p0 and p1, i.e., length(p0 - p1). + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL distance man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL T distance(vec const& p0, vec const& p1); + + /// Returns the dot product of x and y, i.e., result = x * y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL dot man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL T dot(vec const& x, vec const& y); + + /// Returns the cross product of x and y. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL cross man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec<3, T, Q> cross(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + /// Returns a vector in the same direction as x but with length of 1. + /// According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefined and generate an error. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL normalize man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec normalize(vec const& x); + + /// If dot(Nref, I) < 0.0, return N, otherwise, return -N. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL faceforward man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec faceforward( + vec const& N, + vec const& I, + vec const& Nref); + + /// For the incident vector I and surface orientation N, + /// returns the reflection direction : result = I - 2.0 * dot(N, I) * N. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL reflect man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec reflect( + vec const& I, + vec const& N); + + /// For the incident vector I and surface normal N, + /// and the ratio of indices of refraction eta, + /// return the refraction vector. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Floating-point scalar types. + /// + /// @see GLSL refract man page + /// @see GLSL 4.20.8 specification, section 8.5 Geometric Functions + template + GLM_FUNC_DECL vec refract( + vec const& I, + vec const& N, + T eta); + + /// @} +}//namespace glm + +#include "detail/func_geometric.inl" diff --git a/vendor/glm/glm/glm.hpp b/vendor/glm/glm/glm.hpp new file mode 100644 index 0000000..8b61064 --- /dev/null +++ b/vendor/glm/glm/glm.hpp @@ -0,0 +1,136 @@ +/// @ref core +/// @file glm/glm.hpp +/// +/// @defgroup core Core features +/// +/// @brief Features that implement in C++ the GLSL specification as closely as possible. +/// +/// The GLM core consists of C++ types that mirror GLSL types and +/// C++ functions that mirror the GLSL functions. +/// +/// The best documentation for GLM Core is the current GLSL specification, +/// version 4.2 +/// (pdf file). +/// +/// GLM core functionalities require to be included to be used. +/// +/// +/// @defgroup core_vector Vector types +/// +/// Vector types of two to four components with an exhaustive set of operators. +/// +/// @ingroup core +/// +/// +/// @defgroup core_vector_precision Vector types with precision qualifiers +/// +/// @brief Vector types with precision qualifiers which may result in various precision in term of ULPs +/// +/// GLSL allows defining qualifiers for particular variables. +/// With OpenGL's GLSL, these qualifiers have no effect; they are there for compatibility, +/// with OpenGL ES's GLSL, these qualifiers do have an effect. +/// +/// C++ has no language equivalent to qualifier qualifiers. So GLM provides the next-best thing: +/// a number of typedefs that use a particular qualifier. +/// +/// None of these types make any guarantees about the actual qualifier used. +/// +/// @ingroup core +/// +/// +/// @defgroup core_matrix Matrix types +/// +/// Matrix types of with C columns and R rows where C and R are values between 2 to 4 included. +/// These types have exhaustive sets of operators. +/// +/// @ingroup core +/// +/// +/// @defgroup core_matrix_precision Matrix types with precision qualifiers +/// +/// @brief Matrix types with precision qualifiers which may result in various precision in term of ULPs +/// +/// GLSL allows defining qualifiers for particular variables. +/// With OpenGL's GLSL, these qualifiers have no effect; they are there for compatibility, +/// with OpenGL ES's GLSL, these qualifiers do have an effect. +/// +/// C++ has no language equivalent to qualifier qualifiers. So GLM provides the next-best thing: +/// a number of typedefs that use a particular qualifier. +/// +/// None of these types make any guarantees about the actual qualifier used. +/// +/// @ingroup core +/// +/// +/// @defgroup ext Stable extensions +/// +/// @brief Additional features not specified by GLSL specification. +/// +/// EXT extensions are fully tested and documented. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions at once by +/// including . Otherwise, each extension needs to be included a specific file. +/// +/// +/// @defgroup gtc Recommended extensions +/// +/// @brief Additional features not specified by GLSL specification. +/// +/// GTC extensions aim to be stable with tests and documentation. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions at once by +/// including . Otherwise, each extension needs to be included a specific file. +/// +/// +/// @defgroup gtx Experimental extensions +/// +/// @brief Experimental features not specified by GLSL specification. +/// +/// Experimental extensions are useful functions and types, but the development of +/// their API and functionality is not necessarily stable. They can change +/// substantially between versions. Backwards compatibility is not much of an issue +/// for them. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions +/// at once by including . Otherwise, each extension needs to be +/// included a specific file. +/// +/// @mainpage OpenGL Mathematics (GLM) +/// - Website: glm.g-truc.net +/// - GLM API documentation +/// - GLM Manual + +#include "detail/_fixes.hpp" + +#include "detail/setup.hpp" + +#pragma once + +#include +#include +#include +#include +#include +#include "fwd.hpp" + +#include "vec2.hpp" +#include "vec3.hpp" +#include "vec4.hpp" +#include "mat2x2.hpp" +#include "mat2x3.hpp" +#include "mat2x4.hpp" +#include "mat3x2.hpp" +#include "mat3x3.hpp" +#include "mat3x4.hpp" +#include "mat4x2.hpp" +#include "mat4x3.hpp" +#include "mat4x4.hpp" + +#include "trigonometric.hpp" +#include "exponential.hpp" +#include "common.hpp" +#include "packing.hpp" +#include "geometric.hpp" +#include "matrix.hpp" +#include "vector_relational.hpp" +#include "integer.hpp" diff --git a/vendor/glm/glm/gtc/bitfield.hpp b/vendor/glm/glm/gtc/bitfield.hpp new file mode 100644 index 0000000..084fbe7 --- /dev/null +++ b/vendor/glm/glm/gtc/bitfield.hpp @@ -0,0 +1,266 @@ +/// @ref gtc_bitfield +/// @file glm/gtc/bitfield.hpp +/// +/// @see core (dependence) +/// @see gtc_bitfield (dependence) +/// +/// @defgroup gtc_bitfield GLM_GTC_bitfield +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Allow to perform bit operations on integer values + +#include "../detail/setup.hpp" + +#pragma once + +// Dependencies +#include "../ext/scalar_int_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "type_precision.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_bitfield extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_bitfield + /// @{ + + /// Build a mask of 'count' bits + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType mask(genIUType Bits); + + /// Build a mask of 'count' bits + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec mask(vec const& v); + + /// Rotate all bits to the right. All the bits dropped in the right side are inserted back on the left side. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldRotateRight(genIUType In, int Shift); + + /// Rotate all bits to the right. All the bits dropped in the right side are inserted back on the left side. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldRotateRight(vec const& In, int Shift); + + /// Rotate all bits to the left. All the bits dropped in the left side are inserted back on the right side. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldRotateLeft(genIUType In, int Shift); + + /// Rotate all bits to the left. All the bits dropped in the left side are inserted back on the right side. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldRotateLeft(vec const& In, int Shift); + + /// Set to 1 a range of bits. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount); + + /// Set to 1 a range of bits. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldFillOne(vec const& Value, int FirstBit, int BitCount); + + /// Set to 0 a range of bits. + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount); + + /// Set to 0 a range of bits. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Signed and unsigned integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_bitfield + template + GLM_FUNC_DECL vec bitfieldFillZero(vec const& Value, int FirstBit, int BitCount); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int16 bitfieldInterleave(int8 x, int8 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint16 bitfieldInterleave(uint8 x, uint8 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of v.x followed by the first bit of v.y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint16 bitfieldInterleave(u8vec2 const& v); + + /// Deinterleaves the bits of x. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL glm::u8vec2 bitfieldDeinterleave(glm::uint16 x); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int16 x, int16 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint16 x, uint16 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of v.x followed by the first bit of v.y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(u16vec2 const& v); + + /// Deinterleaves the bits of x. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL glm::u16vec2 bitfieldDeinterleave(glm::uint32 x); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int32 x, int32 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint32 x, uint32 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of v.x followed by the first bit of v.y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(u32vec2 const& v); + + /// Deinterleaves the bits of x. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL glm::u32vec2 bitfieldDeinterleave(glm::uint64 x); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int8 x, int8 y, int8 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int16 x, int16 y, int16 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int32 x, int32 y, int32 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint32 x, uint32 y, uint32 z); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int8 x, int8 y, int8 z, int8 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z, uint8 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int16 x, int16 y, int16 z, int16 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z, uint16 w); + + /// @} +} //namespace glm + +#include "bitfield.inl" diff --git a/vendor/glm/glm/gtc/bitfield.inl b/vendor/glm/glm/gtc/bitfield.inl new file mode 100644 index 0000000..06cf188 --- /dev/null +++ b/vendor/glm/glm/gtc/bitfield.inl @@ -0,0 +1,626 @@ +/// @ref gtc_bitfield + +#include "../simd/integer.h" + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y); + + template + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z); + + template + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z, PARAM w); + + template<> + GLM_FUNC_QUALIFIER glm::uint16 bitfieldInterleave(glm::uint8 x, glm::uint8 y) + { + glm::uint16 REG1(x); + glm::uint16 REG2(y); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x0F0F); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x0F0F); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x3333); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x3333); + + REG1 = ((REG1 << 1) | REG1) & static_cast(0x5555); + REG2 = ((REG2 << 1) | REG2) & static_cast(0x5555); + + return REG1 | static_cast(REG2 << 1); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint16 x, glm::uint16 y) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0x00FF00FF); + REG2 = ((REG2 << 8) | REG2) & static_cast(0x00FF00FF); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x0F0F0F0F); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x0F0F0F0F); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x33333333); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x33333333); + + REG1 = ((REG1 << 1) | REG1) & static_cast(0x55555555); + REG2 = ((REG2 << 1) | REG2) & static_cast(0x55555555); + + return REG1 | (REG2 << 1); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0x0000FFFF0000FFFFull); + REG2 = ((REG2 << 16) | REG2) & static_cast(0x0000FFFF0000FFFFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0x00FF00FF00FF00FFull); + REG2 = ((REG2 << 8) | REG2) & static_cast(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x3333333333333333ull); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x3333333333333333ull); + + REG1 = ((REG1 << 1) | REG1) & static_cast(0x5555555555555555ull); + REG2 = ((REG2 << 1) | REG2) & static_cast(0x5555555555555555ull); + + return REG1 | (REG2 << 1); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + glm::uint32 REG3(z); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0xFF0000FFu); + REG2 = ((REG2 << 16) | REG2) & static_cast(0xFF0000FFu); + REG3 = ((REG3 << 16) | REG3) & static_cast(0xFF0000FFu); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0x0F00F00Fu); + REG2 = ((REG2 << 8) | REG2) & static_cast(0x0F00F00Fu); + REG3 = ((REG3 << 8) | REG3) & static_cast(0x0F00F00Fu); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0xC30C30C3u); + REG2 = ((REG2 << 4) | REG2) & static_cast(0xC30C30C3u); + REG3 = ((REG3 << 4) | REG3) & static_cast(0xC30C30C3u); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x49249249u); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x49249249u); + REG3 = ((REG3 << 2) | REG3) & static_cast(0x49249249u); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + + REG1 = ((REG1 << 32) | REG1) & static_cast(0xFFFF00000000FFFFull); + REG2 = ((REG2 << 32) | REG2) & static_cast(0xFFFF00000000FFFFull); + REG3 = ((REG3 << 32) | REG3) & static_cast(0xFFFF00000000FFFFull); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0x00FF0000FF0000FFull); + REG2 = ((REG2 << 16) | REG2) & static_cast(0x00FF0000FF0000FFull); + REG3 = ((REG3 << 16) | REG3) & static_cast(0x00FF0000FF0000FFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0xF00F00F00F00F00Full); + REG2 = ((REG2 << 8) | REG2) & static_cast(0xF00F00F00F00F00Full); + REG3 = ((REG3 << 8) | REG3) & static_cast(0xF00F00F00F00F00Full); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x30C30C30C30C30C3ull); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x30C30C30C30C30C3ull); + REG3 = ((REG3 << 4) | REG3) & static_cast(0x30C30C30C30C30C3ull); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x9249249249249249ull); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x9249249249249249ull); + REG3 = ((REG3 << 2) | REG3) & static_cast(0x9249249249249249ull); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y, glm::uint32 z) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + + REG1 = ((REG1 << 32) | REG1) & static_cast(0xFFFF00000000FFFFull); + REG2 = ((REG2 << 32) | REG2) & static_cast(0xFFFF00000000FFFFull); + REG3 = ((REG3 << 32) | REG3) & static_cast(0xFFFF00000000FFFFull); + + REG1 = ((REG1 << 16) | REG1) & static_cast(0x00FF0000FF0000FFull); + REG2 = ((REG2 << 16) | REG2) & static_cast(0x00FF0000FF0000FFull); + REG3 = ((REG3 << 16) | REG3) & static_cast(0x00FF0000FF0000FFull); + + REG1 = ((REG1 << 8) | REG1) & static_cast(0xF00F00F00F00F00Full); + REG2 = ((REG2 << 8) | REG2) & static_cast(0xF00F00F00F00F00Full); + REG3 = ((REG3 << 8) | REG3) & static_cast(0xF00F00F00F00F00Full); + + REG1 = ((REG1 << 4) | REG1) & static_cast(0x30C30C30C30C30C3ull); + REG2 = ((REG2 << 4) | REG2) & static_cast(0x30C30C30C30C30C3ull); + REG3 = ((REG3 << 4) | REG3) & static_cast(0x30C30C30C30C30C3ull); + + REG1 = ((REG1 << 2) | REG1) & static_cast(0x9249249249249249ull); + REG2 = ((REG2 << 2) | REG2) & static_cast(0x9249249249249249ull); + REG3 = ((REG3 << 2) | REG3) & static_cast(0x9249249249249249ull); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z, glm::uint8 w) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + glm::uint32 REG3(z); + glm::uint32 REG4(w); + + REG1 = ((REG1 << 12) | REG1) & static_cast(0x000F000Fu); + REG2 = ((REG2 << 12) | REG2) & static_cast(0x000F000Fu); + REG3 = ((REG3 << 12) | REG3) & static_cast(0x000F000Fu); + REG4 = ((REG4 << 12) | REG4) & static_cast(0x000F000Fu); + + REG1 = ((REG1 << 6) | REG1) & static_cast(0x03030303u); + REG2 = ((REG2 << 6) | REG2) & static_cast(0x03030303u); + REG3 = ((REG3 << 6) | REG3) & static_cast(0x03030303u); + REG4 = ((REG4 << 6) | REG4) & static_cast(0x03030303u); + + REG1 = ((REG1 << 3) | REG1) & static_cast(0x11111111u); + REG2 = ((REG2 << 3) | REG2) & static_cast(0x11111111u); + REG3 = ((REG3 << 3) | REG3) & static_cast(0x11111111u); + REG4 = ((REG4 << 3) | REG4) & static_cast(0x11111111u); + + return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3); + } + + template<> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z, glm::uint16 w) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + glm::uint64 REG4(w); + + REG1 = ((REG1 << 24) | REG1) & static_cast(0x000000FF000000FFull); + REG2 = ((REG2 << 24) | REG2) & static_cast(0x000000FF000000FFull); + REG3 = ((REG3 << 24) | REG3) & static_cast(0x000000FF000000FFull); + REG4 = ((REG4 << 24) | REG4) & static_cast(0x000000FF000000FFull); + + REG1 = ((REG1 << 12) | REG1) & static_cast(0x000F000F000F000Full); + REG2 = ((REG2 << 12) | REG2) & static_cast(0x000F000F000F000Full); + REG3 = ((REG3 << 12) | REG3) & static_cast(0x000F000F000F000Full); + REG4 = ((REG4 << 12) | REG4) & static_cast(0x000F000F000F000Full); + + REG1 = ((REG1 << 6) | REG1) & static_cast(0x0303030303030303ull); + REG2 = ((REG2 << 6) | REG2) & static_cast(0x0303030303030303ull); + REG3 = ((REG3 << 6) | REG3) & static_cast(0x0303030303030303ull); + REG4 = ((REG4 << 6) | REG4) & static_cast(0x0303030303030303ull); + + REG1 = ((REG1 << 3) | REG1) & static_cast(0x1111111111111111ull); + REG2 = ((REG2 << 3) | REG2) & static_cast(0x1111111111111111ull); + REG3 = ((REG3 << 3) | REG3) & static_cast(0x1111111111111111ull); + REG4 = ((REG4 << 3) | REG4) & static_cast(0x1111111111111111ull); + + return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3); + } +}//namespace detail + + template + GLM_FUNC_QUALIFIER genIUType mask(genIUType Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'mask' accepts only integer values"); + + return Bits >= sizeof(genIUType) * 8 ? ~static_cast(0) : (static_cast(1) << Bits) - static_cast(1); + } + + template + GLM_FUNC_QUALIFIER vec mask(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'mask' accepts only integer values"); + + return detail::functor1::call(mask, v); + } + + template + GLM_FUNC_QUALIFIER genIType bitfieldRotateRight(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast(sizeof(genIType) * 8); + return (In << static_cast(Shift)) | (In >> static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldRotateRight(vec const& In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast(sizeof(T) * 8); + return (In << static_cast(Shift)) | (In >> static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER genIType bitfieldRotateLeft(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast(sizeof(genIType) * 8); + return (In >> static_cast(Shift)) | (In << static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldRotateLeft(vec const& In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast(sizeof(T) * 8); + return (In >> static_cast(Shift)) | (In << static_cast(BitSize - Shift)); + } + + template + GLM_FUNC_QUALIFIER genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount) + { + return Value | static_cast(mask(BitCount) << FirstBit); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldFillOne(vec const& Value, int FirstBit, int BitCount) + { + return Value | static_cast(mask(BitCount) << FirstBit); + } + + template + GLM_FUNC_QUALIFIER genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount) + { + return Value & static_cast(~(mask(BitCount) << FirstBit)); + } + + template + GLM_FUNC_QUALIFIER vec bitfieldFillZero(vec const& Value, int FirstBit, int BitCount) + { + return Value & static_cast(~(mask(BitCount) << FirstBit)); + } + + GLM_FUNC_QUALIFIER int16 bitfieldInterleave(int8 x, int8 y) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y; + + union sign16 + { + int16 i; + uint16 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(uint8 x, uint8 y) + { + return detail::bitfieldInterleave(x, y); + } + + GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(u8vec2 const& v) + { + return detail::bitfieldInterleave(v.x, v.y); + } + + GLM_FUNC_QUALIFIER u8vec2 bitfieldDeinterleave(glm::uint16 x) + { + uint16 REG1(x); + uint16 REG2(x >>= 1); + + REG1 = REG1 & static_cast(0x5555); + REG2 = REG2 & static_cast(0x5555); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x3333); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x3333); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0xFFFF); + REG2 = ((REG2 >> 8) | REG2) & static_cast(0xFFFF); + + return glm::u8vec2(REG1, REG2); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int16 x, int16 y) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint16 x, uint16 y) + { + return detail::bitfieldInterleave(x, y); + } + + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(u16vec2 const& v) + { + return detail::bitfieldInterleave(v.x, v.y); + } + + GLM_FUNC_QUALIFIER glm::u16vec2 bitfieldDeinterleave(glm::uint32 x) + { + glm::uint32 REG1(x); + glm::uint32 REG2(x >>= 1); + + REG1 = REG1 & static_cast(0x55555555); + REG2 = REG2 & static_cast(0x55555555); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x33333333); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x33333333); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F0F0F); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F0F0F); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF00FF); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF00FF); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0x0000FFFF); + REG2 = ((REG2 >> 8) | REG2) & static_cast(0x0000FFFF); + + return glm::u16vec2(REG1, REG2); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y) + { + union sign32 + { + int32 i; + uint32 u; + } sign_x, sign_y; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y) + { + return detail::bitfieldInterleave(x, y); + } + + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(u32vec2 const& v) + { + return detail::bitfieldInterleave(v.x, v.y); + } + + GLM_FUNC_QUALIFIER glm::u32vec2 bitfieldDeinterleave(glm::uint64 x) + { + glm::uint64 REG1(x); + glm::uint64 REG2(x >>= 1); + + REG1 = REG1 & static_cast(0x5555555555555555ull); + REG2 = REG2 & static_cast(0x5555555555555555ull); + + REG1 = ((REG1 >> 1) | REG1) & static_cast(0x3333333333333333ull); + REG2 = ((REG2 >> 1) | REG2) & static_cast(0x3333333333333333ull); + + REG1 = ((REG1 >> 2) | REG1) & static_cast(0x0F0F0F0F0F0F0F0Full); + REG2 = ((REG2 >> 2) | REG2) & static_cast(0x0F0F0F0F0F0F0F0Full); + + REG1 = ((REG1 >> 4) | REG1) & static_cast(0x00FF00FF00FF00FFull); + REG2 = ((REG2 >> 4) | REG2) & static_cast(0x00FF00FF00FF00FFull); + + REG1 = ((REG1 >> 8) | REG1) & static_cast(0x0000FFFF0000FFFFull); + REG2 = ((REG2 >> 8) | REG2) & static_cast(0x0000FFFF0000FFFFull); + + REG1 = ((REG1 >> 16) | REG1) & static_cast(0x00000000FFFFFFFFull); + REG2 = ((REG2 >> 16) | REG2) & static_cast(0x00000000FFFFFFFFull); + + return glm::u32vec2(REG1, REG2); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y, sign_z; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z) + { + return detail::bitfieldInterleave(x, y, z); + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(u8vec3 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y, sign_z; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z) + { + return detail::bitfieldInterleave(x, y, z); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u16vec3 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y, int32 z) + { + union sign16 + { + int32 i; + uint32 u; + } sign_x, sign_y, sign_z; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y, uint32 z) + { + return detail::bitfieldInterleave(x, y, z); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u32vec3 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z, int8 w) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y, sign_z, sign_w; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + sign_w.i = w; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z, uint8 w) + { + return detail::bitfieldInterleave(x, y, z, w); + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(u8vec4 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z, v.w); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z, int16 w) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y, sign_z, sign_w; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + sign_w.i = w; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z, uint16 w) + { + return detail::bitfieldInterleave(x, y, z, w); + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(u16vec4 const& v) + { + return detail::bitfieldInterleave(v.x, v.y, v.z, v.w); + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/color_space.hpp b/vendor/glm/glm/gtc/color_space.hpp new file mode 100644 index 0000000..cffd9f0 --- /dev/null +++ b/vendor/glm/glm/gtc/color_space.hpp @@ -0,0 +1,56 @@ +/// @ref gtc_color_space +/// @file glm/gtc/color_space.hpp +/// +/// @see core (dependence) +/// @see gtc_color_space (dependence) +/// +/// @defgroup gtc_color_space GLM_GTC_color_space +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../exponential.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_color_space extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_color_space + /// @{ + + /// Convert a linear color to sRGB color using a standard gamma correction. + /// IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertLinearToSRGB(vec const& ColorLinear); + + /// Convert a linear color to sRGB color using a custom gamma correction. + /// IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertLinearToSRGB(vec const& ColorLinear, T Gamma); + + /// Convert a sRGB color to linear color using a standard gamma correction. + /// IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertSRGBToLinear(vec const& ColorSRGB); + + /// Convert a sRGB color to linear color using a custom gamma correction. + // IEC 61966-2-1:1999 / Rec. 709 specification https://www.w3.org/Graphics/Color/srgb + template + GLM_FUNC_DECL vec convertSRGBToLinear(vec const& ColorSRGB, T Gamma); + + /// @} +} //namespace glm + +#include "color_space.inl" diff --git a/vendor/glm/glm/gtc/color_space.inl b/vendor/glm/glm/gtc/color_space.inl new file mode 100644 index 0000000..2a90004 --- /dev/null +++ b/vendor/glm/glm/gtc/color_space.inl @@ -0,0 +1,84 @@ +/// @ref gtc_color_space + +namespace glm{ +namespace detail +{ + template + struct compute_rgbToSrgb + { + GLM_FUNC_QUALIFIER static vec call(vec const& ColorRGB, T GammaCorrection) + { + vec const ClampedColor(clamp(ColorRGB, static_cast(0), static_cast(1))); + + return mix( + pow(ClampedColor, vec(GammaCorrection)) * static_cast(1.055) - static_cast(0.055), + ClampedColor * static_cast(12.92), + lessThan(ClampedColor, vec(static_cast(0.0031308)))); + } + }; + + template + struct compute_rgbToSrgb<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(vec<4, T, Q> const& ColorRGB, T GammaCorrection) + { + return vec<4, T, Q>(compute_rgbToSrgb<3, T, Q>::call(vec<3, T, Q>(ColorRGB), GammaCorrection), ColorRGB.w); + } + }; + + template + struct compute_srgbToRgb + { + GLM_FUNC_QUALIFIER static vec call(vec const& ColorSRGB, T Gamma) + { + return mix( + pow((ColorSRGB + static_cast(0.055)) * static_cast(0.94786729857819905213270142180095), vec(Gamma)), + ColorSRGB * static_cast(0.07739938080495356037151702786378), + lessThanEqual(ColorSRGB, vec(static_cast(0.04045)))); + } + }; + + template + struct compute_srgbToRgb<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, T, Q> call(vec<4, T, Q> const& ColorSRGB, T Gamma) + { + return vec<4, T, Q>(compute_srgbToRgb<3, T, Q>::call(vec<3, T, Q>(ColorSRGB), Gamma), ColorSRGB.w); + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER vec convertLinearToSRGB(vec const& ColorLinear) + { + return detail::compute_rgbToSrgb::call(ColorLinear, static_cast(0.41666)); + } + + // Based on Ian Taylor http://chilliant.blogspot.fr/2012/08/srgb-approximations-for-hlsl.html + template<> + GLM_FUNC_QUALIFIER vec<3, float, lowp> convertLinearToSRGB(vec<3, float, lowp> const& ColorLinear) + { + vec<3, float, lowp> S1 = sqrt(ColorLinear); + vec<3, float, lowp> S2 = sqrt(S1); + vec<3, float, lowp> S3 = sqrt(S2); + return 0.662002687f * S1 + 0.684122060f * S2 - 0.323583601f * S3 - 0.0225411470f * ColorLinear; + } + + template + GLM_FUNC_QUALIFIER vec convertLinearToSRGB(vec const& ColorLinear, T Gamma) + { + return detail::compute_rgbToSrgb::call(ColorLinear, static_cast(1) / Gamma); + } + + template + GLM_FUNC_QUALIFIER vec convertSRGBToLinear(vec const& ColorSRGB) + { + return detail::compute_srgbToRgb::call(ColorSRGB, static_cast(2.4)); + } + + template + GLM_FUNC_QUALIFIER vec convertSRGBToLinear(vec const& ColorSRGB, T Gamma) + { + return detail::compute_srgbToRgb::call(ColorSRGB, Gamma); + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/constants.hpp b/vendor/glm/glm/gtc/constants.hpp new file mode 100644 index 0000000..99f2128 --- /dev/null +++ b/vendor/glm/glm/gtc/constants.hpp @@ -0,0 +1,165 @@ +/// @ref gtc_constants +/// @file glm/gtc/constants.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_constants GLM_GTC_constants +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Provide a list of constants and precomputed useful values. + +#pragma once + +// Dependencies +#include "../ext/scalar_constants.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_constants extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_constants + /// @{ + + /// Return 0. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType zero(); + + /// Return 1. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one(); + + /// Return pi * 2. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_pi(); + + /// Return square root of pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_pi(); + + /// Return pi / 2. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType half_pi(); + + /// Return pi / 2 * 3. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType three_over_two_pi(); + + /// Return pi / 4. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType quarter_pi(); + + /// Return 1 / pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_pi(); + + /// Return 1 / (pi * 2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_two_pi(); + + /// Return 2 / pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_over_pi(); + + /// Return 4 / pi. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType four_over_pi(); + + /// Return 2 / sqrt(pi). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_over_root_pi(); + + /// Return 1 / sqrt(2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType one_over_root_two(); + + /// Return sqrt(pi / 2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_half_pi(); + + /// Return sqrt(2 * pi). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_two_pi(); + + /// Return sqrt(ln(4)). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_ln_four(); + + /// Return e constant. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType e(); + + /// Return Euler's constant. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType euler(); + + /// Return sqrt(2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_two(); + + /// Return sqrt(3). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_three(); + + /// Return sqrt(5). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType root_five(); + + /// Return ln(2). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_two(); + + /// Return ln(10). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_ten(); + + /// Return ln(ln(2)). + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType ln_ln_two(); + + /// Return 1 / 3. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType third(); + + /// Return 2 / 3. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType two_thirds(); + + /// Return the golden ratio constant. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType golden_ratio(); + + /// @} +} //namespace glm + +#include "constants.inl" diff --git a/vendor/glm/glm/gtc/constants.inl b/vendor/glm/glm/gtc/constants.inl new file mode 100644 index 0000000..bb98c6b --- /dev/null +++ b/vendor/glm/glm/gtc/constants.inl @@ -0,0 +1,167 @@ +/// @ref gtc_constants + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType zero() + { + return genType(0); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one() + { + return genType(1); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_pi() + { + return genType(6.28318530717958647692528676655900576); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_pi() + { + return genType(1.772453850905516027); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType half_pi() + { + return genType(1.57079632679489661923132169163975144); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType three_over_two_pi() + { + return genType(4.71238898038468985769396507491925432); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType quarter_pi() + { + return genType(0.785398163397448309615660845819875721); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_pi() + { + return genType(0.318309886183790671537767526745028724); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_two_pi() + { + return genType(0.159154943091895335768883763372514362); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_over_pi() + { + return genType(0.636619772367581343075535053490057448); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType four_over_pi() + { + return genType(1.273239544735162686151070106980114898); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_over_root_pi() + { + return genType(1.12837916709551257389615890312154517); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType one_over_root_two() + { + return genType(0.707106781186547524400844362104849039); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_half_pi() + { + return genType(1.253314137315500251); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_two_pi() + { + return genType(2.506628274631000502); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_ln_four() + { + return genType(1.17741002251547469); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType e() + { + return genType(2.71828182845904523536); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType euler() + { + return genType(0.577215664901532860606); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_two() + { + return genType(1.41421356237309504880168872420969808); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_three() + { + return genType(1.73205080756887729352744634150587236); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType root_five() + { + return genType(2.23606797749978969640917366873127623); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_two() + { + return genType(0.693147180559945309417232121458176568); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_ten() + { + return genType(2.30258509299404568401799145468436421); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType ln_ln_two() + { + return genType(-0.3665129205816643); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType third() + { + return genType(0.3333333333333333333333333333333333333333); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType two_thirds() + { + return genType(0.666666666666666666666666666666666666667); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType golden_ratio() + { + return genType(1.61803398874989484820458683436563811); + } + +} //namespace glm diff --git a/vendor/glm/glm/gtc/epsilon.hpp b/vendor/glm/glm/gtc/epsilon.hpp new file mode 100644 index 0000000..640439b --- /dev/null +++ b/vendor/glm/glm/gtc/epsilon.hpp @@ -0,0 +1,60 @@ +/// @ref gtc_epsilon +/// @file glm/gtc/epsilon.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_epsilon GLM_GTC_epsilon +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Comparison functions for a user defined epsilon values. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_epsilon extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_epsilon + /// @{ + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL vec epsilonEqual(vec const& x, vec const& y, T const& epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL bool epsilonEqual(genType const& x, genType const& y, genType const& epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is not satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL vec epsilonNotEqual(vec const& x, vec const& y, T const& epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL bool epsilonNotEqual(genType const& x, genType const& y, genType const& epsilon); + + /// @} +}//namespace glm + +#include "epsilon.inl" diff --git a/vendor/glm/glm/gtc/epsilon.inl b/vendor/glm/glm/gtc/epsilon.inl new file mode 100644 index 0000000..508b9f8 --- /dev/null +++ b/vendor/glm/glm/gtc/epsilon.inl @@ -0,0 +1,80 @@ +/// @ref gtc_epsilon + +// Dependency: +#include "../vector_relational.hpp" +#include "../common.hpp" + +namespace glm +{ + template<> + GLM_FUNC_QUALIFIER bool epsilonEqual + ( + float const& x, + float const& y, + float const& epsilon + ) + { + return abs(x - y) < epsilon; + } + + template<> + GLM_FUNC_QUALIFIER bool epsilonEqual + ( + double const& x, + double const& y, + double const& epsilon + ) + { + return abs(x - y) < epsilon; + } + + template + GLM_FUNC_QUALIFIER vec epsilonEqual(vec const& x, vec const& y, T const& epsilon) + { + return lessThan(abs(x - y), vec(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec epsilonEqual(vec const& x, vec const& y, vec const& epsilon) + { + return lessThan(abs(x - y), vec(epsilon)); + } + + template<> + GLM_FUNC_QUALIFIER bool epsilonNotEqual(float const& x, float const& y, float const& epsilon) + { + return abs(x - y) >= epsilon; + } + + template<> + GLM_FUNC_QUALIFIER bool epsilonNotEqual(double const& x, double const& y, double const& epsilon) + { + return abs(x - y) >= epsilon; + } + + template + GLM_FUNC_QUALIFIER vec epsilonNotEqual(vec const& x, vec const& y, T const& epsilon) + { + return greaterThanEqual(abs(x - y), vec(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec epsilonNotEqual(vec const& x, vec const& y, vec const& epsilon) + { + return greaterThanEqual(abs(x - y), vec(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> epsilonEqual(qua const& x, qua const& y, T const& epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return lessThan(abs(v), vec<4, T, Q>(epsilon)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> epsilonNotEqual(qua const& x, qua const& y, T const& epsilon) + { + vec<4, T, Q> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return greaterThanEqual(abs(v), vec<4, T, Q>(epsilon)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/integer.hpp b/vendor/glm/glm/gtc/integer.hpp new file mode 100644 index 0000000..64ce10b --- /dev/null +++ b/vendor/glm/glm/gtc/integer.hpp @@ -0,0 +1,65 @@ +/// @ref gtc_integer +/// @file glm/gtc/integer.hpp +/// +/// @see core (dependence) +/// @see gtc_integer (dependence) +/// +/// @defgroup gtc_integer GLM_GTC_integer +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// @brief Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../common.hpp" +#include "../integer.hpp" +#include "../exponential.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_integer + /// @{ + + /// Returns the log2 of x for integer values. Usefull to compute mipmap count from the texture size. + /// @see gtc_integer + template + GLM_FUNC_DECL genIUType log2(genIUType x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// + /// @param x The values of the argument must be greater or equal to zero. + /// @tparam T floating point scalar types. + /// + /// @see GLSL round man page + /// @see gtc_integer + template + GLM_FUNC_DECL vec iround(vec const& x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// + /// @param x The values of the argument must be greater or equal to zero. + /// @tparam T floating point scalar types. + /// + /// @see GLSL round man page + /// @see gtc_integer + template + GLM_FUNC_DECL vec uround(vec const& x); + + /// @} +} //namespace glm + +#include "integer.inl" diff --git a/vendor/glm/glm/gtc/integer.inl b/vendor/glm/glm/gtc/integer.inl new file mode 100644 index 0000000..f0a8b4f --- /dev/null +++ b/vendor/glm/glm/gtc/integer.inl @@ -0,0 +1,68 @@ +/// @ref gtc_integer + +namespace glm{ +namespace detail +{ + template + struct compute_log2 + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + //Equivalent to return findMSB(vec); but save one function call in ASM with VC + //return findMSB(vec); + return vec(detail::compute_findMSB_vec::call(v)); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + struct compute_log2<4, int, Q, false, Aligned> + { + GLM_FUNC_QUALIFIER static vec<4, int, Q> call(vec<4, int, Q> const& v) + { + vec<4, int, Q> Result; + _BitScanReverse(reinterpret_cast(&Result.x), v.x); + _BitScanReverse(reinterpret_cast(&Result.y), v.y); + _BitScanReverse(reinterpret_cast(&Result.z), v.z); + _BitScanReverse(reinterpret_cast(&Result.w), v.w); + return Result; + } + }; +# endif//GLM_HAS_BITSCAN_WINDOWS +}//namespace detail + template + GLM_FUNC_QUALIFIER int iround(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'iround' only accept floating-point inputs"); + assert(static_cast(0.0) <= x); + + return static_cast(x + static_cast(0.5)); + } + + template + GLM_FUNC_QUALIFIER vec iround(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'iround' only accept floating-point inputs"); + assert(all(lessThanEqual(vec(0), x))); + + return vec(x + static_cast(0.5)); + } + + template + GLM_FUNC_QUALIFIER uint uround(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'uround' only accept floating-point inputs"); + assert(static_cast(0.0) <= x); + + return static_cast(x + static_cast(0.5)); + } + + template + GLM_FUNC_QUALIFIER vec uround(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'uround' only accept floating-point inputs"); + assert(all(lessThanEqual(vec(0), x))); + + return vec(x + static_cast(0.5)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/matrix_access.hpp b/vendor/glm/glm/gtc/matrix_access.hpp new file mode 100644 index 0000000..4935ba7 --- /dev/null +++ b/vendor/glm/glm/gtc/matrix_access.hpp @@ -0,0 +1,60 @@ +/// @ref gtc_matrix_access +/// @file glm/gtc/matrix_access.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_access GLM_GTC_matrix_access +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines functions to access rows or columns of a matrix easily. + +#pragma once + +// Dependency: +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_access extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_access + /// @{ + + /// Get a specific row of a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL typename genType::row_type row( + genType const& m, + length_t index); + + /// Set a specific row to a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL genType row( + genType const& m, + length_t index, + typename genType::row_type const& x); + + /// Get a specific column of a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL typename genType::col_type column( + genType const& m, + length_t index); + + /// Set a specific column to a matrix. + /// @see gtc_matrix_access + template + GLM_FUNC_DECL genType column( + genType const& m, + length_t index, + typename genType::col_type const& x); + + /// @} +}//namespace glm + +#include "matrix_access.inl" diff --git a/vendor/glm/glm/gtc/matrix_access.inl b/vendor/glm/glm/gtc/matrix_access.inl new file mode 100644 index 0000000..09fcc10 --- /dev/null +++ b/vendor/glm/glm/gtc/matrix_access.inl @@ -0,0 +1,62 @@ +/// @ref gtc_matrix_access + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType row + ( + genType const& m, + length_t index, + typename genType::row_type const& x + ) + { + assert(index >= 0 && index < m[0].length()); + + genType Result = m; + for(length_t i = 0; i < m.length(); ++i) + Result[i][index] = x[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER typename genType::row_type row + ( + genType const& m, + length_t index + ) + { + assert(index >= 0 && index < m[0].length()); + + typename genType::row_type Result(0); + for(length_t i = 0; i < m.length(); ++i) + Result[i] = m[i][index]; + return Result; + } + + template + GLM_FUNC_QUALIFIER genType column + ( + genType const& m, + length_t index, + typename genType::col_type const& x + ) + { + assert(index >= 0 && index < m.length()); + + genType Result = m; + Result[index] = x; + return Result; + } + + template + GLM_FUNC_QUALIFIER typename genType::col_type column + ( + genType const& m, + length_t index + ) + { + assert(index >= 0 && index < m.length()); + + return m[index]; + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/matrix_integer.hpp b/vendor/glm/glm/gtc/matrix_integer.hpp new file mode 100644 index 0000000..d7ebdc7 --- /dev/null +++ b/vendor/glm/glm/gtc/matrix_integer.hpp @@ -0,0 +1,433 @@ +/// @ref gtc_matrix_integer +/// @file glm/gtc/matrix_integer.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_integer GLM_GTC_matrix_integer +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines a number of matrices with integer types. + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_integer + /// @{ + + /// High-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, highp> highp_imat2; + + /// High-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, highp> highp_imat3; + + /// High-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, highp> highp_imat4; + + /// High-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, highp> highp_imat2x2; + + /// High-qualifier signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, highp> highp_imat2x3; + + /// High-qualifier signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, highp> highp_imat2x4; + + /// High-qualifier signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, highp> highp_imat3x2; + + /// High-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, highp> highp_imat3x3; + + /// High-qualifier signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, highp> highp_imat3x4; + + /// High-qualifier signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, highp> highp_imat4x2; + + /// High-qualifier signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, highp> highp_imat4x3; + + /// High-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, highp> highp_imat4x4; + + + /// Medium-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, mediump> mediump_imat2; + + /// Medium-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, mediump> mediump_imat3; + + /// Medium-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, mediump> mediump_imat4; + + + /// Medium-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, mediump> mediump_imat2x2; + + /// Medium-qualifier signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, mediump> mediump_imat2x3; + + /// Medium-qualifier signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, mediump> mediump_imat2x4; + + /// Medium-qualifier signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, mediump> mediump_imat3x2; + + /// Medium-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, mediump> mediump_imat3x3; + + /// Medium-qualifier signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, mediump> mediump_imat3x4; + + /// Medium-qualifier signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, mediump> mediump_imat4x2; + + /// Medium-qualifier signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, mediump> mediump_imat4x3; + + /// Medium-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, mediump> mediump_imat4x4; + + + /// Low-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, lowp> lowp_imat2; + + /// Low-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, lowp> lowp_imat3; + + /// Low-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, lowp> lowp_imat4; + + + /// Low-qualifier signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, lowp> lowp_imat2x2; + + /// Low-qualifier signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, lowp> lowp_imat2x3; + + /// Low-qualifier signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, lowp> lowp_imat2x4; + + /// Low-qualifier signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, lowp> lowp_imat3x2; + + /// Low-qualifier signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, lowp> lowp_imat3x3; + + /// Low-qualifier signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, lowp> lowp_imat3x4; + + /// Low-qualifier signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, lowp> lowp_imat4x2; + + /// Low-qualifier signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, lowp> lowp_imat4x3; + + /// Low-qualifier signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, lowp> lowp_imat4x4; + + + /// High-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, highp> highp_umat2; + + /// High-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, highp> highp_umat3; + + /// High-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, highp> highp_umat4; + + /// High-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, highp> highp_umat2x2; + + /// High-qualifier unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, highp> highp_umat2x3; + + /// High-qualifier unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, highp> highp_umat2x4; + + /// High-qualifier unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, highp> highp_umat3x2; + + /// High-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, highp> highp_umat3x3; + + /// High-qualifier unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, highp> highp_umat3x4; + + /// High-qualifier unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, highp> highp_umat4x2; + + /// High-qualifier unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, highp> highp_umat4x3; + + /// High-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, highp> highp_umat4x4; + + + /// Medium-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, mediump> mediump_umat2; + + /// Medium-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, mediump> mediump_umat3; + + /// Medium-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, mediump> mediump_umat4; + + + /// Medium-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, mediump> mediump_umat2x2; + + /// Medium-qualifier unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, mediump> mediump_umat2x3; + + /// Medium-qualifier unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, mediump> mediump_umat2x4; + + /// Medium-qualifier unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, mediump> mediump_umat3x2; + + /// Medium-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, mediump> mediump_umat3x3; + + /// Medium-qualifier unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, mediump> mediump_umat3x4; + + /// Medium-qualifier unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, mediump> mediump_umat4x2; + + /// Medium-qualifier unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, mediump> mediump_umat4x3; + + /// Medium-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, mediump> mediump_umat4x4; + + + /// Low-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, lowp> lowp_umat2; + + /// Low-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, lowp> lowp_umat3; + + /// Low-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, lowp> lowp_umat4; + + + /// Low-qualifier unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, lowp> lowp_umat2x2; + + /// Low-qualifier unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, lowp> lowp_umat2x3; + + /// Low-qualifier unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, lowp> lowp_umat2x4; + + /// Low-qualifier unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, lowp> lowp_umat3x2; + + /// Low-qualifier unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, lowp> lowp_umat3x3; + + /// Low-qualifier unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, lowp> lowp_umat3x4; + + /// Low-qualifier unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, lowp> lowp_umat4x2; + + /// Low-qualifier unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, lowp> lowp_umat4x3; + + /// Low-qualifier unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, lowp> lowp_umat4x4; + + + + /// Signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, defaultp> imat2; + + /// Signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, defaultp> imat3; + + /// Signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, defaultp> imat4; + + /// Signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, int, defaultp> imat2x2; + + /// Signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, int, defaultp> imat2x3; + + /// Signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, int, defaultp> imat2x4; + + /// Signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, int, defaultp> imat3x2; + + /// Signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, int, defaultp> imat3x3; + + /// Signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, int, defaultp> imat3x4; + + /// Signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, int, defaultp> imat4x2; + + /// Signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, int, defaultp> imat4x3; + + /// Signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, int, defaultp> imat4x4; + + + + /// Unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, defaultp> umat2; + + /// Unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, defaultp> umat3; + + /// Unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, defaultp> umat4; + + /// Unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 2, uint, defaultp> umat2x2; + + /// Unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 3, uint, defaultp> umat2x3; + + /// Unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mat<2, 4, uint, defaultp> umat2x4; + + /// Unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 2, uint, defaultp> umat3x2; + + /// Unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 3, uint, defaultp> umat3x3; + + /// Unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mat<3, 4, uint, defaultp> umat3x4; + + /// Unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 2, uint, defaultp> umat4x2; + + /// Unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 3, uint, defaultp> umat4x3; + + /// Unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mat<4, 4, uint, defaultp> umat4x4; + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/gtc/matrix_inverse.hpp b/vendor/glm/glm/gtc/matrix_inverse.hpp new file mode 100644 index 0000000..a1900ad --- /dev/null +++ b/vendor/glm/glm/gtc/matrix_inverse.hpp @@ -0,0 +1,50 @@ +/// @ref gtc_matrix_inverse +/// @file glm/gtc/matrix_inverse.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_inverse GLM_GTC_matrix_inverse +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines additional matrix inverting functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../matrix.hpp" +#include "../mat2x2.hpp" +#include "../mat3x3.hpp" +#include "../mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_inverse extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_inverse + /// @{ + + /// Fast matrix inverse for affine matrix. + /// + /// @param m Input matrix to invert. + /// @tparam genType Squared floating-point matrix: half, float or double. Inverse of matrix based of half-qualifier floating point value is highly innacurate. + /// @see gtc_matrix_inverse + template + GLM_FUNC_DECL genType affineInverse(genType const& m); + + /// Compute the inverse transpose of a matrix. + /// + /// @param m Input matrix to invert transpose. + /// @tparam genType Squared floating-point matrix: half, float or double. Inverse of matrix based of half-qualifier floating point value is highly innacurate. + /// @see gtc_matrix_inverse + template + GLM_FUNC_DECL genType inverseTranspose(genType const& m); + + /// @} +}//namespace glm + +#include "matrix_inverse.inl" diff --git a/vendor/glm/glm/gtc/matrix_inverse.inl b/vendor/glm/glm/gtc/matrix_inverse.inl new file mode 100644 index 0000000..c004b9e --- /dev/null +++ b/vendor/glm/glm/gtc/matrix_inverse.inl @@ -0,0 +1,118 @@ +/// @ref gtc_matrix_inverse + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> affineInverse(mat<3, 3, T, Q> const& m) + { + mat<2, 2, T, Q> const Inv(inverse(mat<2, 2, T, Q>(m))); + + return mat<3, 3, T, Q>( + vec<3, T, Q>(Inv[0], static_cast(0)), + vec<3, T, Q>(Inv[1], static_cast(0)), + vec<3, T, Q>(-Inv * vec<2, T, Q>(m[2]), static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> affineInverse(mat<4, 4, T, Q> const& m) + { + mat<3, 3, T, Q> const Inv(inverse(mat<3, 3, T, Q>(m))); + + return mat<4, 4, T, Q>( + vec<4, T, Q>(Inv[0], static_cast(0)), + vec<4, T, Q>(Inv[1], static_cast(0)), + vec<4, T, Q>(Inv[2], static_cast(0)), + vec<4, T, Q>(-Inv * vec<3, T, Q>(m[3]), static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> inverseTranspose(mat<2, 2, T, Q> const& m) + { + T Determinant = m[0][0] * m[1][1] - m[1][0] * m[0][1]; + + mat<2, 2, T, Q> Inverse( + + m[1][1] / Determinant, + - m[0][1] / Determinant, + - m[1][0] / Determinant, + + m[0][0] / Determinant); + + return Inverse; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> inverseTranspose(mat<3, 3, T, Q> const& m) + { + T Determinant = + + m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) + - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); + + mat<3, 3, T, Q> Inverse; + Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]); + Inverse[0][1] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]); + Inverse[0][2] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]); + Inverse[1][0] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]); + Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]); + Inverse[1][2] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]); + Inverse[2][0] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]); + Inverse[2][1] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]); + Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]); + Inverse /= Determinant; + + return Inverse; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> inverseTranspose(mat<4, 4, T, Q> const& m) + { + T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + T SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + T SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + T SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + T SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + T SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + T SubFactor11 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + T SubFactor12 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + T SubFactor13 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + T SubFactor14 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + T SubFactor15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + T SubFactor16 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + T SubFactor17 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + mat<4, 4, T, Q> Inverse; + Inverse[0][0] = + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02); + Inverse[0][1] = - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04); + Inverse[0][2] = + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05); + Inverse[0][3] = - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05); + + Inverse[1][0] = - (m[0][1] * SubFactor00 - m[0][2] * SubFactor01 + m[0][3] * SubFactor02); + Inverse[1][1] = + (m[0][0] * SubFactor00 - m[0][2] * SubFactor03 + m[0][3] * SubFactor04); + Inverse[1][2] = - (m[0][0] * SubFactor01 - m[0][1] * SubFactor03 + m[0][3] * SubFactor05); + Inverse[1][3] = + (m[0][0] * SubFactor02 - m[0][1] * SubFactor04 + m[0][2] * SubFactor05); + + Inverse[2][0] = + (m[0][1] * SubFactor06 - m[0][2] * SubFactor07 + m[0][3] * SubFactor08); + Inverse[2][1] = - (m[0][0] * SubFactor06 - m[0][2] * SubFactor09 + m[0][3] * SubFactor10); + Inverse[2][2] = + (m[0][0] * SubFactor07 - m[0][1] * SubFactor09 + m[0][3] * SubFactor11); + Inverse[2][3] = - (m[0][0] * SubFactor08 - m[0][1] * SubFactor10 + m[0][2] * SubFactor11); + + Inverse[3][0] = - (m[0][1] * SubFactor12 - m[0][2] * SubFactor13 + m[0][3] * SubFactor14); + Inverse[3][1] = + (m[0][0] * SubFactor12 - m[0][2] * SubFactor15 + m[0][3] * SubFactor16); + Inverse[3][2] = - (m[0][0] * SubFactor13 - m[0][1] * SubFactor15 + m[0][3] * SubFactor17); + Inverse[3][3] = + (m[0][0] * SubFactor14 - m[0][1] * SubFactor16 + m[0][2] * SubFactor17); + + T Determinant = + + m[0][0] * Inverse[0][0] + + m[0][1] * Inverse[0][1] + + m[0][2] * Inverse[0][2] + + m[0][3] * Inverse[0][3]; + + Inverse /= Determinant; + + return Inverse; + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/matrix_transform.hpp b/vendor/glm/glm/gtc/matrix_transform.hpp new file mode 100644 index 0000000..612418f --- /dev/null +++ b/vendor/glm/glm/gtc/matrix_transform.hpp @@ -0,0 +1,36 @@ +/// @ref gtc_matrix_transform +/// @file glm/gtc/matrix_transform.hpp +/// +/// @see core (dependence) +/// @see gtx_transform +/// @see gtx_transform2 +/// +/// @defgroup gtc_matrix_transform GLM_GTC_matrix_transform +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines functions that generate common transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. + +#pragma once + +// Dependencies +#include "../mat4x4.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../ext/matrix_projection.hpp" +#include "../ext/matrix_clip_space.hpp" +#include "../ext/matrix_transform.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_matrix_transform extension included") +#endif + +#include "matrix_transform.inl" diff --git a/vendor/glm/glm/gtc/matrix_transform.inl b/vendor/glm/glm/gtc/matrix_transform.inl new file mode 100644 index 0000000..15b46bc --- /dev/null +++ b/vendor/glm/glm/gtc/matrix_transform.inl @@ -0,0 +1,3 @@ +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" diff --git a/vendor/glm/glm/gtc/noise.hpp b/vendor/glm/glm/gtc/noise.hpp new file mode 100644 index 0000000..ab1772e --- /dev/null +++ b/vendor/glm/glm/gtc/noise.hpp @@ -0,0 +1,61 @@ +/// @ref gtc_noise +/// @file glm/gtc/noise.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_noise GLM_GTC_noise +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines 2D, 3D and 4D procedural noise functions +/// Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": +/// https://github.com/ashima/webgl-noise +/// Following Stefan Gustavson's paper "Simplex noise demystified": +/// http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_noise.hpp" +#include "../geometric.hpp" +#include "../common.hpp" +#include "../vector_relational.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_noise extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_noise + /// @{ + + /// Classic perlin noise. + /// @see gtc_noise + template + GLM_FUNC_DECL T perlin( + vec const& p); + + /// Periodic perlin noise. + /// @see gtc_noise + template + GLM_FUNC_DECL T perlin( + vec const& p, + vec const& rep); + + /// Simplex noise. + /// @see gtc_noise + template + GLM_FUNC_DECL T simplex( + vec const& p); + + /// @} +}//namespace glm + +#include "noise.inl" diff --git a/vendor/glm/glm/gtc/noise.inl b/vendor/glm/glm/gtc/noise.inl new file mode 100644 index 0000000..30d0b27 --- /dev/null +++ b/vendor/glm/glm/gtc/noise.inl @@ -0,0 +1,807 @@ +/// @ref gtc_noise +/// +// Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": +// https://github.com/ashima/webgl-noise +// Following Stefan Gustavson's paper "Simplex noise demystified": +// http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf + +namespace glm{ +namespace gtc +{ + template + GLM_FUNC_QUALIFIER vec<4, T, Q> grad4(T const& j, vec<4, T, Q> const& ip) + { + vec<3, T, Q> pXYZ = floor(fract(vec<3, T, Q>(j) * vec<3, T, Q>(ip)) * T(7)) * ip[2] - T(1); + T pW = static_cast(1.5) - dot(abs(pXYZ), vec<3, T, Q>(1)); + vec<4, T, Q> s = vec<4, T, Q>(lessThan(vec<4, T, Q>(pXYZ, pW), vec<4, T, Q>(0.0))); + pXYZ = pXYZ + (vec<3, T, Q>(s) * T(2) - T(1)) * s.w; + return vec<4, T, Q>(pXYZ, pW); + } +}//namespace gtc + + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<2, T, Q> const& Position) + { + vec<4, T, Q> Pi = glm::floor(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) + vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); + 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); + Pi = mod(Pi, vec<4, T, Q>(289)); // To avoid truncation effects in permutation + vec<4, T, Q> ix(Pi.x, Pi.z, Pi.x, Pi.z); + vec<4, T, Q> iy(Pi.y, Pi.y, Pi.w, Pi.w); + vec<4, T, Q> fx(Pf.x, Pf.z, Pf.x, Pf.z); + vec<4, T, Q> fy(Pf.y, Pf.y, Pf.w, Pf.w); + + vec<4, T, Q> i = detail::permute(detail::permute(ix) + iy); + + vec<4, T, Q> gx = static_cast(2) * glm::fract(i / T(41)) - T(1); + vec<4, T, Q> gy = glm::abs(gx) - T(0.5); + vec<4, T, Q> tx = glm::floor(gx + T(0.5)); + gx = gx - tx; + + vec<2, T, Q> g00(gx.x, gy.x); + vec<2, T, Q> g10(gx.y, gy.y); + vec<2, T, Q> g01(gx.z, gy.z); + vec<2, T, Q> g11(gx.w, gy.w); + + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); + g00 *= norm.x; + g01 *= norm.y; + g10 *= norm.z; + g11 *= norm.w; + + T n00 = dot(g00, vec<2, T, Q>(fx.x, fy.x)); + T n10 = dot(g10, vec<2, T, Q>(fx.y, fy.y)); + T n01 = dot(g01, vec<2, T, Q>(fx.z, fy.z)); + T n11 = dot(g11, vec<2, T, Q>(fx.w, fy.w)); + + vec<2, T, Q> fade_xy = detail::fade(vec<2, T, Q>(Pf.x, Pf.y)); + vec<2, T, Q> n_x = mix(vec<2, T, Q>(n00, n01), vec<2, T, Q>(n10, n11), fade_xy.x); + T n_xy = mix(n_x.x, n_x.y, fade_xy.y); + return T(2.3) * n_xy; + } + + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<3, T, Q> const& Position) + { + vec<3, T, Q> Pi0 = floor(Position); // Integer part for indexing + vec<3, T, Q> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = detail::mod289(Pi0); + Pi1 = detail::mod289(Pi1); + vec<3, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<3, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy = vec<4, T, Q>(vec<2, T, Q>(Pi0.y), vec<2, T, Q>(Pi1.y)); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + + vec<4, T, Q> gx0 = ixy0 * T(1.0 / 7.0); + vec<4, T, Q> gy0 = fract(floor(gx0) * T(1.0 / 7.0)) - T(0.5); + gx0 = fract(gx0); + vec<4, T, Q> gz0 = vec<4, T, Q>(0.5) - abs(gx0) - abs(gy0); + vec<4, T, Q> sz0 = step(gz0, vec<4, T, Q>(0.0)); + gx0 -= sz0 * (step(T(0), gx0) - T(0.5)); + gy0 -= sz0 * (step(T(0), gy0) - T(0.5)); + + vec<4, T, Q> gx1 = ixy1 * T(1.0 / 7.0); + vec<4, T, Q> gy1 = fract(floor(gx1) * T(1.0 / 7.0)) - T(0.5); + gx1 = fract(gx1); + vec<4, T, Q> gz1 = vec<4, T, Q>(0.5) - abs(gx1) - abs(gy1); + vec<4, T, Q> sz1 = step(gz1, vec<4, T, Q>(0.0)); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + vec<3, T, Q> g000(gx0.x, gy0.x, gz0.x); + vec<3, T, Q> g100(gx0.y, gy0.y, gz0.y); + vec<3, T, Q> g010(gx0.z, gy0.z, gz0.z); + vec<3, T, Q> g110(gx0.w, gy0.w, gz0.w); + vec<3, T, Q> g001(gx1.x, gy1.x, gz1.x); + vec<3, T, Q> g101(gx1.y, gy1.y, gz1.y); + vec<3, T, Q> g011(gx1.z, gy1.z, gz1.z); + vec<3, T, Q> g111(gx1.w, gy1.w, gz1.w); + + vec<4, T, Q> norm0 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec<4, T, Q> norm1 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, vec<3, T, Q>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, vec<3, T, Q>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, vec<3, T, Q>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, vec<3, T, Q>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, vec<3, T, Q>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, vec<3, T, Q>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + vec<3, T, Q> fade_xyz = detail::fade(Pf0); + vec<4, T, Q> n_z = mix(vec<4, T, Q>(n000, n100, n010, n110), vec<4, T, Q>(n001, n101, n011, n111), fade_xyz.z); + vec<2, T, Q> n_yz = mix(vec<2, T, Q>(n_z.x, n_z.y), vec<2, T, Q>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + /* + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<3, T, Q> const& P) + { + vec<3, T, Q> Pi0 = floor(P); // Integer part for indexing + vec<3, T, Q> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = mod(Pi0, T(289)); + Pi1 = mod(Pi1, T(289)); + vec<3, T, Q> Pf0 = fract(P); // Fractional part for interpolation + vec<3, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + + vec<4, T, Q> ixy = permute(permute(ix) + iy); + vec<4, T, Q> ixy0 = permute(ixy + iz0); + vec<4, T, Q> ixy1 = permute(ixy + iz1); + + vec<4, T, Q> gx0 = ixy0 / T(7); + vec<4, T, Q> gy0 = fract(floor(gx0) / T(7)) - T(0.5); + gx0 = fract(gx0); + vec<4, T, Q> gz0 = vec<4, T, Q>(0.5) - abs(gx0) - abs(gy0); + vec<4, T, Q> sz0 = step(gz0, vec<4, T, Q>(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - T(0.5)); + gy0 -= sz0 * (step(0.0, gy0) - T(0.5)); + + vec<4, T, Q> gx1 = ixy1 / T(7); + vec<4, T, Q> gy1 = fract(floor(gx1) / T(7)) - T(0.5); + gx1 = fract(gx1); + vec<4, T, Q> gz1 = vec<4, T, Q>(0.5) - abs(gx1) - abs(gy1); + vec<4, T, Q> sz1 = step(gz1, vec<4, T, Q>(0.0)); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + vec<3, T, Q> g000(gx0.x, gy0.x, gz0.x); + vec<3, T, Q> g100(gx0.y, gy0.y, gz0.y); + vec<3, T, Q> g010(gx0.z, gy0.z, gz0.z); + vec<3, T, Q> g110(gx0.w, gy0.w, gz0.w); + vec<3, T, Q> g001(gx1.x, gy1.x, gz1.x); + vec<3, T, Q> g101(gx1.y, gy1.y, gz1.y); + vec<3, T, Q> g011(gx1.z, gy1.z, gz1.z); + vec<3, T, Q> g111(gx1.w, gy1.w, gz1.w); + + vec<4, T, Q> norm0 = taylorInvSqrt(vec<4, T, Q>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec<4, T, Q> norm1 = taylorInvSqrt(vec<4, T, Q>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, vec<3, T, Q>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, vec<3, T, Q>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, vec<3, T, Q>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, vec<3, T, Q>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, vec<3, T, Q>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, vec<3, T, Q>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + vec<3, T, Q> fade_xyz = fade(Pf0); + vec<4, T, Q> n_z = mix(vec<4, T, Q>(n000, n100, n010, n110), vec<4, T, Q>(n001, n101, n011, n111), fade_xyz.z); + vec<2, T, Q> n_yz = mix( + vec<2, T, Q>(n_z.x, n_z.y), + vec<2, T, Q>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + */ + // Classic Perlin noise + template + GLM_FUNC_QUALIFIER T perlin(vec<4, T, Q> const& Position) + { + vec<4, T, Q> Pi0 = floor(Position); // Integer part for indexing + vec<4, T, Q> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = mod(Pi0, vec<4, T, Q>(289)); + Pi1 = mod(Pi1, vec<4, T, Q>(289)); + vec<4, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<4, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + vec<4, T, Q> iw0(Pi0.w); + vec<4, T, Q> iw1(Pi1.w); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + vec<4, T, Q> ixy00 = detail::permute(ixy0 + iw0); + vec<4, T, Q> ixy01 = detail::permute(ixy0 + iw1); + vec<4, T, Q> ixy10 = detail::permute(ixy1 + iw0); + vec<4, T, Q> ixy11 = detail::permute(ixy1 + iw1); + + vec<4, T, Q> gx00 = ixy00 / T(7); + vec<4, T, Q> gy00 = floor(gx00) / T(7); + vec<4, T, Q> gz00 = floor(gy00) / T(6); + gx00 = fract(gx00) - T(0.5); + gy00 = fract(gy00) - T(0.5); + gz00 = fract(gz00) - T(0.5); + vec<4, T, Q> gw00 = vec<4, T, Q>(0.75) - abs(gx00) - abs(gy00) - abs(gz00); + vec<4, T, Q> sw00 = step(gw00, vec<4, T, Q>(0.0)); + gx00 -= sw00 * (step(T(0), gx00) - T(0.5)); + gy00 -= sw00 * (step(T(0), gy00) - T(0.5)); + + vec<4, T, Q> gx01 = ixy01 / T(7); + vec<4, T, Q> gy01 = floor(gx01) / T(7); + vec<4, T, Q> gz01 = floor(gy01) / T(6); + gx01 = fract(gx01) - T(0.5); + gy01 = fract(gy01) - T(0.5); + gz01 = fract(gz01) - T(0.5); + vec<4, T, Q> gw01 = vec<4, T, Q>(0.75) - abs(gx01) - abs(gy01) - abs(gz01); + vec<4, T, Q> sw01 = step(gw01, vec<4, T, Q>(0.0)); + gx01 -= sw01 * (step(T(0), gx01) - T(0.5)); + gy01 -= sw01 * (step(T(0), gy01) - T(0.5)); + + vec<4, T, Q> gx10 = ixy10 / T(7); + vec<4, T, Q> gy10 = floor(gx10) / T(7); + vec<4, T, Q> gz10 = floor(gy10) / T(6); + gx10 = fract(gx10) - T(0.5); + gy10 = fract(gy10) - T(0.5); + gz10 = fract(gz10) - T(0.5); + vec<4, T, Q> gw10 = vec<4, T, Q>(0.75) - abs(gx10) - abs(gy10) - abs(gz10); + vec<4, T, Q> sw10 = step(gw10, vec<4, T, Q>(0)); + gx10 -= sw10 * (step(T(0), gx10) - T(0.5)); + gy10 -= sw10 * (step(T(0), gy10) - T(0.5)); + + vec<4, T, Q> gx11 = ixy11 / T(7); + vec<4, T, Q> gy11 = floor(gx11) / T(7); + vec<4, T, Q> gz11 = floor(gy11) / T(6); + gx11 = fract(gx11) - T(0.5); + gy11 = fract(gy11) - T(0.5); + gz11 = fract(gz11) - T(0.5); + vec<4, T, Q> gw11 = vec<4, T, Q>(0.75) - abs(gx11) - abs(gy11) - abs(gz11); + vec<4, T, Q> sw11 = step(gw11, vec<4, T, Q>(0.0)); + gx11 -= sw11 * (step(T(0), gx11) - T(0.5)); + gy11 -= sw11 * (step(T(0), gy11) - T(0.5)); + + vec<4, T, Q> g0000(gx00.x, gy00.x, gz00.x, gw00.x); + vec<4, T, Q> g1000(gx00.y, gy00.y, gz00.y, gw00.y); + vec<4, T, Q> g0100(gx00.z, gy00.z, gz00.z, gw00.z); + vec<4, T, Q> g1100(gx00.w, gy00.w, gz00.w, gw00.w); + vec<4, T, Q> g0010(gx10.x, gy10.x, gz10.x, gw10.x); + vec<4, T, Q> g1010(gx10.y, gy10.y, gz10.y, gw10.y); + vec<4, T, Q> g0110(gx10.z, gy10.z, gz10.z, gw10.z); + vec<4, T, Q> g1110(gx10.w, gy10.w, gz10.w, gw10.w); + vec<4, T, Q> g0001(gx01.x, gy01.x, gz01.x, gw01.x); + vec<4, T, Q> g1001(gx01.y, gy01.y, gz01.y, gw01.y); + vec<4, T, Q> g0101(gx01.z, gy01.z, gz01.z, gw01.z); + vec<4, T, Q> g1101(gx01.w, gy01.w, gz01.w, gw01.w); + vec<4, T, Q> g0011(gx11.x, gy11.x, gz11.x, gw11.x); + vec<4, T, Q> g1011(gx11.y, gy11.y, gz11.y, gw11.y); + vec<4, T, Q> g0111(gx11.z, gy11.z, gz11.z, gw11.z); + vec<4, T, Q> g1111(gx11.w, gy11.w, gz11.w, gw11.w); + + vec<4, T, Q> norm00 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); + g0000 *= norm00.x; + g0100 *= norm00.y; + g1000 *= norm00.z; + g1100 *= norm00.w; + + vec<4, T, Q> norm01 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); + g0001 *= norm01.x; + g0101 *= norm01.y; + g1001 *= norm01.z; + g1101 *= norm01.w; + + vec<4, T, Q> norm10 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); + g0010 *= norm10.x; + g0110 *= norm10.y; + g1010 *= norm10.z; + g1110 *= norm10.w; + + vec<4, T, Q> norm11 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); + g0011 *= norm11.x; + g0111 *= norm11.y; + g1011 *= norm11.z; + g1111 *= norm11.w; + + T n0000 = dot(g0000, Pf0); + T n1000 = dot(g1000, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf0.w)); + T n0100 = dot(g0100, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf0.w)); + T n1100 = dot(g1100, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf0.w)); + T n0010 = dot(g0010, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf0.w)); + T n1010 = dot(g1010, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); + T n0110 = dot(g0110, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf0.w)); + T n1110 = dot(g1110, vec<4, T, Q>(Pf1.x, Pf1.y, Pf1.z, Pf0.w)); + T n0001 = dot(g0001, vec<4, T, Q>(Pf0.x, Pf0.y, Pf0.z, Pf1.w)); + T n1001 = dot(g1001, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf1.w)); + T n0101 = dot(g0101, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); + T n1101 = dot(g1101, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf1.w)); + T n0011 = dot(g0011, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf1.w)); + T n1011 = dot(g1011, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf1.w)); + T n0111 = dot(g0111, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf1.w)); + T n1111 = dot(g1111, Pf1); + + vec<4, T, Q> fade_xyzw = detail::fade(Pf0); + vec<4, T, Q> n_0w = mix(vec<4, T, Q>(n0000, n1000, n0100, n1100), vec<4, T, Q>(n0001, n1001, n0101, n1101), fade_xyzw.w); + vec<4, T, Q> n_1w = mix(vec<4, T, Q>(n0010, n1010, n0110, n1110), vec<4, T, Q>(n0011, n1011, n0111, n1111), fade_xyzw.w); + vec<4, T, Q> n_zw = mix(n_0w, n_1w, fade_xyzw.z); + vec<2, T, Q> n_yzw = mix(vec<2, T, Q>(n_zw.x, n_zw.y), vec<2, T, Q>(n_zw.z, n_zw.w), fade_xyzw.y); + T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); + return T(2.2) * n_xyzw; + } + + // Classic Perlin noise, periodic variant + template + GLM_FUNC_QUALIFIER T perlin(vec<2, T, Q> const& Position, vec<2, T, Q> const& rep) + { + vec<4, T, Q> Pi = floor(vec<4, T, Q>(Position.x, Position.y, Position.x, Position.y)) + vec<4, T, Q>(0.0, 0.0, 1.0, 1.0); + vec<4, T, Q> Pf = 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); + Pi = mod(Pi, vec<4, T, Q>(rep.x, rep.y, rep.x, rep.y)); // To create noise with explicit period + Pi = mod(Pi, vec<4, T, Q>(289)); // To avoid truncation effects in permutation + vec<4, T, Q> ix(Pi.x, Pi.z, Pi.x, Pi.z); + vec<4, T, Q> iy(Pi.y, Pi.y, Pi.w, Pi.w); + vec<4, T, Q> fx(Pf.x, Pf.z, Pf.x, Pf.z); + vec<4, T, Q> fy(Pf.y, Pf.y, Pf.w, Pf.w); + + vec<4, T, Q> i = detail::permute(detail::permute(ix) + iy); + + vec<4, T, Q> gx = static_cast(2) * fract(i / T(41)) - T(1); + vec<4, T, Q> gy = abs(gx) - T(0.5); + vec<4, T, Q> tx = floor(gx + T(0.5)); + gx = gx - tx; + + vec<2, T, Q> g00(gx.x, gy.x); + vec<2, T, Q> g10(gx.y, gy.y); + vec<2, T, Q> g01(gx.z, gy.z); + vec<2, T, Q> g11(gx.w, gy.w); + + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); + g00 *= norm.x; + g01 *= norm.y; + g10 *= norm.z; + g11 *= norm.w; + + T n00 = dot(g00, vec<2, T, Q>(fx.x, fy.x)); + T n10 = dot(g10, vec<2, T, Q>(fx.y, fy.y)); + T n01 = dot(g01, vec<2, T, Q>(fx.z, fy.z)); + T n11 = dot(g11, vec<2, T, Q>(fx.w, fy.w)); + + vec<2, T, Q> fade_xy = detail::fade(vec<2, T, Q>(Pf.x, Pf.y)); + vec<2, T, Q> n_x = mix(vec<2, T, Q>(n00, n01), vec<2, T, Q>(n10, n11), fade_xy.x); + T n_xy = mix(n_x.x, n_x.y, fade_xy.y); + return T(2.3) * n_xy; + } + + // Classic Perlin noise, periodic variant + template + GLM_FUNC_QUALIFIER T perlin(vec<3, T, Q> const& Position, vec<3, T, Q> const& rep) + { + vec<3, T, Q> Pi0 = mod(floor(Position), rep); // Integer part, modulo period + vec<3, T, Q> Pi1 = mod(Pi0 + vec<3, T, Q>(T(1)), rep); // Integer part + 1, mod period + Pi0 = mod(Pi0, vec<3, T, Q>(289)); + Pi1 = mod(Pi1, vec<3, T, Q>(289)); + vec<3, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<3, T, Q> Pf1 = Pf0 - vec<3, T, Q>(T(1)); // Fractional part - 1.0 + vec<4, T, Q> ix = vec<4, T, Q>(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy = vec<4, T, Q>(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + + vec<4, T, Q> gx0 = ixy0 / T(7); + vec<4, T, Q> gy0 = fract(floor(gx0) / T(7)) - T(0.5); + gx0 = fract(gx0); + vec<4, T, Q> gz0 = vec<4, T, Q>(0.5) - abs(gx0) - abs(gy0); + vec<4, T, Q> sz0 = step(gz0, vec<4, T, Q>(0)); + gx0 -= sz0 * (step(T(0), gx0) - T(0.5)); + gy0 -= sz0 * (step(T(0), gy0) - T(0.5)); + + vec<4, T, Q> gx1 = ixy1 / T(7); + vec<4, T, Q> gy1 = fract(floor(gx1) / T(7)) - T(0.5); + gx1 = fract(gx1); + vec<4, T, Q> gz1 = vec<4, T, Q>(0.5) - abs(gx1) - abs(gy1); + vec<4, T, Q> sz1 = step(gz1, vec<4, T, Q>(T(0))); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + vec<3, T, Q> g000 = vec<3, T, Q>(gx0.x, gy0.x, gz0.x); + vec<3, T, Q> g100 = vec<3, T, Q>(gx0.y, gy0.y, gz0.y); + vec<3, T, Q> g010 = vec<3, T, Q>(gx0.z, gy0.z, gz0.z); + vec<3, T, Q> g110 = vec<3, T, Q>(gx0.w, gy0.w, gz0.w); + vec<3, T, Q> g001 = vec<3, T, Q>(gx1.x, gy1.x, gz1.x); + vec<3, T, Q> g101 = vec<3, T, Q>(gx1.y, gy1.y, gz1.y); + vec<3, T, Q> g011 = vec<3, T, Q>(gx1.z, gy1.z, gz1.z); + vec<3, T, Q> g111 = vec<3, T, Q>(gx1.w, gy1.w, gz1.w); + + vec<4, T, Q> norm0 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + vec<4, T, Q> norm1 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, vec<3, T, Q>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, vec<3, T, Q>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, vec<3, T, Q>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, vec<3, T, Q>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, vec<3, T, Q>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, vec<3, T, Q>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + vec<3, T, Q> fade_xyz = detail::fade(Pf0); + vec<4, T, Q> n_z = mix(vec<4, T, Q>(n000, n100, n010, n110), vec<4, T, Q>(n001, n101, n011, n111), fade_xyz.z); + vec<2, T, Q> n_yz = mix(vec<2, T, Q>(n_z.x, n_z.y), vec<2, T, Q>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + + // Classic Perlin noise, periodic version + template + GLM_FUNC_QUALIFIER T perlin(vec<4, T, Q> const& Position, vec<4, T, Q> const& rep) + { + vec<4, T, Q> Pi0 = mod(floor(Position), rep); // Integer part modulo rep + vec<4, T, Q> Pi1 = mod(Pi0 + T(1), rep); // Integer part + 1 mod rep + vec<4, T, Q> Pf0 = fract(Position); // Fractional part for interpolation + vec<4, T, Q> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + vec<4, T, Q> ix = vec<4, T, Q>(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + vec<4, T, Q> iy = vec<4, T, Q>(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + vec<4, T, Q> iz0(Pi0.z); + vec<4, T, Q> iz1(Pi1.z); + vec<4, T, Q> iw0(Pi0.w); + vec<4, T, Q> iw1(Pi1.w); + + vec<4, T, Q> ixy = detail::permute(detail::permute(ix) + iy); + vec<4, T, Q> ixy0 = detail::permute(ixy + iz0); + vec<4, T, Q> ixy1 = detail::permute(ixy + iz1); + vec<4, T, Q> ixy00 = detail::permute(ixy0 + iw0); + vec<4, T, Q> ixy01 = detail::permute(ixy0 + iw1); + vec<4, T, Q> ixy10 = detail::permute(ixy1 + iw0); + vec<4, T, Q> ixy11 = detail::permute(ixy1 + iw1); + + vec<4, T, Q> gx00 = ixy00 / T(7); + vec<4, T, Q> gy00 = floor(gx00) / T(7); + vec<4, T, Q> gz00 = floor(gy00) / T(6); + gx00 = fract(gx00) - T(0.5); + gy00 = fract(gy00) - T(0.5); + gz00 = fract(gz00) - T(0.5); + vec<4, T, Q> gw00 = vec<4, T, Q>(0.75) - abs(gx00) - abs(gy00) - abs(gz00); + vec<4, T, Q> sw00 = step(gw00, vec<4, T, Q>(0)); + gx00 -= sw00 * (step(T(0), gx00) - T(0.5)); + gy00 -= sw00 * (step(T(0), gy00) - T(0.5)); + + vec<4, T, Q> gx01 = ixy01 / T(7); + vec<4, T, Q> gy01 = floor(gx01) / T(7); + vec<4, T, Q> gz01 = floor(gy01) / T(6); + gx01 = fract(gx01) - T(0.5); + gy01 = fract(gy01) - T(0.5); + gz01 = fract(gz01) - T(0.5); + vec<4, T, Q> gw01 = vec<4, T, Q>(0.75) - abs(gx01) - abs(gy01) - abs(gz01); + vec<4, T, Q> sw01 = step(gw01, vec<4, T, Q>(0.0)); + gx01 -= sw01 * (step(T(0), gx01) - T(0.5)); + gy01 -= sw01 * (step(T(0), gy01) - T(0.5)); + + vec<4, T, Q> gx10 = ixy10 / T(7); + vec<4, T, Q> gy10 = floor(gx10) / T(7); + vec<4, T, Q> gz10 = floor(gy10) / T(6); + gx10 = fract(gx10) - T(0.5); + gy10 = fract(gy10) - T(0.5); + gz10 = fract(gz10) - T(0.5); + vec<4, T, Q> gw10 = vec<4, T, Q>(0.75) - abs(gx10) - abs(gy10) - abs(gz10); + vec<4, T, Q> sw10 = step(gw10, vec<4, T, Q>(0.0)); + gx10 -= sw10 * (step(T(0), gx10) - T(0.5)); + gy10 -= sw10 * (step(T(0), gy10) - T(0.5)); + + vec<4, T, Q> gx11 = ixy11 / T(7); + vec<4, T, Q> gy11 = floor(gx11) / T(7); + vec<4, T, Q> gz11 = floor(gy11) / T(6); + gx11 = fract(gx11) - T(0.5); + gy11 = fract(gy11) - T(0.5); + gz11 = fract(gz11) - T(0.5); + vec<4, T, Q> gw11 = vec<4, T, Q>(0.75) - abs(gx11) - abs(gy11) - abs(gz11); + vec<4, T, Q> sw11 = step(gw11, vec<4, T, Q>(T(0))); + gx11 -= sw11 * (step(T(0), gx11) - T(0.5)); + gy11 -= sw11 * (step(T(0), gy11) - T(0.5)); + + vec<4, T, Q> g0000(gx00.x, gy00.x, gz00.x, gw00.x); + vec<4, T, Q> g1000(gx00.y, gy00.y, gz00.y, gw00.y); + vec<4, T, Q> g0100(gx00.z, gy00.z, gz00.z, gw00.z); + vec<4, T, Q> g1100(gx00.w, gy00.w, gz00.w, gw00.w); + vec<4, T, Q> g0010(gx10.x, gy10.x, gz10.x, gw10.x); + vec<4, T, Q> g1010(gx10.y, gy10.y, gz10.y, gw10.y); + vec<4, T, Q> g0110(gx10.z, gy10.z, gz10.z, gw10.z); + vec<4, T, Q> g1110(gx10.w, gy10.w, gz10.w, gw10.w); + vec<4, T, Q> g0001(gx01.x, gy01.x, gz01.x, gw01.x); + vec<4, T, Q> g1001(gx01.y, gy01.y, gz01.y, gw01.y); + vec<4, T, Q> g0101(gx01.z, gy01.z, gz01.z, gw01.z); + vec<4, T, Q> g1101(gx01.w, gy01.w, gz01.w, gw01.w); + vec<4, T, Q> g0011(gx11.x, gy11.x, gz11.x, gw11.x); + vec<4, T, Q> g1011(gx11.y, gy11.y, gz11.y, gw11.y); + vec<4, T, Q> g0111(gx11.z, gy11.z, gz11.z, gw11.z); + vec<4, T, Q> g1111(gx11.w, gy11.w, gz11.w, gw11.w); + + vec<4, T, Q> norm00 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); + g0000 *= norm00.x; + g0100 *= norm00.y; + g1000 *= norm00.z; + g1100 *= norm00.w; + + vec<4, T, Q> norm01 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); + g0001 *= norm01.x; + g0101 *= norm01.y; + g1001 *= norm01.z; + g1101 *= norm01.w; + + vec<4, T, Q> norm10 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); + g0010 *= norm10.x; + g0110 *= norm10.y; + g1010 *= norm10.z; + g1110 *= norm10.w; + + vec<4, T, Q> norm11 = detail::taylorInvSqrt(vec<4, T, Q>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); + g0011 *= norm11.x; + g0111 *= norm11.y; + g1011 *= norm11.z; + g1111 *= norm11.w; + + T n0000 = dot(g0000, Pf0); + T n1000 = dot(g1000, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf0.w)); + T n0100 = dot(g0100, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf0.w)); + T n1100 = dot(g1100, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf0.w)); + T n0010 = dot(g0010, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf0.w)); + T n1010 = dot(g1010, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); + T n0110 = dot(g0110, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf0.w)); + T n1110 = dot(g1110, vec<4, T, Q>(Pf1.x, Pf1.y, Pf1.z, Pf0.w)); + T n0001 = dot(g0001, vec<4, T, Q>(Pf0.x, Pf0.y, Pf0.z, Pf1.w)); + T n1001 = dot(g1001, vec<4, T, Q>(Pf1.x, Pf0.y, Pf0.z, Pf1.w)); + T n0101 = dot(g0101, vec<4, T, Q>(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); + T n1101 = dot(g1101, vec<4, T, Q>(Pf1.x, Pf1.y, Pf0.z, Pf1.w)); + T n0011 = dot(g0011, vec<4, T, Q>(Pf0.x, Pf0.y, Pf1.z, Pf1.w)); + T n1011 = dot(g1011, vec<4, T, Q>(Pf1.x, Pf0.y, Pf1.z, Pf1.w)); + T n0111 = dot(g0111, vec<4, T, Q>(Pf0.x, Pf1.y, Pf1.z, Pf1.w)); + T n1111 = dot(g1111, Pf1); + + vec<4, T, Q> fade_xyzw = detail::fade(Pf0); + vec<4, T, Q> n_0w = mix(vec<4, T, Q>(n0000, n1000, n0100, n1100), vec<4, T, Q>(n0001, n1001, n0101, n1101), fade_xyzw.w); + vec<4, T, Q> n_1w = mix(vec<4, T, Q>(n0010, n1010, n0110, n1110), vec<4, T, Q>(n0011, n1011, n0111, n1111), fade_xyzw.w); + vec<4, T, Q> n_zw = mix(n_0w, n_1w, fade_xyzw.z); + vec<2, T, Q> n_yzw = mix(vec<2, T, Q>(n_zw.x, n_zw.y), vec<2, T, Q>(n_zw.z, n_zw.w), fade_xyzw.y); + T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); + return T(2.2) * n_xyzw; + } + + template + GLM_FUNC_QUALIFIER T simplex(glm::vec<2, T, Q> const& v) + { + vec<4, T, Q> const C = vec<4, T, Q>( + T( 0.211324865405187), // (3.0 - sqrt(3.0)) / 6.0 + T( 0.366025403784439), // 0.5 * (sqrt(3.0) - 1.0) + T(-0.577350269189626), // -1.0 + 2.0 * C.x + T( 0.024390243902439)); // 1.0 / 41.0 + + // First corner + vec<2, T, Q> i = floor(v + dot(v, vec<2, T, Q>(C[1]))); + vec<2, T, Q> x0 = v - i + dot(i, vec<2, T, Q>(C[0])); + + // Other corners + //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 + //i1.y = 1.0 - i1.x; + vec<2, T, Q> i1 = (x0.x > x0.y) ? vec<2, T, Q>(1, 0) : vec<2, T, Q>(0, 1); + // x0 = x0 - 0.0 + 0.0 * C.xx ; + // x1 = x0 - i1 + 1.0 * C.xx ; + // x2 = x0 - 1.0 + 2.0 * C.xx ; + vec<4, T, Q> x12 = vec<4, T, Q>(x0.x, x0.y, x0.x, x0.y) + vec<4, T, Q>(C.x, C.x, C.z, C.z); + x12 = vec<4, T, Q>(vec<2, T, Q>(x12) - i1, x12.z, x12.w); + + // Permutations + i = mod(i, vec<2, T, Q>(289)); // Avoid truncation effects in permutation + vec<3, T, Q> p = detail::permute( + detail::permute(i.y + vec<3, T, Q>(T(0), i1.y, T(1))) + + i.x + vec<3, T, Q>(T(0), i1.x, T(1))); + + vec<3, T, Q> m = max(vec<3, T, Q>(0.5) - vec<3, T, Q>( + dot(x0, x0), + dot(vec<2, T, Q>(x12.x, x12.y), vec<2, T, Q>(x12.x, x12.y)), + dot(vec<2, T, Q>(x12.z, x12.w), vec<2, T, Q>(x12.z, x12.w))), vec<3, T, Q>(0)); + m = m * m ; + m = m * m ; + + // Gradients: 41 points uniformly over a line, mapped onto a diamond. + // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) + + vec<3, T, Q> x = static_cast(2) * fract(p * C.w) - T(1); + vec<3, T, Q> h = abs(x) - T(0.5); + vec<3, T, Q> ox = floor(x + T(0.5)); + vec<3, T, Q> a0 = x - ox; + + // Normalise gradients implicitly by scaling m + // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); + m *= static_cast(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h); + + // Compute final noise value at P + vec<3, T, Q> g; + g.x = a0.x * x0.x + h.x * x0.y; + //g.yz = a0.yz * x12.xz + h.yz * x12.yw; + g.y = a0.y * x12.x + h.y * x12.y; + g.z = a0.z * x12.z + h.z * x12.w; + return T(130) * dot(m, g); + } + + template + GLM_FUNC_QUALIFIER T simplex(vec<3, T, Q> const& v) + { + vec<2, T, Q> const C(1.0 / 6.0, 1.0 / 3.0); + vec<4, T, Q> const D(0.0, 0.5, 1.0, 2.0); + + // First corner + vec<3, T, Q> i(floor(v + dot(v, vec<3, T, Q>(C.y)))); + vec<3, T, Q> x0(v - i + dot(i, vec<3, T, Q>(C.x))); + + // Other corners + vec<3, T, Q> g(step(vec<3, T, Q>(x0.y, x0.z, x0.x), x0)); + vec<3, T, Q> l(T(1) - g); + vec<3, T, Q> i1(min(g, vec<3, T, Q>(l.z, l.x, l.y))); + vec<3, T, Q> i2(max(g, vec<3, T, Q>(l.z, l.x, l.y))); + + // x0 = x0 - 0.0 + 0.0 * C.xxx; + // x1 = x0 - i1 + 1.0 * C.xxx; + // x2 = x0 - i2 + 2.0 * C.xxx; + // x3 = x0 - 1.0 + 3.0 * C.xxx; + vec<3, T, Q> x1(x0 - i1 + C.x); + vec<3, T, Q> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y + vec<3, T, Q> x3(x0 - D.y); // -1.0+3.0*C.x = -0.5 = -D.y + + // Permutations + i = detail::mod289(i); + vec<4, T, Q> p(detail::permute(detail::permute(detail::permute( + i.z + vec<4, T, Q>(T(0), i1.z, i2.z, T(1))) + + i.y + vec<4, T, Q>(T(0), i1.y, i2.y, T(1))) + + i.x + vec<4, T, Q>(T(0), i1.x, i2.x, T(1)))); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + T n_ = static_cast(0.142857142857); // 1.0/7.0 + vec<3, T, Q> ns(n_ * vec<3, T, Q>(D.w, D.y, D.z) - vec<3, T, Q>(D.x, D.z, D.x)); + + vec<4, T, Q> j(p - T(49) * floor(p * ns.z * ns.z)); // mod(p,7*7) + + vec<4, T, Q> x_(floor(j * ns.z)); + vec<4, T, Q> y_(floor(j - T(7) * x_)); // mod(j,N) + + vec<4, T, Q> x(x_ * ns.x + ns.y); + vec<4, T, Q> y(y_ * ns.x + ns.y); + vec<4, T, Q> h(T(1) - abs(x) - abs(y)); + + vec<4, T, Q> b0(x.x, x.y, y.x, y.y); + vec<4, T, Q> b1(x.z, x.w, y.z, y.w); + + // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; + // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; + vec<4, T, Q> s0(floor(b0) * T(2) + T(1)); + vec<4, T, Q> s1(floor(b1) * T(2) + T(1)); + vec<4, T, Q> sh(-step(h, vec<4, T, Q>(0.0))); + + vec<4, T, Q> a0 = vec<4, T, Q>(b0.x, b0.z, b0.y, b0.w) + vec<4, T, Q>(s0.x, s0.z, s0.y, s0.w) * vec<4, T, Q>(sh.x, sh.x, sh.y, sh.y); + vec<4, T, Q> a1 = vec<4, T, Q>(b1.x, b1.z, b1.y, b1.w) + vec<4, T, Q>(s1.x, s1.z, s1.y, s1.w) * vec<4, T, Q>(sh.z, sh.z, sh.w, sh.w); + + vec<3, T, Q> p0(a0.x, a0.y, h.x); + vec<3, T, Q> p1(a0.z, a0.w, h.y); + vec<3, T, Q> p2(a1.x, a1.y, h.z); + vec<3, T, Q> p3(a1.z, a1.w, h.w); + + // Normalise gradients + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + vec<4, T, Q> m = max(T(0.6) - vec<4, T, Q>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), vec<4, T, Q>(0)); + m = m * m; + return T(42) * dot(m * m, vec<4, T, Q>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))); + } + + template + GLM_FUNC_QUALIFIER T simplex(vec<4, T, Q> const& v) + { + vec<4, T, Q> const C( + 0.138196601125011, // (5 - sqrt(5))/20 G4 + 0.276393202250021, // 2 * G4 + 0.414589803375032, // 3 * G4 + -0.447213595499958); // -1 + 4 * G4 + + // (sqrt(5) - 1)/4 = F4, used once below + T const F4 = static_cast(0.309016994374947451); + + // First corner + vec<4, T, Q> i = floor(v + dot(v, vec<4, T, Q>(F4))); + vec<4, T, Q> x0 = v - i + dot(i, vec<4, T, Q>(C.x)); + + // Other corners + + // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) + vec<4, T, Q> i0; + vec<3, T, Q> isX = step(vec<3, T, Q>(x0.y, x0.z, x0.w), vec<3, T, Q>(x0.x)); + vec<3, T, Q> isYZ = step(vec<3, T, Q>(x0.z, x0.w, x0.w), vec<3, T, Q>(x0.y, x0.y, x0.z)); + // i0.x = dot(isX, vec3(1.0)); + //i0.x = isX.x + isX.y + isX.z; + //i0.yzw = static_cast(1) - isX; + i0 = vec<4, T, Q>(isX.x + isX.y + isX.z, T(1) - isX); + // i0.y += dot(isYZ.xy, vec2(1.0)); + i0.y += isYZ.x + isYZ.y; + //i0.zw += 1.0 - vec<2, T, Q>(isYZ.x, isYZ.y); + i0.z += static_cast(1) - isYZ.x; + i0.w += static_cast(1) - isYZ.y; + i0.z += isYZ.z; + i0.w += static_cast(1) - isYZ.z; + + // i0 now contains the unique values 0,1,2,3 in each channel + vec<4, T, Q> i3 = clamp(i0, T(0), T(1)); + vec<4, T, Q> i2 = clamp(i0 - T(1), T(0), T(1)); + vec<4, T, Q> i1 = clamp(i0 - T(2), T(0), T(1)); + + // x0 = x0 - 0.0 + 0.0 * C.xxxx + // x1 = x0 - i1 + 0.0 * C.xxxx + // x2 = x0 - i2 + 0.0 * C.xxxx + // x3 = x0 - i3 + 0.0 * C.xxxx + // x4 = x0 - 1.0 + 4.0 * C.xxxx + vec<4, T, Q> x1 = x0 - i1 + C.x; + vec<4, T, Q> x2 = x0 - i2 + C.y; + vec<4, T, Q> x3 = x0 - i3 + C.z; + vec<4, T, Q> x4 = x0 + C.w; + + // Permutations + i = mod(i, vec<4, T, Q>(289)); + T j0 = detail::permute(detail::permute(detail::permute(detail::permute(i.w) + i.z) + i.y) + i.x); + vec<4, T, Q> j1 = detail::permute(detail::permute(detail::permute(detail::permute( + i.w + vec<4, T, Q>(i1.w, i2.w, i3.w, T(1))) + + i.z + vec<4, T, Q>(i1.z, i2.z, i3.z, T(1))) + + i.y + vec<4, T, Q>(i1.y, i2.y, i3.y, T(1))) + + i.x + vec<4, T, Q>(i1.x, i2.x, i3.x, T(1))); + + // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope + // 7*7*6 = 294, which is close to the ring size 17*17 = 289. + vec<4, T, Q> ip = vec<4, T, Q>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0)); + + vec<4, T, Q> p0 = gtc::grad4(j0, ip); + vec<4, T, Q> p1 = gtc::grad4(j1.x, ip); + vec<4, T, Q> p2 = gtc::grad4(j1.y, ip); + vec<4, T, Q> p3 = gtc::grad4(j1.z, ip); + vec<4, T, Q> p4 = gtc::grad4(j1.w, ip); + + // Normalise gradients + vec<4, T, Q> norm = detail::taylorInvSqrt(vec<4, T, Q>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + p4 *= detail::taylorInvSqrt(dot(p4, p4)); + + // Mix contributions from the five corners + vec<3, T, Q> m0 = max(T(0.6) - vec<3, T, Q>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), vec<3, T, Q>(0)); + vec<2, T, Q> m1 = max(T(0.6) - vec<2, T, Q>(dot(x3, x3), dot(x4, x4) ), vec<2, T, Q>(0)); + m0 = m0 * m0; + m1 = m1 * m1; + return T(49) * + (dot(m0 * m0, vec<3, T, Q>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + + dot(m1 * m1, vec<2, T, Q>(dot(p3, x3), dot(p4, x4)))); + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/packing.hpp b/vendor/glm/glm/gtc/packing.hpp new file mode 100644 index 0000000..8e416b3 --- /dev/null +++ b/vendor/glm/glm/gtc/packing.hpp @@ -0,0 +1,728 @@ +/// @ref gtc_packing +/// @file glm/gtc/packing.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_packing GLM_GTC_packing +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// This extension provides a set of function to convert vertors to packed +/// formats. + +#pragma once + +// Dependency: +#include "type_precision.hpp" +#include "../ext/vector_packing.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_packing extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_packing + /// @{ + + /// First, converts the normalized floating-point value v into a 8-bit integer value. + /// Then, the results are packed into the returned 8-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm1x8: round(clamp(c, 0, +1) * 255.0) + /// + /// @see gtc_packing + /// @see uint16 packUnorm2x8(vec2 const& v) + /// @see uint32 packUnorm4x8(vec4 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint8 packUnorm1x8(float v); + + /// Convert a single 8-bit integer to a normalized floating-point value. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x8(uint16 p) + /// @see vec4 unpackUnorm4x8(uint32 p) + /// @see GLSL unpackUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackUnorm1x8(uint8 p); + + /// First, converts each component of the normalized floating-point value v into 8-bit integer values. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm2x8: round(clamp(c, 0, +1) * 255.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint8 packUnorm1x8(float const& v) + /// @see uint32 packUnorm4x8(vec4 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packUnorm2x8(vec2 const& v); + + /// First, unpacks a single 16-bit unsigned integer p into a pair of 8-bit unsigned integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackUnorm1x8(uint8 v) + /// @see vec4 unpackUnorm4x8(uint32 p) + /// @see GLSL unpackUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackUnorm2x8(uint16 p); + + /// First, converts the normalized floating-point value v into 8-bit integer value. + /// Then, the results are packed into the returned 8-bit unsigned integer. + /// + /// The conversion to fixed point is done as follows: + /// packSnorm1x8: round(clamp(s, -1, +1) * 127.0) + /// + /// @see gtc_packing + /// @see uint16 packSnorm2x8(vec2 const& v) + /// @see uint32 packSnorm4x8(vec4 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint8 packSnorm1x8(float s); + + /// First, unpacks a single 8-bit unsigned integer p into a single 8-bit signed integers. + /// Then, the value is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm1x8: clamp(f / 127.0, -1, +1) + /// + /// @see gtc_packing + /// @see vec2 unpackSnorm2x8(uint16 p) + /// @see vec4 unpackSnorm4x8(uint32 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackSnorm1x8(uint8 p); + + /// First, converts each component of the normalized floating-point value v into 8-bit integer values. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x8: round(clamp(c, -1, +1) * 127.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint8 packSnorm1x8(float const& v) + /// @see uint32 packSnorm4x8(vec4 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packSnorm2x8(vec2 const& v); + + /// First, unpacks a single 16-bit unsigned integer p into a pair of 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm2x8: clamp(f / 127.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackSnorm1x8(uint8 p) + /// @see vec4 unpackSnorm4x8(uint32 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackSnorm2x8(uint16 p); + + /// First, converts the normalized floating-point value v into a 16-bit integer value. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm1x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// @see gtc_packing + /// @see uint16 packSnorm1x16(float const& v) + /// @see uint64 packSnorm4x16(vec4 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packUnorm1x16(float v); + + /// First, unpacks a single 16-bit unsigned integer p into a of 16-bit unsigned integers. + /// Then, the value is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm1x16: f / 65535.0 + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x16(uint32 p) + /// @see vec4 unpackUnorm4x16(uint64 p) + /// @see GLSL unpackUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackUnorm1x16(uint16 p); + + /// First, converts each component of the normalized floating-point value v into 16-bit integer values. + /// Then, the results are packed into the returned 64-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm4x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint16 packUnorm1x16(float const& v) + /// @see uint32 packUnorm2x16(vec2 const& v) + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint64 packUnorm4x16(vec4 const& v); + + /// First, unpacks a single 64-bit unsigned integer p into four 16-bit unsigned integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnormx4x16: f / 65535.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackUnorm1x16(uint16 p) + /// @see vec2 unpackUnorm2x16(uint32 p) + /// @see GLSL unpackUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackUnorm4x16(uint64 p); + + /// First, converts the normalized floating-point value v into 16-bit integer value. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion to fixed point is done as follows: + /// packSnorm1x8: round(clamp(s, -1, +1) * 32767.0) + /// + /// @see gtc_packing + /// @see uint32 packSnorm2x16(vec2 const& v) + /// @see uint64 packSnorm4x16(vec4 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packSnorm1x16(float v); + + /// First, unpacks a single 16-bit unsigned integer p into a single 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm1x16: clamp(f / 32767.0, -1, +1) + /// + /// @see gtc_packing + /// @see vec2 unpackSnorm2x16(uint32 p) + /// @see vec4 unpackSnorm4x16(uint64 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackSnorm1x16(uint16 p); + + /// First, converts each component of the normalized floating-point value v into 16-bit integer values. + /// Then, the results are packed into the returned 64-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x8: round(clamp(c, -1, +1) * 32767.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint16 packSnorm1x16(float const& v) + /// @see uint32 packSnorm2x16(vec2 const& v) + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint64 packSnorm4x16(vec4 const& v); + + /// First, unpacks a single 64-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm4x16: clamp(f / 32767.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackSnorm1x16(uint16 p) + /// @see vec2 unpackSnorm2x16(uint32 p) + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackSnorm4x16(uint64 p); + + /// Returns an unsigned integer obtained by converting the components of a floating-point scalar + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing this 16-bit value into a 16-bit unsigned integer. + /// + /// @see gtc_packing + /// @see uint32 packHalf2x16(vec2 const& v) + /// @see uint64 packHalf4x16(vec4 const& v) + /// @see GLSL packHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint16 packHalf1x16(float v); + + /// Returns a floating-point scalar with components obtained by unpacking a 16-bit unsigned integer into a 16-bit value, + /// interpreted as a 16-bit floating-point number according to the OpenGL Specification, + /// and converting it to 32-bit floating-point values. + /// + /// @see gtc_packing + /// @see vec2 unpackHalf2x16(uint32 const& v) + /// @see vec4 unpackHalf4x16(uint64 const& v) + /// @see GLSL unpackHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL float unpackHalf1x16(uint16 v); + + /// Returns an unsigned integer obtained by converting the components of a four-component floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing these four 16-bit values into a 64-bit unsigned integer. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the forth component specifies the 16 most-significant bits. + /// + /// @see gtc_packing + /// @see uint16 packHalf1x16(float const& v) + /// @see uint32 packHalf2x16(vec2 const& v) + /// @see GLSL packHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint64 packHalf4x16(vec4 const& v); + + /// Returns a four-component floating-point vector with components obtained by unpacking a 64-bit unsigned integer into four 16-bit values, + /// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification, + /// and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the forth component is obtained from the 16 most-significant bits of v. + /// + /// @see gtc_packing + /// @see float unpackHalf1x16(uint16 const& v) + /// @see vec2 unpackHalf2x16(uint32 const& v) + /// @see GLSL unpackHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackHalf4x16(uint64 p); + + /// Returns an unsigned integer obtained by converting the components of a four-component signed integer vector + /// to the 10-10-10-2-bit signed integer representation found in the OpenGL Specification, + /// and then packing these four values into a 32-bit unsigned integer. + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see uint32 packI3x10_1x2(uvec4 const& v) + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see ivec4 unpackI3x10_1x2(uint32 const& p) + GLM_FUNC_DECL uint32 packI3x10_1x2(ivec4 const& v); + + /// Unpacks a single 32-bit unsigned integer p into three 10-bit and one 2-bit signed integers. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see vec4 unpackSnorm3x10_1x2(uint32 const& p); + /// @see uvec4 unpackI3x10_1x2(uint32 const& p); + GLM_FUNC_DECL ivec4 unpackI3x10_1x2(uint32 p); + + /// Returns an unsigned integer obtained by converting the components of a four-component unsigned integer vector + /// to the 10-10-10-2-bit unsigned integer representation found in the OpenGL Specification, + /// and then packing these four values into a 32-bit unsigned integer. + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see uint32 packI3x10_1x2(ivec4 const& v) + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see ivec4 unpackU3x10_1x2(uint32 const& p) + GLM_FUNC_DECL uint32 packU3x10_1x2(uvec4 const& v); + + /// Unpacks a single 32-bit unsigned integer p into three 10-bit and one 2-bit unsigned integers. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see vec4 unpackSnorm3x10_1x2(uint32 const& p); + /// @see uvec4 unpackI3x10_1x2(uint32 const& p); + GLM_FUNC_DECL uvec4 unpackU3x10_1x2(uint32 p); + + /// First, converts the first three components of the normalized floating-point value v into 10-bit signed integer values. + /// Then, converts the forth component of the normalized floating-point value v into 2-bit signed integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm3x10_1x2(xyz): round(clamp(c, -1, +1) * 511.0) + /// packSnorm3x10_1x2(w): round(clamp(c, -1, +1) * 1.0) + /// + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see vec4 unpackSnorm3x10_1x2(uint32 const& p) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see uint32 packI3x10_1x2(ivec4 const& v) + GLM_FUNC_DECL uint32 packSnorm3x10_1x2(vec4 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm3x10_1x2(xyz): clamp(f / 511.0, -1, +1) + /// unpackSnorm3x10_1x2(w): clamp(f / 511.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see vec4 unpackUnorm3x10_1x2(uint32 const& p)) + /// @see uvec4 unpackI3x10_1x2(uint32 const& p) + /// @see uvec4 unpackU3x10_1x2(uint32 const& p) + GLM_FUNC_DECL vec4 unpackSnorm3x10_1x2(uint32 p); + + /// First, converts the first three components of the normalized floating-point value v into 10-bit unsigned integer values. + /// Then, converts the forth component of the normalized floating-point value v into 2-bit signed uninteger values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm3x10_1x2(xyz): round(clamp(c, 0, +1) * 1023.0) + /// packUnorm3x10_1x2(w): round(clamp(c, 0, +1) * 3.0) + /// + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see vec4 unpackUnorm3x10_1x2(uint32 const& p) + /// @see uint32 packUnorm3x10_1x2(vec4 const& v) + /// @see uint32 packU3x10_1x2(uvec4 const& v) + /// @see uint32 packI3x10_1x2(ivec4 const& v) + GLM_FUNC_DECL uint32 packUnorm3x10_1x2(vec4 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm3x10_1x2(xyz): clamp(f / 1023.0, 0, +1) + /// unpackSnorm3x10_1x2(w): clamp(f / 3.0, 0, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packSnorm3x10_1x2(vec4 const& v) + /// @see vec4 unpackInorm3x10_1x2(uint32 const& p)) + /// @see uvec4 unpackI3x10_1x2(uint32 const& p) + /// @see uvec4 unpackU3x10_1x2(uint32 const& p) + GLM_FUNC_DECL vec4 unpackUnorm3x10_1x2(uint32 p); + + /// First, converts the first two components of the normalized floating-point value v into 11-bit signless floating-point values. + /// Then, converts the third component of the normalized floating-point value v into a 10-bit signless floating-point value. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The first vector component specifies the 11 least-significant bits of the result; + /// the last component specifies the 10 most-significant bits. + /// + /// @see gtc_packing + /// @see vec3 unpackF2x11_1x10(uint32 const& p) + GLM_FUNC_DECL uint32 packF2x11_1x10(vec3 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into two 11-bit signless floating-point values and one 10-bit signless floating-point value . + /// Then, each component is converted to a normalized floating-point value to generate the returned three-component vector. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packF2x11_1x10(vec3 const& v) + GLM_FUNC_DECL vec3 unpackF2x11_1x10(uint32 p); + + + /// First, converts the first two components of the normalized floating-point value v into 11-bit signless floating-point values. + /// Then, converts the third component of the normalized floating-point value v into a 10-bit signless floating-point value. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The first vector component specifies the 11 least-significant bits of the result; + /// the last component specifies the 10 most-significant bits. + /// + /// packF3x9_E1x5 allows encoding into RGBE / RGB9E5 format + /// + /// @see gtc_packing + /// @see vec3 unpackF3x9_E1x5(uint32 const& p) + GLM_FUNC_DECL uint32 packF3x9_E1x5(vec3 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into two 11-bit signless floating-point values and one 10-bit signless floating-point value . + /// Then, each component is converted to a normalized floating-point value to generate the returned three-component vector. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// unpackF3x9_E1x5 allows decoding RGBE / RGB9E5 data + /// + /// @see gtc_packing + /// @see uint32 packF3x9_E1x5(vec3 const& v) + GLM_FUNC_DECL vec3 unpackF3x9_E1x5(uint32 p); + + /// Returns an unsigned integer vector obtained by converting the components of a floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the forth component specifies the 16 most-significant bits. + /// + /// @see gtc_packing + /// @see vec<3, T, Q> unpackRGBM(vec<4, T, Q> const& p) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec<4, T, Q> packRGBM(vec<3, T, Q> const& rgb); + + /// Returns a floating-point vector with components obtained by reinterpreting an integer vector as 16-bit floating-point numbers and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the forth component is obtained from the 16 most-significant bits of v. + /// + /// @see gtc_packing + /// @see vec<4, T, Q> packRGBM(vec<3, float, Q> const& v) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec<3, T, Q> unpackRGBM(vec<4, T, Q> const& rgbm); + + /// Returns an unsigned integer vector obtained by converting the components of a floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the forth component specifies the 16 most-significant bits. + /// + /// @see gtc_packing + /// @see vec unpackHalf(vec const& p) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec packHalf(vec const& v); + + /// Returns a floating-point vector with components obtained by reinterpreting an integer vector as 16-bit floating-point numbers and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the forth component is obtained from the 16 most-significant bits of v. + /// + /// @see gtc_packing + /// @see vec packHalf(vec const& v) + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + template + GLM_FUNC_DECL vec unpackHalf(vec const& p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec unpackUnorm(vec const& p); + template + GLM_FUNC_DECL vec packUnorm(vec const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see vec packUnorm(vec const& v) + template + GLM_FUNC_DECL vec unpackUnorm(vec const& v); + + /// Convert each component of the normalized floating-point vector into signed integer values. + /// + /// @see gtc_packing + /// @see vec unpackSnorm(vec const& p); + template + GLM_FUNC_DECL vec packSnorm(vec const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see vec packSnorm(vec const& v) + template + GLM_FUNC_DECL vec unpackSnorm(vec const& v); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x4(uint8 p) + GLM_FUNC_DECL uint8 packUnorm2x4(vec2 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint8 packUnorm2x4(vec2 const& v) + GLM_FUNC_DECL vec2 unpackUnorm2x4(uint8 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec4 unpackUnorm4x4(uint16 p) + GLM_FUNC_DECL uint16 packUnorm4x4(vec4 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint16 packUnorm4x4(vec4 const& v) + GLM_FUNC_DECL vec4 unpackUnorm4x4(uint16 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec3 unpackUnorm1x5_1x6_1x5(uint16 p) + GLM_FUNC_DECL uint16 packUnorm1x5_1x6_1x5(vec3 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint16 packUnorm1x5_1x6_1x5(vec3 const& v) + GLM_FUNC_DECL vec3 unpackUnorm1x5_1x6_1x5(uint16 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec4 unpackUnorm3x5_1x1(uint16 p) + GLM_FUNC_DECL uint16 packUnorm3x5_1x1(vec4 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint16 packUnorm3x5_1x1(vec4 const& v) + GLM_FUNC_DECL vec4 unpackUnorm3x5_1x1(uint16 p); + + /// Convert each component of the normalized floating-point vector into unsigned integer values. + /// + /// @see gtc_packing + /// @see vec3 unpackUnorm2x3_1x2(uint8 p) + GLM_FUNC_DECL uint8 packUnorm2x3_1x2(vec3 const& v); + + /// Convert a packed integer to a normalized floating-point vector. + /// + /// @see gtc_packing + /// @see uint8 packUnorm2x3_1x2(vec3 const& v) + GLM_FUNC_DECL vec3 unpackUnorm2x3_1x2(uint8 p); + + + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i8vec2 unpackInt2x8(int16 p) + GLM_FUNC_DECL int16 packInt2x8(i8vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int16 packInt2x8(i8vec2 const& v) + GLM_FUNC_DECL i8vec2 unpackInt2x8(int16 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u8vec2 unpackInt2x8(uint16 p) + GLM_FUNC_DECL uint16 packUint2x8(u8vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint16 packInt2x8(u8vec2 const& v) + GLM_FUNC_DECL u8vec2 unpackUint2x8(uint16 p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i8vec4 unpackInt4x8(int32 p) + GLM_FUNC_DECL int32 packInt4x8(i8vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int32 packInt2x8(i8vec4 const& v) + GLM_FUNC_DECL i8vec4 unpackInt4x8(int32 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u8vec4 unpackUint4x8(uint32 p) + GLM_FUNC_DECL uint32 packUint4x8(u8vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint32 packUint4x8(u8vec2 const& v) + GLM_FUNC_DECL u8vec4 unpackUint4x8(uint32 p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i16vec2 unpackInt2x16(int p) + GLM_FUNC_DECL int packInt2x16(i16vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int packInt2x16(i16vec2 const& v) + GLM_FUNC_DECL i16vec2 unpackInt2x16(int p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i16vec4 unpackInt4x16(int64 p) + GLM_FUNC_DECL int64 packInt4x16(i16vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int64 packInt4x16(i16vec4 const& v) + GLM_FUNC_DECL i16vec4 unpackInt4x16(int64 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u16vec2 unpackUint2x16(uint p) + GLM_FUNC_DECL uint packUint2x16(u16vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint packUint2x16(u16vec2 const& v) + GLM_FUNC_DECL u16vec2 unpackUint2x16(uint p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u16vec4 unpackUint4x16(uint64 p) + GLM_FUNC_DECL uint64 packUint4x16(u16vec4 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see uint64 packUint4x16(u16vec4 const& v) + GLM_FUNC_DECL u16vec4 unpackUint4x16(uint64 p); + + /// Convert each component from an integer vector into a packed integer. + /// + /// @see gtc_packing + /// @see i32vec2 unpackInt2x32(int p) + GLM_FUNC_DECL int64 packInt2x32(i32vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int packInt2x16(i32vec2 const& v) + GLM_FUNC_DECL i32vec2 unpackInt2x32(int64 p); + + /// Convert each component from an integer vector into a packed unsigned integer. + /// + /// @see gtc_packing + /// @see u32vec2 unpackUint2x32(int p) + GLM_FUNC_DECL uint64 packUint2x32(u32vec2 const& v); + + /// Convert a packed integer into an integer vector. + /// + /// @see gtc_packing + /// @see int packUint2x16(u32vec2 const& v) + GLM_FUNC_DECL u32vec2 unpackUint2x32(uint64 p); + + /// @} +}// namespace glm + +#include "packing.inl" diff --git a/vendor/glm/glm/gtc/packing.inl b/vendor/glm/glm/gtc/packing.inl new file mode 100644 index 0000000..8c906e1 --- /dev/null +++ b/vendor/glm/glm/gtc/packing.inl @@ -0,0 +1,938 @@ +/// @ref gtc_packing + +#include "../ext/scalar_relational.hpp" +#include "../ext/vector_relational.hpp" +#include "../common.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../detail/type_half.hpp" +#include +#include + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER glm::uint16 float2half(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((f >> 16) & 0x8000) | // sign + ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | // exponential + ((f >> 13) & 0x03ff); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 float2packed11(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x000007c0 => 00000000 00000000 00000111 11000000 + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((f & 0x7f800000) - 0x38000000) >> 17) & 0x07c0) | // exponential + ((f >> 17) & 0x003f); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 packed11ToFloat(glm::uint32 p) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x000007c0 => 00000000 00000000 00000111 11000000 + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((p & 0x07c0) << 17) + 0x38000000) & 0x7f800000) | // exponential + ((p & 0x003f) << 17); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 float2packed10(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x0000001F => 00000000 00000000 00000000 00011111 + // 0x0000003F => 00000000 00000000 00000000 00111111 + // 0x000003E0 => 00000000 00000000 00000011 11100000 + // 0x000007C0 => 00000000 00000000 00000111 11000000 + // 0x00007C00 => 00000000 00000000 01111100 00000000 + // 0x000003FF => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((f & 0x7f800000) - 0x38000000) >> 18) & 0x03E0) | // exponential + ((f >> 18) & 0x001f); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 packed10ToFloat(glm::uint32 p) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x0000001F => 00000000 00000000 00000000 00011111 + // 0x0000003F => 00000000 00000000 00000000 00111111 + // 0x000003E0 => 00000000 00000000 00000011 11100000 + // 0x000007C0 => 00000000 00000000 00000111 11000000 + // 0x00007C00 => 00000000 00000000 01111100 00000000 + // 0x000003FF => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((p & 0x03E0) << 18) + 0x38000000) & 0x7f800000) | // exponential + ((p & 0x001f) << 18); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint half2float(glm::uint h) + { + return ((h & 0x8000) << 16) | ((( h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13); + } + + GLM_FUNC_QUALIFIER glm::uint floatTo11bit(float x) + { + if(x == 0.0f) + return 0u; + else if(glm::isnan(x)) + return ~0u; + else if(glm::isinf(x)) + return 0x1Fu << 6u; + + uint Pack = 0u; + memcpy(&Pack, &x, sizeof(Pack)); + return float2packed11(Pack); + } + + GLM_FUNC_QUALIFIER float packed11bitToFloat(glm::uint x) + { + if(x == 0) + return 0.0f; + else if(x == ((1 << 11) - 1)) + return ~0;//NaN + else if(x == (0x1f << 6)) + return ~0;//Inf + + uint Result = packed11ToFloat(x); + + float Temp = 0; + memcpy(&Temp, &Result, sizeof(Temp)); + return Temp; + } + + GLM_FUNC_QUALIFIER glm::uint floatTo10bit(float x) + { + if(x == 0.0f) + return 0u; + else if(glm::isnan(x)) + return ~0u; + else if(glm::isinf(x)) + return 0x1Fu << 5u; + + uint Pack = 0; + memcpy(&Pack, &x, sizeof(Pack)); + return float2packed10(Pack); + } + + GLM_FUNC_QUALIFIER float packed10bitToFloat(glm::uint x) + { + if(x == 0) + return 0.0f; + else if(x == ((1 << 10) - 1)) + return ~0;//NaN + else if(x == (0x1f << 5)) + return ~0;//Inf + + uint Result = packed10ToFloat(x); + + float Temp = 0; + memcpy(&Temp, &Result, sizeof(Temp)); + return Temp; + } + +// GLM_FUNC_QUALIFIER glm::uint f11_f11_f10(float x, float y, float z) +// { +// return ((floatTo11bit(x) & ((1 << 11) - 1)) << 0) | ((floatTo11bit(y) & ((1 << 11) - 1)) << 11) | ((floatTo10bit(z) & ((1 << 10) - 1)) << 22); +// } + + union u3u3u2 + { + struct + { + uint x : 3; + uint y : 3; + uint z : 2; + } data; + uint8 pack; + }; + + union u4u4 + { + struct + { + uint x : 4; + uint y : 4; + } data; + uint8 pack; + }; + + union u4u4u4u4 + { + struct + { + uint x : 4; + uint y : 4; + uint z : 4; + uint w : 4; + } data; + uint16 pack; + }; + + union u5u6u5 + { + struct + { + uint x : 5; + uint y : 6; + uint z : 5; + } data; + uint16 pack; + }; + + union u5u5u5u1 + { + struct + { + uint x : 5; + uint y : 5; + uint z : 5; + uint w : 1; + } data; + uint16 pack; + }; + + union u10u10u10u2 + { + struct + { + uint x : 10; + uint y : 10; + uint z : 10; + uint w : 2; + } data; + uint32 pack; + }; + + union i10i10i10i2 + { + struct + { + int x : 10; + int y : 10; + int z : 10; + int w : 2; + } data; + uint32 pack; + }; + + union u9u9u9e5 + { + struct + { + uint x : 9; + uint y : 9; + uint z : 9; + uint w : 5; + } data; + uint32 pack; + }; + + template + struct compute_half + {}; + + template + struct compute_half<1, Q> + { + GLM_FUNC_QUALIFIER static vec<1, uint16, Q> pack(vec<1, float, Q> const& v) + { + int16 const Unpack(detail::toFloat16(v.x)); + u16vec1 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<1, float, Q> unpack(vec<1, uint16, Q> const& v) + { + i16vec1 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<1, float, Q>(detail::toFloat32(v.x)); + } + }; + + template + struct compute_half<2, Q> + { + GLM_FUNC_QUALIFIER static vec<2, uint16, Q> pack(vec<2, float, Q> const& v) + { + vec<2, int16, Q> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y)); + u16vec2 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<2, float, Q> unpack(vec<2, uint16, Q> const& v) + { + i16vec2 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<2, float, Q>(detail::toFloat32(v.x), detail::toFloat32(v.y)); + } + }; + + template + struct compute_half<3, Q> + { + GLM_FUNC_QUALIFIER static vec<3, uint16, Q> pack(vec<3, float, Q> const& v) + { + vec<3, int16, Q> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y), detail::toFloat16(v.z)); + u16vec3 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<3, float, Q> unpack(vec<3, uint16, Q> const& v) + { + i16vec3 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<3, float, Q>(detail::toFloat32(v.x), detail::toFloat32(v.y), detail::toFloat32(v.z)); + } + }; + + template + struct compute_half<4, Q> + { + GLM_FUNC_QUALIFIER static vec<4, uint16, Q> pack(vec<4, float, Q> const& v) + { + vec<4, int16, Q> const Unpack(detail::toFloat16(v.x), detail::toFloat16(v.y), detail::toFloat16(v.z), detail::toFloat16(v.w)); + u16vec4 Packed; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER static vec<4, float, Q> unpack(vec<4, uint16, Q> const& v) + { + i16vec4 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec<4, float, Q>(detail::toFloat32(v.x), detail::toFloat32(v.y), detail::toFloat32(v.z), detail::toFloat32(v.w)); + } + }; +}//namespace detail + + GLM_FUNC_QUALIFIER uint8 packUnorm1x8(float v) + { + return static_cast(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + } + + GLM_FUNC_QUALIFIER float unpackUnorm1x8(uint8 p) + { + float const Unpack(p); + return Unpack * static_cast(0.0039215686274509803921568627451); // 1 / 255 + } + + GLM_FUNC_QUALIFIER uint16 packUnorm2x8(vec2 const& v) + { + u8vec2 const Topack(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + + uint16 Unpack = 0; + memcpy(&Unpack, &Topack, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x8(uint16 p) + { + u8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return vec2(Unpack) * float(0.0039215686274509803921568627451); // 1 / 255 + } + + GLM_FUNC_QUALIFIER uint8 packSnorm1x8(float v) + { + int8 const Topack(static_cast(round(clamp(v ,-1.0f, 1.0f) * 127.0f))); + uint8 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER float unpackSnorm1x8(uint8 p) + { + int8 Unpack = 0; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + static_cast(Unpack) * 0.00787401574803149606299212598425f, // 1.0f / 127.0f + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packSnorm2x8(vec2 const& v) + { + i8vec2 const Topack(round(clamp(v, -1.0f, 1.0f) * 127.0f)); + uint16 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER vec2 unpackSnorm2x8(uint16 p) + { + i8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + vec2(Unpack) * 0.00787401574803149606299212598425f, // 1.0f / 127.0f + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packUnorm1x16(float s) + { + return static_cast(round(clamp(s, 0.0f, 1.0f) * 65535.0f)); + } + + GLM_FUNC_QUALIFIER float unpackUnorm1x16(uint16 p) + { + float const Unpack(p); + return Unpack * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 + } + + GLM_FUNC_QUALIFIER uint64 packUnorm4x16(vec4 const& v) + { + u16vec4 const Topack(round(clamp(v , 0.0f, 1.0f) * 65535.0f)); + uint64 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x16(uint64 p) + { + u16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return vec4(Unpack) * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 + } + + GLM_FUNC_QUALIFIER uint16 packSnorm1x16(float v) + { + int16 const Topack = static_cast(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); + uint16 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER float unpackSnorm1x16(uint16 p) + { + int16 Unpack = 0; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + static_cast(Unpack) * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint64 packSnorm4x16(vec4 const& v) + { + i16vec4 const Topack(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); + uint64 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER vec4 unpackSnorm4x16(uint64 p) + { + i16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return clamp( + vec4(Unpack) * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packHalf1x16(float v) + { + int16 const Topack(detail::toFloat16(v)); + uint16 Packed = 0; + memcpy(&Packed, &Topack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER float unpackHalf1x16(uint16 v) + { + int16 Unpack = 0; + memcpy(&Unpack, &v, sizeof(Unpack)); + return detail::toFloat32(Unpack); + } + + GLM_FUNC_QUALIFIER uint64 packHalf4x16(glm::vec4 const& v) + { + i16vec4 const Unpack( + detail::toFloat16(v.x), + detail::toFloat16(v.y), + detail::toFloat16(v.z), + detail::toFloat16(v.w)); + uint64 Packed = 0; + memcpy(&Packed, &Unpack, sizeof(Packed)); + return Packed; + } + + GLM_FUNC_QUALIFIER glm::vec4 unpackHalf4x16(uint64 v) + { + i16vec4 Unpack; + memcpy(&Unpack, &v, sizeof(Unpack)); + return vec4( + detail::toFloat32(Unpack.x), + detail::toFloat32(Unpack.y), + detail::toFloat32(Unpack.z), + detail::toFloat32(Unpack.w)); + } + + GLM_FUNC_QUALIFIER uint32 packI3x10_1x2(ivec4 const& v) + { + detail::i10i10i10i2 Result; + Result.data.x = v.x; + Result.data.y = v.y; + Result.data.z = v.z; + Result.data.w = v.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER ivec4 unpackI3x10_1x2(uint32 v) + { + detail::i10i10i10i2 Unpack; + Unpack.pack = v; + return ivec4( + Unpack.data.x, + Unpack.data.y, + Unpack.data.z, + Unpack.data.w); + } + + GLM_FUNC_QUALIFIER uint32 packU3x10_1x2(uvec4 const& v) + { + detail::u10u10u10u2 Result; + Result.data.x = v.x; + Result.data.y = v.y; + Result.data.z = v.z; + Result.data.w = v.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER uvec4 unpackU3x10_1x2(uint32 v) + { + detail::u10u10u10u2 Unpack; + Unpack.pack = v; + return uvec4( + Unpack.data.x, + Unpack.data.y, + Unpack.data.z, + Unpack.data.w); + } + + GLM_FUNC_QUALIFIER uint32 packSnorm3x10_1x2(vec4 const& v) + { + ivec4 const Pack(round(clamp(v,-1.0f, 1.0f) * vec4(511.f, 511.f, 511.f, 1.f))); + + detail::i10i10i10i2 Result; + Result.data.x = Pack.x; + Result.data.y = Pack.y; + Result.data.z = Pack.z; + Result.data.w = Pack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackSnorm3x10_1x2(uint32 v) + { + detail::i10i10i10i2 Unpack; + Unpack.pack = v; + + vec4 const Result(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w); + + return clamp(Result * vec4(1.f / 511.f, 1.f / 511.f, 1.f / 511.f, 1.f), -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint32 packUnorm3x10_1x2(vec4 const& v) + { + uvec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec4(1023.f, 1023.f, 1023.f, 3.f))); + + detail::u10u10u10u2 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + Result.data.w = Unpack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm3x10_1x2(uint32 v) + { + vec4 const ScaleFactors(1.0f / 1023.f, 1.0f / 1023.f, 1.0f / 1023.f, 1.0f / 3.f); + + detail::u10u10u10u2 Unpack; + Unpack.pack = v; + return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactors; + } + + GLM_FUNC_QUALIFIER uint32 packF2x11_1x10(vec3 const& v) + { + return + ((detail::floatTo11bit(v.x) & ((1 << 11) - 1)) << 0) | + ((detail::floatTo11bit(v.y) & ((1 << 11) - 1)) << 11) | + ((detail::floatTo10bit(v.z) & ((1 << 10) - 1)) << 22); + } + + GLM_FUNC_QUALIFIER vec3 unpackF2x11_1x10(uint32 v) + { + return vec3( + detail::packed11bitToFloat(v >> 0), + detail::packed11bitToFloat(v >> 11), + detail::packed10bitToFloat(v >> 22)); + } + + GLM_FUNC_QUALIFIER uint32 packF3x9_E1x5(vec3 const& v) + { + float const SharedExpMax = (pow(2.0f, 9.0f - 1.0f) / pow(2.0f, 9.0f)) * pow(2.0f, 31.f - 15.f); + vec3 const Color = clamp(v, 0.0f, SharedExpMax); + float const MaxColor = max(Color.x, max(Color.y, Color.z)); + + float const ExpSharedP = max(-15.f - 1.f, floor(log2(MaxColor))) + 1.0f + 15.f; + float const MaxShared = floor(MaxColor / pow(2.0f, (ExpSharedP - 15.f - 9.f)) + 0.5f); + float const ExpShared = equal(MaxShared, pow(2.0f, 9.0f), epsilon()) ? ExpSharedP + 1.0f : ExpSharedP; + + uvec3 const ColorComp(floor(Color / pow(2.f, (ExpShared - 15.f - 9.f)) + 0.5f)); + + detail::u9u9u9e5 Unpack; + Unpack.data.x = ColorComp.x; + Unpack.data.y = ColorComp.y; + Unpack.data.z = ColorComp.z; + Unpack.data.w = uint(ExpShared); + return Unpack.pack; + } + + GLM_FUNC_QUALIFIER vec3 unpackF3x9_E1x5(uint32 v) + { + detail::u9u9u9e5 Unpack; + Unpack.pack = v; + + return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * pow(2.0f, Unpack.data.w - 15.f - 9.f); + } + + // Based on Brian Karis http://graphicrants.blogspot.fr/2009/04/rgbm-color-encoding.html + template + GLM_FUNC_QUALIFIER vec<4, T, Q> packRGBM(vec<3, T, Q> const& rgb) + { + vec<3, T, Q> const Color(rgb * static_cast(1.0 / 6.0)); + T Alpha = clamp(max(max(Color.x, Color.y), max(Color.z, static_cast(1e-6))), static_cast(0), static_cast(1)); + Alpha = ceil(Alpha * static_cast(255.0)) / static_cast(255.0); + return vec<4, T, Q>(Color / Alpha, Alpha); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> unpackRGBM(vec<4, T, Q> const& rgbm) + { + return vec<3, T, Q>(rgbm.x, rgbm.y, rgbm.z) * rgbm.w * static_cast(6); + } + + template + GLM_FUNC_QUALIFIER vec packHalf(vec const& v) + { + return detail::compute_half::pack(v); + } + + template + GLM_FUNC_QUALIFIER vec unpackHalf(vec const& v) + { + return detail::compute_half::unpack(v); + } + + template + GLM_FUNC_QUALIFIER vec packUnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vec(round(clamp(v, static_cast(0), static_cast(1)) * static_cast(std::numeric_limits::max()))); + } + + template + GLM_FUNC_QUALIFIER vec unpackUnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vec(v) * (static_cast(1) / static_cast(std::numeric_limits::max())); + } + + template + GLM_FUNC_QUALIFIER vec packSnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return vec(round(clamp(v , static_cast(-1), static_cast(1)) * static_cast(std::numeric_limits::max()))); + } + + template + GLM_FUNC_QUALIFIER vec unpackSnorm(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "uintType must be an integer type"); + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "floatType must be a floating point type"); + + return clamp(vec(v) * (static_cast(1) / static_cast(std::numeric_limits::max())), static_cast(-1), static_cast(1)); + } + + GLM_FUNC_QUALIFIER uint8 packUnorm2x4(vec2 const& v) + { + u32vec2 const Unpack(round(clamp(v, 0.0f, 1.0f) * 15.0f)); + detail::u4u4 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x4(uint8 v) + { + float const ScaleFactor(1.f / 15.f); + detail::u4u4 Unpack; + Unpack.pack = v; + return vec2(Unpack.data.x, Unpack.data.y) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint16 packUnorm4x4(vec4 const& v) + { + u32vec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * 15.0f)); + detail::u4u4u4u4 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + Result.data.w = Unpack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x4(uint16 v) + { + float const ScaleFactor(1.f / 15.f); + detail::u4u4u4u4 Unpack; + Unpack.pack = v; + return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint16 packUnorm1x5_1x6_1x5(vec3 const& v) + { + u32vec3 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec3(31.f, 63.f, 31.f))); + detail::u5u6u5 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec3 unpackUnorm1x5_1x6_1x5(uint16 v) + { + vec3 const ScaleFactor(1.f / 31.f, 1.f / 63.f, 1.f / 31.f); + detail::u5u6u5 Unpack; + Unpack.pack = v; + return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint16 packUnorm3x5_1x1(vec4 const& v) + { + u32vec4 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec4(31.f, 31.f, 31.f, 1.f))); + detail::u5u5u5u1 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + Result.data.w = Unpack.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm3x5_1x1(uint16 v) + { + vec4 const ScaleFactor(1.f / 31.f, 1.f / 31.f, 1.f / 31.f, 1.f); + detail::u5u5u5u1 Unpack; + Unpack.pack = v; + return vec4(Unpack.data.x, Unpack.data.y, Unpack.data.z, Unpack.data.w) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER uint8 packUnorm2x3_1x2(vec3 const& v) + { + u32vec3 const Unpack(round(clamp(v, 0.0f, 1.0f) * vec3(7.f, 7.f, 3.f))); + detail::u3u3u2 Result; + Result.data.x = Unpack.x; + Result.data.y = Unpack.y; + Result.data.z = Unpack.z; + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec3 unpackUnorm2x3_1x2(uint8 v) + { + vec3 const ScaleFactor(1.f / 7.f, 1.f / 7.f, 1.f / 3.f); + detail::u3u3u2 Unpack; + Unpack.pack = v; + return vec3(Unpack.data.x, Unpack.data.y, Unpack.data.z) * ScaleFactor; + } + + GLM_FUNC_QUALIFIER int16 packInt2x8(i8vec2 const& v) + { + int16 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i8vec2 unpackInt2x8(int16 p) + { + i8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint16 packUint2x8(u8vec2 const& v) + { + uint16 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u8vec2 unpackUint2x8(uint16 p) + { + u8vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int32 packInt4x8(i8vec4 const& v) + { + int32 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i8vec4 unpackInt4x8(int32 p) + { + i8vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint32 packUint4x8(u8vec4 const& v) + { + uint32 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u8vec4 unpackUint4x8(uint32 p) + { + u8vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int packInt2x16(i16vec2 const& v) + { + int Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i16vec2 unpackInt2x16(int p) + { + i16vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int64 packInt4x16(i16vec4 const& v) + { + int64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i16vec4 unpackInt4x16(int64 p) + { + i16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint packUint2x16(u16vec2 const& v) + { + uint Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u16vec2 unpackUint2x16(uint p) + { + u16vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint64 packUint4x16(u16vec4 const& v) + { + uint64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u16vec4 unpackUint4x16(uint64 p) + { + u16vec4 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER int64 packInt2x32(i32vec2 const& v) + { + int64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER i32vec2 unpackInt2x32(int64 p) + { + i32vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } + + GLM_FUNC_QUALIFIER uint64 packUint2x32(u32vec2 const& v) + { + uint64 Pack = 0; + memcpy(&Pack, &v, sizeof(Pack)); + return Pack; + } + + GLM_FUNC_QUALIFIER u32vec2 unpackUint2x32(uint64 p) + { + u32vec2 Unpack; + memcpy(&Unpack, &p, sizeof(Unpack)); + return Unpack; + } +}//namespace glm + diff --git a/vendor/glm/glm/gtc/quaternion.hpp b/vendor/glm/glm/gtc/quaternion.hpp new file mode 100644 index 0000000..359e072 --- /dev/null +++ b/vendor/glm/glm/gtc/quaternion.hpp @@ -0,0 +1,173 @@ +/// @ref gtc_quaternion +/// @file glm/gtc/quaternion.hpp +/// +/// @see core (dependence) +/// @see gtc_constants (dependence) +/// +/// @defgroup gtc_quaternion GLM_GTC_quaternion +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines a templated quaternion type and several quaternion operations. + +#pragma once + +// Dependency: +#include "../gtc/constants.hpp" +#include "../gtc/matrix_transform.hpp" +#include "../ext/vector_relational.hpp" +#include "../ext/quaternion_common.hpp" +#include "../ext/quaternion_float.hpp" +#include "../ext/quaternion_float_precision.hpp" +#include "../ext/quaternion_double.hpp" +#include "../ext/quaternion_double_precision.hpp" +#include "../ext/quaternion_relational.hpp" +#include "../ext/quaternion_geometric.hpp" +#include "../ext/quaternion_trigonometric.hpp" +#include "../ext/quaternion_transform.hpp" +#include "../detail/type_mat3x3.hpp" +#include "../detail/type_mat4x4.hpp" +#include "../detail/type_vec3.hpp" +#include "../detail/type_vec4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_quaternion extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_quaternion + /// @{ + + /// Returns euler angles, pitch as x, yaw as y, roll as z. + /// The result is expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL vec<3, T, Q> eulerAngles(qua const& x); + + /// Returns roll value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL T roll(qua const& x); + + /// Returns pitch value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL T pitch(qua const& x); + + /// Returns yaw value of euler angles expressed in radians. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL T yaw(qua const& x); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL mat<3, 3, T, Q> mat3_cast(qua const& x); + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL mat<4, 4, T, Q> mat4_cast(qua const& x); + + /// Converts a pure rotation 3 * 3 matrix to a quaternion. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL qua quat_cast(mat<3, 3, T, Q> const& x); + + /// Converts a pure rotation 4 * 4 matrix to a quaternion. + /// + /// @tparam T Floating-point scalar types. + /// + /// @see gtc_quaternion + template + GLM_FUNC_DECL qua quat_cast(mat<4, 4, T, Q> const& x); + + /// Returns the component-wise comparison result of x < y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL vec<4, bool, Q> lessThan(qua const& x, qua const& y); + + /// Returns the component-wise comparison of result x <= y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL vec<4, bool, Q> lessThanEqual(qua const& x, qua const& y); + + /// Returns the component-wise comparison of result x > y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL vec<4, bool, Q> greaterThan(qua const& x, qua const& y); + + /// Returns the component-wise comparison of result x >= y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_quaternion_relational + template + GLM_FUNC_DECL vec<4, bool, Q> greaterThanEqual(qua const& x, qua const& y); + + /// Build a look at quaternion based on the default handedness. + /// + /// @param direction Desired forward direction. Needs to be normalized. + /// @param up Up vector, how the camera is oriented. Typically (0, 1, 0). + template + GLM_FUNC_DECL qua quatLookAt( + vec<3, T, Q> const& direction, + vec<3, T, Q> const& up); + + /// Build a right-handed look at quaternion. + /// + /// @param direction Desired forward direction onto which the -z-axis gets mapped. Needs to be normalized. + /// @param up Up vector, how the camera is oriented. Typically (0, 1, 0). + template + GLM_FUNC_DECL qua quatLookAtRH( + vec<3, T, Q> const& direction, + vec<3, T, Q> const& up); + + /// Build a left-handed look at quaternion. + /// + /// @param direction Desired forward direction onto which the +z-axis gets mapped. Needs to be normalized. + /// @param up Up vector, how the camera is oriented. Typically (0, 1, 0). + template + GLM_FUNC_DECL qua quatLookAtLH( + vec<3, T, Q> const& direction, + vec<3, T, Q> const& up); + /// @} +} //namespace glm + +#include "quaternion.inl" diff --git a/vendor/glm/glm/gtc/quaternion.inl b/vendor/glm/glm/gtc/quaternion.inl new file mode 100644 index 0000000..06f9f02 --- /dev/null +++ b/vendor/glm/glm/gtc/quaternion.inl @@ -0,0 +1,202 @@ +#include "../trigonometric.hpp" +#include "../geometric.hpp" +#include "../exponential.hpp" +#include "epsilon.hpp" +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> eulerAngles(qua const& x) + { + return vec<3, T, Q>(pitch(x), yaw(x), roll(x)); + } + + template + GLM_FUNC_QUALIFIER T roll(qua const& q) + { + return static_cast(atan(static_cast(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); + } + + template + GLM_FUNC_QUALIFIER T pitch(qua const& q) + { + //return T(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); + T const y = static_cast(2) * (q.y * q.z + q.w * q.x); + T const x = q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z; + + if(all(equal(vec<2, T, Q>(x, y), vec<2, T, Q>(0), epsilon()))) //avoid atan2(0,0) - handle singularity - Matiis + return static_cast(static_cast(2) * atan(q.x, q.w)); + + return static_cast(atan(y, x)); + } + + template + GLM_FUNC_QUALIFIER T yaw(qua const& q) + { + return asin(clamp(static_cast(-2) * (q.x * q.z - q.w * q.y), static_cast(-1), static_cast(1))); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> mat3_cast(qua const& q) + { + mat<3, 3, T, Q> Result(T(1)); + T qxx(q.x * q.x); + T qyy(q.y * q.y); + T qzz(q.z * q.z); + T qxz(q.x * q.z); + T qxy(q.x * q.y); + T qyz(q.y * q.z); + T qwx(q.w * q.x); + T qwy(q.w * q.y); + T qwz(q.w * q.z); + + Result[0][0] = T(1) - T(2) * (qyy + qzz); + Result[0][1] = T(2) * (qxy + qwz); + Result[0][2] = T(2) * (qxz - qwy); + + Result[1][0] = T(2) * (qxy - qwz); + Result[1][1] = T(1) - T(2) * (qxx + qzz); + Result[1][2] = T(2) * (qyz + qwx); + + Result[2][0] = T(2) * (qxz + qwy); + Result[2][1] = T(2) * (qyz - qwx); + Result[2][2] = T(1) - T(2) * (qxx + qyy); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> mat4_cast(qua const& q) + { + return mat<4, 4, T, Q>(mat3_cast(q)); + } + + template + GLM_FUNC_QUALIFIER qua quat_cast(mat<3, 3, T, Q> const& m) + { + T fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2]; + T fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2]; + T fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1]; + T fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2]; + + int biggestIndex = 0; + T fourBiggestSquaredMinus1 = fourWSquaredMinus1; + if(fourXSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourXSquaredMinus1; + biggestIndex = 1; + } + if(fourYSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourYSquaredMinus1; + biggestIndex = 2; + } + if(fourZSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourZSquaredMinus1; + biggestIndex = 3; + } + + T biggestVal = sqrt(fourBiggestSquaredMinus1 + static_cast(1)) * static_cast(0.5); + T mult = static_cast(0.25) / biggestVal; + + switch(biggestIndex) + { + case 0: + return qua(biggestVal, (m[1][2] - m[2][1]) * mult, (m[2][0] - m[0][2]) * mult, (m[0][1] - m[1][0]) * mult); + case 1: + return qua((m[1][2] - m[2][1]) * mult, biggestVal, (m[0][1] + m[1][0]) * mult, (m[2][0] + m[0][2]) * mult); + case 2: + return qua((m[2][0] - m[0][2]) * mult, (m[0][1] + m[1][0]) * mult, biggestVal, (m[1][2] + m[2][1]) * mult); + case 3: + return qua((m[0][1] - m[1][0]) * mult, (m[2][0] + m[0][2]) * mult, (m[1][2] + m[2][1]) * mult, biggestVal); + default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity. + assert(false); + return qua(1, 0, 0, 0); + } + } + + template + GLM_FUNC_QUALIFIER qua quat_cast(mat<4, 4, T, Q> const& m4) + { + return quat_cast(mat<3, 3, T, Q>(m4)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThan(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] < y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> lessThanEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThan(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> greaterThanEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result; + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] >= y[i]; + return Result; + } + + + template + GLM_FUNC_QUALIFIER qua quatLookAt(vec<3, T, Q> const& direction, vec<3, T, Q> const& up) + { +# if GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT + return quatLookAtLH(direction, up); +# else + return quatLookAtRH(direction, up); +# endif + } + + template + GLM_FUNC_QUALIFIER qua quatLookAtRH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up) + { + mat<3, 3, T, Q> Result; + + Result[2] = -direction; + vec<3, T, Q> const& Right = cross(up, Result[2]); + Result[0] = Right * inversesqrt(max(static_cast(0.00001), dot(Right, Right))); + Result[1] = cross(Result[2], Result[0]); + + return quat_cast(Result); + } + + template + GLM_FUNC_QUALIFIER qua quatLookAtLH(vec<3, T, Q> const& direction, vec<3, T, Q> const& up) + { + mat<3, 3, T, Q> Result; + + Result[2] = direction; + vec<3, T, Q> const& Right = cross(up, Result[2]); + Result[0] = Right * inversesqrt(max(static_cast(0.00001), dot(Right, Right))); + Result[1] = cross(Result[2], Result[0]); + + return quat_cast(Result); + } +}//namespace glm + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "quaternion_simd.inl" +#endif + diff --git a/vendor/glm/glm/gtc/quaternion_simd.inl b/vendor/glm/glm/gtc/quaternion_simd.inl new file mode 100644 index 0000000..e69de29 diff --git a/vendor/glm/glm/gtc/random.hpp b/vendor/glm/glm/gtc/random.hpp new file mode 100644 index 0000000..9a85958 --- /dev/null +++ b/vendor/glm/glm/gtc/random.hpp @@ -0,0 +1,82 @@ +/// @ref gtc_random +/// @file glm/gtc/random.hpp +/// +/// @see core (dependence) +/// @see gtx_random (extended) +/// +/// @defgroup gtc_random GLM_GTC_random +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Generate random number from various distribution methods. + +#pragma once + +// Dependency: +#include "../ext/scalar_int_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_random extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_random + /// @{ + + /// Generate random numbers in the interval [Min, Max], according a linear distribution + /// + /// @param Min Minimum value included in the sampling + /// @param Max Maximum value included in the sampling + /// @tparam genType Value type. Currently supported: float or double scalars. + /// @see gtc_random + template + GLM_FUNC_DECL genType linearRand(genType Min, genType Max); + + /// Generate random numbers in the interval [Min, Max], according a linear distribution + /// + /// @param Min Minimum value included in the sampling + /// @param Max Maximum value included in the sampling + /// @tparam T Value type. Currently supported: float or double. + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec linearRand(vec const& Min, vec const& Max); + + /// Generate random numbers in the interval [Min, Max], according a gaussian distribution + /// + /// @see gtc_random + template + GLM_FUNC_DECL genType gaussRand(genType Mean, genType Deviation); + + /// Generate a random 2D vector which coordinates are regulary distributed on a circle of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<2, T, defaultp> circularRand(T Radius); + + /// Generate a random 3D vector which coordinates are regulary distributed on a sphere of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<3, T, defaultp> sphericalRand(T Radius); + + /// Generate a random 2D vector which coordinates are regulary distributed within the area of a disk of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<2, T, defaultp> diskRand(T Radius); + + /// Generate a random 3D vector which coordinates are regulary distributed within the volume of a ball of a given radius + /// + /// @see gtc_random + template + GLM_FUNC_DECL vec<3, T, defaultp> ballRand(T Radius); + + /// @} +}//namespace glm + +#include "random.inl" diff --git a/vendor/glm/glm/gtc/random.inl b/vendor/glm/glm/gtc/random.inl new file mode 100644 index 0000000..7048509 --- /dev/null +++ b/vendor/glm/glm/gtc/random.inl @@ -0,0 +1,303 @@ +#include "../geometric.hpp" +#include "../exponential.hpp" +#include "../trigonometric.hpp" +#include "../detail/type_vec1.hpp" +#include +#include +#include +#include + +namespace glm{ +namespace detail +{ + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call(); + }; + + template + struct compute_rand<1, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<1, uint8, P> call() + { + return vec<1, uint8, P>( + std::rand() % std::numeric_limits::max()); + } + }; + + template + struct compute_rand<2, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<2, uint8, P> call() + { + return vec<2, uint8, P>( + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max()); + } + }; + + template + struct compute_rand<3, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<3, uint8, P> call() + { + return vec<3, uint8, P>( + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max()); + } + }; + + template + struct compute_rand<4, uint8, P> + { + GLM_FUNC_QUALIFIER static vec<4, uint8, P> call() + { + return vec<4, uint8, P>( + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max(), + std::rand() % std::numeric_limits::max()); + } + }; + + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call() + { + return + (vec(compute_rand::call()) << static_cast(8)) | + (vec(compute_rand::call()) << static_cast(0)); + } + }; + + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call() + { + return + (vec(compute_rand::call()) << static_cast(16)) | + (vec(compute_rand::call()) << static_cast(0)); + } + }; + + template + struct compute_rand + { + GLM_FUNC_QUALIFIER static vec call() + { + return + (vec(compute_rand::call()) << static_cast(32)) | + (vec(compute_rand::call()) << static_cast(0)); + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max); + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (vec(compute_rand::call() % vec(Max + static_cast(1) - Min))) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return (compute_rand::call() % (Max + static_cast(1) - Min)) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return vec(compute_rand::call()) / static_cast(std::numeric_limits::max()) * (Max - Min) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return vec(compute_rand::call()) / static_cast(std::numeric_limits::max()) * (Max - Min) + Min; + } + }; + + template + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vec call(vec const& Min, vec const& Max) + { + return vec(compute_rand::call()) / static_cast(std::numeric_limits::max()) * (Max - Min) + Min; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER genType linearRand(genType Min, genType Max) + { + return detail::compute_linearRand<1, genType, highp>::call( + vec<1, genType, highp>(Min), + vec<1, genType, highp>(Max)).x; + } + + template + GLM_FUNC_QUALIFIER vec linearRand(vec const& Min, vec const& Max) + { + return detail::compute_linearRand::call(Min, Max); + } + + template + GLM_FUNC_QUALIFIER genType gaussRand(genType Mean, genType Deviation) + { + genType w, x1, x2; + + do + { + x1 = linearRand(genType(-1), genType(1)); + x2 = linearRand(genType(-1), genType(1)); + + w = x1 * x1 + x2 * x2; + } while(w > genType(1)); + + return static_cast(x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean); + } + + template + GLM_FUNC_QUALIFIER vec gaussRand(vec const& Mean, vec const& Deviation) + { + return detail::functor2::call(gaussRand, Mean, Deviation); + } + + template + GLM_FUNC_QUALIFIER vec<2, T, defaultp> diskRand(T Radius) + { + assert(Radius > static_cast(0)); + + vec<2, T, defaultp> Result(T(0)); + T LenRadius(T(0)); + + do + { + Result = linearRand( + vec<2, T, defaultp>(-Radius), + vec<2, T, defaultp>(Radius)); + LenRadius = length(Result); + } + while(LenRadius > Radius); + + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, defaultp> ballRand(T Radius) + { + assert(Radius > static_cast(0)); + + vec<3, T, defaultp> Result(T(0)); + T LenRadius(T(0)); + + do + { + Result = linearRand( + vec<3, T, defaultp>(-Radius), + vec<3, T, defaultp>(Radius)); + LenRadius = length(Result); + } + while(LenRadius > Radius); + + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, defaultp> circularRand(T Radius) + { + assert(Radius > static_cast(0)); + + T a = linearRand(T(0), static_cast(6.283185307179586476925286766559)); + return vec<2, T, defaultp>(glm::cos(a), glm::sin(a)) * Radius; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, defaultp> sphericalRand(T Radius) + { + assert(Radius > static_cast(0)); + + T theta = linearRand(T(0), T(6.283185307179586476925286766559f)); + T phi = std::acos(linearRand(T(-1.0f), T(1.0f))); + + T x = std::sin(phi) * std::cos(theta); + T y = std::sin(phi) * std::sin(theta); + T z = std::cos(phi); + + return vec<3, T, defaultp>(x, y, z) * Radius; + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/reciprocal.hpp b/vendor/glm/glm/gtc/reciprocal.hpp new file mode 100644 index 0000000..c7d1330 --- /dev/null +++ b/vendor/glm/glm/gtc/reciprocal.hpp @@ -0,0 +1,135 @@ +/// @ref gtc_reciprocal +/// @file glm/gtc/reciprocal.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_reciprocal GLM_GTC_reciprocal +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Define secant, cosecant and cotangent functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_reciprocal extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_reciprocal + /// @{ + + /// Secant function. + /// hypotenuse / adjacent or 1 / cos(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType sec(genType angle); + + /// Cosecant function. + /// hypotenuse / opposite or 1 / sin(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType csc(genType angle); + + /// Cotangent function. + /// adjacent / opposite or 1 / tan(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType cot(genType angle); + + /// Inverse secant function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType asec(genType x); + + /// Inverse cosecant function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType acsc(genType x); + + /// Inverse cotangent function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType acot(genType x); + + /// Secant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType sech(genType angle); + + /// Cosecant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType csch(genType angle); + + /// Cotangent hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType coth(genType angle); + + /// Inverse secant hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType asech(genType x); + + /// Inverse cosecant hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType acsch(genType x); + + /// Inverse cotangent hyperbolic function. + /// + /// @return Return an angle expressed in radians. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see gtc_reciprocal + template + GLM_FUNC_DECL genType acoth(genType x); + + /// @} +}//namespace glm + +#include "reciprocal.inl" diff --git a/vendor/glm/glm/gtc/reciprocal.inl b/vendor/glm/glm/gtc/reciprocal.inl new file mode 100644 index 0000000..d88729e --- /dev/null +++ b/vendor/glm/glm/gtc/reciprocal.inl @@ -0,0 +1,191 @@ +/// @ref gtc_reciprocal + +#include "../trigonometric.hpp" +#include + +namespace glm +{ + // sec + template + GLM_FUNC_QUALIFIER genType sec(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'sec' only accept floating-point values"); + return genType(1) / glm::cos(angle); + } + + template + GLM_FUNC_QUALIFIER vec sec(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'sec' only accept floating-point inputs"); + return detail::functor1::call(sec, x); + } + + // csc + template + GLM_FUNC_QUALIFIER genType csc(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'csc' only accept floating-point values"); + return genType(1) / glm::sin(angle); + } + + template + GLM_FUNC_QUALIFIER vec csc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'csc' only accept floating-point inputs"); + return detail::functor1::call(csc, x); + } + + // cot + template + GLM_FUNC_QUALIFIER genType cot(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'cot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return glm::tan(pi_over_2 - angle); + } + + template + GLM_FUNC_QUALIFIER vec cot(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'cot' only accept floating-point inputs"); + return detail::functor1::call(cot, x); + } + + // asec + template + GLM_FUNC_QUALIFIER genType asec(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'asec' only accept floating-point values"); + return acos(genType(1) / x); + } + + template + GLM_FUNC_QUALIFIER vec asec(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'asec' only accept floating-point inputs"); + return detail::functor1::call(asec, x); + } + + // acsc + template + GLM_FUNC_QUALIFIER genType acsc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acsc' only accept floating-point values"); + return asin(genType(1) / x); + } + + template + GLM_FUNC_QUALIFIER vec acsc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acsc' only accept floating-point inputs"); + return detail::functor1::call(acsc, x); + } + + // acot + template + GLM_FUNC_QUALIFIER genType acot(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return pi_over_2 - atan(x); + } + + template + GLM_FUNC_QUALIFIER vec acot(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acot' only accept floating-point inputs"); + return detail::functor1::call(acot, x); + } + + // sech + template + GLM_FUNC_QUALIFIER genType sech(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'sech' only accept floating-point values"); + return genType(1) / glm::cosh(angle); + } + + template + GLM_FUNC_QUALIFIER vec sech(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'sech' only accept floating-point inputs"); + return detail::functor1::call(sech, x); + } + + // csch + template + GLM_FUNC_QUALIFIER genType csch(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'csch' only accept floating-point values"); + return genType(1) / glm::sinh(angle); + } + + template + GLM_FUNC_QUALIFIER vec csch(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'csch' only accept floating-point inputs"); + return detail::functor1::call(csch, x); + } + + // coth + template + GLM_FUNC_QUALIFIER genType coth(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'coth' only accept floating-point values"); + return glm::cosh(angle) / glm::sinh(angle); + } + + template + GLM_FUNC_QUALIFIER vec coth(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'coth' only accept floating-point inputs"); + return detail::functor1::call(coth, x); + } + + // asech + template + GLM_FUNC_QUALIFIER genType asech(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'asech' only accept floating-point values"); + return acosh(genType(1) / x); + } + + template + GLM_FUNC_QUALIFIER vec asech(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'asech' only accept floating-point inputs"); + return detail::functor1::call(asech, x); + } + + // acsch + template + GLM_FUNC_QUALIFIER genType acsch(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acsch' only accept floating-point values"); + return asinh(genType(1) / x); + } + + template + GLM_FUNC_QUALIFIER vec acsch(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acsch' only accept floating-point inputs"); + return detail::functor1::call(acsch, x); + } + + // acoth + template + GLM_FUNC_QUALIFIER genType acoth(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acoth' only accept floating-point values"); + return atanh(genType(1) / x); + } + + template + GLM_FUNC_QUALIFIER vec acoth(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'acoth' only accept floating-point inputs"); + return detail::functor1::call(acoth, x); + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/round.hpp b/vendor/glm/glm/gtc/round.hpp new file mode 100644 index 0000000..56edbbc --- /dev/null +++ b/vendor/glm/glm/gtc/round.hpp @@ -0,0 +1,160 @@ +/// @ref gtc_round +/// @file glm/gtc/round.hpp +/// +/// @see core (dependence) +/// @see gtc_round (dependence) +/// +/// @defgroup gtc_round GLM_GTC_round +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Rounding value to specific boundings + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_round extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_round + /// @{ + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @see gtc_round + template + GLM_FUNC_DECL genIUType ceilPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec ceilPowerOfTwo(vec const& v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @see gtc_round + template + GLM_FUNC_DECL genIUType floorPowerOfTwo(genIUType v); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec floorPowerOfTwo(vec const& v); + + /// Return the power of two number which value is the closet to the input value. + /// + /// @see gtc_round + template + GLM_FUNC_DECL genIUType roundPowerOfTwo(genIUType v); + + /// Return the power of two number which value is the closet to the input value. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec roundPowerOfTwo(vec const& v); + + /// Higher multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL genType ceilMultiple(genType v, genType Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec ceilMultiple(vec const& v, vec const& Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL genType floorMultiple(genType v, genType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec floorMultiple(vec const& v, vec const& Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// + /// @param v Source value to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL genType roundMultiple(genType v, genType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @param v Source values to which is applied the function + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template + GLM_FUNC_DECL vec roundMultiple(vec const& v, vec const& Multiple); + + /// @} +} //namespace glm + +#include "round.inl" diff --git a/vendor/glm/glm/gtc/round.inl b/vendor/glm/glm/gtc/round.inl new file mode 100644 index 0000000..48411e4 --- /dev/null +++ b/vendor/glm/glm/gtc/round.inl @@ -0,0 +1,155 @@ +/// @ref gtc_round + +#include "../integer.hpp" +#include "../ext/vector_integer.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_roundMultiple {}; + + template<> + struct compute_roundMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if (Source >= genType(0)) + return Source - std::fmod(Source, Multiple); + else + { + genType Tmp = Source + genType(1); + return Tmp - std::fmod(Tmp, Multiple) - Multiple; + } + } + }; + + template<> + struct compute_roundMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if (Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; + + template<> + struct compute_roundMultiple + { + template + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if (Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; +}//namespace detail + + ////////////////// + // ceilPowerOfTwo + + template + GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value) + { + return detail::compute_ceilPowerOfTwo<1, genType, defaultp, std::numeric_limits::is_signed>::call(vec<1, genType, defaultp>(value)).x; + } + + template + GLM_FUNC_QUALIFIER vec ceilPowerOfTwo(vec const& v) + { + return detail::compute_ceilPowerOfTwo::is_signed>::call(v); + } + + /////////////////// + // floorPowerOfTwo + + template + GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value) + { + return isPowerOfTwo(value) ? value : static_cast(1) << findMSB(value); + } + + template + GLM_FUNC_QUALIFIER vec floorPowerOfTwo(vec const& v) + { + return detail::functor1::call(floorPowerOfTwo, v); + } + + /////////////////// + // roundPowerOfTwo + + template + GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value) + { + if(isPowerOfTwo(value)) + return value; + + genIUType const prev = static_cast(1) << findMSB(value); + genIUType const next = prev << static_cast(1); + return (next - value) < (value - prev) ? next : prev; + } + + template + GLM_FUNC_QUALIFIER vec roundPowerOfTwo(vec const& v) + { + return detail::functor1::call(roundPowerOfTwo, v); + } + + ////////////////////// + // ceilMultiple + + template + GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple) + { + return detail::compute_ceilMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec ceilMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(ceilMultiple, Source, Multiple); + } + + ////////////////////// + // floorMultiple + + template + GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple) + { + return detail::compute_floorMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec floorMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(floorMultiple, Source, Multiple); + } + + ////////////////////// + // roundMultiple + + template + GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple) + { + return detail::compute_roundMultiple::is_iec559, std::numeric_limits::is_signed>::call(Source, Multiple); + } + + template + GLM_FUNC_QUALIFIER vec roundMultiple(vec const& Source, vec const& Multiple) + { + return detail::functor2::call(roundMultiple, Source, Multiple); + } +}//namespace glm diff --git a/vendor/glm/glm/gtc/type_aligned.hpp b/vendor/glm/glm/gtc/type_aligned.hpp new file mode 100644 index 0000000..5403abf --- /dev/null +++ b/vendor/glm/glm/gtc/type_aligned.hpp @@ -0,0 +1,1315 @@ +/// @ref gtc_type_aligned +/// @file glm/gtc/type_aligned.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_type_aligned GLM_GTC_type_aligned +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Aligned types allowing SIMD optimizations of vectors and matrices types + +#pragma once + +#if (GLM_CONFIG_ALIGNED_GENTYPES == GLM_DISABLE) +# error "GLM: Aligned gentypes require to enable C++ language extensions. Define GLM_FORCE_ALIGNED_GENTYPES before including GLM headers to use aligned types." +#endif + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_type_aligned extension included") +#endif + +#include "../mat4x4.hpp" +#include "../mat4x3.hpp" +#include "../mat4x2.hpp" +#include "../mat3x4.hpp" +#include "../mat3x3.hpp" +#include "../mat3x2.hpp" +#include "../mat2x4.hpp" +#include "../mat2x3.hpp" +#include "../mat2x2.hpp" +#include "../gtc/vec1.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" + +namespace glm +{ + /// @addtogroup gtc_type_aligned + /// @{ + + // -- *vec1 -- + + /// 1 component vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, float, aligned_highp> aligned_highp_vec1; + + /// 1 component vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, float, aligned_mediump> aligned_mediump_vec1; + + /// 1 component vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, float, aligned_lowp> aligned_lowp_vec1; + + /// 1 component vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, double, aligned_highp> aligned_highp_dvec1; + + /// 1 component vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, double, aligned_mediump> aligned_mediump_dvec1; + + /// 1 component vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, double, aligned_lowp> aligned_lowp_dvec1; + + /// 1 component vector aligned in memory of signed integer numbers. + typedef vec<1, int, aligned_highp> aligned_highp_ivec1; + + /// 1 component vector aligned in memory of signed integer numbers. + typedef vec<1, int, aligned_mediump> aligned_mediump_ivec1; + + /// 1 component vector aligned in memory of signed integer numbers. + typedef vec<1, int, aligned_lowp> aligned_lowp_ivec1; + + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef vec<1, uint, aligned_highp> aligned_highp_uvec1; + + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef vec<1, uint, aligned_mediump> aligned_mediump_uvec1; + + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef vec<1, uint, aligned_lowp> aligned_lowp_uvec1; + + /// 1 component vector aligned in memory of bool values. + typedef vec<1, bool, aligned_highp> aligned_highp_bvec1; + + /// 1 component vector aligned in memory of bool values. + typedef vec<1, bool, aligned_mediump> aligned_mediump_bvec1; + + /// 1 component vector aligned in memory of bool values. + typedef vec<1, bool, aligned_lowp> aligned_lowp_bvec1; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, float, packed_highp> packed_highp_vec1; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, float, packed_mediump> packed_mediump_vec1; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, float, packed_lowp> packed_lowp_vec1; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<1, double, packed_highp> packed_highp_dvec1; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<1, double, packed_mediump> packed_mediump_dvec1; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<1, double, packed_lowp> packed_lowp_dvec1; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef vec<1, int, packed_highp> packed_highp_ivec1; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef vec<1, int, packed_mediump> packed_mediump_ivec1; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef vec<1, int, packed_lowp> packed_lowp_ivec1; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef vec<1, uint, packed_highp> packed_highp_uvec1; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef vec<1, uint, packed_mediump> packed_mediump_uvec1; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef vec<1, uint, packed_lowp> packed_lowp_uvec1; + + /// 1 component vector tightly packed in memory of bool values. + typedef vec<1, bool, packed_highp> packed_highp_bvec1; + + /// 1 component vector tightly packed in memory of bool values. + typedef vec<1, bool, packed_mediump> packed_mediump_bvec1; + + /// 1 component vector tightly packed in memory of bool values. + typedef vec<1, bool, packed_lowp> packed_lowp_bvec1; + + // -- *vec2 -- + + /// 2 components vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, float, aligned_highp> aligned_highp_vec2; + + /// 2 components vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, float, aligned_mediump> aligned_mediump_vec2; + + /// 2 components vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, float, aligned_lowp> aligned_lowp_vec2; + + /// 2 components vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, double, aligned_highp> aligned_highp_dvec2; + + /// 2 components vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, double, aligned_mediump> aligned_mediump_dvec2; + + /// 2 components vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, double, aligned_lowp> aligned_lowp_dvec2; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef vec<2, int, aligned_highp> aligned_highp_ivec2; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef vec<2, int, aligned_mediump> aligned_mediump_ivec2; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef vec<2, int, aligned_lowp> aligned_lowp_ivec2; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef vec<2, uint, aligned_highp> aligned_highp_uvec2; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef vec<2, uint, aligned_mediump> aligned_mediump_uvec2; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef vec<2, uint, aligned_lowp> aligned_lowp_uvec2; + + /// 2 components vector aligned in memory of bool values. + typedef vec<2, bool, aligned_highp> aligned_highp_bvec2; + + /// 2 components vector aligned in memory of bool values. + typedef vec<2, bool, aligned_mediump> aligned_mediump_bvec2; + + /// 2 components vector aligned in memory of bool values. + typedef vec<2, bool, aligned_lowp> aligned_lowp_bvec2; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, float, packed_highp> packed_highp_vec2; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, float, packed_mediump> packed_mediump_vec2; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, float, packed_lowp> packed_lowp_vec2; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<2, double, packed_highp> packed_highp_dvec2; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<2, double, packed_mediump> packed_mediump_dvec2; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<2, double, packed_lowp> packed_lowp_dvec2; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef vec<2, int, packed_highp> packed_highp_ivec2; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef vec<2, int, packed_mediump> packed_mediump_ivec2; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef vec<2, int, packed_lowp> packed_lowp_ivec2; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<2, uint, packed_highp> packed_highp_uvec2; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<2, uint, packed_mediump> packed_mediump_uvec2; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<2, uint, packed_lowp> packed_lowp_uvec2; + + /// 2 components vector tightly packed in memory of bool values. + typedef vec<2, bool, packed_highp> packed_highp_bvec2; + + /// 2 components vector tightly packed in memory of bool values. + typedef vec<2, bool, packed_mediump> packed_mediump_bvec2; + + /// 2 components vector tightly packed in memory of bool values. + typedef vec<2, bool, packed_lowp> packed_lowp_bvec2; + + // -- *vec3 -- + + /// 3 components vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, float, aligned_highp> aligned_highp_vec3; + + /// 3 components vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, float, aligned_mediump> aligned_mediump_vec3; + + /// 3 components vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, float, aligned_lowp> aligned_lowp_vec3; + + /// 3 components vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, double, aligned_highp> aligned_highp_dvec3; + + /// 3 components vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, double, aligned_mediump> aligned_mediump_dvec3; + + /// 3 components vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, double, aligned_lowp> aligned_lowp_dvec3; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef vec<3, int, aligned_highp> aligned_highp_ivec3; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef vec<3, int, aligned_mediump> aligned_mediump_ivec3; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef vec<3, int, aligned_lowp> aligned_lowp_ivec3; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef vec<3, uint, aligned_highp> aligned_highp_uvec3; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef vec<3, uint, aligned_mediump> aligned_mediump_uvec3; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef vec<3, uint, aligned_lowp> aligned_lowp_uvec3; + + /// 3 components vector aligned in memory of bool values. + typedef vec<3, bool, aligned_highp> aligned_highp_bvec3; + + /// 3 components vector aligned in memory of bool values. + typedef vec<3, bool, aligned_mediump> aligned_mediump_bvec3; + + /// 3 components vector aligned in memory of bool values. + typedef vec<3, bool, aligned_lowp> aligned_lowp_bvec3; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, float, packed_highp> packed_highp_vec3; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, float, packed_mediump> packed_mediump_vec3; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, float, packed_lowp> packed_lowp_vec3; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<3, double, packed_highp> packed_highp_dvec3; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<3, double, packed_mediump> packed_mediump_dvec3; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<3, double, packed_lowp> packed_lowp_dvec3; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef vec<3, int, packed_highp> packed_highp_ivec3; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef vec<3, int, packed_mediump> packed_mediump_ivec3; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef vec<3, int, packed_lowp> packed_lowp_ivec3; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<3, uint, packed_highp> packed_highp_uvec3; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<3, uint, packed_mediump> packed_mediump_uvec3; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<3, uint, packed_lowp> packed_lowp_uvec3; + + /// 3 components vector tightly packed in memory of bool values. + typedef vec<3, bool, packed_highp> packed_highp_bvec3; + + /// 3 components vector tightly packed in memory of bool values. + typedef vec<3, bool, packed_mediump> packed_mediump_bvec3; + + /// 3 components vector tightly packed in memory of bool values. + typedef vec<3, bool, packed_lowp> packed_lowp_bvec3; + + // -- *vec4 -- + + /// 4 components vector aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, float, aligned_highp> aligned_highp_vec4; + + /// 4 components vector aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, float, aligned_mediump> aligned_mediump_vec4; + + /// 4 components vector aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, float, aligned_lowp> aligned_lowp_vec4; + + /// 4 components vector aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, double, aligned_highp> aligned_highp_dvec4; + + /// 4 components vector aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, double, aligned_mediump> aligned_mediump_dvec4; + + /// 4 components vector aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, double, aligned_lowp> aligned_lowp_dvec4; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef vec<4, int, aligned_highp> aligned_highp_ivec4; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef vec<4, int, aligned_mediump> aligned_mediump_ivec4; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef vec<4, int, aligned_lowp> aligned_lowp_ivec4; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef vec<4, uint, aligned_highp> aligned_highp_uvec4; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef vec<4, uint, aligned_mediump> aligned_mediump_uvec4; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef vec<4, uint, aligned_lowp> aligned_lowp_uvec4; + + /// 4 components vector aligned in memory of bool values. + typedef vec<4, bool, aligned_highp> aligned_highp_bvec4; + + /// 4 components vector aligned in memory of bool values. + typedef vec<4, bool, aligned_mediump> aligned_mediump_bvec4; + + /// 4 components vector aligned in memory of bool values. + typedef vec<4, bool, aligned_lowp> aligned_lowp_bvec4; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, float, packed_highp> packed_highp_vec4; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, float, packed_mediump> packed_mediump_vec4; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, float, packed_lowp> packed_lowp_vec4; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef vec<4, double, packed_highp> packed_highp_dvec4; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef vec<4, double, packed_mediump> packed_mediump_dvec4; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef vec<4, double, packed_lowp> packed_lowp_dvec4; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef vec<4, int, packed_highp> packed_highp_ivec4; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef vec<4, int, packed_mediump> packed_mediump_ivec4; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef vec<4, int, packed_lowp> packed_lowp_ivec4; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<4, uint, packed_highp> packed_highp_uvec4; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<4, uint, packed_mediump> packed_mediump_uvec4; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef vec<4, uint, packed_lowp> packed_lowp_uvec4; + + /// 4 components vector tightly packed in memory of bool values. + typedef vec<4, bool, packed_highp> packed_highp_bvec4; + + /// 4 components vector tightly packed in memory of bool values. + typedef vec<4, bool, packed_mediump> packed_mediump_bvec4; + + /// 4 components vector tightly packed in memory of bool values. + typedef vec<4, bool, packed_lowp> packed_lowp_bvec4; + + // -- *mat2 -- + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_highp> aligned_highp_mat2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_mediump> aligned_mediump_mat2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_lowp> aligned_lowp_mat2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_highp> aligned_highp_dmat2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_mediump> aligned_mediump_dmat2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_lowp> aligned_lowp_dmat2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_highp> packed_highp_mat2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_mediump> packed_mediump_mat2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_lowp> packed_lowp_mat2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_highp> packed_highp_dmat2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_mediump> packed_mediump_dmat2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_lowp> packed_lowp_dmat2; + + // -- *mat3 -- + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_highp> aligned_highp_mat3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_mediump> aligned_mediump_mat3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_lowp> aligned_lowp_mat3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_highp> aligned_highp_dmat3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_mediump> aligned_mediump_dmat3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_lowp> aligned_lowp_dmat3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_highp> packed_highp_mat3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_mediump> packed_mediump_mat3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_lowp> packed_lowp_mat3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_highp> packed_highp_dmat3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_mediump> packed_mediump_dmat3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_lowp> packed_lowp_dmat3; + + // -- *mat4 -- + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_highp> aligned_highp_mat4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_mediump> aligned_mediump_mat4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_lowp> aligned_lowp_mat4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_highp> aligned_highp_dmat4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_mediump> aligned_mediump_dmat4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_lowp> aligned_lowp_dmat4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_highp> packed_highp_mat4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_mediump> packed_mediump_mat4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_lowp> packed_lowp_mat4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_highp> packed_highp_dmat4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_mediump> packed_mediump_dmat4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_lowp> packed_lowp_dmat4; + + // -- *mat2x2 -- + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_highp> aligned_highp_mat2x2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_mediump> aligned_mediump_mat2x2; + + /// 2 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, aligned_lowp> aligned_lowp_mat2x2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_highp> aligned_highp_dmat2x2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_mediump> aligned_mediump_dmat2x2; + + /// 2 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, aligned_lowp> aligned_lowp_dmat2x2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_highp> packed_highp_mat2x2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_mediump> packed_mediump_mat2x2; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, float, packed_lowp> packed_lowp_mat2x2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_highp> packed_highp_dmat2x2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_mediump> packed_mediump_dmat2x2; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 2, double, packed_lowp> packed_lowp_dmat2x2; + + // -- *mat2x3 -- + + /// 2 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, float, aligned_highp> aligned_highp_mat2x3; + + /// 2 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, float, aligned_mediump> aligned_mediump_mat2x3; + + /// 2 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, float, aligned_lowp> aligned_lowp_mat2x3; + + /// 2 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, double, aligned_highp> aligned_highp_dmat2x3; + + /// 2 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, double, aligned_mediump> aligned_mediump_dmat2x3; + + /// 2 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, double, aligned_lowp> aligned_lowp_dmat2x3; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, float, packed_highp> packed_highp_mat2x3; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, float, packed_mediump> packed_mediump_mat2x3; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, float, packed_lowp> packed_lowp_mat2x3; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 3, double, packed_highp> packed_highp_dmat2x3; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 3, double, packed_mediump> packed_mediump_dmat2x3; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 3, double, packed_lowp> packed_lowp_dmat2x3; + + // -- *mat2x4 -- + + /// 2 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, float, aligned_highp> aligned_highp_mat2x4; + + /// 2 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, float, aligned_mediump> aligned_mediump_mat2x4; + + /// 2 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, float, aligned_lowp> aligned_lowp_mat2x4; + + /// 2 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, double, aligned_highp> aligned_highp_dmat2x4; + + /// 2 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, double, aligned_mediump> aligned_mediump_dmat2x4; + + /// 2 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, double, aligned_lowp> aligned_lowp_dmat2x4; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, float, packed_highp> packed_highp_mat2x4; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, float, packed_mediump> packed_mediump_mat2x4; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, float, packed_lowp> packed_lowp_mat2x4; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<2, 4, double, packed_highp> packed_highp_dmat2x4; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<2, 4, double, packed_mediump> packed_mediump_dmat2x4; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<2, 4, double, packed_lowp> packed_lowp_dmat2x4; + + // -- *mat3x2 -- + + /// 3 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, float, aligned_highp> aligned_highp_mat3x2; + + /// 3 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, float, aligned_mediump> aligned_mediump_mat3x2; + + /// 3 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, float, aligned_lowp> aligned_lowp_mat3x2; + + /// 3 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, double, aligned_highp> aligned_highp_dmat3x2; + + /// 3 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, double, aligned_mediump> aligned_mediump_dmat3x2; + + /// 3 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, double, aligned_lowp> aligned_lowp_dmat3x2; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, float, packed_highp> packed_highp_mat3x2; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, float, packed_mediump> packed_mediump_mat3x2; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, float, packed_lowp> packed_lowp_mat3x2; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 2, double, packed_highp> packed_highp_dmat3x2; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 2, double, packed_mediump> packed_mediump_dmat3x2; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 2, double, packed_lowp> packed_lowp_dmat3x2; + + // -- *mat3x3 -- + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_highp> aligned_highp_mat3x3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_mediump> aligned_mediump_mat3x3; + + /// 3 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, aligned_lowp> aligned_lowp_mat3x3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_highp> aligned_highp_dmat3x3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_mediump> aligned_mediump_dmat3x3; + + /// 3 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, aligned_lowp> aligned_lowp_dmat3x3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_highp> packed_highp_mat3x3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_mediump> packed_mediump_mat3x3; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, float, packed_lowp> packed_lowp_mat3x3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_highp> packed_highp_dmat3x3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_mediump> packed_mediump_dmat3x3; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 3, double, packed_lowp> packed_lowp_dmat3x3; + + // -- *mat3x4 -- + + /// 3 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, float, aligned_highp> aligned_highp_mat3x4; + + /// 3 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, float, aligned_mediump> aligned_mediump_mat3x4; + + /// 3 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, float, aligned_lowp> aligned_lowp_mat3x4; + + /// 3 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, double, aligned_highp> aligned_highp_dmat3x4; + + /// 3 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, double, aligned_mediump> aligned_mediump_dmat3x4; + + /// 3 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, double, aligned_lowp> aligned_lowp_dmat3x4; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, float, packed_highp> packed_highp_mat3x4; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, float, packed_mediump> packed_mediump_mat3x4; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, float, packed_lowp> packed_lowp_mat3x4; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<3, 4, double, packed_highp> packed_highp_dmat3x4; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<3, 4, double, packed_mediump> packed_mediump_dmat3x4; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<3, 4, double, packed_lowp> packed_lowp_dmat3x4; + + // -- *mat4x2 -- + + /// 4 by 2 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, float, aligned_highp> aligned_highp_mat4x2; + + /// 4 by 2 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, float, aligned_mediump> aligned_mediump_mat4x2; + + /// 4 by 2 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, float, aligned_lowp> aligned_lowp_mat4x2; + + /// 4 by 2 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, double, aligned_highp> aligned_highp_dmat4x2; + + /// 4 by 2 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, double, aligned_mediump> aligned_mediump_dmat4x2; + + /// 4 by 2 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, double, aligned_lowp> aligned_lowp_dmat4x2; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, float, packed_highp> packed_highp_mat4x2; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, float, packed_mediump> packed_mediump_mat4x2; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, float, packed_lowp> packed_lowp_mat4x2; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 2, double, packed_highp> packed_highp_dmat4x2; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 2, double, packed_mediump> packed_mediump_dmat4x2; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 2, double, packed_lowp> packed_lowp_dmat4x2; + + // -- *mat4x3 -- + + /// 4 by 3 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, float, aligned_highp> aligned_highp_mat4x3; + + /// 4 by 3 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, float, aligned_mediump> aligned_mediump_mat4x3; + + /// 4 by 3 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, float, aligned_lowp> aligned_lowp_mat4x3; + + /// 4 by 3 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, double, aligned_highp> aligned_highp_dmat4x3; + + /// 4 by 3 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, double, aligned_mediump> aligned_mediump_dmat4x3; + + /// 4 by 3 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, double, aligned_lowp> aligned_lowp_dmat4x3; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, float, packed_highp> packed_highp_mat4x3; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, float, packed_mediump> packed_mediump_mat4x3; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, float, packed_lowp> packed_lowp_mat4x3; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 3, double, packed_highp> packed_highp_dmat4x3; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 3, double, packed_mediump> packed_mediump_dmat4x3; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 3, double, packed_lowp> packed_lowp_dmat4x3; + + // -- *mat4x4 -- + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_highp> aligned_highp_mat4x4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_mediump> aligned_mediump_mat4x4; + + /// 4 by 4 matrix aligned in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, aligned_lowp> aligned_lowp_mat4x4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_highp> aligned_highp_dmat4x4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_mediump> aligned_mediump_dmat4x4; + + /// 4 by 4 matrix aligned in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, aligned_lowp> aligned_lowp_dmat4x4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_highp> packed_highp_mat4x4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_mediump> packed_mediump_mat4x4; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, float, packed_lowp> packed_lowp_mat4x4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using high precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_highp> packed_highp_dmat4x4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using medium precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_mediump> packed_mediump_dmat4x4; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers using low precision arithmetic in term of ULPs. + typedef mat<4, 4, double, packed_lowp> packed_lowp_dmat4x4; + + // -- default -- + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + typedef aligned_lowp_vec1 aligned_vec1; + typedef aligned_lowp_vec2 aligned_vec2; + typedef aligned_lowp_vec3 aligned_vec3; + typedef aligned_lowp_vec4 aligned_vec4; + typedef packed_lowp_vec1 packed_vec1; + typedef packed_lowp_vec2 packed_vec2; + typedef packed_lowp_vec3 packed_vec3; + typedef packed_lowp_vec4 packed_vec4; + + typedef aligned_lowp_mat2 aligned_mat2; + typedef aligned_lowp_mat3 aligned_mat3; + typedef aligned_lowp_mat4 aligned_mat4; + typedef packed_lowp_mat2 packed_mat2; + typedef packed_lowp_mat3 packed_mat3; + typedef packed_lowp_mat4 packed_mat4; + + typedef aligned_lowp_mat2x2 aligned_mat2x2; + typedef aligned_lowp_mat2x3 aligned_mat2x3; + typedef aligned_lowp_mat2x4 aligned_mat2x4; + typedef aligned_lowp_mat3x2 aligned_mat3x2; + typedef aligned_lowp_mat3x3 aligned_mat3x3; + typedef aligned_lowp_mat3x4 aligned_mat3x4; + typedef aligned_lowp_mat4x2 aligned_mat4x2; + typedef aligned_lowp_mat4x3 aligned_mat4x3; + typedef aligned_lowp_mat4x4 aligned_mat4x4; + typedef packed_lowp_mat2x2 packed_mat2x2; + typedef packed_lowp_mat2x3 packed_mat2x3; + typedef packed_lowp_mat2x4 packed_mat2x4; + typedef packed_lowp_mat3x2 packed_mat3x2; + typedef packed_lowp_mat3x3 packed_mat3x3; + typedef packed_lowp_mat3x4 packed_mat3x4; + typedef packed_lowp_mat4x2 packed_mat4x2; + typedef packed_lowp_mat4x3 packed_mat4x3; + typedef packed_lowp_mat4x4 packed_mat4x4; +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + typedef aligned_mediump_vec1 aligned_vec1; + typedef aligned_mediump_vec2 aligned_vec2; + typedef aligned_mediump_vec3 aligned_vec3; + typedef aligned_mediump_vec4 aligned_vec4; + typedef packed_mediump_vec1 packed_vec1; + typedef packed_mediump_vec2 packed_vec2; + typedef packed_mediump_vec3 packed_vec3; + typedef packed_mediump_vec4 packed_vec4; + + typedef aligned_mediump_mat2 aligned_mat2; + typedef aligned_mediump_mat3 aligned_mat3; + typedef aligned_mediump_mat4 aligned_mat4; + typedef packed_mediump_mat2 packed_mat2; + typedef packed_mediump_mat3 packed_mat3; + typedef packed_mediump_mat4 packed_mat4; + + typedef aligned_mediump_mat2x2 aligned_mat2x2; + typedef aligned_mediump_mat2x3 aligned_mat2x3; + typedef aligned_mediump_mat2x4 aligned_mat2x4; + typedef aligned_mediump_mat3x2 aligned_mat3x2; + typedef aligned_mediump_mat3x3 aligned_mat3x3; + typedef aligned_mediump_mat3x4 aligned_mat3x4; + typedef aligned_mediump_mat4x2 aligned_mat4x2; + typedef aligned_mediump_mat4x3 aligned_mat4x3; + typedef aligned_mediump_mat4x4 aligned_mat4x4; + typedef packed_mediump_mat2x2 packed_mat2x2; + typedef packed_mediump_mat2x3 packed_mat2x3; + typedef packed_mediump_mat2x4 packed_mat2x4; + typedef packed_mediump_mat3x2 packed_mat3x2; + typedef packed_mediump_mat3x3 packed_mat3x3; + typedef packed_mediump_mat3x4 packed_mat3x4; + typedef packed_mediump_mat4x2 packed_mat4x2; + typedef packed_mediump_mat4x3 packed_mat4x3; + typedef packed_mediump_mat4x4 packed_mat4x4; +#else //defined(GLM_PRECISION_HIGHP_FLOAT) + /// 1 component vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec1 aligned_vec1; + + /// 2 components vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec2 aligned_vec2; + + /// 3 components vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec3 aligned_vec3; + + /// 4 components vector aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_vec4 aligned_vec4; + + /// 1 component vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec1 packed_vec1; + + /// 2 components vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec2 packed_vec2; + + /// 3 components vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec3 packed_vec3; + + /// 4 components vector tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_vec4 packed_vec4; + + /// 2 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2 aligned_mat2; + + /// 3 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3 aligned_mat3; + + /// 4 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4 aligned_mat4; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2 packed_mat2; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3 packed_mat3; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4 packed_mat4; + + /// 2 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2x2 aligned_mat2x2; + + /// 2 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2x3 aligned_mat2x3; + + /// 2 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat2x4 aligned_mat2x4; + + /// 3 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3x2 aligned_mat3x2; + + /// 3 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3x3 aligned_mat3x3; + + /// 3 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat3x4 aligned_mat3x4; + + /// 4 by 2 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4x2 aligned_mat4x2; + + /// 4 by 3 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4x3 aligned_mat4x3; + + /// 4 by 4 matrix tightly aligned in memory of single-precision floating-point numbers. + typedef aligned_highp_mat4x4 aligned_mat4x4; + + /// 2 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2x2 packed_mat2x2; + + /// 2 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2x3 packed_mat2x3; + + /// 2 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat2x4 packed_mat2x4; + + /// 3 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3x2 packed_mat3x2; + + /// 3 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3x3 packed_mat3x3; + + /// 3 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat3x4 packed_mat3x4; + + /// 4 by 2 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4x2 packed_mat4x2; + + /// 4 by 3 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4x3 packed_mat4x3; + + /// 4 by 4 matrix tightly packed in memory of single-precision floating-point numbers. + typedef packed_highp_mat4x4 packed_mat4x4; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef aligned_lowp_dvec1 aligned_dvec1; + typedef aligned_lowp_dvec2 aligned_dvec2; + typedef aligned_lowp_dvec3 aligned_dvec3; + typedef aligned_lowp_dvec4 aligned_dvec4; + typedef packed_lowp_dvec1 packed_dvec1; + typedef packed_lowp_dvec2 packed_dvec2; + typedef packed_lowp_dvec3 packed_dvec3; + typedef packed_lowp_dvec4 packed_dvec4; + + typedef aligned_lowp_dmat2 aligned_dmat2; + typedef aligned_lowp_dmat3 aligned_dmat3; + typedef aligned_lowp_dmat4 aligned_dmat4; + typedef packed_lowp_dmat2 packed_dmat2; + typedef packed_lowp_dmat3 packed_dmat3; + typedef packed_lowp_dmat4 packed_dmat4; + + typedef aligned_lowp_dmat2x2 aligned_dmat2x2; + typedef aligned_lowp_dmat2x3 aligned_dmat2x3; + typedef aligned_lowp_dmat2x4 aligned_dmat2x4; + typedef aligned_lowp_dmat3x2 aligned_dmat3x2; + typedef aligned_lowp_dmat3x3 aligned_dmat3x3; + typedef aligned_lowp_dmat3x4 aligned_dmat3x4; + typedef aligned_lowp_dmat4x2 aligned_dmat4x2; + typedef aligned_lowp_dmat4x3 aligned_dmat4x3; + typedef aligned_lowp_dmat4x4 aligned_dmat4x4; + typedef packed_lowp_dmat2x2 packed_dmat2x2; + typedef packed_lowp_dmat2x3 packed_dmat2x3; + typedef packed_lowp_dmat2x4 packed_dmat2x4; + typedef packed_lowp_dmat3x2 packed_dmat3x2; + typedef packed_lowp_dmat3x3 packed_dmat3x3; + typedef packed_lowp_dmat3x4 packed_dmat3x4; + typedef packed_lowp_dmat4x2 packed_dmat4x2; + typedef packed_lowp_dmat4x3 packed_dmat4x3; + typedef packed_lowp_dmat4x4 packed_dmat4x4; +#elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + typedef aligned_mediump_dvec1 aligned_dvec1; + typedef aligned_mediump_dvec2 aligned_dvec2; + typedef aligned_mediump_dvec3 aligned_dvec3; + typedef aligned_mediump_dvec4 aligned_dvec4; + typedef packed_mediump_dvec1 packed_dvec1; + typedef packed_mediump_dvec2 packed_dvec2; + typedef packed_mediump_dvec3 packed_dvec3; + typedef packed_mediump_dvec4 packed_dvec4; + + typedef aligned_mediump_dmat2 aligned_dmat2; + typedef aligned_mediump_dmat3 aligned_dmat3; + typedef aligned_mediump_dmat4 aligned_dmat4; + typedef packed_mediump_dmat2 packed_dmat2; + typedef packed_mediump_dmat3 packed_dmat3; + typedef packed_mediump_dmat4 packed_dmat4; + + typedef aligned_mediump_dmat2x2 aligned_dmat2x2; + typedef aligned_mediump_dmat2x3 aligned_dmat2x3; + typedef aligned_mediump_dmat2x4 aligned_dmat2x4; + typedef aligned_mediump_dmat3x2 aligned_dmat3x2; + typedef aligned_mediump_dmat3x3 aligned_dmat3x3; + typedef aligned_mediump_dmat3x4 aligned_dmat3x4; + typedef aligned_mediump_dmat4x2 aligned_dmat4x2; + typedef aligned_mediump_dmat4x3 aligned_dmat4x3; + typedef aligned_mediump_dmat4x4 aligned_dmat4x4; + typedef packed_mediump_dmat2x2 packed_dmat2x2; + typedef packed_mediump_dmat2x3 packed_dmat2x3; + typedef packed_mediump_dmat2x4 packed_dmat2x4; + typedef packed_mediump_dmat3x2 packed_dmat3x2; + typedef packed_mediump_dmat3x3 packed_dmat3x3; + typedef packed_mediump_dmat3x4 packed_dmat3x4; + typedef packed_mediump_dmat4x2 packed_dmat4x2; + typedef packed_mediump_dmat4x3 packed_dmat4x3; + typedef packed_mediump_dmat4x4 packed_dmat4x4; +#else //defined(GLM_PRECISION_HIGHP_DOUBLE) + /// 1 component vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec1 aligned_dvec1; + + /// 2 components vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec2 aligned_dvec2; + + /// 3 components vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec3 aligned_dvec3; + + /// 4 components vector aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dvec4 aligned_dvec4; + + /// 1 component vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec1 packed_dvec1; + + /// 2 components vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec2 packed_dvec2; + + /// 3 components vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec3 packed_dvec3; + + /// 4 components vector tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dvec4 packed_dvec4; + + /// 2 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2 aligned_dmat2; + + /// 3 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3 aligned_dmat3; + + /// 4 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4 aligned_dmat4; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2 packed_dmat2; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3 packed_dmat3; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4 packed_dmat4; + + /// 2 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2x2 aligned_dmat2x2; + + /// 2 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2x3 aligned_dmat2x3; + + /// 2 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat2x4 aligned_dmat2x4; + + /// 3 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3x2 aligned_dmat3x2; + + /// 3 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3x3 aligned_dmat3x3; + + /// 3 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat3x4 aligned_dmat3x4; + + /// 4 by 2 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4x2 aligned_dmat4x2; + + /// 4 by 3 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4x3 aligned_dmat4x3; + + /// 4 by 4 matrix tightly aligned in memory of double-precision floating-point numbers. + typedef aligned_highp_dmat4x4 aligned_dmat4x4; + + /// 2 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2x2 packed_dmat2x2; + + /// 2 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2x3 packed_dmat2x3; + + /// 2 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat2x4 packed_dmat2x4; + + /// 3 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3x2 packed_dmat3x2; + + /// 3 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3x3 packed_dmat3x3; + + /// 3 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat3x4 packed_dmat3x4; + + /// 4 by 2 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4x2 packed_dmat4x2; + + /// 4 by 3 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4x3 packed_dmat4x3; + + /// 4 by 4 matrix tightly packed in memory of double-precision floating-point numbers. + typedef packed_highp_dmat4x4 packed_dmat4x4; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef aligned_lowp_ivec1 aligned_ivec1; + typedef aligned_lowp_ivec2 aligned_ivec2; + typedef aligned_lowp_ivec3 aligned_ivec3; + typedef aligned_lowp_ivec4 aligned_ivec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef aligned_mediump_ivec1 aligned_ivec1; + typedef aligned_mediump_ivec2 aligned_ivec2; + typedef aligned_mediump_ivec3 aligned_ivec3; + typedef aligned_mediump_ivec4 aligned_ivec4; +#else //defined(GLM_PRECISION_HIGHP_INT) + /// 1 component vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec1 aligned_ivec1; + + /// 2 components vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec2 aligned_ivec2; + + /// 3 components vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec3 aligned_ivec3; + + /// 4 components vector aligned in memory of signed integer numbers. + typedef aligned_highp_ivec4 aligned_ivec4; + + /// 1 component vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec1 packed_ivec1; + + /// 2 components vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec2 packed_ivec2; + + /// 3 components vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec3 packed_ivec3; + + /// 4 components vector tightly packed in memory of signed integer numbers. + typedef packed_highp_ivec4 packed_ivec4; +#endif//GLM_PRECISION + + // -- Unsigned integer definition -- + +#if(defined(GLM_PRECISION_LOWP_UINT)) + typedef aligned_lowp_uvec1 aligned_uvec1; + typedef aligned_lowp_uvec2 aligned_uvec2; + typedef aligned_lowp_uvec3 aligned_uvec3; + typedef aligned_lowp_uvec4 aligned_uvec4; +#elif(defined(GLM_PRECISION_MEDIUMP_UINT)) + typedef aligned_mediump_uvec1 aligned_uvec1; + typedef aligned_mediump_uvec2 aligned_uvec2; + typedef aligned_mediump_uvec3 aligned_uvec3; + typedef aligned_mediump_uvec4 aligned_uvec4; +#else //defined(GLM_PRECISION_HIGHP_UINT) + /// 1 component vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec1 aligned_uvec1; + + /// 2 components vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec2 aligned_uvec2; + + /// 3 components vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec3 aligned_uvec3; + + /// 4 components vector aligned in memory of unsigned integer numbers. + typedef aligned_highp_uvec4 aligned_uvec4; + + /// 1 component vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec1 packed_uvec1; + + /// 2 components vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec2 packed_uvec2; + + /// 3 components vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec3 packed_uvec3; + + /// 4 components vector tightly packed in memory of unsigned integer numbers. + typedef packed_highp_uvec4 packed_uvec4; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_LOWP_BOOL)) + typedef aligned_lowp_bvec1 aligned_bvec1; + typedef aligned_lowp_bvec2 aligned_bvec2; + typedef aligned_lowp_bvec3 aligned_bvec3; + typedef aligned_lowp_bvec4 aligned_bvec4; +#elif(defined(GLM_PRECISION_MEDIUMP_BOOL)) + typedef aligned_mediump_bvec1 aligned_bvec1; + typedef aligned_mediump_bvec2 aligned_bvec2; + typedef aligned_mediump_bvec3 aligned_bvec3; + typedef aligned_mediump_bvec4 aligned_bvec4; +#else //defined(GLM_PRECISION_HIGHP_BOOL) + /// 1 component vector aligned in memory of bool values. + typedef aligned_highp_bvec1 aligned_bvec1; + + /// 2 components vector aligned in memory of bool values. + typedef aligned_highp_bvec2 aligned_bvec2; + + /// 3 components vector aligned in memory of bool values. + typedef aligned_highp_bvec3 aligned_bvec3; + + /// 4 components vector aligned in memory of bool values. + typedef aligned_highp_bvec4 aligned_bvec4; + + /// 1 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec1 packed_bvec1; + + /// 2 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec2 packed_bvec2; + + /// 3 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec3 packed_bvec3; + + /// 4 components vector tightly packed in memory of bool values. + typedef packed_highp_bvec4 packed_bvec4; +#endif//GLM_PRECISION + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/gtc/type_precision.hpp b/vendor/glm/glm/gtc/type_precision.hpp new file mode 100644 index 0000000..775e2f4 --- /dev/null +++ b/vendor/glm/glm/gtc/type_precision.hpp @@ -0,0 +1,2094 @@ +/// @ref gtc_type_precision +/// @file glm/gtc/type_precision.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_type_precision GLM_GTC_type_precision +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Defines specific C++-based qualifier types. + +#pragma once + +// Dependency: +#include "../gtc/quaternion.hpp" +#include "../gtc/vec1.hpp" +#include "../ext/vector_int1_sized.hpp" +#include "../ext/vector_int2_sized.hpp" +#include "../ext/vector_int3_sized.hpp" +#include "../ext/vector_int4_sized.hpp" +#include "../ext/scalar_int_sized.hpp" +#include "../ext/vector_uint1_sized.hpp" +#include "../ext/vector_uint2_sized.hpp" +#include "../ext/vector_uint3_sized.hpp" +#include "../ext/vector_uint4_sized.hpp" +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/type_vec2.hpp" +#include "../detail/type_vec3.hpp" +#include "../detail/type_vec4.hpp" +#include "../detail/type_mat2x2.hpp" +#include "../detail/type_mat2x3.hpp" +#include "../detail/type_mat2x4.hpp" +#include "../detail/type_mat3x2.hpp" +#include "../detail/type_mat3x3.hpp" +#include "../detail/type_mat3x4.hpp" +#include "../detail/type_mat4x2.hpp" +#include "../detail/type_mat4x3.hpp" +#include "../detail/type_mat4x4.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_type_precision extension included") +#endif + +namespace glm +{ + /////////////////////////// + // Signed int vector types + + /// @addtogroup gtc_type_precision + /// @{ + + /// Low qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8; + + /// Low qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16; + + /// Low qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32; + + /// Low qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64; + + /// Low qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8_t; + + /// Low qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16_t; + + /// Low qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32_t; + + /// Low qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64_t; + + /// Low qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_i8; + + /// Low qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_i16; + + /// Low qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_i32; + + /// Low qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_i64; + + /// Medium qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8; + + /// Medium qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16; + + /// Medium qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32; + + /// Medium qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64; + + /// Medium qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8_t; + + /// Medium qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16_t; + + /// Medium qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32_t; + + /// Medium qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64_t; + + /// Medium qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_i8; + + /// Medium qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_i16; + + /// Medium qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_i32; + + /// Medium qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_i64; + + /// High qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8; + + /// High qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16; + + /// High qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32; + + /// High qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64; + + /// High qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8_t; + + /// High qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32_t; + + /// High qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64_t; + + /// High qualifier 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_i8; + + /// High qualifier 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_i16; + + /// High qualifier 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_i32; + + /// High qualifier 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_i64; + + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::int8_t; + using std::int16_t; + using std::int32_t; + using std::int64_t; +#else + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 int8_t; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 int32_t; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 int64_t; +#endif + + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 i8; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 i16; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 i32; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 i64; + + ///////////////////////////// + // Unsigned int vector types + + /// Low qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8; + + /// Low qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16; + + /// Low qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32; + + /// Low qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64; + + /// Low qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8_t; + + /// Low qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16_t; + + /// Low qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32_t; + + /// Low qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64_t; + + /// Low qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_u8; + + /// Low qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_u16; + + /// Low qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_u32; + + /// Low qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_u64; + + /// Medium qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8; + + /// Medium qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16; + + /// Medium qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32; + + /// Medium qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64; + + /// Medium qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8_t; + + /// Medium qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16_t; + + /// Medium qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32_t; + + /// Medium qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64_t; + + /// Medium qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_u8; + + /// Medium qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_u16; + + /// Medium qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_u32; + + /// Medium qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_u64; + + /// High qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8; + + /// High qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16; + + /// High qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32; + + /// High qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64; + + /// High qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8_t; + + /// High qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16_t; + + /// High qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32_t; + + /// High qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64_t; + + /// High qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_u8; + + /// High qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_u16; + + /// High qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_u32; + + /// High qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_u64; + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::uint8_t; + using std::uint16_t; + using std::uint32_t; + using std::uint64_t; +#else + /// Default qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 uint8_t; + + /// Default qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 uint16_t; + + /// Default qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 uint32_t; + + /// Default qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 uint64_t; +#endif + + /// Default qualifier 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 u8; + + /// Default qualifier 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 u16; + + /// Default qualifier 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 u32; + + /// Default qualifier 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 u64; + + + + + + ////////////////////// + // Float vector types + + /// Single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float float32; + + /// Double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef double float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32_t; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64_t; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32_t; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64_t; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_float32_t; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_float64_t; + + /// Low 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + + /// Medium 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 mediump_float32; + + /// Medium 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 mediump_float64; + + /// Medium 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 mediump_float32_t; + + /// Medium 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 mediump_float64_t; + + /// Medium 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 mediump_f32; + + /// Medium 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 mediump_f64; + + + /// High 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 highp_float32; + + /// High 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 highp_float64; + + /// High 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 highp_float32_t; + + /// High 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 highp_float64_t; + + /// High 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 highp_f32; + + /// High 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 highp_f64; + + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float32_t float32_t; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float64_t float64_t; + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_f32 f32; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef lowp_f64 f64; + +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float32 float32_t; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float64 float64_t; + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float32 f32; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float64 f64; + +#else//(defined(GLM_PRECISION_HIGHP_FLOAT)) + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float32_t float32_t; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float64_t float64_t; + + /// Default 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float32_t f32; + + /// Default 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef highp_float64_t f64; +#endif + + + /// Low single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, lowp> lowp_fvec1; + + /// Low single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, float, lowp> lowp_fvec2; + + /// Low single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, float, lowp> lowp_fvec3; + + /// Low single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, float, lowp> lowp_fvec4; + + + /// Medium single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, mediump> mediump_fvec1; + + /// Medium Single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, float, mediump> mediump_fvec2; + + /// Medium Single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, float, mediump> mediump_fvec3; + + /// Medium Single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, float, mediump> mediump_fvec4; + + + /// High single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, highp> highp_fvec1; + + /// High Single-qualifier floating-point vector of 2 components. + /// @see core_precision + typedef vec<2, float, highp> highp_fvec2; + + /// High Single-qualifier floating-point vector of 3 components. + /// @see core_precision + typedef vec<3, float, highp> highp_fvec3; + + /// High Single-qualifier floating-point vector of 4 components. + /// @see core_precision + typedef vec<4, float, highp> highp_fvec4; + + + /// Low single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, lowp> lowp_f32vec1; + + /// Low single-qualifier floating-point vector of 2 components. + /// @see core_precision + typedef vec<2, f32, lowp> lowp_f32vec2; + + /// Low single-qualifier floating-point vector of 3 components. + /// @see core_precision + typedef vec<3, f32, lowp> lowp_f32vec3; + + /// Low single-qualifier floating-point vector of 4 components. + /// @see core_precision + typedef vec<4, f32, lowp> lowp_f32vec4; + + /// Medium single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, mediump> mediump_f32vec1; + + /// Medium single-qualifier floating-point vector of 2 components. + /// @see core_precision + typedef vec<2, f32, mediump> mediump_f32vec2; + + /// Medium single-qualifier floating-point vector of 3 components. + /// @see core_precision + typedef vec<3, f32, mediump> mediump_f32vec3; + + /// Medium single-qualifier floating-point vector of 4 components. + /// @see core_precision + typedef vec<4, f32, mediump> mediump_f32vec4; + + /// High single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, highp> highp_f32vec1; + + /// High single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f32, highp> highp_f32vec2; + + /// High single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f32, highp> highp_f32vec3; + + /// High single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f32, highp> highp_f32vec4; + + + /// Low double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, lowp> lowp_f64vec1; + + /// Low double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, lowp> lowp_f64vec2; + + /// Low double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, lowp> lowp_f64vec3; + + /// Low double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, lowp> lowp_f64vec4; + + /// Medium double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, mediump> mediump_f64vec1; + + /// Medium double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, mediump> mediump_f64vec2; + + /// Medium double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, mediump> mediump_f64vec3; + + /// Medium double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, mediump> mediump_f64vec4; + + /// High double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, highp> highp_f64vec1; + + /// High double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, highp> highp_f64vec2; + + /// High double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, highp> highp_f64vec3; + + /// High double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, highp> highp_f64vec4; + + + + ////////////////////// + // Float matrix types + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_f32 lowp_fmat1x1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, lowp> lowp_fmat2x2; + + /// Low single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, lowp> lowp_fmat2x3; + + /// Low single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, lowp> lowp_fmat2x4; + + /// Low single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, lowp> lowp_fmat3x2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, lowp> lowp_fmat3x3; + + /// Low single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, lowp> lowp_fmat3x4; + + /// Low single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, lowp> lowp_fmat4x2; + + /// Low single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, lowp> lowp_fmat4x3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, lowp> lowp_fmat4x4; + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_fmat1x1 lowp_fmat1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_fmat2x2 lowp_fmat2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_fmat3x3 lowp_fmat3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_fmat4x4 lowp_fmat4; + + + /// Medium single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_f32 mediump_fmat1x1; + + /// Medium single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, mediump> mediump_fmat2x2; + + /// Medium single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, mediump> mediump_fmat2x3; + + /// Medium single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, mediump> mediump_fmat2x4; + + /// Medium single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, mediump> mediump_fmat3x2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, mediump> mediump_fmat3x3; + + /// Medium single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, mediump> mediump_fmat3x4; + + /// Medium single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, mediump> mediump_fmat4x2; + + /// Medium single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, mediump> mediump_fmat4x3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, mediump> mediump_fmat4x4; + + /// Medium single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_fmat1x1 mediump_fmat1; + + /// Medium single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_fmat2x2 mediump_fmat2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_fmat3x3 mediump_fmat3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_fmat4x4 mediump_fmat4; + + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_f32 highp_fmat1x1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, highp> highp_fmat2x2; + + /// High single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, highp> highp_fmat2x3; + + /// High single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, highp> highp_fmat2x4; + + /// High single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, highp> highp_fmat3x2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, highp> highp_fmat3x3; + + /// High single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, highp> highp_fmat3x4; + + /// High single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, highp> highp_fmat4x2; + + /// High single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, highp> highp_fmat4x3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, highp> highp_fmat4x4; + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_fmat1x1 highp_fmat1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_fmat2x2 highp_fmat2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_fmat3x3 highp_fmat3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_fmat4x4 highp_fmat4; + + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 lowp_f32mat1x1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, lowp> lowp_f32mat2x2; + + /// Low single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, lowp> lowp_f32mat2x3; + + /// Low single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, lowp> lowp_f32mat2x4; + + /// Low single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, lowp> lowp_f32mat3x2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, lowp> lowp_f32mat3x3; + + /// Low single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, lowp> lowp_f32mat3x4; + + /// Low single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, lowp> lowp_f32mat4x2; + + /// Low single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, lowp> lowp_f32mat4x3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, lowp> lowp_f32mat4x4; + + /// Low single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 lowp_f32mat1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat2x2 lowp_f32mat2; + + /// Low single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat3x3 lowp_f32mat3; + + /// Low single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat4x4 lowp_f32mat4; + + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 mediump_f32mat1x1; + + /// Low single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, mediump> mediump_f32mat2x2; + + /// Medium single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, mediump> mediump_f32mat2x3; + + /// Medium single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, mediump> mediump_f32mat2x4; + + /// Medium single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, mediump> mediump_f32mat3x2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, mediump> mediump_f32mat3x3; + + /// Medium single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, mediump> mediump_f32mat3x4; + + /// Medium single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, mediump> mediump_f32mat4x2; + + /// Medium single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, mediump> mediump_f32mat4x3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, mediump> mediump_f32mat4x4; + + /// Medium single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f32mat1; + + /// Medium single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat2x2 mediump_f32mat2; + + /// Medium single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat3x3 mediump_f32mat3; + + /// Medium single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat4x4 mediump_f32mat4; + + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 highp_f32mat1x1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, highp> highp_f32mat2x2; + + /// High single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, highp> highp_f32mat2x3; + + /// High single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, highp> highp_f32mat2x4; + + /// High single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, highp> highp_f32mat3x2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, highp> highp_f32mat3x3; + + /// High single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, highp> highp_f32mat3x4; + + /// High single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, highp> highp_f32mat4x2; + + /// High single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, highp> highp_f32mat4x3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, highp> highp_f32mat4x4; + + /// High single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f32mat1; + + /// High single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x2 highp_f32mat2; + + /// High single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x3 highp_f32mat3; + + /// High single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x4 highp_f32mat4; + + + /// Low double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 lowp_f64mat1x1; + + /// Low double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, lowp> lowp_f64mat2x2; + + /// Low double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, lowp> lowp_f64mat2x3; + + /// Low double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, lowp> lowp_f64mat2x4; + + /// Low double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, lowp> lowp_f64mat3x2; + + /// Low double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, lowp> lowp_f64mat3x3; + + /// Low double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, lowp> lowp_f64mat3x4; + + /// Low double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, lowp> lowp_f64mat4x2; + + /// Low double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, lowp> lowp_f64mat4x3; + + /// Low double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, lowp> lowp_f64mat4x4; + + /// Low double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_f64mat1x1 lowp_f64mat1; + + /// Low double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat2x2 lowp_f64mat2; + + /// Low double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat3x3 lowp_f64mat3; + + /// Low double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat4x4 lowp_f64mat4; + + + /// Medium double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 Highp_f64mat1x1; + + /// Medium double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, mediump> mediump_f64mat2x2; + + /// Medium double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, mediump> mediump_f64mat2x3; + + /// Medium double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, mediump> mediump_f64mat2x4; + + /// Medium double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, mediump> mediump_f64mat3x2; + + /// Medium double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, mediump> mediump_f64mat3x3; + + /// Medium double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, mediump> mediump_f64mat3x4; + + /// Medium double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, mediump> mediump_f64mat4x2; + + /// Medium double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, mediump> mediump_f64mat4x3; + + /// Medium double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, mediump> mediump_f64mat4x4; + + /// Medium double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_f64mat1x1 mediump_f64mat1; + + /// Medium double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat2x2 mediump_f64mat2; + + /// Medium double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat3x3 mediump_f64mat3; + + /// Medium double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat4x4 mediump_f64mat4; + + /// High double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 highp_f64mat1x1; + + /// High double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, highp> highp_f64mat2x2; + + /// High double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, highp> highp_f64mat2x3; + + /// High double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, highp> highp_f64mat2x4; + + /// High double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, highp> highp_f64mat3x2; + + /// High double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, highp> highp_f64mat3x3; + + /// High double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, highp> highp_f64mat3x4; + + /// High double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, highp> highp_f64mat4x2; + + /// High double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, highp> highp_f64mat4x3; + + /// High double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, highp> highp_f64mat4x4; + + /// High double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_f64mat1x1 highp_f64mat1; + + /// High double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f64mat2x2 highp_f64mat2; + + /// High double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f64mat3x3 highp_f64mat3; + + /// High double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f64mat4x4 highp_f64mat4; + + + ///////////////////////////// + // Signed int vector types + + /// Low qualifier signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, int, lowp> lowp_ivec1; + + /// Low qualifier signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, int, lowp> lowp_ivec2; + + /// Low qualifier signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, int, lowp> lowp_ivec3; + + /// Low qualifier signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, int, lowp> lowp_ivec4; + + + /// Medium qualifier signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, int, mediump> mediump_ivec1; + + /// Medium qualifier signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, int, mediump> mediump_ivec2; + + /// Medium qualifier signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, int, mediump> mediump_ivec3; + + /// Medium qualifier signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, int, mediump> mediump_ivec4; + + + /// High qualifier signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, int, highp> highp_ivec1; + + /// High qualifier signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, int, highp> highp_ivec2; + + /// High qualifier signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, int, highp> highp_ivec3; + + /// High qualifier signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, int, highp> highp_ivec4; + + + /// Low qualifier 8 bit signed integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, i8, lowp> lowp_i8vec1; + + /// Low qualifier 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i8, lowp> lowp_i8vec2; + + /// Low qualifier 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i8, lowp> lowp_i8vec3; + + /// Low qualifier 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i8, lowp> lowp_i8vec4; + + + /// Medium qualifier 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i8, mediump> mediump_i8vec1; + + /// Medium qualifier 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i8, mediump> mediump_i8vec2; + + /// Medium qualifier 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i8, mediump> mediump_i8vec3; + + /// Medium qualifier 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i8, mediump> mediump_i8vec4; + + + /// High qualifier 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i8, highp> highp_i8vec1; + + /// High qualifier 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i8, highp> highp_i8vec2; + + /// High qualifier 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i8, highp> highp_i8vec3; + + /// High qualifier 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i8, highp> highp_i8vec4; + + + /// Low qualifier 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i16, lowp> lowp_i16vec1; + + /// Low qualifier 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i16, lowp> lowp_i16vec2; + + /// Low qualifier 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i16, lowp> lowp_i16vec3; + + /// Low qualifier 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i16, lowp> lowp_i16vec4; + + + /// Medium qualifier 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i16, mediump> mediump_i16vec1; + + /// Medium qualifier 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i16, mediump> mediump_i16vec2; + + /// Medium qualifier 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i16, mediump> mediump_i16vec3; + + /// Medium qualifier 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i16, mediump> mediump_i16vec4; + + + /// High qualifier 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i16, highp> highp_i16vec1; + + /// High qualifier 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i16, highp> highp_i16vec2; + + /// High qualifier 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i16, highp> highp_i16vec3; + + /// High qualifier 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i16, highp> highp_i16vec4; + + + /// Low qualifier 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i32, lowp> lowp_i32vec1; + + /// Low qualifier 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i32, lowp> lowp_i32vec2; + + /// Low qualifier 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i32, lowp> lowp_i32vec3; + + /// Low qualifier 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i32, lowp> lowp_i32vec4; + + + /// Medium qualifier 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i32, mediump> mediump_i32vec1; + + /// Medium qualifier 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i32, mediump> mediump_i32vec2; + + /// Medium qualifier 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i32, mediump> mediump_i32vec3; + + /// Medium qualifier 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i32, mediump> mediump_i32vec4; + + + /// High qualifier 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i32, highp> highp_i32vec1; + + /// High qualifier 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i32, highp> highp_i32vec2; + + /// High qualifier 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i32, highp> highp_i32vec3; + + /// High qualifier 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i32, highp> highp_i32vec4; + + + /// Low qualifier 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i64, lowp> lowp_i64vec1; + + /// Low qualifier 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i64, lowp> lowp_i64vec2; + + /// Low qualifier 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i64, lowp> lowp_i64vec3; + + /// Low qualifier 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i64, lowp> lowp_i64vec4; + + + /// Medium qualifier 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i64, mediump> mediump_i64vec1; + + /// Medium qualifier 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i64, mediump> mediump_i64vec2; + + /// Medium qualifier 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i64, mediump> mediump_i64vec3; + + /// Medium qualifier 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i64, mediump> mediump_i64vec4; + + + /// High qualifier 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef vec<1, i64, highp> highp_i64vec1; + + /// High qualifier 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, i64, highp> highp_i64vec2; + + /// High qualifier 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, i64, highp> highp_i64vec3; + + /// High qualifier 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, i64, highp> highp_i64vec4; + + + ///////////////////////////// + // Unsigned int vector types + + /// Low qualifier unsigned integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, uint, lowp> lowp_uvec1; + + /// Low qualifier unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, uint, lowp> lowp_uvec2; + + /// Low qualifier unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, uint, lowp> lowp_uvec3; + + /// Low qualifier unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, uint, lowp> lowp_uvec4; + + + /// Medium qualifier unsigned integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, uint, mediump> mediump_uvec1; + + /// Medium qualifier unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, uint, mediump> mediump_uvec2; + + /// Medium qualifier unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, uint, mediump> mediump_uvec3; + + /// Medium qualifier unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, uint, mediump> mediump_uvec4; + + + /// High qualifier unsigned integer vector of 1 component type. + /// @see gtc_type_precision + typedef vec<1, uint, highp> highp_uvec1; + + /// High qualifier unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, uint, highp> highp_uvec2; + + /// High qualifier unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, uint, highp> highp_uvec3; + + /// High qualifier unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, uint, highp> highp_uvec4; + + + /// Low qualifier 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u8, lowp> lowp_u8vec1; + + /// Low qualifier 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u8, lowp> lowp_u8vec2; + + /// Low qualifier 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u8, lowp> lowp_u8vec3; + + /// Low qualifier 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u8, lowp> lowp_u8vec4; + + + /// Medium qualifier 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u8, mediump> mediump_u8vec1; + + /// Medium qualifier 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u8, mediump> mediump_u8vec2; + + /// Medium qualifier 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u8, mediump> mediump_u8vec3; + + /// Medium qualifier 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u8, mediump> mediump_u8vec4; + + + /// High qualifier 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u8, highp> highp_u8vec1; + + /// High qualifier 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u8, highp> highp_u8vec2; + + /// High qualifier 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u8, highp> highp_u8vec3; + + /// High qualifier 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u8, highp> highp_u8vec4; + + + /// Low qualifier 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u16, lowp> lowp_u16vec1; + + /// Low qualifier 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u16, lowp> lowp_u16vec2; + + /// Low qualifier 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u16, lowp> lowp_u16vec3; + + /// Low qualifier 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u16, lowp> lowp_u16vec4; + + + /// Medium qualifier 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u16, mediump> mediump_u16vec1; + + /// Medium qualifier 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u16, mediump> mediump_u16vec2; + + /// Medium qualifier 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u16, mediump> mediump_u16vec3; + + /// Medium qualifier 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u16, mediump> mediump_u16vec4; + + + /// High qualifier 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u16, highp> highp_u16vec1; + + /// High qualifier 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u16, highp> highp_u16vec2; + + /// High qualifier 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u16, highp> highp_u16vec3; + + /// High qualifier 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u16, highp> highp_u16vec4; + + + /// Low qualifier 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u32, lowp> lowp_u32vec1; + + /// Low qualifier 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u32, lowp> lowp_u32vec2; + + /// Low qualifier 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u32, lowp> lowp_u32vec3; + + /// Low qualifier 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u32, lowp> lowp_u32vec4; + + + /// Medium qualifier 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u32, mediump> mediump_u32vec1; + + /// Medium qualifier 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u32, mediump> mediump_u32vec2; + + /// Medium qualifier 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u32, mediump> mediump_u32vec3; + + /// Medium qualifier 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u32, mediump> mediump_u32vec4; + + + /// High qualifier 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u32, highp> highp_u32vec1; + + /// High qualifier 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u32, highp> highp_u32vec2; + + /// High qualifier 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u32, highp> highp_u32vec3; + + /// High qualifier 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u32, highp> highp_u32vec4; + + + /// Low qualifier 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u64, lowp> lowp_u64vec1; + + /// Low qualifier 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u64, lowp> lowp_u64vec2; + + /// Low qualifier 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u64, lowp> lowp_u64vec3; + + /// Low qualifier 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u64, lowp> lowp_u64vec4; + + + /// Medium qualifier 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u64, mediump> mediump_u64vec1; + + /// Medium qualifier 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u64, mediump> mediump_u64vec2; + + /// Medium qualifier 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u64, mediump> mediump_u64vec3; + + /// Medium qualifier 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u64, mediump> mediump_u64vec4; + + + /// High qualifier 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef vec<1, u64, highp> highp_u64vec1; + + /// High qualifier 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef vec<2, u64, highp> highp_u64vec2; + + /// High qualifier 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef vec<3, u64, highp> highp_u64vec3; + + /// High qualifier 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef vec<4, u64, highp> highp_u64vec4; + + + ////////////////////// + // Float vector types + + /// 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 float32_t; + + /// 32 bit single-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float32 f32; + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 float64_t; + + /// 64 bit double-qualifier floating-point scalar. + /// @see gtc_type_precision + typedef float64 f64; +# endif//GLM_FORCE_SINGLE_ONLY + + /// Single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, float, defaultp> fvec1; + + /// Single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, float, defaultp> fvec2; + + /// Single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, float, defaultp> fvec3; + + /// Single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, float, defaultp> fvec4; + + + /// Single-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f32, defaultp> f32vec1; + + /// Single-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f32, defaultp> f32vec2; + + /// Single-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f32, defaultp> f32vec3; + + /// Single-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f32, defaultp> f32vec4; + +# ifndef GLM_FORCE_SINGLE_ONLY + /// Double-qualifier floating-point vector of 1 component. + /// @see gtc_type_precision + typedef vec<1, f64, defaultp> f64vec1; + + /// Double-qualifier floating-point vector of 2 components. + /// @see gtc_type_precision + typedef vec<2, f64, defaultp> f64vec2; + + /// Double-qualifier floating-point vector of 3 components. + /// @see gtc_type_precision + typedef vec<3, f64, defaultp> f64vec3; + + /// Double-qualifier floating-point vector of 4 components. + /// @see gtc_type_precision + typedef vec<4, f64, defaultp> f64vec4; +# endif//GLM_FORCE_SINGLE_ONLY + + + ////////////////////// + // Float matrix types + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 fmat1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> fmat2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> fmat3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> fmat4; + + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 fmat1x1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> fmat2x2; + + /// Single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, defaultp> fmat2x3; + + /// Single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, defaultp> fmat2x4; + + /// Single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, defaultp> fmat3x2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> fmat3x3; + + /// Single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, defaultp> fmat3x4; + + /// Single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, defaultp> fmat4x2; + + /// Single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, defaultp> fmat4x3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> fmat4x4; + + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f32mat1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> f32mat2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> f32mat3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> f32mat4; + + + /// Single-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 f32mat1x1; + + /// Single-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f32, defaultp> f32mat2x2; + + /// Single-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f32, defaultp> f32mat2x3; + + /// Single-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f32, defaultp> f32mat2x4; + + /// Single-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f32, defaultp> f32mat3x2; + + /// Single-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f32, defaultp> f32mat3x3; + + /// Single-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f32, defaultp> f32mat3x4; + + /// Single-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f32, defaultp> f32mat4x2; + + /// Single-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f32, defaultp> f32mat4x3; + + /// Single-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f32, defaultp> f32mat4x4; + + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1 f64mat1; + + /// Double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, defaultp> f64mat2; + + /// Double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, defaultp> f64mat3; + + /// Double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, defaultp> f64mat4; + + + /// Double-qualifier floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 f64mat1x1; + + /// Double-qualifier floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mat<2, 2, f64, defaultp> f64mat2x2; + + /// Double-qualifier floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef mat<2, 3, f64, defaultp> f64mat2x3; + + /// Double-qualifier floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef mat<2, 4, f64, defaultp> f64mat2x4; + + /// Double-qualifier floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef mat<3, 2, f64, defaultp> f64mat3x2; + + /// Double-qualifier floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mat<3, 3, f64, defaultp> f64mat3x3; + + /// Double-qualifier floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef mat<3, 4, f64, defaultp> f64mat3x4; + + /// Double-qualifier floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef mat<4, 2, f64, defaultp> f64mat4x2; + + /// Double-qualifier floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef mat<4, 3, f64, defaultp> f64mat4x3; + + /// Double-qualifier floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mat<4, 4, f64, defaultp> f64mat4x4; + +# endif//GLM_FORCE_SINGLE_ONLY + + ////////////////////////// + // Quaternion types + + /// Single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua f32quat; + + /// Low single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua lowp_f32quat; + + /// Low double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua lowp_f64quat; + + /// Medium single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua mediump_f32quat; + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Medium double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua mediump_f64quat; + + /// High single-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua highp_f32quat; + + /// High double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua highp_f64quat; + + /// Double-qualifier floating-point quaternion. + /// @see gtc_type_precision + typedef qua f64quat; + +# endif//GLM_FORCE_SINGLE_ONLY + + /// @} +}//namespace glm + +#include "type_precision.inl" diff --git a/vendor/glm/glm/gtc/type_precision.inl b/vendor/glm/glm/gtc/type_precision.inl new file mode 100644 index 0000000..ae80912 --- /dev/null +++ b/vendor/glm/glm/gtc/type_precision.inl @@ -0,0 +1,6 @@ +/// @ref gtc_precision + +namespace glm +{ + +} diff --git a/vendor/glm/glm/gtc/type_ptr.hpp b/vendor/glm/glm/gtc/type_ptr.hpp new file mode 100644 index 0000000..d7e625a --- /dev/null +++ b/vendor/glm/glm/gtc/type_ptr.hpp @@ -0,0 +1,230 @@ +/// @ref gtc_type_ptr +/// @file glm/gtc/type_ptr.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_type_ptr GLM_GTC_type_ptr +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Handles the interaction between pointers and vector, matrix types. +/// +/// This extension defines an overloaded function, glm::value_ptr. It returns +/// a pointer to the memory layout of the object. Matrix types store their values +/// in column-major order. +/// +/// This is useful for uploading data to matrices or copying data to buffer objects. +/// +/// Example: +/// @code +/// #include +/// #include +/// +/// glm::vec3 aVector(3); +/// glm::mat4 someMatrix(1.0); +/// +/// glUniform3fv(uniformLoc, 1, glm::value_ptr(aVector)); +/// glUniformMatrix4fv(uniformMatrixLoc, 1, GL_FALSE, glm::value_ptr(someMatrix)); +/// @endcode +/// +/// need to be included to use the features of this extension. + +#pragma once + +// Dependency: +#include "../gtc/quaternion.hpp" +#include "../gtc/vec1.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_type_ptr extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_type_ptr + /// @{ + + /// Return the constant address to the data of the input parameter. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL typename genType::value_type const * value_ptr(genType const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<1, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<2, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<3, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, Q> make_vec4(vec<4, T, Q> const& v); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<2, T, defaultp> make_vec2(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<3, T, defaultp> make_vec3(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL vec<4, T, defaultp> make_vec4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 2, T, defaultp> make_mat2x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 3, T, defaultp> make_mat2x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 4, T, defaultp> make_mat2x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 2, T, defaultp> make_mat3x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 3, T, defaultp> make_mat3x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 4, T, defaultp> make_mat3x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 2, T, defaultp> make_mat4x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 3, T, defaultp> make_mat4x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> make_mat4x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<2, 2, T, defaultp> make_mat2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<3, 3, T, defaultp> make_mat3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> make_mat4(T const * const ptr); + + /// Build a quaternion from a pointer. + /// @see gtc_type_ptr + template + GLM_FUNC_DECL qua make_quat(T const * const ptr); + + /// @} +}//namespace glm + +#include "type_ptr.inl" diff --git a/vendor/glm/glm/gtc/type_ptr.inl b/vendor/glm/glm/gtc/type_ptr.inl new file mode 100644 index 0000000..71df4d3 --- /dev/null +++ b/vendor/glm/glm/gtc/type_ptr.inl @@ -0,0 +1,386 @@ +/// @ref gtc_type_ptr + +#include + +namespace glm +{ + /// @addtogroup gtc_type_ptr + /// @{ + + template + GLM_FUNC_QUALIFIER T const* value_ptr(vec<2, T, Q> const& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(vec<2, T, Q>& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T const * value_ptr(vec<3, T, Q> const& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(vec<3, T, Q>& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(vec<4, T, Q> const& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(vec<4, T, Q>& v) + { + return &(v.x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 2, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 3, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<4, 4, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 3, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 2, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<2, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<2, 4, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 2, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<4, 2, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<3, 4, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(mat<3, 4, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const* value_ptr(mat<4, 3, T, Q> const& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T * value_ptr(mat<4, 3, T, Q>& m) + { + return &(m[0].x); + } + + template + GLM_FUNC_QUALIFIER T const * value_ptr(qua const& q) + { + return &(q[0]); + } + + template + GLM_FUNC_QUALIFIER T* value_ptr(qua& q) + { + return &(q[0]); + } + + template + inline vec<1, T, Q> make_vec1(vec<1, T, Q> const& v) + { + return v; + } + + template + inline vec<1, T, Q> make_vec1(vec<2, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + inline vec<1, T, Q> make_vec1(vec<3, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + inline vec<1, T, Q> make_vec1(vec<4, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + inline vec<2, T, Q> make_vec2(vec<1, T, Q> const& v) + { + return vec<2, T, Q>(v.x, static_cast(0)); + } + + template + inline vec<2, T, Q> make_vec2(vec<2, T, Q> const& v) + { + return v; + } + + template + inline vec<2, T, Q> make_vec2(vec<3, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template + inline vec<2, T, Q> make_vec2(vec<4, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template + inline vec<3, T, Q> make_vec3(vec<1, T, Q> const& v) + { + return vec<3, T, Q>(v.x, static_cast(0), static_cast(0)); + } + + template + inline vec<3, T, Q> make_vec3(vec<2, T, Q> const& v) + { + return vec<3, T, Q>(v.x, v.y, static_cast(0)); + } + + template + inline vec<3, T, Q> make_vec3(vec<3, T, Q> const& v) + { + return v; + } + + template + inline vec<3, T, Q> make_vec3(vec<4, T, Q> const& v) + { + return vec<3, T, Q>(v); + } + + template + inline vec<4, T, Q> make_vec4(vec<1, T, Q> const& v) + { + return vec<4, T, Q>(v.x, static_cast(0), static_cast(0), static_cast(1)); + } + + template + inline vec<4, T, Q> make_vec4(vec<2, T, Q> const& v) + { + return vec<4, T, Q>(v.x, v.y, static_cast(0), static_cast(1)); + } + + template + inline vec<4, T, Q> make_vec4(vec<3, T, Q> const& v) + { + return vec<4, T, Q>(v.x, v.y, v.z, static_cast(1)); + } + + template + inline vec<4, T, Q> make_vec4(vec<4, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, defaultp> make_vec2(T const *const ptr) + { + vec<2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(vec<2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, defaultp> make_vec3(T const *const ptr) + { + vec<3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(vec<3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, defaultp> make_vec4(T const *const ptr) + { + vec<4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(vec<4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, defaultp> make_mat2x2(T const *const ptr) + { + mat<2, 2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<2, 2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, defaultp> make_mat2x3(T const *const ptr) + { + mat<2, 3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<2, 3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, defaultp> make_mat2x4(T const *const ptr) + { + mat<2, 4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<2, 4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, defaultp> make_mat3x2(T const *const ptr) + { + mat<3, 2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<3, 2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, defaultp> make_mat3x3(T const *const ptr) + { + mat<3, 3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<3, 3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, defaultp> make_mat3x4(T const *const ptr) + { + mat<3, 4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<3, 4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, defaultp> make_mat4x2(T const *const ptr) + { + mat<4, 2, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<4, 2, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, defaultp> make_mat4x3(T const *const ptr) + { + mat<4, 3, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<4, 3, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> make_mat4x4(T const *const ptr) + { + mat<4, 4, T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(mat<4, 4, T, defaultp>)); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, defaultp> make_mat2(T const *const ptr) + { + return make_mat2x2(ptr); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, defaultp> make_mat3(T const *const ptr) + { + return make_mat3x3(ptr); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> make_mat4(T const *const ptr) + { + return make_mat4x4(ptr); + } + + template + GLM_FUNC_QUALIFIER qua make_quat(T const *const ptr) + { + qua Result; + memcpy(value_ptr(Result), ptr, sizeof(qua)); + return Result; + } + + /// @} +}//namespace glm + diff --git a/vendor/glm/glm/gtc/ulp.hpp b/vendor/glm/glm/gtc/ulp.hpp new file mode 100644 index 0000000..0d80a75 --- /dev/null +++ b/vendor/glm/glm/gtc/ulp.hpp @@ -0,0 +1,152 @@ +/// @ref gtc_ulp +/// @file glm/gtc/ulp.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_ulp GLM_GTC_ulp +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Allow the measurement of the accuracy of a function against a reference +/// implementation. This extension works on floating-point data and provide results +/// in ULP. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/_vectorize.hpp" +#include "../ext/scalar_int_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_ulp extension included") +#endif + +namespace glm +{ + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType next_float(genType x); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType prev_float(genType x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType next_float(genType x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam genType A floating-point scalar type. + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL genType prev_float(genType x, int ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @see gtc_ulp + GLM_FUNC_DECL int float_distance(float x, float y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @see gtc_ulp + GLM_FUNC_DECL int64 float_distance(double x, double y); + + /// Return the next ULP value(s) after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec next_float(vec const& x); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec next_float(vec const& x, int ULPs); + + /// Return the value(s) ULP distance after the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec next_float(vec const& x, vec const& ULPs); + + /// Return the previous ULP value(s) before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec prev_float(vec const& x); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec prev_float(vec const& x, int ULPs); + + /// Return the value(s) ULP distance before the input value(s). + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec prev_float(vec const& x, vec const& ULPs); + + /// Return the distance in the number of ULP between 2 single-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec float_distance(vec const& x, vec const& y); + + /// Return the distance in the number of ULP between 2 double-precision floating-point scalars. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam Q Value from qualifier enum + /// + /// @see gtc_ulp + template + GLM_FUNC_DECL vec float_distance(vec const& x, vec const& y); + + /// @} +}//namespace glm + +#include "ulp.inl" diff --git a/vendor/glm/glm/gtc/ulp.inl b/vendor/glm/glm/gtc/ulp.inl new file mode 100644 index 0000000..4ecbd3f --- /dev/null +++ b/vendor/glm/glm/gtc/ulp.inl @@ -0,0 +1,173 @@ +/// @ref gtc_ulp + +#include "../ext/scalar_ulp.hpp" + +namespace glm +{ + template<> + GLM_FUNC_QUALIFIER float next_float(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MAX); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MAX); +# else + return nextafterf(x, FLT_MAX); +# endif + } + + template<> + GLM_FUNC_QUALIFIER double next_float(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafter(x, std::numeric_limits::max()); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MAX); +# else + return nextafter(x, DBL_MAX); +# endif + } + + template + GLM_FUNC_QUALIFIER T next_float(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'next_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for (int i = 0; i < ULPs; ++i) + temp = next_float(temp); + return temp; + } + + GLM_FUNC_QUALIFIER float prev_float(float x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MIN); +# else + return nextafterf(x, FLT_MIN); +# endif + } + + GLM_FUNC_QUALIFIER double prev_float(double x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return _nextafter(x, DBL_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MIN); +# else + return nextafter(x, DBL_MIN); +# endif + } + + template + GLM_FUNC_QUALIFIER T prev_float(T x, int ULPs) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'prev_float' only accept floating-point input"); + assert(ULPs >= 0); + + T temp = x; + for (int i = 0; i < ULPs; ++i) + temp = prev_float(temp); + return temp; + } + + GLM_FUNC_QUALIFIER int float_distance(float x, float y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } + + GLM_FUNC_QUALIFIER int64 float_distance(double x, double y) + { + detail::float_t const a(x); + detail::float_t const b(y); + + return abs(a.i - b.i); + } + + template + GLM_FUNC_QUALIFIER vec next_float(vec const& x) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec next_float(vec const& x, int ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec next_float(vec const& x, vec const& ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = next_float(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prev_float(vec const& x) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prev_float(vec const& x, int ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i], ULPs); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec prev_float(vec const& x, vec const& ULPs) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = prev_float(x[i], ULPs[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec float_distance(vec const& x, vec const& y) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER vec float_distance(vec const& x, vec const& y) + { + vec Result; + for (length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } +}//namespace glm + diff --git a/vendor/glm/glm/gtc/vec1.hpp b/vendor/glm/glm/gtc/vec1.hpp new file mode 100644 index 0000000..63697a2 --- /dev/null +++ b/vendor/glm/glm/gtc/vec1.hpp @@ -0,0 +1,30 @@ +/// @ref gtc_vec1 +/// @file glm/gtc/vec1.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtc_vec1 GLM_GTC_vec1 +/// @ingroup gtc +/// +/// Include to use the features of this extension. +/// +/// Add vec1, ivec1, uvec1 and bvec1 types. + +#pragma once + +// Dependency: +#include "../ext/vector_bool1.hpp" +#include "../ext/vector_bool1_precision.hpp" +#include "../ext/vector_float1.hpp" +#include "../ext/vector_float1_precision.hpp" +#include "../ext/vector_double1.hpp" +#include "../ext/vector_double1_precision.hpp" +#include "../ext/vector_int1.hpp" +#include "../ext/vector_int1_sized.hpp" +#include "../ext/vector_uint1.hpp" +#include "../ext/vector_uint1_sized.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_vec1 extension included") +#endif + diff --git a/vendor/glm/glm/gtx/associated_min_max.hpp b/vendor/glm/glm/gtx/associated_min_max.hpp new file mode 100644 index 0000000..d1a41c0 --- /dev/null +++ b/vendor/glm/glm/gtx/associated_min_max.hpp @@ -0,0 +1,207 @@ +/// @ref gtx_associated_min_max +/// @file glm/gtx/associated_min_max.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_associated_min_max GLM_GTX_associated_min_max +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Min and max functions that return associated values not the compared onces. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_associated_min_max is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_associated_min_max extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_associated_min_max + /// @{ + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMin(T x, U a, T y, U b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec<2, U, Q> associatedMin( + vec const& x, vec const& a, + vec const& y, vec const& b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + T x, const vec& a, + T y, const vec& b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, U a, + vec const& y, U b); + + /// Minimum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMin( + T x, U a, + T y, U b, + T z, U c); + + /// Minimum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMin( + T x, U a, + T y, U b, + T z, U c, + T w, U d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMin( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMax(T x, U a, T y, U b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec<2, U, Q> associatedMax( + vec const& x, vec const& a, + vec const& y, vec const& b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + T x, vec const& a, + T y, vec const& b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, U a, + vec const& y, U b); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMax( + T x, U a, + T y, U b, + T z, U c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL U associatedMax( + T x, U a, + T y, U b, + T z, U c, + T w, U d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template + GLM_FUNC_DECL vec associatedMax( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d); + + /// @} +} //namespace glm + +#include "associated_min_max.inl" diff --git a/vendor/glm/glm/gtx/associated_min_max.inl b/vendor/glm/glm/gtx/associated_min_max.inl new file mode 100644 index 0000000..5186c47 --- /dev/null +++ b/vendor/glm/glm/gtx/associated_min_max.inl @@ -0,0 +1,354 @@ +/// @ref gtx_associated_min_max + +namespace glm{ + +// Min comparison between 2 variables +template +GLM_FUNC_QUALIFIER U associatedMin(T x, U a, T y, U b) +{ + return x < y ? a : b; +} + +template +GLM_FUNC_QUALIFIER vec<2, U, Q> associatedMin +( + vec const& x, vec const& a, + vec const& y, vec const& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] < y[i] ? a[i] : b[i]; + return Result; +} + +template +GLM_FUNC_QUALIFIER vec associatedMin +( + T x, const vec& a, + T y, const vec& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x < y ? a[i] : b[i]; + return Result; +} + +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, U a, + vec const& y, U b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] < y[i] ? a : b; + return Result; +} + +// Min comparison between 3 variables +template +GLM_FUNC_QUALIFIER U associatedMin +( + T x, U a, + T y, U b, + T z, U c +) +{ + U Result = x < y ? (x < z ? a : c) : (y < z ? b : c); + return Result; +} + +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] < y[i] ? (x[i] < z[i] ? a[i] : c[i]) : (y[i] < z[i] ? b[i] : c[i]); + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER U associatedMin +( + T x, U a, + T y, U b, + T z, U c, + T w, U d +) +{ + T Test1 = min(x, y); + T Test2 = min(z, w); + U Result1 = x < y ? a : b; + U Result2 = z < w ? c : d; + U Result = Test1 < Test2 ? Result1 : Result2; + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = min(x[i], y[i]); + T Test2 = min(z[i], w[i]); + U Result1 = x[i] < y[i] ? a[i] : b[i]; + U Result2 = z[i] < w[i] ? c[i] : d[i]; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMin +( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d +) +{ + T Test1 = min(x, y); + T Test2 = min(z, w); + + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + U Result1 = x < y ? a[i] : b[i]; + U Result2 = z < w ? c[i] : d[i]; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Min comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMin +( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = min(x[i], y[i]); + T Test2 = min(z[i], w[i]); + U Result1 = x[i] < y[i] ? a : b; + U Result2 = z[i] < w[i] ? c : d; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER U associatedMax(T x, U a, T y, U b) +{ + return x > y ? a : b; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER vec<2, U, Q> associatedMax +( + vec const& x, vec const& a, + vec const& y, vec const& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? a[i] : b[i]; + return Result; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + T x, vec const& a, + T y, vec const& b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x > y ? a[i] : b[i]; + return Result; +} + +// Max comparison between 2 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, U a, + vec const& y, U b +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? a : b; + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER U associatedMax +( + T x, U a, + T y, U b, + T z, U c +) +{ + U Result = x > y ? (x > z ? a : c) : (y > z ? b : c); + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? (x[i] > z[i] ? a[i] : c[i]) : (y[i] > z[i] ? b[i] : c[i]); + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x > y ? (x > z ? a[i] : c[i]) : (y > z ? b[i] : c[i]); + return Result; +} + +// Max comparison between 3 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + Result[i] = x[i] > y[i] ? (x[i] > z[i] ? a : c) : (y[i] > z[i] ? b : c); + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER U associatedMax +( + T x, U a, + T y, U b, + T z, U c, + T w, U d +) +{ + T Test1 = max(x, y); + T Test2 = max(z, w); + U Result1 = x > y ? a : b; + U Result2 = z > w ? c : d; + U Result = Test1 > Test2 ? Result1 : Result2; + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, vec const& a, + vec const& y, vec const& b, + vec const& z, vec const& c, + vec const& w, vec const& d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = max(x[i], y[i]); + T Test2 = max(z[i], w[i]); + U Result1 = x[i] > y[i] ? a[i] : b[i]; + U Result2 = z[i] > w[i] ? c[i] : d[i]; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + T x, vec const& a, + T y, vec const& b, + T z, vec const& c, + T w, vec const& d +) +{ + T Test1 = max(x, y); + T Test2 = max(z, w); + + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + U Result1 = x > y ? a[i] : b[i]; + U Result2 = z > w ? c[i] : d[i]; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 4 variables +template +GLM_FUNC_QUALIFIER vec associatedMax +( + vec const& x, U a, + vec const& y, U b, + vec const& z, U c, + vec const& w, U d +) +{ + vec Result; + for(length_t i = 0, n = Result.length(); i < n; ++i) + { + T Test1 = max(x[i], y[i]); + T Test2 = max(z[i], w[i]); + U Result1 = x[i] > y[i] ? a : b; + U Result2 = z[i] > w[i] ? c : d; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} +}//namespace glm diff --git a/vendor/glm/glm/gtx/bit.hpp b/vendor/glm/glm/gtx/bit.hpp new file mode 100644 index 0000000..60a7aef --- /dev/null +++ b/vendor/glm/glm/gtx/bit.hpp @@ -0,0 +1,98 @@ +/// @ref gtx_bit +/// @file glm/gtx/bit.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_bit GLM_GTX_bit +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../gtc/bitfield.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_bit is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_bit extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_bit + /// @{ + + /// @see gtx_bit + template + GLM_FUNC_DECL genIUType highestBitValue(genIUType Value); + + /// @see gtx_bit + template + GLM_FUNC_DECL genIUType lowestBitValue(genIUType Value); + + /// Find the highest bit set to 1 in a integer variable and return its value. + /// + /// @see gtx_bit + template + GLM_FUNC_DECL vec highestBitValue(vec const& value); + + /// Return the power of two number which value is just higher the input value. + /// Deprecated, use ceilPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoAbove(genIUType Value); + + /// Return the power of two number which value is just higher the input value. + /// Deprecated, use ceilPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL vec powerOfTwoAbove(vec const& value); + + /// Return the power of two number which value is just lower the input value. + /// Deprecated, use floorPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoBelow(genIUType Value); + + /// Return the power of two number which value is just lower the input value. + /// Deprecated, use floorPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL vec powerOfTwoBelow(vec const& value); + + /// Return the power of two number which value is the closet to the input value. + /// Deprecated, use roundPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoNearest(genIUType Value); + + /// Return the power of two number which value is the closet to the input value. + /// Deprecated, use roundPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template + GLM_DEPRECATED GLM_FUNC_DECL vec powerOfTwoNearest(vec const& value); + + /// @} +} //namespace glm + + +#include "bit.inl" + diff --git a/vendor/glm/glm/gtx/bit.inl b/vendor/glm/glm/gtx/bit.inl new file mode 100644 index 0000000..621b626 --- /dev/null +++ b/vendor/glm/glm/gtx/bit.inl @@ -0,0 +1,92 @@ +/// @ref gtx_bit + +namespace glm +{ + /////////////////// + // highestBitValue + + template + GLM_FUNC_QUALIFIER genIUType highestBitValue(genIUType Value) + { + genIUType tmp = Value; + genIUType result = genIUType(0); + while(tmp) + { + result = (tmp & (~tmp + 1)); // grab lowest bit + tmp &= ~result; // clear lowest bit + } + return result; + } + + template + GLM_FUNC_QUALIFIER vec highestBitValue(vec const& v) + { + return detail::functor1::call(highestBitValue, v); + } + + /////////////////// + // lowestBitValue + + template + GLM_FUNC_QUALIFIER genIUType lowestBitValue(genIUType Value) + { + return (Value & (~Value + 1)); + } + + template + GLM_FUNC_QUALIFIER vec lowestBitValue(vec const& v) + { + return detail::functor1::call(lowestBitValue, v); + } + + /////////////////// + // powerOfTwoAbove + + template + GLM_FUNC_QUALIFIER genType powerOfTwoAbove(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value) << 1; + } + + template + GLM_FUNC_QUALIFIER vec powerOfTwoAbove(vec const& v) + { + return detail::functor1::call(powerOfTwoAbove, v); + } + + /////////////////// + // powerOfTwoBelow + + template + GLM_FUNC_QUALIFIER genType powerOfTwoBelow(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value); + } + + template + GLM_FUNC_QUALIFIER vec powerOfTwoBelow(vec const& v) + { + return detail::functor1::call(powerOfTwoBelow, v); + } + + ///////////////////// + // powerOfTwoNearest + + template + GLM_FUNC_QUALIFIER genType powerOfTwoNearest(genType value) + { + if(isPowerOfTwo(value)) + return value; + + genType const prev = highestBitValue(value); + genType const next = prev << 1; + return (next - value) < (value - prev) ? next : prev; + } + + template + GLM_FUNC_QUALIFIER vec powerOfTwoNearest(vec const& v) + { + return detail::functor1::call(powerOfTwoNearest, v); + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/closest_point.hpp b/vendor/glm/glm/gtx/closest_point.hpp new file mode 100644 index 0000000..de6dbbf --- /dev/null +++ b/vendor/glm/glm/gtx/closest_point.hpp @@ -0,0 +1,49 @@ +/// @ref gtx_closest_point +/// @file glm/gtx/closest_point.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_closest_point GLM_GTX_closest_point +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Find the point on a straight line which is the closet of a point. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_closest_point is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_closest_point extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_closest_point + /// @{ + + /// Find the point on a straight line which is the closet of a point. + /// @see gtx_closest_point + template + GLM_FUNC_DECL vec<3, T, Q> closestPointOnLine( + vec<3, T, Q> const& point, + vec<3, T, Q> const& a, + vec<3, T, Q> const& b); + + /// 2d lines work as well + template + GLM_FUNC_DECL vec<2, T, Q> closestPointOnLine( + vec<2, T, Q> const& point, + vec<2, T, Q> const& a, + vec<2, T, Q> const& b); + + /// @} +}// namespace glm + +#include "closest_point.inl" diff --git a/vendor/glm/glm/gtx/closest_point.inl b/vendor/glm/glm/gtx/closest_point.inl new file mode 100644 index 0000000..0a39b04 --- /dev/null +++ b/vendor/glm/glm/gtx/closest_point.inl @@ -0,0 +1,45 @@ +/// @ref gtx_closest_point + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> closestPointOnLine + ( + vec<3, T, Q> const& point, + vec<3, T, Q> const& a, + vec<3, T, Q> const& b + ) + { + T LineLength = distance(a, b); + vec<3, T, Q> Vector = point - a; + vec<3, T, Q> LineDirection = (b - a) / LineLength; + + // Project Vector to LineDirection to get the distance of point from a + T Distance = dot(Vector, LineDirection); + + if(Distance <= T(0)) return a; + if(Distance >= LineLength) return b; + return a + LineDirection * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> closestPointOnLine + ( + vec<2, T, Q> const& point, + vec<2, T, Q> const& a, + vec<2, T, Q> const& b + ) + { + T LineLength = distance(a, b); + vec<2, T, Q> Vector = point - a; + vec<2, T, Q> LineDirection = (b - a) / LineLength; + + // Project Vector to LineDirection to get the distance of point from a + T Distance = dot(Vector, LineDirection); + + if(Distance <= T(0)) return a; + if(Distance >= LineLength) return b; + return a + LineDirection * Distance; + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/color_encoding.hpp b/vendor/glm/glm/gtx/color_encoding.hpp new file mode 100644 index 0000000..96ded2a --- /dev/null +++ b/vendor/glm/glm/gtx/color_encoding.hpp @@ -0,0 +1,54 @@ +/// @ref gtx_color_encoding +/// @file glm/gtx/color_encoding.hpp +/// +/// @see core (dependence) +/// @see gtx_color_encoding (dependence) +/// +/// @defgroup gtx_color_encoding GLM_GTX_color_encoding +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../vec3.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTC_color_encoding is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTC_color_encoding extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_color_encoding + /// @{ + + /// Convert a linear sRGB color to D65 YUV. + template + GLM_FUNC_DECL vec<3, T, Q> convertLinearSRGBToD65XYZ(vec<3, T, Q> const& ColorLinearSRGB); + + /// Convert a linear sRGB color to D50 YUV. + template + GLM_FUNC_DECL vec<3, T, Q> convertLinearSRGBToD50XYZ(vec<3, T, Q> const& ColorLinearSRGB); + + /// Convert a D65 YUV color to linear sRGB. + template + GLM_FUNC_DECL vec<3, T, Q> convertD65XYZToLinearSRGB(vec<3, T, Q> const& ColorD65XYZ); + + /// Convert a D65 YUV color to D50 YUV. + template + GLM_FUNC_DECL vec<3, T, Q> convertD65XYZToD50XYZ(vec<3, T, Q> const& ColorD65XYZ); + + /// @} +} //namespace glm + +#include "color_encoding.inl" diff --git a/vendor/glm/glm/gtx/color_encoding.inl b/vendor/glm/glm/gtx/color_encoding.inl new file mode 100644 index 0000000..e50fa3e --- /dev/null +++ b/vendor/glm/glm/gtx/color_encoding.inl @@ -0,0 +1,45 @@ +/// @ref gtx_color_encoding + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertLinearSRGBToD65XYZ(vec<3, T, Q> const& ColorLinearSRGB) + { + vec<3, T, Q> const M(0.490f, 0.17697f, 0.2f); + vec<3, T, Q> const N(0.31f, 0.8124f, 0.01063f); + vec<3, T, Q> const O(0.490f, 0.01f, 0.99f); + + return (M * ColorLinearSRGB + N * ColorLinearSRGB + O * ColorLinearSRGB) * static_cast(5.650675255693055f); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertLinearSRGBToD50XYZ(vec<3, T, Q> const& ColorLinearSRGB) + { + vec<3, T, Q> const M(0.436030342570117f, 0.222438466210245f, 0.013897440074263f); + vec<3, T, Q> const N(0.385101860087134f, 0.716942745571917f, 0.097076381494207f); + vec<3, T, Q> const O(0.143067806654203f, 0.060618777416563f, 0.713926257896652f); + + return M * ColorLinearSRGB + N * ColorLinearSRGB + O * ColorLinearSRGB; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertD65XYZToLinearSRGB(vec<3, T, Q> const& ColorD65XYZ) + { + vec<3, T, Q> const M(0.41847f, -0.091169f, 0.0009209f); + vec<3, T, Q> const N(-0.15866f, 0.25243f, 0.015708f); + vec<3, T, Q> const O(0.0009209f, -0.0025498f, 0.1786f); + + return M * ColorD65XYZ + N * ColorD65XYZ + O * ColorD65XYZ; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> convertD65XYZToD50XYZ(vec<3, T, Q> const& ColorD65XYZ) + { + vec<3, T, Q> const M(+1.047844353856414f, +0.029549007606644f, -0.009250984365223f); + vec<3, T, Q> const N(+0.022898981050086f, +0.990508028941971f, +0.015072338237051f); + vec<3, T, Q> const O(-0.050206647741605f, -0.017074711360960f, +0.751717835079977f); + + return M * ColorD65XYZ + N * ColorD65XYZ + O * ColorD65XYZ; + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/color_space.hpp b/vendor/glm/glm/gtx/color_space.hpp new file mode 100644 index 0000000..a634392 --- /dev/null +++ b/vendor/glm/glm/gtx/color_space.hpp @@ -0,0 +1,72 @@ +/// @ref gtx_color_space +/// @file glm/gtx/color_space.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_color_space GLM_GTX_color_space +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Related to RGB to HSV conversions and operations. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_color_space is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_color_space extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_color_space + /// @{ + + /// Converts a color from HSV color space to its color in RGB color space. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<3, T, Q> rgbColor( + vec<3, T, Q> const& hsvValue); + + /// Converts a color from RGB color space to its color in HSV color space. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<3, T, Q> hsvColor( + vec<3, T, Q> const& rgbValue); + + /// Build a saturation matrix. + /// @see gtx_color_space + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> saturation( + T const s); + + /// Modify the saturation of a color. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<3, T, Q> saturation( + T const s, + vec<3, T, Q> const& color); + + /// Modify the saturation of a color. + /// @see gtx_color_space + template + GLM_FUNC_DECL vec<4, T, Q> saturation( + T const s, + vec<4, T, Q> const& color); + + /// Compute color luminosity associating ratios (0.33, 0.59, 0.11) to RGB canals. + /// @see gtx_color_space + template + GLM_FUNC_DECL T luminosity( + vec<3, T, Q> const& color); + + /// @} +}//namespace glm + +#include "color_space.inl" diff --git a/vendor/glm/glm/gtx/color_space.inl b/vendor/glm/glm/gtx/color_space.inl new file mode 100644 index 0000000..f698afe --- /dev/null +++ b/vendor/glm/glm/gtx/color_space.inl @@ -0,0 +1,141 @@ +/// @ref gtx_color_space + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rgbColor(const vec<3, T, Q>& hsvColor) + { + vec<3, T, Q> hsv = hsvColor; + vec<3, T, Q> rgbColor; + + if(hsv.y == static_cast(0)) + // achromatic (grey) + rgbColor = vec<3, T, Q>(hsv.z); + else + { + T sector = floor(hsv.x * (T(1) / T(60))); + T frac = (hsv.x * (T(1) / T(60))) - sector; + // factorial part of h + T o = hsv.z * (T(1) - hsv.y); + T p = hsv.z * (T(1) - hsv.y * frac); + T q = hsv.z * (T(1) - hsv.y * (T(1) - frac)); + + switch(int(sector)) + { + default: + case 0: + rgbColor.r = hsv.z; + rgbColor.g = q; + rgbColor.b = o; + break; + case 1: + rgbColor.r = p; + rgbColor.g = hsv.z; + rgbColor.b = o; + break; + case 2: + rgbColor.r = o; + rgbColor.g = hsv.z; + rgbColor.b = q; + break; + case 3: + rgbColor.r = o; + rgbColor.g = p; + rgbColor.b = hsv.z; + break; + case 4: + rgbColor.r = q; + rgbColor.g = o; + rgbColor.b = hsv.z; + break; + case 5: + rgbColor.r = hsv.z; + rgbColor.g = o; + rgbColor.b = p; + break; + } + } + + return rgbColor; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> hsvColor(const vec<3, T, Q>& rgbColor) + { + vec<3, T, Q> hsv = rgbColor; + float Min = min(min(rgbColor.r, rgbColor.g), rgbColor.b); + float Max = max(max(rgbColor.r, rgbColor.g), rgbColor.b); + float Delta = Max - Min; + + hsv.z = Max; + + if(Max != static_cast(0)) + { + hsv.y = Delta / hsv.z; + T h = static_cast(0); + + if(rgbColor.r == Max) + // between yellow & magenta + h = static_cast(0) + T(60) * (rgbColor.g - rgbColor.b) / Delta; + else if(rgbColor.g == Max) + // between cyan & yellow + h = static_cast(120) + T(60) * (rgbColor.b - rgbColor.r) / Delta; + else + // between magenta & cyan + h = static_cast(240) + T(60) * (rgbColor.r - rgbColor.g) / Delta; + + if(h < T(0)) + hsv.x = h + T(360); + else + hsv.x = h; + } + else + { + // If r = g = b = 0 then s = 0, h is undefined + hsv.y = static_cast(0); + hsv.x = static_cast(0); + } + + return hsv; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> saturation(T const s) + { + vec<3, T, defaultp> rgbw = vec<3, T, defaultp>(T(0.2126), T(0.7152), T(0.0722)); + + vec<3, T, defaultp> const col((T(1) - s) * rgbw); + + mat<4, 4, T, defaultp> result(T(1)); + result[0][0] = col.x + s; + result[0][1] = col.x; + result[0][2] = col.x; + result[1][0] = col.y; + result[1][1] = col.y + s; + result[1][2] = col.y; + result[2][0] = col.z; + result[2][1] = col.z; + result[2][2] = col.z + s; + + return result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> saturation(const T s, const vec<3, T, Q>& color) + { + return vec<3, T, Q>(saturation(s) * vec<4, T, Q>(color, T(0))); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> saturation(const T s, const vec<4, T, Q>& color) + { + return saturation(s) * color; + } + + template + GLM_FUNC_QUALIFIER T luminosity(const vec<3, T, Q>& color) + { + const vec<3, T, Q> tmp = vec<3, T, Q>(0.33, 0.59, 0.11); + return dot(color, tmp); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/color_space_YCoCg.hpp b/vendor/glm/glm/gtx/color_space_YCoCg.hpp new file mode 100644 index 0000000..dd2b771 --- /dev/null +++ b/vendor/glm/glm/gtx/color_space_YCoCg.hpp @@ -0,0 +1,60 @@ +/// @ref gtx_color_space_YCoCg +/// @file glm/gtx/color_space_YCoCg.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_color_space_YCoCg GLM_GTX_color_space_YCoCg +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// RGB to YCoCg conversions and operations + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_color_space_YCoCg is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_color_space_YCoCg extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_color_space_YCoCg + /// @{ + + /// Convert a color from RGB color space to YCoCg color space. + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> rgb2YCoCg( + vec<3, T, Q> const& rgbColor); + + /// Convert a color from YCoCg color space to RGB color space. + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> YCoCg2rgb( + vec<3, T, Q> const& YCoCgColor); + + /// Convert a color from RGB color space to YCoCgR color space. + /// @see "YCoCg-R: A Color Space with RGB Reversibility and Low Dynamic Range" + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> rgb2YCoCgR( + vec<3, T, Q> const& rgbColor); + + /// Convert a color from YCoCgR color space to RGB color space. + /// @see "YCoCg-R: A Color Space with RGB Reversibility and Low Dynamic Range" + /// @see gtx_color_space_YCoCg + template + GLM_FUNC_DECL vec<3, T, Q> YCoCgR2rgb( + vec<3, T, Q> const& YCoCgColor); + + /// @} +}//namespace glm + +#include "color_space_YCoCg.inl" diff --git a/vendor/glm/glm/gtx/color_space_YCoCg.inl b/vendor/glm/glm/gtx/color_space_YCoCg.inl new file mode 100644 index 0000000..83ba857 --- /dev/null +++ b/vendor/glm/glm/gtx/color_space_YCoCg.inl @@ -0,0 +1,107 @@ +/// @ref gtx_color_space_YCoCg + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCg + ( + vec<3, T, Q> const& rgbColor + ) + { + vec<3, T, Q> result; + result.x/*Y */ = rgbColor.r / T(4) + rgbColor.g / T(2) + rgbColor.b / T(4); + result.y/*Co*/ = rgbColor.r / T(2) + rgbColor.g * T(0) - rgbColor.b / T(2); + result.z/*Cg*/ = - rgbColor.r / T(4) + rgbColor.g / T(2) - rgbColor.b / T(4); + return result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCg2rgb + ( + vec<3, T, Q> const& YCoCgColor + ) + { + vec<3, T, Q> result; + result.r = YCoCgColor.x + YCoCgColor.y - YCoCgColor.z; + result.g = YCoCgColor.x + YCoCgColor.z; + result.b = YCoCgColor.x - YCoCgColor.y - YCoCgColor.z; + return result; + } + + template + class compute_YCoCgR { + public: + static GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCgR + ( + vec<3, T, Q> const& rgbColor + ) + { + vec<3, T, Q> result; + result.x/*Y */ = rgbColor.g * static_cast(0.5) + (rgbColor.r + rgbColor.b) * static_cast(0.25); + result.y/*Co*/ = rgbColor.r - rgbColor.b; + result.z/*Cg*/ = rgbColor.g - (rgbColor.r + rgbColor.b) * static_cast(0.5); + return result; + } + + static GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCgR2rgb + ( + vec<3, T, Q> const& YCoCgRColor + ) + { + vec<3, T, Q> result; + T tmp = YCoCgRColor.x - (YCoCgRColor.z * static_cast(0.5)); + result.g = YCoCgRColor.z + tmp; + result.b = tmp - (YCoCgRColor.y * static_cast(0.5)); + result.r = result.b + YCoCgRColor.y; + return result; + } + }; + + template + class compute_YCoCgR { + public: + static GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCgR + ( + vec<3, T, Q> const& rgbColor + ) + { + vec<3, T, Q> result; + result.y/*Co*/ = rgbColor.r - rgbColor.b; + T tmp = rgbColor.b + (result.y >> 1); + result.z/*Cg*/ = rgbColor.g - tmp; + result.x/*Y */ = tmp + (result.z >> 1); + return result; + } + + static GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCgR2rgb + ( + vec<3, T, Q> const& YCoCgRColor + ) + { + vec<3, T, Q> result; + T tmp = YCoCgRColor.x - (YCoCgRColor.z >> 1); + result.g = YCoCgRColor.z + tmp; + result.b = tmp - (YCoCgRColor.y >> 1); + result.r = result.b + YCoCgRColor.y; + return result; + } + }; + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rgb2YCoCgR + ( + vec<3, T, Q> const& rgbColor + ) + { + return compute_YCoCgR::is_integer>::rgb2YCoCgR(rgbColor); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> YCoCgR2rgb + ( + vec<3, T, Q> const& YCoCgRColor + ) + { + return compute_YCoCgR::is_integer>::YCoCgR2rgb(YCoCgRColor); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/common.hpp b/vendor/glm/glm/gtx/common.hpp new file mode 100644 index 0000000..254ada2 --- /dev/null +++ b/vendor/glm/glm/gtx/common.hpp @@ -0,0 +1,76 @@ +/// @ref gtx_common +/// @file glm/gtx/common.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_common GLM_GTX_common +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Provide functions to increase the compatibility with Cg and HLSL languages + +#pragma once + +// Dependencies: +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_common is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_common extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_common + /// @{ + + /// Returns true if x is a denormalized number + /// Numbers whose absolute value is too small to be represented in the normal format are represented in an alternate, denormalized format. + /// This format is less precise but can represent values closer to zero. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see GLSL isnan man page + /// @see GLSL 4.20.8 specification, section 8.3 Common Functions + template + GLM_FUNC_DECL typename genType::bool_type isdenormal(genType const& x); + + /// Similar to 'mod' but with a different rounding and integer support. + /// Returns 'x - y * trunc(x/y)' instead of 'x - y * floor(x/y)' + /// + /// @see GLSL mod vs HLSL fmod + /// @see GLSL mod man page + template + GLM_FUNC_DECL vec fmod(vec const& v); + + /// Returns whether vector components values are within an interval. A open interval excludes its endpoints, and is denoted with square brackets. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_relational + template + GLM_FUNC_DECL vec openBounded(vec const& Value, vec const& Min, vec const& Max); + + /// Returns whether vector components values are within an interval. A closed interval includes its endpoints, and is denoted with square brackets. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see ext_vector_relational + template + GLM_FUNC_DECL vec closeBounded(vec const& Value, vec const& Min, vec const& Max); + + /// @} +}//namespace glm + +#include "common.inl" diff --git a/vendor/glm/glm/gtx/common.inl b/vendor/glm/glm/gtx/common.inl new file mode 100644 index 0000000..4ad2126 --- /dev/null +++ b/vendor/glm/glm/gtx/common.inl @@ -0,0 +1,125 @@ +/// @ref gtx_common + +#include +#include "../gtc/epsilon.hpp" +#include "../gtc/constants.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_fmod + { + GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::fmod, a, b); + } + }; + + template + struct compute_fmod + { + GLM_FUNC_QUALIFIER static vec call(vec const& a, vec const& b) + { + return a % b; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER bool isdenormal(T const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isdenormal' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::fpclassify(x) == FP_SUBNORMAL; +# else + return epsilonNotEqual(x, static_cast(0), epsilon()) && std::fabs(x) < std::numeric_limits::min(); +# endif + } + + template + GLM_FUNC_QUALIFIER typename vec<1, T, Q>::bool_type isdenormal + ( + vec<1, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename vec<1, T, Q>::bool_type( + isdenormal(x.x)); + } + + template + GLM_FUNC_QUALIFIER typename vec<2, T, Q>::bool_type isdenormal + ( + vec<2, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename vec<2, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y)); + } + + template + GLM_FUNC_QUALIFIER typename vec<3, T, Q>::bool_type isdenormal + ( + vec<3, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename vec<3, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y), + isdenormal(x.z)); + } + + template + GLM_FUNC_QUALIFIER typename vec<4, T, Q>::bool_type isdenormal + ( + vec<4, T, Q> const& x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename vec<4, T, Q>::bool_type( + isdenormal(x.x), + isdenormal(x.y), + isdenormal(x.z), + isdenormal(x.w)); + } + + // fmod + template + GLM_FUNC_QUALIFIER genType fmod(genType x, genType y) + { + return fmod(vec<1, genType>(x), y).x; + } + + template + GLM_FUNC_QUALIFIER vec fmod(vec const& x, T y) + { + return detail::compute_fmod::is_iec559>::call(x, vec(y)); + } + + template + GLM_FUNC_QUALIFIER vec fmod(vec const& x, vec const& y) + { + return detail::compute_fmod::is_iec559>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER vec openBounded(vec const& Value, vec const& Min, vec const& Max) + { + return greaterThan(Value, Min) && lessThan(Value, Max); + } + + template + GLM_FUNC_QUALIFIER vec closeBounded(vec const& Value, vec const& Min, vec const& Max) + { + return greaterThanEqual(Value, Min) && lessThanEqual(Value, Max); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/compatibility.hpp b/vendor/glm/glm/gtx/compatibility.hpp new file mode 100644 index 0000000..f1b00a6 --- /dev/null +++ b/vendor/glm/glm/gtx/compatibility.hpp @@ -0,0 +1,133 @@ +/// @ref gtx_compatibility +/// @file glm/gtx/compatibility.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_compatibility GLM_GTX_compatibility +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Provide functions to increase the compatibility with Cg and HLSL languages + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/quaternion.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_compatibility is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_compatibility extension included") +# endif +#endif + +#if GLM_COMPILER & GLM_COMPILER_VC +# include +#elif GLM_COMPILER & GLM_COMPILER_GCC +# include +# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) +# undef isfinite +# endif +#endif//GLM_COMPILER + +namespace glm +{ + /// @addtogroup gtx_compatibility + /// @{ + + template GLM_FUNC_QUALIFIER T lerp(T x, T y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> lerp(const vec<2, T, Q>& x, const vec<2, T, Q>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + + template GLM_FUNC_QUALIFIER vec<3, T, Q> lerp(const vec<3, T, Q>& x, const vec<3, T, Q>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> lerp(const vec<4, T, Q>& x, const vec<4, T, Q>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> lerp(const vec<2, T, Q>& x, const vec<2, T, Q>& y, const vec<2, T, Q>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<3, T, Q> lerp(const vec<3, T, Q>& x, const vec<3, T, Q>& y, const vec<3, T, Q>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> lerp(const vec<4, T, Q>& x, const vec<4, T, Q>& y, const vec<4, T, Q>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + + template GLM_FUNC_QUALIFIER T saturate(T x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> saturate(const vec<2, T, Q>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<3, T, Q> saturate(const vec<3, T, Q>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> saturate(const vec<4, T, Q>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + + template GLM_FUNC_QUALIFIER T atan2(T x, T y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<2, T, Q> atan2(const vec<2, T, Q>& x, const vec<2, T, Q>& y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<3, T, Q> atan2(const vec<3, T, Q>& x, const vec<3, T, Q>& y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template GLM_FUNC_QUALIFIER vec<4, T, Q> atan2(const vec<4, T, Q>& x, const vec<4, T, Q>& y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + + template GLM_FUNC_DECL bool isfinite(genType const& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<1, bool, Q> isfinite(const vec<1, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<2, bool, Q> isfinite(const vec<2, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<3, bool, Q> isfinite(const vec<3, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template GLM_FUNC_DECL vec<4, bool, Q> isfinite(const vec<4, T, Q>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + + typedef bool bool1; //!< \brief boolean type with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, bool, highp> bool2; //!< \brief boolean type with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, bool, highp> bool3; //!< \brief boolean type with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, bool, highp> bool4; //!< \brief boolean type with 4 components. (From GLM_GTX_compatibility extension) + + typedef bool bool1x1; //!< \brief boolean matrix with 1 x 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, bool, highp> bool2x2; //!< \brief boolean matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, bool, highp> bool2x3; //!< \brief boolean matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, bool, highp> bool2x4; //!< \brief boolean matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, bool, highp> bool3x2; //!< \brief boolean matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, bool, highp> bool3x3; //!< \brief boolean matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, bool, highp> bool3x4; //!< \brief boolean matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, bool, highp> bool4x2; //!< \brief boolean matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, bool, highp> bool4x3; //!< \brief boolean matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, bool, highp> bool4x4; //!< \brief boolean matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef int int1; //!< \brief integer vector with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, int, highp> int2; //!< \brief integer vector with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, int, highp> int3; //!< \brief integer vector with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, int, highp> int4; //!< \brief integer vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef int int1x1; //!< \brief integer matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, int, highp> int2x2; //!< \brief integer matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, int, highp> int2x3; //!< \brief integer matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, int, highp> int2x4; //!< \brief integer matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, int, highp> int3x2; //!< \brief integer matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, int, highp> int3x3; //!< \brief integer matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, int, highp> int3x4; //!< \brief integer matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, int, highp> int4x2; //!< \brief integer matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, int, highp> int4x3; //!< \brief integer matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, int, highp> int4x4; //!< \brief integer matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef float float1; //!< \brief single-qualifier floating-point vector with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, float, highp> float2; //!< \brief single-qualifier floating-point vector with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, float, highp> float3; //!< \brief single-qualifier floating-point vector with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, float, highp> float4; //!< \brief single-qualifier floating-point vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef float float1x1; //!< \brief single-qualifier floating-point matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, float, highp> float2x2; //!< \brief single-qualifier floating-point matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, float, highp> float2x3; //!< \brief single-qualifier floating-point matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, float, highp> float2x4; //!< \brief single-qualifier floating-point matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, float, highp> float3x2; //!< \brief single-qualifier floating-point matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, float, highp> float3x3; //!< \brief single-qualifier floating-point matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, float, highp> float3x4; //!< \brief single-qualifier floating-point matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, float, highp> float4x2; //!< \brief single-qualifier floating-point matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, float, highp> float4x3; //!< \brief single-qualifier floating-point matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, float, highp> float4x4; //!< \brief single-qualifier floating-point matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef double double1; //!< \brief double-qualifier floating-point vector with 1 component. (From GLM_GTX_compatibility extension) + typedef vec<2, double, highp> double2; //!< \brief double-qualifier floating-point vector with 2 components. (From GLM_GTX_compatibility extension) + typedef vec<3, double, highp> double3; //!< \brief double-qualifier floating-point vector with 3 components. (From GLM_GTX_compatibility extension) + typedef vec<4, double, highp> double4; //!< \brief double-qualifier floating-point vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef double double1x1; //!< \brief double-qualifier floating-point matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef mat<2, 2, double, highp> double2x2; //!< \brief double-qualifier floating-point matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 3, double, highp> double2x3; //!< \brief double-qualifier floating-point matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<2, 4, double, highp> double2x4; //!< \brief double-qualifier floating-point matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 2, double, highp> double3x2; //!< \brief double-qualifier floating-point matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 3, double, highp> double3x3; //!< \brief double-qualifier floating-point matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<3, 4, double, highp> double3x4; //!< \brief double-qualifier floating-point matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 2, double, highp> double4x2; //!< \brief double-qualifier floating-point matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 3, double, highp> double4x3; //!< \brief double-qualifier floating-point matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef mat<4, 4, double, highp> double4x4; //!< \brief double-qualifier floating-point matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + /// @} +}//namespace glm + +#include "compatibility.inl" diff --git a/vendor/glm/glm/gtx/compatibility.inl b/vendor/glm/glm/gtx/compatibility.inl new file mode 100644 index 0000000..1d49496 --- /dev/null +++ b/vendor/glm/glm/gtx/compatibility.inl @@ -0,0 +1,62 @@ +#include + +namespace glm +{ + // isfinite + template + GLM_FUNC_QUALIFIER bool isfinite( + genType const& x) + { +# if GLM_HAS_CXX11_STL + return std::isfinite(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_VC + return _finite(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_GCC && GLM_PLATFORM & GLM_PLATFORM_ANDROID + return _isfinite(x) != 0; +# else + if (std::numeric_limits::is_integer || std::denorm_absent == std::numeric_limits::has_denorm) + return std::numeric_limits::min() <= x && std::numeric_limits::max() >= x; + else + return -std::numeric_limits::max() <= x && std::numeric_limits::max() >= x; +# endif + } + + template + GLM_FUNC_QUALIFIER vec<1, bool, Q> isfinite( + vec<1, T, Q> const& x) + { + return vec<1, bool, Q>( + isfinite(x.x)); + } + + template + GLM_FUNC_QUALIFIER vec<2, bool, Q> isfinite( + vec<2, T, Q> const& x) + { + return vec<2, bool, Q>( + isfinite(x.x), + isfinite(x.y)); + } + + template + GLM_FUNC_QUALIFIER vec<3, bool, Q> isfinite( + vec<3, T, Q> const& x) + { + return vec<3, bool, Q>( + isfinite(x.x), + isfinite(x.y), + isfinite(x.z)); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isfinite( + vec<4, T, Q> const& x) + { + return vec<4, bool, Q>( + isfinite(x.x), + isfinite(x.y), + isfinite(x.z), + isfinite(x.w)); + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/component_wise.hpp b/vendor/glm/glm/gtx/component_wise.hpp new file mode 100644 index 0000000..34a2b0a --- /dev/null +++ b/vendor/glm/glm/gtx/component_wise.hpp @@ -0,0 +1,69 @@ +/// @ref gtx_component_wise +/// @file glm/gtx/component_wise.hpp +/// @date 2007-05-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_component_wise GLM_GTX_component_wise +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Operations between components of a type + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_component_wise is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_component_wise extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_component_wise + /// @{ + + /// Convert an integer vector to a normalized float vector. + /// If the parameter value type is already a floating qualifier type, the value is passed through. + /// @see gtx_component_wise + template + GLM_FUNC_DECL vec compNormalize(vec const& v); + + /// Convert a normalized float vector to an integer vector. + /// If the parameter value type is already a floating qualifier type, the value is passed through. + /// @see gtx_component_wise + template + GLM_FUNC_DECL vec compScale(vec const& v); + + /// Add all vector components together. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compAdd(genType const& v); + + /// Multiply all vector components together. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compMul(genType const& v); + + /// Find the minimum value between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compMin(genType const& v); + + /// Find the maximum value between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type compMax(genType const& v); + + /// @} +}//namespace glm + +#include "component_wise.inl" diff --git a/vendor/glm/glm/gtx/component_wise.inl b/vendor/glm/glm/gtx/component_wise.inl new file mode 100644 index 0000000..cbbc7d4 --- /dev/null +++ b/vendor/glm/glm/gtx/component_wise.inl @@ -0,0 +1,127 @@ +/// @ref gtx_component_wise + +#include + +namespace glm{ +namespace detail +{ + template + struct compute_compNormalize + {}; + + template + struct compute_compNormalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + floatType const Min = static_cast(std::numeric_limits::min()); + floatType const Max = static_cast(std::numeric_limits::max()); + return (vec(v) - Min) / (Max - Min) * static_cast(2) - static_cast(1); + } + }; + + template + struct compute_compNormalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return vec(v) / static_cast(std::numeric_limits::max()); + } + }; + + template + struct compute_compNormalize + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return v; + } + }; + + template + struct compute_compScale + {}; + + template + struct compute_compScale + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + floatType const Max = static_cast(std::numeric_limits::max()) + static_cast(0.5); + vec const Scaled(v * Max); + vec const Result(Scaled - static_cast(0.5)); + return Result; + } + }; + + template + struct compute_compScale + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return vec(vec(v) * static_cast(std::numeric_limits::max())); + } + }; + + template + struct compute_compScale + { + GLM_FUNC_QUALIFIER static vec call(vec const& v) + { + return v; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER vec compNormalize(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'compNormalize' accepts only floating-point types for 'floatType' template parameter"); + + return detail::compute_compNormalize::is_integer, std::numeric_limits::is_signed>::call(v); + } + + template + GLM_FUNC_QUALIFIER vec compScale(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'compScale' accepts only floating-point types for 'floatType' template parameter"); + + return detail::compute_compScale::is_integer, std::numeric_limits::is_signed>::call(v); + } + + template + GLM_FUNC_QUALIFIER T compAdd(vec const& v) + { + T Result(0); + for(length_t i = 0, n = v.length(); i < n; ++i) + Result += v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER T compMul(vec const& v) + { + T Result(1); + for(length_t i = 0, n = v.length(); i < n; ++i) + Result *= v[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER T compMin(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = min(Result, v[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER T compMax(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = max(Result, v[i]); + return Result; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/dual_quaternion.hpp b/vendor/glm/glm/gtx/dual_quaternion.hpp new file mode 100644 index 0000000..6a51ab7 --- /dev/null +++ b/vendor/glm/glm/gtx/dual_quaternion.hpp @@ -0,0 +1,274 @@ +/// @ref gtx_dual_quaternion +/// @file glm/gtx/dual_quaternion.hpp +/// @author Maksim Vorobiev (msomeone@gmail.com) +/// +/// @see core (dependence) +/// @see gtc_constants (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_dual_quaternion GLM_GTX_dual_quaternion +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines a templated dual-quaternion type and several dual-quaternion operations. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/quaternion.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_dual_quaternion is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_dual_quaternion extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_dual_quaternion + /// @{ + + template + struct tdualquat + { + // -- Implementation detail -- + + typedef T value_type; + typedef qua part_type; + + // -- Data -- + + qua real, dual; + + // -- Component accesses -- + + typedef length_t length_type; + /// Return the count of components of a dual quaternion + GLM_FUNC_DECL static GLM_CONSTEXPR length_type length(){return 2;} + + GLM_FUNC_DECL part_type & operator[](length_type i); + GLM_FUNC_DECL part_type const& operator[](length_type i) const; + + // -- Implicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat() GLM_DEFAULT; + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(tdualquat const& d) GLM_DEFAULT; + template + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(tdualquat const& d); + + // -- Explicit basic constructors -- + + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(qua const& real); + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(qua const& orientation, vec<3, T, Q> const& translation); + GLM_FUNC_DECL GLM_CONSTEXPR tdualquat(qua const& real, qua const& dual); + + // -- Conversion constructors -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR GLM_EXPLICIT tdualquat(tdualquat const& q); + + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR tdualquat(mat<2, 4, T, Q> const& holder_mat); + GLM_FUNC_DECL GLM_EXPLICIT GLM_CONSTEXPR tdualquat(mat<3, 4, T, Q> const& aug_mat); + + // -- Unary arithmetic operators -- + + GLM_FUNC_DECL tdualquat & operator=(tdualquat const& m) GLM_DEFAULT; + + template + GLM_FUNC_DECL tdualquat & operator=(tdualquat const& m); + template + GLM_FUNC_DECL tdualquat & operator*=(U s); + template + GLM_FUNC_DECL tdualquat & operator/=(U s); + }; + + // -- Unary bit operators -- + + template + GLM_FUNC_DECL tdualquat operator+(tdualquat const& q); + + template + GLM_FUNC_DECL tdualquat operator-(tdualquat const& q); + + // -- Binary operators -- + + template + GLM_FUNC_DECL tdualquat operator+(tdualquat const& q, tdualquat const& p); + + template + GLM_FUNC_DECL tdualquat operator*(tdualquat const& q, tdualquat const& p); + + template + GLM_FUNC_DECL vec<3, T, Q> operator*(tdualquat const& q, vec<3, T, Q> const& v); + + template + GLM_FUNC_DECL vec<3, T, Q> operator*(vec<3, T, Q> const& v, tdualquat const& q); + + template + GLM_FUNC_DECL vec<4, T, Q> operator*(tdualquat const& q, vec<4, T, Q> const& v); + + template + GLM_FUNC_DECL vec<4, T, Q> operator*(vec<4, T, Q> const& v, tdualquat const& q); + + template + GLM_FUNC_DECL tdualquat operator*(tdualquat const& q, T const& s); + + template + GLM_FUNC_DECL tdualquat operator*(T const& s, tdualquat const& q); + + template + GLM_FUNC_DECL tdualquat operator/(tdualquat const& q, T const& s); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL bool operator==(tdualquat const& q1, tdualquat const& q2); + + template + GLM_FUNC_DECL bool operator!=(tdualquat const& q1, tdualquat const& q2); + + /// Creates an identity dual quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat dual_quat_identity(); + + /// Returns the normalized quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat normalize(tdualquat const& q); + + /// Returns the linear interpolation of two dual quaternion. + /// + /// @see gtc_dual_quaternion + template + GLM_FUNC_DECL tdualquat lerp(tdualquat const& x, tdualquat const& y, T const& a); + + /// Returns the q inverse. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat inverse(tdualquat const& q); + + /// Converts a quaternion to a 2 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL mat<2, 4, T, Q> mat2x4_cast(tdualquat const& x); + + /// Converts a quaternion to a 3 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL mat<3, 4, T, Q> mat3x4_cast(tdualquat const& x); + + /// Converts a 2 * 4 matrix (matrix which holds real and dual parts) to a quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat dualquat_cast(mat<2, 4, T, Q> const& x); + + /// Converts a 3 * 4 matrix (augmented matrix rotation + translation) to a quaternion. + /// + /// @see gtx_dual_quaternion + template + GLM_FUNC_DECL tdualquat dualquat_cast(mat<3, 4, T, Q> const& x); + + + /// Dual-quaternion of low single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat lowp_dualquat; + + /// Dual-quaternion of medium single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat mediump_dualquat; + + /// Dual-quaternion of high single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat highp_dualquat; + + + /// Dual-quaternion of low single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat lowp_fdualquat; + + /// Dual-quaternion of medium single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat mediump_fdualquat; + + /// Dual-quaternion of high single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat highp_fdualquat; + + + /// Dual-quaternion of low double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat lowp_ddualquat; + + /// Dual-quaternion of medium double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat mediump_ddualquat; + + /// Dual-quaternion of high double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat highp_ddualquat; + + +#if(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + /// Dual-quaternion of floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_fdualquat dualquat; + + /// Dual-quaternion of single-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_fdualquat fdualquat; +#elif(defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef highp_fdualquat dualquat; + typedef highp_fdualquat fdualquat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef mediump_fdualquat dualquat; + typedef mediump_fdualquat fdualquat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_fdualquat dualquat; + typedef lowp_fdualquat fdualquat; +#else +# error "GLM error: multiple default precision requested for single-precision floating-point types" +#endif + + +#if(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + /// Dual-quaternion of default double-qualifier floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_ddualquat ddualquat; +#elif(defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef highp_ddualquat ddualquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef mediump_ddualquat ddualquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_ddualquat ddualquat; +#else +# error "GLM error: Multiple default precision requested for double-precision floating-point types" +#endif + + /// @} +} //namespace glm + +#include "dual_quaternion.inl" diff --git a/vendor/glm/glm/gtx/dual_quaternion.inl b/vendor/glm/glm/gtx/dual_quaternion.inl new file mode 100644 index 0000000..fad07ea --- /dev/null +++ b/vendor/glm/glm/gtx/dual_quaternion.inl @@ -0,0 +1,352 @@ +/// @ref gtx_dual_quaternion + +#include "../geometric.hpp" +#include + +namespace glm +{ + // -- Component accesses -- + + template + GLM_FUNC_QUALIFIER typename tdualquat::part_type & tdualquat::operator[](typename tdualquat::length_type i) + { + assert(i >= 0 && i < this->length()); + return (&real)[i]; + } + + template + GLM_FUNC_QUALIFIER typename tdualquat::part_type const& tdualquat::operator[](typename tdualquat::length_type i) const + { + assert(i >= 0 && i < this->length()); + return (&real)[i]; + } + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat() +# if GLM_CONFIG_DEFAULTED_FUNCTIONS != GLM_DISABLE + : real(qua()) + , dual(qua(0, 0, 0, 0)) +# endif + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(tdualquat const& d) + : real(d.real) + , dual(d.dual) + {} +# endif + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(tdualquat const& d) + : real(d.real) + , dual(d.dual) + {} + + // -- Explicit basic constructors -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& r) + : real(r), dual(qua(0, 0, 0, 0)) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& q, vec<3, T, Q> const& p) + : real(q), dual( + T(-0.5) * ( p.x*q.x + p.y*q.y + p.z*q.z), + T(+0.5) * ( p.x*q.w + p.y*q.z - p.z*q.y), + T(+0.5) * (-p.x*q.z + p.y*q.w + p.z*q.x), + T(+0.5) * ( p.x*q.y - p.y*q.x + p.z*q.w)) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& r, qua const& d) + : real(r), dual(d) + {} + + // -- Conversion constructors -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(tdualquat const& q) + : real(q.real) + , dual(q.dual) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(mat<2, 4, T, Q> const& m) + { + *this = dualquat_cast(m); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(mat<3, 4, T, Q> const& m) + { + *this = dualquat_cast(m); + } + + // -- Unary arithmetic operators -- + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_FUNC_QUALIFIER tdualquat & tdualquat::operator=(tdualquat const& q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } +# endif + + template + template + GLM_FUNC_QUALIFIER tdualquat & tdualquat::operator=(tdualquat const& q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tdualquat & tdualquat::operator*=(U s) + { + this->real *= static_cast(s); + this->dual *= static_cast(s); + return *this; + } + + template + template + GLM_FUNC_QUALIFIER tdualquat & tdualquat::operator/=(U s) + { + this->real /= static_cast(s); + this->dual /= static_cast(s); + return *this; + } + + // -- Unary bit operators -- + + template + GLM_FUNC_QUALIFIER tdualquat operator+(tdualquat const& q) + { + return q; + } + + template + GLM_FUNC_QUALIFIER tdualquat operator-(tdualquat const& q) + { + return tdualquat(-q.real, -q.dual); + } + + // -- Binary operators -- + + template + GLM_FUNC_QUALIFIER tdualquat operator+(tdualquat const& q, tdualquat const& p) + { + return tdualquat(q.real + p.real,q.dual + p.dual); + } + + template + GLM_FUNC_QUALIFIER tdualquat operator*(tdualquat const& p, tdualquat const& o) + { + return tdualquat(p.real * o.real,p.real * o.dual + p.dual * o.real); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(tdualquat const& q, vec<3, T, Q> const& v) + { + vec<3, T, Q> const real_v3(q.real.x,q.real.y,q.real.z); + vec<3, T, Q> const dual_v3(q.dual.x,q.dual.y,q.dual.z); + return (cross(real_v3, cross(real_v3,v) + v * q.real.w + dual_v3) + dual_v3 * q.real.w - real_v3 * q.dual.w) * T(2) + v; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> operator*(vec<3, T, Q> const& v, tdualquat const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(tdualquat const& q, vec<4, T, Q> const& v) + { + return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> operator*(vec<4, T, Q> const& v, tdualquat const& q) + { + return glm::inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER tdualquat operator*(tdualquat const& q, T const& s) + { + return tdualquat(q.real * s, q.dual * s); + } + + template + GLM_FUNC_QUALIFIER tdualquat operator*(T const& s, tdualquat const& q) + { + return q * s; + } + + template + GLM_FUNC_QUALIFIER tdualquat operator/(tdualquat const& q, T const& s) + { + return tdualquat(q.real / s, q.dual / s); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER bool operator==(tdualquat const& q1, tdualquat const& q2) + { + return (q1.real == q2.real) && (q1.dual == q2.dual); + } + + template + GLM_FUNC_QUALIFIER bool operator!=(tdualquat const& q1, tdualquat const& q2) + { + return (q1.real != q2.real) || (q1.dual != q2.dual); + } + + // -- Operations -- + + template + GLM_FUNC_QUALIFIER tdualquat dual_quat_identity() + { + return tdualquat( + qua(static_cast(1), static_cast(0), static_cast(0), static_cast(0)), + qua(static_cast(0), static_cast(0), static_cast(0), static_cast(0))); + } + + template + GLM_FUNC_QUALIFIER tdualquat normalize(tdualquat const& q) + { + return q / length(q.real); + } + + template + GLM_FUNC_QUALIFIER tdualquat lerp(tdualquat const& x, tdualquat const& y, T const& a) + { + // Dual Quaternion Linear blend aka DLB: + // Lerp is only defined in [0, 1] + assert(a >= static_cast(0)); + assert(a <= static_cast(1)); + T const k = dot(x.real,y.real) < static_cast(0) ? -a : a; + T const one(1); + return tdualquat(x * (one - a) + y * k); + } + + template + GLM_FUNC_QUALIFIER tdualquat inverse(tdualquat const& q) + { + const glm::qua real = conjugate(q.real); + const glm::qua dual = conjugate(q.dual); + return tdualquat(real, dual + (real * (-2.0f * dot(real,dual)))); + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> mat2x4_cast(tdualquat const& x) + { + return mat<2, 4, T, Q>( x[0].x, x[0].y, x[0].z, x[0].w, x[1].x, x[1].y, x[1].z, x[1].w ); + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> mat3x4_cast(tdualquat const& x) + { + qua r = x.real / length2(x.real); + + qua const rr(r.w * x.real.w, r.x * x.real.x, r.y * x.real.y, r.z * x.real.z); + r *= static_cast(2); + + T const xy = r.x * x.real.y; + T const xz = r.x * x.real.z; + T const yz = r.y * x.real.z; + T const wx = r.w * x.real.x; + T const wy = r.w * x.real.y; + T const wz = r.w * x.real.z; + + vec<4, T, Q> const a( + rr.w + rr.x - rr.y - rr.z, + xy - wz, + xz + wy, + -(x.dual.w * r.x - x.dual.x * r.w + x.dual.y * r.z - x.dual.z * r.y)); + + vec<4, T, Q> const b( + xy + wz, + rr.w + rr.y - rr.x - rr.z, + yz - wx, + -(x.dual.w * r.y - x.dual.x * r.z - x.dual.y * r.w + x.dual.z * r.x)); + + vec<4, T, Q> const c( + xz - wy, + yz + wx, + rr.w + rr.z - rr.x - rr.y, + -(x.dual.w * r.z + x.dual.x * r.y - x.dual.y * r.x - x.dual.z * r.w)); + + return mat<3, 4, T, Q>(a, b, c); + } + + template + GLM_FUNC_QUALIFIER tdualquat dualquat_cast(mat<2, 4, T, Q> const& x) + { + return tdualquat( + qua( x[0].w, x[0].x, x[0].y, x[0].z ), + qua( x[1].w, x[1].x, x[1].y, x[1].z )); + } + + template + GLM_FUNC_QUALIFIER tdualquat dualquat_cast(mat<3, 4, T, Q> const& x) + { + qua real; + + T const trace = x[0].x + x[1].y + x[2].z; + if(trace > static_cast(0)) + { + T const r = sqrt(T(1) + trace); + T const invr = static_cast(0.5) / r; + real.w = static_cast(0.5) * r; + real.x = (x[2].y - x[1].z) * invr; + real.y = (x[0].z - x[2].x) * invr; + real.z = (x[1].x - x[0].y) * invr; + } + else if(x[0].x > x[1].y && x[0].x > x[2].z) + { + T const r = sqrt(T(1) + x[0].x - x[1].y - x[2].z); + T const invr = static_cast(0.5) / r; + real.x = static_cast(0.5)*r; + real.y = (x[1].x + x[0].y) * invr; + real.z = (x[0].z + x[2].x) * invr; + real.w = (x[2].y - x[1].z) * invr; + } + else if(x[1].y > x[2].z) + { + T const r = sqrt(T(1) + x[1].y - x[0].x - x[2].z); + T const invr = static_cast(0.5) / r; + real.x = (x[1].x + x[0].y) * invr; + real.y = static_cast(0.5) * r; + real.z = (x[2].y + x[1].z) * invr; + real.w = (x[0].z - x[2].x) * invr; + } + else + { + T const r = sqrt(T(1) + x[2].z - x[0].x - x[1].y); + T const invr = static_cast(0.5) / r; + real.x = (x[0].z + x[2].x) * invr; + real.y = (x[2].y + x[1].z) * invr; + real.z = static_cast(0.5) * r; + real.w = (x[1].x - x[0].y) * invr; + } + + qua dual; + dual.x = static_cast(0.5) * ( x[0].w * real.w + x[1].w * real.z - x[2].w * real.y); + dual.y = static_cast(0.5) * (-x[0].w * real.z + x[1].w * real.w + x[2].w * real.x); + dual.z = static_cast(0.5) * ( x[0].w * real.y - x[1].w * real.x + x[2].w * real.w); + dual.w = -static_cast(0.5) * ( x[0].w * real.x + x[1].w * real.y + x[2].w * real.z); + return tdualquat(real, dual); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/easing.hpp b/vendor/glm/glm/gtx/easing.hpp new file mode 100644 index 0000000..57f3d61 --- /dev/null +++ b/vendor/glm/glm/gtx/easing.hpp @@ -0,0 +1,219 @@ +/// @ref gtx_easing +/// @file glm/gtx/easing.hpp +/// @author Robert Chisholm +/// +/// @see core (dependence) +/// +/// @defgroup gtx_easing GLM_GTX_easing +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Easing functions for animations and transitons +/// All functions take a parameter x in the range [0.0,1.0] +/// +/// Based on the AHEasing project of Warren Moore (https://github.com/warrenm/AHEasing) + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_easing is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_easing extension included") +# endif +#endif + +namespace glm{ + /// @addtogroup gtx_easing + /// @{ + + /// Modelled after the line y = x + /// @see gtx_easing + template + GLM_FUNC_DECL genType linearInterpolation(genType const & a); + + /// Modelled after the parabola y = x^2 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quadraticEaseIn(genType const & a); + + /// Modelled after the parabola y = -x^2 + 2x + /// @see gtx_easing + template + GLM_FUNC_DECL genType quadraticEaseOut(genType const & a); + + /// Modelled after the piecewise quadratic + /// y = (1/2)((2x)^2) ; [0, 0.5) + /// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType quadraticEaseInOut(genType const & a); + + /// Modelled after the cubic y = x^3 + template + GLM_FUNC_DECL genType cubicEaseIn(genType const & a); + + /// Modelled after the cubic y = (x - 1)^3 + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType cubicEaseOut(genType const & a); + + /// Modelled after the piecewise cubic + /// y = (1/2)((2x)^3) ; [0, 0.5) + /// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType cubicEaseInOut(genType const & a); + + /// Modelled after the quartic x^4 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quarticEaseIn(genType const & a); + + /// Modelled after the quartic y = 1 - (x - 1)^4 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quarticEaseOut(genType const & a); + + /// Modelled after the piecewise quartic + /// y = (1/2)((2x)^4) ; [0, 0.5) + /// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType quarticEaseInOut(genType const & a); + + /// Modelled after the quintic y = x^5 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quinticEaseIn(genType const & a); + + /// Modelled after the quintic y = (x - 1)^5 + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType quinticEaseOut(genType const & a); + + /// Modelled after the piecewise quintic + /// y = (1/2)((2x)^5) ; [0, 0.5) + /// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType quinticEaseInOut(genType const & a); + + /// Modelled after quarter-cycle of sine wave + /// @see gtx_easing + template + GLM_FUNC_DECL genType sineEaseIn(genType const & a); + + /// Modelled after quarter-cycle of sine wave (different phase) + /// @see gtx_easing + template + GLM_FUNC_DECL genType sineEaseOut(genType const & a); + + /// Modelled after half sine wave + /// @see gtx_easing + template + GLM_FUNC_DECL genType sineEaseInOut(genType const & a); + + /// Modelled after shifted quadrant IV of unit circle + /// @see gtx_easing + template + GLM_FUNC_DECL genType circularEaseIn(genType const & a); + + /// Modelled after shifted quadrant II of unit circle + /// @see gtx_easing + template + GLM_FUNC_DECL genType circularEaseOut(genType const & a); + + /// Modelled after the piecewise circular function + /// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5) + /// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType circularEaseInOut(genType const & a); + + /// Modelled after the exponential function y = 2^(10(x - 1)) + /// @see gtx_easing + template + GLM_FUNC_DECL genType exponentialEaseIn(genType const & a); + + /// Modelled after the exponential function y = -2^(-10x) + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType exponentialEaseOut(genType const & a); + + /// Modelled after the piecewise exponential + /// y = (1/2)2^(10(2x - 1)) ; [0,0.5) + /// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType exponentialEaseInOut(genType const & a); + + /// Modelled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1)) + /// @see gtx_easing + template + GLM_FUNC_DECL genType elasticEaseIn(genType const & a); + + /// Modelled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1 + /// @see gtx_easing + template + GLM_FUNC_DECL genType elasticEaseOut(genType const & a); + + /// Modelled after the piecewise exponentially-damped sine wave: + /// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5) + /// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1] + /// @see gtx_easing + template + GLM_FUNC_DECL genType elasticEaseInOut(genType const & a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseIn(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseOut(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseInOut(genType const& a); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseIn(genType const& a, genType const& o); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseOut(genType const& a, genType const& o); + + /// @param a parameter + /// @param o Optional overshoot modifier + /// @see gtx_easing + template + GLM_FUNC_DECL genType backEaseInOut(genType const& a, genType const& o); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType bounceEaseIn(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType bounceEaseOut(genType const& a); + + /// @see gtx_easing + template + GLM_FUNC_DECL genType bounceEaseInOut(genType const& a); + + /// @} +}//namespace glm + +#include "easing.inl" diff --git a/vendor/glm/glm/gtx/easing.inl b/vendor/glm/glm/gtx/easing.inl new file mode 100644 index 0000000..4b7d05b --- /dev/null +++ b/vendor/glm/glm/gtx/easing.inl @@ -0,0 +1,436 @@ +/// @ref gtx_easing + +#include + +namespace glm{ + + template + GLM_FUNC_QUALIFIER genType linearInterpolation(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a; + } + + template + GLM_FUNC_QUALIFIER genType quadraticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a; + } + + template + GLM_FUNC_QUALIFIER genType quadraticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return -(a * (a - static_cast(2))); + } + + template + GLM_FUNC_QUALIFIER genType quadraticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(2) * a * a; + } + else + { + return (-static_cast(2) * a * a) + (4 * a) - one(); + } + } + + template + GLM_FUNC_QUALIFIER genType cubicEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a * a; + } + + template + GLM_FUNC_QUALIFIER genType cubicEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType const f = a - one(); + return f * f * f + one(); + } + + template + GLM_FUNC_QUALIFIER genType cubicEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if (a < static_cast(0.5)) + { + return static_cast(4) * a * a * a; + } + else + { + genType const f = ((static_cast(2) * a) - static_cast(2)); + return static_cast(0.5) * f * f * f + one(); + } + } + + template + GLM_FUNC_QUALIFIER genType quarticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a * a * a; + } + + template + GLM_FUNC_QUALIFIER genType quarticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType const f = (a - one()); + return f * f * f * (one() - a) + one(); + } + + template + GLM_FUNC_QUALIFIER genType quarticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(8) * a * a * a * a; + } + else + { + genType const f = (a - one()); + return -static_cast(8) * f * f * f * f + one(); + } + } + + template + GLM_FUNC_QUALIFIER genType quinticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return a * a * a * a * a; + } + + template + GLM_FUNC_QUALIFIER genType quinticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType const f = (a - one()); + return f * f * f * f * f + one(); + } + + template + GLM_FUNC_QUALIFIER genType quinticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(16) * a * a * a * a * a; + } + else + { + genType const f = ((static_cast(2) * a) - static_cast(2)); + return static_cast(0.5) * f * f * f * f * f + one(); + } + } + + template + GLM_FUNC_QUALIFIER genType sineEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return sin((a - one()) * half_pi()) + one(); + } + + template + GLM_FUNC_QUALIFIER genType sineEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return sin(a * half_pi()); + } + + template + GLM_FUNC_QUALIFIER genType sineEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return static_cast(0.5) * (one() - cos(a * pi())); + } + + template + GLM_FUNC_QUALIFIER genType circularEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return one() - sqrt(one() - (a * a)); + } + + template + GLM_FUNC_QUALIFIER genType circularEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return sqrt((static_cast(2) - a) * a); + } + + template + GLM_FUNC_QUALIFIER genType circularEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(0.5) * (one() - std::sqrt(one() - static_cast(4) * (a * a))); + } + else + { + return static_cast(0.5) * (std::sqrt(-((static_cast(2) * a) - static_cast(3)) * ((static_cast(2) * a) - one())) + one()); + } + } + + template + GLM_FUNC_QUALIFIER genType exponentialEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a <= zero()) + return a; + else + { + genType const Complementary = a - one(); + genType const Two = static_cast(2); + + return glm::pow(Two, Complementary * static_cast(10)); + } + } + + template + GLM_FUNC_QUALIFIER genType exponentialEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a >= one()) + return a; + else + { + return one() - glm::pow(static_cast(2), -static_cast(10) * a); + } + } + + template + GLM_FUNC_QUALIFIER genType exponentialEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + return static_cast(0.5) * glm::pow(static_cast(2), (static_cast(20) * a) - static_cast(10)); + else + return -static_cast(0.5) * glm::pow(static_cast(2), (-static_cast(20) * a) + static_cast(10)) + one(); + } + + template + GLM_FUNC_QUALIFIER genType elasticEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return std::sin(static_cast(13) * half_pi() * a) * glm::pow(static_cast(2), static_cast(10) * (a - one())); + } + + template + GLM_FUNC_QUALIFIER genType elasticEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return std::sin(-static_cast(13) * half_pi() * (a + one())) * glm::pow(static_cast(2), -static_cast(10) * a) + one(); + } + + template + GLM_FUNC_QUALIFIER genType elasticEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + return static_cast(0.5) * std::sin(static_cast(13) * half_pi() * (static_cast(2) * a)) * glm::pow(static_cast(2), static_cast(10) * ((static_cast(2) * a) - one())); + else + return static_cast(0.5) * (std::sin(-static_cast(13) * half_pi() * ((static_cast(2) * a - one()) + one())) * glm::pow(static_cast(2), -static_cast(10) * (static_cast(2) * a - one())) + static_cast(2)); + } + + template + GLM_FUNC_QUALIFIER genType backEaseIn(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType z = ((o + one()) * a) - o; + return (a * a * z); + } + + template + GLM_FUNC_QUALIFIER genType backEaseOut(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType n = a - one(); + genType z = ((o + one()) * n) + o; + return (n * n * z) + one(); + } + + template + GLM_FUNC_QUALIFIER genType backEaseInOut(genType const& a, genType const& o) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + genType s = o * static_cast(1.525); + genType x = static_cast(0.5); + genType n = a / static_cast(0.5); + + if (n < static_cast(1)) + { + genType z = ((s + static_cast(1)) * n) - s; + genType m = n * n * z; + return x * m; + } + else + { + n -= static_cast(2); + genType z = ((s + static_cast(1)) * n) + s; + genType m = (n*n*z) + static_cast(2); + return x * m; + } + } + + template + GLM_FUNC_QUALIFIER genType backEaseIn(genType const& a) + { + return backEaseIn(a, static_cast(1.70158)); + } + + template + GLM_FUNC_QUALIFIER genType backEaseOut(genType const& a) + { + return backEaseOut(a, static_cast(1.70158)); + } + + template + GLM_FUNC_QUALIFIER genType backEaseInOut(genType const& a) + { + return backEaseInOut(a, static_cast(1.70158)); + } + + template + GLM_FUNC_QUALIFIER genType bounceEaseOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(4.0 / 11.0)) + { + return (static_cast(121) * a * a) / static_cast(16); + } + else if(a < static_cast(8.0 / 11.0)) + { + return (static_cast(363.0 / 40.0) * a * a) - (static_cast(99.0 / 10.0) * a) + static_cast(17.0 / 5.0); + } + else if(a < static_cast(9.0 / 10.0)) + { + return (static_cast(4356.0 / 361.0) * a * a) - (static_cast(35442.0 / 1805.0) * a) + static_cast(16061.0 / 1805.0); + } + else + { + return (static_cast(54.0 / 5.0) * a * a) - (static_cast(513.0 / 25.0) * a) + static_cast(268.0 / 25.0); + } + } + + template + GLM_FUNC_QUALIFIER genType bounceEaseIn(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + return one() - bounceEaseOut(one() - a); + } + + template + GLM_FUNC_QUALIFIER genType bounceEaseInOut(genType const& a) + { + // Only defined in [0, 1] + assert(a >= zero()); + assert(a <= one()); + + if(a < static_cast(0.5)) + { + return static_cast(0.5) * (one() - bounceEaseOut(a * static_cast(2))); + } + else + { + return static_cast(0.5) * bounceEaseOut(a * static_cast(2) - one()) + static_cast(0.5); + } + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/euler_angles.hpp b/vendor/glm/glm/gtx/euler_angles.hpp new file mode 100644 index 0000000..2723697 --- /dev/null +++ b/vendor/glm/glm/gtx/euler_angles.hpp @@ -0,0 +1,335 @@ +/// @ref gtx_euler_angles +/// @file glm/gtx/euler_angles.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_euler_angles GLM_GTX_euler_angles +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build matrices from Euler angles. +/// +/// Extraction of Euler angles from rotation matrix. +/// Based on the original paper 2014 Mike Day - Extracting Euler Angles from a Rotation Matrix. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_euler_angles is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_euler_angles extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_euler_angles + /// @{ + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle X. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleX( + T const& angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle Y. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleY( + T const& angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle Z. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZ( + T const& angleZ); + + /// Creates a 3D 4 * 4 homogeneous derived matrix from the rotation matrix about X-axis. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> derivedEulerAngleX( + T const & angleX, T const & angularVelocityX); + + /// Creates a 3D 4 * 4 homogeneous derived matrix from the rotation matrix about Y-axis. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> derivedEulerAngleY( + T const & angleY, T const & angularVelocityY); + + /// Creates a 3D 4 * 4 homogeneous derived matrix from the rotation matrix about Z-axis. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> derivedEulerAngleZ( + T const & angleZ, T const & angularVelocityZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXY( + T const& angleX, + T const& angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYX( + T const& angleY, + T const& angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXZ( + T const& angleX, + T const& angleZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZX( + T const& angle, + T const& angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYZ( + T const& angleY, + T const& angleZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZY( + T const& angleZ, + T const& angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Y * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXYZ( + T const& t1, + T const& t2, + T const& t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYXZ( + T const& yaw, + T const& pitch, + T const& roll); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Z * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXZX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Y * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXYX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYXY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * Z * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYZY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * Y * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZYZ( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZXZ( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Z * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleXZY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * Z * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleYZX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * Y * X). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZYX( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * X * Y). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> eulerAngleZXY( + T const & t1, + T const & t2, + T const & t3); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, defaultp> yawPitchRoll( + T const& yaw, + T const& pitch, + T const& roll); + + /// Creates a 2D 2 * 2 rotation matrix from an euler angle. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<2, 2, T, defaultp> orientate2(T const& angle); + + /// Creates a 2D 4 * 4 homogeneous rotation matrix from an euler angle. + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<3, 3, T, defaultp> orientate3(T const& angle); + + /// Creates a 3D 3 * 3 rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<3, 3, T, Q> orientate3(vec<3, T, Q> const& angles); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template + GLM_FUNC_DECL mat<4, 4, T, Q> orientate4(vec<3, T, Q> const& angles); + + /// Extracts the (X * Y * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleXYZ(mat<4, 4, T, defaultp> const& M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * X * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleYXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (X * Z * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleXZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (X * Y * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleXYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * X * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleYXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * Z * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleYZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * Y * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleZYZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * X * Z) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleZXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (X * Z * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleXZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Y * Z * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleYZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * Y * X) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleZYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// Extracts the (Z * X * Y) Euler angles from the rotation matrix M + /// @see gtx_euler_angles + template + GLM_FUNC_DECL void extractEulerAngleZXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3); + + /// @} +}//namespace glm + +#include "euler_angles.inl" diff --git a/vendor/glm/glm/gtx/euler_angles.inl b/vendor/glm/glm/gtx/euler_angles.inl new file mode 100644 index 0000000..68c5012 --- /dev/null +++ b/vendor/glm/glm/gtx/euler_angles.inl @@ -0,0 +1,899 @@ +/// @ref gtx_euler_angles + +#include "compatibility.hpp" // glm::atan2 + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleX + ( + T const& angleX + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + + return mat<4, 4, T, defaultp>( + T(1), T(0), T(0), T(0), + T(0), cosX, sinX, T(0), + T(0),-sinX, cosX, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleY + ( + T const& angleY + ) + { + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return mat<4, 4, T, defaultp>( + cosY, T(0), -sinY, T(0), + T(0), T(1), T(0), T(0), + sinY, T(0), cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZ + ( + T const& angleZ + ) + { + T cosZ = glm::cos(angleZ); + T sinZ = glm::sin(angleZ); + + return mat<4, 4, T, defaultp>( + cosZ, sinZ, T(0), T(0), + -sinZ, cosZ, T(0), T(0), + T(0), T(0), T(1), T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> derivedEulerAngleX + ( + T const & angleX, + T const & angularVelocityX + ) + { + T cosX = glm::cos(angleX) * angularVelocityX; + T sinX = glm::sin(angleX) * angularVelocityX; + + return mat<4, 4, T, defaultp>( + T(0), T(0), T(0), T(0), + T(0),-sinX, cosX, T(0), + T(0),-cosX,-sinX, T(0), + T(0), T(0), T(0), T(0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> derivedEulerAngleY + ( + T const & angleY, + T const & angularVelocityY + ) + { + T cosY = glm::cos(angleY) * angularVelocityY; + T sinY = glm::sin(angleY) * angularVelocityY; + + return mat<4, 4, T, defaultp>( + -sinY, T(0), -cosY, T(0), + T(0), T(0), T(0), T(0), + cosY, T(0), -sinY, T(0), + T(0), T(0), T(0), T(0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> derivedEulerAngleZ + ( + T const & angleZ, + T const & angularVelocityZ + ) + { + T cosZ = glm::cos(angleZ) * angularVelocityZ; + T sinZ = glm::sin(angleZ) * angularVelocityZ; + + return mat<4, 4, T, defaultp>( + -sinZ, cosZ, T(0), T(0), + -cosZ, -sinZ, T(0), T(0), + T(0), T(0), T(0), T(0), + T(0), T(0), T(0), T(0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXY + ( + T const& angleX, + T const& angleY + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return mat<4, 4, T, defaultp>( + cosY, -sinX * -sinY, cosX * -sinY, T(0), + T(0), cosX, sinX, T(0), + sinY, -sinX * cosY, cosX * cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYX + ( + T const& angleY, + T const& angleX + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return mat<4, 4, T, defaultp>( + cosY, 0, -sinY, T(0), + sinY * sinX, cosX, cosY * sinX, T(0), + sinY * cosX, -sinX, cosY * cosX, T(0), + T(0), T(0), T(0), T(1)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXZ + ( + T const& angleX, + T const& angleZ + ) + { + return eulerAngleX(angleX) * eulerAngleZ(angleZ); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZX + ( + T const& angleZ, + T const& angleX + ) + { + return eulerAngleZ(angleZ) * eulerAngleX(angleX); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYZ + ( + T const& angleY, + T const& angleZ + ) + { + return eulerAngleY(angleY) * eulerAngleZ(angleZ); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZY + ( + T const& angleZ, + T const& angleY + ) + { + return eulerAngleZ(angleZ) * eulerAngleY(angleY); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXYZ + ( + T const& t1, + T const& t2, + T const& t3 + ) + { + T c1 = glm::cos(-t1); + T c2 = glm::cos(-t2); + T c3 = glm::cos(-t3); + T s1 = glm::sin(-t1); + T s2 = glm::sin(-t2); + T s3 = glm::sin(-t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2 * c3; + Result[0][1] =-c1 * s3 + s1 * s2 * c3; + Result[0][2] = s1 * s3 + c1 * s2 * c3; + Result[0][3] = static_cast(0); + Result[1][0] = c2 * s3; + Result[1][1] = c1 * c3 + s1 * s2 * s3; + Result[1][2] =-s1 * c3 + c1 * s2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] =-s2; + Result[2][1] = s1 * c2; + Result[2][2] = c1 * c2; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYXZ + ( + T const& yaw, + T const& pitch, + T const& roll + ) + { + T tmp_ch = glm::cos(yaw); + T tmp_sh = glm::sin(yaw); + T tmp_cp = glm::cos(pitch); + T tmp_sp = glm::sin(pitch); + T tmp_cb = glm::cos(roll); + T tmp_sb = glm::sin(roll); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + Result[0][1] = tmp_sb * tmp_cp; + Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + Result[0][3] = static_cast(0); + Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + Result[1][1] = tmp_cb * tmp_cp; + Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + Result[1][3] = static_cast(0); + Result[2][0] = tmp_sh * tmp_cp; + Result[2][1] = -tmp_sp; + Result[2][2] = tmp_ch * tmp_cp; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXZX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2; + Result[0][1] = c1 * s2; + Result[0][2] = s1 * s2; + Result[0][3] = static_cast(0); + Result[1][0] =-c3 * s2; + Result[1][1] = c1 * c2 * c3 - s1 * s3; + Result[1][2] = c1 * s3 + c2 * c3 * s1; + Result[1][3] = static_cast(0); + Result[2][0] = s2 * s3; + Result[2][1] =-c3 * s1 - c1 * c2 * s3; + Result[2][2] = c1 * c3 - c2 * s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXYX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2; + Result[0][1] = s1 * s2; + Result[0][2] =-c1 * s2; + Result[0][3] = static_cast(0); + Result[1][0] = s2 * s3; + Result[1][1] = c1 * c3 - c2 * s1 * s3; + Result[1][2] = c3 * s1 + c1 * c2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] = c3 * s2; + Result[2][1] =-c1 * s3 - c2 * c3 * s1; + Result[2][2] = c1 * c2 * c3 - s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYXY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c3 - c2 * s1 * s3; + Result[0][1] = s2* s3; + Result[0][2] =-c3 * s1 - c1 * c2 * s3; + Result[0][3] = static_cast(0); + Result[1][0] = s1 * s2; + Result[1][1] = c2; + Result[1][2] = c1 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = c1 * s3 + c2 * c3 * s1; + Result[2][1] =-c3 * s2; + Result[2][2] = c1 * c2 * c3 - s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYZY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2 * c3 - s1 * s3; + Result[0][1] = c3 * s2; + Result[0][2] =-c1 * s3 - c2 * c3 * s1; + Result[0][3] = static_cast(0); + Result[1][0] =-c1 * s2; + Result[1][1] = c2; + Result[1][2] = s1 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = c3 * s1 + c1 * c2 * s3; + Result[2][1] = s2 * s3; + Result[2][2] = c1 * c3 - c2 * s1 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZYZ + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2 * c3 - s1 * s3; + Result[0][1] = c1 * s3 + c2 * c3 * s1; + Result[0][2] =-c3 * s2; + Result[0][3] = static_cast(0); + Result[1][0] =-c3 * s1 - c1 * c2 * s3; + Result[1][1] = c1 * c3 - c2 * s1 * s3; + Result[1][2] = s2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] = c1 * s2; + Result[2][1] = s1 * s2; + Result[2][2] = c2; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZXZ + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c3 - c2 * s1 * s3; + Result[0][1] = c3 * s1 + c1 * c2 * s3; + Result[0][2] = s2 *s3; + Result[0][3] = static_cast(0); + Result[1][0] =-c1 * s3 - c2 * c3 * s1; + Result[1][1] = c1 * c2 * c3 - s1 * s3; + Result[1][2] = c3 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = s1 * s2; + Result[2][1] =-c1 * s2; + Result[2][2] = c2; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleXZY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c2 * c3; + Result[0][1] = s1 * s3 + c1 * c3 * s2; + Result[0][2] = c3 * s1 * s2 - c1 * s3; + Result[0][3] = static_cast(0); + Result[1][0] =-s2; + Result[1][1] = c1 * c2; + Result[1][2] = c2 * s1; + Result[1][3] = static_cast(0); + Result[2][0] = c2 * s3; + Result[2][1] = c1 * s2 * s3 - c3 * s1; + Result[2][2] = c1 * c3 + s1 * s2 *s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleYZX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2; + Result[0][1] = s2; + Result[0][2] =-c2 * s1; + Result[0][3] = static_cast(0); + Result[1][0] = s1 * s3 - c1 * c3 * s2; + Result[1][1] = c2 * c3; + Result[1][2] = c1 * s3 + c3 * s1 * s2; + Result[1][3] = static_cast(0); + Result[2][0] = c3 * s1 + c1 * s2 * s3; + Result[2][1] =-c2 * s3; + Result[2][2] = c1 * c3 - s1 * s2 * s3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZYX + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c2; + Result[0][1] = c2 * s1; + Result[0][2] =-s2; + Result[0][3] = static_cast(0); + Result[1][0] = c1 * s2 * s3 - c3 * s1; + Result[1][1] = c1 * c3 + s1 * s2 * s3; + Result[1][2] = c2 * s3; + Result[1][3] = static_cast(0); + Result[2][0] = s1 * s3 + c1 * c3 * s2; + Result[2][1] = c3 * s1 * s2 - c1 * s3; + Result[2][2] = c2 * c3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> eulerAngleZXY + ( + T const & t1, + T const & t2, + T const & t3 + ) + { + T c1 = glm::cos(t1); + T s1 = glm::sin(t1); + T c2 = glm::cos(t2); + T s2 = glm::sin(t2); + T c3 = glm::cos(t3); + T s3 = glm::sin(t3); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = c1 * c3 - s1 * s2 * s3; + Result[0][1] = c3 * s1 + c1 * s2 * s3; + Result[0][2] =-c2 * s3; + Result[0][3] = static_cast(0); + Result[1][0] =-c2 * s1; + Result[1][1] = c1 * c2; + Result[1][2] = s2; + Result[1][3] = static_cast(0); + Result[2][0] = c1 * s3 + c3 * s1 * s2; + Result[2][1] = s1 * s3 - c1 * c3 * s2; + Result[2][2] = c2 * c3; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> yawPitchRoll + ( + T const& yaw, + T const& pitch, + T const& roll + ) + { + T tmp_ch = glm::cos(yaw); + T tmp_sh = glm::sin(yaw); + T tmp_cp = glm::cos(pitch); + T tmp_sp = glm::sin(pitch); + T tmp_cb = glm::cos(roll); + T tmp_sb = glm::sin(roll); + + mat<4, 4, T, defaultp> Result; + Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + Result[0][1] = tmp_sb * tmp_cp; + Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + Result[0][3] = static_cast(0); + Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + Result[1][1] = tmp_cb * tmp_cp; + Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + Result[1][3] = static_cast(0); + Result[2][0] = tmp_sh * tmp_cp; + Result[2][1] = -tmp_sp; + Result[2][2] = tmp_ch * tmp_cp; + Result[2][3] = static_cast(0); + Result[3][0] = static_cast(0); + Result[3][1] = static_cast(0); + Result[3][2] = static_cast(0); + Result[3][3] = static_cast(1); + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, defaultp> orientate2 + ( + T const& angle + ) + { + T c = glm::cos(angle); + T s = glm::sin(angle); + + mat<2, 2, T, defaultp> Result; + Result[0][0] = c; + Result[0][1] = s; + Result[1][0] = -s; + Result[1][1] = c; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, defaultp> orientate3 + ( + T const& angle + ) + { + T c = glm::cos(angle); + T s = glm::sin(angle); + + mat<3, 3, T, defaultp> Result; + Result[0][0] = c; + Result[0][1] = s; + Result[0][2] = 0.0f; + Result[1][0] = -s; + Result[1][1] = c; + Result[1][2] = 0.0f; + Result[2][0] = 0.0f; + Result[2][1] = 0.0f; + Result[2][2] = 1.0f; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> orientate3 + ( + vec<3, T, Q> const& angles + ) + { + return mat<3, 3, T, Q>(yawPitchRoll(angles.z, angles.x, angles.y)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> orientate4 + ( + vec<3, T, Q> const& angles + ) + { + return yawPitchRoll(angles.z, angles.x, angles.y); + } + + template + GLM_FUNC_DECL void extractEulerAngleXYZ(mat<4, 4, T, defaultp> const& M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][1], M[2][2]); + T C2 = glm::sqrt(M[0][0]*M[0][0] + M[1][0]*M[1][0]); + T T2 = glm::atan2(-M[2][0], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[0][2] - C1*M[0][1], C1*M[1][1] - S1*M[1][2 ]); + t1 = -T1; + t2 = -T2; + t3 = -T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][0], M[2][2]); + T C2 = glm::sqrt(M[0][1]*M[0][1] + M[1][1]*M[1][1]); + T T2 = glm::atan2(-M[2][1], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[1][2] - C1*M[1][0], C1*M[0][0] - S1*M[0][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleXZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[0][2], M[0][1]); + T S2 = glm::sqrt(M[1][0]*M[1][0] + M[2][0]*M[2][0]); + T T2 = glm::atan2(S2, M[0][0]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[1][2] - S1*M[1][1], C1*M[2][2] - S1*M[2][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleXYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[0][1], -M[0][2]); + T S2 = glm::sqrt(M[1][0]*M[1][0] + M[2][0]*M[2][0]); + T T2 = glm::atan2(S2, M[0][0]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(-C1*M[2][1] - S1*M[2][2], C1*M[1][1] + S1*M[1][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[1][0], M[1][2]); + T S2 = glm::sqrt(M[0][1]*M[0][1] + M[2][1]*M[2][1]); + T T2 = glm::atan2(S2, M[1][1]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[2][0] - S1*M[2][2], C1*M[0][0] - S1*M[0][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[1][2], -M[1][0]); + T S2 = glm::sqrt(M[0][1]*M[0][1] + M[2][1]*M[2][1]); + T T2 = glm::atan2(S2, M[1][1]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(-S1*M[0][0] - C1*M[0][2], S1*M[2][0] + C1*M[2][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZYZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][1], M[2][0]); + T S2 = glm::sqrt(M[0][2]*M[0][2] + M[1][2]*M[1][2]); + T T2 = glm::atan2(S2, M[2][2]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[0][1] - S1*M[0][0], C1*M[1][1] - S1*M[1][0]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZXZ(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[2][0], -M[2][1]); + T S2 = glm::sqrt(M[0][2]*M[0][2] + M[1][2]*M[1][2]); + T T2 = glm::atan2(S2, M[2][2]); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(-C1*M[1][0] - S1*M[1][1], C1*M[0][0] + S1*M[0][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleXZY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[1][2], M[1][1]); + T C2 = glm::sqrt(M[0][0]*M[0][0] + M[2][0]*M[2][0]); + T T2 = glm::atan2(-M[1][0], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[0][1] - C1*M[0][2], C1*M[2][2] - S1*M[2][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleYZX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(-M[0][2], M[0][0]); + T C2 = glm::sqrt(M[1][1]*M[1][1] + M[2][1]*M[2][1]); + T T2 = glm::atan2(M[0][1], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[1][0] + C1*M[1][2], S1*M[2][0] + C1*M[2][2]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZYX(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(M[0][1], M[0][0]); + T C2 = glm::sqrt(M[1][2]*M[1][2] + M[2][2]*M[2][2]); + T T2 = glm::atan2(-M[0][2], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(S1*M[2][0] - C1*M[2][1], C1*M[1][1] - S1*M[1][0]); + t1 = T1; + t2 = T2; + t3 = T3; + } + + template + GLM_FUNC_QUALIFIER void extractEulerAngleZXY(mat<4, 4, T, defaultp> const & M, + T & t1, + T & t2, + T & t3) + { + T T1 = glm::atan2(-M[1][0], M[1][1]); + T C2 = glm::sqrt(M[0][2]*M[0][2] + M[2][2]*M[2][2]); + T T2 = glm::atan2(M[1][2], C2); + T S1 = glm::sin(T1); + T C1 = glm::cos(T1); + T T3 = glm::atan2(C1*M[2][0] + S1*M[2][1], C1*M[0][0] + S1*M[0][1]); + t1 = T1; + t2 = T2; + t3 = T3; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/extend.hpp b/vendor/glm/glm/gtx/extend.hpp new file mode 100644 index 0000000..28b7c5c --- /dev/null +++ b/vendor/glm/glm/gtx/extend.hpp @@ -0,0 +1,42 @@ +/// @ref gtx_extend +/// @file glm/gtx/extend.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extend GLM_GTX_extend +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Extend a position from a source to a position at a defined length. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_extend is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_extend extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_extend + /// @{ + + /// Extends of Length the Origin position using the (Source - Origin) direction. + /// @see gtx_extend + template + GLM_FUNC_DECL genType extend( + genType const& Origin, + genType const& Source, + typename genType::value_type const Length); + + /// @} +}//namespace glm + +#include "extend.inl" diff --git a/vendor/glm/glm/gtx/extend.inl b/vendor/glm/glm/gtx/extend.inl new file mode 100644 index 0000000..32128eb --- /dev/null +++ b/vendor/glm/glm/gtx/extend.inl @@ -0,0 +1,48 @@ +/// @ref gtx_extend + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType extend + ( + genType const& Origin, + genType const& Source, + genType const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> extend + ( + vec<2, T, Q> const& Origin, + vec<2, T, Q> const& Source, + T const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> extend + ( + vec<3, T, Q> const& Origin, + vec<3, T, Q> const& Source, + T const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> extend + ( + vec<4, T, Q> const& Origin, + vec<4, T, Q> const& Source, + T const& Distance + ) + { + return Origin + (Source - Origin) * Distance; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/extended_min_max.hpp b/vendor/glm/glm/gtx/extended_min_max.hpp new file mode 100644 index 0000000..025eda2 --- /dev/null +++ b/vendor/glm/glm/gtx/extended_min_max.hpp @@ -0,0 +1,137 @@ +/// @ref gtx_extended_min_max +/// @file glm/gtx/extended_min_max.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extended_min_max GLM_GTX_extented_min_max +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Min and max functions for 3 to 4 parameters. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../ext/vector_common.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_extented_min_max is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_extented_min_max extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_extended_min_max + /// @{ + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T min( + T const& x, + T const& y, + T const& z); + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + typename C::T const& y, + typename C::T const& z); + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + C const& y, + C const& z); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T min( + T const& x, + T const& y, + T const& z, + T const& w); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C min( + C const& x, + C const& y, + C const& z, + C const& w); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T max( + T const& x, + T const& y, + T const& z); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + typename C::T const& y, + typename C::T const& z); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + C const& y, + C const& z); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template + GLM_FUNC_DECL T max( + T const& x, + T const& y, + T const& z, + T const& w); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template class C> + GLM_FUNC_DECL C max( + C const& x, + C const& y, + C const& z, + C const& w); + + /// @} +}//namespace glm + +#include "extended_min_max.inl" diff --git a/vendor/glm/glm/gtx/extended_min_max.inl b/vendor/glm/glm/gtx/extended_min_max.inl new file mode 100644 index 0000000..de5998f --- /dev/null +++ b/vendor/glm/glm/gtx/extended_min_max.inl @@ -0,0 +1,138 @@ +/// @ref gtx_extended_min_max + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T min( + T const& x, + T const& y, + T const& z) + { + return glm::min(glm::min(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + typename C::T const& y, + typename C::T const& z + ) + { + return glm::min(glm::min(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + C const& y, + C const& z + ) + { + return glm::min(glm::min(x, y), z); + } + + template + GLM_FUNC_QUALIFIER T min + ( + T const& x, + T const& y, + T const& z, + T const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C min + ( + C const& x, + C const& y, + C const& z, + C const& w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template + GLM_FUNC_QUALIFIER T max( + T const& x, + T const& y, + T const& z) + { + return glm::max(glm::max(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + typename C::T const& y, + typename C::T const& z + ) + { + return glm::max(glm::max(x, y), z); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + C const& y, + C const& z + ) + { + return glm::max(glm::max(x, y), z); + } + + template + GLM_FUNC_QUALIFIER T max + ( + T const& x, + T const& y, + T const& z, + T const& w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + typename C::T const& y, + typename C::T const& z, + typename C::T const& w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template class C> + GLM_FUNC_QUALIFIER C max + ( + C const& x, + C const& y, + C const& z, + C const& w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/exterior_product.hpp b/vendor/glm/glm/gtx/exterior_product.hpp new file mode 100644 index 0000000..5522df7 --- /dev/null +++ b/vendor/glm/glm/gtx/exterior_product.hpp @@ -0,0 +1,45 @@ +/// @ref gtx_exterior_product +/// @file glm/gtx/exterior_product.hpp +/// +/// @see core (dependence) +/// @see gtx_exterior_product (dependence) +/// +/// @defgroup gtx_exterior_product GLM_GTX_exterior_product +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// @brief Allow to perform bit operations on integer values + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_exterior_product is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_exterior_product extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_exterior_product + /// @{ + + /// Returns the cross product of x and y. + /// + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see Exterior product + template + GLM_FUNC_DECL T cross(vec<2, T, Q> const& v, vec<2, T, Q> const& u); + + /// @} +} //namespace glm + +#include "exterior_product.inl" diff --git a/vendor/glm/glm/gtx/exterior_product.inl b/vendor/glm/glm/gtx/exterior_product.inl new file mode 100644 index 0000000..93661fd --- /dev/null +++ b/vendor/glm/glm/gtx/exterior_product.inl @@ -0,0 +1,26 @@ +/// @ref gtx_exterior_product + +#include + +namespace glm { +namespace detail +{ + template + struct compute_cross_vec2 + { + GLM_FUNC_QUALIFIER static T call(vec<2, T, Q> const& v, vec<2, T, Q> const& u) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'cross' accepts only floating-point inputs"); + + return v.x * u.y - u.x * v.y; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER T cross(vec<2, T, Q> const& x, vec<2, T, Q> const& y) + { + return detail::compute_cross_vec2::value>::call(x, y); + } +}//namespace glm + diff --git a/vendor/glm/glm/gtx/fast_exponential.hpp b/vendor/glm/glm/gtx/fast_exponential.hpp new file mode 100644 index 0000000..6fb7286 --- /dev/null +++ b/vendor/glm/glm/gtx/fast_exponential.hpp @@ -0,0 +1,95 @@ +/// @ref gtx_fast_exponential +/// @file glm/gtx/fast_exponential.hpp +/// +/// @see core (dependence) +/// @see gtx_half_float (dependence) +/// +/// @defgroup gtx_fast_exponential GLM_GTX_fast_exponential +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Fast but less accurate implementations of exponential based functions. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_fast_exponential is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_fast_exponential extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_exponential + /// @{ + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL genType fastPow(genType x, genType y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastPow(vec const& x, vec const& y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL genTypeT fastPow(genTypeT x, genTypeU y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastPow(vec const& x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastExp(T x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastExp(vec const& x); + + /// Faster than the common log function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastLog(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastLog(vec const& x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastExp2(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastExp2(vec const& x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL T fastLog2(T x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template + GLM_FUNC_DECL vec fastLog2(vec const& x); + + /// @} +}//namespace glm + +#include "fast_exponential.inl" diff --git a/vendor/glm/glm/gtx/fast_exponential.inl b/vendor/glm/glm/gtx/fast_exponential.inl new file mode 100644 index 0000000..f139e50 --- /dev/null +++ b/vendor/glm/glm/gtx/fast_exponential.inl @@ -0,0 +1,136 @@ +/// @ref gtx_fast_exponential + +namespace glm +{ + // fastPow: + template + GLM_FUNC_QUALIFIER genType fastPow(genType x, genType y) + { + return exp(y * log(x)); + } + + template + GLM_FUNC_QUALIFIER vec fastPow(vec const& x, vec const& y) + { + return exp(y * log(x)); + } + + template + GLM_FUNC_QUALIFIER T fastPow(T x, int y) + { + T f = static_cast(1); + for(int i = 0; i < y; ++i) + f *= x; + return f; + } + + template + GLM_FUNC_QUALIFIER vec fastPow(vec const& x, vec const& y) + { + vec Result; + for(length_t i = 0, n = x.length(); i < n; ++i) + Result[i] = fastPow(x[i], y[i]); + return Result; + } + + // fastExp + // Note: This function provides accurate results only for value between -1 and 1, else avoid it. + template + GLM_FUNC_QUALIFIER T fastExp(T x) + { + // This has a better looking and same performance in release mode than the following code. However, in debug mode it's slower. + // return 1.0f + x * (1.0f + x * 0.5f * (1.0f + x * 0.3333333333f * (1.0f + x * 0.25 * (1.0f + x * 0.2f)))); + T x2 = x * x; + T x3 = x2 * x; + T x4 = x3 * x; + T x5 = x4 * x; + return T(1) + x + (x2 * T(0.5)) + (x3 * T(0.1666666667)) + (x4 * T(0.041666667)) + (x5 * T(0.008333333333)); + } + /* // Try to handle all values of float... but often shower than std::exp, glm::floor and the loop kill the performance + GLM_FUNC_QUALIFIER float fastExp(float x) + { + const float e = 2.718281828f; + const float IntegerPart = floor(x); + const float FloatPart = x - IntegerPart; + float z = 1.f; + + for(int i = 0; i < int(IntegerPart); ++i) + z *= e; + + const float x2 = FloatPart * FloatPart; + const float x3 = x2 * FloatPart; + const float x4 = x3 * FloatPart; + const float x5 = x4 * FloatPart; + return z * (1.0f + FloatPart + (x2 * 0.5f) + (x3 * 0.1666666667f) + (x4 * 0.041666667f) + (x5 * 0.008333333333f)); + } + + // Increase accuracy on number bigger that 1 and smaller than -1 but it's not enough for high and negative numbers + GLM_FUNC_QUALIFIER float fastExp(float x) + { + // This has a better looking and same performance in release mode than the following code. However, in debug mode it's slower. + // return 1.0f + x * (1.0f + x * 0.5f * (1.0f + x * 0.3333333333f * (1.0f + x * 0.25 * (1.0f + x * 0.2f)))); + float x2 = x * x; + float x3 = x2 * x; + float x4 = x3 * x; + float x5 = x4 * x; + float x6 = x5 * x; + float x7 = x6 * x; + float x8 = x7 * x; + return 1.0f + x + (x2 * 0.5f) + (x3 * 0.1666666667f) + (x4 * 0.041666667f) + (x5 * 0.008333333333f)+ (x6 * 0.00138888888888f) + (x7 * 0.000198412698f) + (x8 * 0.0000248015873f);; + } + */ + + template + GLM_FUNC_QUALIFIER vec fastExp(vec const& x) + { + return detail::functor1::call(fastExp, x); + } + + // fastLog + template + GLM_FUNC_QUALIFIER genType fastLog(genType x) + { + return std::log(x); + } + + /* Slower than the VC7.1 function... + GLM_FUNC_QUALIFIER float fastLog(float x) + { + float y1 = (x - 1.0f) / (x + 1.0f); + float y2 = y1 * y1; + return 2.0f * y1 * (1.0f + y2 * (0.3333333333f + y2 * (0.2f + y2 * 0.1428571429f))); + } + */ + + template + GLM_FUNC_QUALIFIER vec fastLog(vec const& x) + { + return detail::functor1::call(fastLog, x); + } + + //fastExp2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType fastExp2(genType x) + { + return fastExp(0.69314718055994530941723212145818f * x); + } + + template + GLM_FUNC_QUALIFIER vec fastExp2(vec const& x) + { + return detail::functor1::call(fastExp2, x); + } + + // fastLog2, ln2 = 0.69314718055994530941723212145818f + template + GLM_FUNC_QUALIFIER genType fastLog2(genType x) + { + return fastLog(x) / 0.69314718055994530941723212145818f; + } + + template + GLM_FUNC_QUALIFIER vec fastLog2(vec const& x) + { + return detail::functor1::call(fastLog2, x); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/fast_square_root.hpp b/vendor/glm/glm/gtx/fast_square_root.hpp new file mode 100644 index 0000000..9fb3f2f --- /dev/null +++ b/vendor/glm/glm/gtx/fast_square_root.hpp @@ -0,0 +1,92 @@ +/// @ref gtx_fast_square_root +/// @file glm/gtx/fast_square_root.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_fast_square_root GLM_GTX_fast_square_root +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Fast but less accurate implementations of square root based functions. +/// - Sqrt optimisation based on Newton's method, +/// www.gamedev.net/community/forums/topic.asp?topic id=139956 + +#pragma once + +// Dependency: +#include "../common.hpp" +#include "../exponential.hpp" +#include "../geometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_fast_square_root is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_fast_square_root extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_square_root + /// @{ + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastSqrt(genType x); + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL vec fastSqrt(vec const& x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastInverseSqrt(genType x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL vec fastInverseSqrt(vec const& x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastLength(genType x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL T fastLength(vec const& x); + + /// Faster than the common distance function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastDistance(genType x, genType y); + + /// Faster than the common distance function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL T fastDistance(vec const& x, vec const& y); + + /// Faster than the common normalize function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL genType fastNormalize(genType const& x); + + /// @} +}// namespace glm + +#include "fast_square_root.inl" diff --git a/vendor/glm/glm/gtx/fast_square_root.inl b/vendor/glm/glm/gtx/fast_square_root.inl new file mode 100644 index 0000000..4e6c6de --- /dev/null +++ b/vendor/glm/glm/gtx/fast_square_root.inl @@ -0,0 +1,75 @@ +/// @ref gtx_fast_square_root + +namespace glm +{ + // fastSqrt + template + GLM_FUNC_QUALIFIER genType fastSqrt(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fastSqrt' only accept floating-point input"); + + return genType(1) / fastInverseSqrt(x); + } + + template + GLM_FUNC_QUALIFIER vec fastSqrt(vec const& x) + { + return detail::functor1::call(fastSqrt, x); + } + + // fastInversesqrt + template + GLM_FUNC_QUALIFIER genType fastInverseSqrt(genType x) + { + return detail::compute_inversesqrt<1, genType, lowp, detail::is_aligned::value>::call(vec<1, genType, lowp>(x)).x; + } + + template + GLM_FUNC_QUALIFIER vec fastInverseSqrt(vec const& x) + { + return detail::compute_inversesqrt::value>::call(x); + } + + // fastLength + template + GLM_FUNC_QUALIFIER genType fastLength(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fastLength' only accept floating-point inputs"); + + return abs(x); + } + + template + GLM_FUNC_QUALIFIER T fastLength(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'fastLength' only accept floating-point inputs"); + + return fastSqrt(dot(x, x)); + } + + // fastDistance + template + GLM_FUNC_QUALIFIER genType fastDistance(genType x, genType y) + { + return fastLength(y - x); + } + + template + GLM_FUNC_QUALIFIER T fastDistance(vec const& x, vec const& y) + { + return fastLength(y - x); + } + + // fastNormalize + template + GLM_FUNC_QUALIFIER genType fastNormalize(genType x) + { + return x > genType(0) ? genType(1) : -genType(1); + } + + template + GLM_FUNC_QUALIFIER vec fastNormalize(vec const& x) + { + return x * fastInverseSqrt(dot(x, x)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/fast_trigonometry.hpp b/vendor/glm/glm/gtx/fast_trigonometry.hpp new file mode 100644 index 0000000..2650d6e --- /dev/null +++ b/vendor/glm/glm/gtx/fast_trigonometry.hpp @@ -0,0 +1,79 @@ +/// @ref gtx_fast_trigonometry +/// @file glm/gtx/fast_trigonometry.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_fast_trigonometry GLM_GTX_fast_trigonometry +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Fast but less accurate implementations of trigonometric functions. + +#pragma once + +// Dependency: +#include "../gtc/constants.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_fast_trigonometry is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_fast_trigonometry extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_trigonometry + /// @{ + + /// Wrap an angle to [0 2pi[ + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T wrapAngle(T angle); + + /// Faster than the common sin function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastSin(T angle); + + /// Faster than the common cos function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastCos(T angle); + + /// Faster than the common tan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastTan(T angle); + + /// Faster than the common asin function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAsin(T angle); + + /// Faster than the common acos function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAcos(T angle); + + /// Faster than the common atan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAtan(T y, T x); + + /// Faster than the common atan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template + GLM_FUNC_DECL T fastAtan(T angle); + + /// @} +}//namespace glm + +#include "fast_trigonometry.inl" diff --git a/vendor/glm/glm/gtx/fast_trigonometry.inl b/vendor/glm/glm/gtx/fast_trigonometry.inl new file mode 100644 index 0000000..1a710cb --- /dev/null +++ b/vendor/glm/glm/gtx/fast_trigonometry.inl @@ -0,0 +1,142 @@ +/// @ref gtx_fast_trigonometry + +namespace glm{ +namespace detail +{ + template + GLM_FUNC_QUALIFIER vec taylorCos(vec const& x) + { + return static_cast(1) + - (x * x) * (1.f / 2.f) + + ((x * x) * (x * x)) * (1.f / 24.f) + - (((x * x) * (x * x)) * (x * x)) * (1.f / 720.f) + + (((x * x) * (x * x)) * ((x * x) * (x * x))) * (1.f / 40320.f); + } + + template + GLM_FUNC_QUALIFIER T cos_52s(T x) + { + T const xx(x * x); + return (T(0.9999932946) + xx * (T(-0.4999124376) + xx * (T(0.0414877472) + xx * T(-0.0012712095)))); + } + + template + GLM_FUNC_QUALIFIER vec cos_52s(vec const& x) + { + return detail::functor1::call(cos_52s, x); + } +}//namespace detail + + // wrapAngle + template + GLM_FUNC_QUALIFIER T wrapAngle(T angle) + { + return abs(mod(angle, two_pi())); + } + + template + GLM_FUNC_QUALIFIER vec wrapAngle(vec const& x) + { + return detail::functor1::call(wrapAngle, x); + } + + // cos + template + GLM_FUNC_QUALIFIER T fastCos(T x) + { + T const angle(wrapAngle(x)); + + if(angle < half_pi()) + return detail::cos_52s(angle); + if(angle < pi()) + return -detail::cos_52s(pi() - angle); + if(angle < (T(3) * half_pi())) + return -detail::cos_52s(angle - pi()); + + return detail::cos_52s(two_pi() - angle); + } + + template + GLM_FUNC_QUALIFIER vec fastCos(vec const& x) + { + return detail::functor1::call(fastCos, x); + } + + // sin + template + GLM_FUNC_QUALIFIER T fastSin(T x) + { + return fastCos(half_pi() - x); + } + + template + GLM_FUNC_QUALIFIER vec fastSin(vec const& x) + { + return detail::functor1::call(fastSin, x); + } + + // tan + template + GLM_FUNC_QUALIFIER T fastTan(T x) + { + return x + (x * x * x * T(0.3333333333)) + (x * x * x * x * x * T(0.1333333333333)) + (x * x * x * x * x * x * x * T(0.0539682539)); + } + + template + GLM_FUNC_QUALIFIER vec fastTan(vec const& x) + { + return detail::functor1::call(fastTan, x); + } + + // asin + template + GLM_FUNC_QUALIFIER T fastAsin(T x) + { + return x + (x * x * x * T(0.166666667)) + (x * x * x * x * x * T(0.075)) + (x * x * x * x * x * x * x * T(0.0446428571)) + (x * x * x * x * x * x * x * x * x * T(0.0303819444));// + (x * x * x * x * x * x * x * x * x * x * x * T(0.022372159)); + } + + template + GLM_FUNC_QUALIFIER vec fastAsin(vec const& x) + { + return detail::functor1::call(fastAsin, x); + } + + // acos + template + GLM_FUNC_QUALIFIER T fastAcos(T x) + { + return T(1.5707963267948966192313216916398) - fastAsin(x); //(PI / 2) + } + + template + GLM_FUNC_QUALIFIER vec fastAcos(vec const& x) + { + return detail::functor1::call(fastAcos, x); + } + + // atan + template + GLM_FUNC_QUALIFIER T fastAtan(T y, T x) + { + T sgn = sign(y) * sign(x); + return abs(fastAtan(y / x)) * sgn; + } + + template + GLM_FUNC_QUALIFIER vec fastAtan(vec const& y, vec const& x) + { + return detail::functor2::call(fastAtan, y, x); + } + + template + GLM_FUNC_QUALIFIER T fastAtan(T x) + { + return x - (x * x * x * T(0.333333333333)) + (x * x * x * x * x * T(0.2)) - (x * x * x * x * x * x * x * T(0.1428571429)) + (x * x * x * x * x * x * x * x * x * T(0.111111111111)) - (x * x * x * x * x * x * x * x * x * x * x * T(0.0909090909)); + } + + template + GLM_FUNC_QUALIFIER vec fastAtan(vec const& x) + { + return detail::functor1::call(fastAtan, x); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/float_notmalize.inl b/vendor/glm/glm/gtx/float_notmalize.inl new file mode 100644 index 0000000..8cdbc5a --- /dev/null +++ b/vendor/glm/glm/gtx/float_notmalize.inl @@ -0,0 +1,13 @@ +/// @ref gtx_float_normalize + +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec floatNormalize(vec const& v) + { + return vec(v) / static_cast(std::numeric_limits::max()); + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/functions.hpp b/vendor/glm/glm/gtx/functions.hpp new file mode 100644 index 0000000..9f4166c --- /dev/null +++ b/vendor/glm/glm/gtx/functions.hpp @@ -0,0 +1,56 @@ +/// @ref gtx_functions +/// @file glm/gtx/functions.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_functions GLM_GTX_functions +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// List of useful common functions. + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/qualifier.hpp" +#include "../detail/type_vec2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_functions is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_functions extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_functions + /// @{ + + /// 1D gauss function + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL T gauss( + T x, + T ExpectedValue, + T StandardDeviation); + + /// 2D gauss function + /// + /// @see gtc_epsilon + template + GLM_FUNC_DECL T gauss( + vec<2, T, Q> const& Coord, + vec<2, T, Q> const& ExpectedValue, + vec<2, T, Q> const& StandardDeviation); + + /// @} +}//namespace glm + +#include "functions.inl" + diff --git a/vendor/glm/glm/gtx/functions.inl b/vendor/glm/glm/gtx/functions.inl new file mode 100644 index 0000000..29cbb20 --- /dev/null +++ b/vendor/glm/glm/gtx/functions.inl @@ -0,0 +1,30 @@ +/// @ref gtx_functions + +#include "../exponential.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T gauss + ( + T x, + T ExpectedValue, + T StandardDeviation + ) + { + return exp(-((x - ExpectedValue) * (x - ExpectedValue)) / (static_cast(2) * StandardDeviation * StandardDeviation)) / (StandardDeviation * sqrt(static_cast(6.28318530717958647692528676655900576))); + } + + template + GLM_FUNC_QUALIFIER T gauss + ( + vec<2, T, Q> const& Coord, + vec<2, T, Q> const& ExpectedValue, + vec<2, T, Q> const& StandardDeviation + ) + { + vec<2, T, Q> const Squared = ((Coord - ExpectedValue) * (Coord - ExpectedValue)) / (static_cast(2) * StandardDeviation * StandardDeviation); + return exp(-(Squared.x + Squared.y)); + } +}//namespace glm + diff --git a/vendor/glm/glm/gtx/gradient_paint.hpp b/vendor/glm/glm/gtx/gradient_paint.hpp new file mode 100644 index 0000000..6f85bf4 --- /dev/null +++ b/vendor/glm/glm/gtx/gradient_paint.hpp @@ -0,0 +1,53 @@ +/// @ref gtx_gradient_paint +/// @file glm/gtx/gradient_paint.hpp +/// +/// @see core (dependence) +/// @see gtx_optimum_pow (dependence) +/// +/// @defgroup gtx_gradient_paint GLM_GTX_gradient_paint +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Functions that return the color of procedural gradient for specific coordinates. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/optimum_pow.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_gradient_paint is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_gradient_paint extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_gradient_paint + /// @{ + + /// Return a color from a radial gradient. + /// @see - gtx_gradient_paint + template + GLM_FUNC_DECL T radialGradient( + vec<2, T, Q> const& Center, + T const& Radius, + vec<2, T, Q> const& Focal, + vec<2, T, Q> const& Position); + + /// Return a color from a linear gradient. + /// @see - gtx_gradient_paint + template + GLM_FUNC_DECL T linearGradient( + vec<2, T, Q> const& Point0, + vec<2, T, Q> const& Point1, + vec<2, T, Q> const& Position); + + /// @} +}// namespace glm + +#include "gradient_paint.inl" diff --git a/vendor/glm/glm/gtx/gradient_paint.inl b/vendor/glm/glm/gtx/gradient_paint.inl new file mode 100644 index 0000000..4c495e6 --- /dev/null +++ b/vendor/glm/glm/gtx/gradient_paint.inl @@ -0,0 +1,36 @@ +/// @ref gtx_gradient_paint + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T radialGradient + ( + vec<2, T, Q> const& Center, + T const& Radius, + vec<2, T, Q> const& Focal, + vec<2, T, Q> const& Position + ) + { + vec<2, T, Q> F = Focal - Center; + vec<2, T, Q> D = Position - Focal; + T Radius2 = pow2(Radius); + T Fx2 = pow2(F.x); + T Fy2 = pow2(F.y); + + T Numerator = (D.x * F.x + D.y * F.y) + sqrt(Radius2 * (pow2(D.x) + pow2(D.y)) - pow2(D.x * F.y - D.y * F.x)); + T Denominator = Radius2 - (Fx2 + Fy2); + return Numerator / Denominator; + } + + template + GLM_FUNC_QUALIFIER T linearGradient + ( + vec<2, T, Q> const& Point0, + vec<2, T, Q> const& Point1, + vec<2, T, Q> const& Position + ) + { + vec<2, T, Q> Dist = Point1 - Point0; + return (Dist.x * (Position.x - Point0.x) + Dist.y * (Position.y - Point0.y)) / glm::dot(Dist, Dist); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/handed_coordinate_space.hpp b/vendor/glm/glm/gtx/handed_coordinate_space.hpp new file mode 100644 index 0000000..3c85968 --- /dev/null +++ b/vendor/glm/glm/gtx/handed_coordinate_space.hpp @@ -0,0 +1,50 @@ +/// @ref gtx_handed_coordinate_space +/// @file glm/gtx/handed_coordinate_space.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_handed_coordinate_space GLM_GTX_handed_coordinate_space +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// To know if a set of three basis vectors defines a right or left-handed coordinate system. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_handed_coordinate_space is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_handed_coordinate_space extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_handed_coordinate_space + /// @{ + + //! Return if a trihedron right handed or not. + //! From GLM_GTX_handed_coordinate_space extension. + template + GLM_FUNC_DECL bool rightHanded( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal); + + //! Return if a trihedron left handed or not. + //! From GLM_GTX_handed_coordinate_space extension. + template + GLM_FUNC_DECL bool leftHanded( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal); + + /// @} +}// namespace glm + +#include "handed_coordinate_space.inl" diff --git a/vendor/glm/glm/gtx/handed_coordinate_space.inl b/vendor/glm/glm/gtx/handed_coordinate_space.inl new file mode 100644 index 0000000..e43c17b --- /dev/null +++ b/vendor/glm/glm/gtx/handed_coordinate_space.inl @@ -0,0 +1,26 @@ +/// @ref gtx_handed_coordinate_space + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool rightHanded + ( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal + ) + { + return dot(cross(normal, tangent), binormal) > T(0); + } + + template + GLM_FUNC_QUALIFIER bool leftHanded + ( + vec<3, T, Q> const& tangent, + vec<3, T, Q> const& binormal, + vec<3, T, Q> const& normal + ) + { + return dot(cross(normal, tangent), binormal) < T(0); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/hash.hpp b/vendor/glm/glm/gtx/hash.hpp new file mode 100644 index 0000000..05dae9f --- /dev/null +++ b/vendor/glm/glm/gtx/hash.hpp @@ -0,0 +1,142 @@ +/// @ref gtx_hash +/// @file glm/gtx/hash.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_hash GLM_GTX_hash +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add std::hash support for glm types + +#pragma once + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_hash is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_hash extension included") +# endif +#endif + +#include + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/vec1.hpp" + +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" + +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" + +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" + +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" + +#if !GLM_HAS_CXX11_STL +# error "GLM_GTX_hash requires C++11 standard library support" +#endif + +namespace std +{ + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<1, T, Q> const& v) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<2, T, Q> const& v) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<3, T, Q> const& v) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<4, T, Q> const& v) const; + }; + + template + struct hash> + { + GLM_FUNC_DECL size_t operator()(glm::qua const& q) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::tdualquat const& q) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 2, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 3, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 4, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 2, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 3, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 4, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 2, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 3, T,Q> const& m) const; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 4, T,Q> const& m) const; + }; +} // namespace std + +#include "hash.inl" diff --git a/vendor/glm/glm/gtx/hash.inl b/vendor/glm/glm/gtx/hash.inl new file mode 100644 index 0000000..ff71ca9 --- /dev/null +++ b/vendor/glm/glm/gtx/hash.inl @@ -0,0 +1,184 @@ +/// @ref gtx_hash +/// +/// @see core (dependence) +/// +/// @defgroup gtx_hash GLM_GTX_hash +/// @ingroup gtx +/// +/// @brief Add std::hash support for glm types +/// +/// need to be included to use the features of this extension. + +namespace glm { +namespace detail +{ + GLM_INLINE void hash_combine(size_t &seed, size_t hash) + { + hash += 0x9e3779b9 + (seed << 6) + (seed >> 2); + seed ^= hash; + } +}} + +namespace std +{ + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<1, T, Q> const& v) const + { + hash hasher; + return hasher(v.x); + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<2, T, Q> const& v) const + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(v.x)); + glm::detail::hash_combine(seed, hasher(v.y)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<3, T, Q> const& v) const + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(v.x)); + glm::detail::hash_combine(seed, hasher(v.y)); + glm::detail::hash_combine(seed, hasher(v.z)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::vec<4, T, Q> const& v) const + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(v.x)); + glm::detail::hash_combine(seed, hasher(v.y)); + glm::detail::hash_combine(seed, hasher(v.z)); + glm::detail::hash_combine(seed, hasher(v.w)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::qua const& q) const + { + size_t seed = 0; + hash hasher; + glm::detail::hash_combine(seed, hasher(q.x)); + glm::detail::hash_combine(seed, hasher(q.y)); + glm::detail::hash_combine(seed, hasher(q.z)); + glm::detail::hash_combine(seed, hasher(q.w)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::tdualquat const& q) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(q.real)); + glm::detail::hash_combine(seed, hasher(q.dual)); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<2, 2, T, Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<2, 3, T, Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<2, 4, T, Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<3, 2, T, Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<3, 3, T, Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<3, 4, T, Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 2, T,Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + glm::detail::hash_combine(seed, hasher(m[3])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 3, T,Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + glm::detail::hash_combine(seed, hasher(m[3])); + return seed; + } + + template + GLM_FUNC_QUALIFIER size_t hash>::operator()(glm::mat<4, 4, T, Q> const& m) const + { + size_t seed = 0; + hash> hasher; + glm::detail::hash_combine(seed, hasher(m[0])); + glm::detail::hash_combine(seed, hasher(m[1])); + glm::detail::hash_combine(seed, hasher(m[2])); + glm::detail::hash_combine(seed, hasher(m[3])); + return seed; + } +} diff --git a/vendor/glm/glm/gtx/integer.hpp b/vendor/glm/glm/gtx/integer.hpp new file mode 100644 index 0000000..d0b4c61 --- /dev/null +++ b/vendor/glm/glm/gtx/integer.hpp @@ -0,0 +1,76 @@ +/// @ref gtx_integer +/// @file glm/gtx/integer.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_integer GLM_GTX_integer +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add support for integer for core functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/integer.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_integer is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_integer extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_integer + /// @{ + + //! Returns x raised to the y power. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int pow(int x, uint y); + + //! Returns the positive square root of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int sqrt(int x); + + //! Returns the floor log2 of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL unsigned int floor_log2(unsigned int x); + + //! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int mod(int x, int y); + + //! Return the factorial value of a number (!12 max, integer only) + //! From GLM_GTX_integer extension. + template + GLM_FUNC_DECL genType factorial(genType const& x); + + //! 32bit signed integer. + //! From GLM_GTX_integer extension. + typedef signed int sint; + + //! Returns x raised to the y power. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint pow(uint x, uint y); + + //! Returns the positive square root of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint sqrt(uint x); + + //! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint mod(uint x, uint y); + + //! Returns the number of leading zeros. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint nlz(uint x); + + /// @} +}//namespace glm + +#include "integer.inl" diff --git a/vendor/glm/glm/gtx/integer.inl b/vendor/glm/glm/gtx/integer.inl new file mode 100644 index 0000000..956366b --- /dev/null +++ b/vendor/glm/glm/gtx/integer.inl @@ -0,0 +1,185 @@ +/// @ref gtx_integer + +namespace glm +{ + // pow + GLM_FUNC_QUALIFIER int pow(int x, uint y) + { + if(y == 0) + return x >= 0 ? 1 : -1; + + int result = x; + for(uint i = 1; i < y; ++i) + result *= x; + return result; + } + + // sqrt: From Christopher J. Musial, An integer square root, Graphics Gems, 1990, page 387 + GLM_FUNC_QUALIFIER int sqrt(int x) + { + if(x <= 1) return x; + + int NextTrial = x >> 1; + int CurrentAnswer; + + do + { + CurrentAnswer = NextTrial; + NextTrial = (NextTrial + x / NextTrial) >> 1; + } while(NextTrial < CurrentAnswer); + + return CurrentAnswer; + } + +// Henry Gordon Dietz: http://aggregate.org/MAGIC/ +namespace detail +{ + GLM_FUNC_QUALIFIER unsigned int ones32(unsigned int x) + { + /* 32-bit recursive reduction using SWAR... + but first step is mapping 2-bit values + into sum of 2 1-bit values in sneaky way + */ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return(x & 0x0000003f); + } +}//namespace detail + + // Henry Gordon Dietz: http://aggregate.org/MAGIC/ +/* + GLM_FUNC_QUALIFIER unsigned int floor_log2(unsigned int x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + + return _detail::ones32(x) >> 1; + } +*/ + // mod + GLM_FUNC_QUALIFIER int mod(int x, int y) + { + return ((x % y) + y) % y; + } + + // factorial (!12 max, integer only) + template + GLM_FUNC_QUALIFIER genType factorial(genType const& x) + { + genType Temp = x; + genType Result; + for(Result = 1; Temp > 1; --Temp) + Result *= Temp; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> factorial( + vec<2, T, Q> const& x) + { + return vec<2, T, Q>( + factorial(x.x), + factorial(x.y)); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> factorial( + vec<3, T, Q> const& x) + { + return vec<3, T, Q>( + factorial(x.x), + factorial(x.y), + factorial(x.z)); + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> factorial( + vec<4, T, Q> const& x) + { + return vec<4, T, Q>( + factorial(x.x), + factorial(x.y), + factorial(x.z), + factorial(x.w)); + } + + GLM_FUNC_QUALIFIER uint pow(uint x, uint y) + { + if (y == 0) + return 1u; + + uint result = x; + for(uint i = 1; i < y; ++i) + result *= x; + return result; + } + + GLM_FUNC_QUALIFIER uint sqrt(uint x) + { + if(x <= 1) return x; + + uint NextTrial = x >> 1; + uint CurrentAnswer; + + do + { + CurrentAnswer = NextTrial; + NextTrial = (NextTrial + x / NextTrial) >> 1; + } while(NextTrial < CurrentAnswer); + + return CurrentAnswer; + } + + GLM_FUNC_QUALIFIER uint mod(uint x, uint y) + { + return x - y * (x / y); + } + +#if(GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_GCC)) + + GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) + { + return 31u - findMSB(x); + } + +#else + + // Hackers Delight: http://www.hackersdelight.org/HDcode/nlz.c.txt + GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) + { + int y, m, n; + + y = -int(x >> 16); // If left half of x is 0, + m = (y >> 16) & 16; // set n = 16. If left half + n = 16 - m; // is nonzero, set n = 0 and + x = x >> m; // shift x right 16. + // Now x is of the form 0000xxxx. + y = x - 0x100; // If positions 8-15 are 0, + m = (y >> 16) & 8; // add 8 to n and shift x left 8. + n = n + m; + x = x << m; + + y = x - 0x1000; // If positions 12-15 are 0, + m = (y >> 16) & 4; // add 4 to n and shift x left 4. + n = n + m; + x = x << m; + + y = x - 0x4000; // If positions 14-15 are 0, + m = (y >> 16) & 2; // add 2 to n and shift x left 2. + n = n + m; + x = x << m; + + y = x >> 14; // Set y = 0, 1, 2, or 3. + m = y & ~(y >> 1); // Set m = 0, 1, 2, or 2 resp. + return unsigned(n + 2 - m); + } + +#endif//(GLM_COMPILER) + +}//namespace glm diff --git a/vendor/glm/glm/gtx/intersect.hpp b/vendor/glm/glm/gtx/intersect.hpp new file mode 100644 index 0000000..3c78f2b --- /dev/null +++ b/vendor/glm/glm/gtx/intersect.hpp @@ -0,0 +1,92 @@ +/// @ref gtx_intersect +/// @file glm/gtx/intersect.hpp +/// +/// @see core (dependence) +/// @see gtx_closest_point (dependence) +/// +/// @defgroup gtx_intersect GLM_GTX_intersect +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add intersection functions + +#pragma once + +// Dependency: +#include +#include +#include "../glm.hpp" +#include "../geometric.hpp" +#include "../gtx/closest_point.hpp" +#include "../gtx/vector_query.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_closest_point is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_closest_point extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_intersect + /// @{ + + //! Compute the intersection of a ray and a plane. + //! Ray direction and plane normal must be unit length. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRayPlane( + genType const& orig, genType const& dir, + genType const& planeOrig, genType const& planeNormal, + typename genType::value_type & intersectionDistance); + + //! Compute the intersection of a ray and a triangle. + /// Based om Tomas Möller implementation http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/ + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRayTriangle( + vec<3, T, Q> const& orig, vec<3, T, Q> const& dir, + vec<3, T, Q> const& v0, vec<3, T, Q> const& v1, vec<3, T, Q> const& v2, + vec<2, T, Q>& baryPosition, T& distance); + + //! Compute the intersection of a line and a triangle. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectLineTriangle( + genType const& orig, genType const& dir, + genType const& vert0, genType const& vert1, genType const& vert2, + genType & position); + + //! Compute the intersection distance of a ray and a sphere. + //! The ray direction vector is unit length. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRaySphere( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, typename genType::value_type const sphereRadiusSquered, + typename genType::value_type & intersectionDistance); + + //! Compute the intersection of a ray and a sphere. + //! From GLM_GTX_intersect extension. + template + GLM_FUNC_DECL bool intersectRaySphere( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadius, + genType & intersectionPosition, genType & intersectionNormal); + + //! Compute the intersection of a line and a sphere. + //! From GLM_GTX_intersect extension + template + GLM_FUNC_DECL bool intersectLineSphere( + genType const& point0, genType const& point1, + genType const& sphereCenter, typename genType::value_type sphereRadius, + genType & intersectionPosition1, genType & intersectionNormal1, + genType & intersectionPosition2 = genType(), genType & intersectionNormal2 = genType()); + + /// @} +}//namespace glm + +#include "intersect.inl" diff --git a/vendor/glm/glm/gtx/intersect.inl b/vendor/glm/glm/gtx/intersect.inl new file mode 100644 index 0000000..54ecb4d --- /dev/null +++ b/vendor/glm/glm/gtx/intersect.inl @@ -0,0 +1,200 @@ +/// @ref gtx_intersect + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool intersectRayPlane + ( + genType const& orig, genType const& dir, + genType const& planeOrig, genType const& planeNormal, + typename genType::value_type & intersectionDistance + ) + { + typename genType::value_type d = glm::dot(dir, planeNormal); + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + + if(glm::abs(d) > Epsilon) // if dir and planeNormal are not perpendicular + { + typename genType::value_type const tmp_intersectionDistance = glm::dot(planeOrig - orig, planeNormal) / d; + if (tmp_intersectionDistance > static_cast(0)) { // allow only intersections + intersectionDistance = tmp_intersectionDistance; + return true; + } + } + + return false; + } + + template + GLM_FUNC_QUALIFIER bool intersectRayTriangle + ( + vec<3, T, Q> const& orig, vec<3, T, Q> const& dir, + vec<3, T, Q> const& vert0, vec<3, T, Q> const& vert1, vec<3, T, Q> const& vert2, + vec<2, T, Q>& baryPosition, T& distance + ) + { + // find vectors for two edges sharing vert0 + vec<3, T, Q> const edge1 = vert1 - vert0; + vec<3, T, Q> const edge2 = vert2 - vert0; + + // begin calculating determinant - also used to calculate U parameter + vec<3, T, Q> const p = glm::cross(dir, edge2); + + // if determinant is near zero, ray lies in plane of triangle + T const det = glm::dot(edge1, p); + + vec<3, T, Q> Perpendicular(0); + + if(det > std::numeric_limits::epsilon()) + { + // calculate distance from vert0 to ray origin + vec<3, T, Q> const dist = orig - vert0; + + // calculate U parameter and test bounds + baryPosition.x = glm::dot(dist, p); + if(baryPosition.x < static_cast(0) || baryPosition.x > det) + return false; + + // prepare to test V parameter + Perpendicular = glm::cross(dist, edge1); + + // calculate V parameter and test bounds + baryPosition.y = glm::dot(dir, Perpendicular); + if((baryPosition.y < static_cast(0)) || ((baryPosition.x + baryPosition.y) > det)) + return false; + } + else if(det < -std::numeric_limits::epsilon()) + { + // calculate distance from vert0 to ray origin + vec<3, T, Q> const dist = orig - vert0; + + // calculate U parameter and test bounds + baryPosition.x = glm::dot(dist, p); + if((baryPosition.x > static_cast(0)) || (baryPosition.x < det)) + return false; + + // prepare to test V parameter + Perpendicular = glm::cross(dist, edge1); + + // calculate V parameter and test bounds + baryPosition.y = glm::dot(dir, Perpendicular); + if((baryPosition.y > static_cast(0)) || (baryPosition.x + baryPosition.y < det)) + return false; + } + else + return false; // ray is parallel to the plane of the triangle + + T inv_det = static_cast(1) / det; + + // calculate distance, ray intersects triangle + distance = glm::dot(edge2, Perpendicular) * inv_det; + baryPosition *= inv_det; + + return true; + } + + template + GLM_FUNC_QUALIFIER bool intersectLineTriangle + ( + genType const& orig, genType const& dir, + genType const& vert0, genType const& vert1, genType const& vert2, + genType & position + ) + { + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + + genType edge1 = vert1 - vert0; + genType edge2 = vert2 - vert0; + + genType Perpendicular = cross(dir, edge2); + + float det = dot(edge1, Perpendicular); + + if (det > -Epsilon && det < Epsilon) + return false; + typename genType::value_type inv_det = typename genType::value_type(1) / det; + + genType Tengant = orig - vert0; + + position.y = dot(Tengant, Perpendicular) * inv_det; + if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1)) + return false; + + genType Cotengant = cross(Tengant, edge1); + + position.z = dot(dir, Cotengant) * inv_det; + if (position.z < typename genType::value_type(0) || position.y + position.z > typename genType::value_type(1)) + return false; + + position.x = dot(edge2, Cotengant) * inv_det; + + return true; + } + + template + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadiusSquered, + typename genType::value_type & intersectionDistance + ) + { + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + genType diff = sphereCenter - rayStarting; + typename genType::value_type t0 = dot(diff, rayNormalizedDirection); + typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; + if( dSquared > sphereRadiusSquered ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadiusSquered - dSquared ); + intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1; + return intersectionDistance > Epsilon; + } + + template + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadius, + genType & intersectionPosition, genType & intersectionNormal + ) + { + typename genType::value_type distance; + if( intersectRaySphere( rayStarting, rayNormalizedDirection, sphereCenter, sphereRadius * sphereRadius, distance ) ) + { + intersectionPosition = rayStarting + rayNormalizedDirection * distance; + intersectionNormal = (intersectionPosition - sphereCenter) / sphereRadius; + return true; + } + return false; + } + + template + GLM_FUNC_QUALIFIER bool intersectLineSphere + ( + genType const& point0, genType const& point1, + genType const& sphereCenter, typename genType::value_type sphereRadius, + genType & intersectionPoint1, genType & intersectionNormal1, + genType & intersectionPoint2, genType & intersectionNormal2 + ) + { + typename genType::value_type Epsilon = std::numeric_limits::epsilon(); + genType dir = normalize(point1 - point0); + genType diff = sphereCenter - point0; + typename genType::value_type t0 = dot(diff, dir); + typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; + if( dSquared > sphereRadius * sphereRadius ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadius * sphereRadius - dSquared ); + if( t0 < t1 + Epsilon ) + t1 = -t1; + intersectionPoint1 = point0 + dir * (t0 - t1); + intersectionNormal1 = (intersectionPoint1 - sphereCenter) / sphereRadius; + intersectionPoint2 = point0 + dir * (t0 + t1); + intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius; + return true; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/io.hpp b/vendor/glm/glm/gtx/io.hpp new file mode 100644 index 0000000..8d974f0 --- /dev/null +++ b/vendor/glm/glm/gtx/io.hpp @@ -0,0 +1,201 @@ +/// @ref gtx_io +/// @file glm/gtx/io.hpp +/// @author Jan P Springer (regnirpsj@gmail.com) +/// +/// @see core (dependence) +/// @see gtc_matrix_access (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_io GLM_GTX_io +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// std::[w]ostream support for glm types +/// +/// std::[w]ostream support for glm types + qualifier/width/etc. manipulators +/// based on howard hinnant's std::chrono io proposal +/// [http://home.roadrunner.com/~hinnant/bloomington/chrono_io.html] + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/quaternion.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_io is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_io extension included") +# endif +#endif + +#include // std::basic_ostream<> (fwd) +#include // std::locale, std::locale::facet, std::locale::id +#include // std::pair<> + +namespace glm +{ + /// @addtogroup gtx_io + /// @{ + + namespace io + { + enum order_type { column_major, row_major}; + + template + class format_punct : public std::locale::facet + { + typedef CTy char_type; + + public: + + static std::locale::id id; + + bool formatted; + unsigned precision; + unsigned width; + char_type separator; + char_type delim_left; + char_type delim_right; + char_type space; + char_type newline; + order_type order; + + GLM_FUNC_DECL explicit format_punct(size_t a = 0); + GLM_FUNC_DECL explicit format_punct(format_punct const&); + }; + + template > + class basic_state_saver { + + public: + + GLM_FUNC_DECL explicit basic_state_saver(std::basic_ios&); + GLM_FUNC_DECL ~basic_state_saver(); + + private: + + typedef ::std::basic_ios state_type; + typedef typename state_type::char_type char_type; + typedef ::std::ios_base::fmtflags flags_type; + typedef ::std::streamsize streamsize_type; + typedef ::std::locale const locale_type; + + state_type& state_; + flags_type flags_; + streamsize_type precision_; + streamsize_type width_; + char_type fill_; + locale_type locale_; + + GLM_FUNC_DECL basic_state_saver& operator=(basic_state_saver const&); + }; + + typedef basic_state_saver state_saver; + typedef basic_state_saver wstate_saver; + + template > + class basic_format_saver + { + public: + + GLM_FUNC_DECL explicit basic_format_saver(std::basic_ios&); + GLM_FUNC_DECL ~basic_format_saver(); + + private: + + basic_state_saver const bss_; + + GLM_FUNC_DECL basic_format_saver& operator=(basic_format_saver const&); + }; + + typedef basic_format_saver format_saver; + typedef basic_format_saver wformat_saver; + + struct precision + { + unsigned value; + + GLM_FUNC_DECL explicit precision(unsigned); + }; + + struct width + { + unsigned value; + + GLM_FUNC_DECL explicit width(unsigned); + }; + + template + struct delimeter + { + CTy value[3]; + + GLM_FUNC_DECL explicit delimeter(CTy /* left */, CTy /* right */, CTy /* separator */ = ','); + }; + + struct order + { + order_type value; + + GLM_FUNC_DECL explicit order(order_type); + }; + + // functions, inlined (inline) + + template + FTy const& get_facet(std::basic_ios&); + template + std::basic_ios& formatted(std::basic_ios&); + template + std::basic_ios& unformattet(std::basic_ios&); + + template + std::basic_ostream& operator<<(std::basic_ostream&, precision const&); + template + std::basic_ostream& operator<<(std::basic_ostream&, width const&); + template + std::basic_ostream& operator<<(std::basic_ostream&, delimeter const&); + template + std::basic_ostream& operator<<(std::basic_ostream&, order const&); + }//namespace io + + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, qua const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<1, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<2, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<3, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<4, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 2, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 3, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 4, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 2, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 3, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 4, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 2, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 3, T, Q> const&); + template + GLM_FUNC_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 4, T, Q> const&); + + template + GLM_FUNC_DECL std::basic_ostream & operator<<(std::basic_ostream &, + std::pair const, mat<4, 4, T, Q> const> const&); + + /// @} +}//namespace glm + +#include "io.inl" diff --git a/vendor/glm/glm/gtx/io.inl b/vendor/glm/glm/gtx/io.inl new file mode 100644 index 0000000..a3a1bb6 --- /dev/null +++ b/vendor/glm/glm/gtx/io.inl @@ -0,0 +1,440 @@ +/// @ref gtx_io +/// @author Jan P Springer (regnirpsj@gmail.com) + +#include // std::fixed, std::setfill<>, std::setprecision, std::right, std::setw +#include // std::basic_ostream<> +#include "../gtc/matrix_access.hpp" // glm::col, glm::row +#include "../gtx/type_trait.hpp" // glm::type<> + +namespace glm{ +namespace io +{ + template + GLM_FUNC_QUALIFIER format_punct::format_punct(size_t a) + : std::locale::facet(a) + , formatted(true) + , precision(3) + , width(1 + 4 + 1 + precision) + , separator(',') + , delim_left('[') + , delim_right(']') + , space(' ') + , newline('\n') + , order(column_major) + {} + + template + GLM_FUNC_QUALIFIER format_punct::format_punct(format_punct const& a) + : std::locale::facet(0) + , formatted(a.formatted) + , precision(a.precision) + , width(a.width) + , separator(a.separator) + , delim_left(a.delim_left) + , delim_right(a.delim_right) + , space(a.space) + , newline(a.newline) + , order(a.order) + {} + + template std::locale::id format_punct::id; + + template + GLM_FUNC_QUALIFIER basic_state_saver::basic_state_saver(std::basic_ios& a) + : state_(a) + , flags_(a.flags()) + , precision_(a.precision()) + , width_(a.width()) + , fill_(a.fill()) + , locale_(a.getloc()) + {} + + template + GLM_FUNC_QUALIFIER basic_state_saver::~basic_state_saver() + { + state_.imbue(locale_); + state_.fill(fill_); + state_.width(width_); + state_.precision(precision_); + state_.flags(flags_); + } + + template + GLM_FUNC_QUALIFIER basic_format_saver::basic_format_saver(std::basic_ios& a) + : bss_(a) + { + a.imbue(std::locale(a.getloc(), new format_punct(get_facet >(a)))); + } + + template + GLM_FUNC_QUALIFIER + basic_format_saver::~basic_format_saver() + {} + + GLM_FUNC_QUALIFIER precision::precision(unsigned a) + : value(a) + {} + + GLM_FUNC_QUALIFIER width::width(unsigned a) + : value(a) + {} + + template + GLM_FUNC_QUALIFIER delimeter::delimeter(CTy a, CTy b, CTy c) + : value() + { + value[0] = a; + value[1] = b; + value[2] = c; + } + + GLM_FUNC_QUALIFIER order::order(order_type a) + : value(a) + {} + + template + GLM_FUNC_QUALIFIER FTy const& get_facet(std::basic_ios& ios) + { + if(!std::has_facet(ios.getloc())) + ios.imbue(std::locale(ios.getloc(), new FTy)); + + return std::use_facet(ios.getloc()); + } + + template + GLM_FUNC_QUALIFIER std::basic_ios& formatted(std::basic_ios& ios) + { + const_cast&>(get_facet >(ios)).formatted = true; + return ios; + } + + template + GLM_FUNC_QUALIFIER std::basic_ios& unformatted(std::basic_ios& ios) + { + const_cast&>(get_facet >(ios)).formatted = false; + return ios; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, precision const& a) + { + const_cast&>(get_facet >(os)).precision = a.value; + return os; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, width const& a) + { + const_cast&>(get_facet >(os)).width = a.value; + return os; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, delimeter const& a) + { + format_punct & fmt(const_cast&>(get_facet >(os))); + + fmt.delim_left = a.value[0]; + fmt.delim_right = a.value[1]; + fmt.separator = a.value[2]; + + return os; + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, order const& a) + { + const_cast&>(get_facet >(os)).order = a.value; + return os; + } +} // namespace io + +namespace detail +{ + template + GLM_FUNC_QUALIFIER std::basic_ostream& + print_vector_on(std::basic_ostream& os, V const& a) + { + typename std::basic_ostream::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct const& fmt(io::get_facet >(os)); + + length_t const& components(type::components); + + if(fmt.formatted) + { + io::basic_state_saver const bss(os); + + os << std::fixed << std::right << std::setprecision(fmt.precision) << std::setfill(fmt.space) << fmt.delim_left; + + for(length_t i(0); i < components; ++i) + { + os << std::setw(fmt.width) << a[i]; + if(components-1 != i) + os << fmt.separator; + } + + os << fmt.delim_right; + } + else + { + for(length_t i(0); i < components; ++i) + { + os << a[i]; + + if(components-1 != i) + os << fmt.space; + } + } + } + + return os; + } +}//namespace detail + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, qua const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<1, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<2, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<3, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, vec<4, T, Q> const& a) + { + return detail::print_vector_on(os, a); + } + +namespace detail +{ + template class M, length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream& print_matrix_on(std::basic_ostream& os, M const& a) + { + typename std::basic_ostream::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct const& fmt(io::get_facet >(os)); + + length_t const& cols(type >::cols); + length_t const& rows(type >::rows); + + if(fmt.formatted) + { + os << fmt.newline << fmt.delim_left; + + switch(fmt.order) + { + case io::column_major: + { + for(length_t i(0); i < rows; ++i) + { + if (0 != i) + os << fmt.space; + + os << row(a, i); + + if(rows-1 != i) + os << fmt.newline; + } + } + break; + + case io::row_major: + { + for(length_t i(0); i < cols; ++i) + { + if(0 != i) + os << fmt.space; + + os << column(a, i); + + if(cols-1 != i) + os << fmt.newline; + } + } + break; + } + + os << fmt.delim_right; + } + else + { + switch (fmt.order) + { + case io::column_major: + { + for(length_t i(0); i < cols; ++i) + { + os << column(a, i); + + if(cols - 1 != i) + os << fmt.space; + } + } + break; + + case io::row_major: + { + for (length_t i(0); i < rows; ++i) + { + os << row(a, i); + + if (rows-1 != i) + os << fmt.space; + } + } + break; + } + } + } + + return os; + } +}//namespace detail + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<2, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<2, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<2, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<3, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<(std::basic_ostream& os, mat<3, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<3, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<4, 2, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<4, 3, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + + template + GLM_FUNC_QUALIFIER std::basic_ostream & operator<<(std::basic_ostream& os, mat<4, 4, T, Q> const& a) + { + return detail::print_matrix_on(os, a); + } + +namespace detail +{ + template class M, length_t C, length_t R, typename T, qualifier Q> + GLM_FUNC_QUALIFIER std::basic_ostream& print_matrix_pair_on(std::basic_ostream& os, std::pair const, M const> const& a) + { + typename std::basic_ostream::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct const& fmt(io::get_facet >(os)); + M const& ml(a.first); + M const& mr(a.second); + length_t const& cols(type >::cols); + length_t const& rows(type >::rows); + + if(fmt.formatted) + { + os << fmt.newline << fmt.delim_left; + + switch(fmt.order) + { + case io::column_major: + { + for(length_t i(0); i < rows; ++i) + { + if(0 != i) + os << fmt.space; + + os << row(ml, i) << ((rows-1 != i) ? fmt.space : fmt.delim_right) << fmt.space << ((0 != i) ? fmt.space : fmt.delim_left) << row(mr, i); + + if(rows-1 != i) + os << fmt.newline; + } + } + break; + case io::row_major: + { + for(length_t i(0); i < cols; ++i) + { + if(0 != i) + os << fmt.space; + + os << column(ml, i) << ((cols-1 != i) ? fmt.space : fmt.delim_right) << fmt.space << ((0 != i) ? fmt.space : fmt.delim_left) << column(mr, i); + + if(cols-1 != i) + os << fmt.newline; + } + } + break; + } + + os << fmt.delim_right; + } + else + { + os << ml << fmt.space << mr; + } + } + + return os; + } +}//namespace detail + + template + GLM_FUNC_QUALIFIER std::basic_ostream& operator<<( + std::basic_ostream & os, + std::pair const, + mat<4, 4, T, Q> const> const& a) + { + return detail::print_matrix_pair_on(os, a); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/log_base.hpp b/vendor/glm/glm/gtx/log_base.hpp new file mode 100644 index 0000000..ba28c9d --- /dev/null +++ b/vendor/glm/glm/gtx/log_base.hpp @@ -0,0 +1,48 @@ +/// @ref gtx_log_base +/// @file glm/gtx/log_base.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_log_base GLM_GTX_log_base +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Logarithm for any base. base can be a vector or a scalar. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_log_base is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_log_base extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_log_base + /// @{ + + /// Logarithm for any base. + /// From GLM_GTX_log_base. + template + GLM_FUNC_DECL genType log( + genType const& x, + genType const& base); + + /// Logarithm for any base. + /// From GLM_GTX_log_base. + template + GLM_FUNC_DECL vec sign( + vec const& x, + vec const& base); + + /// @} +}//namespace glm + +#include "log_base.inl" diff --git a/vendor/glm/glm/gtx/log_base.inl b/vendor/glm/glm/gtx/log_base.inl new file mode 100644 index 0000000..4bbb8e8 --- /dev/null +++ b/vendor/glm/glm/gtx/log_base.inl @@ -0,0 +1,16 @@ +/// @ref gtx_log_base + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType log(genType const& x, genType const& base) + { + return glm::log(x) / glm::log(base); + } + + template + GLM_FUNC_QUALIFIER vec log(vec const& x, vec const& base) + { + return glm::log(x) / glm::log(base); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/matrix_cross_product.hpp b/vendor/glm/glm/gtx/matrix_cross_product.hpp new file mode 100644 index 0000000..1e585f9 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_cross_product.hpp @@ -0,0 +1,47 @@ +/// @ref gtx_matrix_cross_product +/// @file glm/gtx/matrix_cross_product.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_matrix_cross_product GLM_GTX_matrix_cross_product +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build cross product matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_cross_product is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_cross_product extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_cross_product + /// @{ + + //! Build a cross product matrix. + //! From GLM_GTX_matrix_cross_product extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> matrixCross3( + vec<3, T, Q> const& x); + + //! Build a cross product matrix. + //! From GLM_GTX_matrix_cross_product extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> matrixCross4( + vec<3, T, Q> const& x); + + /// @} +}//namespace glm + +#include "matrix_cross_product.inl" diff --git a/vendor/glm/glm/gtx/matrix_cross_product.inl b/vendor/glm/glm/gtx/matrix_cross_product.inl new file mode 100644 index 0000000..3a15397 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_cross_product.inl @@ -0,0 +1,37 @@ +/// @ref gtx_matrix_cross_product + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> matrixCross3 + ( + vec<3, T, Q> const& x + ) + { + mat<3, 3, T, Q> Result(T(0)); + Result[0][1] = x.z; + Result[1][0] = -x.z; + Result[0][2] = -x.y; + Result[2][0] = x.y; + Result[1][2] = x.x; + Result[2][1] = -x.x; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> matrixCross4 + ( + vec<3, T, Q> const& x + ) + { + mat<4, 4, T, Q> Result(T(0)); + Result[0][1] = x.z; + Result[1][0] = -x.z; + Result[0][2] = -x.y; + Result[2][0] = x.y; + Result[1][2] = x.x; + Result[2][1] = -x.x; + return Result; + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/matrix_decompose.hpp b/vendor/glm/glm/gtx/matrix_decompose.hpp new file mode 100644 index 0000000..acd7a7f --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_decompose.hpp @@ -0,0 +1,46 @@ +/// @ref gtx_matrix_decompose +/// @file glm/gtx/matrix_decompose.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_decompose GLM_GTX_matrix_decompose +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Decomposes a model matrix to translations, rotation and scale components + +#pragma once + +// Dependencies +#include "../mat4x4.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../geometric.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtc/matrix_transform.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_decompose is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_decompose extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_decompose + /// @{ + + /// Decomposes a model matrix to translations, rotation and scale components + /// @see gtx_matrix_decompose + template + GLM_FUNC_DECL bool decompose( + mat<4, 4, T, Q> const& modelMatrix, + vec<3, T, Q> & scale, qua & orientation, vec<3, T, Q> & translation, vec<3, T, Q> & skew, vec<4, T, Q> & perspective); + + /// @} +}//namespace glm + +#include "matrix_decompose.inl" diff --git a/vendor/glm/glm/gtx/matrix_decompose.inl b/vendor/glm/glm/gtx/matrix_decompose.inl new file mode 100644 index 0000000..694f5ec --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_decompose.inl @@ -0,0 +1,186 @@ +/// @ref gtx_matrix_decompose + +#include "../gtc/constants.hpp" +#include "../gtc/epsilon.hpp" + +namespace glm{ +namespace detail +{ + /// Make a linear combination of two vectors and return the result. + // result = (a * ascl) + (b * bscl) + template + GLM_FUNC_QUALIFIER vec<3, T, Q> combine( + vec<3, T, Q> const& a, + vec<3, T, Q> const& b, + T ascl, T bscl) + { + return (a * ascl) + (b * bscl); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> scale(vec<3, T, Q> const& v, T desiredLength) + { + return v * desiredLength / length(v); + } +}//namespace detail + + // Matrix decompose + // http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp + // Decomposes the mode matrix to translations,rotation scale components + + template + GLM_FUNC_QUALIFIER bool decompose(mat<4, 4, T, Q> const& ModelMatrix, vec<3, T, Q> & Scale, qua & Orientation, vec<3, T, Q> & Translation, vec<3, T, Q> & Skew, vec<4, T, Q> & Perspective) + { + mat<4, 4, T, Q> LocalMatrix(ModelMatrix); + + // Normalize the matrix. + if(epsilonEqual(LocalMatrix[3][3], static_cast(0), epsilon())) + return false; + + for(length_t i = 0; i < 4; ++i) + for(length_t j = 0; j < 4; ++j) + LocalMatrix[i][j] /= LocalMatrix[3][3]; + + // perspectiveMatrix is used to solve for perspective, but it also provides + // an easy way to test for singularity of the upper 3x3 component. + mat<4, 4, T, Q> PerspectiveMatrix(LocalMatrix); + + for(length_t i = 0; i < 3; i++) + PerspectiveMatrix[i][3] = static_cast(0); + PerspectiveMatrix[3][3] = static_cast(1); + + /// TODO: Fixme! + if(epsilonEqual(determinant(PerspectiveMatrix), static_cast(0), epsilon())) + return false; + + // First, isolate perspective. This is the messiest. + if( + epsilonNotEqual(LocalMatrix[0][3], static_cast(0), epsilon()) || + epsilonNotEqual(LocalMatrix[1][3], static_cast(0), epsilon()) || + epsilonNotEqual(LocalMatrix[2][3], static_cast(0), epsilon())) + { + // rightHandSide is the right hand side of the equation. + vec<4, T, Q> RightHandSide; + RightHandSide[0] = LocalMatrix[0][3]; + RightHandSide[1] = LocalMatrix[1][3]; + RightHandSide[2] = LocalMatrix[2][3]; + RightHandSide[3] = LocalMatrix[3][3]; + + // Solve the equation by inverting PerspectiveMatrix and multiplying + // rightHandSide by the inverse. (This is the easiest way, not + // necessarily the best.) + mat<4, 4, T, Q> InversePerspectiveMatrix = glm::inverse(PerspectiveMatrix);// inverse(PerspectiveMatrix, inversePerspectiveMatrix); + mat<4, 4, T, Q> TransposedInversePerspectiveMatrix = glm::transpose(InversePerspectiveMatrix);// transposeMatrix4(inversePerspectiveMatrix, transposedInversePerspectiveMatrix); + + Perspective = TransposedInversePerspectiveMatrix * RightHandSide; + // v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint); + + // Clear the perspective partition + LocalMatrix[0][3] = LocalMatrix[1][3] = LocalMatrix[2][3] = static_cast(0); + LocalMatrix[3][3] = static_cast(1); + } + else + { + // No perspective. + Perspective = vec<4, T, Q>(0, 0, 0, 1); + } + + // Next take care of translation (easy). + Translation = vec<3, T, Q>(LocalMatrix[3]); + LocalMatrix[3] = vec<4, T, Q>(0, 0, 0, LocalMatrix[3].w); + + vec<3, T, Q> Row[3], Pdum3; + + // Now get scale and shear. + for(length_t i = 0; i < 3; ++i) + for(length_t j = 0; j < 3; ++j) + Row[i][j] = LocalMatrix[i][j]; + + // Compute X scale factor and normalize first row. + Scale.x = length(Row[0]);// v3Length(Row[0]); + + Row[0] = detail::scale(Row[0], static_cast(1)); + + // Compute XY shear factor and make 2nd row orthogonal to 1st. + Skew.z = dot(Row[0], Row[1]); + Row[1] = detail::combine(Row[1], Row[0], static_cast(1), -Skew.z); + + // Now, compute Y scale and normalize 2nd row. + Scale.y = length(Row[1]); + Row[1] = detail::scale(Row[1], static_cast(1)); + Skew.z /= Scale.y; + + // Compute XZ and YZ shears, orthogonalize 3rd row. + Skew.y = glm::dot(Row[0], Row[2]); + Row[2] = detail::combine(Row[2], Row[0], static_cast(1), -Skew.y); + Skew.x = glm::dot(Row[1], Row[2]); + Row[2] = detail::combine(Row[2], Row[1], static_cast(1), -Skew.x); + + // Next, get Z scale and normalize 3rd row. + Scale.z = length(Row[2]); + Row[2] = detail::scale(Row[2], static_cast(1)); + Skew.y /= Scale.z; + Skew.x /= Scale.z; + + // At this point, the matrix (in rows[]) is orthonormal. + // Check for a coordinate system flip. If the determinant + // is -1, then negate the matrix and the scaling factors. + Pdum3 = cross(Row[1], Row[2]); // v3Cross(row[1], row[2], Pdum3); + if(dot(Row[0], Pdum3) < 0) + { + for(length_t i = 0; i < 3; i++) + { + Scale[i] *= static_cast(-1); + Row[i] *= static_cast(-1); + } + } + + // Now, get the rotations out, as described in the gem. + + // FIXME - Add the ability to return either quaternions (which are + // easier to recompose with) or Euler angles (rx, ry, rz), which + // are easier for authors to deal with. The latter will only be useful + // when we fix https://bugs.webkit.org/show_bug.cgi?id=23799, so I + // will leave the Euler angle code here for now. + + // ret.rotateY = asin(-Row[0][2]); + // if (cos(ret.rotateY) != 0) { + // ret.rotateX = atan2(Row[1][2], Row[2][2]); + // ret.rotateZ = atan2(Row[0][1], Row[0][0]); + // } else { + // ret.rotateX = atan2(-Row[2][0], Row[1][1]); + // ret.rotateZ = 0; + // } + + int i, j, k = 0; + T root, trace = Row[0].x + Row[1].y + Row[2].z; + if(trace > static_cast(0)) + { + root = sqrt(trace + static_cast(1.0)); + Orientation.w = static_cast(0.5) * root; + root = static_cast(0.5) / root; + Orientation.x = root * (Row[1].z - Row[2].y); + Orientation.y = root * (Row[2].x - Row[0].z); + Orientation.z = root * (Row[0].y - Row[1].x); + } // End if > 0 + else + { + static int Next[3] = {1, 2, 0}; + i = 0; + if(Row[1].y > Row[0].x) i = 1; + if(Row[2].z > Row[i][i]) i = 2; + j = Next[i]; + k = Next[j]; + + root = sqrt(Row[i][i] - Row[j][j] - Row[k][k] + static_cast(1.0)); + + Orientation[i] = static_cast(0.5) * root; + root = static_cast(0.5) / root; + Orientation[j] = root * (Row[i][j] + Row[j][i]); + Orientation[k] = root * (Row[i][k] + Row[k][i]); + Orientation.w = root * (Row[j][k] - Row[k][j]); + } // End if <= 0 + + return true; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/matrix_factorisation.hpp b/vendor/glm/glm/gtx/matrix_factorisation.hpp new file mode 100644 index 0000000..5a975d6 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_factorisation.hpp @@ -0,0 +1,69 @@ +/// @ref gtx_matrix_factorisation +/// @file glm/gtx/matrix_factorisation.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_factorisation GLM_GTX_matrix_factorisation +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Functions to factor matrices in various forms + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_factorisation is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_factorisation extension included") +# endif +#endif + +/* +Suggestions: + - Move helper functions flipud and fliplr to another file: They may be helpful in more general circumstances. + - Implement other types of matrix factorisation, such as: QL and LQ, L(D)U, eigendecompositions, etc... +*/ + +namespace glm +{ + /// @addtogroup gtx_matrix_factorisation + /// @{ + + /// Flips the matrix rows up and down. + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DECL mat flipud(mat const& in); + + /// Flips the matrix columns right and left. + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DECL mat fliplr(mat const& in); + + /// Performs QR factorisation of a matrix. + /// Returns 2 matrices, q and r, such that the columns of q are orthonormal and span the same subspace than those of the input matrix, r is an upper triangular matrix, and q*r=in. + /// Given an n-by-m input matrix, q has dimensions min(n,m)-by-m, and r has dimensions n-by-min(n,m). + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DECL void qr_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& q, mat& r); + + /// Performs RQ factorisation of a matrix. + /// Returns 2 matrices, r and q, such that r is an upper triangular matrix, the rows of q are orthonormal and span the same subspace than those of the input matrix, and r*q=in. + /// Note that in the context of RQ factorisation, the diagonal is seen as starting in the lower-right corner of the matrix, instead of the usual upper-left. + /// Given an n-by-m input matrix, r has dimensions min(n,m)-by-m, and q has dimensions n-by-min(n,m). + /// + /// From GLM_GTX_matrix_factorisation extension. + template + GLM_FUNC_DECL void rq_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& r, mat& q); + + /// @} +} + +#include "matrix_factorisation.inl" diff --git a/vendor/glm/glm/gtx/matrix_factorisation.inl b/vendor/glm/glm/gtx/matrix_factorisation.inl new file mode 100644 index 0000000..c479b8a --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_factorisation.inl @@ -0,0 +1,84 @@ +/// @ref gtx_matrix_factorisation + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat flipud(mat const& in) + { + mat tin = transpose(in); + tin = fliplr(tin); + mat out = transpose(tin); + + return out; + } + + template + GLM_FUNC_QUALIFIER mat fliplr(mat const& in) + { + mat out; + for (length_t i = 0; i < C; i++) + { + out[i] = in[(C - i) - 1]; + } + + return out; + } + + template + GLM_FUNC_QUALIFIER void qr_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& q, mat& r) + { + // Uses modified Gram-Schmidt method + // Source: https://en.wikipedia.org/wiki/Gram–Schmidt_process + // And https://en.wikipedia.org/wiki/QR_decomposition + + //For all the linearly independs columns of the input... + // (there can be no more linearly independents columns than there are rows.) + for (length_t i = 0; i < (C < R ? C : R); i++) + { + //Copy in Q the input's i-th column. + q[i] = in[i]; + + //j = [0,i[ + // Make that column orthogonal to all the previous ones by substracting to it the non-orthogonal projection of all the previous columns. + // Also: Fill the zero elements of R + for (length_t j = 0; j < i; j++) + { + q[i] -= dot(q[i], q[j])*q[j]; + r[j][i] = 0; + } + + //Now, Q i-th column is orthogonal to all the previous columns. Normalize it. + q[i] = normalize(q[i]); + + //j = [i,C[ + //Finally, compute the corresponding coefficients of R by computing the projection of the resulting column on the other columns of the input. + for (length_t j = i; j < C; j++) + { + r[j][i] = dot(in[j], q[i]); + } + } + } + + template + GLM_FUNC_QUALIFIER void rq_decompose(mat const& in, mat<(C < R ? C : R), R, T, Q>& r, mat& q) + { + // From https://en.wikipedia.org/wiki/QR_decomposition: + // The RQ decomposition transforms a matrix A into the product of an upper triangular matrix R (also known as right-triangular) and an orthogonal matrix Q. The only difference from QR decomposition is the order of these matrices. + // QR decomposition is Gram–Schmidt orthogonalization of columns of A, started from the first column. + // RQ decomposition is Gram–Schmidt orthogonalization of rows of A, started from the last row. + + mat tin = transpose(in); + tin = fliplr(tin); + + mat tr; + mat<(C < R ? C : R), C, T, Q> tq; + qr_decompose(tin, tq, tr); + + tr = fliplr(tr); + r = transpose(tr); + r = fliplr(r); + + tq = fliplr(tq); + q = transpose(tq); + } +} //namespace glm diff --git a/vendor/glm/glm/gtx/matrix_interpolation.hpp b/vendor/glm/glm/gtx/matrix_interpolation.hpp new file mode 100644 index 0000000..7d5ad4c --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_interpolation.hpp @@ -0,0 +1,60 @@ +/// @ref gtx_matrix_interpolation +/// @file glm/gtx/matrix_interpolation.hpp +/// @author Ghenadii Ursachi (the.asteroth@gmail.com) +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_interpolation GLM_GTX_matrix_interpolation +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Allows to directly interpolate two matrices. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_interpolation is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_interpolation extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_interpolation + /// @{ + + /// Get the axis and angle of the rotation from a matrix. + /// From GLM_GTX_matrix_interpolation extension. + template + GLM_FUNC_DECL void axisAngle( + mat<4, 4, T, Q> const& Mat, vec<3, T, Q> & Axis, T & Angle); + + /// Build a matrix from axis and angle. + /// From GLM_GTX_matrix_interpolation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> axisAngleMatrix( + vec<3, T, Q> const& Axis, T const Angle); + + /// Extracts the rotation part of a matrix. + /// From GLM_GTX_matrix_interpolation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> extractMatrixRotation( + mat<4, 4, T, Q> const& Mat); + + /// Build a interpolation of 4 * 4 matrixes. + /// From GLM_GTX_matrix_interpolation extension. + /// Warning! works only with rotation and/or translation matrixes, scale will generate unexpected results. + template + GLM_FUNC_DECL mat<4, 4, T, Q> interpolate( + mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2, T const Delta); + + /// @} +}//namespace glm + +#include "matrix_interpolation.inl" diff --git a/vendor/glm/glm/gtx/matrix_interpolation.inl b/vendor/glm/glm/gtx/matrix_interpolation.inl new file mode 100644 index 0000000..de40b7d --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_interpolation.inl @@ -0,0 +1,129 @@ +/// @ref gtx_matrix_interpolation + +#include "../gtc/constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER void axisAngle(mat<4, 4, T, Q> const& m, vec<3, T, Q> & axis, T& angle) + { + T epsilon = static_cast(0.01); + T epsilon2 = static_cast(0.1); + + if((abs(m[1][0] - m[0][1]) < epsilon) && (abs(m[2][0] - m[0][2]) < epsilon) && (abs(m[2][1] - m[1][2]) < epsilon)) + { + if ((abs(m[1][0] + m[0][1]) < epsilon2) && (abs(m[2][0] + m[0][2]) < epsilon2) && (abs(m[2][1] + m[1][2]) < epsilon2) && (abs(m[0][0] + m[1][1] + m[2][2] - static_cast(3.0)) < epsilon2)) + { + angle = static_cast(0.0); + axis.x = static_cast(1.0); + axis.y = static_cast(0.0); + axis.z = static_cast(0.0); + return; + } + angle = static_cast(3.1415926535897932384626433832795); + T xx = (m[0][0] + static_cast(1.0)) * static_cast(0.5); + T yy = (m[1][1] + static_cast(1.0)) * static_cast(0.5); + T zz = (m[2][2] + static_cast(1.0)) * static_cast(0.5); + T xy = (m[1][0] + m[0][1]) * static_cast(0.25); + T xz = (m[2][0] + m[0][2]) * static_cast(0.25); + T yz = (m[2][1] + m[1][2]) * static_cast(0.25); + if((xx > yy) && (xx > zz)) + { + if(xx < epsilon) + { + axis.x = static_cast(0.0); + axis.y = static_cast(0.7071); + axis.z = static_cast(0.7071); + } + else + { + axis.x = sqrt(xx); + axis.y = xy / axis.x; + axis.z = xz / axis.x; + } + } + else if (yy > zz) + { + if(yy < epsilon) + { + axis.x = static_cast(0.7071); + axis.y = static_cast(0.0); + axis.z = static_cast(0.7071); + } + else + { + axis.y = sqrt(yy); + axis.x = xy / axis.y; + axis.z = yz / axis.y; + } + } + else + { + if (zz < epsilon) + { + axis.x = static_cast(0.7071); + axis.y = static_cast(0.7071); + axis.z = static_cast(0.0); + } + else + { + axis.z = sqrt(zz); + axis.x = xz / axis.z; + axis.y = yz / axis.z; + } + } + return; + } + T s = sqrt((m[2][1] - m[1][2]) * (m[2][1] - m[1][2]) + (m[2][0] - m[0][2]) * (m[2][0] - m[0][2]) + (m[1][0] - m[0][1]) * (m[1][0] - m[0][1])); + if (glm::abs(s) < T(0.001)) + s = static_cast(1); + T const angleCos = (m[0][0] + m[1][1] + m[2][2] - static_cast(1)) * static_cast(0.5); + if(angleCos - static_cast(1) < epsilon) + angle = pi() * static_cast(0.25); + else + angle = acos(angleCos); + axis.x = (m[1][2] - m[2][1]) / s; + axis.y = (m[2][0] - m[0][2]) / s; + axis.z = (m[0][1] - m[1][0]) / s; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> axisAngleMatrix(vec<3, T, Q> const& axis, T const angle) + { + T c = cos(angle); + T s = sin(angle); + T t = static_cast(1) - c; + vec<3, T, Q> n = normalize(axis); + + return mat<4, 4, T, Q>( + t * n.x * n.x + c, t * n.x * n.y + n.z * s, t * n.x * n.z - n.y * s, static_cast(0.0), + t * n.x * n.y - n.z * s, t * n.y * n.y + c, t * n.y * n.z + n.x * s, static_cast(0.0), + t * n.x * n.z + n.y * s, t * n.y * n.z - n.x * s, t * n.z * n.z + c, static_cast(0.0), + static_cast(0.0), static_cast(0.0), static_cast(0.0), static_cast(1.0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> extractMatrixRotation(mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0][0], m[0][1], m[0][2], static_cast(0.0), + m[1][0], m[1][1], m[1][2], static_cast(0.0), + m[2][0], m[2][1], m[2][2], static_cast(0.0), + static_cast(0.0), static_cast(0.0), static_cast(0.0), static_cast(1.0)); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> interpolate(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2, T const delta) + { + mat<4, 4, T, Q> m1rot = extractMatrixRotation(m1); + mat<4, 4, T, Q> dltRotation = m2 * transpose(m1rot); + vec<3, T, Q> dltAxis; + T dltAngle; + axisAngle(dltRotation, dltAxis, dltAngle); + mat<4, 4, T, Q> out = axisAngleMatrix(dltAxis, dltAngle * delta) * m1rot; + out[3][0] = m1[3][0] + delta * (m2[3][0] - m1[3][0]); + out[3][1] = m1[3][1] + delta * (m2[3][1] - m1[3][1]); + out[3][2] = m1[3][2] + delta * (m2[3][2] - m1[3][2]); + return out; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/matrix_major_storage.hpp b/vendor/glm/glm/gtx/matrix_major_storage.hpp new file mode 100644 index 0000000..8c6bc22 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_major_storage.hpp @@ -0,0 +1,119 @@ +/// @ref gtx_matrix_major_storage +/// @file glm/gtx/matrix_major_storage.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_matrix_major_storage GLM_GTX_matrix_major_storage +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build matrices with specific matrix order, row or column + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_major_storage is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_major_storage extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_major_storage + /// @{ + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> rowMajor2( + vec<2, T, Q> const& v1, + vec<2, T, Q> const& v2); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> rowMajor2( + mat<2, 2, T, Q> const& m); + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> rowMajor3( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> rowMajor3( + mat<3, 3, T, Q> const& m); + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> rowMajor4( + vec<4, T, Q> const& v1, + vec<4, T, Q> const& v2, + vec<4, T, Q> const& v3, + vec<4, T, Q> const& v4); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> rowMajor4( + mat<4, 4, T, Q> const& m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> colMajor2( + vec<2, T, Q> const& v1, + vec<2, T, Q> const& v2); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> colMajor2( + mat<2, 2, T, Q> const& m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> colMajor3( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> colMajor3( + mat<3, 3, T, Q> const& m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> colMajor4( + vec<4, T, Q> const& v1, + vec<4, T, Q> const& v2, + vec<4, T, Q> const& v3, + vec<4, T, Q> const& v4); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> colMajor4( + mat<4, 4, T, Q> const& m); + + /// @} +}//namespace glm + +#include "matrix_major_storage.inl" diff --git a/vendor/glm/glm/gtx/matrix_major_storage.inl b/vendor/glm/glm/gtx/matrix_major_storage.inl new file mode 100644 index 0000000..279dd34 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_major_storage.inl @@ -0,0 +1,166 @@ +/// @ref gtx_matrix_major_storage + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> rowMajor2 + ( + vec<2, T, Q> const& v1, + vec<2, T, Q> const& v2 + ) + { + mat<2, 2, T, Q> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> rowMajor2( + const mat<2, 2, T, Q>& m) + { + mat<2, 2, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rowMajor3( + const vec<3, T, Q>& v1, + const vec<3, T, Q>& v2, + const vec<3, T, Q>& v3) + { + mat<3, 3, T, Q> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[2][0] = v1.z; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + Result[2][1] = v2.z; + Result[0][2] = v3.x; + Result[1][2] = v3.y; + Result[2][2] = v3.z; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rowMajor3( + const mat<3, 3, T, Q>& m) + { + mat<3, 3, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rowMajor4( + const vec<4, T, Q>& v1, + const vec<4, T, Q>& v2, + const vec<4, T, Q>& v3, + const vec<4, T, Q>& v4) + { + mat<4, 4, T, Q> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[2][0] = v1.z; + Result[3][0] = v1.w; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + Result[2][1] = v2.z; + Result[3][1] = v2.w; + Result[0][2] = v3.x; + Result[1][2] = v3.y; + Result[2][2] = v3.z; + Result[3][2] = v3.w; + Result[0][3] = v4.x; + Result[1][3] = v4.y; + Result[2][3] = v4.z; + Result[3][3] = v4.w; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rowMajor4( + const mat<4, 4, T, Q>& m) + { + mat<4, 4, T, Q> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[2][3] = m[3][2]; + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + Result[3][2] = m[2][3]; + Result[3][3] = m[3][3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> colMajor2( + const vec<2, T, Q>& v1, + const vec<2, T, Q>& v2) + { + return mat<2, 2, T, Q>(v1, v2); + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> colMajor2( + const mat<2, 2, T, Q>& m) + { + return mat<2, 2, T, Q>(m); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> colMajor3( + const vec<3, T, Q>& v1, + const vec<3, T, Q>& v2, + const vec<3, T, Q>& v3) + { + return mat<3, 3, T, Q>(v1, v2, v3); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> colMajor3( + const mat<3, 3, T, Q>& m) + { + return mat<3, 3, T, Q>(m); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> colMajor4( + const vec<4, T, Q>& v1, + const vec<4, T, Q>& v2, + const vec<4, T, Q>& v3, + const vec<4, T, Q>& v4) + { + return mat<4, 4, T, Q>(v1, v2, v3, v4); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> colMajor4( + const mat<4, 4, T, Q>& m) + { + return mat<4, 4, T, Q>(m); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/matrix_operation.hpp b/vendor/glm/glm/gtx/matrix_operation.hpp new file mode 100644 index 0000000..de6ff1f --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_operation.hpp @@ -0,0 +1,103 @@ +/// @ref gtx_matrix_operation +/// @file glm/gtx/matrix_operation.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_operation GLM_GTX_matrix_operation +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Build diagonal matrices from vectors. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_operation is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_operation extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_operation + /// @{ + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> diagonal2x2( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 3, T, Q> diagonal2x3( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 4, T, Q> diagonal2x4( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 2, T, Q> diagonal3x2( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> diagonal3x3( + vec<3, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 4, T, Q> diagonal3x4( + vec<3, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 2, T, Q> diagonal4x2( + vec<2, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 3, T, Q> diagonal4x3( + vec<3, T, Q> const& v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> diagonal4x4( + vec<4, T, Q> const& v); + + /// Build an adjugate matrix. + /// From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<2, 2, T, Q> adjugate(mat<2, 2, T, Q> const& m); + + /// Build an adjugate matrix. + /// From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> adjugate(mat<3, 3, T, Q> const& m); + + /// Build an adjugate matrix. + /// From GLM_GTX_matrix_operation extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> adjugate(mat<4, 4, T, Q> const& m); + + /// @} +}//namespace glm + +#include "matrix_operation.inl" diff --git a/vendor/glm/glm/gtx/matrix_operation.inl b/vendor/glm/glm/gtx/matrix_operation.inl new file mode 100644 index 0000000..9de83f8 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_operation.inl @@ -0,0 +1,176 @@ +/// @ref gtx_matrix_operation + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> diagonal2x2 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 2, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 3, T, Q> diagonal2x3 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 3, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 4, T, Q> diagonal2x4 + ( + vec<2, T, Q> const& v + ) + { + mat<2, 4, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 2, T, Q> diagonal3x2 + ( + vec<2, T, Q> const& v + ) + { + mat<3, 2, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> diagonal3x3 + ( + vec<3, T, Q> const& v + ) + { + mat<3, 3, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 4, T, Q> diagonal3x4 + ( + vec<3, T, Q> const& v + ) + { + mat<3, 4, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> diagonal4x4 + ( + vec<4, T, Q> const& v + ) + { + mat<4, 4, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + Result[3][3] = v[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 3, T, Q> diagonal4x3 + ( + vec<3, T, Q> const& v + ) + { + mat<4, 3, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 2, T, Q> diagonal4x2 + ( + vec<2, T, Q> const& v + ) + { + mat<4, 2, T, Q> Result(static_cast(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<2, 2, T, Q> adjugate(mat<2, 2, T, Q> const& m) + { + return mat<2, 2, T, Q>( + +m[1][1], -m[1][0], + -m[0][1], +m[0][0]); + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> adjugate(mat<3, 3, T, Q> const& m) + { + T const m00 = determinant(mat<2, 2, T, Q>(m[1][1], m[2][1], m[1][2], m[2][2])); + T const m01 = determinant(mat<2, 2, T, Q>(m[0][1], m[2][1], m[0][2], m[2][2])); + T const m02 = determinant(mat<2, 2, T, Q>(m[0][1], m[1][1], m[0][2], m[1][2])); + + T const m10 = determinant(mat<2, 2, T, Q>(m[1][0], m[2][0], m[1][2], m[2][2])); + T const m11 = determinant(mat<2, 2, T, Q>(m[0][0], m[2][0], m[0][2], m[2][2])); + T const m12 = determinant(mat<2, 2, T, Q>(m[0][0], m[1][0], m[0][2], m[1][2])); + + T const m20 = determinant(mat<2, 2, T, Q>(m[1][0], m[2][0], m[1][1], m[2][1])); + T const m21 = determinant(mat<2, 2, T, Q>(m[0][0], m[2][0], m[0][1], m[2][1])); + T const m22 = determinant(mat<2, 2, T, Q>(m[0][0], m[1][0], m[0][1], m[1][1])); + + return mat<3, 3, T, Q>( + +m00, -m01, +m02, + -m10, +m11, -m12, + +m20, -m21, +m22); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> adjugate(mat<4, 4, T, Q> const& m) + { + T const m00 = determinant(mat<3, 3, T, Q>(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3])); + T const m01 = determinant(mat<3, 3, T, Q>(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3])); + T const m02 = determinant(mat<3, 3, T, Q>(m[1][0], m[1][1], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][1], m[3][3])); + T const m03 = determinant(mat<3, 3, T, Q>(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2])); + + T const m10 = determinant(mat<3, 3, T, Q>(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3])); + T const m11 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3])); + T const m12 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3])); + T const m13 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2])); + + T const m20 = determinant(mat<3, 3, T, Q>(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3])); + T const m21 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3])); + T const m22 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3])); + T const m23 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2])); + + T const m30 = determinant(mat<3, 3, T, Q>(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3])); + T const m31 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3])); + T const m32 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3])); + T const m33 = determinant(mat<3, 3, T, Q>(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2])); + + return mat<4, 4, T, Q>( + +m00, -m01, +m02, -m03, + -m10, +m11, -m12, +m13, + +m20, -m21, +m22, -m23, + -m30, +m31, -m32, +m33); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/matrix_query.hpp b/vendor/glm/glm/gtx/matrix_query.hpp new file mode 100644 index 0000000..8011b2b --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_query.hpp @@ -0,0 +1,77 @@ +/// @ref gtx_matrix_query +/// @file glm/gtx/matrix_query.hpp +/// +/// @see core (dependence) +/// @see gtx_vector_query (dependence) +/// +/// @defgroup gtx_matrix_query GLM_GTX_matrix_query +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Query to evaluate matrix properties + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/vector_query.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_query is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_query extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_query + /// @{ + + /// Return whether a matrix a null matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNull(mat<2, 2, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix a null matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNull(mat<3, 3, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is a null matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNull(mat<4, 4, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is an identity matrix. + /// From GLM_GTX_matrix_query extension. + template class matType> + GLM_FUNC_DECL bool isIdentity(matType const& m, T const& epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNormalized(mat<2, 2, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNormalized(mat<3, 3, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template + GLM_FUNC_DECL bool isNormalized(mat<4, 4, T, Q> const& m, T const& epsilon); + + /// Return whether a matrix is an orthonormalized matrix. + /// From GLM_GTX_matrix_query extension. + template class matType> + GLM_FUNC_DECL bool isOrthogonal(matType const& m, T const& epsilon); + + /// @} +}//namespace glm + +#include "matrix_query.inl" diff --git a/vendor/glm/glm/gtx/matrix_query.inl b/vendor/glm/glm/gtx/matrix_query.inl new file mode 100644 index 0000000..77bd231 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_query.inl @@ -0,0 +1,113 @@ +/// @ref gtx_matrix_query + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool isNull(mat<2, 2, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m.length() ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNull(mat<3, 3, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m.length() ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNull(mat<4, 4, T, Q> const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m.length() ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template + GLM_FUNC_QUALIFIER bool isIdentity(mat const& m, T const& epsilon) + { + bool result = true; + for(length_t i = 0; result && i < m[0].length() ; ++i) + { + for(length_t j = 0; result && j < i ; ++j) + result = abs(m[i][j]) <= epsilon; + if(result) + result = abs(m[i][i] - 1) <= epsilon; + for(length_t j = i + 1; result && j < m.length(); ++j) + result = abs(m[i][j]) <= epsilon; + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(mat<2, 2, T, Q> const& m, T const& epsilon) + { + bool result(true); + for(length_t i = 0; result && i < m.length(); ++i) + result = isNormalized(m[i], epsilon); + for(length_t i = 0; result && i < m.length(); ++i) + { + typename mat<2, 2, T, Q>::col_type v; + for(length_t j = 0; j < m.length(); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(mat<3, 3, T, Q> const& m, T const& epsilon) + { + bool result(true); + for(length_t i = 0; result && i < m.length(); ++i) + result = isNormalized(m[i], epsilon); + for(length_t i = 0; result && i < m.length(); ++i) + { + typename mat<3, 3, T, Q>::col_type v; + for(length_t j = 0; j < m.length(); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(mat<4, 4, T, Q> const& m, T const& epsilon) + { + bool result(true); + for(length_t i = 0; result && i < m.length(); ++i) + result = isNormalized(m[i], epsilon); + for(length_t i = 0; result && i < m.length(); ++i) + { + typename mat<4, 4, T, Q>::col_type v; + for(length_t j = 0; j < m.length(); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template + GLM_FUNC_QUALIFIER bool isOrthogonal(mat const& m, T const& epsilon) + { + bool result = true; + for(length_t i(0); result && i < m.length() - 1; ++i) + for(length_t j(i + 1); result && j < m.length(); ++j) + result = areOrthogonal(m[i], m[j], epsilon); + + if(result) + { + mat tmp = transpose(m); + for(length_t i(0); result && i < m.length() - 1 ; ++i) + for(length_t j(i + 1); result && j < m.length(); ++j) + result = areOrthogonal(tmp[i], tmp[j], epsilon); + } + return result; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/matrix_transform_2d.hpp b/vendor/glm/glm/gtx/matrix_transform_2d.hpp new file mode 100644 index 0000000..5f9c540 --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_transform_2d.hpp @@ -0,0 +1,81 @@ +/// @ref gtx_matrix_transform_2d +/// @file glm/gtx/matrix_transform_2d.hpp +/// @author Miguel Ãngel Pérez Martínez +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_transform_2d GLM_GTX_matrix_transform_2d +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines functions that generate common 2d transformation matrices. + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../vec2.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_matrix_transform_2d is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_matrix_transform_2d extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_transform_2d + /// @{ + + /// Builds a translation 3 * 3 matrix created from a vector of 2 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a translation vector. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> translate( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v); + + /// Builds a rotation 3 * 3 matrix created from an angle. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param angle Rotation angle expressed in radians. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rotate( + mat<3, 3, T, Q> const& m, + T angle); + + /// Builds a scale 3 * 3 matrix created from a vector of 2 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a scale vector. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> scale( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v); + + /// Builds an horizontal (parallel to the x axis) shear 3 * 3 matrix. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param y Shear factor. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearX( + mat<3, 3, T, Q> const& m, + T y); + + /// Builds a vertical (parallel to the y axis) shear 3 * 3 matrix. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param x Shear factor. + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearY( + mat<3, 3, T, Q> const& m, + T x); + + /// @} +}//namespace glm + +#include "matrix_transform_2d.inl" diff --git a/vendor/glm/glm/gtx/matrix_transform_2d.inl b/vendor/glm/glm/gtx/matrix_transform_2d.inl new file mode 100644 index 0000000..a68d24d --- /dev/null +++ b/vendor/glm/glm/gtx/matrix_transform_2d.inl @@ -0,0 +1,68 @@ +/// @ref gtx_matrix_transform_2d +/// @author Miguel Ãngel Pérez Martínez + +#include "../trigonometric.hpp" + +namespace glm +{ + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> translate( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v) + { + mat<3, 3, T, Q> Result(m); + Result[2] = m[0] * v[0] + m[1] * v[1] + m[2]; + return Result; + } + + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> rotate( + mat<3, 3, T, Q> const& m, + T angle) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + mat<3, 3, T, Q> Result; + Result[0] = m[0] * c + m[1] * s; + Result[1] = m[0] * -s + m[1] * c; + Result[2] = m[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> scale( + mat<3, 3, T, Q> const& m, + vec<2, T, Q> const& v) + { + mat<3, 3, T, Q> Result; + Result[0] = m[0] * v[0]; + Result[1] = m[1] * v[1]; + Result[2] = m[2]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearX( + mat<3, 3, T, Q> const& m, + T y) + { + mat<3, 3, T, Q> Result(1); + Result[0][1] = y; + return m * Result; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearY( + mat<3, 3, T, Q> const& m, + T x) + { + mat<3, 3, T, Q> Result(1); + Result[1][0] = x; + return m * Result; + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/mixed_product.hpp b/vendor/glm/glm/gtx/mixed_product.hpp new file mode 100644 index 0000000..b242e35 --- /dev/null +++ b/vendor/glm/glm/gtx/mixed_product.hpp @@ -0,0 +1,41 @@ +/// @ref gtx_mixed_product +/// @file glm/gtx/mixed_product.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_mixed_product GLM_GTX_mixed_producte +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Mixed product of 3 vectors. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_mixed_product is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_mixed_product extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_mixed_product + /// @{ + + /// @brief Mixed product of 3 vectors (from GLM_GTX_mixed_product extension) + template + GLM_FUNC_DECL T mixedProduct( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3); + + /// @} +}// namespace glm + +#include "mixed_product.inl" diff --git a/vendor/glm/glm/gtx/mixed_product.inl b/vendor/glm/glm/gtx/mixed_product.inl new file mode 100644 index 0000000..e5cdbdb --- /dev/null +++ b/vendor/glm/glm/gtx/mixed_product.inl @@ -0,0 +1,15 @@ +/// @ref gtx_mixed_product + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T mixedProduct + ( + vec<3, T, Q> const& v1, + vec<3, T, Q> const& v2, + vec<3, T, Q> const& v3 + ) + { + return dot(cross(v1, v2), v3); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/norm.hpp b/vendor/glm/glm/gtx/norm.hpp new file mode 100644 index 0000000..dfaebb7 --- /dev/null +++ b/vendor/glm/glm/gtx/norm.hpp @@ -0,0 +1,88 @@ +/// @ref gtx_norm +/// @file glm/gtx/norm.hpp +/// +/// @see core (dependence) +/// @see gtx_quaternion (dependence) +/// @see gtx_component_wise (dependence) +/// +/// @defgroup gtx_norm GLM_GTX_norm +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Various ways to compute vector norms. + +#pragma once + +// Dependency: +#include "../geometric.hpp" +#include "../gtx/quaternion.hpp" +#include "../gtx/component_wise.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_norm is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_norm extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_norm + /// @{ + + /// Returns the squared length of x. + /// From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T length2(vec const& x); + + /// Returns the squared distance between p0 and p1, i.e., length2(p0 - p1). + /// From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T distance2(vec const& p0, vec const& p1); + + //! Returns the L1 norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l1Norm(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + //! Returns the L1 norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l1Norm(vec<3, T, Q> const& v); + + //! Returns the L2 norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l2Norm(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + //! Returns the L2 norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T l2Norm(vec<3, T, Q> const& x); + + //! Returns the L norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lxNorm(vec<3, T, Q> const& x, vec<3, T, Q> const& y, unsigned int Depth); + + //! Returns the L norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lxNorm(vec<3, T, Q> const& x, unsigned int Depth); + + //! Returns the LMax norm between x and y. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lMaxNorm(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + //! Returns the LMax norm of v. + //! From GLM_GTX_norm extension. + template + GLM_FUNC_DECL T lMaxNorm(vec<3, T, Q> const& x); + + /// @} +}//namespace glm + +#include "norm.inl" diff --git a/vendor/glm/glm/gtx/norm.inl b/vendor/glm/glm/gtx/norm.inl new file mode 100644 index 0000000..6db561b --- /dev/null +++ b/vendor/glm/glm/gtx/norm.inl @@ -0,0 +1,95 @@ +/// @ref gtx_norm + +#include "../detail/qualifier.hpp" + +namespace glm{ +namespace detail +{ + template + struct compute_length2 + { + GLM_FUNC_QUALIFIER static T call(vec const& v) + { + return dot(v, v); + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER genType length2(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'length2' accepts only floating-point inputs"); + return x * x; + } + + template + GLM_FUNC_QUALIFIER T length2(vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'length2' accepts only floating-point inputs"); + return detail::compute_length2::value>::call(v); + } + + template + GLM_FUNC_QUALIFIER T distance2(T p0, T p1) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'distance2' accepts only floating-point inputs"); + return length2(p1 - p0); + } + + template + GLM_FUNC_QUALIFIER T distance2(vec const& p0, vec const& p1) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'distance2' accepts only floating-point inputs"); + return length2(p1 - p0); + } + + template + GLM_FUNC_QUALIFIER T l1Norm(vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + return abs(b.x - a.x) + abs(b.y - a.y) + abs(b.z - a.z); + } + + template + GLM_FUNC_QUALIFIER T l1Norm(vec<3, T, Q> const& v) + { + return abs(v.x) + abs(v.y) + abs(v.z); + } + + template + GLM_FUNC_QUALIFIER T l2Norm(vec<3, T, Q> const& a, vec<3, T, Q> const& b + ) + { + return length(b - a); + } + + template + GLM_FUNC_QUALIFIER T l2Norm(vec<3, T, Q> const& v) + { + return length(v); + } + + template + GLM_FUNC_QUALIFIER T lxNorm(vec<3, T, Q> const& x, vec<3, T, Q> const& y, unsigned int Depth) + { + return pow(pow(abs(y.x - x.x), T(Depth)) + pow(abs(y.y - x.y), T(Depth)) + pow(abs(y.z - x.z), T(Depth)), T(1) / T(Depth)); + } + + template + GLM_FUNC_QUALIFIER T lxNorm(vec<3, T, Q> const& v, unsigned int Depth) + { + return pow(pow(abs(v.x), T(Depth)) + pow(abs(v.y), T(Depth)) + pow(abs(v.z), T(Depth)), T(1) / T(Depth)); + } + + template + GLM_FUNC_QUALIFIER T lMaxNorm(vec<3, T, Q> const& a, vec<3, T, Q> const& b) + { + return compMax(abs(b - a)); + } + + template + GLM_FUNC_QUALIFIER T lMaxNorm(vec<3, T, Q> const& v) + { + return compMax(abs(v)); + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/normal.hpp b/vendor/glm/glm/gtx/normal.hpp new file mode 100644 index 0000000..068682f --- /dev/null +++ b/vendor/glm/glm/gtx/normal.hpp @@ -0,0 +1,41 @@ +/// @ref gtx_normal +/// @file glm/gtx/normal.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_normal GLM_GTX_normal +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Compute the normal of a triangle. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_normal is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_normal extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_normal + /// @{ + + /// Computes triangle normal from triangle points. + /// + /// @see gtx_normal + template + GLM_FUNC_DECL vec<3, T, Q> triangleNormal(vec<3, T, Q> const& p1, vec<3, T, Q> const& p2, vec<3, T, Q> const& p3); + + /// @} +}//namespace glm + +#include "normal.inl" diff --git a/vendor/glm/glm/gtx/normal.inl b/vendor/glm/glm/gtx/normal.inl new file mode 100644 index 0000000..74f9fc9 --- /dev/null +++ b/vendor/glm/glm/gtx/normal.inl @@ -0,0 +1,15 @@ +/// @ref gtx_normal + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> triangleNormal + ( + vec<3, T, Q> const& p1, + vec<3, T, Q> const& p2, + vec<3, T, Q> const& p3 + ) + { + return normalize(cross(p1 - p2, p1 - p3)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/normalize_dot.hpp b/vendor/glm/glm/gtx/normalize_dot.hpp new file mode 100644 index 0000000..5195802 --- /dev/null +++ b/vendor/glm/glm/gtx/normalize_dot.hpp @@ -0,0 +1,49 @@ +/// @ref gtx_normalize_dot +/// @file glm/gtx/normalize_dot.hpp +/// +/// @see core (dependence) +/// @see gtx_fast_square_root (dependence) +/// +/// @defgroup gtx_normalize_dot GLM_GTX_normalize_dot +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Dot product of vectors that need to be normalize with a single square root. + +#pragma once + +// Dependency: +#include "../gtx/fast_square_root.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_normalize_dot is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_normalize_dot extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_normalize_dot + /// @{ + + /// Normalize parameters and returns the dot product of x and y. + /// It's faster that dot(normalize(x), normalize(y)). + /// + /// @see gtx_normalize_dot extension. + template + GLM_FUNC_DECL T normalizeDot(vec const& x, vec const& y); + + /// Normalize parameters and returns the dot product of x and y. + /// Faster that dot(fastNormalize(x), fastNormalize(y)). + /// + /// @see gtx_normalize_dot extension. + template + GLM_FUNC_DECL T fastNormalizeDot(vec const& x, vec const& y); + + /// @} +}//namespace glm + +#include "normalize_dot.inl" diff --git a/vendor/glm/glm/gtx/normalize_dot.inl b/vendor/glm/glm/gtx/normalize_dot.inl new file mode 100644 index 0000000..7bcd9a5 --- /dev/null +++ b/vendor/glm/glm/gtx/normalize_dot.inl @@ -0,0 +1,16 @@ +/// @ref gtx_normalize_dot + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T normalizeDot(vec const& x, vec const& y) + { + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); + } + + template + GLM_FUNC_QUALIFIER T fastNormalizeDot(vec const& x, vec const& y) + { + return glm::dot(x, y) * glm::fastInverseSqrt(glm::dot(x, x) * glm::dot(y, y)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/number_precision.hpp b/vendor/glm/glm/gtx/number_precision.hpp new file mode 100644 index 0000000..3a606bd --- /dev/null +++ b/vendor/glm/glm/gtx/number_precision.hpp @@ -0,0 +1,61 @@ +/// @ref gtx_number_precision +/// @file glm/gtx/number_precision.hpp +/// +/// @see core (dependence) +/// @see gtc_type_precision (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_number_precision GLM_GTX_number_precision +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defined size types. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_number_precision is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_number_precision extension included") +# endif +#endif + +namespace glm{ +namespace gtx +{ + ///////////////////////////// + // Unsigned int vector types + + /// @addtogroup gtx_number_precision + /// @{ + + typedef u8 u8vec1; //!< \brief 8bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u16 u16vec1; //!< \brief 16bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u32 u32vec1; //!< \brief 32bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u64 u64vec1; //!< \brief 64bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + + ////////////////////// + // Float vector types + + typedef f32 f32vec1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64vec1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + + ////////////////////// + // Float matrix types + + typedef f32 f32mat1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f32 f32mat1x1; //!< \brief Single-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64mat1; //!< \brief Double-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64mat1x1; //!< \brief Double-qualifier floating-point scalar. (from GLM_GTX_number_precision extension) + + /// @} +}//namespace gtx +}//namespace glm + +#include "number_precision.inl" diff --git a/vendor/glm/glm/gtx/number_precision.inl b/vendor/glm/glm/gtx/number_precision.inl new file mode 100644 index 0000000..b39d71c --- /dev/null +++ b/vendor/glm/glm/gtx/number_precision.inl @@ -0,0 +1,6 @@ +/// @ref gtx_number_precision + +namespace glm +{ + +} diff --git a/vendor/glm/glm/gtx/optimum_pow.hpp b/vendor/glm/glm/gtx/optimum_pow.hpp new file mode 100644 index 0000000..9284a47 --- /dev/null +++ b/vendor/glm/glm/gtx/optimum_pow.hpp @@ -0,0 +1,54 @@ +/// @ref gtx_optimum_pow +/// @file glm/gtx/optimum_pow.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_optimum_pow GLM_GTX_optimum_pow +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Integer exponentiation of power functions. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_optimum_pow is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_optimum_pow extension included") +# endif +#endif + +namespace glm{ +namespace gtx +{ + /// @addtogroup gtx_optimum_pow + /// @{ + + /// Returns x raised to the power of 2. + /// + /// @see gtx_optimum_pow + template + GLM_FUNC_DECL genType pow2(genType const& x); + + /// Returns x raised to the power of 3. + /// + /// @see gtx_optimum_pow + template + GLM_FUNC_DECL genType pow3(genType const& x); + + /// Returns x raised to the power of 4. + /// + /// @see gtx_optimum_pow + template + GLM_FUNC_DECL genType pow4(genType const& x); + + /// @} +}//namespace gtx +}//namespace glm + +#include "optimum_pow.inl" diff --git a/vendor/glm/glm/gtx/optimum_pow.inl b/vendor/glm/glm/gtx/optimum_pow.inl new file mode 100644 index 0000000..a26c19c --- /dev/null +++ b/vendor/glm/glm/gtx/optimum_pow.inl @@ -0,0 +1,22 @@ +/// @ref gtx_optimum_pow + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType pow2(genType const& x) + { + return x * x; + } + + template + GLM_FUNC_QUALIFIER genType pow3(genType const& x) + { + return x * x * x; + } + + template + GLM_FUNC_QUALIFIER genType pow4(genType const& x) + { + return (x * x) * (x * x); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/orthonormalize.hpp b/vendor/glm/glm/gtx/orthonormalize.hpp new file mode 100644 index 0000000..3e004fb --- /dev/null +++ b/vendor/glm/glm/gtx/orthonormalize.hpp @@ -0,0 +1,49 @@ +/// @ref gtx_orthonormalize +/// @file glm/gtx/orthonormalize.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_orthonormalize GLM_GTX_orthonormalize +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Orthonormalize matrices. + +#pragma once + +// Dependency: +#include "../vec3.hpp" +#include "../mat3x3.hpp" +#include "../geometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_orthonormalize is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_orthonormalize extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_orthonormalize + /// @{ + + /// Returns the orthonormalized matrix of m. + /// + /// @see gtx_orthonormalize + template + GLM_FUNC_DECL mat<3, 3, T, Q> orthonormalize(mat<3, 3, T, Q> const& m); + + /// Orthonormalizes x according y. + /// + /// @see gtx_orthonormalize + template + GLM_FUNC_DECL vec<3, T, Q> orthonormalize(vec<3, T, Q> const& x, vec<3, T, Q> const& y); + + /// @} +}//namespace glm + +#include "orthonormalize.inl" diff --git a/vendor/glm/glm/gtx/orthonormalize.inl b/vendor/glm/glm/gtx/orthonormalize.inl new file mode 100644 index 0000000..cb553ba --- /dev/null +++ b/vendor/glm/glm/gtx/orthonormalize.inl @@ -0,0 +1,29 @@ +/// @ref gtx_orthonormalize + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> orthonormalize(mat<3, 3, T, Q> const& m) + { + mat<3, 3, T, Q> r = m; + + r[0] = normalize(r[0]); + + T d0 = dot(r[0], r[1]); + r[1] -= r[0] * d0; + r[1] = normalize(r[1]); + + T d1 = dot(r[1], r[2]); + d0 = dot(r[0], r[2]); + r[2] -= r[0] * d0 + r[1] * d1; + r[2] = normalize(r[2]); + + return r; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> orthonormalize(vec<3, T, Q> const& x, vec<3, T, Q> const& y) + { + return normalize(x - y * dot(y, x)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/perpendicular.hpp b/vendor/glm/glm/gtx/perpendicular.hpp new file mode 100644 index 0000000..72b77b6 --- /dev/null +++ b/vendor/glm/glm/gtx/perpendicular.hpp @@ -0,0 +1,41 @@ +/// @ref gtx_perpendicular +/// @file glm/gtx/perpendicular.hpp +/// +/// @see core (dependence) +/// @see gtx_projection (dependence) +/// +/// @defgroup gtx_perpendicular GLM_GTX_perpendicular +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Perpendicular of a vector from other one + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/projection.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_perpendicular is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_perpendicular extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_perpendicular + /// @{ + + //! Projects x a perpendicular axis of Normal. + //! From GLM_GTX_perpendicular extension. + template + GLM_FUNC_DECL genType perp(genType const& x, genType const& Normal); + + /// @} +}//namespace glm + +#include "perpendicular.inl" diff --git a/vendor/glm/glm/gtx/perpendicular.inl b/vendor/glm/glm/gtx/perpendicular.inl new file mode 100644 index 0000000..1e72f33 --- /dev/null +++ b/vendor/glm/glm/gtx/perpendicular.inl @@ -0,0 +1,10 @@ +/// @ref gtx_perpendicular + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType perp(genType const& x, genType const& Normal) + { + return x - proj(x, Normal); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/polar_coordinates.hpp b/vendor/glm/glm/gtx/polar_coordinates.hpp new file mode 100644 index 0000000..76beb82 --- /dev/null +++ b/vendor/glm/glm/gtx/polar_coordinates.hpp @@ -0,0 +1,48 @@ +/// @ref gtx_polar_coordinates +/// @file glm/gtx/polar_coordinates.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_polar_coordinates GLM_GTX_polar_coordinates +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Conversion from Euclidean space to polar space and revert. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_polar_coordinates is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_polar_coordinates extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_polar_coordinates + /// @{ + + /// Convert Euclidean to Polar coordinates, x is the latitude, y the longitude and z the xz distance. + /// + /// @see gtx_polar_coordinates + template + GLM_FUNC_DECL vec<3, T, Q> polar( + vec<3, T, Q> const& euclidean); + + /// Convert Polar to Euclidean coordinates. + /// + /// @see gtx_polar_coordinates + template + GLM_FUNC_DECL vec<3, T, Q> euclidean( + vec<2, T, Q> const& polar); + + /// @} +}//namespace glm + +#include "polar_coordinates.inl" diff --git a/vendor/glm/glm/gtx/polar_coordinates.inl b/vendor/glm/glm/gtx/polar_coordinates.inl new file mode 100644 index 0000000..371c8dd --- /dev/null +++ b/vendor/glm/glm/gtx/polar_coordinates.inl @@ -0,0 +1,36 @@ +/// @ref gtx_polar_coordinates + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> polar + ( + vec<3, T, Q> const& euclidean + ) + { + T const Length(length(euclidean)); + vec<3, T, Q> const tmp(euclidean / Length); + T const xz_dist(sqrt(tmp.x * tmp.x + tmp.z * tmp.z)); + + return vec<3, T, Q>( + asin(tmp.y), // latitude + atan(tmp.x, tmp.z), // longitude + xz_dist); // xz distance + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> euclidean + ( + vec<2, T, Q> const& polar + ) + { + T const latitude(polar.x); + T const longitude(polar.y); + + return vec<3, T, Q>( + cos(latitude) * sin(longitude), + sin(latitude), + cos(latitude) * cos(longitude)); + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/projection.hpp b/vendor/glm/glm/gtx/projection.hpp new file mode 100644 index 0000000..678f3ad --- /dev/null +++ b/vendor/glm/glm/gtx/projection.hpp @@ -0,0 +1,43 @@ +/// @ref gtx_projection +/// @file glm/gtx/projection.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_projection GLM_GTX_projection +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Projection of a vector to other one + +#pragma once + +// Dependency: +#include "../geometric.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_projection is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_projection extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_projection + /// @{ + + /// Projects x on Normal. + /// + /// @param[in] x A vector to project + /// @param[in] Normal A normal that doesn't need to be of unit length. + /// + /// @see gtx_projection + template + GLM_FUNC_DECL genType proj(genType const& x, genType const& Normal); + + /// @} +}//namespace glm + +#include "projection.inl" diff --git a/vendor/glm/glm/gtx/projection.inl b/vendor/glm/glm/gtx/projection.inl new file mode 100644 index 0000000..f23f884 --- /dev/null +++ b/vendor/glm/glm/gtx/projection.inl @@ -0,0 +1,10 @@ +/// @ref gtx_projection + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType proj(genType const& x, genType const& Normal) + { + return glm::dot(x, Normal) / glm::dot(Normal, Normal) * Normal; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/quaternion.hpp b/vendor/glm/glm/gtx/quaternion.hpp new file mode 100644 index 0000000..5c2b5ad --- /dev/null +++ b/vendor/glm/glm/gtx/quaternion.hpp @@ -0,0 +1,174 @@ +/// @ref gtx_quaternion +/// @file glm/gtx/quaternion.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_quaternion GLM_GTX_quaternion +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Extented quaternion types and functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/quaternion.hpp" +#include "../ext/quaternion_exponential.hpp" +#include "../gtx/norm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_quaternion is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_quaternion extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_quaternion + /// @{ + + /// Create an identity quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL GLM_CONSTEXPR qua quat_identity(); + + /// Compute a cross product between a quaternion and a vector. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL vec<3, T, Q> cross( + qua const& q, + vec<3, T, Q> const& v); + + //! Compute a cross product between a vector and a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL vec<3, T, Q> cross( + vec<3, T, Q> const& v, + qua const& q); + + //! Compute a point on a path according squad equation. + //! q1 and q2 are control points; s1 and s2 are intermediate control points. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua squad( + qua const& q1, + qua const& q2, + qua const& s1, + qua const& s2, + T const& h); + + //! Returns an intermediate control point for squad interpolation. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua intermediate( + qua const& prev, + qua const& curr, + qua const& next); + + //! Returns quarternion square root. + /// + /// @see gtx_quaternion + //template + //qua sqrt( + // qua const& q); + + //! Rotates a 3 components vector by a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL vec<3, T, Q> rotate( + qua const& q, + vec<3, T, Q> const& v); + + /// Rotates a 4 components vector by a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL vec<4, T, Q> rotate( + qua const& q, + vec<4, T, Q> const& v); + + /// Extract the real component of a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL T extractRealComponent( + qua const& q); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL mat<3, 3, T, Q> toMat3( + qua const& x){return mat3_cast(x);} + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL mat<4, 4, T, Q> toMat4( + qua const& x){return mat4_cast(x);} + + /// Converts a 3 * 3 matrix to a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua toQuat( + mat<3, 3, T, Q> const& x){return quat_cast(x);} + + /// Converts a 4 * 4 matrix to a quaternion. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua toQuat( + mat<4, 4, T, Q> const& x){return quat_cast(x);} + + /// Quaternion interpolation using the rotation short path. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua shortMix( + qua const& x, + qua const& y, + T const& a); + + /// Quaternion normalized linear interpolation. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua fastMix( + qua const& x, + qua const& y, + T const& a); + + /// Compute the rotation between two vectors. + /// @param orig vector, needs to be normalized + /// @param dest vector, needs to be normalized + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL qua rotation( + vec<3, T, Q> const& orig, + vec<3, T, Q> const& dest); + + /// Returns the squared length of x. + /// + /// @see gtx_quaternion + template + GLM_FUNC_DECL GLM_CONSTEXPR T length2(qua const& q); + + /// @} +}//namespace glm + +#include "quaternion.inl" diff --git a/vendor/glm/glm/gtx/quaternion.inl b/vendor/glm/glm/gtx/quaternion.inl new file mode 100644 index 0000000..d125bcc --- /dev/null +++ b/vendor/glm/glm/gtx/quaternion.inl @@ -0,0 +1,159 @@ +/// @ref gtx_quaternion + +#include +#include "../gtc/constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua quat_identity() + { + return qua(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> cross(vec<3, T, Q> const& v, qua const& q) + { + return inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> cross(qua const& q, vec<3, T, Q> const& v) + { + return q * v; + } + + template + GLM_FUNC_QUALIFIER qua squad + ( + qua const& q1, + qua const& q2, + qua const& s1, + qua const& s2, + T const& h) + { + return mix(mix(q1, q2, h), mix(s1, s2, h), static_cast(2) * (static_cast(1) - h) * h); + } + + template + GLM_FUNC_QUALIFIER qua intermediate + ( + qua const& prev, + qua const& curr, + qua const& next + ) + { + qua invQuat = inverse(curr); + return exp((log(next * invQuat) + log(prev * invQuat)) / static_cast(-4)) * curr; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotate(qua const& q, vec<3, T, Q> const& v) + { + return q * v; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotate(qua const& q, vec<4, T, Q> const& v) + { + return q * v; + } + + template + GLM_FUNC_QUALIFIER T extractRealComponent(qua const& q) + { + T w = static_cast(1) - q.x * q.x - q.y * q.y - q.z * q.z; + if(w < T(0)) + return T(0); + else + return -sqrt(w); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T length2(qua const& q) + { + return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; + } + + template + GLM_FUNC_QUALIFIER qua shortMix(qua const& x, qua const& y, T const& a) + { + if(a <= static_cast(0)) return x; + if(a >= static_cast(1)) return y; + + T fCos = dot(x, y); + qua y2(y); //BUG!!! qua y2; + if(fCos < static_cast(0)) + { + y2 = -y; + fCos = -fCos; + } + + //if(fCos > 1.0f) // problem + T k0, k1; + if(fCos > (static_cast(1) - epsilon())) + { + k0 = static_cast(1) - a; + k1 = static_cast(0) + a; //BUG!!! 1.0f + a; + } + else + { + T fSin = sqrt(T(1) - fCos * fCos); + T fAngle = atan(fSin, fCos); + T fOneOverSin = static_cast(1) / fSin; + k0 = sin((static_cast(1) - a) * fAngle) * fOneOverSin; + k1 = sin((static_cast(0) + a) * fAngle) * fOneOverSin; + } + + return qua( + k0 * x.w + k1 * y2.w, + k0 * x.x + k1 * y2.x, + k0 * x.y + k1 * y2.y, + k0 * x.z + k1 * y2.z); + } + + template + GLM_FUNC_QUALIFIER qua fastMix(qua const& x, qua const& y, T const& a) + { + return glm::normalize(x * (static_cast(1) - a) + (y * a)); + } + + template + GLM_FUNC_QUALIFIER qua rotation(vec<3, T, Q> const& orig, vec<3, T, Q> const& dest) + { + T cosTheta = dot(orig, dest); + vec<3, T, Q> rotationAxis; + + if(cosTheta >= static_cast(1) - epsilon()) { + // orig and dest point in the same direction + return quat_identity(); + } + + if(cosTheta < static_cast(-1) + epsilon()) + { + // special case when vectors in opposite directions : + // there is no "ideal" rotation axis + // So guess one; any will do as long as it's perpendicular to start + // This implementation favors a rotation around the Up axis (Y), + // since it's often what you want to do. + rotationAxis = cross(vec<3, T, Q>(0, 0, 1), orig); + if(length2(rotationAxis) < epsilon()) // bad luck, they were parallel, try again! + rotationAxis = cross(vec<3, T, Q>(1, 0, 0), orig); + + rotationAxis = normalize(rotationAxis); + return angleAxis(pi(), rotationAxis); + } + + // Implementation from Stan Melax's Game Programming Gems 1 article + rotationAxis = cross(orig, dest); + + T s = sqrt((T(1) + cosTheta) * static_cast(2)); + T invs = static_cast(1) / s; + + return qua( + s * static_cast(0.5f), + rotationAxis.x * invs, + rotationAxis.y * invs, + rotationAxis.z * invs); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/range.hpp b/vendor/glm/glm/gtx/range.hpp new file mode 100644 index 0000000..93bcb9a --- /dev/null +++ b/vendor/glm/glm/gtx/range.hpp @@ -0,0 +1,98 @@ +/// @ref gtx_range +/// @file glm/gtx/range.hpp +/// @author Joshua Moerman +/// +/// @defgroup gtx_range GLM_GTX_range +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines begin and end for vectors and matrices. Useful for range-based for loop. +/// The range is defined over the elements, not over columns or rows (e.g. mat4 has 16 elements). + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_range is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_range extension included") +# endif +#endif + +#include "../gtc/type_ptr.hpp" +#include "../gtc/vec1.hpp" + +namespace glm +{ + /// @addtogroup gtx_range + /// @{ + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4100) // unreferenced formal parameter +# endif + + template + inline length_t components(vec<1, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(vec<2, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(vec<3, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(vec<4, T, Q> const& v) + { + return v.length(); + } + + template + inline length_t components(genType const& m) + { + return m.length() * m[0].length(); + } + + template + inline typename genType::value_type const * begin(genType const& v) + { + return value_ptr(v); + } + + template + inline typename genType::value_type const * end(genType const& v) + { + return begin(v) + components(v); + } + + template + inline typename genType::value_type * begin(genType& v) + { + return value_ptr(v); + } + + template + inline typename genType::value_type * end(genType& v) + { + return begin(v) + components(v); + } + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + + /// @} +}//namespace glm diff --git a/vendor/glm/glm/gtx/raw_data.hpp b/vendor/glm/glm/gtx/raw_data.hpp new file mode 100644 index 0000000..86cbe77 --- /dev/null +++ b/vendor/glm/glm/gtx/raw_data.hpp @@ -0,0 +1,51 @@ +/// @ref gtx_raw_data +/// @file glm/gtx/raw_data.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_raw_data GLM_GTX_raw_data +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Projection of a vector to other one + +#pragma once + +// Dependencies +#include "../ext/scalar_uint_sized.hpp" +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_raw_data is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_raw_data extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_raw_data + /// @{ + + //! Type for byte numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint8 byte; + + //! Type for word numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint16 word; + + //! Type for dword numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint32 dword; + + //! Type for qword numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint64 qword; + + /// @} +}// namespace glm + +#include "raw_data.inl" diff --git a/vendor/glm/glm/gtx/raw_data.inl b/vendor/glm/glm/gtx/raw_data.inl new file mode 100644 index 0000000..c740317 --- /dev/null +++ b/vendor/glm/glm/gtx/raw_data.inl @@ -0,0 +1,2 @@ +/// @ref gtx_raw_data + diff --git a/vendor/glm/glm/gtx/rotate_normalized_axis.hpp b/vendor/glm/glm/gtx/rotate_normalized_axis.hpp new file mode 100644 index 0000000..2103ca0 --- /dev/null +++ b/vendor/glm/glm/gtx/rotate_normalized_axis.hpp @@ -0,0 +1,68 @@ +/// @ref gtx_rotate_normalized_axis +/// @file glm/gtx/rotate_normalized_axis.hpp +/// +/// @see core (dependence) +/// @see gtc_matrix_transform +/// @see gtc_quaternion +/// +/// @defgroup gtx_rotate_normalized_axis GLM_GTX_rotate_normalized_axis +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Quaternions and matrices rotations around normalized axis. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtc/quaternion.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_rotate_normalized_axis is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_rotate_normalized_axis extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_rotate_normalized_axis + /// @{ + + /// Builds a rotation 4 * 4 matrix created from a normalized axis and an angle. + /// + /// @param m Input matrix multiplied by this rotation matrix. + /// @param angle Rotation angle expressed in radians. + /// @param axis Rotation axis, must be normalized. + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommended), float or double. + /// + /// @see gtx_rotate_normalized_axis + /// @see - rotate(T angle, T x, T y, T z) + /// @see - rotate(mat<4, 4, T, Q> const& m, T angle, T x, T y, T z) + /// @see - rotate(T angle, vec<3, T, Q> const& v) + template + GLM_FUNC_DECL mat<4, 4, T, Q> rotateNormalizedAxis( + mat<4, 4, T, Q> const& m, + T const& angle, + vec<3, T, Q> const& axis); + + /// Rotates a quaternion from a vector of 3 components normalized axis and an angle. + /// + /// @param q Source orientation + /// @param angle Angle expressed in radians. + /// @param axis Normalized axis of the rotation, must be normalized. + /// + /// @see gtx_rotate_normalized_axis + template + GLM_FUNC_DECL qua rotateNormalizedAxis( + qua const& q, + T const& angle, + vec<3, T, Q> const& axis); + + /// @} +}//namespace glm + +#include "rotate_normalized_axis.inl" diff --git a/vendor/glm/glm/gtx/rotate_normalized_axis.inl b/vendor/glm/glm/gtx/rotate_normalized_axis.inl new file mode 100644 index 0000000..b2e9278 --- /dev/null +++ b/vendor/glm/glm/gtx/rotate_normalized_axis.inl @@ -0,0 +1,58 @@ +/// @ref gtx_rotate_normalized_axis + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotateNormalizedAxis + ( + mat<4, 4, T, Q> const& m, + T const& angle, + vec<3, T, Q> const& v + ) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + vec<3, T, Q> const axis(v); + + vec<3, T, Q> const temp((static_cast(1) - c) * axis); + + mat<4, 4, T, Q> Rotate; + Rotate[0][0] = c + temp[0] * axis[0]; + Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + + Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + Rotate[1][1] = c + temp[1] * axis[1]; + Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + + Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + Rotate[2][2] = c + temp[2] * axis[2]; + + mat<4, 4, T, Q> Result; + Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + Result[3] = m[3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER qua rotateNormalizedAxis + ( + qua const& q, + T const& angle, + vec<3, T, Q> const& v + ) + { + vec<3, T, Q> const Tmp(v); + + T const AngleRad(angle); + T const Sin = sin(AngleRad * T(0.5)); + + return q * qua(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + //return gtc::quaternion::cross(q, tquat(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/rotate_vector.hpp b/vendor/glm/glm/gtx/rotate_vector.hpp new file mode 100644 index 0000000..dcd5b95 --- /dev/null +++ b/vendor/glm/glm/gtx/rotate_vector.hpp @@ -0,0 +1,123 @@ +/// @ref gtx_rotate_vector +/// @file glm/gtx/rotate_vector.hpp +/// +/// @see core (dependence) +/// @see gtx_transform (dependence) +/// +/// @defgroup gtx_rotate_vector GLM_GTX_rotate_vector +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Function to directly rotate a vector + +#pragma once + +// Dependency: +#include "../gtx/transform.hpp" +#include "../gtc/epsilon.hpp" +#include "../ext/vector_relational.hpp" +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_rotate_vector is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_rotate_vector extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_rotate_vector + /// @{ + + /// Returns Spherical interpolation between two vectors + /// + /// @param x A first vector + /// @param y A second vector + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// + /// @see gtx_rotate_vector + template + GLM_FUNC_DECL vec<3, T, Q> slerp( + vec<3, T, Q> const& x, + vec<3, T, Q> const& y, + T const& a); + + //! Rotate a two dimensional vector. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<2, T, Q> rotate( + vec<2, T, Q> const& v, + T const& angle); + + //! Rotate a three dimensional vector around an axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotate( + vec<3, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal); + + //! Rotate a four dimensional vector around an axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotate( + vec<4, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal); + + //! Rotate a three dimensional vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotateX( + vec<3, T, Q> const& v, + T const& angle); + + //! Rotate a three dimensional vector around the Y axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotateY( + vec<3, T, Q> const& v, + T const& angle); + + //! Rotate a three dimensional vector around the Z axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<3, T, Q> rotateZ( + vec<3, T, Q> const& v, + T const& angle); + + //! Rotate a four dimensional vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotateX( + vec<4, T, Q> const& v, + T const& angle); + + //! Rotate a four dimensional vector around the Y axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotateY( + vec<4, T, Q> const& v, + T const& angle); + + //! Rotate a four dimensional vector around the Z axis. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL vec<4, T, Q> rotateZ( + vec<4, T, Q> const& v, + T const& angle); + + //! Build a rotation matrix from a normal and a up vector. + //! From GLM_GTX_rotate_vector extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> orientation( + vec<3, T, Q> const& Normal, + vec<3, T, Q> const& Up); + + /// @} +}//namespace glm + +#include "rotate_vector.inl" diff --git a/vendor/glm/glm/gtx/rotate_vector.inl b/vendor/glm/glm/gtx/rotate_vector.inl new file mode 100644 index 0000000..f8136e7 --- /dev/null +++ b/vendor/glm/glm/gtx/rotate_vector.inl @@ -0,0 +1,187 @@ +/// @ref gtx_rotate_vector + +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec<3, T, Q> slerp + ( + vec<3, T, Q> const& x, + vec<3, T, Q> const& y, + T const& a + ) + { + // get cosine of angle between vectors (-1 -> 1) + T CosAlpha = dot(x, y); + // get angle (0 -> pi) + T Alpha = acos(CosAlpha); + // get sine of angle between vectors (0 -> 1) + T SinAlpha = sin(Alpha); + // this breaks down when SinAlpha = 0, i.e. Alpha = 0 or pi + T t1 = sin((static_cast(1) - a) * Alpha) / SinAlpha; + T t2 = sin(a * Alpha) / SinAlpha; + + // interpolate src vectors + return x * t1 + y * t2; + } + + template + GLM_FUNC_QUALIFIER vec<2, T, Q> rotate + ( + vec<2, T, Q> const& v, + T const& angle + ) + { + vec<2, T, Q> Result; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotate + ( + vec<3, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal + ) + { + return mat<3, 3, T, Q>(glm::rotate(angle, normal)) * v; + } + /* + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateGTX( + const vec<3, T, Q>& x, + T angle, + const vec<3, T, Q>& normal) + { + const T Cos = cos(radians(angle)); + const T Sin = sin(radians(angle)); + return x * Cos + ((x * normal) * (T(1) - Cos)) * normal + cross(x, normal) * Sin; + } + */ + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotate + ( + vec<4, T, Q> const& v, + T const& angle, + vec<3, T, Q> const& normal + ) + { + return rotate(angle, normal) * v; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateX + ( + vec<3, T, Q> const& v, + T const& angle + ) + { + vec<3, T, Q> Result(v); + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.y = v.y * Cos - v.z * Sin; + Result.z = v.y * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateY + ( + vec<3, T, Q> const& v, + T const& angle + ) + { + vec<3, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos + v.z * Sin; + Result.z = -v.x * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<3, T, Q> rotateZ + ( + vec<3, T, Q> const& v, + T const& angle + ) + { + vec<3, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotateX + ( + vec<4, T, Q> const& v, + T const& angle + ) + { + vec<4, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.y = v.y * Cos - v.z * Sin; + Result.z = v.y * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotateY + ( + vec<4, T, Q> const& v, + T const& angle + ) + { + vec<4, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos + v.z * Sin; + Result.z = -v.x * Sin + v.z * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER vec<4, T, Q> rotateZ + ( + vec<4, T, Q> const& v, + T const& angle + ) + { + vec<4, T, Q> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> orientation + ( + vec<3, T, Q> const& Normal, + vec<3, T, Q> const& Up + ) + { + if(all(equal(Normal, Up, epsilon()))) + return mat<4, 4, T, Q>(static_cast(1)); + + vec<3, T, Q> RotationAxis = cross(Up, Normal); + T Angle = acos(dot(Normal, Up)); + + return rotate(Angle, RotationAxis); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/scalar_multiplication.hpp b/vendor/glm/glm/gtx/scalar_multiplication.hpp new file mode 100644 index 0000000..496ba19 --- /dev/null +++ b/vendor/glm/glm/gtx/scalar_multiplication.hpp @@ -0,0 +1,75 @@ +/// @ref gtx +/// @file glm/gtx/scalar_multiplication.hpp +/// @author Joshua Moerman +/// +/// Include to use the features of this extension. +/// +/// Enables scalar multiplication for all types +/// +/// Since GLSL is very strict about types, the following (often used) combinations do not work: +/// double * vec4 +/// int * vec4 +/// vec4 / int +/// So we'll fix that! Of course "float * vec4" should remain the same (hence the enable_if magic) + +#pragma once + +#include "../detail/setup.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_scalar_multiplication is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_scalar_multiplication extension included") +# endif +#endif + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include + +namespace glm +{ + template + using return_type_scalar_multiplication = typename std::enable_if< + !std::is_same::value // T may not be a float + && std::is_arithmetic::value, Vec // But it may be an int or double (no vec3 or mat3, ...) + >::type; + +#define GLM_IMPLEMENT_SCAL_MULT(Vec) \ + template \ + return_type_scalar_multiplication \ + operator*(T const& s, Vec rh){ \ + return rh *= static_cast(s); \ + } \ + \ + template \ + return_type_scalar_multiplication \ + operator*(Vec lh, T const& s){ \ + return lh *= static_cast(s); \ + } \ + \ + template \ + return_type_scalar_multiplication \ + operator/(Vec lh, T const& s){ \ + return lh *= 1.0f / static_cast(s); \ + } + +GLM_IMPLEMENT_SCAL_MULT(vec2) +GLM_IMPLEMENT_SCAL_MULT(vec3) +GLM_IMPLEMENT_SCAL_MULT(vec4) + +GLM_IMPLEMENT_SCAL_MULT(mat2) +GLM_IMPLEMENT_SCAL_MULT(mat2x3) +GLM_IMPLEMENT_SCAL_MULT(mat2x4) +GLM_IMPLEMENT_SCAL_MULT(mat3x2) +GLM_IMPLEMENT_SCAL_MULT(mat3) +GLM_IMPLEMENT_SCAL_MULT(mat3x4) +GLM_IMPLEMENT_SCAL_MULT(mat4x2) +GLM_IMPLEMENT_SCAL_MULT(mat4x3) +GLM_IMPLEMENT_SCAL_MULT(mat4) + +#undef GLM_IMPLEMENT_SCAL_MULT +} // namespace glm diff --git a/vendor/glm/glm/gtx/scalar_relational.hpp b/vendor/glm/glm/gtx/scalar_relational.hpp new file mode 100644 index 0000000..8be9c57 --- /dev/null +++ b/vendor/glm/glm/gtx/scalar_relational.hpp @@ -0,0 +1,36 @@ +/// @ref gtx_scalar_relational +/// @file glm/gtx/scalar_relational.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_scalar_relational GLM_GTX_scalar_relational +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Extend a position from a source to a position at a defined length. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_extend is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_extend extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_scalar_relational + /// @{ + + + + /// @} +}//namespace glm + +#include "scalar_relational.inl" diff --git a/vendor/glm/glm/gtx/scalar_relational.inl b/vendor/glm/glm/gtx/scalar_relational.inl new file mode 100644 index 0000000..c2a121c --- /dev/null +++ b/vendor/glm/glm/gtx/scalar_relational.inl @@ -0,0 +1,88 @@ +/// @ref gtx_scalar_relational + +namespace glm +{ + template + GLM_FUNC_QUALIFIER bool lessThan + ( + T const& x, + T const& y + ) + { + return x < y; + } + + template + GLM_FUNC_QUALIFIER bool lessThanEqual + ( + T const& x, + T const& y + ) + { + return x <= y; + } + + template + GLM_FUNC_QUALIFIER bool greaterThan + ( + T const& x, + T const& y + ) + { + return x > y; + } + + template + GLM_FUNC_QUALIFIER bool greaterThanEqual + ( + T const& x, + T const& y + ) + { + return x >= y; + } + + template + GLM_FUNC_QUALIFIER bool equal + ( + T const& x, + T const& y + ) + { + return detail::compute_equal::is_iec559>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER bool notEqual + ( + T const& x, + T const& y + ) + { + return !detail::compute_equal::is_iec559>::call(x, y); + } + + GLM_FUNC_QUALIFIER bool any + ( + bool const& x + ) + { + return x; + } + + GLM_FUNC_QUALIFIER bool all + ( + bool const& x + ) + { + return x; + } + + GLM_FUNC_QUALIFIER bool not_ + ( + bool const& x + ) + { + return !x; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/spline.hpp b/vendor/glm/glm/gtx/spline.hpp new file mode 100644 index 0000000..731c979 --- /dev/null +++ b/vendor/glm/glm/gtx/spline.hpp @@ -0,0 +1,65 @@ +/// @ref gtx_spline +/// @file glm/gtx/spline.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_spline GLM_GTX_spline +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Spline functions + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/optimum_pow.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_spline is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_spline extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_spline + /// @{ + + /// Return a point from a catmull rom curve. + /// @see gtx_spline extension. + template + GLM_FUNC_DECL genType catmullRom( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s); + + /// Return a point from a hermite curve. + /// @see gtx_spline extension. + template + GLM_FUNC_DECL genType hermite( + genType const& v1, + genType const& t1, + genType const& v2, + genType const& t2, + typename genType::value_type const& s); + + /// Return a point from a cubic curve. + /// @see gtx_spline extension. + template + GLM_FUNC_DECL genType cubic( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s); + + /// @} +}//namespace glm + +#include "spline.inl" diff --git a/vendor/glm/glm/gtx/spline.inl b/vendor/glm/glm/gtx/spline.inl new file mode 100644 index 0000000..c3fd056 --- /dev/null +++ b/vendor/glm/glm/gtx/spline.inl @@ -0,0 +1,60 @@ +/// @ref gtx_spline + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType catmullRom + ( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s + ) + { + typename genType::value_type s2 = pow2(s); + typename genType::value_type s3 = pow3(s); + + typename genType::value_type f1 = -s3 + typename genType::value_type(2) * s2 - s; + typename genType::value_type f2 = typename genType::value_type(3) * s3 - typename genType::value_type(5) * s2 + typename genType::value_type(2); + typename genType::value_type f3 = typename genType::value_type(-3) * s3 + typename genType::value_type(4) * s2 + s; + typename genType::value_type f4 = s3 - s2; + + return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) / typename genType::value_type(2); + + } + + template + GLM_FUNC_QUALIFIER genType hermite + ( + genType const& v1, + genType const& t1, + genType const& v2, + genType const& t2, + typename genType::value_type const& s + ) + { + typename genType::value_type s2 = pow2(s); + typename genType::value_type s3 = pow3(s); + + typename genType::value_type f1 = typename genType::value_type(2) * s3 - typename genType::value_type(3) * s2 + typename genType::value_type(1); + typename genType::value_type f2 = typename genType::value_type(-2) * s3 + typename genType::value_type(3) * s2; + typename genType::value_type f3 = s3 - typename genType::value_type(2) * s2 + s; + typename genType::value_type f4 = s3 - s2; + + return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2; + } + + template + GLM_FUNC_QUALIFIER genType cubic + ( + genType const& v1, + genType const& v2, + genType const& v3, + genType const& v4, + typename genType::value_type const& s + ) + { + return ((v1 * s + v2) * s + v3) * s + v4; + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/std_based_type.hpp b/vendor/glm/glm/gtx/std_based_type.hpp new file mode 100644 index 0000000..cd3be8c --- /dev/null +++ b/vendor/glm/glm/gtx/std_based_type.hpp @@ -0,0 +1,68 @@ +/// @ref gtx_std_based_type +/// @file glm/gtx/std_based_type.hpp +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_std_based_type GLM_GTX_std_based_type +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Adds vector types based on STL value types. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_std_based_type is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_std_based_type extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_std_based_type + /// @{ + + /// Vector type based of one std::size_t component. + /// @see GLM_GTX_std_based_type + typedef vec<1, std::size_t, defaultp> size1; + + /// Vector type based of two std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<2, std::size_t, defaultp> size2; + + /// Vector type based of three std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<3, std::size_t, defaultp> size3; + + /// Vector type based of four std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<4, std::size_t, defaultp> size4; + + /// Vector type based of one std::size_t component. + /// @see GLM_GTX_std_based_type + typedef vec<1, std::size_t, defaultp> size1_t; + + /// Vector type based of two std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<2, std::size_t, defaultp> size2_t; + + /// Vector type based of three std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<3, std::size_t, defaultp> size3_t; + + /// Vector type based of four std::size_t components. + /// @see GLM_GTX_std_based_type + typedef vec<4, std::size_t, defaultp> size4_t; + + /// @} +}//namespace glm + +#include "std_based_type.inl" diff --git a/vendor/glm/glm/gtx/std_based_type.inl b/vendor/glm/glm/gtx/std_based_type.inl new file mode 100644 index 0000000..9c34bdb --- /dev/null +++ b/vendor/glm/glm/gtx/std_based_type.inl @@ -0,0 +1,6 @@ +/// @ref gtx_std_based_type + +namespace glm +{ + +} diff --git a/vendor/glm/glm/gtx/string_cast.hpp b/vendor/glm/glm/gtx/string_cast.hpp new file mode 100644 index 0000000..27846bf --- /dev/null +++ b/vendor/glm/glm/gtx/string_cast.hpp @@ -0,0 +1,52 @@ +/// @ref gtx_string_cast +/// @file glm/gtx/string_cast.hpp +/// +/// @see core (dependence) +/// @see gtx_integer (dependence) +/// @see gtx_quaternion (dependence) +/// +/// @defgroup gtx_string_cast GLM_GTX_string_cast +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Setup strings for GLM type values +/// +/// This extension is not supported with CUDA + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" +#include +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_string_cast is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_string_cast extension included") +# endif +#endif + +#if(GLM_COMPILER & GLM_COMPILER_CUDA) +# error "GLM_GTX_string_cast is not supported on CUDA compiler" +#endif + +namespace glm +{ + /// @addtogroup gtx_string_cast + /// @{ + + /// Create a string from a GLM vector or matrix typed variable. + /// @see gtx_string_cast extension. + template + GLM_FUNC_DECL std::string to_string(genType const& x); + + /// @} +}//namespace glm + +#include "string_cast.inl" diff --git a/vendor/glm/glm/gtx/string_cast.inl b/vendor/glm/glm/gtx/string_cast.inl new file mode 100644 index 0000000..f67751d --- /dev/null +++ b/vendor/glm/glm/gtx/string_cast.inl @@ -0,0 +1,492 @@ +/// @ref gtx_string_cast + +#include +#include + +namespace glm{ +namespace detail +{ + template + struct cast + { + typedef T value_type; + }; + + template <> + struct cast + { + typedef double value_type; + }; + + GLM_FUNC_QUALIFIER std::string format(const char* msg, ...) + { + std::size_t const STRING_BUFFER(4096); + char text[STRING_BUFFER]; + va_list list; + + if(msg == GLM_NULLPTR) + return std::string(); + + va_start(list, msg); +# if (GLM_COMPILER & GLM_COMPILER_VC) + vsprintf_s(text, STRING_BUFFER, msg, list); +# else// + std::vsprintf(text, msg, list); +# endif// + va_end(list); + + return std::string(text); + } + + static const char* LabelTrue = "true"; + static const char* LabelFalse = "false"; + + template + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%d";} + }; + + template + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%f";} + }; + +# if GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + template<> + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";} + }; + + template<> + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";} + }; +# endif//GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + + template + struct prefix{}; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "d";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "b";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u8";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i8";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u16";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i16";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "u64";} + }; + + template<> + struct prefix + { + GLM_FUNC_QUALIFIER static char const * value() {return "i64";} + }; + + template + struct compute_to_string + {}; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<1, bool, Q> const& x) + { + return detail::format("bvec1(%s)", + x[0] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<2, bool, Q> const& x) + { + return detail::format("bvec2(%s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<3, bool, Q> const& x) + { + return detail::format("bvec3(%s, %s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse, + x[2] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<4, bool, Q> const& x) + { + return detail::format("bvec4(%s, %s, %s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse, + x[2] ? detail::LabelTrue : detail::LabelFalse, + x[3] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<1, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec1(%s)", + PrefixStr, + LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec2(%s, %s)", + PrefixStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0]), + static_cast::value_type>(x[1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec3(%s, %s, %s)", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0]), + static_cast::value_type>(x[1]), + static_cast::value_type>(x[2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(vec<4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%svec4(%s, %s, %s, %s)", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0]), + static_cast::value_type>(x[1]), + static_cast::value_type>(x[2]), + static_cast::value_type>(x[3])); + } + }; + + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x2((%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x3((%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<2, 4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x4((%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), static_cast::value_type>(x[0][3]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), static_cast::value_type>(x[1][3])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x2((%s, %s), (%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<3, 4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), static_cast::value_type>(x[0][3]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), static_cast::value_type>(x[1][3]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2]), static_cast::value_type>(x[2][3])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 2, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x2((%s, %s), (%s, %s), (%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), + static_cast::value_type>(x[3][0]), static_cast::value_type>(x[3][1])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 3, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2]), + static_cast::value_type>(x[3][0]), static_cast::value_type>(x[3][1]), static_cast::value_type>(x[3][2])); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(mat<4, 4, T, Q> const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x[0][0]), static_cast::value_type>(x[0][1]), static_cast::value_type>(x[0][2]), static_cast::value_type>(x[0][3]), + static_cast::value_type>(x[1][0]), static_cast::value_type>(x[1][1]), static_cast::value_type>(x[1][2]), static_cast::value_type>(x[1][3]), + static_cast::value_type>(x[2][0]), static_cast::value_type>(x[2][1]), static_cast::value_type>(x[2][2]), static_cast::value_type>(x[2][3]), + static_cast::value_type>(x[3][0]), static_cast::value_type>(x[3][1]), static_cast::value_type>(x[3][2]), static_cast::value_type>(x[3][3])); + } + }; + + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(qua const& q) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%squat(%s, {%s, %s, %s})", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(q.w), + static_cast::value_type>(q.x), + static_cast::value_type>(q.y), + static_cast::value_type>(q.z)); + } + }; + + template + struct compute_to_string > + { + GLM_FUNC_QUALIFIER static std::string call(tdualquat const& x) + { + char const * PrefixStr = prefix::value(); + char const * LiteralStr = literal::is_iec559>::value(); + std::string FormatStr(detail::format("%sdualquat((%s, {%s, %s, %s}), (%s, {%s, %s, %s}))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + static_cast::value_type>(x.real.w), + static_cast::value_type>(x.real.x), + static_cast::value_type>(x.real.y), + static_cast::value_type>(x.real.z), + static_cast::value_type>(x.dual.w), + static_cast::value_type>(x.dual.x), + static_cast::value_type>(x.dual.y), + static_cast::value_type>(x.dual.z)); + } + }; + +}//namespace detail + +template +GLM_FUNC_QUALIFIER std::string to_string(matType const& x) +{ + return detail::compute_to_string::call(x); +} + +}//namespace glm diff --git a/vendor/glm/glm/gtx/texture.hpp b/vendor/glm/glm/gtx/texture.hpp new file mode 100644 index 0000000..20585e6 --- /dev/null +++ b/vendor/glm/glm/gtx/texture.hpp @@ -0,0 +1,46 @@ +/// @ref gtx_texture +/// @file glm/gtx/texture.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_texture GLM_GTX_texture +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Wrapping mode of texture coordinates. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/integer.hpp" +#include "../gtx/component_wise.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_texture is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_texture extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_texture + /// @{ + + /// Compute the number of mipmaps levels necessary to create a mipmap complete texture + /// + /// @param Extent Extent of the texture base level mipmap + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + template + T levels(vec const& Extent); + + /// @} +}// namespace glm + +#include "texture.inl" + diff --git a/vendor/glm/glm/gtx/texture.inl b/vendor/glm/glm/gtx/texture.inl new file mode 100644 index 0000000..593c826 --- /dev/null +++ b/vendor/glm/glm/gtx/texture.inl @@ -0,0 +1,17 @@ +/// @ref gtx_texture + +namespace glm +{ + template + inline T levels(vec const& Extent) + { + return glm::log2(compMax(Extent)) + static_cast(1); + } + + template + inline T levels(T Extent) + { + return vec<1, T, defaultp>(Extent).x; + } +}//namespace glm + diff --git a/vendor/glm/glm/gtx/transform.hpp b/vendor/glm/glm/gtx/transform.hpp new file mode 100644 index 0000000..0279fc8 --- /dev/null +++ b/vendor/glm/glm/gtx/transform.hpp @@ -0,0 +1,60 @@ +/// @ref gtx_transform +/// @file glm/gtx/transform.hpp +/// +/// @see core (dependence) +/// @see gtc_matrix_transform (dependence) +/// @see gtx_transform +/// @see gtx_transform2 +/// +/// @defgroup gtx_transform GLM_GTX_transform +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add transformation matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/matrix_transform.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_transform is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_transform extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_transform + /// @{ + + /// Transforms a matrix with a translation 4 * 4 matrix created from 3 scalars. + /// @see gtc_matrix_transform + /// @see gtx_transform + template + GLM_FUNC_DECL mat<4, 4, T, Q> translate( + vec<3, T, Q> const& v); + + /// Builds a rotation 4 * 4 matrix created from an axis of 3 scalars and an angle expressed in radians. + /// @see gtc_matrix_transform + /// @see gtx_transform + template + GLM_FUNC_DECL mat<4, 4, T, Q> rotate( + T angle, + vec<3, T, Q> const& v); + + /// Transforms a matrix with a scale 4 * 4 matrix created from a vector of 3 components. + /// @see gtc_matrix_transform + /// @see gtx_transform + template + GLM_FUNC_DECL mat<4, 4, T, Q> scale( + vec<3, T, Q> const& v); + + /// @} +}// namespace glm + +#include "transform.inl" diff --git a/vendor/glm/glm/gtx/transform.inl b/vendor/glm/glm/gtx/transform.inl new file mode 100644 index 0000000..48ee680 --- /dev/null +++ b/vendor/glm/glm/gtx/transform.inl @@ -0,0 +1,23 @@ +/// @ref gtx_transform + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> translate(vec<3, T, Q> const& v) + { + return translate(mat<4, 4, T, Q>(static_cast(1)), v); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> rotate(T angle, vec<3, T, Q> const& v) + { + return rotate(mat<4, 4, T, Q>(static_cast(1)), angle, v); + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scale(vec<3, T, Q> const& v) + { + return scale(mat<4, 4, T, Q>(static_cast(1)), v); + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/transform2.hpp b/vendor/glm/glm/gtx/transform2.hpp new file mode 100644 index 0000000..0d8ba9d --- /dev/null +++ b/vendor/glm/glm/gtx/transform2.hpp @@ -0,0 +1,89 @@ +/// @ref gtx_transform2 +/// @file glm/gtx/transform2.hpp +/// +/// @see core (dependence) +/// @see gtx_transform (dependence) +/// +/// @defgroup gtx_transform2 GLM_GTX_transform2 +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Add extra transformation matrices + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/transform.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_transform2 is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_transform2 extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_transform2 + /// @{ + + //! Transforms a matrix with a shearing on X axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> shearX2D(mat<3, 3, T, Q> const& m, T y); + + //! Transforms a matrix with a shearing on Y axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> shearY2D(mat<3, 3, T, Q> const& m, T x); + + //! Transforms a matrix with a shearing on X axis + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> shearX3D(mat<4, 4, T, Q> const& m, T y, T z); + + //! Transforms a matrix with a shearing on Y axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> shearY3D(mat<4, 4, T, Q> const& m, T x, T z); + + //! Transforms a matrix with a shearing on Z axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> shearZ3D(mat<4, 4, T, Q> const& m, T x, T y); + + //template GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shear(const mat<4, 4, T, Q> & m, shearPlane, planePoint, angle) + // Identity + tan(angle) * cross(Normal, OnPlaneVector) 0 + // - dot(PointOnPlane, normal) * OnPlaneVector 1 + + // Reflect functions seem to don't work + //template mat<3, 3, T, Q> reflect2D(const mat<3, 3, T, Q> & m, const vec<3, T, Q>& normal){return reflect2DGTX(m, normal);} //!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension) + //template mat<4, 4, T, Q> reflect3D(const mat<4, 4, T, Q> & m, const vec<3, T, Q>& normal){return reflect3DGTX(m, normal);} //!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension) + + //! Build planar projection matrix along normal axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<3, 3, T, Q> proj2D(mat<3, 3, T, Q> const& m, vec<3, T, Q> const& normal); + + //! Build planar projection matrix along normal axis. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> proj3D(mat<4, 4, T, Q> const & m, vec<3, T, Q> const& normal); + + //! Build a scale bias matrix. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> scaleBias(T scale, T bias); + + //! Build a scale bias matrix. + //! From GLM_GTX_transform2 extension. + template + GLM_FUNC_DECL mat<4, 4, T, Q> scaleBias(mat<4, 4, T, Q> const& m, T scale, T bias); + + /// @} +}// namespace glm + +#include "transform2.inl" diff --git a/vendor/glm/glm/gtx/transform2.inl b/vendor/glm/glm/gtx/transform2.inl new file mode 100644 index 0000000..2b53198 --- /dev/null +++ b/vendor/glm/glm/gtx/transform2.inl @@ -0,0 +1,125 @@ +/// @ref gtx_transform2 + +namespace glm +{ + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearX2D(mat<3, 3, T, Q> const& m, T s) + { + mat<3, 3, T, Q> r(1); + r[1][0] = s; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> shearY2D(mat<3, 3, T, Q> const& m, T s) + { + mat<3, 3, T, Q> r(1); + r[0][1] = s; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shearX3D(mat<4, 4, T, Q> const& m, T s, T t) + { + mat<4, 4, T, Q> r(1); + r[0][1] = s; + r[0][2] = t; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shearY3D(mat<4, 4, T, Q> const& m, T s, T t) + { + mat<4, 4, T, Q> r(1); + r[1][0] = s; + r[1][2] = t; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shearZ3D(mat<4, 4, T, Q> const& m, T s, T t) + { + mat<4, 4, T, Q> r(1); + r[2][0] = s; + r[2][1] = t; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> reflect2D(mat<3, 3, T, Q> const& m, vec<3, T, Q> const& normal) + { + mat<3, 3, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - static_cast(2) * normal.x * normal.x; + r[0][1] = -static_cast(2) * normal.x * normal.y; + r[1][0] = -static_cast(2) * normal.x * normal.y; + r[1][1] = static_cast(1) - static_cast(2) * normal.y * normal.y; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> reflect3D(mat<4, 4, T, Q> const& m, vec<3, T, Q> const& normal) + { + mat<4, 4, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - static_cast(2) * normal.x * normal.x; + r[0][1] = -static_cast(2) * normal.x * normal.y; + r[0][2] = -static_cast(2) * normal.x * normal.z; + + r[1][0] = -static_cast(2) * normal.x * normal.y; + r[1][1] = static_cast(1) - static_cast(2) * normal.y * normal.y; + r[1][2] = -static_cast(2) * normal.y * normal.z; + + r[2][0] = -static_cast(2) * normal.x * normal.z; + r[2][1] = -static_cast(2) * normal.y * normal.z; + r[2][2] = static_cast(1) - static_cast(2) * normal.z * normal.z; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<3, 3, T, Q> proj2D( + const mat<3, 3, T, Q>& m, + const vec<3, T, Q>& normal) + { + mat<3, 3, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - normal.x * normal.x; + r[0][1] = - normal.x * normal.y; + r[1][0] = - normal.x * normal.y; + r[1][1] = static_cast(1) - normal.y * normal.y; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> proj3D( + const mat<4, 4, T, Q>& m, + const vec<3, T, Q>& normal) + { + mat<4, 4, T, Q> r(static_cast(1)); + r[0][0] = static_cast(1) - normal.x * normal.x; + r[0][1] = - normal.x * normal.y; + r[0][2] = - normal.x * normal.z; + r[1][0] = - normal.x * normal.y; + r[1][1] = static_cast(1) - normal.y * normal.y; + r[1][2] = - normal.y * normal.z; + r[2][0] = - normal.x * normal.z; + r[2][1] = - normal.y * normal.z; + r[2][2] = static_cast(1) - normal.z * normal.z; + return m * r; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scaleBias(T scale, T bias) + { + mat<4, 4, T, Q> result; + result[3] = vec<4, T, Q>(vec<3, T, Q>(bias), static_cast(1)); + result[0][0] = scale; + result[1][1] = scale; + result[2][2] = scale; + return result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> scaleBias(mat<4, 4, T, Q> const& m, T scale, T bias) + { + return m * scaleBias(scale, bias); + } +}//namespace glm + diff --git a/vendor/glm/glm/gtx/type_aligned.hpp b/vendor/glm/glm/gtx/type_aligned.hpp new file mode 100644 index 0000000..2ae522c --- /dev/null +++ b/vendor/glm/glm/gtx/type_aligned.hpp @@ -0,0 +1,982 @@ +/// @ref gtx_type_aligned +/// @file glm/gtx/type_aligned.hpp +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_type_aligned GLM_GTX_type_aligned +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines aligned types. + +#pragma once + +// Dependency: +#include "../gtc/type_precision.hpp" +#include "../gtc/quaternion.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_type_aligned is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_type_aligned extension included") +# endif +#endif + +namespace glm +{ + /////////////////////////// + // Signed int vector types + + /// @addtogroup gtx_type_aligned + /// @{ + + /// Low qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int8, aligned_lowp_int8, 1); + + /// Low qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int16, aligned_lowp_int16, 2); + + /// Low qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int32, aligned_lowp_int32, 4); + + /// Low qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int64, aligned_lowp_int64, 8); + + + /// Low qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int8_t, aligned_lowp_int8_t, 1); + + /// Low qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int16_t, aligned_lowp_int16_t, 2); + + /// Low qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int32_t, aligned_lowp_int32_t, 4); + + /// Low qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int64_t, aligned_lowp_int64_t, 8); + + + /// Low qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i8, aligned_lowp_i8, 1); + + /// Low qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i16, aligned_lowp_i16, 2); + + /// Low qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i32, aligned_lowp_i32, 4); + + /// Low qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i64, aligned_lowp_i64, 8); + + + /// Medium qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int8, aligned_mediump_int8, 1); + + /// Medium qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int16, aligned_mediump_int16, 2); + + /// Medium qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int32, aligned_mediump_int32, 4); + + /// Medium qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int64, aligned_mediump_int64, 8); + + + /// Medium qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int8_t, aligned_mediump_int8_t, 1); + + /// Medium qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int16_t, aligned_mediump_int16_t, 2); + + /// Medium qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int32_t, aligned_mediump_int32_t, 4); + + /// Medium qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int64_t, aligned_mediump_int64_t, 8); + + + /// Medium qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i8, aligned_mediump_i8, 1); + + /// Medium qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i16, aligned_mediump_i16, 2); + + /// Medium qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i32, aligned_mediump_i32, 4); + + /// Medium qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i64, aligned_mediump_i64, 8); + + + /// High qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int8, aligned_highp_int8, 1); + + /// High qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int16, aligned_highp_int16, 2); + + /// High qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int32, aligned_highp_int32, 4); + + /// High qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int64, aligned_highp_int64, 8); + + + /// High qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int8_t, aligned_highp_int8_t, 1); + + /// High qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int16_t, aligned_highp_int16_t, 2); + + /// High qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int32_t, aligned_highp_int32_t, 4); + + /// High qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int64_t, aligned_highp_int64_t, 8); + + + /// High qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i8, aligned_highp_i8, 1); + + /// High qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i16, aligned_highp_i16, 2); + + /// High qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i32, aligned_highp_i32, 4); + + /// High qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i64, aligned_highp_i64, 8); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int8, aligned_int8, 1); + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int16, aligned_int16, 2); + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int32, aligned_int32, 4); + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int64, aligned_int64, 8); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int8_t, aligned_int8_t, 1); + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int16_t, aligned_int16_t, 2); + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int32_t, aligned_int32_t, 4); + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int64_t, aligned_int64_t, 8); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8, aligned_i8, 1); + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16, aligned_i16, 2); + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32, aligned_i32, 4); + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64, aligned_i64, 8); + + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec1, aligned_ivec1, 4); + + /// Default qualifier 32 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec2, aligned_ivec2, 8); + + /// Default qualifier 32 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec3, aligned_ivec3, 16); + + /// Default qualifier 32 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec4, aligned_ivec4, 16); + + + /// Default qualifier 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec1, aligned_i8vec1, 1); + + /// Default qualifier 8 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec2, aligned_i8vec2, 2); + + /// Default qualifier 8 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec3, aligned_i8vec3, 4); + + /// Default qualifier 8 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec4, aligned_i8vec4, 4); + + + /// Default qualifier 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec1, aligned_i16vec1, 2); + + /// Default qualifier 16 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec2, aligned_i16vec2, 4); + + /// Default qualifier 16 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec3, aligned_i16vec3, 8); + + /// Default qualifier 16 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec4, aligned_i16vec4, 8); + + + /// Default qualifier 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec1, aligned_i32vec1, 4); + + /// Default qualifier 32 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec2, aligned_i32vec2, 8); + + /// Default qualifier 32 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec3, aligned_i32vec3, 16); + + /// Default qualifier 32 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec4, aligned_i32vec4, 16); + + + /// Default qualifier 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec1, aligned_i64vec1, 8); + + /// Default qualifier 64 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec2, aligned_i64vec2, 16); + + /// Default qualifier 64 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec3, aligned_i64vec3, 32); + + /// Default qualifier 64 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec4, aligned_i64vec4, 32); + + + ///////////////////////////// + // Unsigned int vector types + + /// Low qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint8, aligned_lowp_uint8, 1); + + /// Low qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint16, aligned_lowp_uint16, 2); + + /// Low qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint32, aligned_lowp_uint32, 4); + + /// Low qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint64, aligned_lowp_uint64, 8); + + + /// Low qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint8_t, aligned_lowp_uint8_t, 1); + + /// Low qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint16_t, aligned_lowp_uint16_t, 2); + + /// Low qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint32_t, aligned_lowp_uint32_t, 4); + + /// Low qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint64_t, aligned_lowp_uint64_t, 8); + + + /// Low qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u8, aligned_lowp_u8, 1); + + /// Low qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u16, aligned_lowp_u16, 2); + + /// Low qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u32, aligned_lowp_u32, 4); + + /// Low qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u64, aligned_lowp_u64, 8); + + + /// Medium qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint8, aligned_mediump_uint8, 1); + + /// Medium qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint16, aligned_mediump_uint16, 2); + + /// Medium qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint32, aligned_mediump_uint32, 4); + + /// Medium qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint64, aligned_mediump_uint64, 8); + + + /// Medium qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint8_t, aligned_mediump_uint8_t, 1); + + /// Medium qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint16_t, aligned_mediump_uint16_t, 2); + + /// Medium qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint32_t, aligned_mediump_uint32_t, 4); + + /// Medium qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint64_t, aligned_mediump_uint64_t, 8); + + + /// Medium qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u8, aligned_mediump_u8, 1); + + /// Medium qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u16, aligned_mediump_u16, 2); + + /// Medium qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u32, aligned_mediump_u32, 4); + + /// Medium qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u64, aligned_mediump_u64, 8); + + + /// High qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint8, aligned_highp_uint8, 1); + + /// High qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint16, aligned_highp_uint16, 2); + + /// High qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint32, aligned_highp_uint32, 4); + + /// High qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint64, aligned_highp_uint64, 8); + + + /// High qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint8_t, aligned_highp_uint8_t, 1); + + /// High qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint16_t, aligned_highp_uint16_t, 2); + + /// High qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint32_t, aligned_highp_uint32_t, 4); + + /// High qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint64_t, aligned_highp_uint64_t, 8); + + + /// High qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u8, aligned_highp_u8, 1); + + /// High qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u16, aligned_highp_u16, 2); + + /// High qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u32, aligned_highp_u32, 4); + + /// High qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u64, aligned_highp_u64, 8); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint8, aligned_uint8, 1); + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint16, aligned_uint16, 2); + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint32, aligned_uint32, 4); + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint64, aligned_uint64, 8); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint8_t, aligned_uint8_t, 1); + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint16_t, aligned_uint16_t, 2); + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint32_t, aligned_uint32_t, 4); + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint64_t, aligned_uint64_t, 8); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8, aligned_u8, 1); + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16, aligned_u16, 2); + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32, aligned_u32, 4); + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64, aligned_u64, 8); + + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec1, aligned_uvec1, 4); + + /// Default qualifier 32 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec2, aligned_uvec2, 8); + + /// Default qualifier 32 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec3, aligned_uvec3, 16); + + /// Default qualifier 32 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec4, aligned_uvec4, 16); + + + /// Default qualifier 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec1, aligned_u8vec1, 1); + + /// Default qualifier 8 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec2, aligned_u8vec2, 2); + + /// Default qualifier 8 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec3, aligned_u8vec3, 4); + + /// Default qualifier 8 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec4, aligned_u8vec4, 4); + + + /// Default qualifier 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec1, aligned_u16vec1, 2); + + /// Default qualifier 16 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec2, aligned_u16vec2, 4); + + /// Default qualifier 16 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec3, aligned_u16vec3, 8); + + /// Default qualifier 16 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec4, aligned_u16vec4, 8); + + + /// Default qualifier 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec1, aligned_u32vec1, 4); + + /// Default qualifier 32 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec2, aligned_u32vec2, 8); + + /// Default qualifier 32 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec3, aligned_u32vec3, 16); + + /// Default qualifier 32 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec4, aligned_u32vec4, 16); + + + /// Default qualifier 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec1, aligned_u64vec1, 8); + + /// Default qualifier 64 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec2, aligned_u64vec2, 16); + + /// Default qualifier 64 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec3, aligned_u64vec3, 32); + + /// Default qualifier 64 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec4, aligned_u64vec4, 32); + + + ////////////////////// + // Float vector types + + /// 32 bit single-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32, aligned_float32, 4); + + /// 32 bit single-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32_t, aligned_float32_t, 4); + + /// 32 bit single-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32, aligned_f32, 4); + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// 64 bit double-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64, aligned_float64, 8); + + /// 64 bit double-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64_t, aligned_float64_t, 8); + + /// 64 bit double-qualifier floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64, aligned_f64, 8); + +# endif//GLM_FORCE_SINGLE_ONLY + + + /// Single-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec1, aligned_vec1, 4); + + /// Single-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec2, aligned_vec2, 8); + + /// Single-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec3, aligned_vec3, 16); + + /// Single-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec4, aligned_vec4, 16); + + + /// Single-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec1, aligned_fvec1, 4); + + /// Single-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec2, aligned_fvec2, 8); + + /// Single-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec3, aligned_fvec3, 16); + + /// Single-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec4, aligned_fvec4, 16); + + + /// Single-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec1, aligned_f32vec1, 4); + + /// Single-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec2, aligned_f32vec2, 8); + + /// Single-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec3, aligned_f32vec3, 16); + + /// Single-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec4, aligned_f32vec4, 16); + + + /// Double-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec1, aligned_dvec1, 8); + + /// Double-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec2, aligned_dvec2, 16); + + /// Double-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec3, aligned_dvec3, 32); + + /// Double-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec4, aligned_dvec4, 32); + + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec1, aligned_f64vec1, 8); + + /// Double-qualifier floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec2, aligned_f64vec2, 16); + + /// Double-qualifier floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec3, aligned_f64vec3, 32); + + /// Double-qualifier floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec4, aligned_f64vec4, 32); + +# endif//GLM_FORCE_SINGLE_ONLY + + ////////////////////// + // Float matrix types + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1 mat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat2, aligned_mat2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat3, aligned_mat3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat4, aligned_mat4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 mat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat2x2, aligned_mat2x2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat3x3, aligned_mat3x3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat4x4, aligned_mat4x4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 fmat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x2, aligned_fmat2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x3, aligned_fmat3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x4, aligned_fmat4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f32 fmat1x1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x2, aligned_fmat2x2, 16); + + /// Single-qualifier floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x3, aligned_fmat2x3, 16); + + /// Single-qualifier floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x4, aligned_fmat2x4, 16); + + /// Single-qualifier floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x2, aligned_fmat3x2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x3, aligned_fmat3x3, 16); + + /// Single-qualifier floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x4, aligned_fmat3x4, 16); + + /// Single-qualifier floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x2, aligned_fmat4x2, 16); + + /// Single-qualifier floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x3, aligned_fmat4x3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x4, aligned_fmat4x4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 f32mat1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x2, aligned_f32mat2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x3, aligned_f32mat3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x4, aligned_f32mat4, 16); + + + /// Single-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f32 f32mat1x1; + + /// Single-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x2, aligned_f32mat2x2, 16); + + /// Single-qualifier floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x3, aligned_f32mat2x3, 16); + + /// Single-qualifier floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x4, aligned_f32mat2x4, 16); + + /// Single-qualifier floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x2, aligned_f32mat3x2, 16); + + /// Single-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x3, aligned_f32mat3x3, 16); + + /// Single-qualifier floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x4, aligned_f32mat3x4, 16); + + /// Single-qualifier floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x2, aligned_f32mat4x2, 16); + + /// Single-qualifier floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x3, aligned_f32mat4x3, 16); + + /// Single-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x4, aligned_f32mat4x4, 16); + + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1 f64mat1; + + /// Double-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x2, aligned_f64mat2, 32); + + /// Double-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x3, aligned_f64mat3, 32); + + /// Double-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x4, aligned_f64mat4, 32); + + + /// Double-qualifier floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f64 f64mat1x1; + + /// Double-qualifier floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x2, aligned_f64mat2x2, 32); + + /// Double-qualifier floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x3, aligned_f64mat2x3, 32); + + /// Double-qualifier floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x4, aligned_f64mat2x4, 32); + + /// Double-qualifier floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x2, aligned_f64mat3x2, 32); + + /// Double-qualifier floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x3, aligned_f64mat3x3, 32); + + /// Double-qualifier floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x4, aligned_f64mat3x4, 32); + + /// Double-qualifier floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x2, aligned_f64mat4x2, 32); + + /// Double-qualifier floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x3, aligned_f64mat4x3, 32); + + /// Double-qualifier floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x4, aligned_f64mat4x4, 32); + +# endif//GLM_FORCE_SINGLE_ONLY + + + ////////////////////////// + // Quaternion types + + /// Single-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(quat, aligned_quat, 16); + + /// Single-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(quat, aligned_fquat, 16); + + /// Double-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dquat, aligned_dquat, 32); + + /// Single-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32quat, aligned_f32quat, 16); + +# ifndef GLM_FORCE_SINGLE_ONLY + + /// Double-qualifier floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64quat, aligned_f64quat, 32); + +# endif//GLM_FORCE_SINGLE_ONLY + + /// @} +}//namespace glm + +#include "type_aligned.inl" diff --git a/vendor/glm/glm/gtx/type_aligned.inl b/vendor/glm/glm/gtx/type_aligned.inl new file mode 100644 index 0000000..54c1b81 --- /dev/null +++ b/vendor/glm/glm/gtx/type_aligned.inl @@ -0,0 +1,6 @@ +/// @ref gtc_type_aligned + +namespace glm +{ + +} diff --git a/vendor/glm/glm/gtx/type_trait.hpp b/vendor/glm/glm/gtx/type_trait.hpp new file mode 100644 index 0000000..56685c8 --- /dev/null +++ b/vendor/glm/glm/gtx/type_trait.hpp @@ -0,0 +1,85 @@ +/// @ref gtx_type_trait +/// @file glm/gtx/type_trait.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_type_trait GLM_GTX_type_trait +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Defines traits for each type. + +#pragma once + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_type_trait is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_type_trait extension included") +# endif +#endif + +// Dependency: +#include "../detail/qualifier.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" + +namespace glm +{ + /// @addtogroup gtx_type_trait + /// @{ + + template + struct type + { + static bool const is_vec = false; + static bool const is_mat = false; + static bool const is_quat = false; + static length_t const components = 0; + static length_t const cols = 0; + static length_t const rows = 0; + }; + + template + struct type > + { + static bool const is_vec = true; + static bool const is_mat = false; + static bool const is_quat = false; + static length_t const components = L; + }; + + template + struct type > + { + static bool const is_vec = false; + static bool const is_mat = true; + static bool const is_quat = false; + static length_t const components = C; + static length_t const cols = C; + static length_t const rows = R; + }; + + template + struct type > + { + static bool const is_vec = false; + static bool const is_mat = false; + static bool const is_quat = true; + static length_t const components = 4; + }; + + template + struct type > + { + static bool const is_vec = false; + static bool const is_mat = false; + static bool const is_quat = true; + static length_t const components = 8; + }; + + /// @} +}//namespace glm + +#include "type_trait.inl" diff --git a/vendor/glm/glm/gtx/type_trait.inl b/vendor/glm/glm/gtx/type_trait.inl new file mode 100644 index 0000000..045de95 --- /dev/null +++ b/vendor/glm/glm/gtx/type_trait.inl @@ -0,0 +1,61 @@ +/// @ref gtx_type_trait + +namespace glm +{ + template + bool const type::is_vec; + template + bool const type::is_mat; + template + bool const type::is_quat; + template + length_t const type::components; + template + length_t const type::cols; + template + length_t const type::rows; + + // vec + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; + + // mat + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; + template + length_t const type >::cols; + template + length_t const type >::rows; + + // tquat + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; + + // tdualquat + template + bool const type >::is_vec; + template + bool const type >::is_mat; + template + bool const type >::is_quat; + template + length_t const type >::components; +}//namespace glm diff --git a/vendor/glm/glm/gtx/vec_swizzle.hpp b/vendor/glm/glm/gtx/vec_swizzle.hpp new file mode 100644 index 0000000..1c49abc --- /dev/null +++ b/vendor/glm/glm/gtx/vec_swizzle.hpp @@ -0,0 +1,2782 @@ +/// @ref gtx_vec_swizzle +/// @file glm/gtx/vec_swizzle.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_vec_swizzle GLM_GTX_vec_swizzle +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Functions to perform swizzle operation. + +#pragma once + +#include "../glm.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_vec_swizzle is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_vec_swizzle extension included") +# endif +#endif + +namespace glm { + // xx + template + GLM_INLINE glm::vec<2, T, Q> xx(const glm::vec<1, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template + GLM_INLINE glm::vec<2, T, Q> xx(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template + GLM_INLINE glm::vec<2, T, Q> xx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + template + GLM_INLINE glm::vec<2, T, Q> xx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.x); + } + + // xy + template + GLM_INLINE glm::vec<2, T, Q> xy(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + template + GLM_INLINE glm::vec<2, T, Q> xy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + template + GLM_INLINE glm::vec<2, T, Q> xy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.y); + } + + // xz + template + GLM_INLINE glm::vec<2, T, Q> xz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.z); + } + + template + GLM_INLINE glm::vec<2, T, Q> xz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.z); + } + + // xw + template + GLM_INLINE glm::vec<2, T, Q> xw(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.x, v.w); + } + + // yx + template + GLM_INLINE glm::vec<2, T, Q> yx(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + template + GLM_INLINE glm::vec<2, T, Q> yx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + template + GLM_INLINE glm::vec<2, T, Q> yx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.x); + } + + // yy + template + GLM_INLINE glm::vec<2, T, Q> yy(const glm::vec<2, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + template + GLM_INLINE glm::vec<2, T, Q> yy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + template + GLM_INLINE glm::vec<2, T, Q> yy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.y); + } + + // yz + template + GLM_INLINE glm::vec<2, T, Q> yz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.z); + } + + template + GLM_INLINE glm::vec<2, T, Q> yz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.z); + } + + // yw + template + GLM_INLINE glm::vec<2, T, Q> yw(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.y, v.w); + } + + // zx + template + GLM_INLINE glm::vec<2, T, Q> zx(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.x); + } + + template + GLM_INLINE glm::vec<2, T, Q> zx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.x); + } + + // zy + template + GLM_INLINE glm::vec<2, T, Q> zy(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.y); + } + + template + GLM_INLINE glm::vec<2, T, Q> zy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.y); + } + + // zz + template + GLM_INLINE glm::vec<2, T, Q> zz(const glm::vec<3, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.z); + } + + template + GLM_INLINE glm::vec<2, T, Q> zz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.z); + } + + // zw + template + GLM_INLINE glm::vec<2, T, Q> zw(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.z, v.w); + } + + // wx + template + GLM_INLINE glm::vec<2, T, Q> wx(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.x); + } + + // wy + template + GLM_INLINE glm::vec<2, T, Q> wy(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.y); + } + + // wz + template + GLM_INLINE glm::vec<2, T, Q> wz(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.z); + } + + // ww + template + GLM_INLINE glm::vec<2, T, Q> ww(const glm::vec<4, T, Q> &v) { + return glm::vec<2, T, Q>(v.w, v.w); + } + + // xxx + template + GLM_INLINE glm::vec<3, T, Q> xxx(const glm::vec<1, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> xxx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> xxx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> xxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.x); + } + + // xxy + template + GLM_INLINE glm::vec<3, T, Q> xxy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> xxy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> xxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.y); + } + + // xxz + template + GLM_INLINE glm::vec<3, T, Q> xxz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> xxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.z); + } + + // xxw + template + GLM_INLINE glm::vec<3, T, Q> xxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.x, v.w); + } + + // xyx + template + GLM_INLINE glm::vec<3, T, Q> xyx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> xyx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> xyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.x); + } + + // xyy + template + GLM_INLINE glm::vec<3, T, Q> xyy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> xyy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> xyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.y); + } + + // xyz + template + GLM_INLINE glm::vec<3, T, Q> xyz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> xyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.z); + } + + // xyw + template + GLM_INLINE glm::vec<3, T, Q> xyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.y, v.w); + } + + // xzx + template + GLM_INLINE glm::vec<3, T, Q> xzx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> xzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.x); + } + + // xzy + template + GLM_INLINE glm::vec<3, T, Q> xzy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> xzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.y); + } + + // xzz + template + GLM_INLINE glm::vec<3, T, Q> xzz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> xzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.z); + } + + // xzw + template + GLM_INLINE glm::vec<3, T, Q> xzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.z, v.w); + } + + // xwx + template + GLM_INLINE glm::vec<3, T, Q> xwx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.x); + } + + // xwy + template + GLM_INLINE glm::vec<3, T, Q> xwy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.y); + } + + // xwz + template + GLM_INLINE glm::vec<3, T, Q> xwz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.z); + } + + // xww + template + GLM_INLINE glm::vec<3, T, Q> xww(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.x, v.w, v.w); + } + + // yxx + template + GLM_INLINE glm::vec<3, T, Q> yxx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> yxx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> yxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.x); + } + + // yxy + template + GLM_INLINE glm::vec<3, T, Q> yxy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> yxy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> yxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.y); + } + + // yxz + template + GLM_INLINE glm::vec<3, T, Q> yxz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> yxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.z); + } + + // yxw + template + GLM_INLINE glm::vec<3, T, Q> yxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.x, v.w); + } + + // yyx + template + GLM_INLINE glm::vec<3, T, Q> yyx(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> yyx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> yyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.x); + } + + // yyy + template + GLM_INLINE glm::vec<3, T, Q> yyy(const glm::vec<2, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> yyy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> yyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.y); + } + + // yyz + template + GLM_INLINE glm::vec<3, T, Q> yyz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> yyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.z); + } + + // yyw + template + GLM_INLINE glm::vec<3, T, Q> yyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.y, v.w); + } + + // yzx + template + GLM_INLINE glm::vec<3, T, Q> yzx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> yzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.x); + } + + // yzy + template + GLM_INLINE glm::vec<3, T, Q> yzy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> yzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.y); + } + + // yzz + template + GLM_INLINE glm::vec<3, T, Q> yzz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> yzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.z); + } + + // yzw + template + GLM_INLINE glm::vec<3, T, Q> yzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.z, v.w); + } + + // ywx + template + GLM_INLINE glm::vec<3, T, Q> ywx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.x); + } + + // ywy + template + GLM_INLINE glm::vec<3, T, Q> ywy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.y); + } + + // ywz + template + GLM_INLINE glm::vec<3, T, Q> ywz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.z); + } + + // yww + template + GLM_INLINE glm::vec<3, T, Q> yww(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.y, v.w, v.w); + } + + // zxx + template + GLM_INLINE glm::vec<3, T, Q> zxx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> zxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.x); + } + + // zxy + template + GLM_INLINE glm::vec<3, T, Q> zxy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> zxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.y); + } + + // zxz + template + GLM_INLINE glm::vec<3, T, Q> zxz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> zxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.z); + } + + // zxw + template + GLM_INLINE glm::vec<3, T, Q> zxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.x, v.w); + } + + // zyx + template + GLM_INLINE glm::vec<3, T, Q> zyx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> zyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.x); + } + + // zyy + template + GLM_INLINE glm::vec<3, T, Q> zyy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> zyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.y); + } + + // zyz + template + GLM_INLINE glm::vec<3, T, Q> zyz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> zyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.z); + } + + // zyw + template + GLM_INLINE glm::vec<3, T, Q> zyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.y, v.w); + } + + // zzx + template + GLM_INLINE glm::vec<3, T, Q> zzx(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.x); + } + + template + GLM_INLINE glm::vec<3, T, Q> zzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.x); + } + + // zzy + template + GLM_INLINE glm::vec<3, T, Q> zzy(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.y); + } + + template + GLM_INLINE glm::vec<3, T, Q> zzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.y); + } + + // zzz + template + GLM_INLINE glm::vec<3, T, Q> zzz(const glm::vec<3, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.z); + } + + template + GLM_INLINE glm::vec<3, T, Q> zzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.z); + } + + // zzw + template + GLM_INLINE glm::vec<3, T, Q> zzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.z, v.w); + } + + // zwx + template + GLM_INLINE glm::vec<3, T, Q> zwx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.x); + } + + // zwy + template + GLM_INLINE glm::vec<3, T, Q> zwy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.y); + } + + // zwz + template + GLM_INLINE glm::vec<3, T, Q> zwz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.z); + } + + // zww + template + GLM_INLINE glm::vec<3, T, Q> zww(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.z, v.w, v.w); + } + + // wxx + template + GLM_INLINE glm::vec<3, T, Q> wxx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.x); + } + + // wxy + template + GLM_INLINE glm::vec<3, T, Q> wxy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.y); + } + + // wxz + template + GLM_INLINE glm::vec<3, T, Q> wxz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.z); + } + + // wxw + template + GLM_INLINE glm::vec<3, T, Q> wxw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.x, v.w); + } + + // wyx + template + GLM_INLINE glm::vec<3, T, Q> wyx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.x); + } + + // wyy + template + GLM_INLINE glm::vec<3, T, Q> wyy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.y); + } + + // wyz + template + GLM_INLINE glm::vec<3, T, Q> wyz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.z); + } + + // wyw + template + GLM_INLINE glm::vec<3, T, Q> wyw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.y, v.w); + } + + // wzx + template + GLM_INLINE glm::vec<3, T, Q> wzx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.x); + } + + // wzy + template + GLM_INLINE glm::vec<3, T, Q> wzy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.y); + } + + // wzz + template + GLM_INLINE glm::vec<3, T, Q> wzz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.z); + } + + // wzw + template + GLM_INLINE glm::vec<3, T, Q> wzw(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.z, v.w); + } + + // wwx + template + GLM_INLINE glm::vec<3, T, Q> wwx(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.x); + } + + // wwy + template + GLM_INLINE glm::vec<3, T, Q> wwy(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.y); + } + + // wwz + template + GLM_INLINE glm::vec<3, T, Q> wwz(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.z); + } + + // www + template + GLM_INLINE glm::vec<3, T, Q> www(const glm::vec<4, T, Q> &v) { + return glm::vec<3, T, Q>(v.w, v.w, v.w); + } + + // xxxx + template + GLM_INLINE glm::vec<4, T, Q> xxxx(const glm::vec<1, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.x); + } + + // xxxy + template + GLM_INLINE glm::vec<4, T, Q> xxxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.y); + } + + // xxxz + template + GLM_INLINE glm::vec<4, T, Q> xxxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.z); + } + + // xxxw + template + GLM_INLINE glm::vec<4, T, Q> xxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.x, v.w); + } + + // xxyx + template + GLM_INLINE glm::vec<4, T, Q> xxyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.x); + } + + // xxyy + template + GLM_INLINE glm::vec<4, T, Q> xxyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.y); + } + + // xxyz + template + GLM_INLINE glm::vec<4, T, Q> xxyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.z); + } + + // xxyw + template + GLM_INLINE glm::vec<4, T, Q> xxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.y, v.w); + } + + // xxzx + template + GLM_INLINE glm::vec<4, T, Q> xxzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.x); + } + + // xxzy + template + GLM_INLINE glm::vec<4, T, Q> xxzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.y); + } + + // xxzz + template + GLM_INLINE glm::vec<4, T, Q> xxzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.z); + } + + // xxzw + template + GLM_INLINE glm::vec<4, T, Q> xxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.z, v.w); + } + + // xxwx + template + GLM_INLINE glm::vec<4, T, Q> xxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.x); + } + + // xxwy + template + GLM_INLINE glm::vec<4, T, Q> xxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.y); + } + + // xxwz + template + GLM_INLINE glm::vec<4, T, Q> xxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.z); + } + + // xxww + template + GLM_INLINE glm::vec<4, T, Q> xxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.x, v.w, v.w); + } + + // xyxx + template + GLM_INLINE glm::vec<4, T, Q> xyxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.x); + } + + // xyxy + template + GLM_INLINE glm::vec<4, T, Q> xyxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.y); + } + + // xyxz + template + GLM_INLINE glm::vec<4, T, Q> xyxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.z); + } + + // xyxw + template + GLM_INLINE glm::vec<4, T, Q> xyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.x, v.w); + } + + // xyyx + template + GLM_INLINE glm::vec<4, T, Q> xyyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.x); + } + + // xyyy + template + GLM_INLINE glm::vec<4, T, Q> xyyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.y); + } + + // xyyz + template + GLM_INLINE glm::vec<4, T, Q> xyyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.z); + } + + // xyyw + template + GLM_INLINE glm::vec<4, T, Q> xyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.y, v.w); + } + + // xyzx + template + GLM_INLINE glm::vec<4, T, Q> xyzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.x); + } + + // xyzy + template + GLM_INLINE glm::vec<4, T, Q> xyzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.y); + } + + // xyzz + template + GLM_INLINE glm::vec<4, T, Q> xyzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.z); + } + + // xyzw + template + GLM_INLINE glm::vec<4, T, Q> xyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.z, v.w); + } + + // xywx + template + GLM_INLINE glm::vec<4, T, Q> xywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.x); + } + + // xywy + template + GLM_INLINE glm::vec<4, T, Q> xywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.y); + } + + // xywz + template + GLM_INLINE glm::vec<4, T, Q> xywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.z); + } + + // xyww + template + GLM_INLINE glm::vec<4, T, Q> xyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.y, v.w, v.w); + } + + // xzxx + template + GLM_INLINE glm::vec<4, T, Q> xzxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.x); + } + + // xzxy + template + GLM_INLINE glm::vec<4, T, Q> xzxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.y); + } + + // xzxz + template + GLM_INLINE glm::vec<4, T, Q> xzxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.z); + } + + // xzxw + template + GLM_INLINE glm::vec<4, T, Q> xzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.x, v.w); + } + + // xzyx + template + GLM_INLINE glm::vec<4, T, Q> xzyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.x); + } + + // xzyy + template + GLM_INLINE glm::vec<4, T, Q> xzyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.y); + } + + // xzyz + template + GLM_INLINE glm::vec<4, T, Q> xzyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.z); + } + + // xzyw + template + GLM_INLINE glm::vec<4, T, Q> xzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.y, v.w); + } + + // xzzx + template + GLM_INLINE glm::vec<4, T, Q> xzzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.x); + } + + // xzzy + template + GLM_INLINE glm::vec<4, T, Q> xzzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.y); + } + + // xzzz + template + GLM_INLINE glm::vec<4, T, Q> xzzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> xzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.z); + } + + // xzzw + template + GLM_INLINE glm::vec<4, T, Q> xzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.z, v.w); + } + + // xzwx + template + GLM_INLINE glm::vec<4, T, Q> xzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.x); + } + + // xzwy + template + GLM_INLINE glm::vec<4, T, Q> xzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.y); + } + + // xzwz + template + GLM_INLINE glm::vec<4, T, Q> xzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.z); + } + + // xzww + template + GLM_INLINE glm::vec<4, T, Q> xzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.z, v.w, v.w); + } + + // xwxx + template + GLM_INLINE glm::vec<4, T, Q> xwxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.x); + } + + // xwxy + template + GLM_INLINE glm::vec<4, T, Q> xwxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.y); + } + + // xwxz + template + GLM_INLINE glm::vec<4, T, Q> xwxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.z); + } + + // xwxw + template + GLM_INLINE glm::vec<4, T, Q> xwxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.x, v.w); + } + + // xwyx + template + GLM_INLINE glm::vec<4, T, Q> xwyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.x); + } + + // xwyy + template + GLM_INLINE glm::vec<4, T, Q> xwyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.y); + } + + // xwyz + template + GLM_INLINE glm::vec<4, T, Q> xwyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.z); + } + + // xwyw + template + GLM_INLINE glm::vec<4, T, Q> xwyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.y, v.w); + } + + // xwzx + template + GLM_INLINE glm::vec<4, T, Q> xwzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.x); + } + + // xwzy + template + GLM_INLINE glm::vec<4, T, Q> xwzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.y); + } + + // xwzz + template + GLM_INLINE glm::vec<4, T, Q> xwzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.z); + } + + // xwzw + template + GLM_INLINE glm::vec<4, T, Q> xwzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.z, v.w); + } + + // xwwx + template + GLM_INLINE glm::vec<4, T, Q> xwwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.x); + } + + // xwwy + template + GLM_INLINE glm::vec<4, T, Q> xwwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.y); + } + + // xwwz + template + GLM_INLINE glm::vec<4, T, Q> xwwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.z); + } + + // xwww + template + GLM_INLINE glm::vec<4, T, Q> xwww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.x, v.w, v.w, v.w); + } + + // yxxx + template + GLM_INLINE glm::vec<4, T, Q> yxxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.x); + } + + // yxxy + template + GLM_INLINE glm::vec<4, T, Q> yxxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.y); + } + + // yxxz + template + GLM_INLINE glm::vec<4, T, Q> yxxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.z); + } + + // yxxw + template + GLM_INLINE glm::vec<4, T, Q> yxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.x, v.w); + } + + // yxyx + template + GLM_INLINE glm::vec<4, T, Q> yxyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.x); + } + + // yxyy + template + GLM_INLINE glm::vec<4, T, Q> yxyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.y); + } + + // yxyz + template + GLM_INLINE glm::vec<4, T, Q> yxyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.z); + } + + // yxyw + template + GLM_INLINE glm::vec<4, T, Q> yxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.y, v.w); + } + + // yxzx + template + GLM_INLINE glm::vec<4, T, Q> yxzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.x); + } + + // yxzy + template + GLM_INLINE glm::vec<4, T, Q> yxzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.y); + } + + // yxzz + template + GLM_INLINE glm::vec<4, T, Q> yxzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.z); + } + + // yxzw + template + GLM_INLINE glm::vec<4, T, Q> yxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.z, v.w); + } + + // yxwx + template + GLM_INLINE glm::vec<4, T, Q> yxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.x); + } + + // yxwy + template + GLM_INLINE glm::vec<4, T, Q> yxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.y); + } + + // yxwz + template + GLM_INLINE glm::vec<4, T, Q> yxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.z); + } + + // yxww + template + GLM_INLINE glm::vec<4, T, Q> yxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.x, v.w, v.w); + } + + // yyxx + template + GLM_INLINE glm::vec<4, T, Q> yyxx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.x); + } + + // yyxy + template + GLM_INLINE glm::vec<4, T, Q> yyxy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.y); + } + + // yyxz + template + GLM_INLINE glm::vec<4, T, Q> yyxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.z); + } + + // yyxw + template + GLM_INLINE glm::vec<4, T, Q> yyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.x, v.w); + } + + // yyyx + template + GLM_INLINE glm::vec<4, T, Q> yyyx(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.x); + } + + // yyyy + template + GLM_INLINE glm::vec<4, T, Q> yyyy(const glm::vec<2, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.y); + } + + // yyyz + template + GLM_INLINE glm::vec<4, T, Q> yyyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.z); + } + + // yyyw + template + GLM_INLINE glm::vec<4, T, Q> yyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.y, v.w); + } + + // yyzx + template + GLM_INLINE glm::vec<4, T, Q> yyzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.x); + } + + // yyzy + template + GLM_INLINE glm::vec<4, T, Q> yyzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.y); + } + + // yyzz + template + GLM_INLINE glm::vec<4, T, Q> yyzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.z); + } + + // yyzw + template + GLM_INLINE glm::vec<4, T, Q> yyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.z, v.w); + } + + // yywx + template + GLM_INLINE glm::vec<4, T, Q> yywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.x); + } + + // yywy + template + GLM_INLINE glm::vec<4, T, Q> yywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.y); + } + + // yywz + template + GLM_INLINE glm::vec<4, T, Q> yywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.z); + } + + // yyww + template + GLM_INLINE glm::vec<4, T, Q> yyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.y, v.w, v.w); + } + + // yzxx + template + GLM_INLINE glm::vec<4, T, Q> yzxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.x); + } + + // yzxy + template + GLM_INLINE glm::vec<4, T, Q> yzxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.y); + } + + // yzxz + template + GLM_INLINE glm::vec<4, T, Q> yzxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.z); + } + + // yzxw + template + GLM_INLINE glm::vec<4, T, Q> yzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.x, v.w); + } + + // yzyx + template + GLM_INLINE glm::vec<4, T, Q> yzyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.x); + } + + // yzyy + template + GLM_INLINE glm::vec<4, T, Q> yzyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.y); + } + + // yzyz + template + GLM_INLINE glm::vec<4, T, Q> yzyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.z); + } + + // yzyw + template + GLM_INLINE glm::vec<4, T, Q> yzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.y, v.w); + } + + // yzzx + template + GLM_INLINE glm::vec<4, T, Q> yzzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.x); + } + + // yzzy + template + GLM_INLINE glm::vec<4, T, Q> yzzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.y); + } + + // yzzz + template + GLM_INLINE glm::vec<4, T, Q> yzzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> yzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.z); + } + + // yzzw + template + GLM_INLINE glm::vec<4, T, Q> yzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.z, v.w); + } + + // yzwx + template + GLM_INLINE glm::vec<4, T, Q> yzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.x); + } + + // yzwy + template + GLM_INLINE glm::vec<4, T, Q> yzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.y); + } + + // yzwz + template + GLM_INLINE glm::vec<4, T, Q> yzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.z); + } + + // yzww + template + GLM_INLINE glm::vec<4, T, Q> yzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.z, v.w, v.w); + } + + // ywxx + template + GLM_INLINE glm::vec<4, T, Q> ywxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.x); + } + + // ywxy + template + GLM_INLINE glm::vec<4, T, Q> ywxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.y); + } + + // ywxz + template + GLM_INLINE glm::vec<4, T, Q> ywxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.z); + } + + // ywxw + template + GLM_INLINE glm::vec<4, T, Q> ywxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.x, v.w); + } + + // ywyx + template + GLM_INLINE glm::vec<4, T, Q> ywyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.x); + } + + // ywyy + template + GLM_INLINE glm::vec<4, T, Q> ywyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.y); + } + + // ywyz + template + GLM_INLINE glm::vec<4, T, Q> ywyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.z); + } + + // ywyw + template + GLM_INLINE glm::vec<4, T, Q> ywyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.y, v.w); + } + + // ywzx + template + GLM_INLINE glm::vec<4, T, Q> ywzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.x); + } + + // ywzy + template + GLM_INLINE glm::vec<4, T, Q> ywzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.y); + } + + // ywzz + template + GLM_INLINE glm::vec<4, T, Q> ywzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.z); + } + + // ywzw + template + GLM_INLINE glm::vec<4, T, Q> ywzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.z, v.w); + } + + // ywwx + template + GLM_INLINE glm::vec<4, T, Q> ywwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.x); + } + + // ywwy + template + GLM_INLINE glm::vec<4, T, Q> ywwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.y); + } + + // ywwz + template + GLM_INLINE glm::vec<4, T, Q> ywwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.z); + } + + // ywww + template + GLM_INLINE glm::vec<4, T, Q> ywww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.y, v.w, v.w, v.w); + } + + // zxxx + template + GLM_INLINE glm::vec<4, T, Q> zxxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.x); + } + + // zxxy + template + GLM_INLINE glm::vec<4, T, Q> zxxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.y); + } + + // zxxz + template + GLM_INLINE glm::vec<4, T, Q> zxxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.z); + } + + // zxxw + template + GLM_INLINE glm::vec<4, T, Q> zxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.x, v.w); + } + + // zxyx + template + GLM_INLINE glm::vec<4, T, Q> zxyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.x); + } + + // zxyy + template + GLM_INLINE glm::vec<4, T, Q> zxyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.y); + } + + // zxyz + template + GLM_INLINE glm::vec<4, T, Q> zxyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.z); + } + + // zxyw + template + GLM_INLINE glm::vec<4, T, Q> zxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.y, v.w); + } + + // zxzx + template + GLM_INLINE glm::vec<4, T, Q> zxzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.x); + } + + // zxzy + template + GLM_INLINE glm::vec<4, T, Q> zxzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.y); + } + + // zxzz + template + GLM_INLINE glm::vec<4, T, Q> zxzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.z); + } + + // zxzw + template + GLM_INLINE glm::vec<4, T, Q> zxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.z, v.w); + } + + // zxwx + template + GLM_INLINE glm::vec<4, T, Q> zxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.x); + } + + // zxwy + template + GLM_INLINE glm::vec<4, T, Q> zxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.y); + } + + // zxwz + template + GLM_INLINE glm::vec<4, T, Q> zxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.z); + } + + // zxww + template + GLM_INLINE glm::vec<4, T, Q> zxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.x, v.w, v.w); + } + + // zyxx + template + GLM_INLINE glm::vec<4, T, Q> zyxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.x); + } + + // zyxy + template + GLM_INLINE glm::vec<4, T, Q> zyxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.y); + } + + // zyxz + template + GLM_INLINE glm::vec<4, T, Q> zyxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.z); + } + + // zyxw + template + GLM_INLINE glm::vec<4, T, Q> zyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.x, v.w); + } + + // zyyx + template + GLM_INLINE glm::vec<4, T, Q> zyyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.x); + } + + // zyyy + template + GLM_INLINE glm::vec<4, T, Q> zyyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.y); + } + + // zyyz + template + GLM_INLINE glm::vec<4, T, Q> zyyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.z); + } + + // zyyw + template + GLM_INLINE glm::vec<4, T, Q> zyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.y, v.w); + } + + // zyzx + template + GLM_INLINE glm::vec<4, T, Q> zyzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.x); + } + + // zyzy + template + GLM_INLINE glm::vec<4, T, Q> zyzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.y); + } + + // zyzz + template + GLM_INLINE glm::vec<4, T, Q> zyzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.z); + } + + // zyzw + template + GLM_INLINE glm::vec<4, T, Q> zyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.z, v.w); + } + + // zywx + template + GLM_INLINE glm::vec<4, T, Q> zywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.x); + } + + // zywy + template + GLM_INLINE glm::vec<4, T, Q> zywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.y); + } + + // zywz + template + GLM_INLINE glm::vec<4, T, Q> zywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.z); + } + + // zyww + template + GLM_INLINE glm::vec<4, T, Q> zyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.y, v.w, v.w); + } + + // zzxx + template + GLM_INLINE glm::vec<4, T, Q> zzxx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.x); + } + + // zzxy + template + GLM_INLINE glm::vec<4, T, Q> zzxy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.y); + } + + // zzxz + template + GLM_INLINE glm::vec<4, T, Q> zzxz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.z); + } + + // zzxw + template + GLM_INLINE glm::vec<4, T, Q> zzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.x, v.w); + } + + // zzyx + template + GLM_INLINE glm::vec<4, T, Q> zzyx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.x); + } + + // zzyy + template + GLM_INLINE glm::vec<4, T, Q> zzyy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.y); + } + + // zzyz + template + GLM_INLINE glm::vec<4, T, Q> zzyz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.z); + } + + // zzyw + template + GLM_INLINE glm::vec<4, T, Q> zzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.y, v.w); + } + + // zzzx + template + GLM_INLINE glm::vec<4, T, Q> zzzx(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.x); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.x); + } + + // zzzy + template + GLM_INLINE glm::vec<4, T, Q> zzzy(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.y); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.y); + } + + // zzzz + template + GLM_INLINE glm::vec<4, T, Q> zzzz(const glm::vec<3, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.z); + } + + template + GLM_INLINE glm::vec<4, T, Q> zzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.z); + } + + // zzzw + template + GLM_INLINE glm::vec<4, T, Q> zzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.z, v.w); + } + + // zzwx + template + GLM_INLINE glm::vec<4, T, Q> zzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.x); + } + + // zzwy + template + GLM_INLINE glm::vec<4, T, Q> zzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.y); + } + + // zzwz + template + GLM_INLINE glm::vec<4, T, Q> zzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.z); + } + + // zzww + template + GLM_INLINE glm::vec<4, T, Q> zzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.z, v.w, v.w); + } + + // zwxx + template + GLM_INLINE glm::vec<4, T, Q> zwxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.x); + } + + // zwxy + template + GLM_INLINE glm::vec<4, T, Q> zwxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.y); + } + + // zwxz + template + GLM_INLINE glm::vec<4, T, Q> zwxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.z); + } + + // zwxw + template + GLM_INLINE glm::vec<4, T, Q> zwxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.x, v.w); + } + + // zwyx + template + GLM_INLINE glm::vec<4, T, Q> zwyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.x); + } + + // zwyy + template + GLM_INLINE glm::vec<4, T, Q> zwyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.y); + } + + // zwyz + template + GLM_INLINE glm::vec<4, T, Q> zwyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.z); + } + + // zwyw + template + GLM_INLINE glm::vec<4, T, Q> zwyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.y, v.w); + } + + // zwzx + template + GLM_INLINE glm::vec<4, T, Q> zwzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.x); + } + + // zwzy + template + GLM_INLINE glm::vec<4, T, Q> zwzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.y); + } + + // zwzz + template + GLM_INLINE glm::vec<4, T, Q> zwzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.z); + } + + // zwzw + template + GLM_INLINE glm::vec<4, T, Q> zwzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.z, v.w); + } + + // zwwx + template + GLM_INLINE glm::vec<4, T, Q> zwwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.x); + } + + // zwwy + template + GLM_INLINE glm::vec<4, T, Q> zwwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.y); + } + + // zwwz + template + GLM_INLINE glm::vec<4, T, Q> zwwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.z); + } + + // zwww + template + GLM_INLINE glm::vec<4, T, Q> zwww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.z, v.w, v.w, v.w); + } + + // wxxx + template + GLM_INLINE glm::vec<4, T, Q> wxxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.x); + } + + // wxxy + template + GLM_INLINE glm::vec<4, T, Q> wxxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.y); + } + + // wxxz + template + GLM_INLINE glm::vec<4, T, Q> wxxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.z); + } + + // wxxw + template + GLM_INLINE glm::vec<4, T, Q> wxxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.x, v.w); + } + + // wxyx + template + GLM_INLINE glm::vec<4, T, Q> wxyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.x); + } + + // wxyy + template + GLM_INLINE glm::vec<4, T, Q> wxyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.y); + } + + // wxyz + template + GLM_INLINE glm::vec<4, T, Q> wxyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.z); + } + + // wxyw + template + GLM_INLINE glm::vec<4, T, Q> wxyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.y, v.w); + } + + // wxzx + template + GLM_INLINE glm::vec<4, T, Q> wxzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.x); + } + + // wxzy + template + GLM_INLINE glm::vec<4, T, Q> wxzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.y); + } + + // wxzz + template + GLM_INLINE glm::vec<4, T, Q> wxzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.z); + } + + // wxzw + template + GLM_INLINE glm::vec<4, T, Q> wxzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.z, v.w); + } + + // wxwx + template + GLM_INLINE glm::vec<4, T, Q> wxwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.x); + } + + // wxwy + template + GLM_INLINE glm::vec<4, T, Q> wxwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.y); + } + + // wxwz + template + GLM_INLINE glm::vec<4, T, Q> wxwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.z); + } + + // wxww + template + GLM_INLINE glm::vec<4, T, Q> wxww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.x, v.w, v.w); + } + + // wyxx + template + GLM_INLINE glm::vec<4, T, Q> wyxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.x); + } + + // wyxy + template + GLM_INLINE glm::vec<4, T, Q> wyxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.y); + } + + // wyxz + template + GLM_INLINE glm::vec<4, T, Q> wyxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.z); + } + + // wyxw + template + GLM_INLINE glm::vec<4, T, Q> wyxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.x, v.w); + } + + // wyyx + template + GLM_INLINE glm::vec<4, T, Q> wyyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.x); + } + + // wyyy + template + GLM_INLINE glm::vec<4, T, Q> wyyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.y); + } + + // wyyz + template + GLM_INLINE glm::vec<4, T, Q> wyyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.z); + } + + // wyyw + template + GLM_INLINE glm::vec<4, T, Q> wyyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.y, v.w); + } + + // wyzx + template + GLM_INLINE glm::vec<4, T, Q> wyzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.x); + } + + // wyzy + template + GLM_INLINE glm::vec<4, T, Q> wyzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.y); + } + + // wyzz + template + GLM_INLINE glm::vec<4, T, Q> wyzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.z); + } + + // wyzw + template + GLM_INLINE glm::vec<4, T, Q> wyzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.z, v.w); + } + + // wywx + template + GLM_INLINE glm::vec<4, T, Q> wywx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.x); + } + + // wywy + template + GLM_INLINE glm::vec<4, T, Q> wywy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.y); + } + + // wywz + template + GLM_INLINE glm::vec<4, T, Q> wywz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.z); + } + + // wyww + template + GLM_INLINE glm::vec<4, T, Q> wyww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.y, v.w, v.w); + } + + // wzxx + template + GLM_INLINE glm::vec<4, T, Q> wzxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.x); + } + + // wzxy + template + GLM_INLINE glm::vec<4, T, Q> wzxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.y); + } + + // wzxz + template + GLM_INLINE glm::vec<4, T, Q> wzxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.z); + } + + // wzxw + template + GLM_INLINE glm::vec<4, T, Q> wzxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.x, v.w); + } + + // wzyx + template + GLM_INLINE glm::vec<4, T, Q> wzyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.x); + } + + // wzyy + template + GLM_INLINE glm::vec<4, T, Q> wzyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.y); + } + + // wzyz + template + GLM_INLINE glm::vec<4, T, Q> wzyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.z); + } + + // wzyw + template + GLM_INLINE glm::vec<4, T, Q> wzyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.y, v.w); + } + + // wzzx + template + GLM_INLINE glm::vec<4, T, Q> wzzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.x); + } + + // wzzy + template + GLM_INLINE glm::vec<4, T, Q> wzzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.y); + } + + // wzzz + template + GLM_INLINE glm::vec<4, T, Q> wzzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.z); + } + + // wzzw + template + GLM_INLINE glm::vec<4, T, Q> wzzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.z, v.w); + } + + // wzwx + template + GLM_INLINE glm::vec<4, T, Q> wzwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.x); + } + + // wzwy + template + GLM_INLINE glm::vec<4, T, Q> wzwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.y); + } + + // wzwz + template + GLM_INLINE glm::vec<4, T, Q> wzwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.z); + } + + // wzww + template + GLM_INLINE glm::vec<4, T, Q> wzww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.z, v.w, v.w); + } + + // wwxx + template + GLM_INLINE glm::vec<4, T, Q> wwxx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.x); + } + + // wwxy + template + GLM_INLINE glm::vec<4, T, Q> wwxy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.y); + } + + // wwxz + template + GLM_INLINE glm::vec<4, T, Q> wwxz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.z); + } + + // wwxw + template + GLM_INLINE glm::vec<4, T, Q> wwxw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.x, v.w); + } + + // wwyx + template + GLM_INLINE glm::vec<4, T, Q> wwyx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.x); + } + + // wwyy + template + GLM_INLINE glm::vec<4, T, Q> wwyy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.y); + } + + // wwyz + template + GLM_INLINE glm::vec<4, T, Q> wwyz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.z); + } + + // wwyw + template + GLM_INLINE glm::vec<4, T, Q> wwyw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.y, v.w); + } + + // wwzx + template + GLM_INLINE glm::vec<4, T, Q> wwzx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.x); + } + + // wwzy + template + GLM_INLINE glm::vec<4, T, Q> wwzy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.y); + } + + // wwzz + template + GLM_INLINE glm::vec<4, T, Q> wwzz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.z); + } + + // wwzw + template + GLM_INLINE glm::vec<4, T, Q> wwzw(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.z, v.w); + } + + // wwwx + template + GLM_INLINE glm::vec<4, T, Q> wwwx(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.x); + } + + // wwwy + template + GLM_INLINE glm::vec<4, T, Q> wwwy(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.y); + } + + // wwwz + template + GLM_INLINE glm::vec<4, T, Q> wwwz(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.z); + } + + // wwww + template + GLM_INLINE glm::vec<4, T, Q> wwww(const glm::vec<4, T, Q> &v) { + return glm::vec<4, T, Q>(v.w, v.w, v.w, v.w); + } + +} diff --git a/vendor/glm/glm/gtx/vector_angle.hpp b/vendor/glm/glm/gtx/vector_angle.hpp new file mode 100644 index 0000000..9ae4371 --- /dev/null +++ b/vendor/glm/glm/gtx/vector_angle.hpp @@ -0,0 +1,57 @@ +/// @ref gtx_vector_angle +/// @file glm/gtx/vector_angle.hpp +/// +/// @see core (dependence) +/// @see gtx_quaternion (dependence) +/// @see gtx_epsilon (dependence) +/// +/// @defgroup gtx_vector_angle GLM_GTX_vector_angle +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Compute angle between vectors + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtx/quaternion.hpp" +#include "../gtx/rotate_vector.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_vector_angle is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_vector_angle extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_vector_angle + /// @{ + + //! Returns the absolute angle between two vectors. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template + GLM_FUNC_DECL T angle(vec const& x, vec const& y); + + //! Returns the oriented angle between two 2d vectors. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template + GLM_FUNC_DECL T orientedAngle(vec<2, T, Q> const& x, vec<2, T, Q> const& y); + + //! Returns the oriented angle between two 3d vectors based from a reference axis. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template + GLM_FUNC_DECL T orientedAngle(vec<3, T, Q> const& x, vec<3, T, Q> const& y, vec<3, T, Q> const& ref); + + /// @} +}// namespace glm + +#include "vector_angle.inl" diff --git a/vendor/glm/glm/gtx/vector_angle.inl b/vendor/glm/glm/gtx/vector_angle.inl new file mode 100644 index 0000000..a1f957a --- /dev/null +++ b/vendor/glm/glm/gtx/vector_angle.inl @@ -0,0 +1,44 @@ +/// @ref gtx_vector_angle + +namespace glm +{ + template + GLM_FUNC_QUALIFIER genType angle + ( + genType const& x, + genType const& y + ) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), genType(-1), genType(1))); + } + + template + GLM_FUNC_QUALIFIER T angle(vec const& x, vec const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), T(-1), T(1))); + } + + //! \todo epsilon is hard coded to 0.01 + template + GLM_FUNC_QUALIFIER T orientedAngle(vec<2, T, Q> const& x, vec<2, T, Q> const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'orientedAngle' only accept floating-point inputs"); + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + + if(all(epsilonEqual(y, glm::rotate(x, Angle), T(0.0001)))) + return Angle; + else + return -Angle; + } + + template + GLM_FUNC_QUALIFIER T orientedAngle(vec<3, T, Q> const& x, vec<3, T, Q> const& y, vec<3, T, Q> const& ref) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'orientedAngle' only accept floating-point inputs"); + + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + return mix(Angle, -Angle, dot(ref, cross(x, y)) < T(0)); + } +}//namespace glm diff --git a/vendor/glm/glm/gtx/vector_query.hpp b/vendor/glm/glm/gtx/vector_query.hpp new file mode 100644 index 0000000..77c7b97 --- /dev/null +++ b/vendor/glm/glm/gtx/vector_query.hpp @@ -0,0 +1,66 @@ +/// @ref gtx_vector_query +/// @file glm/gtx/vector_query.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_vector_query GLM_GTX_vector_query +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Query informations of vector types + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include +#include + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_vector_query is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_vector_query extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_vector_query + /// @{ + + //! Check whether two vectors are collinears. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool areCollinear(vec const& v0, vec const& v1, T const& epsilon); + + //! Check whether two vectors are orthogonals. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool areOrthogonal(vec const& v0, vec const& v1, T const& epsilon); + + //! Check whether a vector is normalized. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool isNormalized(vec const& v, T const& epsilon); + + //! Check whether a vector is null. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool isNull(vec const& v, T const& epsilon); + + //! Check whether a each component of a vector is null. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL vec isCompNull(vec const& v, T const& epsilon); + + //! Check whether two vectors are orthonormal. + /// @see gtx_vector_query extensions. + template + GLM_FUNC_DECL bool areOrthonormal(vec const& v0, vec const& v1, T const& epsilon); + + /// @} +}// namespace glm + +#include "vector_query.inl" diff --git a/vendor/glm/glm/gtx/vector_query.inl b/vendor/glm/glm/gtx/vector_query.inl new file mode 100644 index 0000000..d1a5c9b --- /dev/null +++ b/vendor/glm/glm/gtx/vector_query.inl @@ -0,0 +1,154 @@ +/// @ref gtx_vector_query + +#include + +namespace glm{ +namespace detail +{ + template + struct compute_areCollinear{}; + + template + struct compute_areCollinear<2, T, Q> + { + GLM_FUNC_QUALIFIER static bool call(vec<2, T, Q> const& v0, vec<2, T, Q> const& v1, T const& epsilon) + { + return length(cross(vec<3, T, Q>(v0, static_cast(0)), vec<3, T, Q>(v1, static_cast(0)))) < epsilon; + } + }; + + template + struct compute_areCollinear<3, T, Q> + { + GLM_FUNC_QUALIFIER static bool call(vec<3, T, Q> const& v0, vec<3, T, Q> const& v1, T const& epsilon) + { + return length(cross(v0, v1)) < epsilon; + } + }; + + template + struct compute_areCollinear<4, T, Q> + { + GLM_FUNC_QUALIFIER static bool call(vec<4, T, Q> const& v0, vec<4, T, Q> const& v1, T const& epsilon) + { + return length(cross(vec<3, T, Q>(v0), vec<3, T, Q>(v1))) < epsilon; + } + }; + + template + struct compute_isCompNull{}; + + template + struct compute_isCompNull<2, T, Q> + { + GLM_FUNC_QUALIFIER static vec<2, bool, Q> call(vec<2, T, Q> const& v, T const& epsilon) + { + return vec<2, bool, Q>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon)); + } + }; + + template + struct compute_isCompNull<3, T, Q> + { + GLM_FUNC_QUALIFIER static vec<3, bool, Q> call(vec<3, T, Q> const& v, T const& epsilon) + { + return vec<3, bool, Q>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon), + (abs(v.z) < epsilon)); + } + }; + + template + struct compute_isCompNull<4, T, Q> + { + GLM_FUNC_QUALIFIER static vec<4, bool, Q> call(vec<4, T, Q> const& v, T const& epsilon) + { + return vec<4, bool, Q>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon), + (abs(v.z) < epsilon), + (abs(v.w) < epsilon)); + } + }; + +}//namespace detail + + template + GLM_FUNC_QUALIFIER bool areCollinear(vec const& v0, vec const& v1, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'areCollinear' only accept floating-point inputs"); + + return detail::compute_areCollinear::call(v0, v1, epsilon); + } + + template + GLM_FUNC_QUALIFIER bool areOrthogonal(vec const& v0, vec const& v1, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'areOrthogonal' only accept floating-point inputs"); + + return abs(dot(v0, v1)) <= max( + static_cast(1), + length(v0)) * max(static_cast(1), length(v1)) * epsilon; + } + + template + GLM_FUNC_QUALIFIER bool isNormalized(vec const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isNormalized' only accept floating-point inputs"); + + return abs(length(v) - static_cast(1)) <= static_cast(2) * epsilon; + } + + template + GLM_FUNC_QUALIFIER bool isNull(vec const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isNull' only accept floating-point inputs"); + + return length(v) <= epsilon; + } + + template + GLM_FUNC_QUALIFIER vec isCompNull(vec const& v, T const& epsilon) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559, "'isCompNull' only accept floating-point inputs"); + + return detail::compute_isCompNull::call(v, epsilon); + } + + template + GLM_FUNC_QUALIFIER vec<2, bool, Q> isCompNull(vec<2, T, Q> const& v, T const& epsilon) + { + return vec<2, bool, Q>( + abs(v.x) < epsilon, + abs(v.y) < epsilon); + } + + template + GLM_FUNC_QUALIFIER vec<3, bool, Q> isCompNull(vec<3, T, Q> const& v, T const& epsilon) + { + return vec<3, bool, Q>( + abs(v.x) < epsilon, + abs(v.y) < epsilon, + abs(v.z) < epsilon); + } + + template + GLM_FUNC_QUALIFIER vec<4, bool, Q> isCompNull(vec<4, T, Q> const& v, T const& epsilon) + { + return vec<4, bool, Q>( + abs(v.x) < epsilon, + abs(v.y) < epsilon, + abs(v.z) < epsilon, + abs(v.w) < epsilon); + } + + template + GLM_FUNC_QUALIFIER bool areOrthonormal(vec const& v0, vec const& v1, T const& epsilon) + { + return isNormalized(v0, epsilon) && isNormalized(v1, epsilon) && (abs(dot(v0, v1)) <= epsilon); + } + +}//namespace glm diff --git a/vendor/glm/glm/gtx/wrap.hpp b/vendor/glm/glm/gtx/wrap.hpp new file mode 100644 index 0000000..ad4eb3f --- /dev/null +++ b/vendor/glm/glm/gtx/wrap.hpp @@ -0,0 +1,37 @@ +/// @ref gtx_wrap +/// @file glm/gtx/wrap.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_wrap GLM_GTX_wrap +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Wrapping mode of texture coordinates. + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../ext/scalar_common.hpp" +#include "../ext/vector_common.hpp" +#include "../gtc/vec1.hpp" + +#if GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# ifndef GLM_ENABLE_EXPERIMENTAL +# pragma message("GLM: GLM_GTX_wrap is an experimental extension and may change in the future. Use #define GLM_ENABLE_EXPERIMENTAL before including it, if you really want to use it.") +# else +# pragma message("GLM: GLM_GTX_wrap extension included") +# endif +#endif + +namespace glm +{ + /// @addtogroup gtx_wrap + /// @{ + + /// @} +}// namespace glm + +#include "wrap.inl" diff --git a/vendor/glm/glm/gtx/wrap.inl b/vendor/glm/glm/gtx/wrap.inl new file mode 100644 index 0000000..4be3b4c --- /dev/null +++ b/vendor/glm/glm/gtx/wrap.inl @@ -0,0 +1,6 @@ +/// @ref gtx_wrap + +namespace glm +{ + +}//namespace glm diff --git a/vendor/glm/glm/integer.hpp b/vendor/glm/glm/integer.hpp new file mode 100644 index 0000000..8817db3 --- /dev/null +++ b/vendor/glm/glm/integer.hpp @@ -0,0 +1,212 @@ +/// @ref core +/// @file glm/integer.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.8 Integer Functions +/// +/// @defgroup core_func_integer Integer functions +/// @ingroup core +/// +/// Provides GLSL functions on integer types +/// +/// These all operate component-wise. The description is per component. +/// The notation [a, b] means the set of bits from bit-number a through bit-number +/// b, inclusive. The lowest-order bit is bit 0. +/// +/// Include to use these core features. + +#pragma once + +#include "detail/qualifier.hpp" +#include "common.hpp" +#include "vector_relational.hpp" + +namespace glm +{ + /// @addtogroup core_func_integer + /// @{ + + /// Adds 32-bit unsigned integer x and y, returning the sum + /// modulo pow(2, 32). The value carry is set to 0 if the sum was + /// less than pow(2, 32), or to 1 otherwise. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL uaddCarry man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec uaddCarry( + vec const& x, + vec const& y, + vec & carry); + + /// Subtracts the 32-bit unsigned integer y from x, returning + /// the difference if non-negative, or pow(2, 32) plus the difference + /// otherwise. The value borrow is set to 0 if x >= y, or to 1 otherwise. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL usubBorrow man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec usubBorrow( + vec const& x, + vec const& y, + vec & borrow); + + /// Multiplies 32-bit integers x and y, producing a 64-bit + /// result. The 32 least-significant bits are returned in lsb. + /// The 32 most-significant bits are returned in msb. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL umulExtended man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL void umulExtended( + vec const& x, + vec const& y, + vec & msb, + vec & lsb); + + /// Multiplies 32-bit integers x and y, producing a 64-bit + /// result. The 32 least-significant bits are returned in lsb. + /// The 32 most-significant bits are returned in msb. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL imulExtended man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL void imulExtended( + vec const& x, + vec const& y, + vec & msb, + vec & lsb); + + /// Extracts bits [offset, offset + bits - 1] from value, + /// returning them in the least significant bits of the result. + /// For unsigned data types, the most significant bits of the + /// result will be set to zero. For signed data types, the + /// most significant bits will be set to the value of bit offset + base - 1. + /// + /// If bits is zero, the result will be zero. The result will be + /// undefined if offset or bits is negative, or if the sum of + /// offset and bits is greater than the number of bits used + /// to store the operand. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see GLSL bitfieldExtract man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitfieldExtract( + vec const& Value, + int Offset, + int Bits); + + /// Returns the insertion the bits least-significant bits of insert into base. + /// + /// The result will have bits [offset, offset + bits - 1] taken + /// from bits [0, bits - 1] of insert, and all other bits taken + /// directly from the corresponding bits of base. If bits is + /// zero, the result will simply be base. The result will be + /// undefined if offset or bits is negative, or if the sum of + /// offset and bits is greater than the number of bits used to + /// store the operand. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitfieldInsert man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitfieldInsert( + vec const& Base, + vec const& Insert, + int Offset, + int Bits); + + /// Returns the reversal of the bits of value. + /// The bit numbered n of the result will be taken from bit (bits - 1) - n of value, + /// where bits is the total number of bits used to represent value. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitfieldReverse man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitfieldReverse(vec const& v); + + /// Returns the number of bits set to 1 in the binary representation of value. + /// + /// @tparam genType Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitCount man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL int bitCount(genType v); + + /// Returns the number of bits set to 1 in the binary representation of value. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see GLSL bitCount man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec bitCount(vec const& v); + + /// Returns the bit number of the least significant bit set to + /// 1 in the binary representation of value. + /// If value is zero, -1 will be returned. + /// + /// @tparam genIUType Signed or unsigned integer scalar types. + /// + /// @see GLSL findLSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL int findLSB(genIUType x); + + /// Returns the bit number of the least significant bit set to + /// 1 in the binary representation of value. + /// If value is zero, -1 will be returned. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see GLSL findLSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec findLSB(vec const& v); + + /// Returns the bit number of the most significant bit in the binary representation of value. + /// For positive integers, the result will be the bit number of the most significant bit set to 1. + /// For negative integers, the result will be the bit number of the most significant + /// bit set to 0. For a value of zero or negative one, -1 will be returned. + /// + /// @tparam genIUType Signed or unsigned integer scalar types. + /// + /// @see GLSL findMSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL int findMSB(genIUType x); + + /// Returns the bit number of the most significant bit in the binary representation of value. + /// For positive integers, the result will be the bit number of the most significant bit set to 1. + /// For negative integers, the result will be the bit number of the most significant + /// bit set to 0. For a value of zero or negative one, -1 will be returned. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see GLSL findMSB man page + /// @see GLSL 4.20.8 specification, section 8.8 Integer Functions + template + GLM_FUNC_DECL vec findMSB(vec const& v); + + /// @} +}//namespace glm + +#include "detail/func_integer.inl" diff --git a/vendor/glm/glm/mat2x2.hpp b/vendor/glm/glm/mat2x2.hpp new file mode 100644 index 0000000..96bec96 --- /dev/null +++ b/vendor/glm/glm/mat2x2.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat2x2.hpp + +#pragma once +#include "./ext/matrix_double2x2.hpp" +#include "./ext/matrix_double2x2_precision.hpp" +#include "./ext/matrix_float2x2.hpp" +#include "./ext/matrix_float2x2_precision.hpp" + diff --git a/vendor/glm/glm/mat2x3.hpp b/vendor/glm/glm/mat2x3.hpp new file mode 100644 index 0000000..d68dc25 --- /dev/null +++ b/vendor/glm/glm/mat2x3.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat2x3.hpp + +#pragma once +#include "./ext/matrix_double2x3.hpp" +#include "./ext/matrix_double2x3_precision.hpp" +#include "./ext/matrix_float2x3.hpp" +#include "./ext/matrix_float2x3_precision.hpp" + diff --git a/vendor/glm/glm/mat2x4.hpp b/vendor/glm/glm/mat2x4.hpp new file mode 100644 index 0000000..b04b738 --- /dev/null +++ b/vendor/glm/glm/mat2x4.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat2x4.hpp + +#pragma once +#include "./ext/matrix_double2x4.hpp" +#include "./ext/matrix_double2x4_precision.hpp" +#include "./ext/matrix_float2x4.hpp" +#include "./ext/matrix_float2x4_precision.hpp" + diff --git a/vendor/glm/glm/mat3x2.hpp b/vendor/glm/glm/mat3x2.hpp new file mode 100644 index 0000000..c853153 --- /dev/null +++ b/vendor/glm/glm/mat3x2.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat3x2.hpp + +#pragma once +#include "./ext/matrix_double3x2.hpp" +#include "./ext/matrix_double3x2_precision.hpp" +#include "./ext/matrix_float3x2.hpp" +#include "./ext/matrix_float3x2_precision.hpp" + diff --git a/vendor/glm/glm/mat3x3.hpp b/vendor/glm/glm/mat3x3.hpp new file mode 100644 index 0000000..fd4fa31 --- /dev/null +++ b/vendor/glm/glm/mat3x3.hpp @@ -0,0 +1,8 @@ +/// @ref core +/// @file glm/mat3x3.hpp + +#pragma once +#include "./ext/matrix_double3x3.hpp" +#include "./ext/matrix_double3x3_precision.hpp" +#include "./ext/matrix_float3x3.hpp" +#include "./ext/matrix_float3x3_precision.hpp" diff --git a/vendor/glm/glm/mat3x4.hpp b/vendor/glm/glm/mat3x4.hpp new file mode 100644 index 0000000..6342bf5 --- /dev/null +++ b/vendor/glm/glm/mat3x4.hpp @@ -0,0 +1,8 @@ +/// @ref core +/// @file glm/mat3x4.hpp + +#pragma once +#include "./ext/matrix_double3x4.hpp" +#include "./ext/matrix_double3x4_precision.hpp" +#include "./ext/matrix_float3x4.hpp" +#include "./ext/matrix_float3x4_precision.hpp" diff --git a/vendor/glm/glm/mat4x2.hpp b/vendor/glm/glm/mat4x2.hpp new file mode 100644 index 0000000..e013e46 --- /dev/null +++ b/vendor/glm/glm/mat4x2.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat4x2.hpp + +#pragma once +#include "./ext/matrix_double4x2.hpp" +#include "./ext/matrix_double4x2_precision.hpp" +#include "./ext/matrix_float4x2.hpp" +#include "./ext/matrix_float4x2_precision.hpp" + diff --git a/vendor/glm/glm/mat4x3.hpp b/vendor/glm/glm/mat4x3.hpp new file mode 100644 index 0000000..205725a --- /dev/null +++ b/vendor/glm/glm/mat4x3.hpp @@ -0,0 +1,8 @@ +/// @ref core +/// @file glm/mat4x3.hpp + +#pragma once +#include "./ext/matrix_double4x3.hpp" +#include "./ext/matrix_double4x3_precision.hpp" +#include "./ext/matrix_float4x3.hpp" +#include "./ext/matrix_float4x3_precision.hpp" diff --git a/vendor/glm/glm/mat4x4.hpp b/vendor/glm/glm/mat4x4.hpp new file mode 100644 index 0000000..3515f7f --- /dev/null +++ b/vendor/glm/glm/mat4x4.hpp @@ -0,0 +1,9 @@ +/// @ref core +/// @file glm/mat4x4.hpp + +#pragma once +#include "./ext/matrix_double4x4.hpp" +#include "./ext/matrix_double4x4_precision.hpp" +#include "./ext/matrix_float4x4.hpp" +#include "./ext/matrix_float4x4_precision.hpp" + diff --git a/vendor/glm/glm/matrix.hpp b/vendor/glm/glm/matrix.hpp new file mode 100644 index 0000000..6badf53 --- /dev/null +++ b/vendor/glm/glm/matrix.hpp @@ -0,0 +1,161 @@ +/// @ref core +/// @file glm/matrix.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions +/// +/// @defgroup core_func_matrix Matrix functions +/// @ingroup core +/// +/// Provides GLSL matrix functions. +/// +/// Include to use these core features. + +#pragma once + +// Dependencies +#include "detail/qualifier.hpp" +#include "detail/setup.hpp" +#include "vec2.hpp" +#include "vec3.hpp" +#include "vec4.hpp" +#include "mat2x2.hpp" +#include "mat2x3.hpp" +#include "mat2x4.hpp" +#include "mat3x2.hpp" +#include "mat3x3.hpp" +#include "mat3x4.hpp" +#include "mat4x2.hpp" +#include "mat4x3.hpp" +#include "mat4x4.hpp" + +namespace glm { +namespace detail +{ + template + struct outerProduct_trait{}; + + template + struct outerProduct_trait<2, 2, T, Q> + { + typedef mat<2, 2, T, Q> type; + }; + + template + struct outerProduct_trait<2, 3, T, Q> + { + typedef mat<3, 2, T, Q> type; + }; + + template + struct outerProduct_trait<2, 4, T, Q> + { + typedef mat<4, 2, T, Q> type; + }; + + template + struct outerProduct_trait<3, 2, T, Q> + { + typedef mat<2, 3, T, Q> type; + }; + + template + struct outerProduct_trait<3, 3, T, Q> + { + typedef mat<3, 3, T, Q> type; + }; + + template + struct outerProduct_trait<3, 4, T, Q> + { + typedef mat<4, 3, T, Q> type; + }; + + template + struct outerProduct_trait<4, 2, T, Q> + { + typedef mat<2, 4, T, Q> type; + }; + + template + struct outerProduct_trait<4, 3, T, Q> + { + typedef mat<3, 4, T, Q> type; + }; + + template + struct outerProduct_trait<4, 4, T, Q> + { + typedef mat<4, 4, T, Q> type; + }; +}//namespace detail + + /// @addtogroup core_func_matrix + /// @{ + + /// Multiply matrix x by matrix y component-wise, i.e., + /// result[i][j] is the scalar product of x[i][j] and y[i][j]. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL matrixCompMult man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL mat matrixCompMult(mat const& x, mat const& y); + + /// Treats the first parameter c as a column vector + /// and the second parameter r as a row vector + /// and does a linear algebraic matrix multiply c * r. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL outerProduct man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL typename detail::outerProduct_trait::type outerProduct(vec const& c, vec const& r); + + /// Returns the transposed matrix of x + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL transpose man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL typename mat::transpose_type transpose(mat const& x); + + /// Return the determinant of a squared matrix. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL determinant man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL T determinant(mat const& m); + + /// Return the inverse of a squared matrix. + /// + /// @tparam C Integer between 1 and 4 included that qualify the number a column + /// @tparam R Integer between 1 and 4 included that qualify the number a row + /// @tparam T Floating-point or signed integer scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL inverse man page + /// @see GLSL 4.20.8 specification, section 8.6 Matrix Functions + template + GLM_FUNC_DECL mat inverse(mat const& m); + + /// @} +}//namespace glm + +#include "detail/func_matrix.inl" diff --git a/vendor/glm/glm/packing.hpp b/vendor/glm/glm/packing.hpp new file mode 100644 index 0000000..ca83ac1 --- /dev/null +++ b/vendor/glm/glm/packing.hpp @@ -0,0 +1,173 @@ +/// @ref core +/// @file glm/packing.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions +/// @see gtc_packing +/// +/// @defgroup core_func_packing Floating-Point Pack and Unpack Functions +/// @ingroup core +/// +/// Provides GLSL functions to pack and unpack half, single and double-precision floating point values into more compact integer types. +/// +/// These functions do not operate component-wise, rather as described in each case. +/// +/// Include to use these core features. + +#pragma once + +#include "./ext/vector_uint2.hpp" +#include "./ext/vector_float2.hpp" +#include "./ext/vector_float4.hpp" + +namespace glm +{ + /// @addtogroup core_func_packing + /// @{ + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packUnorm2x16(vec2 const& v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x16: round(clamp(v, -1, +1) * 32767.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packSnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packSnorm2x16(vec2 const& v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm4x8: round(clamp(c, 0, +1) * 255.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packUnorm4x8(vec4 const& v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm4x8: round(clamp(c, -1, +1) * 127.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see GLSL packSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packSnorm4x8(vec4 const& v); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm2x16: f / 65535.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackUnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackUnorm2x16(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm2x16: clamp(f / 32767.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackSnorm2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackSnorm2x16(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackUnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackUnorm4x8(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm4x8: clamp(f / 127.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see GLSL unpackSnorm4x8 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec4 unpackSnorm4x8(uint p); + + /// Returns a double-qualifier value obtained by packing the components of v into a 64-bit value. + /// If an IEEE 754 Inf or NaN is created, it will not signal, and the resulting floating point value is unspecified. + /// Otherwise, the bit- level representation of v is preserved. + /// The first vector component specifies the 32 least significant bits; + /// the second component specifies the 32 most significant bits. + /// + /// @see GLSL packDouble2x32 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL double packDouble2x32(uvec2 const& v); + + /// Returns a two-component unsigned integer vector representation of v. + /// The bit-level representation of v is preserved. + /// The first component of the vector contains the 32 least significant bits of the double; + /// the second component consists the 32 most significant bits. + /// + /// @see GLSL unpackDouble2x32 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uvec2 unpackDouble2x32(double v); + + /// Returns an unsigned integer obtained by converting the components of a two-component floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing these two 16- bit integers into a 32-bit unsigned integer. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the second component specifies the 16 most-significant bits. + /// + /// @see GLSL packHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL uint packHalf2x16(vec2 const& v); + + /// Returns a two-component floating-point vector with components obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values, + /// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification, + /// and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the second component is obtained from the 16 most-significant bits of v. + /// + /// @see GLSL unpackHalf2x16 man page + /// @see GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions + GLM_FUNC_DECL vec2 unpackHalf2x16(uint v); + + /// @} +}//namespace glm + +#include "detail/func_packing.inl" diff --git a/vendor/glm/glm/simd/common.h b/vendor/glm/glm/simd/common.h new file mode 100644 index 0000000..9b017cb --- /dev/null +++ b/vendor/glm/glm/simd/common.h @@ -0,0 +1,240 @@ +/// @ref simd +/// @file glm/simd/common.h + +#pragma once + +#include "platform.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_add(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_add_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_add(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_add_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_sub(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_sub_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_sub(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_sub_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_mul(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_mul_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_mul(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_mul_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_div(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_div_ps(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_div(glm_f32vec4 a, glm_f32vec4 b) +{ + return _mm_div_ss(a, b); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_div_lowp(glm_f32vec4 a, glm_f32vec4 b) +{ + return glm_vec4_mul(a, _mm_rcp_ps(b)); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_swizzle_xyzw(glm_f32vec4 a) +{ +# if GLM_ARCH & GLM_ARCH_AVX2_BIT + return _mm_permute_ps(a, _MM_SHUFFLE(3, 2, 1, 0)); +# else + return _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 2, 1, 0)); +# endif +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_fma(glm_f32vec4 a, glm_f32vec4 b, glm_f32vec4 c) +{ +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) && !(GLM_COMPILER & GLM_COMPILER_CLANG) + return _mm_fmadd_ss(a, b, c); +# else + return _mm_add_ss(_mm_mul_ss(a, b), c); +# endif +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_fma(glm_f32vec4 a, glm_f32vec4 b, glm_f32vec4 c) +{ +# if (GLM_ARCH & GLM_ARCH_AVX2_BIT) && !(GLM_COMPILER & GLM_COMPILER_CLANG) + return _mm_fmadd_ps(a, b, c); +# else + return glm_vec4_add(glm_vec4_mul(a, b), c); +# endif +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_abs(glm_f32vec4 x) +{ + return _mm_and_ps(x, _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF))); +} + +GLM_FUNC_QUALIFIER glm_ivec4 glm_ivec4_abs(glm_ivec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSSE3_BIT + return _mm_sign_epi32(x, x); +# else + glm_ivec4 const sgn0 = _mm_srai_epi32(x, 31); + glm_ivec4 const inv0 = _mm_xor_si128(x, sgn0); + glm_ivec4 const sub0 = _mm_sub_epi32(inv0, sgn0); + return sub0; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_sign(glm_vec4 x) +{ + glm_vec4 const zro0 = _mm_setzero_ps(); + glm_vec4 const cmp0 = _mm_cmplt_ps(x, zro0); + glm_vec4 const cmp1 = _mm_cmpgt_ps(x, zro0); + glm_vec4 const and0 = _mm_and_ps(cmp0, _mm_set1_ps(-1.0f)); + glm_vec4 const and1 = _mm_and_ps(cmp1, _mm_set1_ps(1.0f)); + glm_vec4 const or0 = _mm_or_ps(and0, and1); + return or0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_round(glm_vec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + return _mm_round_ps(x, _MM_FROUND_TO_NEAREST_INT); +# else + glm_vec4 const sgn0 = _mm_castsi128_ps(_mm_set1_epi32(int(0x80000000))); + glm_vec4 const and0 = _mm_and_ps(sgn0, x); + glm_vec4 const or0 = _mm_or_ps(and0, _mm_set_ps1(8388608.0f)); + glm_vec4 const add0 = glm_vec4_add(x, or0); + glm_vec4 const sub0 = glm_vec4_sub(add0, or0); + return sub0; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_floor(glm_vec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + return _mm_floor_ps(x); +# else + glm_vec4 const rnd0 = glm_vec4_round(x); + glm_vec4 const cmp0 = _mm_cmplt_ps(x, rnd0); + glm_vec4 const and0 = _mm_and_ps(cmp0, _mm_set1_ps(1.0f)); + glm_vec4 const sub0 = glm_vec4_sub(rnd0, and0); + return sub0; +# endif +} + +/* trunc TODO +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_trunc(glm_vec4 x) +{ + return glm_vec4(); +} +*/ + +//roundEven +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_roundEven(glm_vec4 x) +{ + glm_vec4 const sgn0 = _mm_castsi128_ps(_mm_set1_epi32(int(0x80000000))); + glm_vec4 const and0 = _mm_and_ps(sgn0, x); + glm_vec4 const or0 = _mm_or_ps(and0, _mm_set_ps1(8388608.0f)); + glm_vec4 const add0 = glm_vec4_add(x, or0); + glm_vec4 const sub0 = glm_vec4_sub(add0, or0); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_ceil(glm_vec4 x) +{ +# if GLM_ARCH & GLM_ARCH_SSE41_BIT + return _mm_ceil_ps(x); +# else + glm_vec4 const rnd0 = glm_vec4_round(x); + glm_vec4 const cmp0 = _mm_cmpgt_ps(x, rnd0); + glm_vec4 const and0 = _mm_and_ps(cmp0, _mm_set1_ps(1.0f)); + glm_vec4 const add0 = glm_vec4_add(rnd0, and0); + return add0; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_fract(glm_vec4 x) +{ + glm_vec4 const flr0 = glm_vec4_floor(x); + glm_vec4 const sub0 = glm_vec4_sub(x, flr0); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_mod(glm_vec4 x, glm_vec4 y) +{ + glm_vec4 const div0 = glm_vec4_div(x, y); + glm_vec4 const flr0 = glm_vec4_floor(div0); + glm_vec4 const mul0 = glm_vec4_mul(y, flr0); + glm_vec4 const sub0 = glm_vec4_sub(x, mul0); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_clamp(glm_vec4 v, glm_vec4 minVal, glm_vec4 maxVal) +{ + glm_vec4 const min0 = _mm_min_ps(v, maxVal); + glm_vec4 const max0 = _mm_max_ps(min0, minVal); + return max0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_mix(glm_vec4 v1, glm_vec4 v2, glm_vec4 a) +{ + glm_vec4 const sub0 = glm_vec4_sub(_mm_set1_ps(1.0f), a); + glm_vec4 const mul0 = glm_vec4_mul(v1, sub0); + glm_vec4 const mad0 = glm_vec4_fma(v2, a, mul0); + return mad0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_step(glm_vec4 edge, glm_vec4 x) +{ + glm_vec4 const cmp = _mm_cmple_ps(x, edge); + return _mm_movemask_ps(cmp) == 0 ? _mm_set1_ps(1.0f) : _mm_setzero_ps(); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_smoothstep(glm_vec4 edge0, glm_vec4 edge1, glm_vec4 x) +{ + glm_vec4 const sub0 = glm_vec4_sub(x, edge0); + glm_vec4 const sub1 = glm_vec4_sub(edge1, edge0); + glm_vec4 const div0 = glm_vec4_sub(sub0, sub1); + glm_vec4 const clp0 = glm_vec4_clamp(div0, _mm_setzero_ps(), _mm_set1_ps(1.0f)); + glm_vec4 const mul0 = glm_vec4_mul(_mm_set1_ps(2.0f), clp0); + glm_vec4 const sub2 = glm_vec4_sub(_mm_set1_ps(3.0f), mul0); + glm_vec4 const mul1 = glm_vec4_mul(clp0, clp0); + glm_vec4 const mul2 = glm_vec4_mul(mul1, sub2); + return mul2; +} + +// Agner Fog method +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_nan(glm_vec4 x) +{ + glm_ivec4 const t1 = _mm_castps_si128(x); // reinterpret as 32-bit integer + glm_ivec4 const t2 = _mm_sll_epi32(t1, _mm_cvtsi32_si128(1)); // shift out sign bit + glm_ivec4 const t3 = _mm_set1_epi32(int(0xFF000000)); // exponent mask + glm_ivec4 const t4 = _mm_and_si128(t2, t3); // exponent + glm_ivec4 const t5 = _mm_andnot_si128(t3, t2); // fraction + glm_ivec4 const Equal = _mm_cmpeq_epi32(t3, t4); + glm_ivec4 const Nequal = _mm_cmpeq_epi32(t5, _mm_setzero_si128()); + glm_ivec4 const And = _mm_and_si128(Equal, Nequal); + return _mm_castsi128_ps(And); // exponent = all 1s and fraction != 0 +} + +// Agner Fog method +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_inf(glm_vec4 x) +{ + glm_ivec4 const t1 = _mm_castps_si128(x); // reinterpret as 32-bit integer + glm_ivec4 const t2 = _mm_sll_epi32(t1, _mm_cvtsi32_si128(1)); // shift out sign bit + return _mm_castsi128_ps(_mm_cmpeq_epi32(t2, _mm_set1_epi32(int(0xFF000000)))); // exponent is all 1s, fraction is 0 +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/simd/exponential.h b/vendor/glm/glm/simd/exponential.h new file mode 100644 index 0000000..bc351d0 --- /dev/null +++ b/vendor/glm/glm/simd/exponential.h @@ -0,0 +1,20 @@ +/// @ref simd +/// @file glm/simd/experimental.h + +#pragma once + +#include "platform.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec1_sqrt_lowp(glm_f32vec4 x) +{ + return _mm_mul_ss(_mm_rsqrt_ss(x), x); +} + +GLM_FUNC_QUALIFIER glm_f32vec4 glm_vec4_sqrt_lowp(glm_f32vec4 x) +{ + return _mm_mul_ps(_mm_rsqrt_ps(x), x); +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/simd/geometric.h b/vendor/glm/glm/simd/geometric.h new file mode 100644 index 0000000..07d7cbc --- /dev/null +++ b/vendor/glm/glm/simd/geometric.h @@ -0,0 +1,124 @@ +/// @ref simd +/// @file glm/simd/geometric.h + +#pragma once + +#include "common.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_DECL glm_vec4 glm_vec4_dot(glm_vec4 v1, glm_vec4 v2); +GLM_FUNC_DECL glm_vec4 glm_vec1_dot(glm_vec4 v1, glm_vec4 v2); + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_length(glm_vec4 x) +{ + glm_vec4 const dot0 = glm_vec4_dot(x, x); + glm_vec4 const sqt0 = _mm_sqrt_ps(dot0); + return sqt0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_distance(glm_vec4 p0, glm_vec4 p1) +{ + glm_vec4 const sub0 = _mm_sub_ps(p0, p1); + glm_vec4 const len0 = glm_vec4_length(sub0); + return len0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_dot(glm_vec4 v1, glm_vec4 v2) +{ +# if GLM_ARCH & GLM_ARCH_AVX_BIT + return _mm_dp_ps(v1, v2, 0xff); +# elif GLM_ARCH & GLM_ARCH_SSE3_BIT + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const hadd0 = _mm_hadd_ps(mul0, mul0); + glm_vec4 const hadd1 = _mm_hadd_ps(hadd0, hadd0); + return hadd1; +# else + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const swp0 = _mm_shuffle_ps(mul0, mul0, _MM_SHUFFLE(2, 3, 0, 1)); + glm_vec4 const add0 = _mm_add_ps(mul0, swp0); + glm_vec4 const swp1 = _mm_shuffle_ps(add0, add0, _MM_SHUFFLE(0, 1, 2, 3)); + glm_vec4 const add1 = _mm_add_ps(add0, swp1); + return add1; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec1_dot(glm_vec4 v1, glm_vec4 v2) +{ +# if GLM_ARCH & GLM_ARCH_AVX_BIT + return _mm_dp_ps(v1, v2, 0xff); +# elif GLM_ARCH & GLM_ARCH_SSE3_BIT + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const had0 = _mm_hadd_ps(mul0, mul0); + glm_vec4 const had1 = _mm_hadd_ps(had0, had0); + return had1; +# else + glm_vec4 const mul0 = _mm_mul_ps(v1, v2); + glm_vec4 const mov0 = _mm_movehl_ps(mul0, mul0); + glm_vec4 const add0 = _mm_add_ps(mov0, mul0); + glm_vec4 const swp1 = _mm_shuffle_ps(add0, add0, 1); + glm_vec4 const add1 = _mm_add_ss(add0, swp1); + return add1; +# endif +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_cross(glm_vec4 v1, glm_vec4 v2) +{ + glm_vec4 const swp0 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 0, 2, 1)); + glm_vec4 const swp1 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 1, 0, 2)); + glm_vec4 const swp2 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 0, 2, 1)); + glm_vec4 const swp3 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 1, 0, 2)); + glm_vec4 const mul0 = _mm_mul_ps(swp0, swp3); + glm_vec4 const mul1 = _mm_mul_ps(swp1, swp2); + glm_vec4 const sub0 = _mm_sub_ps(mul0, mul1); + return sub0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_normalize(glm_vec4 v) +{ + glm_vec4 const dot0 = glm_vec4_dot(v, v); + glm_vec4 const isr0 = _mm_rsqrt_ps(dot0); + glm_vec4 const mul0 = _mm_mul_ps(v, isr0); + return mul0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_faceforward(glm_vec4 N, glm_vec4 I, glm_vec4 Nref) +{ + glm_vec4 const dot0 = glm_vec4_dot(Nref, I); + glm_vec4 const sgn0 = glm_vec4_sign(dot0); + glm_vec4 const mul0 = _mm_mul_ps(sgn0, _mm_set1_ps(-1.0f)); + glm_vec4 const mul1 = _mm_mul_ps(N, mul0); + return mul1; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_vec4_reflect(glm_vec4 I, glm_vec4 N) +{ + glm_vec4 const dot0 = glm_vec4_dot(N, I); + glm_vec4 const mul0 = _mm_mul_ps(N, dot0); + glm_vec4 const mul1 = _mm_mul_ps(mul0, _mm_set1_ps(2.0f)); + glm_vec4 const sub0 = _mm_sub_ps(I, mul1); + return sub0; +} + +GLM_FUNC_QUALIFIER __m128 glm_vec4_refract(glm_vec4 I, glm_vec4 N, glm_vec4 eta) +{ + glm_vec4 const dot0 = glm_vec4_dot(N, I); + glm_vec4 const mul0 = _mm_mul_ps(eta, eta); + glm_vec4 const mul1 = _mm_mul_ps(dot0, dot0); + glm_vec4 const sub0 = _mm_sub_ps(_mm_set1_ps(1.0f), mul0); + glm_vec4 const sub1 = _mm_sub_ps(_mm_set1_ps(1.0f), mul1); + glm_vec4 const mul2 = _mm_mul_ps(sub0, sub1); + + if(_mm_movemask_ps(_mm_cmplt_ss(mul2, _mm_set1_ps(0.0f))) == 0) + return _mm_set1_ps(0.0f); + + glm_vec4 const sqt0 = _mm_sqrt_ps(mul2); + glm_vec4 const mad0 = glm_vec4_fma(eta, dot0, sqt0); + glm_vec4 const mul4 = _mm_mul_ps(mad0, N); + glm_vec4 const mul5 = _mm_mul_ps(eta, I); + glm_vec4 const sub2 = _mm_sub_ps(mul5, mul4); + + return sub2; +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/simd/integer.h b/vendor/glm/glm/simd/integer.h new file mode 100644 index 0000000..9381418 --- /dev/null +++ b/vendor/glm/glm/simd/integer.h @@ -0,0 +1,115 @@ +/// @ref simd +/// @file glm/simd/integer.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER glm_uvec4 glm_i128_interleave(glm_uvec4 x) +{ + glm_uvec4 const Mask4 = _mm_set1_epi32(0x0000FFFF); + glm_uvec4 const Mask3 = _mm_set1_epi32(0x00FF00FF); + glm_uvec4 const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + glm_uvec4 const Mask1 = _mm_set1_epi32(0x33333333); + glm_uvec4 const Mask0 = _mm_set1_epi32(0x55555555); + + glm_uvec4 Reg1; + glm_uvec4 Reg2; + + // REG1 = x; + // REG2 = y; + //Reg1 = _mm_unpacklo_epi64(x, y); + Reg1 = x; + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + return Reg1; +} + +GLM_FUNC_QUALIFIER glm_uvec4 glm_i128_interleave2(glm_uvec4 x, glm_uvec4 y) +{ + glm_uvec4 const Mask4 = _mm_set1_epi32(0x0000FFFF); + glm_uvec4 const Mask3 = _mm_set1_epi32(0x00FF00FF); + glm_uvec4 const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + glm_uvec4 const Mask1 = _mm_set1_epi32(0x33333333); + glm_uvec4 const Mask0 = _mm_set1_epi32(0x55555555); + + glm_uvec4 Reg1; + glm_uvec4 Reg2; + + // REG1 = x; + // REG2 = y; + Reg1 = _mm_unpacklo_epi64(x, y); + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + return Reg1; +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/simd/matrix.h b/vendor/glm/glm/simd/matrix.h new file mode 100644 index 0000000..b6c42ea --- /dev/null +++ b/vendor/glm/glm/simd/matrix.h @@ -0,0 +1,1028 @@ +/// @ref simd +/// @file glm/simd/matrix.h + +#pragma once + +#include "geometric.h" + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +GLM_FUNC_QUALIFIER void glm_mat4_matrixCompMult(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + out[0] = _mm_mul_ps(in1[0], in2[0]); + out[1] = _mm_mul_ps(in1[1], in2[1]); + out[2] = _mm_mul_ps(in1[2], in2[2]); + out[3] = _mm_mul_ps(in1[3], in2[3]); +} + +GLM_FUNC_QUALIFIER void glm_mat4_add(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + out[0] = _mm_add_ps(in1[0], in2[0]); + out[1] = _mm_add_ps(in1[1], in2[1]); + out[2] = _mm_add_ps(in1[2], in2[2]); + out[3] = _mm_add_ps(in1[3], in2[3]); +} + +GLM_FUNC_QUALIFIER void glm_mat4_sub(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + out[0] = _mm_sub_ps(in1[0], in2[0]); + out[1] = _mm_sub_ps(in1[1], in2[1]); + out[2] = _mm_sub_ps(in1[2], in2[2]); + out[3] = _mm_sub_ps(in1[3], in2[3]); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_mul_vec4(glm_vec4 const m[4], glm_vec4 v) +{ + __m128 v0 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 v1 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 v2 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 v3 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(m[0], v0); + __m128 m1 = _mm_mul_ps(m[1], v1); + __m128 m2 = _mm_mul_ps(m[2], v2); + __m128 m3 = _mm_mul_ps(m[3], v3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + return a2; +} + +GLM_FUNC_QUALIFIER __m128 glm_vec4_mul_mat4(glm_vec4 v, glm_vec4 const m[4]) +{ + __m128 i0 = m[0]; + __m128 i1 = m[1]; + __m128 i2 = m[2]; + __m128 i3 = m[3]; + + __m128 m0 = _mm_mul_ps(v, i0); + __m128 m1 = _mm_mul_ps(v, i1); + __m128 m2 = _mm_mul_ps(v, i2); + __m128 m3 = _mm_mul_ps(v, i3); + + __m128 u0 = _mm_unpacklo_ps(m0, m1); + __m128 u1 = _mm_unpackhi_ps(m0, m1); + __m128 a0 = _mm_add_ps(u0, u1); + + __m128 u2 = _mm_unpacklo_ps(m2, m3); + __m128 u3 = _mm_unpackhi_ps(m2, m3); + __m128 a1 = _mm_add_ps(u2, u3); + + __m128 f0 = _mm_movelh_ps(a0, a1); + __m128 f1 = _mm_movehl_ps(a1, a0); + __m128 f2 = _mm_add_ps(f0, f1); + + return f2; +} + +GLM_FUNC_QUALIFIER void glm_mat4_mul(glm_vec4 const in1[4], glm_vec4 const in2[4], glm_vec4 out[4]) +{ + { + __m128 e0 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[0] = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[1] = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[2] = a2; + } + + { + //(__m128&)_mm_shuffle_epi32(__m128i&)in2[0], _MM_SHUFFLE(3, 3, 3, 3)) + __m128 e0 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[3] = a2; + } +} + +GLM_FUNC_QUALIFIER void glm_mat4_transpose(glm_vec4 const in[4], glm_vec4 out[4]) +{ + __m128 tmp0 = _mm_shuffle_ps(in[0], in[1], 0x44); + __m128 tmp2 = _mm_shuffle_ps(in[0], in[1], 0xEE); + __m128 tmp1 = _mm_shuffle_ps(in[2], in[3], 0x44); + __m128 tmp3 = _mm_shuffle_ps(in[2], in[3], 0xEE); + + out[0] = _mm_shuffle_ps(tmp0, tmp1, 0x88); + out[1] = _mm_shuffle_ps(tmp0, tmp1, 0xDD); + out[2] = _mm_shuffle_ps(tmp2, tmp3, 0x88); + out[3] = _mm_shuffle_ps(tmp2, tmp3, 0xDD); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_determinant_highp(glm_vec4 const in[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = glm_vec4_dot(in[0], Row2); + return Det0; +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_determinant_lowp(glm_vec4 const m[4]) +{ + // _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128( + + //T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + //T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + //T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + //T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + //T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + //T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + // First 2 columns + __m128 Swp2A = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(0, 1, 1, 2))); + __m128 Swp3A = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(3, 2, 3, 3))); + __m128 MulA = _mm_mul_ps(Swp2A, Swp3A); + + // Second 2 columns + __m128 Swp2B = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(3, 2, 3, 3))); + __m128 Swp3B = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(0, 1, 1, 2))); + __m128 MulB = _mm_mul_ps(Swp2B, Swp3B); + + // Columns subtraction + __m128 SubE = _mm_sub_ps(MulA, MulB); + + // Last 2 rows + __m128 Swp2C = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(0, 0, 1, 2))); + __m128 Swp3C = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(1, 2, 0, 0))); + __m128 MulC = _mm_mul_ps(Swp2C, Swp3C); + __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); + + //vec<4, T, Q> DetCof( + // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + // - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + __m128 SubFacA = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubE), _MM_SHUFFLE(2, 1, 0, 0))); + __m128 SwpFacA = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(0, 0, 0, 1))); + __m128 MulFacA = _mm_mul_ps(SwpFacA, SubFacA); + + __m128 SubTmpB = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(0, 0, 3, 1)); + __m128 SubFacB = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubTmpB), _MM_SHUFFLE(3, 1, 1, 0)));//SubF[0], SubE[3], SubE[3], SubE[1]; + __m128 SwpFacB = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(1, 1, 2, 2))); + __m128 MulFacB = _mm_mul_ps(SwpFacB, SubFacB); + + __m128 SubRes = _mm_sub_ps(MulFacA, MulFacB); + + __m128 SubTmpC = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(1, 0, 2, 2)); + __m128 SubFacC = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubTmpC), _MM_SHUFFLE(3, 3, 2, 0))); + __m128 SwpFacC = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(2, 3, 3, 3))); + __m128 MulFacC = _mm_mul_ps(SwpFacC, SubFacC); + + __m128 AddRes = _mm_add_ps(SubRes, MulFacC); + __m128 DetCof = _mm_mul_ps(AddRes, _mm_setr_ps( 1.0f,-1.0f, 1.0f,-1.0f)); + + //return m[0][0] * DetCof[0] + // + m[0][1] * DetCof[1] + // + m[0][2] * DetCof[2] + // + m[0][3] * DetCof[3]; + + return glm_vec4_dot(m[0], DetCof); +} + +GLM_FUNC_QUALIFIER glm_vec4 glm_mat4_determinant(glm_vec4 const m[4]) +{ + // _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(add) + + //T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + //T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + //T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + //T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + //T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + //T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + // First 2 columns + __m128 Swp2A = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(0, 1, 1, 2)); + __m128 Swp3A = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(3, 2, 3, 3)); + __m128 MulA = _mm_mul_ps(Swp2A, Swp3A); + + // Second 2 columns + __m128 Swp2B = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(3, 2, 3, 3)); + __m128 Swp3B = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(0, 1, 1, 2)); + __m128 MulB = _mm_mul_ps(Swp2B, Swp3B); + + // Columns subtraction + __m128 SubE = _mm_sub_ps(MulA, MulB); + + // Last 2 rows + __m128 Swp2C = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(0, 0, 1, 2)); + __m128 Swp3C = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(1, 2, 0, 0)); + __m128 MulC = _mm_mul_ps(Swp2C, Swp3C); + __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); + + //vec<4, T, Q> DetCof( + // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + // - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + __m128 SubFacA = _mm_shuffle_ps(SubE, SubE, _MM_SHUFFLE(2, 1, 0, 0)); + __m128 SwpFacA = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(0, 0, 0, 1)); + __m128 MulFacA = _mm_mul_ps(SwpFacA, SubFacA); + + __m128 SubTmpB = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(0, 0, 3, 1)); + __m128 SubFacB = _mm_shuffle_ps(SubTmpB, SubTmpB, _MM_SHUFFLE(3, 1, 1, 0));//SubF[0], SubE[3], SubE[3], SubE[1]; + __m128 SwpFacB = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(1, 1, 2, 2)); + __m128 MulFacB = _mm_mul_ps(SwpFacB, SubFacB); + + __m128 SubRes = _mm_sub_ps(MulFacA, MulFacB); + + __m128 SubTmpC = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(1, 0, 2, 2)); + __m128 SubFacC = _mm_shuffle_ps(SubTmpC, SubTmpC, _MM_SHUFFLE(3, 3, 2, 0)); + __m128 SwpFacC = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(2, 3, 3, 3)); + __m128 MulFacC = _mm_mul_ps(SwpFacC, SubFacC); + + __m128 AddRes = _mm_add_ps(SubRes, MulFacC); + __m128 DetCof = _mm_mul_ps(AddRes, _mm_setr_ps( 1.0f,-1.0f, 1.0f,-1.0f)); + + //return m[0][0] * DetCof[0] + // + m[0][1] * DetCof[1] + // + m[0][2] * DetCof[2] + // + m[0][3] * DetCof[3]; + + return glm_vec4_dot(m[0], DetCof); +} + +GLM_FUNC_QUALIFIER void glm_mat4_inverse(glm_vec4 const in[4], glm_vec4 out[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = glm_vec4_dot(in[0], Row2); + __m128 Rcp0 = _mm_div_ps(_mm_set1_ps(1.0f), Det0); + //__m128 Rcp0 = _mm_rcp_ps(Det0); + + // Inverse /= Determinant; + out[0] = _mm_mul_ps(Inv0, Rcp0); + out[1] = _mm_mul_ps(Inv1, Rcp0); + out[2] = _mm_mul_ps(Inv2, Rcp0); + out[3] = _mm_mul_ps(Inv3, Rcp0); +} + +GLM_FUNC_QUALIFIER void glm_mat4_inverse_lowp(glm_vec4 const in[4], glm_vec4 out[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = glm_vec4_dot(in[0], Row2); + __m128 Rcp0 = _mm_rcp_ps(Det0); + //__m128 Rcp0 = _mm_div_ps(one, Det0); + // Inverse /= Determinant; + out[0] = _mm_mul_ps(Inv0, Rcp0); + out[1] = _mm_mul_ps(Inv1, Rcp0); + out[2] = _mm_mul_ps(Inv2, Rcp0); + out[3] = _mm_mul_ps(Inv3, Rcp0); +} +/* +GLM_FUNC_QUALIFIER void glm_mat4_rotate(__m128 const in[4], float Angle, float const v[3], __m128 out[4]) +{ + float a = glm::radians(Angle); + float c = cos(a); + float s = sin(a); + + glm::vec4 AxisA(v[0], v[1], v[2], float(0)); + __m128 AxisB = _mm_set_ps(AxisA.w, AxisA.z, AxisA.y, AxisA.x); + __m128 AxisC = detail::sse_nrm_ps(AxisB); + + __m128 Cos0 = _mm_set_ss(c); + __m128 CosA = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Sin0 = _mm_set_ss(s); + __m128 SinA = _mm_shuffle_ps(Sin0, Sin0, _MM_SHUFFLE(0, 0, 0, 0)); + + // vec<3, T, Q> temp = (valType(1) - c) * axis; + __m128 Temp0 = _mm_sub_ps(one, CosA); + __m128 Temp1 = _mm_mul_ps(Temp0, AxisC); + + //Rotate[0][0] = c + temp[0] * axis[0]; + //Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + //Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + __m128 Axis0 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 TmpA0 = _mm_mul_ps(Axis0, AxisC); + __m128 CosA0 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 1, 1, 0)); + __m128 TmpA1 = _mm_add_ps(CosA0, TmpA0); + __m128 SinA0 = SinA;//_mm_set_ps(0.0f, s, -s, 0.0f); + __m128 TmpA2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 1, 2, 3)); + __m128 TmpA3 = _mm_mul_ps(SinA0, TmpA2); + __m128 TmpA4 = _mm_add_ps(TmpA1, TmpA3); + + //Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + //Rotate[1][1] = c + temp[1] * axis[1]; + //Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + __m128 Axis1 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 TmpB0 = _mm_mul_ps(Axis1, AxisC); + __m128 CosA1 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 1, 0, 1)); + __m128 TmpB1 = _mm_add_ps(CosA1, TmpB0); + __m128 SinB0 = SinA;//_mm_set_ps(-s, 0.0f, s, 0.0f); + __m128 TmpB2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 0, 3, 2)); + __m128 TmpB3 = _mm_mul_ps(SinA0, TmpB2); + __m128 TmpB4 = _mm_add_ps(TmpB1, TmpB3); + + //Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + //Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + //Rotate[2][2] = c + temp[2] * axis[2]; + __m128 Axis2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 TmpC0 = _mm_mul_ps(Axis2, AxisC); + __m128 CosA2 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 0, 1, 1)); + __m128 TmpC1 = _mm_add_ps(CosA2, TmpC0); + __m128 SinC0 = SinA;//_mm_set_ps(s, -s, 0.0f, 0.0f); + __m128 TmpC2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 3, 0, 1)); + __m128 TmpC3 = _mm_mul_ps(SinA0, TmpC2); + __m128 TmpC4 = _mm_add_ps(TmpC1, TmpC3); + + __m128 Result[4]; + Result[0] = TmpA4; + Result[1] = TmpB4; + Result[2] = TmpC4; + Result[3] = _mm_set_ps(1, 0, 0, 0); + + //mat<4, 4, valType> Result; + //Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + //Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + //Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + //Result[3] = m[3]; + //return Result; + sse_mul_ps(in, Result, out); +} +*/ +GLM_FUNC_QUALIFIER void glm_mat4_outerProduct(__m128 const& c, __m128 const& r, __m128 out[4]) +{ + out[0] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(0, 0, 0, 0))); + out[1] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(1, 1, 1, 1))); + out[2] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(2, 2, 2, 2))); + out[3] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(3, 3, 3, 3))); +} + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/simd/neon.h b/vendor/glm/glm/simd/neon.h new file mode 100644 index 0000000..6c38b06 --- /dev/null +++ b/vendor/glm/glm/simd/neon.h @@ -0,0 +1,155 @@ +/// @ref simd_neon +/// @file glm/simd/neon.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_NEON_BIT +#include + +namespace glm { + namespace neon { + static float32x4_t dupq_lane(float32x4_t vsrc, int lane) { + switch(lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + case 0: return vdupq_laneq_f32(vsrc, 0); + case 1: return vdupq_laneq_f32(vsrc, 1); + case 2: return vdupq_laneq_f32(vsrc, 2); + case 3: return vdupq_laneq_f32(vsrc, 3); +#else + case 0: return vdupq_n_f32(vgetq_lane_f32(vsrc, 0)); + case 1: return vdupq_n_f32(vgetq_lane_f32(vsrc, 1)); + case 2: return vdupq_n_f32(vgetq_lane_f32(vsrc, 2)); + case 3: return vdupq_n_f32(vgetq_lane_f32(vsrc, 3)); +#endif + } + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); + } + + static float32x2_t dup_lane(float32x4_t vsrc, int lane) { + switch(lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + case 0: return vdup_laneq_f32(vsrc, 0); + case 1: return vdup_laneq_f32(vsrc, 1); + case 2: return vdup_laneq_f32(vsrc, 2); + case 3: return vdup_laneq_f32(vsrc, 3); +#else + case 0: return vdup_n_f32(vgetq_lane_f32(vsrc, 0)); + case 1: return vdup_n_f32(vgetq_lane_f32(vsrc, 1)); + case 2: return vdup_n_f32(vgetq_lane_f32(vsrc, 2)); + case 3: return vdup_n_f32(vgetq_lane_f32(vsrc, 3)); +#endif + } + assert(!"Unreachable code executed!"); + return vdup_n_f32(0.0f); + } + + static float32x4_t copy_lane(float32x4_t vdst, int dlane, float32x4_t vsrc, int slane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + switch(dlane) { + case 0: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 0, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 0, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 0, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 0, vsrc, 3); + } + assert(!"Unreachable code executed!"); + case 1: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 1, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 1, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 1, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 1, vsrc, 3); + } + assert(!"Unreachable code executed!"); + case 2: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 2, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 2, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 2, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 2, vsrc, 3); + } + assert(!"Unreachable code executed!"); + case 3: + switch(slane) { + case 0: return vcopyq_laneq_f32(vdst, 3, vsrc, 0); + case 1: return vcopyq_laneq_f32(vdst, 3, vsrc, 1); + case 2: return vcopyq_laneq_f32(vdst, 3, vsrc, 2); + case 3: return vcopyq_laneq_f32(vdst, 3, vsrc, 3); + } + assert(!"Unreachable code executed!"); + } +#else + + float l; + switch(slane) { + case 0: l = vgetq_lane_f32(vsrc, 0); break; + case 1: l = vgetq_lane_f32(vsrc, 1); break; + case 2: l = vgetq_lane_f32(vsrc, 2); break; + case 3: l = vgetq_lane_f32(vsrc, 3); break; + default: + assert(!"Unreachable code executed!"); + } + switch(dlane) { + case 0: return vsetq_lane_f32(l, vdst, 0); + case 1: return vsetq_lane_f32(l, vdst, 1); + case 2: return vsetq_lane_f32(l, vdst, 2); + case 3: return vsetq_lane_f32(l, vdst, 3); + } +#endif + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); + } + + static float32x4_t mul_lane(float32x4_t v, float32x4_t vlane, int lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + switch(lane) { + case 0: return vmulq_laneq_f32(v, vlane, 0); break; + case 1: return vmulq_laneq_f32(v, vlane, 1); break; + case 2: return vmulq_laneq_f32(v, vlane, 2); break; + case 3: return vmulq_laneq_f32(v, vlane, 3); break; + default: + assert(!"Unreachable code executed!"); + } + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); +#else + return vmulq_f32(v, dupq_lane(vlane, lane)); +#endif + } + + static float32x4_t madd_lane(float32x4_t acc, float32x4_t v, float32x4_t vlane, int lane) { +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT +#ifdef GLM_CONFIG_FORCE_FMA +# define FMADD_LANE(acc, x, y, L) do { asm volatile ("fmla %0.4s, %1.4s, %2.4s" : "+w"(acc) : "w"(x), "w"(dup_lane(y, L))); } while(0) +#else +# define FMADD_LANE(acc, x, y, L) do { acc = vmlaq_laneq_f32(acc, x, y, L); } while(0) +#endif + + switch(lane) { + case 0: + FMADD_LANE(acc, v, vlane, 0); + return acc; + case 1: + FMADD_LANE(acc, v, vlane, 1); + return acc; + case 2: + FMADD_LANE(acc, v, vlane, 2); + return acc; + case 3: + FMADD_LANE(acc, v, vlane, 3); + return acc; + default: + assert(!"Unreachable code executed!"); + } + assert(!"Unreachable code executed!"); + return vdupq_n_f32(0.0f); +# undef FMADD_LANE +#else + return vaddq_f32(acc, vmulq_f32(v, dupq_lane(vlane, lane))); +#endif + } + } //namespace neon +} // namespace glm +#endif // GLM_ARCH & GLM_ARCH_NEON_BIT diff --git a/vendor/glm/glm/simd/packing.h b/vendor/glm/glm/simd/packing.h new file mode 100644 index 0000000..609163e --- /dev/null +++ b/vendor/glm/glm/simd/packing.h @@ -0,0 +1,8 @@ +/// @ref simd +/// @file glm/simd/packing.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/simd/platform.h b/vendor/glm/glm/simd/platform.h new file mode 100644 index 0000000..ad25cc1 --- /dev/null +++ b/vendor/glm/glm/simd/platform.h @@ -0,0 +1,398 @@ +#pragma once + +/////////////////////////////////////////////////////////////////////////////////// +// Platform + +#define GLM_PLATFORM_UNKNOWN 0x00000000 +#define GLM_PLATFORM_WINDOWS 0x00010000 +#define GLM_PLATFORM_LINUX 0x00020000 +#define GLM_PLATFORM_APPLE 0x00040000 +//#define GLM_PLATFORM_IOS 0x00080000 +#define GLM_PLATFORM_ANDROID 0x00100000 +#define GLM_PLATFORM_CHROME_NACL 0x00200000 +#define GLM_PLATFORM_UNIX 0x00400000 +#define GLM_PLATFORM_QNXNTO 0x00800000 +#define GLM_PLATFORM_WINCE 0x01000000 +#define GLM_PLATFORM_CYGWIN 0x02000000 + +#ifdef GLM_FORCE_PLATFORM_UNKNOWN +# define GLM_PLATFORM GLM_PLATFORM_UNKNOWN +#elif defined(__CYGWIN__) +# define GLM_PLATFORM GLM_PLATFORM_CYGWIN +#elif defined(__QNXNTO__) +# define GLM_PLATFORM GLM_PLATFORM_QNXNTO +#elif defined(__APPLE__) +# define GLM_PLATFORM GLM_PLATFORM_APPLE +#elif defined(WINCE) +# define GLM_PLATFORM GLM_PLATFORM_WINCE +#elif defined(_WIN32) +# define GLM_PLATFORM GLM_PLATFORM_WINDOWS +#elif defined(__native_client__) +# define GLM_PLATFORM GLM_PLATFORM_CHROME_NACL +#elif defined(__ANDROID__) +# define GLM_PLATFORM GLM_PLATFORM_ANDROID +#elif defined(__linux) +# define GLM_PLATFORM GLM_PLATFORM_LINUX +#elif defined(__unix) +# define GLM_PLATFORM GLM_PLATFORM_UNIX +#else +# define GLM_PLATFORM GLM_PLATFORM_UNKNOWN +#endif// + +/////////////////////////////////////////////////////////////////////////////////// +// Compiler + +#define GLM_COMPILER_UNKNOWN 0x00000000 + +// Intel +#define GLM_COMPILER_INTEL 0x00100000 +#define GLM_COMPILER_INTEL14 0x00100040 +#define GLM_COMPILER_INTEL15 0x00100050 +#define GLM_COMPILER_INTEL16 0x00100060 +#define GLM_COMPILER_INTEL17 0x00100070 + +// Visual C++ defines +#define GLM_COMPILER_VC 0x01000000 +#define GLM_COMPILER_VC12 0x01000001 +#define GLM_COMPILER_VC14 0x01000002 +#define GLM_COMPILER_VC15 0x01000003 +#define GLM_COMPILER_VC15_3 0x01000004 +#define GLM_COMPILER_VC15_5 0x01000005 +#define GLM_COMPILER_VC15_6 0x01000006 +#define GLM_COMPILER_VC15_7 0x01000007 +#define GLM_COMPILER_VC15_8 0x01000008 +#define GLM_COMPILER_VC15_9 0x01000009 +#define GLM_COMPILER_VC16 0x0100000A + +// GCC defines +#define GLM_COMPILER_GCC 0x02000000 +#define GLM_COMPILER_GCC46 0x020000D0 +#define GLM_COMPILER_GCC47 0x020000E0 +#define GLM_COMPILER_GCC48 0x020000F0 +#define GLM_COMPILER_GCC49 0x02000100 +#define GLM_COMPILER_GCC5 0x02000200 +#define GLM_COMPILER_GCC6 0x02000300 +#define GLM_COMPILER_GCC7 0x02000400 +#define GLM_COMPILER_GCC8 0x02000500 + +// CUDA +#define GLM_COMPILER_CUDA 0x10000000 +#define GLM_COMPILER_CUDA75 0x10000001 +#define GLM_COMPILER_CUDA80 0x10000002 +#define GLM_COMPILER_CUDA90 0x10000004 + +// SYCL +#define GLM_COMPILER_SYCL 0x00300000 + +// Clang +#define GLM_COMPILER_CLANG 0x20000000 +#define GLM_COMPILER_CLANG34 0x20000050 +#define GLM_COMPILER_CLANG35 0x20000060 +#define GLM_COMPILER_CLANG36 0x20000070 +#define GLM_COMPILER_CLANG37 0x20000080 +#define GLM_COMPILER_CLANG38 0x20000090 +#define GLM_COMPILER_CLANG39 0x200000A0 +#define GLM_COMPILER_CLANG40 0x200000B0 +#define GLM_COMPILER_CLANG41 0x200000C0 +#define GLM_COMPILER_CLANG42 0x200000D0 + +// Build model +#define GLM_MODEL_32 0x00000010 +#define GLM_MODEL_64 0x00000020 + +// Force generic C++ compiler +#ifdef GLM_FORCE_COMPILER_UNKNOWN +# define GLM_COMPILER GLM_COMPILER_UNKNOWN + +#elif defined(__INTEL_COMPILER) +# if __INTEL_COMPILER >= 1700 +# define GLM_COMPILER GLM_COMPILER_INTEL17 +# elif __INTEL_COMPILER >= 1600 +# define GLM_COMPILER GLM_COMPILER_INTEL16 +# elif __INTEL_COMPILER >= 1500 +# define GLM_COMPILER GLM_COMPILER_INTEL15 +# elif __INTEL_COMPILER >= 1400 +# define GLM_COMPILER GLM_COMPILER_INTEL14 +# elif __INTEL_COMPILER < 1400 +# error "GLM requires ICC 2013 SP1 or newer" +# endif + +// CUDA +#elif defined(__CUDACC__) +# if !defined(CUDA_VERSION) && !defined(GLM_FORCE_CUDA) +# include // make sure version is defined since nvcc does not define it itself! +# endif +# if CUDA_VERSION >= 8000 +# define GLM_COMPILER GLM_COMPILER_CUDA80 +# elif CUDA_VERSION >= 7500 +# define GLM_COMPILER GLM_COMPILER_CUDA75 +# elif CUDA_VERSION >= 7000 +# define GLM_COMPILER GLM_COMPILER_CUDA70 +# elif CUDA_VERSION < 7000 +# error "GLM requires CUDA 7.0 or higher" +# endif + +// SYCL +#elif defined(__SYCL_DEVICE_ONLY__) +# define GLM_COMPILER GLM_COMPILER_SYCL + +// Clang +#elif defined(__clang__) +# if defined(__apple_build_version__) +# if (__clang_major__ < 6) +# error "GLM requires Clang 3.4 / Apple Clang 6.0 or higher" +# elif __clang_major__ == 6 && __clang_minor__ == 0 +# define GLM_COMPILER GLM_COMPILER_CLANG35 +# elif __clang_major__ == 6 && __clang_minor__ >= 1 +# define GLM_COMPILER GLM_COMPILER_CLANG36 +# elif __clang_major__ >= 7 +# define GLM_COMPILER GLM_COMPILER_CLANG37 +# endif +# else +# if ((__clang_major__ == 3) && (__clang_minor__ < 4)) || (__clang_major__ < 3) +# error "GLM requires Clang 3.4 or higher" +# elif __clang_major__ == 3 && __clang_minor__ == 4 +# define GLM_COMPILER GLM_COMPILER_CLANG34 +# elif __clang_major__ == 3 && __clang_minor__ == 5 +# define GLM_COMPILER GLM_COMPILER_CLANG35 +# elif __clang_major__ == 3 && __clang_minor__ == 6 +# define GLM_COMPILER GLM_COMPILER_CLANG36 +# elif __clang_major__ == 3 && __clang_minor__ == 7 +# define GLM_COMPILER GLM_COMPILER_CLANG37 +# elif __clang_major__ == 3 && __clang_minor__ == 8 +# define GLM_COMPILER GLM_COMPILER_CLANG38 +# elif __clang_major__ == 3 && __clang_minor__ >= 9 +# define GLM_COMPILER GLM_COMPILER_CLANG39 +# elif __clang_major__ == 4 && __clang_minor__ == 0 +# define GLM_COMPILER GLM_COMPILER_CLANG40 +# elif __clang_major__ == 4 && __clang_minor__ == 1 +# define GLM_COMPILER GLM_COMPILER_CLANG41 +# elif __clang_major__ == 4 && __clang_minor__ >= 2 +# define GLM_COMPILER GLM_COMPILER_CLANG42 +# elif __clang_major__ >= 4 +# define GLM_COMPILER GLM_COMPILER_CLANG42 +# endif +# endif + +// Visual C++ +#elif defined(_MSC_VER) +# if _MSC_VER >= 1920 +# define GLM_COMPILER GLM_COMPILER_VC16 +# elif _MSC_VER >= 1916 +# define GLM_COMPILER GLM_COMPILER_VC15_9 +# elif _MSC_VER >= 1915 +# define GLM_COMPILER GLM_COMPILER_VC15_8 +# elif _MSC_VER >= 1914 +# define GLM_COMPILER GLM_COMPILER_VC15_7 +# elif _MSC_VER >= 1913 +# define GLM_COMPILER GLM_COMPILER_VC15_6 +# elif _MSC_VER >= 1912 +# define GLM_COMPILER GLM_COMPILER_VC15_5 +# elif _MSC_VER >= 1911 +# define GLM_COMPILER GLM_COMPILER_VC15_3 +# elif _MSC_VER >= 1910 +# define GLM_COMPILER GLM_COMPILER_VC15 +# elif _MSC_VER >= 1900 +# define GLM_COMPILER GLM_COMPILER_VC14 +# elif _MSC_VER >= 1800 +# define GLM_COMPILER GLM_COMPILER_VC12 +# elif _MSC_VER < 1800 +# error "GLM requires Visual C++ 12 - 2013 or higher" +# endif//_MSC_VER + +// G++ +#elif defined(__GNUC__) || defined(__MINGW32__) +# if __GNUC__ >= 8 +# define GLM_COMPILER GLM_COMPILER_GCC8 +# elif __GNUC__ >= 7 +# define GLM_COMPILER GLM_COMPILER_GCC7 +# elif __GNUC__ >= 6 +# define GLM_COMPILER GLM_COMPILER_GCC6 +# elif __GNUC__ >= 5 +# define GLM_COMPILER GLM_COMPILER_GCC5 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9 +# define GLM_COMPILER GLM_COMPILER_GCC49 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 8 +# define GLM_COMPILER GLM_COMPILER_GCC48 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 7 +# define GLM_COMPILER GLM_COMPILER_GCC47 +# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 6 +# define GLM_COMPILER GLM_COMPILER_GCC46 +# elif ((__GNUC__ == 4) && (__GNUC_MINOR__ < 6)) || (__GNUC__ < 4) +# error "GLM requires GCC 4.6 or higher" +# endif + +#else +# define GLM_COMPILER GLM_COMPILER_UNKNOWN +#endif + +#ifndef GLM_COMPILER +# error "GLM_COMPILER undefined, your compiler may not be supported by GLM. Add #define GLM_COMPILER 0 to ignore this message." +#endif//GLM_COMPILER + +/////////////////////////////////////////////////////////////////////////////////// +// Instruction sets + +// User defines: GLM_FORCE_PURE GLM_FORCE_INTRINSICS GLM_FORCE_SSE2 GLM_FORCE_SSE3 GLM_FORCE_AVX GLM_FORCE_AVX2 GLM_FORCE_AVX2 + +#define GLM_ARCH_MIPS_BIT (0x10000000) +#define GLM_ARCH_PPC_BIT (0x20000000) +#define GLM_ARCH_ARM_BIT (0x40000000) +#define GLM_ARCH_ARMV8_BIT (0x01000000) +#define GLM_ARCH_X86_BIT (0x80000000) + +#define GLM_ARCH_SIMD_BIT (0x00001000) + +#define GLM_ARCH_NEON_BIT (0x00000001) +#define GLM_ARCH_SSE_BIT (0x00000002) +#define GLM_ARCH_SSE2_BIT (0x00000004) +#define GLM_ARCH_SSE3_BIT (0x00000008) +#define GLM_ARCH_SSSE3_BIT (0x00000010) +#define GLM_ARCH_SSE41_BIT (0x00000020) +#define GLM_ARCH_SSE42_BIT (0x00000040) +#define GLM_ARCH_AVX_BIT (0x00000080) +#define GLM_ARCH_AVX2_BIT (0x00000100) + +#define GLM_ARCH_UNKNOWN (0) +#define GLM_ARCH_X86 (GLM_ARCH_X86_BIT) +#define GLM_ARCH_SSE (GLM_ARCH_SSE_BIT | GLM_ARCH_SIMD_BIT | GLM_ARCH_X86) +#define GLM_ARCH_SSE2 (GLM_ARCH_SSE2_BIT | GLM_ARCH_SSE) +#define GLM_ARCH_SSE3 (GLM_ARCH_SSE3_BIT | GLM_ARCH_SSE2) +#define GLM_ARCH_SSSE3 (GLM_ARCH_SSSE3_BIT | GLM_ARCH_SSE3) +#define GLM_ARCH_SSE41 (GLM_ARCH_SSE41_BIT | GLM_ARCH_SSSE3) +#define GLM_ARCH_SSE42 (GLM_ARCH_SSE42_BIT | GLM_ARCH_SSE41) +#define GLM_ARCH_AVX (GLM_ARCH_AVX_BIT | GLM_ARCH_SSE42) +#define GLM_ARCH_AVX2 (GLM_ARCH_AVX2_BIT | GLM_ARCH_AVX) +#define GLM_ARCH_ARM (GLM_ARCH_ARM_BIT) +#define GLM_ARCH_ARMV8 (GLM_ARCH_NEON_BIT | GLM_ARCH_SIMD_BIT | GLM_ARCH_ARM | GLM_ARCH_ARMV8_BIT) +#define GLM_ARCH_NEON (GLM_ARCH_NEON_BIT | GLM_ARCH_SIMD_BIT | GLM_ARCH_ARM) +#define GLM_ARCH_MIPS (GLM_ARCH_MIPS_BIT) +#define GLM_ARCH_PPC (GLM_ARCH_PPC_BIT) + +#if defined(GLM_FORCE_ARCH_UNKNOWN) || defined(GLM_FORCE_PURE) +# define GLM_ARCH GLM_ARCH_UNKNOWN +#elif defined(GLM_FORCE_NEON) +# if __ARM_ARCH >= 8 +# define GLM_ARCH (GLM_ARCH_ARMV8) +# else +# define GLM_ARCH (GLM_ARCH_NEON) +# endif +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_AVX2) +# define GLM_ARCH (GLM_ARCH_AVX2) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_AVX) +# define GLM_ARCH (GLM_ARCH_AVX) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE42) +# define GLM_ARCH (GLM_ARCH_SSE42) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE41) +# define GLM_ARCH (GLM_ARCH_SSE41) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSSE3) +# define GLM_ARCH (GLM_ARCH_SSSE3) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE3) +# define GLM_ARCH (GLM_ARCH_SSE3) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE2) +# define GLM_ARCH (GLM_ARCH_SSE2) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_SSE) +# define GLM_ARCH (GLM_ARCH_SSE) +# define GLM_FORCE_INTRINSICS +#elif defined(GLM_FORCE_INTRINSICS) && !defined(GLM_FORCE_XYZW_ONLY) +# if defined(__AVX2__) +# define GLM_ARCH (GLM_ARCH_AVX2) +# elif defined(__AVX__) +# define GLM_ARCH (GLM_ARCH_AVX) +# elif defined(__SSE4_2__) +# define GLM_ARCH (GLM_ARCH_SSE42) +# elif defined(__SSE4_1__) +# define GLM_ARCH (GLM_ARCH_SSE41) +# elif defined(__SSSE3__) +# define GLM_ARCH (GLM_ARCH_SSSE3) +# elif defined(__SSE3__) +# define GLM_ARCH (GLM_ARCH_SSE3) +# elif defined(__SSE2__) || defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86_FP) +# define GLM_ARCH (GLM_ARCH_SSE2) +# elif defined(__i386__) +# define GLM_ARCH (GLM_ARCH_X86) +# elif defined(__ARM_ARCH) && (__ARM_ARCH >= 8) +# define GLM_ARCH (GLM_ARCH_ARMV8) +# elif defined(__ARM_NEON) +# define GLM_ARCH (GLM_ARCH_ARM | GLM_ARCH_NEON) +# elif defined(__arm__ ) || defined(_M_ARM) +# define GLM_ARCH (GLM_ARCH_ARM) +# elif defined(__mips__ ) +# define GLM_ARCH (GLM_ARCH_MIPS) +# elif defined(__powerpc__ ) || defined(_M_PPC) +# define GLM_ARCH (GLM_ARCH_PPC) +# else +# define GLM_ARCH (GLM_ARCH_UNKNOWN) +# endif +#else +# if defined(__x86_64__) || defined(_M_X64) || defined(_M_IX86) || defined(__i386__) +# define GLM_ARCH (GLM_ARCH_X86) +# elif defined(__arm__) || defined(_M_ARM) +# define GLM_ARCH (GLM_ARCH_ARM) +# elif defined(__powerpc__) || defined(_M_PPC) +# define GLM_ARCH (GLM_ARCH_PPC) +# elif defined(__mips__) +# define GLM_ARCH (GLM_ARCH_MIPS) +# else +# define GLM_ARCH (GLM_ARCH_UNKNOWN) +# endif +#endif + +#if GLM_ARCH & GLM_ARCH_AVX2_BIT +# include +#elif GLM_ARCH & GLM_ARCH_AVX_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSE42_BIT +# if GLM_COMPILER & GLM_COMPILER_CLANG +# include +# endif +# include +#elif GLM_ARCH & GLM_ARCH_SSE41_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSSE3_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSE3_BIT +# include +#elif GLM_ARCH & GLM_ARCH_SSE2_BIT +# include +#elif GLM_ARCH & GLM_ARCH_NEON_BIT +# include "neon.h" +#endif//GLM_ARCH + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + typedef __m128 glm_f32vec4; + typedef __m128i glm_i32vec4; + typedef __m128i glm_u32vec4; + typedef __m128d glm_f64vec2; + typedef __m128i glm_i64vec2; + typedef __m128i glm_u64vec2; + + typedef glm_f32vec4 glm_vec4; + typedef glm_i32vec4 glm_ivec4; + typedef glm_u32vec4 glm_uvec4; + typedef glm_f64vec2 glm_dvec2; +#endif + +#if GLM_ARCH & GLM_ARCH_AVX_BIT + typedef __m256d glm_f64vec4; + typedef glm_f64vec4 glm_dvec4; +#endif + +#if GLM_ARCH & GLM_ARCH_AVX2_BIT + typedef __m256i glm_i64vec4; + typedef __m256i glm_u64vec4; +#endif + +#if GLM_ARCH & GLM_ARCH_NEON_BIT + typedef float32x4_t glm_f32vec4; + typedef int32x4_t glm_i32vec4; + typedef uint32x4_t glm_u32vec4; +#endif diff --git a/vendor/glm/glm/simd/trigonometric.h b/vendor/glm/glm/simd/trigonometric.h new file mode 100644 index 0000000..739b796 --- /dev/null +++ b/vendor/glm/glm/simd/trigonometric.h @@ -0,0 +1,9 @@ +/// @ref simd +/// @file glm/simd/trigonometric.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + diff --git a/vendor/glm/glm/simd/vector_relational.h b/vendor/glm/glm/simd/vector_relational.h new file mode 100644 index 0000000..f7385e9 --- /dev/null +++ b/vendor/glm/glm/simd/vector_relational.h @@ -0,0 +1,8 @@ +/// @ref simd +/// @file glm/simd/vector_relational.h + +#pragma once + +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/vendor/glm/glm/trigonometric.hpp b/vendor/glm/glm/trigonometric.hpp new file mode 100644 index 0000000..fcf07f8 --- /dev/null +++ b/vendor/glm/glm/trigonometric.hpp @@ -0,0 +1,210 @@ +/// @ref core +/// @file glm/trigonometric.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions +/// +/// @defgroup core_func_trigonometric Angle and Trigonometry Functions +/// @ingroup core +/// +/// Function parameters specified as angle are assumed to be in units of radians. +/// In no case will any of these functions result in a divide by zero error. If +/// the divisor of a ratio is 0, then results will be undefined. +/// +/// These all operate component-wise. The description is per component. +/// +/// Include to use these core features. +/// +/// @see ext_vector_trigonometric + +#pragma once + +#include "detail/setup.hpp" +#include "detail/qualifier.hpp" + +namespace glm +{ + /// @addtogroup core_func_trigonometric + /// @{ + + /// Converts degrees to radians and returns the result. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL radians man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec radians(vec const& degrees); + + /// Converts radians to degrees and returns the result. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL degrees man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec degrees(vec const& radians); + + /// The standard trigonometric sine function. + /// The values returned by this function will range from [-1, 1]. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL sin man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec sin(vec const& angle); + + /// The standard trigonometric cosine function. + /// The values returned by this function will range from [-1, 1]. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL cos man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec cos(vec const& angle); + + /// The standard trigonometric tangent function. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL tan man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec tan(vec const& angle); + + /// Arc sine. Returns an angle whose sine is x. + /// The range of values returned by this function is [-PI/2, PI/2]. + /// Results are undefined if |x| > 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL asin man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec asin(vec const& x); + + /// Arc cosine. Returns an angle whose sine is x. + /// The range of values returned by this function is [0, PI]. + /// Results are undefined if |x| > 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL acos man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec acos(vec const& x); + + /// Arc tangent. Returns an angle whose tangent is y/x. + /// The signs of x and y are used to determine what + /// quadrant the angle is in. The range of values returned + /// by this function is [-PI, PI]. Results are undefined + /// if x and y are both 0. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL atan man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec atan(vec const& y, vec const& x); + + /// Arc tangent. Returns an angle whose tangent is y_over_x. + /// The range of values returned by this function is [-PI/2, PI/2]. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL atan man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec atan(vec const& y_over_x); + + /// Returns the hyperbolic sine function, (exp(x) - exp(-x)) / 2 + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL sinh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec sinh(vec const& angle); + + /// Returns the hyperbolic cosine function, (exp(x) + exp(-x)) / 2 + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL cosh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec cosh(vec const& angle); + + /// Returns the hyperbolic tangent function, sinh(angle) / cosh(angle) + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL tanh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec tanh(vec const& angle); + + /// Arc hyperbolic sine; returns the inverse of sinh. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL asinh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec asinh(vec const& x); + + /// Arc hyperbolic cosine; returns the non-negative inverse + /// of cosh. Results are undefined if x < 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL acosh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec acosh(vec const& x); + + /// Arc hyperbolic tangent; returns the inverse of tanh. + /// Results are undefined if abs(x) >= 1. + /// + /// @tparam L Integer between 1 and 4 included that qualify the dimension of the vector + /// @tparam T Floating-point scalar types + /// @tparam Q Value from qualifier enum + /// + /// @see GLSL atanh man page + /// @see GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions + template + GLM_FUNC_DECL vec atanh(vec const& x); + + /// @} +}//namespace glm + +#include "detail/func_trigonometric.inl" diff --git a/vendor/glm/glm/vec2.hpp b/vendor/glm/glm/vec2.hpp new file mode 100644 index 0000000..cd4e070 --- /dev/null +++ b/vendor/glm/glm/vec2.hpp @@ -0,0 +1,14 @@ +/// @ref core +/// @file glm/vec2.hpp + +#pragma once +#include "./ext/vector_bool2.hpp" +#include "./ext/vector_bool2_precision.hpp" +#include "./ext/vector_float2.hpp" +#include "./ext/vector_float2_precision.hpp" +#include "./ext/vector_double2.hpp" +#include "./ext/vector_double2_precision.hpp" +#include "./ext/vector_int2.hpp" +#include "./ext/vector_int2_sized.hpp" +#include "./ext/vector_uint2.hpp" +#include "./ext/vector_uint2_sized.hpp" diff --git a/vendor/glm/glm/vec3.hpp b/vendor/glm/glm/vec3.hpp new file mode 100644 index 0000000..f5a927d --- /dev/null +++ b/vendor/glm/glm/vec3.hpp @@ -0,0 +1,14 @@ +/// @ref core +/// @file glm/vec3.hpp + +#pragma once +#include "./ext/vector_bool3.hpp" +#include "./ext/vector_bool3_precision.hpp" +#include "./ext/vector_float3.hpp" +#include "./ext/vector_float3_precision.hpp" +#include "./ext/vector_double3.hpp" +#include "./ext/vector_double3_precision.hpp" +#include "./ext/vector_int3.hpp" +#include "./ext/vector_int3_sized.hpp" +#include "./ext/vector_uint3.hpp" +#include "./ext/vector_uint3_sized.hpp" diff --git a/vendor/glm/glm/vec4.hpp b/vendor/glm/glm/vec4.hpp new file mode 100644 index 0000000..c6ea9f1 --- /dev/null +++ b/vendor/glm/glm/vec4.hpp @@ -0,0 +1,15 @@ +/// @ref core +/// @file glm/vec4.hpp + +#pragma once +#include "./ext/vector_bool4.hpp" +#include "./ext/vector_bool4_precision.hpp" +#include "./ext/vector_float4.hpp" +#include "./ext/vector_float4_precision.hpp" +#include "./ext/vector_double4.hpp" +#include "./ext/vector_double4_precision.hpp" +#include "./ext/vector_int4.hpp" +#include "./ext/vector_int4_sized.hpp" +#include "./ext/vector_uint4.hpp" +#include "./ext/vector_uint4_sized.hpp" + diff --git a/vendor/glm/glm/vector_relational.hpp b/vendor/glm/glm/vector_relational.hpp new file mode 100644 index 0000000..a0fe17e --- /dev/null +++ b/vendor/glm/glm/vector_relational.hpp @@ -0,0 +1,121 @@ +/// @ref core +/// @file glm/vector_relational.hpp +/// +/// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions +/// +/// @defgroup core_func_vector_relational Vector Relational Functions +/// @ingroup core +/// +/// Relational and equality operators (<, <=, >, >=, ==, !=) are defined to +/// operate on scalars and produce scalar Boolean results. For vector results, +/// use the following built-in functions. +/// +/// In all cases, the sizes of all the input and return vectors for any particular +/// call must match. +/// +/// Include to use these core features. +/// +/// @see ext_vector_relational + +#pragma once + +#include "detail/qualifier.hpp" +#include "detail/setup.hpp" + +namespace glm +{ + /// @addtogroup core_func_vector_relational + /// @{ + + /// Returns the component-wise comparison result of x < y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL lessThan man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec lessThan(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x <= y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL lessThanEqual man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec lessThanEqual(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x > y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL greaterThan man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec greaterThan(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x >= y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point or integer scalar type. + /// + /// @see GLSL greaterThanEqual man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec greaterThanEqual(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x == y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point, integer or bool scalar type. + /// + /// @see GLSL equal man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec equal(vec const& x, vec const& y); + + /// Returns the component-wise comparison of result x != y. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// @tparam T A floating-point, integer or bool scalar type. + /// + /// @see GLSL notEqual man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec notEqual(vec const& x, vec const& y); + + /// Returns true if any component of x is true. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL any man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR bool any(vec const& v); + + /// Returns true if all components of x are true. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL all man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR bool all(vec const& v); + + /// Returns the component-wise logical complement of x. + /// /!\ Because of language incompatibilities between C++ and GLSL, GLM defines the function not but not_ instead. + /// + /// @tparam L An integer between 1 and 4 included that qualify the dimension of the vector. + /// + /// @see GLSL not man page + /// @see GLSL 4.20.8 specification, section 8.7 Vector Relational Functions + template + GLM_FUNC_DECL GLM_CONSTEXPR vec not_(vec const& v); + + /// @} +}//namespace glm + +#include "detail/func_vector_relational.inl" diff --git a/vendor/glm/manual.md b/vendor/glm/manual.md new file mode 100644 index 0000000..a7f6956 --- /dev/null +++ b/vendor/glm/manual.md @@ -0,0 +1,2411 @@ +![Alt](./doc/manual/logo-mini.png "GLM Logo") + +# GLM 0.9.9 Manual + +![Alt](./doc/manual/g-truc.png "G-Truc Logo") + +--- +

+ +## Table of Contents ++ [0. Licenses](#section0) ++ [1. Getting started](#section1) ++ [1.1. Using global headers](#section1_1) ++ [1.2. Using separated headers](#section1_2) ++ [1.3. Using extension headers](#section1_3) ++ [1.4. Dependencies](#section1_4) ++ [1.5. Finding GLM with CMake](#section1_5) ++ [2. Preprocessor configurations](#section2) ++ [2.1. GLM\_FORCE\_MESSAGES: Platform auto detection and default configuration](#section2_1) ++ [2.2. GLM\_FORCE\_PLATFORM\_UNKNOWN: Force GLM to no detect the build platform](#section2_2) ++ [2.3. GLM\_FORCE\_COMPILER\_UNKNOWN: Force GLM to no detect the C++ compiler](#section2_3) ++ [2.4. GLM\_FORCE\_ARCH\_UNKNOWN: Force GLM to no detect the build architecture](#section2_4) ++ [2.5. GLM\_FORCE\_CXX\_UNKNOWN: Force GLM to no detect the C++ standard](#section2_5) ++ [2.6. GLM\_FORCE\_CXX**: C++ language detection](#section2_6) ++ [2.7. GLM\_FORCE\_EXPLICIT\_CTOR: Requiring explicit conversions](#section2_7) ++ [2.8. GLM\_FORCE\_INLINE: Force inline](#section2_8) ++ [2.9. GLM\_FORCE\_ALIGNED\_GENTYPES: Force GLM to enable aligned types](#section2_9) ++ [2.10. GLM\_FORCE\_DEFAULT\_ALIGNED\_GENTYPES: Force GLM to use aligned types by default](#section2_10) ++ [2.11. GLM\_FORCE\_INTRINSICS: Using SIMD optimizations](#section2_11) ++ [2.12. GLM\_FORCE\_PRECISION\_**: Default precision](#section2_12) ++ [2.13. GLM\_FORCE\_SINGLE\_ONLY: Removed explicit 64-bits floating point types](#section2_13) ++ [2.14. GLM\_FORCE\_SWIZZLE: Enable swizzle operators](#section2_14) ++ [2.15. GLM\_FORCE\_XYZW\_ONLY: Only exposes x, y, z and w components](#section2_15) ++ [2.16. GLM\_FORCE\_LEFT\_HANDED: Force left handed coordinate system](#section2_16) ++ [2.17. GLM\_FORCE\_DEPTH\_ZERO\_TO\_ONE: Force the use of a clip space between 0 to 1](#section2_17) ++ [2.18. GLM\_FORCE\_SIZE\_T\_LENGTH: Vector and matrix static size type](#section2_18) ++ [2.19. GLM\_FORCE\_UNRESTRICTED\_GENTYPE: Removing genType restriction](#section2_19) ++ [2.20. GLM\_FORCE\_SILENT\_WARNINGS: Silent C++ warnings from language extensions](#section2_20) ++ [2.21. GLM\_FORCE\_QUAT\_DATA\_WXYZ: Force GLM to store quat data as w,x,y,z instead of x,y,z,w](#section2_21) ++ [3. Stable extensions](#section3) ++ [3.1. Scalar types](#section3_1) ++ [3.2. Scalar functions](#section3_2) ++ [3.3. Vector types](#section3_3) ++ [3.4. Vector types with precision qualifiers](#section3_4) ++ [3.5. Vector functions](#section3_5) ++ [3.6. Matrix types](#section3_6) ++ [3.7. Matrix types with precision qualifiers](#section3_7) ++ [3.8. Matrix functions](#section3_8) ++ [3.9. Quaternion types](#section3_9) ++ [3.10. Quaternion types with precision qualifiers](#section3_10) ++ [3.11. Quaternion functions](#section3_11) ++ [4. Recommended extensions](#section4) ++ [4.1. GLM_GTC_bitfield](#section4_1) ++ [4.2. GLM_GTC_color_space](#section4_2) ++ [4.3. GLM_GTC_constants](#section4_3) ++ [4.4. GLM_GTC_epsilon](#section4_4) ++ [4.5. GLM_GTC_integer](#section4_5) ++ [4.6. GLM_GTC_matrix_access](#section4_6) ++ [4.7. GLM_GTC_matrix_integer](#section4_7) ++ [4.8. GLM_GTC_matrix_inverse](#section4_8) ++ [4.9. GLM_GTC_matrix_transform](#section4_9) ++ [4.10. GLM_GTC_noise](#section4_10) ++ [4.11. GLM_GTC_packing](#section4_11) ++ [4.12. GLM_GTC_quaternion](#section4_12) ++ [4.13. GLM_GTC_random](#section4_13) ++ [4.14. GLM_GTC_reciprocal](#section4_14) ++ [4.15. GLM_GTC_round](#section4_15) ++ [4.16. GLM_GTC_type_alignment](#section4_16) ++ [4.17. GLM_GTC_type_precision](#section4_17) ++ [4.18. GLM_GTC_type_ptr](#section4_18) ++ [4.19. GLM_GTC_ulp](#section4_19) ++ [4.20. GLM_GTC_vec1](#section4_20) ++ [5. OpenGL interoperability](#section5) ++ [5.1. GLM Replacements for deprecated OpenGL functions](#section5_1) ++ [5.2. GLM Replacements for GLU functions](#section5_2) ++ [6. Known issues](#section6) ++ [6.1. Not function](#section6_1) ++ [6.2. Precision qualifiers support](#section6_2) ++ [7. FAQ](#section7) ++ [7.1 Why GLM follows GLSL specification and conventions?](#section7_1) ++ [7.2. Does GLM run GLSL programs?](#section7_2) ++ [7.3. Does a GLSL compiler build GLM codes?](#section7_3) ++ [7.4. Should I use ‘GTX’ extensions?](#section7_4) ++ [7.5. Where can I ask my questions?](#section7_5) ++ [7.6. Where can I find the documentation of extensions?](#section7_6) ++ [7.7. Should I use 'using namespace glm;'?](#section7_7) ++ [7.8. Is GLM fast?](#section7_8) ++ [7.9. When I build with Visual C++ with /w4 warning level, I have warnings...](#section7_9) ++ [7.10. Why some GLM functions can crash because of division by zero?](#section7_10) ++ [7.11. What unit for angles us used in GLM?](#section7_11) ++ [7.12. Windows headers cause build errors...](#section7_12) ++ [7.13. Constant expressions support](#section7_13) ++ [8. Code samples](#section8) ++ [8.1. Compute a triangle normal](#section8_1) ++ [8.2. Matrix transform](#section8_2) ++ [8.3. Vector types](#section8_3) ++ [8.4. Lighting](#section8_4) ++ [9. Contributing to GLM](#section9) ++ [9.1. Submitting bug reports](#section9_1) ++ [9.2. Contributing to GLM with pull request](#section9_2) ++ [9.3. Coding style](#section9_3) ++ [10. References](#section10) ++ [10.1. OpenGL specifications](#section10_1) ++ [10.2. External links](#section10_2) ++ [10.3. Projects using GLM](#section10_3) ++ [10.4. Tutorials using GLM](#section10_4) ++ [10.5. Equivalent for other languages](#section10_5) ++ [10.6. Alternatives to GLM](#section10_6) ++ [10.7. Acknowledgements](#section10_7) + +--- +
+ +## Licenses + +### The Happy Bunny License (Modified MIT License) + +Copyright (c) 2005 - G-Truc Creation + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +Restrictions: By making use of the Software for military purposes, you +choose to make a Bunny unhappy. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +![](./doc/manual/frontpage1.png) + +### The MIT License + +Copyright (c) 2005 - G-Truc Creation + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +![](./doc/manual/frontpage2.png) + +--- +
+ +## 1. Getting started +### 1.1. Using global headers + +GLM is a header-only library, and thus does not need to be compiled. We can use GLM's implementation of GLSL's mathematics functionality by including the `` header: + +```cpp +#include +``` + +To extend the feature set supported by GLM and keeping the library as close to GLSL as possible, new features are implemented as extensions that can be included thought a separated header: +```cpp +// Include all GLM core / GLSL features +#include // vec2, vec3, mat4, radians + +// Include all GLM extensions +#include // perspective, translate, rotate + +glm::mat4 transform(glm::vec2 const& Orientation, glm::vec3 const& Translate, glm::vec3 const& Up) +{ + glm::mat4 Proj = glm::perspective(glm::radians(45.f), 1.33f, 0.1f, 10.f); + glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.f), Translate); + glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Orientation.y, Up); + glm::mat4 View = glm::rotate(ViewRotateX, Orientation.x, Up); + glm::mat4 Model = glm::mat4(1.0f); + return Proj * View * Model; +} +``` + +*Note: Including `` and `` is convenient but pull a lot of code which will significantly increase build time, particularly if these files are included in all source files. We may prefer to use the approaches describe in the two following sections to keep the project build fast.* + +### 1.2. Using separated headers + +GLM relies on C++ templates heavily, and may significantly increase compilation times for projects that use it. Hence, user projects could only include the features they actually use. Following is the list of all the core features, based on GLSL specification, headers: +```cpp +#include // vec2, bvec2, dvec2, ivec2 and uvec2 +#include // vec3, bvec3, dvec3, ivec3 and uvec3 +#include // vec4, bvec4, dvec4, ivec4 and uvec4 +#include // mat2, dmat2 +#include // mat2x3, dmat2x3 +#include // mat2x4, dmat2x4 +#include // mat3x2, dmat3x2 +#include // mat3, dmat3 +#include // mat3x4, dmat2 +#include // mat4x2, dmat4x2 +#include // mat4x3, dmat4x3 +#include // mat4, dmat4 +#include // all the GLSL common functions: abs, min, mix, isnan, fma, etc. +#include // all the GLSL exponential functions: pow, log, exp2, sqrt, etc. +#include // all the GLSL geometry functions: dot, cross, reflect, etc. +#include // all the GLSL integer functions: findMSB, bitfieldExtract, etc. +#include // all the GLSL matrix functions: transpose, inverse, etc. +#include // all the GLSL packing functions: packUnorm4x8, unpackHalf2x16, etc. +#include // all the GLSL trigonometric functions: radians, cos, asin, etc. +#include // all the GLSL vector relational functions: equal, less, etc. +``` + +The following is a code sample using separated core headers and an extension: +```cpp +// Include GLM core features +#include // vec2 +#include // vec3 +#include // mat4 +#include //radians + +// Include GLM extension +#include // perspective, translate, rotate + +glm::mat4 transform(glm::vec2 const& Orientation, glm::vec3 const& Translate, glm::vec3 const& Up) +{ + glm::mat4 Proj = glm::perspective(glm::radians(45.f), 1.33f, 0.1f, 10.f); + glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.f), Translate); + glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Orientation.y, Up); + glm::mat4 View = glm::rotate(ViewRotateX, Orientation.x, Up); + glm::mat4 Model = glm::mat4(1.0f); + return Proj * View * Model; +} +``` + +### 1.3. Using extension headers + +Using GLM through split headers to minimize the project build time: +```cpp +// Include GLM vector extensions: +#include // vec2 +#include // vec3 +#include // radians + +// Include GLM matrix extensions: +#include // mat4 +#include // perspective, translate, rotate + +glm::mat4 transform(glm::vec2 const& Orientation, glm::vec3 const& Translate, glm::vec3 const& Up) +{ + glm::mat4 Proj = glm::perspective(glm::radians(45.f), 1.33f, 0.1f, 10.f); + glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.f), Translate); + glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Orientation.y, Up); + glm::mat4 View = glm::rotate(ViewRotateX, Orientation.x, Up); + glm::mat4 Model = glm::mat4(1.0f); + return Proj * View * Model; +} +``` + +### 1.4. Dependencies + +GLM does not depend on external libraries or headers such as ``, [``](http://www.opengl.org/registry/api/GL/glcorearb.h), ``, ``, or ``. + +### 1.5. Finding GLM with CMake + +GLM packages a `glmConfig.cmake` and `glmConfig-version.cmake` in the root of the repository and the release archives. To find GLM with CMake you can pass `-Dglm_DIR=/cmake/glm/` when running CMake. You can then either add `${GLM_INCLUDE_DIRS}` to your target's include directories, or link against the imported `glm::glm` target. + +--- +
+ +## 2. Preprocessor configurations + +### 2.1. GLM\_FORCE\_MESSAGES: Platform auto detection and default configuration + +When included, GLM will first automatically detect the compiler used, the C++ standard supported, the compiler arguments used to configure itself matching the build environment. + +For example, if the compiler arguments request AVX code generation, GLM will rely on its code path providing AVX optimizations when available. + +We can change GLM configuration using specific C++ preprocessor defines that must be declared before including any GLM headers. + +Using `GLM_FORCE_MESSAGES`, GLM will report the configuration as part of the build log. + +```cpp +#define GLM_FORCE_MESSAGES // Or defined when building (e.g. -DGLM_FORCE_SWIZZLE) +#include +``` + +Example of configuration log generated by `GLM_FORCE_MESSAGES`: +```cpp +GLM: version 0.9.9.1 +GLM: C++ 17 with extensions +GLM: Clang compiler detected +GLM: x86 64 bits with AVX instruction set build target +GLM: Linux platform detected +GLM: GLM_FORCE_SWIZZLE is undefined. swizzling functions or operators are disabled. +GLM: GLM_FORCE_SIZE_T_LENGTH is undefined. .length() returns a glm::length_t, a typedef of int following GLSL. +GLM: GLM_FORCE_UNRESTRICTED_GENTYPE is undefined. Follows strictly GLSL on valid function genTypes. +GLM: GLM_FORCE_DEPTH_ZERO_TO_ONE is undefined. Using negative one to one depth clip space. +GLM: GLM_FORCE_LEFT_HANDED is undefined. Using right handed coordinate system. +``` + +The following subsections describe each configurations and defines. + +### 2.2. GLM\_FORCE\_PLATFORM\_UNKNOWN: Force GLM to no detect the build platform + +`GLM_FORCE_PLATFORM_UNKNOWN` prevents GLM from detecting the build platform. + +### 2.3. GLM\_FORCE\_COMPILER\_UNKNOWN: Force GLM to no detect the C++ compiler + +`GLM_FORCE_COMPILER_UNKNOWN` prevents GLM from detecting the C++ compiler. + +### 2.4. GLM\_FORCE\_ARCH\_UNKNOWN: Force GLM to no detect the build architecture + +`GLM_FORCE_ARCH_UNKNOWN` prevents GLM from detecting the build target architecture. + +### 2.5. GLM\_FORCE\_CXX\_UNKNOWN: Force GLM to no detect the C++ standard + +`GLM_FORCE_CSS_UNKNOWN` prevents GLM from detecting the C++ compiler standard support. + +### 2.6. GLM\_FORCE\_CXX**: C++ language detection + +GLM will automatically take advantage of compilers’ language extensions when enabled. To increase cross platform compatibility and to avoid compiler extensions, a programmer can define `GLM_FORCE_CXX98` before +any inclusion of `` to restrict the language feature set C++98: + +```cpp +#define GLM_FORCE_CXX98 +#include +``` + +For C++11, C++14, and C++17 equivalent defines are available: +* `GLM_FORCE_CXX11` +* `GLM_FORCE_CXX14` +* `GLM_FORCE_CXX17` + +```cpp +#define GLM_FORCE_CXX11 +#include + +// If the compiler doesn’t support C++11, compiler errors will happen. +``` + +`GLM_FORCE_CXX17` overrides `GLM_FORCE_CXX14`; `GLM_FORCE_CXX14` overrides `GLM_FORCE_CXX11`; and `GLM_FORCE_CXX11` overrides `GLM_FORCE_CXX98` defines. + +### 2.7. GLM\_FORCE\_EXPLICIT\_CTOR: Requiring explicit conversions + +GLSL supports implicit conversions of vector and matrix types. For example, an ivec4 can be implicitly converted into `vec4`. + +Often, this behaviour is not desirable but following the spirit of the library, this is the default behavior in GLM. However, GLM 0.9.6 introduced the define `GLM_FORCE_EXPLICIT_CTOR` to require explicit conversion for GLM types. + +```cpp +#include + +void foo() +{ + glm::ivec4 a; + ... + + glm::vec4 b(a); // Explicit conversion, OK + glm::vec4 c = a; // Implicit conversion, OK + ... +} +``` + +With `GLM_FORCE_EXPLICIT_CTOR` define, implicit conversions are not allowed: + +```cpp +#define GLM_FORCE_EXPLICIT_CTOR +#include + +void foo() +{ + glm::ivec4 a; + { + glm::vec4 b(a); // Explicit conversion, OK + glm::vec4 c = a; // Implicit conversion, ERROR + ... +} +``` + +### 2.8. GLM\_FORCE\_INLINE: Force inline + +To push further the software performance, a programmer can define `GLM_FORCE_INLINE` before any inclusion of `` to force the compiler to inline GLM code. + +```cpp +#define GLM_FORCE_INLINE +#include +``` + +### 2.9. GLM\_FORCE\_ALIGNED\_GENTYPES: Force GLM to enable aligned types + +Every object type has the property called alignment requirement, which is an integer value (of type `std::size_t`, always a power of 2) representing the number of bytes between successive addresses at which objects of this type can be allocated. The alignment requirement of a type can be queried with alignof or `std::alignment_of`. The pointer alignment function `std::align` can be used to obtain a suitably-aligned pointer within some buffer, and `std::aligned_storage` can be used to obtain suitably-aligned storage. + +Each object type imposes its alignment requirement on every object of that type; stricter alignment (with larger alignment requirement) can be requested using C++11 `alignas`. + +In order to satisfy alignment requirements of all non-static members of a class, padding may be inserted after some of its members. + +GLM supports both packed and aligned types. Packed types allow filling data structure without inserting extra padding. Aligned GLM types align addresses based on the size of the value type of a GLM type. + +```cpp +#define GLM_FORCE_ALIGNED_GENTYPES +#include +#include + +typedef glm::aligned_vec4 vec4a; +typedef glm::packed_vec4 vec4p; +``` + +### 2.10. GLM\_FORCE\_DEFAULT\_ALIGNED\_GENTYPES: Force GLM to use aligned types by default + +GLM allows using aligned types by default for vector types using `GLM_FORCE_DEFAULT_ALIGNED_GENTYPES`: + +```cpp +#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +#include + +struct MyStruct +{ + glm::vec4 a; + float b; + glm::vec3 c; +}; + +void foo() +{ + printf("MyStruct requires memory padding: %d bytes\n", sizeof(MyStruct)); +} + +>>> MyStruct requires memory padding: 48 bytes +``` + +```cpp +#include + +struct MyStruct +{ + glm::vec4 a; + float b; + glm::vec3 c; +}; + +void foo() +{ + printf("MyStruct is tightly packed: %d bytes\n", sizeof(MyStruct)); +} + +>>> MyStruct is tightly packed: 32 bytes +``` + +*Note: GLM SIMD optimizations require the use of aligned types* + +### 2.11. GLM\_FORCE\_INTRINSICS: Using SIMD optimizations + +GLM provides some SIMD optimizations based on [compiler intrinsics](https://msdn.microsoft.com/en-us/library/26td21ds.aspx). +These optimizations will be automatically thanks to compiler arguments when `GLM_FORCE_INTRINSICS` is defined before including GLM files. +For example, if a program is compiled with Visual Studio using `/arch:AVX`, GLM will detect this argument and generate code using AVX instructions automatically when available. + +It’s possible to avoid the instruction set detection by forcing the use of a specific instruction set with one of the fallowing define: +`GLM_FORCE_SSE2`, `GLM_FORCE_SSE3`, `GLM_FORCE_SSSE3`, `GLM_FORCE_SSE41`, `GLM_FORCE_SSE42`, `GLM_FORCE_AVX`, `GLM_FORCE_AVX2` or `GLM_FORCE_AVX512`. + +The use of intrinsic functions by GLM implementation can be avoided using the define `GLM_FORCE_PURE` before any inclusion of GLM headers. This can be particularly useful if we want to rely on C++14 `constexpr`. + +```cpp +#define GLM_FORCE_PURE +#include + +static_assert(glm::vec4::length() == 4, "Using GLM C++ 14 constexpr support for compile time tests"); + +// GLM code will be compiled using pure C++ code without any intrinsics +``` + +```cpp +#define GLM_FORCE_SIMD_AVX2 +#include + +// If the compiler doesn’t support AVX2 instrinsics, compiler errors will happen. +``` + +Additionally, GLM provides a low level SIMD API in glm/simd directory for users who are really interested in writing fast algorithms. + +### 2.12. GLM\_FORCE\_PRECISION\_**: Default precision + +C++ does not provide a way to implement GLSL default precision selection (as defined in GLSL 4.10 specification section 4.5.3) with GLSL-like syntax. + +```glsl +precision mediump int; +precision highp float; +``` + +To use the default precision functionality, GLM provides some defines that need to added before any include of `glm.hpp`: + +```cpp +#define GLM_FORCE_PRECISION_MEDIUMP_INT +#define GLM_FORCE_PRECISION_HIGHP_FLOAT +#include +``` + +Available defines for floating point types (`glm::vec\*`, `glm::mat\*`): + +* `GLM_FORCE_PRECISION_LOWP_FLOAT`: Low precision +* `GLM_FORCE_PRECISION_MEDIUMP_FLOAT`: Medium precision +* `GLM_FORCE_PRECISION_HIGHP_FLOAT`: High precision (default) + +Available defines for floating point types (`glm::dvec\*`, `glm::dmat\*`): + +* `GLM_FORCE_PRECISION_LOWP_DOUBLE`: Low precision +* `GLM_FORCE_PRECISION_MEDIUMP_DOUBLE`: Medium precision +* `GLM_FORCE_PRECISION_HIGHP_DOUBLE`: High precision (default) + +Available defines for signed integer types (`glm::ivec\*`): + +* `GLM_FORCE_PRECISION_LOWP_INT`: Low precision +* `GLM_FORCE_PRECISION_MEDIUMP_INT`: Medium precision +* `GLM_FORCE_PRECISION_HIGHP_INT`: High precision (default) + +Available defines for unsigned integer types (`glm::uvec\*`): + +* `GLM_FORCE_PRECISION_LOWP_UINT`: Low precision +* `GLM_FORCE_PRECISION_MEDIUMP_UINT`: Medium precision +* `GLM_FORCE_PRECISION_HIGHP_UINT`: High precision (default) + +### 2.13. GLM\_FORCE\_SINGLE\_ONLY: Removed explicit 64-bits floating point types + +Some platforms (Dreamcast) doesn't support double precision floating point values. To compile on such platforms, GCC has the `--m4-single-only` build argument. When defining `GLM_FORCE_SINGLE_ONLY` before including GLM headers, GLM releases the requirement of double precision floating point values support. Effectivement, all the float64 types are no longer defined and double behaves like float. + +### 2.14. GLM\_FORCE\_SWIZZLE: Enable swizzle operators + +Shader languages like GLSL often feature so-called swizzle expressions, which may be used to freely select and arrange a vector's components. For example, `variable.x`, `variable.xzy` and `variable.zxyy` respectively form a scalar, a 3D vector and a 4D vector. The result of a swizzle expression in GLSL can be either an R-value or an L-value. Swizzle expressions can be written with characters from exactly one of `xyzw` (usually for positions), `rgba` (usually for colors), and `stpq` (usually for texture coordinates). + +```glsl +vec4 A; +vec2 B; + +B.yx = A.wy; +B = A.xx; +vec3 C = A.bgr; +vec3 D = B.rsz; // Invalid, won't compile +``` + +GLM supports some of this functionality. Swizzling can be enabled by defining `GLM_FORCE_SWIZZLE`. + +*Note: Enabling swizzle expressions will massively increase the size of your binaries and the time it takes to compile them!* + +GLM has two levels of swizzling support described in the following subsections. + +#### 2.14.1. Swizzle functions for standard C++ 98 + +When compiling GLM as C++98, R-value swizzle expressions are simulated through member functions of each vector type. + +```cpp +#define GLM_FORCE_SWIZZLE // Or defined when building (e.g. -DGLM_FORCE_SWIZZLE) +#include + +void foo() +{ + glm::vec4 const ColorRGBA = glm::vec4(1.0f, 0.5f, 0.0f, 1.0f); + glm::vec3 const ColorBGR = ColorRGBA.bgr(); + + glm::vec3 const PositionA = glm::vec3(1.0f, 0.5f, 0.0f); + glm::vec3 const PositionB = PositionXYZ.xyz() * 2.0f; + + glm::vec2 const TexcoordST = glm::vec2(1.0f, 0.5f); + glm::vec4 const TexcoordSTPQ = TexcoordST.stst(); +} +``` + +Swizzle operators return a **copy** of the component values, and thus *can't* be used as L-values to change a vector's values. + +```cpp +#define GLM_FORCE_SWIZZLE +#include + +void foo() +{ + glm::vec3 const A = glm::vec3(1.0f, 0.5f, 0.0f); + + // No compiler error, but A is not modified. + // An anonymous copy is being modified (and then discarded). + A.bgr() = glm::vec3(2.0f, 1.5f, 1.0f); // A is not modified! +} +``` + +#### 2.14.2. Swizzle operations for C++ 98 with language extensions + +Visual C++, GCC and Clang support, as a _non-standard language extension_, anonymous `struct`s as `union` members. This permits a powerful swizzling implementation that both allows L-value swizzle expressions and GLSL-like syntax. To use this feature, the language extension must be enabled by a supporting compiler and `GLM_FORCE_SWIZZLE` must be `#define`d. + +```cpp +#define GLM_FORCE_SWIZZLE +#include + +// Only guaranteed to work with Visual C++! +// Some compilers that support Microsoft extensions may compile this. +void foo() +{ + glm::vec4 ColorRGBA = glm::vec4(1.0f, 0.5f, 0.0f, 1.0f); + + // l-value: + glm::vec4 ColorBGRA = ColorRGBA.bgra; + + // r-value: + ColorRGBA.bgra = ColorRGBA; + + // Both l-value and r-value + ColorRGBA.bgra = ColorRGBA.rgba; +} +``` + +This version returns implementation-specific objects that _implicitly convert_ to their respective vector types. As a consequence of this design, these extra types **can't be directly used** as C++ function arguments; they must be converted through constructors or `operator()`. + +```cpp +#define GLM_FORCE_SWIZZLE +#include + +using namespace glm; + +void foo() +{ + vec4 Color = vec4(1.0f, 0.5f, 0.0f, 1.0f); + + // Generates compiler errors. Color.rgba is not a vector type. + vec4 ClampedA = clamp(Color.rgba, 0.f, 1.f); // ERROR + + // Explicit conversion through a constructor + vec4 ClampedB = clamp(vec4(Color.rgba), 0.f, 1.f); // OK + + // Explicit conversion through operator() + vec4 ClampedC = clamp(Color.rgba(), 0.f, 1.f); // OK +} +``` + +*Note: The implementation has a caveat: Swizzle operator types must be different on both size of the equal operator or the operation will fail. There is no known fix for this issue to date* + +### 2.15. GLM\_FORCE\_XYZW\_ONLY: Only exposes x, y, z and w components + +Following GLSL specifications, GLM supports three sets of components to access vector types member: x, y, z, w; r, g, b, a; and s, t, p, q. +Also, this is making vector component very expressive in the code, it may make debugging vector types a little cubersom as the debuggers will typically display three time the values for each compoenents due to the existence of the three sets. + +To simplify vector types, GLM allows exposing only x, y, z and w components thanks to `GLM_FORCE_XYZW_ONLY` define. + +### 2.16. GLM\_FORCE\_LEFT\_HANDED: Force left handed coordinate system + +By default, OpenGL is using a right handed coordinate system. However, others APIs such as Direct3D have done different choice and relies on the left handed coordinate system. + +GLM allows switching the coordinate system to left handed by defining `GLM_FORCE_LEFT_HANDED`. + +### 2.17. GLM\_FORCE\_DEPTH\_ZERO\_TO\_ONE: Force the use of a clip space between 0 to 1 + +By default, OpenGL is using a -1 to 1 clip space in Z-axis. However, others APIs such as Direct3D relies on a clip space between 0 to 1 in Z-axis. + +GLM allows switching the clip space in Z-axis to 0 to 1 by defining `GLM_FORCE_DEPTH_ZERO_TO_ONE`. + +### 2.18. GLM\_FORCE\_SIZE\_T\_LENGTH: Vector and matrix static size + +GLSL supports the member function .length() for all vector and matrix types. + +```cpp +#include + +void foo(vec4 const& v) +{ + int Length = v.length(); + ... +} +``` + +This function returns an `int` however this function typically interacts with STL `size_t` based code. GLM provides `GLM_FORCE_SIZE_T_LENGTH` pre-processor configuration so that member functions `length()` return a `size_t`. + +Additionally, GLM defines the type `glm::length_t` to identify `length()` returned type, independently from `GLM_FORCE_SIZE_T_LENGTH`. + +```cpp +#define GLM_FORCE_SIZE_T_LENGTH +#include + +void foo(vec4 const& v) +{ + glm::length_t Length = v.length(); + ... +} +``` + +### 2.19. GLM\_FORCE\_UNRESTRICTED\_GENTYPE: Removing genType restriction + +GLSL has restrictions on types supported by certain functions that may appear excessive. +By default, GLM follows the GLSL specification as accurately as possible however it's possible to relax these rules using `GLM_FORCE_UNRESTRICTED_GENTYPE` define. + +```cpp +#include + +float average(float const A, float const B) +{ + return glm::mix(A, B, 0.5f); // By default glm::mix only supports floating-point types +} +``` + +By defining GLM\_FORCE\_UNRESTRICTED\_GENTYPE, we allow using integer types: + +```cpp +#define GLM_FORCE_UNRESTRICTED_GENTYPE +#include + +int average(int const A, int const B) +{ + return glm::mix(A, B, 0.5f); // integers are ok thanks to GLM_FORCE_UNRESTRICTED_GENTYPE +} +``` + +### 2.20. GLM\_FORCE\_SILENT\_WARNINGS: Silent C++ warnings from language extensions + +When using /W4 on Visual C++ or -Wpedantic on GCC, for example, the compilers will generate warnings for using C++ language extensions (/Za with Visual C++) such as anonymous struct. +GLM relies on anonymous structs for swizzle operators and aligned vector types. To silent those warnings define `GLM_FORCE_SILENT_WARNINGS` before including GLM headers. + + +### 2.21. GLM\_FORCE\_QUAT\_DATA\_WXYZ: Force GLM to store quat data as w,x,y,z instead of x,y,z,w + +By default GLM store quaternion components with the x, y, z, w order. `GLM_FORCE_QUAT_DATA_WXYZ` allows switching the quaternion data storage to the w, x, y, z order. + +--- +
+ +## 3. Stable extensions + +### 3.1. Scalar types + +#### 3.1.1. GLM_EXT_scalar_int_sized + +This extension exposes sized and signed integer types. + +Include `` to use these features. + +#### 3.1.2. GLM_EXT_scalar_uint_sized + +This extension exposes sized and unsigned integer types. + +```cpp +#include + +glm::uint64 pack(glm::uint32 A, glm::uint16 B, glm::uint8 C, glm::uint8 D) +{ + glm::uint64 ShiftA = 0; + glm::uint64 ShiftB = sizeof(glm::uint32) * 8; + glm::uint64 ShiftC = (sizeof(glm::uint32) + sizeof(glm::uint16)) * 8; + glm::uint64 ShiftD = (sizeof(glm::uint32) + sizeof(glm::uint16) + sizeof(glm::uint8)) * 8; + return (glm::uint64(A) << ShiftA) | (glm::uint64(B) << ShiftB) | (glm::uint64(C) << ShiftC) | (glm::uint64(D) << ShiftD); +} +``` + +Include `` to use these features. + +### 3.2. Scalar functions + +#### 3.2.1. GLM_EXT_scalar_common + +This extension exposes support for `min` and `max` functions taking more than two scalar arguments. Also, it adds `fmin` and `fmax` variants which prevents `NaN` propagation. + +```cpp +#include + +float positiveMax(float const a, float const b) +{ + return glm::fmax(a, b, 0.0f); +} +``` + +Include `` to use these features. + +#### 3.2.2. GLM_EXT_scalar_relational + +This extension exposes `equal` and `notEqual` scalar variants which takes an epsilon argument. + +```cpp +#include + +bool epsilonEqual(float const a, float const b) +{ + float const CustomEpsilon = 0.0001f; + return glm::equal(a, b, CustomEpsilon); +} +``` + +Include `` to use these features. + +#### 3.2.3. GLM_EXT_scalar_constants + +This extension exposes useful constants such as `epsilon` and `pi`. + +```cpp +#include + +float circumference(float const Diameter) +{ + return glm::pi() * Diameter; +} +``` + +```cpp +#include // abs +#include // epsilon + +bool equalULP1(float const a, float const b) +{ + return glm::abs(a - b) <= glm::epsilon(); +} +``` + +Include `` to use these features. + +#### 3.2.4. GLM_EXT_scalar_ulp + +This extension exposes function that measure of accuracy in numeric calculations. + +```cpp +#include + +bool test_ulp(float x) +{ + float const a = glm::next_float(x); // return a float a ULP away from the float argument. + return float_distance(a, x) == 1; // check both float are a single ULP away. +} +``` + +Include `` to use these features. + +### 3.3. Vector types + +#### 3.3.1. GLM_EXT_vector_float1 + +This extension exposes single-precision floating point vector with 1 component: `vec1`. + +Include `` to use these features. + +#### 3.3.2. GLM_EXT_vector_float2 + +This extension exposes single-precision floating point vector with 2 components: `vec2`. + +Include `` to use these features. + +#### 3.3.3. GLM_EXT_vector_float3 + +This extension exposes single-precision floating point vector with 3 components: `vec3`. + +Include `` to use these features. + +#### 3.3.4. GLM_EXT_vector_float4 + +This extension exposes single-precision floating point vector with 4 components: `vec4`. + +Include `` to use these features. + +#### 3.3.5. GLM_EXT_vector_double1 + +This extension exposes double-precision floating point vector with 1 component: `dvec1`. + +Include `` to use these features. + +#### 3.3.6. GLM_EXT_vector_double2 + +This extension exposes double-precision floating point vector with 2 components: `dvec2`. + +Include `` to use these features. + +#### 3.3.7. GLM_EXT_vector_double3 + +This extension exposes double-precision floating point vector with 3 components: `dvec3`. + +Include `` to use these features. + +#### 3.3.8. GLM_EXT_vector_double4 + +This extension exposes double-precision floating point vector with 4 components: `dvec4`. + +Include `` to use these features. + +#### 3.3.9. GLM_EXT_vector_int1 + +This extension exposes signed integer vector with 1 component: `ivec1`. + +Include `` to use these features. + +#### 3.3.10. GLM_EXT_vector_int2 + +This extension exposes signed integer vector with 2 components: `ivec2`. + +Include `` to use these features. + +#### 3.3.11. GLM_EXT_vector_int3 + +This extension exposes signed integer vector with 3 components: `ivec3`. + +Include `` to use these features. + +#### 3.3.12. GLM_EXT_vector_int4 + +This extension exposes signed integer vector with 4 components: `ivec4`. + +Include `` to use these features. + +#### 3.3.13. GLM_EXT_vector_int1 + +This extension exposes unsigned integer vector with 1 component: `uvec1`. + +Include `` to use these features. + +#### 3.3.14. GLM_EXT_vector_uint2 + +This extension exposes unsigned integer vector with 2 components: `uvec2`. + +Include `` to use these features. + +#### 3.3.15. GLM_EXT_vector_uint3 + +This extension exposes unsigned integer vector with 3 components: `uvec3`. + +Include `` to use these features. + +#### 3.3.16. GLM_EXT_vector_uint4 + +This extension exposes unsigned integer vector with 4 components: `uvec4`. + +Include `` to use these features. + +#### 3.3.17. GLM_EXT_vector_bool1 + +This extension exposes boolean vector with 1 component: `bvec1`. + +Include `` to use these features. + +#### 3.3.18. GLM_EXT_vector_bool2 + +This extension exposes boolean vector with 2 components: `bvec2`. + +Include `` to use these features. + +#### 3.3.19. GLM_EXT_vector_bool3 + +This extension exposes boolean vector with 3 components: `bvec3`. + +Include `` to use these features. + +#### 3.3.20. GLM_EXT_vector_bool4 + +This extension exposes boolean vector with 4 components: `bvec4`. + +Include `` to use these features. + +### 3.4. Vector types with precision qualifiers + +#### 3.4.1. GLM_EXT_vector_float1_precision + +This extension exposes single-precision floating point vector with 1 component using various precision in term of ULPs: `lowp_vec1`, `mediump_vec1` and `highp_vec1`. + +Include `` to use these features. + +#### 3.4.2. GLM_EXT_vector_float2_precision + +This extension exposes single-precision floating point vector with 2 components using various precision in term of ULPs: `lowp_vec2`, `mediump_vec2` and `highp_vec2`. + +Include `` to use these features. + +#### 3.4.3. GLM_EXT_vector_float3_precision + +This extension exposes single-precision floating point vector with 3 components using various precision in term of ULPs: `lowp_vec3`, `mediump_vec3` and `highp_vec3`. + +Include `` to use these features. + +#### 3.4.4. GLM_EXT_vector_float4_precision + +This extension exposes single-precision floating point vector with 4 components using various precision in term of ULPs: `lowp_vec4`, `mediump_vec4` and `highp_vec4`. + +Include `` to use these features. + +#### 3.4.5. GLM_EXT_vector_double1_precision + +This extension exposes double-precision floating point vector with 1 component using various precision in term of ULPs: `lowp_dvec1`, `mediump_dvec1` and `highp_dvec1`. + +Include `` to use these features. + +#### 3.4.6. GLM_EXT_vector_double2_precision + +This extension exposes double-precision floating point vector with 2 components using various precision in term of ULPs: `lowp_dvec2`, `mediump_dvec2` and `highp_dvec2`. + +Include `` to use these features. + +#### 3.4.7. GLM_EXT_vector_double3_precision + +This extension exposes double-precision floating point vector with 3 components using various precision in term of ULPs: `lowp_dvec3`, `mediump_dvec3` and `highp_dvec3`. + +Include `` to use these features. + +#### 3.4.8. GLM_EXT_vector_double4_precision + +This extension exposes double-precision floating point vector with 4 components using various precision in term of ULPs: `lowp_dvec4`, `mediump_dvec4` and `highp_dvec4`. + +Include `` to use these features. + +### 3.5. Vector functions + +#### 3.5.1. GLM_EXT_vector_common + +This extension exposes support for `min` and `max` functions taking more than two vector arguments. Also, it adds `fmin` and `fmax` variants which prevents `NaN` propagation. + +```cpp +#include // vec2 +#include // fmax + +float positiveMax(float const a, float const b) +{ + return glm::fmax(a, b, 0.0f); +} +``` + +Include `` to use these features. + +#### 3.5.2. GLM_EXT_vector_relational + +This extension exposes `equal` and `notEqual` vector variants which takes an epsilon argument. + +```cpp +#include // vec2 +#include // equal, all + +bool epsilonEqual(glm::vec2 const& A, glm::vec2 const& B) +{ + float const CustomEpsilon = 0.0001f; + return glm::all(glm::equal(A, B, CustomEpsilon)); +} +``` + +Include `` to use these features. + +#### 3.5.3. GLM_EXT_vector_ulp + +This extension exposes function that measure of accuracy in numeric calculations. + +```cpp +#include +#include +#include + +bool test_ulp(glm::vec4 const& x) +{ + glm::vec4 const a = glm::next_float(x); // return a float a ULP away from the float argument. + return glm::all(float_distance(a, x) == glm::ivec4(1)); // check both float are a single ULP away. +} +``` + +Include `` to use these features. + +### 3.6. Matrix types + +#### 3.6.1. GLM_EXT_matrix_float2x2 + +This extension exposes single-precision floating point vector with 2 columns by 2 rows: `mat2x2`. + +Include `` to use these features. + +#### 3.6.2. GLM_EXT_matrix_float2x3 + +This extension exposes single-precision floating point vector with 2 columns by 3 rows: `mat2x3`. + +Include `` to use these features. + +#### 3.6.3. GLM_EXT_matrix_float2x4 + +This extension exposes single-precision floating point vector with 2 columns by 4 rows: `mat2x4`. + +Include `` to use these features. + +#### 3.6.4. GLM_EXT_matrix_float3x2 + +This extension exposes single-precision floating point vector with 3 columns by 2 rows: `mat3x2`. + +Include `` to use these features. + +#### 3.6.5. GLM_EXT_matrix_float3x3 + +This extension exposes single-precision floating point vector with 3 columns by 3 rows: `mat3x3`. + +Include `` to use these features. + +#### 3.6.6. GLM_EXT_matrix_float3x4 + +This extension exposes single-precision floating point vector with 3 columns by 4 rows: `mat3x4`. + +Include `` to use these features. + +#### 3.6.7. GLM_EXT_matrix_float4x2 + +This extension exposes single-precision floating point vector with 4 columns by 2 rows: `mat4x2`. + +Include `` to use these features. + +#### 3.6.8. GLM_EXT_matrix_float4x3 + +This extension exposes single-precision floating point vector with 4 columns by 3 rows: `mat4x3`. + +Include `` to use these features. + +#### 3.6.9. GLM_EXT_matrix_float4x4 + +This extension exposes single-precision floating point vector with 4 columns by 4 rows: `mat4x4`. + +Include `` to use these features. + +#### 3.6.10. GLM_EXT_matrix_double2x2 + +This extension exposes double-precision floating point vector with 2 columns by 2 rows: `dmat2x2`. + +Include `` to use these features. + +#### 3.6.11. GLM_EXT_matrix_double2x3 + +This extension exposes double-precision floating point vector with 2 columns by 3 rows: `dmat2x3`. + +Include `` to use these features. + +#### 3.6.12. GLM_EXT_matrix_double2x4 + +This extension exposes double-precision floating point vector with 2 columns by 4 rows: `dmat2x4`. + +Include `` to use these features. + +#### 3.6.13. GLM_EXT_matrix_double3x2 + +This extension exposes double-precision floating point vector with 3 columns by 2 rows: `dmat3x2`. + +Include `` to use these features. + +#### 3.6.14. GLM_EXT_matrix_double3x3 + +This extension exposes double-precision floating point vector with 3 columns by 3 rows: `dmat3x3`. + +Include `` to use these features. + +#### 3.6.15. GLM_EXT_matrix_double3x4 + +This extension exposes double-precision floating point vector with 3 columns by 4 rows: `dmat3x4`. + +Include `` to use these features. + +#### 3.6.16. GLM_EXT_matrix_double4x2 + +This extension exposes double-precision floating point vector with 4 columns by 2 rows: `dmat4x2`. + +Include `` to use these features. + +#### 3.6.17. GLM_EXT_matrix_double4x3 + +This extension exposes double-precision floating point vector with 4 columns by 3 rows: `dmat4x3`. + +Include `` to use these features. + +#### 3.6.18. GLM_EXT_matrix_double4x4 + +This extension exposes double-precision floating point vector with 4 columns by 4 rows: `dmat4x4`. + +Include `` to use these features. + +### 3.7. Matrix types with precision qualifiers + +#### 3.7.1. GLM_EXT_matrix_float2x2_precision + +This extension exposes single-precision floating point vector with 2 columns by 2 rows using various precision in term of ULPs: `lowp_mat2x2`, `mediump_mat2x2` and `highp_mat2x2`. + +Include `` to use these features. + +#### 3.7.2. GLM_EXT_matrix_float2x3_precision + +This extension exposes single-precision floating point vector with 2 columns by 3 rows using various precision in term of ULPs: `lowp_mat2x3`, `mediump_mat2x3` and `highp_mat2x3`. + +Include `` to use these features. + +#### 3.7.3. GLM_EXT_matrix_float2x4_precision + +This extension exposes single-precision floating point vector with 2 columns by 4 rows using various precision in term of ULPs: `lowp_mat2x4`, `mediump_mat2x4` and `highp_mat2x4`. + +Include `` to use these features. + +#### 3.7.4. GLM_EXT_matrix_float3x2_precision + +This extension exposes single-precision floating point vector with 3 columns by 2 rows using various precision in term of ULPs: `lowp_mat3x2`, `mediump_mat3x2` and `highp_mat3x2`. + +Include `` to use these features. + +#### 3.7.5. GLM_EXT_matrix_float3x3_precision + +This extension exposes single-precision floating point vector with 3 columns by 3 rows using various precision in term of ULPs: `lowp_mat3x3`, `mediump_mat3x3` and `highp_mat3x3`. + +Include `` to use these features. + +#### 3.7.6. GLM_EXT_matrix_float3x4_precision + +This extension exposes single-precision floating point vector with 3 columns by 4 rows using various precision in term of ULPs: `lowp_mat3x4`, `mediump_mat3x4` and `highp_mat3x4`. + +Include `` to use these features. + +#### 3.7.7. GLM_EXT_matrix_float4x2_precision + +This extension exposes single-precision floating point vector with 4 columns by 2 rows using various precision in term of ULPs: `lowp_mat4x2`, `mediump_mat4x2` and `highp_mat4x2`. + +Include `` to use these features. + +#### 3.7.8. GLM_EXT_matrix_float4x3_precision + +This extension exposes single-precision floating point vector with 4 columns by 3 rows using various precision in term of ULPs: `lowp_mat4x3`, `mediump_mat4x3` and `highp_mat4x3`. + +Include `` to use these features. + +#### 3.7.9. GLM_EXT_matrix_float4x4_precision + +This extension exposes single-precision floating point vector with 4 columns by 4 rows using various precision in term of ULPs: `lowp_mat4x4`, `mediump_mat4x4` and `highp_mat4x4`. + +Include `` to use these features. + +#### 3.7.10. GLM_EXT_matrix_double2x2_precision + +This extension exposes double-precision floating point vector with 2 columns by 2 rows using various precision in term of ULPs: `lowp_dmat2x2`, `mediump_dmat2x2` and `highp_dmat2x2`. + +Include `` to use these features. + +#### 3.7.11. GLM_EXT_matrix_double2x3_precision + +This extension exposes double-precision floating point vector with 2 columns by 3 rows using various precision in term of ULPs: `lowp_dmat2x3`, `mediump_dmat2x3` and `highp_dmat2x3`. + +Include `` to use these features. + +#### 3.7.12. GLM_EXT_matrix_double2x4_precision + +This extension exposes double-precision floating point vector with 2 columns by 4 rows using various precision in term of ULPs: `lowp_dmat2x4`, `mediump_dmat2x4` and `highp_dmat2x4`. + +Include `` to use these features. + +#### 3.7.13. GLM_EXT_matrix_double3x2_precision + +This extension exposes double-precision floating point vector with 3 columns by 2 rows using various precision in term of ULPs: `lowp_dmat3x2`, `mediump_dmat3x2` and `highp_dmat3x2`. + +Include `` to use these features. + +#### 3.7.14. GLM_EXT_matrix_double3x3_precision + +This extension exposes double-precision floating point vector with 3 columns by 3 rows using various precision in term of ULPs: `lowp_dmat3x3`, `mediump_dmat3x3` and `highp_dmat3x3`. + +Include `` to use these features. + +#### 3.7.15. GLM_EXT_matrix_double3x4_precision + +This extension exposes double-precision floating point vector with 3 columns by 4 rows using various precision in term of ULPs: `lowp_dmat3x4`, `mediump_dmat3x4` and `highp_dmat3x4`. + +Include `` to use these features. + +#### 3.7.16. GLM_EXT_matrix_double4x2_precision + +This extension exposes double-precision floating point vector with 4 columns by 2 rows using various precision in term of ULPs: `lowp_dmat4x2`, `mediump_dmat4x2` and `highp_dmat4x2`. + +Include `` to use these features. + +#### 3.7.17. GLM_EXT_matrix_double4x3_precision + +This extension exposes double-precision floating point vector with 4 columns by 3 rows using various precision in term of ULPs: `lowp_dmat4x3`, `mediump_dmat4x3` and `highp_dmat4x3`. + +Include `` to use these features. + +#### 3.7.18. GLM_EXT_matrix_double4x4_precision + +This extension exposes double-precision floating point vector with 4 columns by 4 rows using various precision in term of ULPs: `lowp_dmat4x4`, `mediump_dmat4x4` and `highp_dmat4x4`. + +Include `` to use these features. + +### 3.8. Matrix functions + +#### 3.8.1. GLM_EXT_matrix_relational + +This extension exposes `equal` and `notEqual` matrix variants which takes an optional epsilon argument. + +```cpp +#include // bvec4 +#include // mat4 +#include // equal, all + +bool epsilonEqual(glm::mat4 const& A, glm::mat4 const& B) +{ + float const CustomEpsilon = 0.0001f; + glm::bvec4 const ColumnEqual = glm::equal(A, B, CustomEpsilon); // Evaluation per column + return glm::all(ColumnEqual); +} +``` + +Include `` to use these features. + +#### 3.8.2. GLM_EXT_matrix_transform + +This extension exposes matrix transformation functions: `translate`, `rotate` and `scale`. + +```cpp +#include // vec2 +#include // vec3 +#include // mat4x4 +#include // translate, rotate, scale, identity + +glm::mat4 computeModelViewMatrix(float Translate, glm::vec2 const & Rotate) +{ + glm::mat4 View = glm::translate(glm::identity(), glm::vec3(0.0f, 0.0f, -Translate)); + View = glm::rotate(View, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f)); + View = glm::rotate(View, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f)); + glm::mat4 Model = glm::scale(glm::identity(), glm::vec3(0.5f)); + return View * Model; +} +``` + +Include `` to use these features. + +#### 3.8.3. GLM_EXT_matrix_clip_space + +This extension exposes functions to transform scenes into the clip space. + +```cpp +#include // mat4x4 +#include // perspective +#include // radians + +glm::mat4 computeProjection(float Width, float Height) +{ + return glm::perspective(glm::radians(45.0f), Width / Height, 0.1f, 100.f); +} +``` + +Include `` to use these features. + +#### 3.8.4. GLM_EXT_matrix_projection + +This extension exposes functions to map object coordinates into window coordinates and reverse + +Include `` to use these features. + +### 3.9. Quaternion types + +#### 3.9.1. GLM_EXT_quaternion_float + +This extension exposes single-precision floating point quaternion: `quat`. + +Include `` to use these features. + +#### 3.9.2. GLM_EXT_quaternion_double + +This extension exposes double-precision floating point quaternion: `dquat`. + +Include `` to use these features. + +### 3.10. Quaternion types with precision qualifiers + +#### 3.10.1. GLM_EXT_quaternion_float_precision + +This extension exposes single-precision floating point quaternion using various precision in term of ULPs: `lowp_quat`, `mediump_quat` and `highp_quat`. + +Include `` to use these features. + +#### 3.10.2. GLM_EXT_quaternion_double_precision + +This extension exposes double-precision floating point quaternion using various precision in term of ULPs: `lowp_dquat`, `mediump_dquat` and `highp_dquat`. + +Include `` to use these features. + +### 3.11. Quaternion functions + +#### 3.11.1. GLM_EXT_quaternion_common + +This extension exposes common quaternion functions such as `slerp`, `conjugate` and `inverse`. + +Include `` to use these features. + +#### 3.11.2. GLM_EXT_quaternion_geometric + +This extension exposes geometric quaternion functions such as `length`, `normalize`, `dot` and `cross`. + +Include `` to use these features. + +#### 3.11.3. GLM_EXT_quaternion_trigonometric + +This extension exposes trigonometric quaternion functions such as `angle` and `axis`. + +Include `` to use these features. + +#### 3.11.4. GLM_EXT_quaternion_exponential + +This extensions expose exponential functions for quaternions such as `exp`, `log`, `pow` and `sqrt`. + +Include `` to use these features. + +#### 3.11.5. GLM_EXT_quaternion_relational + +This extension exposes relational functions to compare quaternions. + +Include `` to use these features. + +#### 3.11.6. GLM_EXT_quaternion_transform + +This extension exposes functions to transform objects. + +Include `` to use these features. + +--- +
+ +## 4. Recommended extensions + +GLM extends the core GLSL feature set with extensions. These extensions include: quaternion, transformation, spline, matrix inverse, color spaces, etc. + +To include an extension, we only need to include the dedicated header file. Once included, the features are added to the GLM namespace. + +```cpp +#include +#include + +int foo() +{ + glm::vec4 Position = glm::vec4(glm:: vec3(0.0f), 1.0f); + glm::mat4 Model = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f)); + + glm::vec4 Transformed = Model * Position; + ... + + return 0; +} +``` + +When an extension is included, all the dependent core functionalities and extensions will be included as well. + +### 4.1. GLM_GTC_bitfield + +Fast bitfield operations on scalar and vector variables. + +`` need to be included to use these features. + +### 4.2. GLM_GTC_color_space + +Conversion between linear RGB and sRGB color spaces. + +`` need to be included to use these features. + +### 4.3. GLM_GTC_constants + +Provide a list of built-in constants. + +`` need to be included to use these features. + +### 4.4. GLM\_GTC\_epsilon + +Approximate equality comparisons for floating-point numbers, possibly with a user-defined epsilon. + +`` need to be included to use these features. + +### 4.5. GLM\_GTC\_integer + +Integer variants of core GLM functions. + +`` need to be included to use these features. + +### 4.6. GLM\_GTC\_matrix\_access + +Functions to conveniently access the individual rows or columns of a matrix. + +`` need to be included to use these features. + +### 4.7. GLM\_GTC\_matrix\_integer + +Integer matrix types similar to the core floating-point matrices. Some operations (such as inverse and determinant) are not supported. + +`` need to be included to use these features. + +### 4.8. GLM\_GTC\_matrix\_inverse + +Additional matrix inverse functions. + +`` need to be included to use these features. + +### 4.9. GLM\_GTC\_matrix\_transform + +Matrix transformation functions that follow the OpenGL fixed-function conventions. + +For example, the `lookAt` function generates a transformation matrix that projects world coordinates into eye coordinates suitable for projection matrices (e.g. `perspective`, `ortho`). See the OpenGL compatibility specifications for more information about the layout of these generated matrices. + +The matrices generated by this extension use standard OpenGL fixed-function conventions. For example, the `lookAt` function generates a transform from world space into the specific eye space that the +projective matrix functions (`perspective`, `ortho`, etc) are designed to expect. The OpenGL compatibility specifications define the particular layout of this eye space. + +`` need to be included to use these features. + +### 4.10. GLM\_GTC\_noise + +Define 2D, 3D and 4D procedural noise functions. + +<`glm/gtc/noise.hpp>` need to be included to use these features. + +![](/doc/manual/noise-simplex1.jpg) + +Figure 4.10.1: glm::simplex(glm::vec2(x / 16.f, y / 16.f)); + +![](/doc/manual/noise-simplex2.jpg) + +Figure 4.10.2: glm::simplex(glm::vec3(x / 16.f, y / 16.f, 0.5f)); + +![](/doc/manual/noise-simplex3.jpg) + +Figure 4.10.3: glm::simplex(glm::vec4(x / 16.f, y / 16.f, 0.5f, 0.5f)); + +![](/doc/manual/noise-perlin1.jpg) + +Figure 4.10.4: glm::perlin(glm::vec2(x / 16.f, y / 16.f)); + +![](/doc/manual/noise-perlin2.jpg) + +Figure 4.10.5: glm::perlin(glm::vec3(x / 16.f, y / 16.f, 0.5f)); + +![](/doc/manual/noise-perlin3.jpg) + +Figure 4.10.6: glm::perlin(glm::vec4(x / 16.f, y / 16.f, 0.5f, 0.5f))); + +![](/doc/manual/noise-perlin4.png) + +Figure 4.10.7: glm::perlin(glm::vec2(x / 16.f, y / 16.f), glm::vec2(2.0f)); + +![](/doc/manual/noise-perlin5.png) + +Figure 4.10.8: glm::perlin(glm::vec3(x / 16.f, y / 16.f, 0.5f), glm::vec3(2.0f)); + +![](/doc/manual/noise-perlin6.png) + +Figure 4.10.9: glm::perlin(glm::vec4(x / 16.f, y / 16.f, glm::vec2(0.5f)), glm::vec4(2.0f)); + +### 4.11. GLM\_GTC\_packing + +Convert scalar and vector types to and from packed formats, saving space at the cost of precision. However, packing a value into a format that it was previously unpacked from is guaranteed to be lossless. + +`` need to be included to use these features. + +### 4.12. GLM\_GTC\_quaternion + +Quaternions and operations upon thereof. + +`` need to be included to use these features. + +### 4.13. GLM\_GTC\_random + +Probability distributions in up to four dimensions. + +`` need to be included to use these features. + +![](/doc/manual/random-linearrand.png) + +Figure 4.13.1: glm::vec4(glm::linearRand(glm::vec2(-1), glm::vec2(1)), 0, 1); + +![](/doc/manual/random-circularrand.png) + +Figure 4.13.2: glm::vec4(glm::circularRand(1.0f), 0, 1); + +![](/doc/manual/random-sphericalrand.png) + +Figure 4.13.3: glm::vec4(glm::sphericalRand(1.0f), 1); + +![](/doc/manual/random-diskrand.png) + +Figure 4.13.4: glm::vec4(glm::diskRand(1.0f), 0, 1); + +![](/doc/manual/random-ballrand.png) + +Figure 4.13.5: glm::vec4(glm::ballRand(1.0f), 1); + +![](/doc/manual/random-gaussrand.png) + +Figure 4.13.6: glm::vec4(glm::gaussRand(glm::vec3(0), glm::vec3(1)), 1); + +### 4.14. GLM\_GTC\_reciprocal + +Reciprocal trigonometric functions (e.g. secant, cosecant, tangent). + +`` need to be included to use the features of this extension. + +### 4.15. GLM\_GTC\_round + +Various rounding operations and common special cases thereof. + +`` need to be included to use the features of this extension. + +### 4.16. GLM\_GTC\_type\_aligned + +Aligned vector types. + +`` need to be included to use the features of this extension. + +### 4.17. GLM\_GTC\_type\_precision + +Vector and matrix types with defined precisions, e.g. `i8vec4`, which is a 4D vector of signed 8-bit integers. + +`` need to be included to use the features of this extension. + +### 4.18. GLM\_GTC\_type\_ptr + +Facilitate interactions between pointers to basic types (e.g. `float*`) and GLM types (e.g. `mat4`). + +This extension defines an overloaded function, `glm::value_ptr`, which returns a pointer to the memory layout of any GLM vector or matrix (`vec3`, `mat4`, etc.). Matrix types store their values in column-major order. This is useful for uploading data to matrices or for copying data to buffer objects. + +```cpp +// GLM_GTC_type_ptr provides a safe solution: +#include +#include + +void foo() +{ + glm::vec4 v(0.0f); + glm::mat4 m(1.0f); + ... + glVertex3fv(glm::value_ptr(v)) + glLoadMatrixfv(glm::value_ptr(m)); +} + +// Another solution, this one inspired by the STL: +#include + +void foo() +{ + glm::vec4 v(0.0f); + glm::mat4 m(1.0f); + ... + glVertex3fv(&v[0]); + glLoadMatrixfv(&m[0][0]); +} +``` + +*Note: It would be possible to implement [`glVertex3fv`](http://www.opengl.org/sdk/docs/man2/xhtml/glVertex.xml)(glm::vec3(0)) in C++ with the appropriate cast operator that would result as an +implicit cast in this example. However cast operators may produce programs running with unexpected behaviours without build error or any form of notification. * + +`` need to be included to use these features. + +### 4.19. GLM\_GTC\_ulp + +Measure a function's accuracy given a reference implementation of it. This extension works on floating-point data and provides results in [ULP](http://ljk.imag.fr/membres/Carine.Lucas/TPScilab/JMMuller/ulp-toms.pdf). + +`` need to be included to use these features. + +### 4.20. GLM\_GTC\_vec1 + +Add \*vec1 types. + +`` need to be included to use these features. + +--- +
+ +## 5. OpenGL interoperability + +### 5.1. GLM replacements for deprecated OpenGL functions + +OpenGL 3.1 specification has deprecated some features that have been removed from OpenGL 3.2 core profile specification. GLM provides some replacement functions. + +[***glRotate{f, d}:***](https://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml) + +```cpp +glm::mat4 glm::rotate(glm::mat4 const& m, float angle, glm::vec3 const& axis); +glm::dmat4 glm::rotate(glm::dmat4 const& m, double angle, glm::dvec3 const& axis); +``` + +From `GLM_GTC_matrix_transform` extension: <glm/gtc/matrix\_transform.hpp> + +[***glScale{f, d}:***](http://www.opengl.org/sdk/docs/man2/xhtml/glScale.xml) + +```cpp +glm::mat4 glm::scale(glm::mat4 const& m, glm::vec3 const& factors); +glm::dmat4 glm::scale(glm::dmat4 const& m, glm::dvec3 const& factors); +``` + +From `GLM_GTC_matrix_transform` extension: <glm/gtc/matrix\_transform.hpp> + +[***glTranslate{f, d}:***](https://www.opengl.org/sdk/docs/man2/xhtml/glTranslate.xml) + +```cpp +glm::mat4 glm::translate(glm::mat4 const& m, glm::vec3 const& translation); +glm::dmat4 glm::translate(glm::dmat4 const& m, glm::dvec3 const& translation); +``` + +From `GLM_GTC_matrix_transform` extension: <glm/gtc/matrix\_transform.hpp> + +[***glLoadIdentity:***](https://www.opengl.org/sdk/docs/man2/xhtml/glLoadIdentity.xml) + +```cpp +glm::mat4(1.0) or glm::mat4(); +glm::dmat4(1.0) or glm::dmat4(); +``` + +From GLM core library: `` + +[***glMultMatrix{f, d}:***](https://www.opengl.org/sdk/docs/man2/xhtml/glMultMatrix.xml) + +```cpp +glm::mat4() * glm::mat4(); +glm::dmat4() * glm::dmat4(); +``` + +From GLM core library: `` + +[***glLoadTransposeMatrix{f, d}:***](https://www.opengl.org/sdk/docs/man2/xhtml/glLoadTransposeMatrix.xml) + +```cpp +glm::transpose(glm::mat4()); +glm::transpose(glm::dmat4()); +``` + +From GLM core library: `` + +[***glMultTransposeMatrix{f, d}:***](https://www.opengl.org/sdk/docs/man2/xhtml/glMultTransposeMatrix.xml) + +```cpp +glm::mat4() * glm::transpose(glm::mat4()); +glm::dmat4() * glm::transpose(glm::dmat4()); +``` + +From GLM core library: `` + +[***glFrustum:***](http://www.opengl.org/sdk/docs/man2/xhtml/glFrustum.xml) + +```cpp +glm::mat4 glm::frustum(float left, float right, float bottom, float top, float zNear, float zFar); +glm::dmat4 glm::frustum(double left, double right, double bottom, double top, double zNear, double zFar); +``` + +From `GLM_GTC_matrix_transform` extension: `` + +[***glOrtho:***](https://www.opengl.org/sdk/docs/man2/xhtml/glOrtho.xml) + +```cpp +glm::mat4 glm::ortho(float left, float right, float bottom, float top, float zNear, float zFar); +glm::dmat4 glm::ortho(double left, double right, double bottom, double top, double zNear, double zFar); +``` + +From `GLM_GTC_matrix_transform` extension: `` + +### 5.2. GLM replacements for GLU functions + +[***gluLookAt:***](https://www.opengl.org/sdk/docs/man2/xhtml/gluLookAt.xml) + +```cpp +glm::mat4 glm::lookAt(glm::vec3 const& eye, glm::vec3 const& center, glm::vec3 const& up); +glm::dmat4 glm::lookAt(glm::dvec3 const& eye, glm::dvec3 const& center, glm::dvec3 const& up); +``` + +From `GLM_GTC_matrix_transform` extension: `` + +[***gluOrtho2D:***](https://www.opengl.org/sdk/docs/man2/xhtml/gluOrtho2D.xml) + +```cpp +glm::mat4 glm::ortho(float left, float right, float bottom, float top); +glm::dmat4 glm::ortho(double left, double right, double bottom, double top); +``` + +From `GLM_GTC_matrix_transform` extension: `` + +[***gluPerspective:***](https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml) + +```cpp +glm::mat4 perspective(float fovy, float aspect, float zNear, float zFar); +glm::dmat4 perspective(double fovy, double aspect, double zNear, double zFar); +``` + +Note that in GLM, fovy is expressed in radians, not degrees. + +From `GLM_GTC_matrix_transform` extension: `` + +[***gluPickMatrix:***](https://www.opengl.org/sdk/docs/man2/xhtml/gluPickMatrix.xml) + +```cpp +glm::mat4 pickMatrix(glm::vec2 const& center, glm::vec2 const& delta, glm::ivec4 const& viewport); +glm::dmat4 pickMatrix(glm::dvec2 const& center, glm::dvec2 const& delta, glm::ivec4 const& viewport); +``` + +From `GLM_GTC_matrix_transform` extension: `` + +[***gluProject:***](http://www.opengl.org/sdk/docs/man2/xhtml/gluProject.xml) + +```cpp +glm::vec3 project(glm::vec3 const& obj, glm::mat4 const& model, glm::mat4 const& proj, glm::ivec4 const& viewport); +glm::dvec3 project(glm::dvec3 const& obj, glm::dmat4 const& model, glm::dmat4 const& proj, glm::ivec4 const& viewport); +``` + +From `GLM_GTC_matrix_transform` extension: `` + +[***gluUnProject:***](https://www.opengl.org/sdk/docs/man2/xhtml/gluUnProject.xml) + +```cpp +glm::vec3 unProject(glm::vec3 const& win, glm::mat4 const& model, glm::mat4 const& proj, glm::ivec4 const& viewport); +glm::dvec3 unProject(glm::dvec3 const& win, glm::dmat4 const& model, glm::dmat4 const& proj, glm::ivec4 const& viewport); +``` + +From `GLM_GTC_matrix_transform` extension: `` + +--- +
+ +## 6. Known issues + +This section reports GLSL features that GLM can't accurately emulate due to language restrictions. + +### 6.1. not function + +The GLSL function 'not' is a keyword in C++. To prevent name collisions and ensure a consistent API, the name `not\_` (note the underscore) is used instead. + +### 6.2. Precision qualifiers support + +GLM supports GLSL precision qualifiers through prefixes instead of qualifiers. For example, GLM exposes \verb|lowp_vec4|, \verb|mediump_vec4| and \verb|highp_vec4| as variations of \verb|vec4|. + +Similarly to GLSL, GLM precision qualifiers are used to trade precision of operations in term of [ULPs](http://en.wikipedia.org/wiki/Unit_in_the_last_place) for better performance. By default, all the types use high precision. + +```cpp +// Using precision qualifier in GLSL: + +ivec3 foo(in vec4 v) +{ + highp vec4 a = v; + mediump vec4 b = a; + lowp ivec3 c = ivec3(b); + return c; +} + +// Using precision qualifier in GLM: + +#include + +ivec3 foo(const vec4 & v) +{ + highp_vec4 a = v; + medium_vec4 b = a; + lowp_ivec3 c = glm::ivec3(b); + return c; +} +``` + +--- +
+ +## 7. FAQ + +### 7.1 Why GLM follows GLSL specification and conventions? + +Following GLSL conventions is a really strict policy of GLM. It has been designed following the idea that everyone does its own math library with his own conventions. The idea is that brilliant developers (the OpenGL ARB) worked together and agreed to make GLSL. Following GLSL conventions +is a way to find consensus. Moreover, basically when a developer knows GLSL, he knows GLM. + +### 7.2. Does GLM run GLSL program? + +No, GLM is a C++ implementation of a subset of GLSL. + +### 7.3. Does a GLSL compiler build GLM codes? + +No, this is not what GLM attends to do. + +### 7.4. Should I use ‘GTX’ extensions? + +GTX extensions are qualified to be experimental extensions. In GLM this means that these extensions might change from version to version without any restriction. In practice, it doesn’t really change except time to +time. GTC extensions are stabled, tested and perfectly reliable in time. Many GTX extensions extend GTC extensions and provide a way to explore features and implementations and APIs and then are promoted to GTC +extensions. This is fairly the way OpenGL features are developed; through extensions. + +Stating with GLM 0.9.9, to use experimental extensions, an application must define GLM_ENABLE_EXPERIMENTAL. + +### 7.5. Where can I ask my questions? + +A good place is [stackoverflow](http://stackoverflow.com/search?q=GLM) using the GLM tag. + +### 7.6. Where can I find the documentation of extensions? + +The Doxygen generated documentation includes a complete list of all extensions available. Explore this [*API documentation*](http://glm.g-truc.net/html/index.html) to get a complete +view of all GLM capabilities! + +### 7.7. Should I use ‘using namespace glm;’? + +NO! Chances are that if using namespace glm; is called, especially in a header file, name collisions will happen as GLM is based on GLSL which uses common tokens for types and functions. Avoiding using namespace +glm; will a higher compatibility with third party library and SDKs. + +### 7.8. Is GLM fast? + +GLM is mainly designed to be convenient and that's why it is written against the GLSL specification. + +Following the Pareto principle where 20% of the code consumes 80% of the execution time, GLM operates perfectly on the 80% of the code that consumes 20% of the performances. Furthermore, thanks to the lowp, +mediump and highp qualifiers, GLM provides approximations which trade precision for performance. Finally, GLM can automatically produce SIMD optimized code for functions of its implementation. + +However, on performance critical code paths, we should expect that dedicated algorithms should be written to reach peak performance. + +### 7.9. When I build with Visual C++ with /W4 warning level, I have warnings... + +You should not have any warnings even in `/W4` mode. However, if you expect such level for your code, then you should ask for the same level to the compiler by at least disabling the Visual C++ language extensions +(`/Za`) which generates warnings when used. If these extensions are enabled, then GLM will take advantage of them and the compiler will generate warnings. + +### 7.10. Why some GLM functions can crash because of division by zero? + +GLM functions crashing is the result of a domain error. Such behavior follows the precedent set by C and C++'s standard library. For example, it’s a domain error to pass a null vector (all zeroes) to glm::normalize function, or to pass a negative number into std::sqrt. + +### 7.11. What unit for angles is used in GLM? + +GLSL is using radians but GLU is using degrees to express angles. This has caused GLM to use inconsistent units for angles. Starting with GLM 0.9.6, all GLM functions are using radians. For more information, follow +the [link](http://www.g-truc.net/post-0693.html#menu). + +### 7.12. Windows headers cause build errors... + +Some Windows headers define min and max as macros which may cause compatibility with third party libraries such as GLM. +It is highly recommended to [`define NOMINMAX`](http://stackoverflow.com/questions/4913922/possible-problems-with-nominmax-on-visual-c) before including Windows headers to workaround this issue. +To workaround the incompatibility with these macros, GLM will systematically undef these macros if they are defined. + +### 7.13. Constant expressions support + +GLM has some C++ constant expressions support. However, GLM automatically detects the use of SIMD instruction sets through compiler arguments to populate its implementation with SIMD intrinsics. +Unfortunately, GCC and Clang doesn't support SIMD instrinsics as constant expressions. To allow constant expressions on all vectors and matrices types, define `GLM_FORCE_PURE` before including GLM headers. + +--- +
+ +## 8. Code samples + +This series of samples only shows various GLM features without consideration of any sort. + +### 8.1. Compute a triangle normal + +```cpp +#include // vec3 normalize cross + +glm::vec3 computeNormal(glm::vec3 const& a, glm::vec3 const& b, glm::vec3 const& c) +{ + return glm::normalize(glm::cross(c - a, b - a)); +} + +// A much faster but less accurate alternative: +#include // vec3 cross +#include // fastNormalize + +glm::vec3 computeNormal(glm::vec3 const& a, glm::vec3 const& b, glm::vec3 const& c) +{ + return glm::fastNormalize(glm::cross(c - a, b - a)); +} +``` + +### 8.2. Matrix transform + +```cpp +#include // vec3, vec4, ivec4, mat4 +#include // translate, rotate, scale, perspective +#include // value_ptr + +void setUniformMVP(GLuint Location, glm::vec3 const& Translate, glm::vec3 const& Rotate) +{ + glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.f); + glm::mat4 ViewTranslate = glm::translate( + glm::mat4(1.0f), Translate); + glm::mat4 ViewRotateX = glm::rotate( + ViewTranslate, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f)); + glm::mat4 View = glm::rotate(ViewRotateX, + Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f)); + glm::mat4 Model = glm::scale( + glm::mat4(1.0f), glm::vec3(0.5f)); + glm::mat4 MVP = Projection * View * Model; + glUniformMatrix4fv(Location, 1, GL_FALSE, glm::value_ptr(MVP)); +} +``` + +### 8.3. Vector types + +```cpp +#include // vec2 +#include // hvec2, i8vec2, i32vec2 + +std::size_t const VertexCount = 4; + +// Float quad geometry +std::size_t const PositionSizeF32 = VertexCount * sizeof(glm::vec2); +glm::vec2 const PositionDataF32[VertexCount] = +{ + glm::vec2(-1.0f,-1.0f), + glm::vec2( 1.0f,-1.0f), + glm::vec2( 1.0f, 1.0f), + glm::vec2(-1.0f, 1.0f) +}; + +// Half-float quad geometry +std::size_t const PositionSizeF16 = VertexCount * sizeof(glm::hvec2); +glm::hvec2 const PositionDataF16[VertexCount] = +{ + glm::hvec2(-1.0f, -1.0f), + glm::hvec2( 1.0f, -1.0f), + glm::hvec2( 1.0f, 1.0f), + glm::hvec2(-1.0f, 1.0f) +}; + +// 8 bits signed integer quad geometry +std::size_t const PositionSizeI8 = VertexCount * sizeof(glm::i8vec2); +glm::i8vec2 const PositionDataI8[VertexCount] = +{ + glm::i8vec2(-1,-1), + glm::i8vec2( 1,-1), + glm::i8vec2( 1, 1), + glm::i8vec2(-1, 1) +}; + +// 32 bits signed integer quad geometry +std::size_t const PositionSizeI32 = VertexCount * sizeof(glm::i32vec2); +glm::i32vec2 const PositionDataI32[VertexCount] = +{ + glm::i32vec2(-1,-1), + glm::i32vec2( 1,-1), + glm::i32vec2( 1, 1), + glm::i32vec2(-1, 1) +}; +``` + +### 8.4. Lighting + +```cpp +#include // vec3 normalize reflect dot pow +#include // ballRand + +// vecRand3, generate a random and equiprobable normalized vec3 +glm::vec3 lighting(intersection const& Intersection, material const& Material, light const& Light, glm::vec3 const& View) +{ + glm::vec3 Color = glm::vec3(0.0f); + glm::vec3 LightVertor = glm::normalize( + Light.position() - Intersection.globalPosition() + + glm::ballRand(0.0f, Light.inaccuracy()); + + if(!shadow(Intersection.globalPosition(), Light.position(), LightVertor)) + { + float Diffuse = glm::dot(Intersection.normal(), LightVector); + if(Diffuse <= 0.0f) + return Color; + + if(Material.isDiffuse()) + Color += Light.color() * Material.diffuse() * Diffuse; + + if(Material.isSpecular()) + { + glm::vec3 Reflect = glm::reflect(-LightVector, Intersection.normal()); + float Dot = glm::dot(Reflect, View); + float Base = Dot > 0.0f ? Dot : 0.0f; + float Specular = glm::pow(Base, Material.exponent()); + Color += Material.specular() \* Specular; + } + } + + return Color; +} +``` + +--- +
+ +## 9. Contributing to GLM + +### 9.1. Submitting bug reports + +Bug should be reported on Github using the [issue page](https://github.com/g-truc/glm/issues). + +A minimal code to reproduce the issue will help. + +Additional, bugs can be configuration specific. We can report the configuration by defining `GLM_FORCE_MESSAGES` before including GLM headers then build and copy paste the build messages GLM will output. + +```cpp +#define GLM_FORCE_MESSAGES +#include +``` + +An example of build messages generated by GLM: +``` +GLM: 0.9.9.1 +GLM: C++ 17 with extensions +GLM: GCC compiler detected" +GLM: x86 64 bits with AVX instruction set build target +GLM: Linux platform detected +GLM: GLM_FORCE_SWIZZLE is undefined. swizzling functions or operators are disabled. +GLM: GLM_FORCE_SIZE_T_LENGTH is undefined. .length() returns a glm::length_t, a typedef of int following GLSL. +GLM: GLM_FORCE_UNRESTRICTED_GENTYPE is undefined. Follows strictly GLSL on valid function genTypes. +GLM: GLM_FORCE_DEPTH_ZERO_TO_ONE is undefined. Using negative one to one depth clip space. +GLM: GLM_FORCE_LEFT_HANDED is undefined. Using right handed coordinate system. +``` + +### 9.2. Contributing to GLM with pull request + +This tutorial will show us how to successfully contribute a bug-fix to GLM using GitHub's Pull Request workflow. + +We will be typing git commands in the Terminal. Mac and Linux users may have git pre-installed. You can download git from [here](http://git-scm.com/downloads). + +The tutorial assumes you have some basic understanding of git concepts - repositories, branches, commits, etc. Explaining it all from scratch is beyond the scope of this tutorial. Some good links to learn git basics are: [Link 1](http://git-scm.com/book/en/Getting-Started-Git-Basics), [Link 2](https://www.atlassian.com/git/tutorial/git-basics) + +#### Step 1: Setup our GLM Fork + +We will make our changes in our own copy of the GLM sitory. On the GLM GitHub repo and we press the Fork button. +We need to download a copy of our fork to our local machine. In the terminal, type: + +``` +>>> git clone +``` + +This will clone our fork repository into the current folder. + +We can find our repository git url on the Github reposotory page. The url looks like this: `https://github.com//.git` + +#### Step 2: Synchronizing our fork + +We can use the following command to add `upstream` (original project repository) as a remote repository so that we can fetch the latest GLM commits into our branch and keep our forked copy is synchronized. + +``` +>>> git remote add upstream https://github.com/processing/processing.git +``` + +To synchronize our fork to the latest commit in the GLM repository, we can use the following command: + +``` +>>> git fetch upstream +``` + +Then, we can merge the remote master branch to our current branch: + +``` +>>> git merge upstream/master +``` + +Now our local copy of our fork has been synchronized. However, the fork's copy is not updated on GitHub's servers yet. To do that, use: + +``` +>>> git push origin master +``` + +#### Step 3: Modifying our GLM Fork + +Our fork is now setup and we are ready to modify GLM to fix a bug. + +It's a good practice to make changes in our fork in a separate branch than the master branch because we can submit only one pull request per branch. + +Before creating a new branch, it's best to synchronize our fork and then create a new branch from the latest master branch. + +If we are not on the master branch, we should switch to it using: +``` +>>> git checkout master +``` + +To create a new branch called `bugifx`, we use: +``` +git branch bugfix +``` + +Once the code changes for the fix is done, we need to commit the changes: +``` +>>> git commit -m "Resolve the issue that caused problem with a specific fix #432" +``` + +The commit message should be as specific as possible and finished by the bug number in the [GLM GitHub issue page](https://github.com/g-truc/glm/issues) + +Finally, we need to push our changes in our branch to our GitHub fork using: +``` +>>> git push origin bugfix +``` + +Some things to keep in mind for a pull request: +* Keep it minimal: Try to make the minimum required changes to fix the issue. If we have added any debugging code, we should remove it. +* A fix at a time: The pull request should deal with one issue at a time only, unless two issue are so interlinked they must be fixed together. +* Write a test: GLM is largely unit tests. Unit tests are in `glm/test` directory. We should also add tests for the fixes we provide to ensure future regression doesn't happen. +* No whitespace changes: Avoid unnecessary formatting or whitespace changes in other parts of the code. Be careful with auto-format options in the code editor which can cause wide scale formatting changes. +* Follow [GLM Code Style](#section9_3) for consistency. +* Tests passes: Make sure GLM build and tests don't fail because of the changes. + +#### Step 4: Submitting a Pull Request + +We need to submit a pull request from the `bugfix` branch to GLM's master branch. + +On the fork github page, we can click on the *Pull Request* button. Then we can describe our pull request. Finally we press *Send Pull Request*. + +Please be patient and give them some time to go through it. + +The pull request review may suggest additional changes. So we can make those changes in our branch, and push those changes to our fork repository. Our pull request will always include the latest changes in our branch on GitHub, so we don't need to resubmit the pull request. + +Once your changes have been accepted, a project maintainer will merge our pull request. + +We are grateful to the users for their time and effort in contributing fixes. + +### 9.3. Coding style + +#### Indentation + +Always tabs. Never spaces. + +#### Spacing + +No space after if. Use if(blah) not if (blah). Example if/else block: + +```cpp +if(blah) +{ + // yes like this +} +else +{ + // something besides +} +``` + +Single line if blocks: +```cpp +if(blah) + // yes like this +else + // something besides +``` + +No spaces inside parens: +```cpp +if (blah) // No +if( blah ) // No +if ( blah ) // No +if(blah) // Yes +``` + +Use spaces before/after commas: +```cpp +someFunction(apple,bear,cat); // No +someFunction(apple, bear, cat); // Yes +``` + +Use spaces before/after use of `+, -, *, /, %, >>, <<, |, &, ^, ||, &&` operators: +```cpp +vec4 v = a + b; +``` + +#### Blank lines + +One blank line after the function blocks. + +#### Comments + +Always one space after the // in single line comments + +One space before // at the end of a line (that has code as well) + +Try to use // comments inside functions, to make it easier to remove a whole block via /* */ + +#### Cases + +```cpp +#define GLM_MY_DEFINE 76 + +class myClass +{}; + +myClass const MyClass; + +namespace glm{ // glm namespace is for public code +namespace detail // glm::detail namespace is for implementation detail +{ + float myFunction(vec2 const& V) + { + return V.x + V.y; + } + + float myFunction(vec2 const* const V) + { + return V->x + V->y; + } +}//namespace detail +}//namespace glm +``` + +--- +
+ +## 10. References + +### 10.1. OpenGL specifications + +* OpenGL 4.3 core specification +* [GLSL 4.30 specification](http://www.opengl.org/registry/doc/GLSLangSpec.4.30.7.diff.pdf) +![](media/image21.png){width="2.859722222222222in" height="1.6083333333333334in"}- [*GLU 1.3 specification*](http://www.opengl.org/documentation/specs/glu/glu1_3.pdf) + +### 10.2. External links + +* [GLM on stackoverflow](http://stackoverflow.com/search?q=GLM) + +### 10.3. Projects using GLM + +***[Leo’s Fortune](http://www.leosfortune.com/)*** + +Leo’s Fortune is a platform adventure game where you hunt down the cunning and mysterious thief that stole your gold. Available on PS4, Xbox One, PC, Mac, iOS and Android. + +Beautifully hand-crafted levels bring the story of Leo to life in this epic adventure. + +“I just returned home to find all my gold has been stolen! For some devious purpose, the thief has dropped pieces of my gold like breadcrumbs through the woods.†+ +“Despite this pickle of a trap, I am left with no choice but to follow the trail.†+ +“Whatever lies ahead, I must recover my fortune.†-Leopold + +![](/doc/manual/references-leosfortune.jpeg) + +![](/doc/manual/references-leosfortune2.jpg) + +[***OpenGL 4.0 Shading Language Cookbook***](http://www.packtpub.com/opengl-4-0-shading-language-cookbook/book?tag=rk/opengl4-abr1/0811) + +A set of recipes that demonstrates a wide of techniques for producing high-quality, real-time 3D graphics with GLSL 4.0, such as: + +* Using GLSL 4.0 to implement lighting and shading techniques. +* Using the new features of GLSL 4.0 including tessellation and geometry shaders. +* Using textures in GLSL as part of a wide variety of techniques from basic texture mapping to deferred shading. + +Simple, easy-to-follow examples with GLSL source code are provided, as well as a basic description of the theory behind each technique. + +![](/doc/manual/references-glsl4book.jpg) + +[***Outerra***](http://outerra.com/) + +A 3D planetary engine for seamless planet rendering from space down to the surface. Can use arbitrary resolution of elevation data, refining it to centimetre resolution using fractal algorithms. + +![](/doc/manual/references-outerra1.jpg) + +![](/doc/manual/references-outerra2.jpg) + +![](/doc/manual/references-outerra3.jpg) + +![](/doc/manual/references-outerra4.jpg) + +[***Falcor***](https://github.com/NVIDIA/Falcor) + +Real-time rendering research framework by NVIDIA. + +[***Cinder***](https://libcinder.org/) + +Cinder is a free and open source library for professional-quality creative coding in C++. + +Cinder is a C++ library for programming with aesthetic intent - the sort of development often called creative coding. This includes domains like graphics, audio, video, and computational geometry. Cinder is cross-platform, with official support for OS X, Windows, iOS, and WinRT. + +Cinder is production-proven, powerful enough to be the primary tool for professionals, but still suitable for learning and experimentation. Cinder is released under the [2-Clause BSD License](http://opensource.org/licenses/BSD-2-Clause). + +![](/doc/manual/references-cinder.png) + +[***opencloth***](http://code.google.com/p/opencloth/) + +A collection of source codes implementing cloth simulation algorithms in OpenGL. + +Simple, easy-to-follow examples with GLSL source code, as well as a basic description of the theory behind each technique. + +![](/doc/manual/references-opencloth1.png) + +![](/doc/manual/references-opencloth3.png) + +[***LibreOffice***](https://www.libreoffice.org/) + +LibreOffice includes several applications that make it the most powerful Free and Open Source office suite on the market. + +[***Are you using GLM in a project?***](mailto:glm@g-truc.net) + +### 10.4. Tutorials using GLM + +* [Sascha Willems' Vulkan examples](https://github.com/SaschaWillems/Vulkan), Examples and demos for the new Vulkan API +* [VKTS](https://github.com/McNopper/Vulkan) Vulkan examples using VulKan ToolS (VKTS) +* [*The OpenGL Samples Pack*](http://www.g-truc.net/project-0026.html#menu), samples that show how to set up all the different new features +* [*Learning Modern 3D Graphics programming*](http://www.arcsynthesis.org/gltut/), a great OpenGL tutorial using GLM by Jason L. McKesson +* [*Morten Nobel-Jørgensen’s*](http://blog.nobel-joergensen.com/2011/04/02/glm-brilliant-math-library-for-opengl/) review and use an [*OpenGL renderer*](https://github.com/mortennobel/RenderE) +* [*Swiftless’ OpenGL tutorial*](http://www.swiftless.com/opengltuts.html) using GLM by Donald Urquhart +* [*Rastergrid*](http://rastergrid.com/blog/), many technical articles with companion programs using GLM by Daniel Rákos\ +* [*OpenGL Tutorial*](http://www.opengl-tutorial.org), tutorials for OpenGL 3.1 and later +* [*OpenGL Programming on Wikibooks*](http://en.wikibooks.org/wiki/OpenGL_Programming): For beginners who are discovering OpenGL. +* [*3D Game Engine Programming*](http://3dgep.com/): Learning the latest 3D Game Engine Programming techniques. +* [Game Tutorials](http://www.gametutorials.com/opengl-4-matrices-and-glm/), graphics and game programming. +* [open.gl](https://open.gl/), OpenGL tutorial +* [c-jump](http://www.c-jump.com/bcc/common/Talk3/Math/GLM/GLM.html), GLM tutorial +* [Learn OpenGL](http://learnopengl.com/), OpenGL tutorial +* [***Are you using GLM in a tutorial?***](mailto:glm@g-truc.net) + +### 10.5. Equivalent for other languages + +* [*cglm*](https://github.com/recp/cglm): OpenGL Mathematics (glm) for C. +* [*GlmSharp*](https://github.com/Philip-Trettner/GlmSharp): Open-source semi-generated GLM-flavored math library for .NET/C\#. +* [glm-js](https://github.com/humbletim/glm-js): JavaScript adaptation of the OpenGL Mathematics (GLM) C++ library interfaces +* [JVM OpenGL Mathematics (GLM)](https://github.com/kotlin-graphics/glm): written in Kotlin, Java compatible +* [JGLM](https://github.com/jroyalty/jglm) - Java OpenGL Mathematics Library +* [SwiftGL Math Library](https://github.com/SwiftGL/Math/blob/master/Sources/glm.swift) GLM for Swift +* [glm-go](https://github.com/jbowtie/glm-go): Simple linear algebra library similar in spirit to GLM +* [openll](https://github.com/Polkm/openll): Lua bindings for OpenGL, GLM, GLFW, OpenAL, SOIL and PhysicsFS +* [glm-rs](https://github.com/dche/glm-rs): GLSL mathematics for Rust programming language +* [glmpython](https://github.com/Queatz/glmpython): GLM math library for Python + +### 10.6. Alternatives to GLM + +* [*CML*](http://cmldev.net/): The CML (Configurable Math Library) is a free C++ math library for games and graphics. +* [*Eigen*](http://eigen.tuxfamily.org/): A more heavy weight math library for general linear algebra in C++. +* [*glhlib*](http://glhlib.sourceforge.net/): A much more than glu C library. +* Are you using or developing an alternative library to GLM? + +### 10.7. Acknowledgements + +GLM is developed and maintained by [*Christophe Riccio*](http://www.g-truc.net) but many contributors have made this project what it is. + +Special thanks to: +* Ashima Arts and Stefan Gustavson for their work on [*webgl-noise*](https://github.com/ashima/webgl-noise) which has been used for GLM noises implementation. +* [*Arthur Winters*](http://athile.net/library/wiki/index.php?title=Athile_Technologies) for the C++11 and Visual C++ swizzle operators implementation and tests. +* Joshua Smith and Christoph Schied for the discussions and the experiments around the swizzle operators implementation issues. +* Guillaume Chevallereau for providing and maintaining the [*nightlight build system*](http://my.cdash.org/index.php?project=GLM). +* Ghenadii Ursachi for GLM\_GTX\_matrix\_interpolation implementation. +* Mathieu Roumillac for providing some implementation ideas. +* [*Grant James*](http://www.zeuscmd.com/) for the implementation of all combination of none-squared matrix products. +* Jesse Talavera-Greenberg for his work on the manual amount other things. +* All the GLM users that have report bugs and hence help GLM to become a great library! diff --git a/vendor/glm/readme.md b/vendor/glm/readme.md new file mode 100644 index 0000000..611c257 --- /dev/null +++ b/vendor/glm/readme.md @@ -0,0 +1,1209 @@ +![glm](/doc/manual/logo-mini.png) + +[OpenGL Mathematics](http://glm.g-truc.net/) (*GLM*) is a header only C++ mathematics library for graphics software based on the [OpenGL Shading Language (GLSL) specifications](https://www.opengl.org/registry/doc/GLSLangSpec.4.50.diff.pdf). + +*GLM* provides classes and functions designed and implemented with the same naming conventions and functionality than *GLSL* so that anyone who knows *GLSL*, can use *GLM* as well in C++. + +This project isn't limited to *GLSL* features. An extension system, based on the *GLSL* extension conventions, provides extended capabilities: matrix transformations, quaternions, data packing, random numbers, noise, etc... + +This library works perfectly with *[OpenGL](https://www.opengl.org)* but it also ensures interoperability with other third party libraries and SDK. It is a good candidate for software rendering (raytracing / rasterisation), image processing, physic simulations and any development context that requires a simple and convenient mathematics library. + +*GLM* is written in C++98 but can take advantage of C++11 when supported by the compiler. It is a platform independent library with no dependence and it officially supports the following compilers: +- [Apple Clang 6.0](https://developer.apple.com/library/mac/documentation/CompilerTools/Conceptual/LLVMCompilerOverview/index.html) and higher +- [GCC](http://gcc.gnu.org/) 4.7 and higher +- [Intel C++ Composer](https://software.intel.com/en-us/intel-compilers) XE 2013 and higher +- [LLVM](http://llvm.org/) 3.4 and higher +- [Visual C++](http://www.visualstudio.com/) 2013 and higher +- [CUDA](https://developer.nvidia.com/about-cuda) 9.0 and higher (experimental) +- [SYCL](https://www.khronos.org/sycl/) (experimental: only [ComputeCpp](https://codeplay.com/products/computesuite/computecpp) implementation has been tested). +- Any C++11 compiler + +For more information about *GLM*, please have a look at the [manual](manual.md) and the [API reference documentation](http://glm.g-truc.net/0.9.8/api/index.html). +The source code and the documentation are licensed under either the [Happy Bunny License (Modified MIT) or the MIT License](manual.md#section0). + +Thanks for contributing to the project by [submitting issues](https://github.com/g-truc/glm/issues) for bug reports and feature requests. Any feedback is welcome at [glm@g-truc.net](mailto://glm@g-truc.net). + +```cpp +#include // glm::vec3 +#include // glm::vec4 +#include // glm::mat4 +#include // glm::translate, glm::rotate, glm::scale +#include // glm::perspective +#include // glm::pi + +glm::mat4 camera(float Translate, glm::vec2 const& Rotate) +{ + glm::mat4 Projection = glm::perspective(glm::pi() * 0.25f, 4.0f / 3.0f, 0.1f, 100.f); + glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate)); + View = glm::rotate(View, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f)); + View = glm::rotate(View, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f)); + glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); + return Projection * View * Model; +} +``` + +## [Lastest release](https://github.com/g-truc/glm/releases/latest) + +## Project Health + +| Service | System | Compiler | Status | +| ------- | ------ | -------- | ------ | +| [Travis CI](https://travis-ci.org/g-truc/glm)| MacOSX, Linux 64 bits | Clang 3.6, Clang 5.0, GCC 4.9, GCC 7.3 | [![Travis CI](https://travis-ci.org/g-truc/glm.svg?branch=master)](https://travis-ci.org/g-truc/glm) +| [AppVeyor](https://ci.appveyor.com/project/Groovounet/glm)| Windows 32 and 64 | Visual Studio 2013, Visual Studio 2015, Visual Studio 2017 | [![AppVeyor](https://ci.appveyor.com/api/projects/status/32r7s2skrgm9ubva?svg=true)](https://ci.appveyor.com/project/Groovounet/glm) + +## Release notes + +### [GLM 0.9.9.8](https://github.com/g-truc/glm/releases/tag/0.9.9.8) - 2020-04-13 +#### Features: +- Added GLM_EXT_vector_intX* and GLM_EXT_vector_uintX* extensions +- Added GLM_EXT_matrix_intX* and GLM_EXT_matrix_uintX* extensions + +#### Improvements: +- Added clamp, repeat, mirrorClamp and mirrorRepeat function to GLM_EXT_scalar_commond and GLM_EXT_vector_commond extensions with tests + +#### Fixes: +- Fixed unnecessary warnings from matrix_projection.inl #995 +- Fixed quaternion slerp overload which interpolates with extra spins #996 +- Fixed for glm::length using arch64 #992 +- Fixed singularity check for quatLookAt #770 + +### [GLM 0.9.9.7](https://github.com/g-truc/glm/releases/tag/0.9.9.7) - 2020-01-05 +#### Improvements: +- Improved Neon support with more functions optimized #950 +- Added CMake GLM interface #963 +- Added fma implementation based on std::fma #969 +- Added missing quat constexpr #955 +- Added GLM_FORCE_QUAT_DATA_WXYZ to store quat data as w,x,y,z instead of x,y,z,w #983 + +#### Fixes: +- Fixed equal ULP variation when using negative sign #965 +- Fixed for intersection ray/plane and added related tests #953 +- Fixed ARM 64bit detection #949 +- Fixed GLM_EXT_matrix_clip_space warnings #980 +- Fixed Wimplicit-int-float-conversion warnings with clang 10+ #986 +- Fixed EXT_matrix_clip_space perspectiveFov + +### [GLM 0.9.9.6](https://github.com/g-truc/glm/releases/tag/0.9.9.6) - 2019-09-08 +#### Features: +- Added Neon support #945 +- Added SYCL support #914 +- Added EXT_scalar_integer extension with power of two and multiple scalar functions +- Added EXT_vector_integer extension with power of two and multiple vector functions + +#### Improvements: +- Added Visual C++ 2019 detection +- Added Visual C++ 2017 15.8 and 15.9 detection +- Added missing genType check for bitCount and bitfieldReverse #893 + +#### Fixes: +- Fixed for g++6 where -std=c++1z sets __cplusplus to 201500 instead of 201402 #921 +- Fixed hash hashes qua instead of tquat #919 +- Fixed .natvis as structs renamed #915 +- Fixed ldexp and frexp declaration #895 +- Fixed missing const to quaternion conversion operators #890 +- Fixed EXT_scalar_ulp and EXT_vector_ulp API coding style +- Fixed quaternion componant order: w, {x, y, z} #916 +- Fixed GLM_HAS_CXX11_STL broken on Clang with Linux #926 +- Fixed Clang or GCC build due to wrong GLM_HAS_IF_CONSTEXPR definition #907 +- Fixed CUDA 9 build #910 + +#### Deprecation: + - Removed CMake install and uninstall scripts + +### [GLM 0.9.9.5](https://github.com/g-truc/glm/releases/tag/0.9.9.5) - 2019-04-01 +#### Fixes: +- Fixed build errors when defining GLM_ENABLE_EXPERIMENTAL #884 #883 +- Fixed 'if constexpr' warning #887 +- Fixed missing declarations for frexp and ldexp #886 + +### [GLM 0.9.9.4](https://github.com/g-truc/glm/releases/tag/0.9.9.4) - 2019-03-19 +#### Features: +- Added mix implementation for matrices in EXT_matrix_common #842 +- Added BUILD_SHARED_LIBS and BUILD_STATIC_LIBS build options #871 + +#### Improvements: +- Added GLM_FORCE_INTRINSICS to enable SIMD instruction code path. By default, it's disabled allowing constexpr support by default. #865 +- Optimized inverseTransform #867 + +#### Fixes: +- Fixed in mat4x3 conversion #829 +- Fixed constexpr issue on GCC #832 #865 +- Fixed mix implementation to improve GLSL conformance #866 +- Fixed int8 being defined as unsigned char with some compiler #839 +- Fixed vec1 include #856 +- Ignore .vscode #848 + +### [GLM 0.9.9.3](https://github.com/g-truc/glm/releases/tag/0.9.9.3) - 2018-10-31 +#### Features: +- Added equal and notEqual overload with max ULPs parameters for scalar numbers #121 +- Added GLM_FORCE_SILENT_WARNINGS to silent GLM warnings when using language extensions but using W4 or Wpedantic warnings #814 #775 +- Added adjugate functions to GTX_matrix_operation #151 +- Added GLM_FORCE_ALIGNED_GENTYPES to enable aligned types and SIMD instruction are not enabled. This disable constexpr #816 + +#### Improvements: +- Added constant time ULP distance between float #121 +- Added GLM_FORCE_SILENT_WARNINGS to suppress GLM warnings #822 + +#### Fixes: +- Fixed simplex noise build with double #734 +- Fixed bitfieldInsert according to GLSL spec #818 +- Fixed refract for negative 'k' #808 + +### [GLM 0.9.9.2](https://github.com/g-truc/glm/releases/tag/0.9.9.2) - 2018-09-14 +#### Fixes: +- Fixed GLM_FORCE_CXX** section in the manual +- Fixed default initialization with vector and quaternion types using GLM_FORCE_CTOR_INIT #812 + +### [GLM 0.9.9.1](https://github.com/g-truc/glm/releases/tag/0.9.9.1) - 2018-09-03 +#### Features: +- Added bitfieldDeinterleave to GTC_bitfield +- Added missing equal and notEqual with epsilon for quaternion types to GTC_quaternion +- Added EXT_matrix_relational: equal and notEqual with epsilon for matrix types +- Added missing aligned matrix types to GTC_type_aligned +- Added C++17 detection +- Added Visual C++ language standard version detection +- Added PDF manual build from markdown + +#### Improvements: +- Added a section to the manual for contributing to GLM +- Refactor manual, lists all configuration defines +- Added missing vec1 based constructors +- Redesigned constexpr support which excludes both SIMD and constexpr #783 +- Added detection of Visual C++ 2017 toolsets +- Added identity functions #765 +- Splitted headers into EXT extensions to improve compilation time #670 +- Added separated performance tests +- Clarified refract valid range of the indices of refraction, between -1 and 1 inclusively #806 + +#### Fixes: +- Fixed SIMD detection on Clang and GCC +- Fixed build problems due to printf and std::clock_t #778 +- Fixed int mod +- Anonymous unions require C++ language extensions +- Fixed ortho #790 +- Fixed Visual C++ 2013 warnings in vector relational code #782 +- Fixed ICC build errors with constexpr #704 +- Fixed defaulted operator= and constructors #791 +- Fixed invalid conversion from int scalar with vec4 constructor when using SSE instruction +- Fixed infinite loop in random functions when using negative radius values using an assert #739 + +### [GLM 0.9.9.0](https://github.com/g-truc/glm/releases/tag/0.9.9.0) - 2018-05-22 +#### Features: +- Added RGBM encoding in GTC_packing #420 +- Added GTX_color_encoding extension +- Added GTX_vec_swizzle, faster compile time swizzling then swizzle operator #558 +- Added GTX_exterior_product with a vec2 cross implementation #621 +- Added GTX_matrix_factorisation to factor matrices in various forms #654 +- Added [GLM_ENABLE_EXPERIMENTAL](manual.md#section7_4) to enable experimental features. +- Added packing functions for integer vectors #639 +- Added conan packaging configuration #643 #641 +- Added quatLookAt to GTX_quaternion #659 +- Added fmin, fmax and fclamp to GTX_extended_min_max #372 +- Added EXT_vector_relational: extend equal and notEqual to take an epsilon argument +- Added EXT_vector_relational: openBounded and closeBounded +- Added EXT_vec1: *vec1 types +- Added GTX_texture: levels function +- Added spearate functions to use both nagative one and zero near clip plans #680 +- Added GLM_FORCE_SINGLE_ONLY to use GLM on platforms that don't support double #627 +- Added GTX_easing for interpolation functions #761 + +#### Improvements: +- No more default initialization of vector, matrix and quaternion types +- Added lowp variant of GTC_color_space convertLinearToSRGB #419 +- Replaced the manual by a markdown version #458 +- Improved API documentation #668 +- Optimized GTC_packing implementation +- Optimized GTC_noise functions +- Optimized GTC_color_space HSV to RGB conversions +- Optimised GTX_color_space_YCoCg YCoCgR conversions +- Optimized GTX_matrix_interpolation axisAngle function +- Added FAQ 12: Windows headers cause build errors... #557 +- Removed GCC shadow warnings #595 +- Added error for including of different versions of GLM #619 +- Added GLM_FORCE_IGNORE_VERSION to ignore error caused by including different version of GLM #619 +- Reduced warnings when using very strict compilation flags #646 +- length() member functions are constexpr #657 +- Added support of -Weverything with Clang #646 +- Improved exponential function test coverage +- Enabled warnings as error with Clang unit tests +- Conan package is an external repository: https://github.com/bincrafters/conan-glm +- Clarify quat_cast documentation, applying on pure rotation matrices #759 + +#### Fixes: +- Removed doxygen references to GTC_half_float which was removed in 0.9.4 +- Fixed glm::decompose #448 +- Fixed intersectRayTriangle #6 +- Fixed dual quaternion != operator #629 +- Fixed usused variable warning in GTX_spline #618 +- Fixed references to GLM_FORCE_RADIANS which was removed #642 +- Fixed glm::fastInverseSqrt to use fast inverse square #640 +- Fixed axisAngle NaN #638 +- Fixed integer pow from GTX_integer with null exponent #658 +- Fixed quat normalize build error #656 +- Fixed Visual C++ 2017.2 warning regarding __has_feature definision #655 +- Fixed documentation warnings +- Fixed GLM_HAS_OPENMP when OpenMP is not enabled +- Fixed Better follow GLSL min and max specification #372 +- Fixed quaternion constructor from two vectors special cases #469 +- Fixed glm::to_string on quaternions wrong components order #681 +- Fixed acsch #698 +- Fixed isnan on CUDA #727 + +#### Deprecation: +- Requires Visual Studio 2013, GCC 4.7, Clang 3.4, Cuda 7, ICC 2013 or a C++11 compiler +- Removed GLM_GTX_simd_vec4 extension +- Removed GLM_GTX_simd_mat4 extension +- Removed GLM_GTX_simd_quat extension +- Removed GLM_SWIZZLE, use GLM_FORCE_SWIZZLE instead +- Removed GLM_MESSAGES, use GLM_FORCE_MESSAGES instead +- Removed GLM_DEPTH_ZERO_TO_ONE, use GLM_FORCE_DEPTH_ZERO_TO_ONE instead +- Removed GLM_LEFT_HANDED, use GLM_FORCE_LEFT_HANDED instead +- Removed GLM_FORCE_NO_CTOR_INIT +- Removed glm::uninitialize + +--- +### [GLM 0.9.8.5](https://github.com/g-truc/glm/releases/tag/0.9.8.5) - 2017-08-16 +#### Features: +- Added Conan package support #647 + +#### Fixes: +- Fixed Clang version detection from source #608 +- Fixed packF3x9_E1x5 exponent packing #614 +- Fixed build error min and max specializations with integer #616 +- Fixed simd_mat4 build error #652 + +--- +### [GLM 0.9.8.4](https://github.com/g-truc/glm/releases/tag/0.9.8.4) - 2017-01-22 +#### Fixes: +- Fixed GTC_packing test failing on GCC x86 due to denorms #212 #577 +- Fixed POPCNT optimization build in Clang #512 +- Fixed intersectRayPlane returns true in parallel case #578 +- Fixed GCC 6.2 compiler warnings #580 +- Fixed GTX_matrix_decompose decompose #582 #448 +- Fixed GCC 4.5 and older build #566 +- Fixed Visual C++ internal error when declaring a global vec type with siwzzle expression enabled #594 +- Fixed GLM_FORCE_CXX11 with Clang and libstlc++ which wasn't using C++11 STL features. #604 + +--- +### [GLM 0.9.8.3](https://github.com/g-truc/glm/releases/tag/0.9.8.3) - 2016-11-12 +#### Improvements: +- Broader support of GLM_FORCE_UNRESTRICTED_GENTYPE #378 + +#### Fixes: +- Fixed Android build error with C++11 compiler but C++98 STL #284 #564 +- Fixed GTX_transform2 shear* functions #403 +- Fixed interaction between GLM_FORCE_UNRESTRICTED_GENTYPE and ortho function #568 +- Fixed bitCount with AVX on 32 bit builds #567 +- Fixed CMake find_package with version specification #572 #573 + +--- +### [GLM 0.9.8.2](https://github.com/g-truc/glm/releases/tag/0.9.8.2) - 2016-11-01 +#### Improvements: +- Added Visual C++ 15 detection +- Added Clang 4.0 detection +- Added warning messages when using GLM_FORCE_CXX** but the compiler + is known to not fully support the requested C++ version #555 +- Refactored GLM_COMPILER_VC values +- Made quat, vec, mat type component length() static #565 + +#### Fixes: +- Fixed Visual C++ constexpr build error #555, #556 + +--- +### [GLM 0.9.8.1](https://github.com/g-truc/glm/releases/tag/0.9.8.1) - 2016-09-25 +#### Improvements: +- Optimized quaternion log function #554 + +#### Fixes: +- Fixed GCC warning filtering, replaced -pedantic by -Wpedantic +- Fixed SIMD faceforward bug. #549 +- Fixed GCC 4.8 with C++11 compilation option #550 +- Fixed Visual Studio aligned type W4 warning #548 +- Fixed packing/unpacking function fixed for 5_6_5 and 5_5_5_1 #552 + +--- +### [GLM 0.9.8.0](https://github.com/g-truc/glm/releases/tag/0.9.8.0) - 2016-09-11 +#### Features: +- Added right and left handed projection and clip control support #447 #415 #119 +- Added compNormalize and compScale functions to GTX_component_wise +- Added packF3x9_E1x5 and unpackF3x9_E1x5 to GTC_packing for RGB9E5 #416 +- Added (un)packHalf to GTC_packing +- Added (un)packUnorm and (un)packSnorm to GTC_packing +- Added 16bit pack and unpack to GTC_packing +- Added 8bit pack and unpack to GTC_packing +- Added missing bvec* && and || operators +- Added iround and uround to GTC_integer, fast round on positive values +- Added raw SIMD API +- Added 'aligned' qualifiers +- Added GTC_type_aligned with aligned *vec* types +- Added GTC_functions extension +- Added quaternion version of isnan and isinf #521 +- Added lowestBitValue to GTX_bit #536 +- Added GLM_FORCE_UNRESTRICTED_GENTYPE allowing non basic genType #543 + +#### Improvements: +- Improved SIMD and swizzle operators interactions with GCC and Clang #474 +- Improved GTC_random linearRand documentation +- Improved GTC_reciprocal documentation +- Improved GLM_FORCE_EXPLICIT_CTOR coverage #481 +- Improved OpenMP support detection for Clang, GCC, ICC and VC +- Improved GTX_wrap for SIMD friendliness +- Added constexpr for *vec*, *mat*, *quat* and *dual_quat* types #493 +- Added NEON instruction set detection +- Added MIPS CPUs detection +- Added PowerPC CPUs detection +- Use Cuda built-in function for abs function implementation with Cuda compiler +- Factorized GLM_COMPILER_LLVM and GLM_COMPILER_APPLE_CLANG into GLM_COMPILER_CLANG +- No more warnings for use of long long +- Added more information to build messages + +#### Fixes: +- Fixed GTX_extended_min_max filename typo #386 +- Fixed intersectRayTriangle to not do any unintentional backface culling +- Fixed long long warnings when using C++98 on GCC and Clang #482 +- Fixed sign with signed integer function on non-x86 architecture +- Fixed strict aliasing warnings #473 +- Fixed missing vec1 overload to length2 and distance2 functions #431 +- Fixed GLM test '/fp:fast' and '/Za' command-line options are incompatible +- Fixed quaterion to mat3 cast function mat3_cast from GTC_quaternion #542 +- Fixed GTX_io for Cuda #547 #546 + +#### Deprecation: +- Removed GLM_FORCE_SIZE_FUNC define +- Deprecated GLM_GTX_simd_vec4 extension +- Deprecated GLM_GTX_simd_mat4 extension +- Deprecated GLM_GTX_simd_quat extension +- Deprecated GLM_SWIZZLE, use GLM_FORCE_SWIZZLE instead +- Deprecated GLM_MESSAGES, use GLM_FORCE_MESSAGES instead + +--- +### [GLM 0.9.7.6](https://github.com/g-truc/glm/releases/tag/0.9.7.6) - 2016-07-16 +#### Improvements: +- Added pkg-config file #509 +- Updated list of compiler versions detected +- Improved C++ 11 STL detection #523 + +#### Fixes: +- Fixed STL for C++11 detection on ICC #510 +- Fixed missing vec1 overload to length2 and distance2 functions #431 +- Fixed long long warnings when using C++98 on GCC and Clang #482 +- Fixed scalar reciprocal functions (GTC_reciprocal) #520 + +--- +### [GLM 0.9.7.5](https://github.com/g-truc/glm/releases/tag/0.9.7.5) - 2016-05-24 +#### Improvements: +- Added Visual C++ Clang toolset detection + +#### Fixes: +- Fixed uaddCarry warning #497 +- Fixed roundPowerOfTwo and floorPowerOfTwo #503 +- Fixed Visual C++ SIMD instruction set automatic detection in 64 bits +- Fixed to_string when used with GLM_FORCE_INLINE #506 +- Fixed GLM_FORCE_INLINE with binary vec4 operators +- Fixed GTX_extended_min_max filename typo #386 +- Fixed intersectRayTriangle to not do any unintentional backface culling + +--- +### [GLM 0.9.7.4](https://github.com/g-truc/glm/releases/tag/0.9.7.4) - 2016-03-19 +#### Fixes: +- Fixed asinh and atanh warning with C++98 STL #484 +- Fixed polar coordinates function latitude #485 +- Fixed outerProduct defintions and operator signatures for mat2x4 and vec4 #475 +- Fixed eulerAngles precision error, returns NaN #451 +- Fixed undefined reference errors #489 +- Fixed missing GLM_PLATFORM_CYGWIN declaration #495 +- Fixed various undefined reference errors #490 + +--- +### [GLM 0.9.7.3](https://github.com/g-truc/glm/releases/tag/0.9.7.3) - 2016-02-21 +#### Improvements: +- Added AVX512 detection + +#### Fixes: +- Fixed CMake policy warning +- Fixed GCC 6.0 detection #477 +- Fixed Clang build on Windows #479 +- Fixed 64 bits constants warnings on GCC #463 + +--- +### [GLM 0.9.7.2](https://github.com/g-truc/glm/releases/tag/0.9.7.2) - 2016-01-03 +#### Fixes: +- Fixed GTC_round floorMultiple/ceilMultiple #412 +- Fixed GTC_packing unpackUnorm3x10_1x2 #414 +- Fixed GTC_matrix_inverse affineInverse #192 +- Fixed ICC on Linux build errors #449 +- Fixed ldexp and frexp compilation errors +- Fixed "Declaration shadows a field" warning #468 +- Fixed 'GLM_COMPILER_VC2005 is not defined' warning #468 +- Fixed various 'X is not defined' warnings #468 +- Fixed missing unary + operator #435 +- Fixed Cygwin build errors when using C++11 #405 + +--- +### [GLM 0.9.7.1](https://github.com/g-truc/glm/releases/tag/0.9.7.1) - 2015-09-07 +#### Improvements: +- Improved constexpr for constant functions coverage #198 +- Added to_string for quat and dual_quat in GTX_string_cast #375 +- Improved overall execution time of unit tests #396 + +#### Fixes: +- Fixed strict alignment warnings #235 #370 +- Fixed link errors on compilers not supported default function #377 +- Fixed compilation warnings in vec4 +- Fixed non-identity quaternions for equal vectors #234 +- Fixed excessive GTX_fast_trigonometry execution time #396 +- Fixed Visual Studio 2015 'hides class member' warnings #394 +- Fixed builtin bitscan never being used #392 +- Removed unused func_noise.* files #398 + +--- +### [GLM 0.9.7.0](https://github.com/g-truc/glm/releases/tag/0.9.7.0) - 2015-08-02 +#### Features: +- Added GTC_color_space: convertLinearToSRGB and convertSRGBToLinear functions +- Added 'fmod' overload to GTX_common with tests #308 +- Left handed perspective and lookAt functions #314 +- Added functions eulerAngleXYZ and extractEulerAngleXYZ #311 +- Added to perform std::hash on GLM types #320 #367 +- Added for texcoord wrapping +- Added static components and precision members to all vector and quat types #350 +- Added .gitignore #349 +- Added support of defaulted functions to GLM types, to use them in unions #366 + +#### Improvements: +- Changed usage of __has_include to support Intel compiler #307 +- Specialized integer implementation of YCoCg-R #310 +- Don't show status message in 'FindGLM' if 'QUIET' option is set. #317 +- Added master branch continuous integration service on Linux 64 #332 +- Clarified manual regarding angle unit in GLM, added FAQ 11 #326 +- Updated list of compiler versions + +#### Fixes: +- Fixed default precision for quat and dual_quat type #312 +- Fixed (u)int64 MSB/LSB handling on BE archs #306 +- Fixed multi-line comment warning in g++. #315 +- Fixed specifier removal by 'std::make_pair<>' #333 +- Fixed perspective fovy argument documentation #327 +- Removed -m64 causing build issues on Linux 32 #331 +- Fixed isfinite with C++98 compilers #343 +- Fixed Intel compiler build error on Linux #354 +- Fixed use of libstdc++ with Clang #351 +- Fixed quaternion pow #346 +- Fixed decompose warnings #373 +- Fixed matrix conversions #371 + +#### Deprecation: +- Removed integer specification for 'mod' in GTC_integer #308 +- Removed GTX_multiple, replaced by GTC_round + +--- +### [GLM 0.9.6.3](https://github.com/g-truc/glm/releases/tag/0.9.6.3) - 2015-02-15 +- Fixed Android doesn't have C++ 11 STL #284 + +--- +### [GLM 0.9.6.2](https://github.com/g-truc/glm/releases/tag/0.9.6.2) - 2015-02-15 +#### Features: +- Added display of GLM version with other GLM_MESSAGES +- Added ARM instruction set detection + +#### Improvements: +- Removed assert for perspective with zFar < zNear #298 +- Added Visual Studio natvis support for vec1, quat and dualqual types +- Cleaned up C++11 feature detections +- Clarify GLM licensing + +#### Fixes: +- Fixed faceforward build #289 +- Fixed conflict with Xlib #define True 1 #293 +- Fixed decompose function VS2010 templating issues #294 +- Fixed mat4x3 = mat2x3 * mat4x2 operator #297 +- Fixed warnings in F2x11_1x10 packing function in GTC_packing #295 +- Fixed Visual Studio natvis support for vec4 #288 +- Fixed GTC_packing *pack*norm*x* build and added tests #292 +- Disabled GTX_scalar_multiplication for GCC, failing to build tests #242 +- Fixed Visual C++ 2015 constexpr errors: Disabled only partial support +- Fixed functions not inlined with Clang #302 +- Fixed memory corruption (undefined behaviour) #303 + +--- +### [GLM 0.9.6.1](https://github.com/g-truc/glm/releases/tag/0.9.6.1) - 2014-12-10 +#### Features: +- Added GLM_LANG_CXX14_FLAG and GLM_LANG_CXX1Z_FLAG language feature flags +- Added C++14 detection + +#### Improvements: +- Clean up GLM_MESSAGES compilation log to report only detected capabilities + +#### Fixes: +- Fixed scalar uaddCarry build error with Cuda #276 +- Fixed C++11 explicit conversion operators detection #282 +- Fixed missing explicit conversion when using integer log2 with *vec1 types +- Fixed 64 bits integer GTX_string_cast to_string on VC 32 bit compiler +- Fixed Android build issue, STL C++11 is not supported by the NDK #284 +- Fixed unsupported _BitScanForward64 and _BitScanReverse64 in VC10 +- Fixed Visual C++ 32 bit build #283 +- Fixed GLM_FORCE_SIZE_FUNC pragma message +- Fixed C++98 only build +- Fixed conflict between GTX_compatibility and GTC_quaternion #286 +- Fixed C++ language restriction using GLM_FORCE_CXX** + +--- +### [GLM 0.9.6.0](https://github.com/g-truc/glm/releases/tag/0.9.6.0) - 2014-11-30 +#### Features: +- Exposed template vector and matrix types in 'glm' namespace #239, #244 +- Added GTX_scalar_multiplication for C++ 11 compiler only #242 +- Added GTX_range for C++ 11 compiler only #240 +- Added closestPointOnLine function for tvec2 to GTX_closest_point #238 +- Added GTC_vec1 extension, *vec1 support to *vec* types +- Updated GTX_associated_min_max with vec1 support +- Added support of precision and integers to linearRand #230 +- Added Integer types support to GTX_string_cast #249 +- Added vec3 slerp #237 +- Added GTX_common with isdenomal #223 +- Added GLM_FORCE_SIZE_FUNC to replace .length() by .size() #245 +- Added GLM_FORCE_NO_CTOR_INIT +- Added 'uninitialize' to explicitly not initialize a GLM type +- Added GTC_bitfield extension, promoted GTX_bit +- Added GTC_integer extension, promoted GTX_bit and GTX_integer +- Added GTC_round extension, promoted GTX_bit +- Added GLM_FORCE_EXPLICIT_CTOR to require explicit type conversions #269 +- Added GTX_type_aligned for aligned vector, matrix and quaternion types + +#### Improvements: +- Rely on C++11 to implement isinf and isnan +- Removed GLM_FORCE_CUDA, Cuda is implicitly detected +- Separated Apple Clang and LLVM compiler detection +- Used pragma once +- Undetected C++ compiler automatically compile with GLM_FORCE_CXX98 and + GLM_FORCE_PURE +- Added not function (from GLSL specification) on VC12 +- Optimized bitfieldReverse and bitCount functions +- Optimized findLSB and findMSB functions. +- Optimized matrix-vector multiple performance with Cuda #257, #258 +- Reduced integer type redifinitions #233 +- Rewrited of GTX_fast_trigonometry #264 #265 +- Made types trivially copyable #263 +- Removed in GLM tests +- Used std features within GLM without redeclaring +- Optimized cot function #272 +- Optimized sign function #272 +- Added explicit cast from quat to mat3 and mat4 #275 + +#### Fixes: +- Fixed std::nextafter not supported with C++11 on Android #217 +- Fixed missing value_type for dual quaternion +- Fixed return type of dual quaternion length +- Fixed infinite loop in isfinite function with GCC #221 +- Fixed Visual Studio 14 compiler warnings +- Fixed implicit conversion from another tvec2 type to another tvec2 #241 +- Fixed lack of consistency of quat and dualquat constructors +- Fixed uaddCarray #253 +- Fixed float comparison warnings #270 + +#### Deprecation: +- Requires Visual Studio 2010, GCC 4.2, Apple Clang 4.0, LLVM 3.0, Cuda 4, ICC 2013 or a C++98 compiler +- Removed degrees for function parameters +- Removed GLM_FORCE_RADIANS, active by default +- Removed VC 2005 / 8 and 2008 / 9 support +- Removed GCC 3.4 to 4.3 support +- Removed LLVM GCC support +- Removed LLVM 2.6 to 3.1 support +- Removed CUDA 3.0 to 3.2 support + +--- +### [GLM 0.9.5.4 - 2014-06-21](https://github.com/g-truc/glm/releases/tag/0.9.5.4) +- Fixed non-utf8 character #196 +- Added FindGLM install for CMake #189 +- Fixed GTX_color_space - saturation #195 +- Fixed glm::isinf and glm::isnan for with Android NDK 9d #191 +- Fixed builtin GLM_ARCH_SSE4 #204 +- Optimized Quaternion vector rotation #205 +- Fixed missing doxygen @endcond tag #211 +- Fixed instruction set detection with Clang #158 +- Fixed orientate3 function #207 +- Fixed lerp when cosTheta is close to 1 in quaternion slerp #210 +- Added GTX_io for io with #144 +- Fixed fastDistance ambiguity #215 +- Fixed tweakedInfinitePerspective #208 and added user-defined epsilon to + tweakedInfinitePerspective +- Fixed std::copy and std::vector with GLM types #214 +- Fixed strict aliasing issues #212, #152 +- Fixed std::nextafter not supported with C++11 on Android #213 +- Fixed corner cases in exp and log functions for quaternions #199 + +--- +### GLM 0.9.5.3 - 2014-04-02 +- Added instruction set auto detection with Visual C++ using _M_IX86_FP - /arch + compiler argument +- Fixed GTX_raw_data code dependency +- Fixed GCC instruction set detection +- Added GLM_GTX_matrix_transform_2d extension (#178, #176) +- Fixed CUDA issues (#169, #168, #183, #182) +- Added support for all extensions but GTX_string_cast to CUDA +- Fixed strict aliasing warnings in GCC 4.8.1 / Android NDK 9c (#152) +- Fixed missing bitfieldInterleave definisions +- Fixed usubBorrow (#171) +- Fixed eulerAngle*** not consistent for right-handed coordinate system (#173) +- Added full tests for eulerAngle*** functions (#173) +- Added workaround for a CUDA compiler bug (#186, #185) + +--- +### GLM 0.9.5.2 - 2014-02-08 +- Fixed initializer list ambiguity (#159, #160) +- Fixed warnings with the Android NDK 9c +- Fixed non power of two matrix products +- Fixed mix function link error +- Fixed SSE code included in GLM tests on "pure" platforms +- Fixed undefined reference to fastInverseSqrt (#161) +- Fixed GLM_FORCE_RADIANS with build error (#165) +- Fix dot product clamp range for vector angle functions. (#163) +- Tentative fix for strict aliasing warning in GCC 4.8.1 / Android NDK 9c (#152) +- Fixed GLM_GTC_constants description brief (#162) + +--- +### GLM 0.9.5.1 - 2014-01-11 +- Fixed angle and orientedAngle that sometimes return NaN values (#145) +- Deprecated degrees for function parameters and display a message +- Added possible static_cast conversion of GLM types (#72) +- Fixed error 'inverse' is not a member of 'glm' from glm::unProject (#146) +- Fixed mismatch between some declarations and definitions +- Fixed inverse link error when using namespace glm; (#147) +- Optimized matrix inverse and division code (#149) +- Added intersectRayPlane function (#153) +- Fixed outerProduct return type (#155) + +--- +### GLM 0.9.5.0 - 2013-12-25 +- Added forward declarations (glm/fwd.hpp) for faster compilations +- Added per feature headers +- Minimized GLM internal dependencies +- Improved Intel Compiler detection +- Added bitfieldInterleave and _mm_bit_interleave_si128 functions +- Added GTX_scalar_relational +- Added GTX_dual_quaternion +- Added rotation function to GTX_quaternion (#22) +- Added precision variation of each type +- Added quaternion comparison functions +- Fixed GTX_multiple for negative value +- Removed GTX_ocl_type extension +- Fixed post increment and decrement operators +- Fixed perspective with zNear == 0 (#71) +- Removed l-value swizzle operators +- Cleaned up compiler detection code for unsupported compilers +- Replaced C cast by C++ casts +- Fixed .length() that should return a int and not a size_t +- Added GLM_FORCE_SIZE_T_LENGTH and glm::length_t +- Removed unnecessary conversions +- Optimized packing and unpacking functions +- Removed the normalization of the up argument of lookAt function (#114) +- Added low precision specializations of inversesqrt +- Fixed ldexp and frexp implementations +- Increased assert coverage +- Increased static_assert coverage +- Replaced GLM traits by STL traits when possible +- Allowed including individual core feature +- Increased unit tests completness +- Added creating of a quaternion from two vectors +- Added C++11 initializer lists +- Fixed umulExtended and imulExtended implementations for vector types (#76) +- Fixed CUDA coverage for GTC extensions +- Added GTX_io extension +- Improved GLM messages enabled when defining GLM_MESSAGES +- Hidden matrix _inverse function implementation detail into private section + +--- +### [GLM 0.9.4.6](https://github.com/g-truc/glm/releases/tag/0.9.4.6) - 2013-09-20 +- Fixed detection to select the last known compiler if newer version #106 +- Fixed is_int and is_uint code duplication with GCC and C++11 #107 +- Fixed test suite build while using Clang in C++11 mode +- Added c++1y mode support in CMake test suite +- Removed ms extension mode to CMake when no using Visual C++ +- Added pedantic mode to CMake test suite for Clang and GCC +- Added use of GCC frontend on Unix for ICC and Visual C++ fronted on Windows + for ICC +- Added compilation errors for unsupported compiler versions +- Fixed glm::orientation with GLM_FORCE_RADIANS defined #112 +- Fixed const ref issue on assignment operator taking a scalar parameter #116 +- Fixed glm::eulerAngleY implementation #117 + +--- +### GLM 0.9.4.5 - 2013-08-12 +- Fixed CUDA support +- Fixed inclusion of intrinsics in "pure" mode #92 +- Fixed language detection on GCC when the C++0x mode isn't enabled #95 +- Fixed issue #97: register is deprecated in C++11 +- Fixed issue #96: CUDA issues +- Added Windows CE detection #92 +- Added missing value_ptr for quaternions #99 + +--- +### GLM 0.9.4.4 - 2013-05-29 +- Fixed slerp when costheta is close to 1 #65 +- Fixed mat4x2 value_type constructor #70 +- Fixed glm.natvis for Visual C++ 12 #82 +- Added assert in inversesqrt to detect division by zero #61 +- Fixed missing swizzle operators #86 +- Fixed CUDA warnings #86 +- Fixed GLM natvis for VC11 #82 +- Fixed GLM_GTX_multiple with negative values #79 +- Fixed glm::perspective when zNear is zero #71 + +--- +### GLM 0.9.4.3 - 2013-03-20 +- Detected qualifier for Clang +- Fixed C++11 mode for GCC, couldn't be enabled without MS extensions +- Fixed squad, intermediate and exp quaternion functions +- Fixed GTX_polar_coordinates euclidean function, takes a vec2 instead of a vec3 +- Clarify the license applying on the manual +- Added a docx copy of the manual +- Fixed GLM_GTX_matrix_interpolation +- Fixed isnan and isinf on Android with Clang +- Autodetected C++ version using __cplusplus value +- Fixed mix for bool and bvec* third parameter + +--- +### GLM 0.9.4.2 - 2013-02-14 +- Fixed compAdd from GTX_component_wise +- Fixed SIMD support for Intel compiler on Windows +- Fixed isnan and isinf for CUDA compiler +- Fixed GLM_FORCE_RADIANS on glm::perspective +- Fixed GCC warnings +- Fixed packDouble2x32 on Xcode +- Fixed mix for vec4 SSE implementation +- Fixed 0x2013 dash character in comments that cause issue in Windows + Japanese mode +- Fixed documentation warnings +- Fixed CUDA warnings + +--- +### GLM 0.9.4.1 - 2012-12-22 +- Improved half support: -0.0 case and implicit conversions +- Fixed Intel Composer Compiler support on Linux +- Fixed interaction between quaternion and euler angles +- Fixed GTC_constants build +- Fixed GTX_multiple +- Fixed quat slerp using mix function when cosTheta close to 1 +- Improved fvec4SIMD and fmat4x4SIMD implementations +- Fixed assert messages +- Added slerp and lerp quaternion functions and tests + +--- +### GLM 0.9.4.0 - 2012-11-18 +- Added Intel Composer Compiler support +- Promoted GTC_espilon extension +- Promoted GTC_ulp extension +- Removed GLM website from the source repository +- Added GLM_FORCE_RADIANS so that all functions takes radians for arguments +- Fixed detection of Clang and LLVM GCC on MacOS X +- Added debugger visualizers for Visual C++ 2012 +- Requires Visual Studio 2005, GCC 4.2, Clang 2.6, Cuda 3, ICC 2013 or a C++98 compiler + +--- +### [GLM 0.9.3.4](https://github.com/g-truc/glm/releases/tag/0.9.3.4) - 2012-06-30 +- Added SSE4 and AVX2 detection. +- Removed VIRTREV_xstream and the incompatibility generated with GCC +- Fixed C++11 compiler option for GCC +- Removed MS language extension option for GCC (not fonctionnal) +- Fixed bitfieldExtract for vector types +- Fixed warnings +- Fixed SSE includes + +--- +### GLM 0.9.3.3 - 2012-05-10 +- Fixed isinf and isnan +- Improved compatibility with Intel compiler +- Added CMake test build options: SIMD, C++11, fast math and MS land ext +- Fixed SIMD mat4 test on GCC +- Fixed perspectiveFov implementation +- Fixed matrixCompMult for none-square matrices +- Fixed namespace issue on stream operators +- Fixed various warnings +- Added VC11 support + +--- +### GLM 0.9.3.2 - 2012-03-15 +- Fixed doxygen documentation +- Fixed Clang version detection +- Fixed simd mat4 /= operator + +--- +### GLM 0.9.3.1 - 2012-01-25 +- Fixed platform detection +- Fixed warnings +- Removed detail code from Doxygen doc + +--- +### GLM 0.9.3.0 - 2012-01-09 +- Added CPP Check project +- Fixed conflict with Windows headers +- Fixed isinf implementation +- Fixed Boost conflict +- Fixed warnings + +--- +### GLM 0.9.3.B - 2011-12-12 +- Added support for Chrone Native Client +- Added epsilon constant +- Removed value_size function from vector types +- Fixed roundEven on GCC +- Improved API documentation +- Fixed modf implementation +- Fixed step function accuracy +- Fixed outerProduct + +--- +### GLM 0.9.3.A - 2011-11-11 +- Improved doxygen documentation +- Added new swizzle operators for C++11 compilers +- Added new swizzle operators declared as functions +- Added GLSL 4.20 length for vector and matrix types +- Promoted GLM_GTC_noise extension: simplex, perlin, periodic noise functions +- Promoted GLM_GTC_random extension: linear, gaussian and various random number +generation distribution +- Added GLM_GTX_constants: provides useful constants +- Added extension versioning +- Removed many unused namespaces +- Fixed half based type contructors +- Added GLSL core noise functions + +--- +### [GLM 0.9.2.7](https://github.com/g-truc/glm/releases/tag/0.9.2.7) - 2011-10-24 +- Added more swizzling constructors +- Added missing none-squared matrix products + +--- +### [GLM 0.9.2.6](https://github.com/g-truc/glm/releases/tag/0.9.2.6) - 2011-10-01 +- Fixed half based type build on old GCC +- Fixed /W4 warnings on Visual C++ +- Fixed some missing l-value swizzle operators + +--- +### GLM 0.9.2.5 - 2011-09-20 +- Fixed floatBitToXint functions +- Fixed pack and unpack functions +- Fixed round functions + +--- +### GLM 0.9.2.4 - 2011-09-03 +- Fixed extensions bugs + +--- +### GLM 0.9.2.3 - 2011-06-08 +- Fixed build issues + +--- +### GLM 0.9.2.2 - 2011-06-02 +- Expend matrix constructors flexibility +- Improved quaternion implementation +- Fixed many warnings across platforms and compilers + +--- +### GLM 0.9.2.1 - 2011-05-24 +- Automatically detect CUDA support +- Improved compiler detection +- Fixed errors and warnings in VC with C++ extensions disabled +- Fixed and tested GLM_GTX_vector_angle +- Fixed and tested GLM_GTX_rotate_vector + +--- +### GLM 0.9.2.0 - 2011-05-09 +- Added CUDA support +- Added CTest test suite +- Added GLM_GTX_ulp extension +- Added GLM_GTX_noise extension +- Added GLM_GTX_matrix_interpolation extension +- Updated quaternion slerp interpolation + +--- +### [GLM 0.9.1.3](https://github.com/g-truc/glm/releases/tag/0.9.1.3) - 2011-05-07 +- Fixed bugs + +--- +### GLM 0.9.1.2 - 2011-04-15 +- Fixed bugs + +--- +### GLM 0.9.1.1 - 2011-03-17 +- Fixed bugs + +--- +### GLM 0.9.1.0 - 2011-03-03 +- Fixed bugs + +--- +### GLM 0.9.1.B - 2011-02-13 +- Updated API documentation +- Improved SIMD implementation +- Fixed Linux build + +--- +### [GLM 0.9.0.8](https://github.com/g-truc/glm/releases/tag/0.9.0.8) - 2011-02-13 +- Added quaternion product operator. +- Clarify that GLM is a header only library. + +--- +### GLM 0.9.1.A - 2011-01-31 +- Added SIMD support +- Added new swizzle functions +- Improved static assert error message with C++0x static_assert +- New setup system +- Reduced branching +- Fixed trunc implementation + +--- +### [GLM 0.9.0.7](https://github.com/g-truc/glm/releases/tag/0.9.0.7) - 2011-01-30 +- Added GLSL 4.10 packing functions +- Added == and != operators for every types. + +--- +### GLM 0.9.0.6 - 2010-12-21 +- Many matrices bugs fixed + +--- +### GLM 0.9.0.5 - 2010-11-01 +- Improved Clang support +- Fixed bugs + +--- +### GLM 0.9.0.4 - 2010-10-04 +- Added autoexp for GLM +- Fixed bugs + +--- +### GLM 0.9.0.3 - 2010-08-26 +- Fixed non-squared matrix operators + +--- +### GLM 0.9.0.2 - 2010-07-08 +- Added GLM_GTX_int_10_10_10_2 +- Fixed bugs + +--- +### GLM 0.9.0.1 - 2010-06-21 +- Fixed extensions errors + +--- +### GLM 0.9.0.0 - 2010-05-25 +- Objective-C support +- Fixed warnings +- Updated documentation + +--- +### GLM 0.9.B.2 - 2010-04-30 +- Git transition +- Removed experimental code from releases +- Fixed bugs + +--- +### GLM 0.9.B.1 - 2010-04-03 +- Based on GLSL 4.00 specification +- Added the new core functions +- Added some implicit conversion support + +--- +### GLM 0.9.A.2 - 2010-02-20 +- Improved some possible errors messages +- Improved declarations and definitions match + +--- +### GLM 0.9.A.1 - 2010-02-09 +- Removed deprecated features +- Internal redesign + +--- +### GLM 0.8.4.4 final - 2010-01-25 +- Fixed warnings + +--- +### GLM 0.8.4.3 final - 2009-11-16 +- Fixed Half float arithmetic +- Fixed setup defines + +--- +### GLM 0.8.4.2 final - 2009-10-19 +- Fixed Half float adds + +--- +### GLM 0.8.4.1 final - 2009-10-05 +- Updated documentation +- Fixed MacOS X build + +--- +### GLM 0.8.4.0 final - 2009-09-16 +- Added GCC 4.4 and VC2010 support +- Added matrix optimizations + +--- +### GLM 0.8.3.5 final - 2009-08-11 +- Fixed bugs + +--- +### GLM 0.8.3.4 final - 2009-08-10 +- Updated GLM according GLSL 1.5 spec +- Fixed bugs + +--- +### GLM 0.8.3.3 final - 2009-06-25 +- Fixed bugs + +--- +### GLM 0.8.3.2 final - 2009-06-04 +- Added GLM_GTC_quaternion +- Added GLM_GTC_type_precision + +--- +### GLM 0.8.3.1 final - 2009-05-21 +- Fixed old extension system. + +--- +### GLM 0.8.3.0 final - 2009-05-06 +- Added stable extensions. +- Added new extension system. + +--- +### GLM 0.8.2.3 final - 2009-04-01 +- Fixed bugs. + +--- +### GLM 0.8.2.2 final - 2009-02-24 +- Fixed bugs. + +--- +### GLM 0.8.2.1 final - 2009-02-13 +- Fixed bugs. + +--- +### GLM 0.8.2 final - 2009-01-21 +- Fixed bugs. + +--- +### GLM 0.8.1 final - 2008-10-30 +- Fixed bugs. + +--- +### GLM 0.8.0 final - 2008-10-23 +- New method to use extension. + +--- +### GLM 0.8.0 beta3 - 2008-10-10 +- Added CMake support for GLM tests. + +--- +### GLM 0.8.0 beta2 - 2008-10-04 +- Improved half scalars and vectors support. + +--- +### GLM 0.8.0 beta1 - 2008-09-26 +- Improved GLSL conformance +- Added GLSL 1.30 support +- Improved API documentation + +--- +### GLM 0.7.6 final - 2008-08-08 +- Improved C++ standard comformance +- Added Static assert for types checking + +--- +### GLM 0.7.5 final - 2008-07-05 +- Added build message system with Visual Studio +- Pedantic build with GCC + +--- +### GLM 0.7.4 final - 2008-06-01 +- Added external dependencies system. + +--- +### GLM 0.7.3 final - 2008-05-24 +- Fixed bugs +- Added new extension group + +--- +### GLM 0.7.2 final - 2008-04-27 +- Updated documentation +- Added preprocessor options + +--- +### GLM 0.7.1 final - 2008-03-24 +- Disabled half on GCC +- Fixed extensions + +--- +### GLM 0.7.0 final - 2008-03-22 +- Changed to MIT license +- Added new documentation + +--- +### GLM 0.6.4 - 2007-12-10 +- Fixed swizzle operators + +--- +### GLM 0.6.3 - 2007-11-05 +- Fixed type data accesses +- Fixed 3DSMax sdk conflict + +--- +### GLM 0.6.2 - 2007-10-08 +- Fixed extension + +--- +### GLM 0.6.1 - 2007-10-07 +- Fixed a namespace error +- Added extensions + +--- +### GLM 0.6.0 : 2007-09-16 +- Added new extension namespace mecanium +- Added Automatic compiler detection + +--- +### GLM 0.5.1 - 2007-02-19 +- Fixed swizzle operators + +--- +### GLM 0.5.0 - 2007-01-06 +- Upgrated to GLSL 1.2 +- Added swizzle operators +- Added setup settings + +--- +### GLM 0.4.1 - 2006-05-22 +- Added OpenGL examples + +--- +### GLM 0.4.0 - 2006-05-17 +- Added missing operators to vec* and mat* +- Added first GLSL 1.2 features +- Fixed windows.h before glm.h when windows.h required + +--- +### GLM 0.3.2 - 2006-04-21 +- Fixed texcoord components access. +- Fixed mat4 and imat4 division operators. + +--- +### GLM 0.3.1 - 2006-03-28 +- Added GCC 4.0 support under MacOS X. +- Added GCC 4.0 and 4.1 support under Linux. +- Added code optimisations. + +--- +### GLM 0.3 - 2006-02-19 +- Improved GLSL type conversion and construction compliance. +- Added experimental extensions. +- Added Doxygen Documentation. +- Added code optimisations. +- Fixed bugs. + +--- +### GLM 0.2 - 2005-05-05 +- Improve adaptative from GLSL. +- Add experimental extensions based on OpenGL extension process. +- Fixe bugs. + +--- +### GLM 0.1 - 2005-02-21 +- Add vec2, vec3, vec4 GLSL types +- Add ivec2, ivec3, ivec4 GLSL types +- Add bvec2, bvec3, bvec4 GLSL types +- Add mat2, mat3, mat4 GLSL types +- Add almost all functions + diff --git a/vendor/glm/test/CMakeLists.txt b/vendor/glm/test/CMakeLists.txt new file mode 100644 index 0000000..2fd15de --- /dev/null +++ b/vendor/glm/test/CMakeLists.txt @@ -0,0 +1,246 @@ +option(GLM_QUIET "No CMake Message" OFF) +option(BUILD_SHARED_LIBS "Build shared library" ON) +option(BUILD_STATIC_LIBS "Build static library" ON) +option(GLM_TEST_ENABLE_CXX_98 "Enable C++ 98" OFF) +option(GLM_TEST_ENABLE_CXX_11 "Enable C++ 11" OFF) +option(GLM_TEST_ENABLE_CXX_14 "Enable C++ 14" OFF) +option(GLM_TEST_ENABLE_CXX_17 "Enable C++ 17" OFF) +option(GLM_TEST_ENABLE_CXX_20 "Enable C++ 20" OFF) + +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if(GLM_TEST_ENABLE_CXX_20) + set(CMAKE_CXX_STANDARD 20) + add_definitions(-DGLM_FORCE_CXX2A) + if(NOT GLM_QUIET) + message(STATUS "GLM: Build with C++20 features") + endif() + +elseif(GLM_TEST_ENABLE_CXX_17) + set(CMAKE_CXX_STANDARD 17) + add_definitions(-DGLM_FORCE_CXX17) + if(NOT GLM_QUIET) + message(STATUS "GLM: Build with C++17 features") + endif() + +elseif(GLM_TEST_ENABLE_CXX_14) + set(CMAKE_CXX_STANDARD 14) + add_definitions(-DGLM_FORCE_CXX14) + if(NOT GLM_QUIET) + message(STATUS "GLM: Build with C++14 features") + endif() + +elseif(GLM_TEST_ENABLE_CXX_11) + set(CMAKE_CXX_STANDARD 11) + add_definitions(-DGLM_FORCE_CXX11) + if(NOT GLM_QUIET) + message(STATUS "GLM: Build with C++11 features") + endif() + +elseif(GLM_TEST_ENABLE_CXX_98) + set(CMAKE_CXX_STANDARD 98) + add_definitions(-DGLM_FORCE_CXX98) + if(NOT GLM_QUIET) + message(STATUS "GLM: Build with C++98 features") + endif() +endif() + +option(GLM_TEST_ENABLE_LANG_EXTENSIONS "Enable language extensions" OFF) + +option(GLM_DISABLE_AUTO_DETECTION "Enable language extensions" OFF) + +if(GLM_DISABLE_AUTO_DETECTION) + add_definitions(-DGLM_FORCE_PLATFORM_UNKNOWN -DGLM_FORCE_COMPILER_UNKNOWN -DGLM_FORCE_ARCH_UNKNOWN -DGLM_FORCE_CXX_UNKNOWN) +endif() + +if(GLM_TEST_ENABLE_LANG_EXTENSIONS) + set(CMAKE_CXX_EXTENSIONS ON) + if((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "GNU")) + add_compile_options(-fms-extensions) + endif() + message(STATUS "GLM: Build with C++ language extensions") +else() + set(CMAKE_CXX_EXTENSIONS OFF) + if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_compile_options(/Za) + if(MSVC15) + add_compile_options(/permissive-) + endif() + endif() +endif() + +option(GLM_TEST_ENABLE_FAST_MATH "Enable fast math optimizations" OFF) +if(GLM_TEST_ENABLE_FAST_MATH) + if(NOT GLM_QUIET) + message(STATUS "GLM: Build with fast math optimizations") + endif() + + if((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "GNU")) + add_compile_options(-ffast-math) + + elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_compile_options(/fp:fast) + endif() +else() + if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_compile_options(/fp:precise) + endif() +endif() + +option(GLM_TEST_ENABLE "Build unit tests" ON) +option(GLM_TEST_ENABLE_SIMD_SSE2 "Enable SSE2 optimizations" OFF) +option(GLM_TEST_ENABLE_SIMD_SSE3 "Enable SSE3 optimizations" OFF) +option(GLM_TEST_ENABLE_SIMD_SSSE3 "Enable SSSE3 optimizations" OFF) +option(GLM_TEST_ENABLE_SIMD_SSE4_1 "Enable SSE 4.1 optimizations" OFF) +option(GLM_TEST_ENABLE_SIMD_SSE4_2 "Enable SSE 4.2 optimizations" OFF) +option(GLM_TEST_ENABLE_SIMD_AVX "Enable AVX optimizations" OFF) +option(GLM_TEST_ENABLE_SIMD_AVX2 "Enable AVX2 optimizations" OFF) +option(GLM_TEST_FORCE_PURE "Force 'pure' instructions" OFF) + +if(GLM_TEST_FORCE_PURE) + add_definitions(-DGLM_FORCE_PURE) + + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + add_compile_options(-mfpmath=387) + endif() + message(STATUS "GLM: No SIMD instruction set") + +elseif(GLM_TEST_ENABLE_SIMD_AVX2) + add_definitions(-DGLM_FORCE_PURE) + + if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_compile_options(-mavx2) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + add_compile_options(/QxAVX2) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_compile_options(/arch:AVX2) + endif() + message(STATUS "GLM: AVX2 instruction set") + +elseif(GLM_TEST_ENABLE_SIMD_AVX) + add_definitions(-DGLM_FORCE_INTRINSICS) + + if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_compile_options(-mavx) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + add_compile_options(/QxAVX) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + add_compile_options(/arch:AVX) + endif() + message(STATUS "GLM: AVX instruction set") + +elseif(GLM_TEST_ENABLE_SIMD_SSE4_2) + add_definitions(-DGLM_FORCE_INTRINSICS) + + if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_compile_options(-msse4.2) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + add_compile_options(/QxSSE4.2) + elseif((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND NOT CMAKE_CL_64) + add_compile_options(/arch:SSE2) # VC doesn't support SSE4.2 + endif() + message(STATUS "GLM: SSE4.2 instruction set") + +elseif(GLM_TEST_ENABLE_SIMD_SSE4_1) + add_definitions(-DGLM_FORCE_INTRINSICS) + + if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_compile_options(-msse4.1) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + add_compile_options(/QxSSE4.1) + elseif((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND NOT CMAKE_CL_64) + add_compile_options(/arch:SSE2) # VC doesn't support SSE4.1 + endif() + message(STATUS "GLM: SSE4.1 instruction set") + +elseif(GLM_TEST_ENABLE_SIMD_SSSE3) + add_definitions(-DGLM_FORCE_INTRINSICS) + + if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_compile_options(-mssse3) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + add_compile_options(/QxSSSE3) + elseif((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND NOT CMAKE_CL_64) + add_compile_options(/arch:SSE2) # VC doesn't support SSSE3 + endif() + message(STATUS "GLM: SSSE3 instruction set") + +elseif(GLM_TEST_ENABLE_SIMD_SSE3) + add_definitions(-DGLM_FORCE_INTRINSICS) + + if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_compile_options(-msse3) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + add_compile_options(/QxSSE3) + elseif((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND NOT CMAKE_CL_64) + add_compile_options(/arch:SSE2) # VC doesn't support SSE3 + endif() + message(STATUS "GLM: SSE3 instruction set") + +elseif(GLM_TEST_ENABLE_SIMD_SSE2) + add_definitions(-DGLM_FORCE_INTRINSICS) + + if((CMAKE_CXX_COMPILER_ID MATCHES "GNU") OR (CMAKE_CXX_COMPILER_ID MATCHES "Clang")) + add_compile_options(-msse2) + elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + add_compile_options(/QxSSE2) + elseif((CMAKE_CXX_COMPILER_ID MATCHES "MSVC") AND NOT CMAKE_CL_64) + add_compile_options(/arch:SSE2) + endif() + message(STATUS "GLM: SSE2 instruction set") +endif() + +# Compiler and default options + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + if(NOT GLM_QUIET) + message("GLM: Clang - ${CMAKE_CXX_COMPILER_ID} compiler") + endif() + + add_compile_options(-Werror -Weverything) + add_compile_options(-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++11-long-long -Wno-padded -Wno-gnu-anonymous-struct -Wno-nested-anon-types) + add_compile_options(-Wno-undefined-reinterpret-cast -Wno-sign-conversion -Wno-unused-variable -Wno-missing-prototypes -Wno-unreachable-code -Wno-missing-variable-declarations -Wno-sign-compare -Wno-global-constructors -Wno-unused-macros -Wno-format-nonliteral) + +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + if(NOT GLM_QUIET) + message("GLM: GCC - ${CMAKE_CXX_COMPILER_ID} compiler") + endif() + + add_compile_options(-O2) + add_compile_options(-Wno-long-long) + +elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") + if(NOT GLM_QUIET) + message("GLM: Intel - ${CMAKE_CXX_COMPILER_ID} compiler") + endif() + +elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + if(NOT GLM_QUIET) + message("GLM: Visual C++ - ${CMAKE_CXX_COMPILER_ID} compiler") + endif() + + add_compile_options(/W4 /WX) + add_compile_options(/wd4309 /wd4324 /wd4389 /wd4127 /wd4267 /wd4146 /wd4201 /wd4464 /wd4514 /wd4701 /wd4820 /wd4365) + add_definitions(-D_CRT_SECURE_NO_WARNINGS) +endif() + +function(glmCreateTestGTC NAME) + set(SAMPLE_NAME test-${NAME}) + add_executable(${SAMPLE_NAME} ${NAME}.cpp) + + add_test( + NAME ${SAMPLE_NAME} + COMMAND $ ) + target_link_libraries(${SAMPLE_NAME} PRIVATE glm::glm) +endfunction() + +if(GLM_TEST_ENABLE) + add_subdirectory(bug) + add_subdirectory(core) + add_subdirectory(ext) + add_subdirectory(gtc) + add_subdirectory(gtx) + add_subdirectory(perf) +endif() + + diff --git a/vendor/glm/test/bug/CMakeLists.txt b/vendor/glm/test/bug/CMakeLists.txt new file mode 100644 index 0000000..26e8569 --- /dev/null +++ b/vendor/glm/test/bug/CMakeLists.txt @@ -0,0 +1 @@ +glmCreateTestGTC(bug_ms_vec_static) diff --git a/vendor/glm/test/bug/bug_ms_vec_static.cpp b/vendor/glm/test/bug/bug_ms_vec_static.cpp new file mode 100644 index 0000000..7f44e40 --- /dev/null +++ b/vendor/glm/test/bug/bug_ms_vec_static.cpp @@ -0,0 +1,31 @@ +#include + +#if GLM_CONFIG_ANONYMOUS_STRUCT == GLM_ENABLE +struct vec2; + +struct _swizzle +{ + char _buffer[1]; +}; + +struct vec2 +{ + GLM_CONSTEXPR vec2() : + x(0), y(0) + {} + + union + { + struct { float x, y; }; + struct { _swizzle xx; }; + }; +}; +#endif + +// Visual C++ has a bug generating the error: fatal error C1001: An internal error has occurred in the compiler. +// vec2 Bar; + +int main() +{ + return 0; +} diff --git a/vendor/glm/test/cmake/CMakeLists.txt b/vendor/glm/test/cmake/CMakeLists.txt new file mode 100644 index 0000000..5bc11ef --- /dev/null +++ b/vendor/glm/test/cmake/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.2 FATAL_ERROR) +project(test_find_glm) + +find_package(glm REQUIRED) + +add_executable(test_find_glm test_find_glm.cpp) +target_link_libraries(test_find_glm glm::glm) + diff --git a/vendor/glm/test/cmake/test_find_glm.cpp b/vendor/glm/test/cmake/test_find_glm.cpp new file mode 100644 index 0000000..361b977 --- /dev/null +++ b/vendor/glm/test/cmake/test_find_glm.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +glm::mat4 camera(float Translate, glm::vec2 const& Rotate) +{ + glm::mat4 Projection = glm::perspective(glm::pi() * 0.25f, 4.0f / 3.0f, 0.1f, 100.f); + glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate)); + View = glm::rotate(View, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f)); + View = glm::rotate(View, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f)); + glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); + return Projection * View * Model; +} + +int main() +{ + const glm::mat4 m = camera(1.f, glm::vec2(1.f, 0.5f)); + std::cout << "matrix diagonal: " << m[0][0] << ", " + << m[1][1] << ", " << m[2][2] << ", " << m[3][3] << "\n"; + return 0; +} + diff --git a/vendor/glm/test/core/CMakeLists.txt b/vendor/glm/test/core/CMakeLists.txt new file mode 100644 index 0000000..b8dd968 --- /dev/null +++ b/vendor/glm/test/core/CMakeLists.txt @@ -0,0 +1,52 @@ +glmCreateTestGTC(core_cpp_constexpr) +glmCreateTestGTC(core_cpp_defaulted_ctor) +glmCreateTestGTC(core_force_aligned_gentypes) +glmCreateTestGTC(core_force_ctor_init) +glmCreateTestGTC(core_force_cxx03) +glmCreateTestGTC(core_force_cxx98) +glmCreateTestGTC(core_force_arch_unknown) +glmCreateTestGTC(core_force_compiler_unknown) +glmCreateTestGTC(core_force_cxx_unknown) +glmCreateTestGTC(core_force_explicit_ctor) +glmCreateTestGTC(core_force_inline) +glmCreateTestGTC(core_force_platform_unknown) +glmCreateTestGTC(core_force_pure) +glmCreateTestGTC(core_force_unrestricted_gentype) +glmCreateTestGTC(core_force_xyzw_only) +glmCreateTestGTC(core_force_quat_wxyz) +glmCreateTestGTC(core_type_aligned) +glmCreateTestGTC(core_type_cast) +glmCreateTestGTC(core_type_ctor) +glmCreateTestGTC(core_type_int) +glmCreateTestGTC(core_type_length) +glmCreateTestGTC(core_type_mat2x2) +glmCreateTestGTC(core_type_mat2x3) +glmCreateTestGTC(core_type_mat2x4) +glmCreateTestGTC(core_type_mat3x2) +glmCreateTestGTC(core_type_mat3x3) +glmCreateTestGTC(core_type_mat3x4) +glmCreateTestGTC(core_type_mat4x2) +glmCreateTestGTC(core_type_mat4x3) +glmCreateTestGTC(core_type_mat4x4) +glmCreateTestGTC(core_type_vec1) +glmCreateTestGTC(core_type_vec2) +glmCreateTestGTC(core_type_vec3) +glmCreateTestGTC(core_type_vec4) +glmCreateTestGTC(core_func_common) +glmCreateTestGTC(core_func_exponential) +glmCreateTestGTC(core_func_geometric) +glmCreateTestGTC(core_func_integer) +glmCreateTestGTC(core_func_integer_bit_count) +glmCreateTestGTC(core_func_integer_find_lsb) +glmCreateTestGTC(core_func_integer_find_msb) +glmCreateTestGTC(core_func_matrix) +glmCreateTestGTC(core_func_noise) +glmCreateTestGTC(core_func_packing) +glmCreateTestGTC(core_func_trigonometric) +glmCreateTestGTC(core_func_vector_relational) +glmCreateTestGTC(core_func_swizzle) +glmCreateTestGTC(core_setup_force_cxx98) +glmCreateTestGTC(core_setup_force_size_t_length) +glmCreateTestGTC(core_setup_message) +glmCreateTestGTC(core_setup_platform_unknown) +glmCreateTestGTC(core_setup_precision) diff --git a/vendor/glm/test/core/core_cpp_constexpr.cpp b/vendor/glm/test/core/core_cpp_constexpr.cpp new file mode 100644 index 0000000..3dc0a92 --- /dev/null +++ b/vendor/glm/test/core/core_cpp_constexpr.cpp @@ -0,0 +1,750 @@ +#include + +#if GLM_CONFIG_CONSTEXP == GLM_ENABLE + +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_vec1() +{ + int Error = 0; + + { + constexpr glm::bvec1 B(true); + constexpr bool A = glm::all(B); + static_assert(A, "GLM: Failed constexpr"); + + constexpr glm::bvec1 D(true); + constexpr bool C = glm::any(D); + static_assert(C, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec2 C(true); + constexpr glm::bvec2 B(true); + static_assert(glm::any(glm::equal(C, B)), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 O(glm::ivec1(1)); + static_assert(glm::ivec1(1) == O, "GLM: Failed constexpr"); + + constexpr glm::ivec1 P(1); + static_assert(glm::ivec1(1) == P, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 L(glm::ivec2(1, 2)); + static_assert(glm::ivec1(1) == L, "GLM: Failed constexpr"); + + constexpr glm::ivec1 M(glm::ivec3(1, 2, 3)); + static_assert(glm::ivec1(1) == M, "GLM: Failed constexpr"); + + constexpr glm::ivec1 N(glm::ivec4(1, 2, 3, 4)); + static_assert(glm::ivec1(1) == N, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(1); + static_assert(A[0] == 1, "GLM: Failed constexpr"); + static_assert(glm::vec1(1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec1::length() == 1, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec1 A1(true); + constexpr glm::bvec1 A2(true); + constexpr glm::bvec1 B1(false); + constexpr glm::bvec1 B2(false); + static_assert(A1 == A2 && B1 == B2, "GLM: Failed constexpr"); + static_assert(A1 == A2 || B1 == B2, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(1); + constexpr glm::ivec1 B = A + 1; + constexpr glm::ivec1 C(3); + static_assert(A + B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec1 D = +A; + static_assert(D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(3); + constexpr glm::ivec1 B = A - 1; + constexpr glm::ivec1 C(1); + static_assert(A - B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec1 D = -A; + static_assert(-D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(3); + constexpr glm::ivec1 B = A * 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B * C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(3); + constexpr glm::ivec1 B = A / 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B / C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(3); + constexpr glm::ivec1 B = A % 2; + constexpr glm::ivec1 C(1); + static_assert(B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec1 D(2); + static_assert(A % D == C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(1); + constexpr glm::ivec1 B = A & 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A & C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(1); + constexpr glm::ivec1 B = A | 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A | C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(1); + constexpr glm::ivec1 B = A ^ 0; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(0); + static_assert(A == (A ^ C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(1); + constexpr glm::ivec1 B = A << 1; + static_assert(B == glm::ivec1(2), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == (A << C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(2); + constexpr glm::ivec1 B = A >> 1; + static_assert(B == glm::ivec1(1), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == A >> C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec1 A(~0); + constexpr glm::ivec1 B = ~A; + static_assert(A == ~B, "GLM: Failed constexpr"); + } + + return Error; +} + +static int test_vec2() +{ + int Error = 0; + + { + constexpr glm::bvec2 B(true); + constexpr bool A = glm::all(B); + static_assert(A, "GLM: Failed constexpr"); + + constexpr glm::bvec2 D(true, false); + constexpr bool C = glm::any(D); + static_assert(C, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec2 C(true); + constexpr glm::bvec2 B(true, false); + static_assert(glm::any(glm::equal(C, B)), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 O(glm::ivec1(1)); + static_assert(glm::ivec2(1) == O, "GLM: Failed constexpr"); + + constexpr glm::ivec2 A(1); + static_assert(glm::ivec2(1) == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 F(glm::ivec1(1), glm::ivec1(2)); + static_assert(glm::ivec2(1, 2) == F, "GLM: Failed constexpr"); + + constexpr glm::ivec2 G(1, glm::ivec1(2)); + static_assert(glm::ivec2(1, 2) == G, "GLM: Failed constexpr"); + + constexpr glm::ivec2 H(glm::ivec1(1), 2); + static_assert(glm::ivec2(1, 2) == H, "GLM: Failed constexpr"); + + constexpr glm::ivec2 I(1, 2); + static_assert(glm::ivec2(1, 2) == I, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 L(glm::ivec2(1, 2)); + static_assert(glm::ivec2(1, 2) == L, "GLM: Failed constexpr"); + + constexpr glm::ivec2 M(glm::ivec3(1, 2, 3)); + static_assert(glm::ivec2(1, 2) == M, "GLM: Failed constexpr"); + + constexpr glm::ivec2 N(glm::ivec4(1, 2, 3, 4)); + static_assert(glm::ivec2(1, 2) == N, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(1); + static_assert(A[0] == 1, "GLM: Failed constexpr"); + static_assert(glm::vec2(1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec2(1.0f, -1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec2(1.0f, -1.0f).y < 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec2::length() == 2, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec2 A1(true); + constexpr glm::bvec2 A2(true); + constexpr glm::bvec2 B1(false); + constexpr glm::bvec2 B2(false); + static_assert(A1 == A2 && B1 == B2, "GLM: Failed constexpr"); + static_assert(A1 == A2 || B1 == B2, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(1); + constexpr glm::ivec2 B = A + 1; + constexpr glm::ivec2 C(3); + static_assert(A + B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec2 D = +A; + static_assert(D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(3); + constexpr glm::ivec2 B = A - 1; + constexpr glm::ivec2 C(1); + static_assert(A - B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec2 D = -A; + static_assert(-D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(3); + constexpr glm::ivec2 B = A * 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec2 C(1); + static_assert(B * C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(3); + constexpr glm::ivec2 B = A / 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec2 C(1); + static_assert(B / C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(3); + constexpr glm::ivec2 B = A % 2; + constexpr glm::ivec2 C(1); + static_assert(B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec1 D(2); + static_assert(A % D == C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(1); + constexpr glm::ivec2 B = A & 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A & C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(1); + constexpr glm::ivec2 B = A | 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A | C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(1); + constexpr glm::ivec2 B = A ^ 0; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(0); + static_assert(A == (A ^ C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(1); + constexpr glm::ivec2 B = A << 1; + static_assert(B == glm::ivec2(2), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == (A << C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(2); + constexpr glm::ivec2 B = A >> 1; + static_assert(B == glm::ivec2(1), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == A >> C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec2 A(~0); + constexpr glm::ivec2 B = ~A; + static_assert(A == ~B, "GLM: Failed constexpr"); + } + + return Error; +} + +static int test_vec3() +{ + int Error = 0; + + { + constexpr glm::bvec3 B(true); + constexpr bool A = glm::all(B); + static_assert(A, "GLM: Failed constexpr"); + + constexpr glm::bvec3 D(true, false, true); + constexpr bool C = glm::any(D); + static_assert(C, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec3 C(true); + constexpr glm::bvec3 B(true, false, true); + static_assert(glm::any(glm::equal(C, B)), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 O(glm::ivec1(1)); + static_assert(glm::ivec3(1) == O, "GLM: Failed constexpr"); + + constexpr glm::ivec3 A(1); + static_assert(glm::ivec3(1) == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 B(glm::ivec2(1, 2), 3); + static_assert(glm::ivec3(1, 2, 3) == B, "GLM: Failed constexpr"); + + constexpr glm::ivec3 C(1, glm::ivec2(2, 3)); + static_assert(glm::ivec3(1, 2, 3) == C, "GLM: Failed constexpr"); + + constexpr glm::ivec3 D(glm::ivec1(1), glm::ivec2(2, 3)); + static_assert(glm::ivec3(1, 2, 3) == D, "GLM: Failed constexpr"); + + constexpr glm::ivec3 E(glm::ivec2(1, 2), glm::ivec1(3)); + static_assert(glm::ivec3(1, 2, 3) == E, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 F(glm::ivec1(1), glm::ivec1(2), glm::ivec1(3)); + static_assert(glm::ivec3(1, 2, 3) == F, "GLM: Failed constexpr"); + + constexpr glm::ivec3 G(1, glm::ivec1(2), glm::ivec1(3)); + static_assert(glm::ivec3(1, 2, 3) == G, "GLM: Failed constexpr"); + + constexpr glm::ivec3 H(glm::ivec1(1), 2, glm::ivec1(3)); + static_assert(glm::ivec3(1, 2, 3) == H, "GLM: Failed constexpr"); + + constexpr glm::ivec3 I(1, 2, glm::ivec1(3)); + static_assert(glm::ivec3(1, 2, 3) == I, "GLM: Failed constexpr"); + + constexpr glm::ivec3 J(glm::ivec1(1), glm::ivec1(2), 3); + static_assert(glm::ivec3(1, 2, 3) == J, "GLM: Failed constexpr"); + + constexpr glm::ivec3 K(1, glm::ivec1(2), 3); + static_assert(glm::ivec3(1, 2, 3) == K, "GLM: Failed constexpr"); + + constexpr glm::ivec3 L(glm::ivec1(1), 2, 3); + static_assert(glm::ivec3(1, 2, 3) == L, "GLM: Failed constexpr"); + + constexpr glm::ivec3 M(1, 2, 3); + static_assert(glm::ivec3(1, 2, 3) == M, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 N(glm::ivec4(1, 2, 3, 4)); + static_assert(glm::ivec3(1, 2, 3) == N, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 const A(1); + static_assert(A[0] == 1, "GLM: Failed constexpr"); + static_assert(glm::vec3(1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec3(1.0f, -1.0f, -1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec3(1.0f, -1.0f, -1.0f).y < 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec3::length() == 3, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec3 A1(true); + constexpr glm::bvec3 A2(true); + constexpr glm::bvec3 B1(false); + constexpr glm::bvec3 B2(false); + static_assert(A1 == A2 && B1 == B2, "GLM: Failed constexpr"); + static_assert(A1 == A2 || B1 == B2, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(1); + constexpr glm::ivec3 B = A + 1; + constexpr glm::ivec3 C(3); + static_assert(A + B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec3 D = +A; + static_assert(D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(3); + constexpr glm::ivec3 B = A - 1; + constexpr glm::ivec3 C(1); + static_assert(A - B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec3 D = -A; + static_assert(-D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(3); + constexpr glm::ivec3 B = A * 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec3 C(1); + static_assert(B * C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(3); + constexpr glm::ivec3 B = A / 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec3 C(1); + static_assert(B / C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(3); + constexpr glm::ivec3 B = A % 2; + constexpr glm::ivec3 C(1); + static_assert(B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec1 D(2); + static_assert(A % D == C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(1); + constexpr glm::ivec3 B = A & 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A & C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(1); + constexpr glm::ivec3 B = A | 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A | C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(1); + constexpr glm::ivec3 B = A ^ 0; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(0); + static_assert(A == (A ^ C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(1); + constexpr glm::ivec3 B = A << 1; + static_assert(B == glm::ivec3(2), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == (A << C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(2); + constexpr glm::ivec3 B = A >> 1; + static_assert(B == glm::ivec3(1), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == A >> C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec3 A(~0); + constexpr glm::ivec3 B = ~A; + static_assert(A == ~B, "GLM: Failed constexpr"); + } + + return Error; +} + +static int test_vec4() +{ + int Error = 0; + + { + constexpr glm::bvec4 B(true); + constexpr bool A = glm::all(B); + static_assert(A, "GLM: Failed constexpr"); + + constexpr glm::bvec4 D(true, false, true, false); + constexpr bool C = glm::any(D); + static_assert(C, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec4 C(true); + constexpr glm::bvec4 B(true, false, true, false); + static_assert(glm::any(glm::equal(C, B)), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 O(glm::ivec4(1)); + static_assert(glm::ivec4(1) == O, "GLM: Failed constexpr"); + + constexpr glm::ivec4 A(1); + static_assert(glm::ivec4(1) == A, "GLM: Failed constexpr"); + + constexpr glm::ivec4 N(glm::ivec4(1, 2, 3, 4)); + static_assert(glm::ivec4(1, 2, 3, 4) == N, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(glm::ivec3(1, 2, 3), 4); + static_assert(glm::ivec4(1, 2, 3, 4) == A, "GLM: Failed constexpr"); + + constexpr glm::ivec4 B(glm::ivec2(1, 2), glm::ivec2(3, 4)); + static_assert(glm::ivec4(1, 2, 3, 4) == B, "GLM: Failed constexpr"); + + constexpr glm::ivec4 C(1, glm::ivec3(2, 3, 4)); + static_assert(glm::ivec4(1, 2, 3, 4) == C, "GLM: Failed constexpr"); + + constexpr glm::ivec4 D(glm::ivec1(1), glm::ivec2(2, 3), glm::ivec1(4)); + static_assert(glm::ivec4(1, 2, 3, 4) == D, "GLM: Failed constexpr"); + + constexpr glm::ivec4 E(glm::ivec2(1, 2), glm::ivec1(3), glm::ivec1(4)); + static_assert(glm::ivec4(1, 2, 3, 4) == E, "GLM: Failed constexpr"); + + constexpr glm::ivec4 F(glm::ivec1(1), glm::ivec1(2), glm::ivec2(3, 4)); + static_assert(glm::ivec4(1, 2, 3, 4) == F, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(1); + static_assert(A[0] == 1, "GLM: Failed constexpr"); + static_assert(glm::ivec4(1).x > 0, "GLM: Failed constexpr"); + static_assert(glm::ivec4(1.0f, -1.0f, -1.0f, 1.0f).x > 0, "GLM: Failed constexpr"); + static_assert(glm::ivec4(1.0f, -1.0f, -1.0f, 1.0f).y < 0, "GLM: Failed constexpr"); + static_assert(glm::ivec4::length() == 4, "GLM: Failed constexpr"); + } + + { + constexpr glm::bvec4 A1(true); + constexpr glm::bvec4 A2(true); + constexpr glm::bvec4 B1(false); + constexpr glm::bvec4 B2(false); + static_assert(A1 == A2 && B1 == B2, "GLM: Failed constexpr"); + static_assert(A1 == A2 || B1 == B2, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(1); + constexpr glm::ivec4 B = A + 1; + constexpr glm::ivec4 C(3); + static_assert(A + B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec4 D = +A; + static_assert(D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(3); + constexpr glm::ivec4 B = A - 1; + constexpr glm::ivec4 C(1); + static_assert(A - B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec4 D = -A; + static_assert(-D == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(3); + constexpr glm::ivec4 B = A * 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec4 C(1); + static_assert(B * C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(3); + constexpr glm::ivec4 B = A / 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec4 C(1); + static_assert(B / C == A, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(3); + constexpr glm::ivec4 B = A % 2; + constexpr glm::ivec4 C(1); + static_assert(B == C, "GLM: Failed constexpr"); + + constexpr glm::ivec1 D(2); + static_assert(A % D == C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(1); + constexpr glm::ivec4 B = A & 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A & C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(1); + constexpr glm::ivec4 B = A | 1; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(A == (A | C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(1); + constexpr glm::ivec4 B = A ^ 0; + static_assert(A == B, "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(0); + static_assert(A == (A ^ C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(1); + constexpr glm::ivec4 B = A << 1; + static_assert(B == glm::ivec4(2), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == (A << C), "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(2); + constexpr glm::ivec4 B = A >> 1; + static_assert(B == glm::ivec4(1), "GLM: Failed constexpr"); + + constexpr glm::ivec1 C(1); + static_assert(B == A >> C, "GLM: Failed constexpr"); + } + + { + constexpr glm::ivec4 A(~0); + constexpr glm::ivec4 B = ~A; + static_assert(A == ~B, "GLM: Failed constexpr"); + } + + return Error; +} + +static int test_quat() +{ + int Error = 0; + + { + static_assert(glm::quat::length() == 4, "GLM: Failed constexpr"); + static_assert(glm::quat(1.0f, glm::vec3(0.0f)).w > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::quat(1.0f, 0.0f, 0.0f, 0.0f).w > 0.0f, "GLM: Failed constexpr"); + + glm::quat constexpr Q = glm::identity(); + static_assert(Q.x - glm::quat(1.0f, glm::vec3(0.0f)).x <= glm::epsilon(), "GLM: Failed constexpr"); + } + + return Error; +} + +static int test_mat2x2() +{ + int Error = 0; + + static_assert(glm::mat2x2::length() == 2, "GLM: Failed constexpr"); + + return Error; +} + +#endif//GLM_CONFIG_CONSTEXP == GLM_ENABLE + +int main() +{ + int Error = 0; + +# if GLM_CONFIG_CONSTEXP == GLM_ENABLE + Error += test_vec1(); + Error += test_vec2(); + Error += test_vec3(); + Error += test_vec4(); + Error += test_quat(); + Error += test_mat2x2(); +# endif//GLM_CONFIG_CONSTEXP == GLM_ENABLE + + return Error; +} + diff --git a/vendor/glm/test/core/core_cpp_defaulted_ctor.cpp b/vendor/glm/test/core/core_cpp_defaulted_ctor.cpp new file mode 100644 index 0000000..07afd9c --- /dev/null +++ b/vendor/glm/test/core/core_cpp_defaulted_ctor.cpp @@ -0,0 +1,145 @@ +#include + +#if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + +#include +#include +#include +#include +#include +#include + +static int test_vec_memcpy() +{ + int Error = 0; + + { + glm::ivec1 const A = glm::ivec1(76); + glm::ivec1 B; + std::memcpy(&B, &A, sizeof(glm::ivec1)); + Error += B == A ? 0 : 1; + } + + { + glm::ivec2 const A = glm::ivec2(76); + glm::ivec2 B; + std::memcpy(&B, &A, sizeof(glm::ivec2)); + Error += B == A ? 0 : 1; + } + + { + glm::ivec3 const A = glm::ivec3(76); + glm::ivec3 B; + std::memcpy(&B, &A, sizeof(glm::ivec3)); + Error += B == A ? 0 : 1; + } + + { + glm::ivec4 const A = glm::ivec4(76); + glm::ivec4 B; + std::memcpy(&B, &A, sizeof(glm::ivec4)); + Error += B == A ? 0 : 1; + } + + return Error; +} + +static int test_mat_memcpy() +{ + int Error = 0; + + { + glm::mat2x2 const A = glm::mat2x2(76); + glm::mat2x2 B; + std::memcpy(&B, &A, sizeof(glm::mat2x2)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat2x3 const A = glm::mat2x3(76); + glm::mat2x3 B; + std::memcpy(&B, &A, sizeof(glm::mat2x3)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat2x4 const A = glm::mat2x4(76); + glm::mat2x4 B; + std::memcpy(&B, &A, sizeof(glm::mat2x4)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat3x2 const A = glm::mat3x2(76); + glm::mat3x2 B; + std::memcpy(&B, &A, sizeof(glm::mat3x2)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat3x3 const A = glm::mat3x3(76); + glm::mat3x3 B; + std::memcpy(&B, &A, sizeof(glm::mat3x3)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat3x4 const A = glm::mat3x4(76); + glm::mat3x4 B; + std::memcpy(&B, &A, sizeof(glm::mat3x4)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat4x2 const A = glm::mat4x2(76); + glm::mat4x2 B; + std::memcpy(&B, &A, sizeof(glm::mat4x2)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat4x3 const A = glm::mat4x3(76); + glm::mat4x3 B; + std::memcpy(&B, &A, sizeof(glm::mat4x3)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + { + glm::mat4x4 const A = glm::mat4x4(76); + glm::mat4x4 B; + std::memcpy(&B, &A, sizeof(glm::mat4x4)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +static int test_quat_memcpy() +{ + int Error = 0; + + { + glm::quat const A = glm::quat(1, 0, 0, 0); + glm::quat B; + std::memcpy(&B, &A, sizeof(glm::quat)); + Error += glm::all(glm::equal(B, A, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +#endif//GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + +int main() +{ + int Error = 0; + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + Error += test_vec_memcpy(); + Error += test_mat_memcpy(); + Error += test_quat_memcpy(); +# endif//GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_aligned_gentypes.cpp b/vendor/glm/test/core/core_force_aligned_gentypes.cpp new file mode 100644 index 0000000..70713c4 --- /dev/null +++ b/vendor/glm/test/core/core_force_aligned_gentypes.cpp @@ -0,0 +1,10 @@ +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_arch_unknown.cpp b/vendor/glm/test/core/core_force_arch_unknown.cpp new file mode 100644 index 0000000..45b51bf --- /dev/null +++ b/vendor/glm/test/core/core_force_arch_unknown.cpp @@ -0,0 +1,14 @@ +#ifndef GLM_FORCE_ARCH_UNKNOWN +# define GLM_FORCE_ARCH_UNKNOWN +#endif + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_compiler_unknown.cpp b/vendor/glm/test/core/core_force_compiler_unknown.cpp new file mode 100644 index 0000000..44d7fc3 --- /dev/null +++ b/vendor/glm/test/core/core_force_compiler_unknown.cpp @@ -0,0 +1,14 @@ +#ifndef GLM_FORCE_COMPILER_UNKNOWN +# define GLM_FORCE_COMPILER_UNKNOWN +#endif + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_ctor_init.cpp b/vendor/glm/test/core/core_force_ctor_init.cpp new file mode 100644 index 0000000..298b7ed --- /dev/null +++ b/vendor/glm/test/core/core_force_ctor_init.cpp @@ -0,0 +1,139 @@ +#define GLM_FORCE_CTOR_INIT + +#include +#include + +static int test_vec() +{ + int Error = 0; + + glm::vec1 V1; + Error += glm::all(glm::equal(V1, glm::vec1(0), glm::epsilon())) ? 0 : 1; + + glm::dvec1 U1; + Error += glm::all(glm::equal(U1, glm::dvec1(0), glm::epsilon())) ? 0 : 1; + + glm::vec2 V2; + Error += glm::all(glm::equal(V2, glm::vec2(0, 0), glm::epsilon())) ? 0 : 1; + + glm::dvec2 U2; + Error += glm::all(glm::equal(U2, glm::dvec2(0, 0), glm::epsilon())) ? 0 : 1; + + glm::vec3 V3; + Error += glm::all(glm::equal(V3, glm::vec3(0, 0, 0), glm::epsilon())) ? 0 : 1; + + glm::dvec3 U3; + Error += glm::all(glm::equal(U3, glm::dvec3(0, 0, 0), glm::epsilon())) ? 0 : 1; + + glm::vec4 V4; + Error += glm::all(glm::equal(V4, glm::vec4(0, 0, 0, 0), glm::epsilon())) ? 0 : 1; + + glm::dvec4 U4; + Error += glm::all(glm::equal(U4, glm::dvec4(0, 0, 0, 0), glm::epsilon())) ? 0 : 1; + + return Error; +} + +static int test_mat() +{ + int Error = 0; + + { + glm::mat2x2 F; + Error += glm::all(glm::equal(F, glm::mat2x2(1), glm::epsilon())) ? 0 : 1; + + glm::dmat2x2 D; + Error += glm::all(glm::equal(D, glm::dmat2x2(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat2x3 F; + Error += glm::all(glm::equal(F, glm::mat2x3(1), glm::epsilon())) ? 0 : 1; + + glm::dmat2x3 D; + Error += glm::all(glm::equal(D, glm::dmat2x3(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat2x4 F; + Error += glm::all(glm::equal(F, glm::mat2x4(1), glm::epsilon())) ? 0 : 1; + + glm::dmat2x4 D; + Error += glm::all(glm::equal(D, glm::dmat2x4(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat3x2 F; + Error += glm::all(glm::equal(F, glm::mat3x2(1), glm::epsilon())) ? 0 : 1; + + glm::dmat3x2 D; + Error += glm::all(glm::equal(D, glm::dmat3x2(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat3x3 F; + Error += glm::all(glm::equal(F, glm::mat3x3(1), glm::epsilon())) ? 0 : 1; + + glm::dmat3x3 D; + Error += glm::all(glm::equal(D, glm::dmat3x3(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat3x4 F; + Error += glm::all(glm::equal(F, glm::mat3x4(1), glm::epsilon())) ? 0 : 1; + + glm::dmat3x4 D; + Error += glm::all(glm::equal(D, glm::dmat3x4(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat4x2 F; + Error += glm::all(glm::equal(F, glm::mat4x2(1), glm::epsilon())) ? 0 : 1; + + glm::dmat4x2 D; + Error += glm::all(glm::equal(D, glm::dmat4x2(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat4x3 F; + Error += glm::all(glm::equal(F, glm::mat4x3(1), glm::epsilon())) ? 0 : 1; + + glm::dmat4x3 D; + Error += glm::all(glm::equal(D, glm::dmat4x3(1), glm::epsilon())) ? 0 : 1; + } + + { + glm::mat4x4 F; + Error += glm::all(glm::equal(F, glm::mat4x4(1), glm::epsilon())) ? 0 : 1; + + glm::dmat4x4 D; + Error += glm::all(glm::equal(D, glm::dmat4x4(1), glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +static int test_qua() +{ + int Error = 0; + + glm::quat F; + Error += glm::all(glm::equal(F, glm::quat(1, 0, 0, 0), glm::epsilon())) ? 0 : 1; + + glm::dquat D; + Error += glm::all(glm::equal(D, glm::dquat(1, 0, 0, 0), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_vec(); + Error += test_mat(); + Error += test_qua(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_cxx03.cpp b/vendor/glm/test/core/core_force_cxx03.cpp new file mode 100644 index 0000000..fc6e9c5 --- /dev/null +++ b/vendor/glm/test/core/core_force_cxx03.cpp @@ -0,0 +1,14 @@ +#ifndef GLM_FORCE_CXX03 +# define GLM_FORCE_CXX03 +#endif + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_cxx98.cpp b/vendor/glm/test/core/core_force_cxx98.cpp new file mode 100644 index 0000000..42a5c25 --- /dev/null +++ b/vendor/glm/test/core/core_force_cxx98.cpp @@ -0,0 +1,14 @@ +#ifndef GLM_FORCE_CXX98 +# define GLM_FORCE_CXX98 +#endif + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_cxx_unknown.cpp b/vendor/glm/test/core/core_force_cxx_unknown.cpp new file mode 100644 index 0000000..62299d6 --- /dev/null +++ b/vendor/glm/test/core/core_force_cxx_unknown.cpp @@ -0,0 +1,14 @@ +#ifndef GLM_FORCE_CXX_UNKNOWN +# define GLM_FORCE_CXX_UNKNOWN +#endif + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_depth_zero_to_one.cpp b/vendor/glm/test/core/core_force_depth_zero_to_one.cpp new file mode 100644 index 0000000..23b3615 --- /dev/null +++ b/vendor/glm/test/core/core_force_depth_zero_to_one.cpp @@ -0,0 +1,12 @@ +#define GLM_FORCE_DEPTH_ZERO_TO_ONE + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_explicit_ctor.cpp b/vendor/glm/test/core/core_force_explicit_ctor.cpp new file mode 100644 index 0000000..7af5b79 --- /dev/null +++ b/vendor/glm/test/core/core_force_explicit_ctor.cpp @@ -0,0 +1,17 @@ +#define GLM_FORCE_EXPLICIT_CTOR + +#include +#include + +int main() +{ + int Error = 0; + + glm::ivec4 B(1); + Error += B == glm::ivec4(1) ? 0 : 1; + + //glm::vec4 A = B; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_inline.cpp b/vendor/glm/test/core/core_force_inline.cpp new file mode 100644 index 0000000..cd23fd9 --- /dev/null +++ b/vendor/glm/test/core/core_force_inline.cpp @@ -0,0 +1,12 @@ +#define GLM_FORCE_INLINE + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_left_handed.cpp b/vendor/glm/test/core/core_force_left_handed.cpp new file mode 100644 index 0000000..b7ec31b --- /dev/null +++ b/vendor/glm/test/core/core_force_left_handed.cpp @@ -0,0 +1,12 @@ +#define GLM_FORCE_LEFT_HANDED + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_platform_unknown.cpp b/vendor/glm/test/core/core_force_platform_unknown.cpp new file mode 100644 index 0000000..fb7fa75 --- /dev/null +++ b/vendor/glm/test/core/core_force_platform_unknown.cpp @@ -0,0 +1,14 @@ +#ifndef GLM_FORCE_PLATFORM_UNKNOWN +# define GLM_FORCE_PLATFORM_UNKNOWN +#endif + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_pure.cpp b/vendor/glm/test/core/core_force_pure.cpp new file mode 100644 index 0000000..a32a4ed --- /dev/null +++ b/vendor/glm/test/core/core_force_pure.cpp @@ -0,0 +1,434 @@ +#ifndef GLM_FORCE_PURE +# define GLM_FORCE_PURE +#endif//GLM_FORCE_PURE +#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +#define GLM_FORCE_SWIZZLE +#include +#include +#include +#include +#include +#include +#include + +static int test_vec4_ctor() +{ + int Error = 0; + + { + glm::ivec4 A(1, 2, 3, 4); + glm::ivec4 B(A); + Error += glm::all(glm::equal(A, B)) ? 0 : 1; + } + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + +#if GLM_HAS_INITIALIZER_LISTS + { + glm::vec4 a{ 0, 1, 2, 3 }; + std::vector v = { + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {8, 9, 0, 1}}; + } + + { + glm::dvec4 a{ 0, 1, 2, 3 }; + std::vector v = { + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {8, 9, 0, 1}}; + } +#endif + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::ivec4 A = glm::vec4(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = A.xyzw; + glm::ivec4 C(A.xyzw); + glm::ivec4 D(A.xyzw()); + glm::ivec4 E(A.x, A.yzw); + glm::ivec4 F(A.x, A.yzw()); + glm::ivec4 G(A.xyz, A.w); + glm::ivec4 H(A.xyz(), A.w); + glm::ivec4 I(A.xy, A.zw); + glm::ivec4 J(A.xy(), A.zw()); + glm::ivec4 K(A.x, A.y, A.zw); + glm::ivec4 L(A.x, A.yz, A.w); + glm::ivec4 M(A.xy, A.z, A.w); + + Error += glm::all(glm::equal(A, B)) ? 0 : 1; + Error += glm::all(glm::equal(A, C)) ? 0 : 1; + Error += glm::all(glm::equal(A, D)) ? 0 : 1; + Error += glm::all(glm::equal(A, E)) ? 0 : 1; + Error += glm::all(glm::equal(A, F)) ? 0 : 1; + Error += glm::all(glm::equal(A, G)) ? 0 : 1; + Error += glm::all(glm::equal(A, H)) ? 0 : 1; + Error += glm::all(glm::equal(A, I)) ? 0 : 1; + Error += glm::all(glm::equal(A, J)) ? 0 : 1; + Error += glm::all(glm::equal(A, K)) ? 0 : 1; + Error += glm::all(glm::equal(A, L)) ? 0 : 1; + Error += glm::all(glm::equal(A, M)) ? 0 : 1; + } +# endif + +# if GLM_CONFIG_SWIZZLE + { + glm::ivec4 A = glm::vec4(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = A.xyzw(); + glm::ivec4 C(A.xyzw()); + glm::ivec4 D(A.xyzw()); + glm::ivec4 E(A.x, A.yzw()); + glm::ivec4 F(A.x, A.yzw()); + glm::ivec4 G(A.xyz(), A.w); + glm::ivec4 H(A.xyz(), A.w); + glm::ivec4 I(A.xy(), A.zw()); + glm::ivec4 J(A.xy(), A.zw()); + glm::ivec4 K(A.x, A.y, A.zw()); + glm::ivec4 L(A.x, A.yz(), A.w); + glm::ivec4 M(A.xy(), A.z, A.w); + + Error += glm::all(glm::equal(A, B)) ? 0 : 1; + Error += glm::all(glm::equal(A, C)) ? 0 : 1; + Error += glm::all(glm::equal(A, D)) ? 0 : 1; + Error += glm::all(glm::equal(A, E)) ? 0 : 1; + Error += glm::all(glm::equal(A, F)) ? 0 : 1; + Error += glm::all(glm::equal(A, G)) ? 0 : 1; + Error += glm::all(glm::equal(A, H)) ? 0 : 1; + Error += glm::all(glm::equal(A, I)) ? 0 : 1; + Error += glm::all(glm::equal(A, J)) ? 0 : 1; + Error += glm::all(glm::equal(A, K)) ? 0 : 1; + Error += glm::all(glm::equal(A, L)) ? 0 : 1; + Error += glm::all(glm::equal(A, M)) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE + + { + glm::ivec4 A(1); + glm::ivec4 B(1, 1, 1, 1); + + Error += A == B ? 0 : 1; + } + + { + std::vector Tests; + Tests.push_back(glm::ivec4(glm::ivec2(1, 2), 3, 4)); + Tests.push_back(glm::ivec4(1, glm::ivec2(2, 3), 4)); + Tests.push_back(glm::ivec4(1, 2, glm::ivec2(3, 4))); + Tests.push_back(glm::ivec4(glm::ivec3(1, 2, 3), 4)); + Tests.push_back(glm::ivec4(1, glm::ivec3(2, 3, 4))); + Tests.push_back(glm::ivec4(glm::ivec2(1, 2), glm::ivec2(3, 4))); + Tests.push_back(glm::ivec4(1, 2, 3, 4)); + Tests.push_back(glm::ivec4(glm::ivec4(1, 2, 3, 4))); + + for(std::size_t i = 0; i < Tests.size(); ++i) + Error += Tests[i] == glm::ivec4(1, 2, 3, 4) ? 0 : 1; + } + + return Error; +} + +static int test_bvec4_ctor() +{ + int Error = 0; + + glm::bvec4 const A(true); + glm::bvec4 const B(true); + glm::bvec4 const C(false); + glm::bvec4 const D = A && B; + glm::bvec4 const E = A && C; + glm::bvec4 const F = A || C; + + Error += D == glm::bvec4(true) ? 0 : 1; + Error += E == glm::bvec4(false) ? 0 : 1; + Error += F == glm::bvec4(true) ? 0 : 1; + + bool const G = A == C; + bool const H = A != C; + + Error += !G ? 0 : 1; + Error += H ? 0 : 1; + + return Error; +} + +static int test_vec4_operators() +{ + int Error = 0; + + { + glm::ivec4 A(1); + glm::ivec4 B(1); + bool R = A != B; + bool S = A == B; + + Error += (S && !R) ? 0 : 1; + } + + { + glm::vec4 const A(1.0f, 2.0f, 3.0f, 4.0f); + glm::vec4 const B(4.0f, 5.0f, 6.0f, 7.0f); + + glm::vec4 const C = A + B; + Error += glm::all(glm::equal(C, glm::vec4(5, 7, 9, 11), 0.001f)) ? 0 : 1; + + glm::vec4 D = B - A; + Error += glm::all(glm::equal(D, glm::vec4(3, 3, 3, 3), 0.001f)) ? 0 : 1; + + glm::vec4 E = A * B; + Error += glm::all(glm::equal(E, glm::vec4(4, 10, 18, 28), 0.001f)) ? 0 : 1; + + glm::vec4 F = B / A; + Error += glm::all(glm::equal(F, glm::vec4(4, 2.5, 2, 7.0f / 4.0f), 0.001f)) ? 0 : 1; + + glm::vec4 G = A + 1.0f; + Error += glm::all(glm::equal(G, glm::vec4(2, 3, 4, 5), 0.001f)) ? 0 : 1; + + glm::vec4 H = B - 1.0f; + Error += glm::all(glm::equal(H, glm::vec4(3, 4, 5, 6), 0.001f)) ? 0 : 1; + + glm::vec4 I = A * 2.0f; + Error += glm::all(glm::equal(I, glm::vec4(2, 4, 6, 8), 0.001f)) ? 0 : 1; + + glm::vec4 J = B / 2.0f; + Error += glm::all(glm::equal(J, glm::vec4(2, 2.5, 3, 3.5), 0.001f)) ? 0 : 1; + + glm::vec4 K = 1.0f + A; + Error += glm::all(glm::equal(K, glm::vec4(2, 3, 4, 5), 0.001f)) ? 0 : 1; + + glm::vec4 L = 1.0f - B; + Error += glm::all(glm::equal(L, glm::vec4(-3, -4, -5, -6), 0.001f)) ? 0 : 1; + + glm::vec4 M = 2.0f * A; + Error += glm::all(glm::equal(M, glm::vec4(2, 4, 6, 8), 0.001f)) ? 0 : 1; + + glm::vec4 const N = 2.0f / B; + Error += glm::all(glm::equal(N, glm::vec4(0.5, 2.0 / 5.0, 2.0 / 6.0, 2.0 / 7.0), 0.0001f)) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B(4.0f, 5.0f, 6.0f, 7.0f); + + A += B; + Error += A == glm::ivec4(5, 7, 9, 11) ? 0 : 1; + + A += 1; + Error += A == glm::ivec4(6, 8, 10, 12) ? 0 : 1; + } + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B(4.0f, 5.0f, 6.0f, 7.0f); + + B -= A; + Error += B == glm::ivec4(3, 3, 3, 3) ? 0 : 1; + + B -= 1; + Error += B == glm::ivec4(2, 2, 2, 2) ? 0 : 1; + } + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B(4.0f, 5.0f, 6.0f, 7.0f); + + A *= B; + Error += A == glm::ivec4(4, 10, 18, 28) ? 0 : 1; + + A *= 2; + Error += A == glm::ivec4(8, 20, 36, 56) ? 0 : 1; + } + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B(4.0f, 4.0f, 6.0f, 8.0f); + + B /= A; + Error += B == glm::ivec4(4, 2, 2, 2) ? 0 : 1; + + B /= 2; + Error += B == glm::ivec4(2, 1, 1, 1) ? 0 : 1; + } + { + glm::ivec4 B(2); + + B /= B.y; + Error += B == glm::ivec4(1) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = -A; + Error += B == glm::ivec4(-1.0f, -2.0f, -3.0f, -4.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = --A; + Error += B == glm::ivec4(0.0f, 1.0f, 2.0f, 3.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = A--; + Error += B == glm::ivec4(1.0f, 2.0f, 3.0f, 4.0f) ? 0 : 1; + Error += A == glm::ivec4(0.0f, 1.0f, 2.0f, 3.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = ++A; + Error += B == glm::ivec4(2.0f, 3.0f, 4.0f, 5.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = A++; + Error += B == glm::ivec4(1.0f, 2.0f, 3.0f, 4.0f) ? 0 : 1; + Error += A == glm::ivec4(2.0f, 3.0f, 4.0f, 5.0f) ? 0 : 1; + } + + return Error; +} + +static int test_vec4_equal() +{ + int Error = 0; + + { + glm::uvec4 const A(1, 2, 3, 4); + glm::uvec4 const B(1, 2, 3, 4); + Error += A == B ? 0 : 1; + Error += A != B ? 1 : 0; + } + + { + glm::ivec4 const A(1, 2, 3, 4); + glm::ivec4 const B(1, 2, 3, 4); + Error += A == B ? 0 : 1; + Error += A != B ? 1 : 0; + } + + return Error; +} + +static int test_vec4_size() +{ + int Error = 0; + + Error += sizeof(glm::vec4) == sizeof(glm::lowp_vec4) ? 0 : 1; + Error += sizeof(glm::vec4) == sizeof(glm::mediump_vec4) ? 0 : 1; + Error += sizeof(glm::vec4) == sizeof(glm::highp_vec4) ? 0 : 1; + Error += 16 == sizeof(glm::mediump_vec4) ? 0 : 1; + Error += sizeof(glm::dvec4) == sizeof(glm::lowp_dvec4) ? 0 : 1; + Error += sizeof(glm::dvec4) == sizeof(glm::mediump_dvec4) ? 0 : 1; + Error += sizeof(glm::dvec4) == sizeof(glm::highp_dvec4) ? 0 : 1; + Error += 32 == sizeof(glm::highp_dvec4) ? 0 : 1; + Error += glm::vec4().length() == 4 ? 0 : 1; + Error += glm::dvec4().length() == 4 ? 0 : 1; + + return Error; +} + +static int test_vec4_swizzle_partial() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + glm::ivec4 A(1, 2, 3, 4); + + { + glm::ivec4 B(A.xy, A.zw); + Error += A == B ? 0 : 1; + } + { + glm::ivec4 B(A.xy, 3, 4); + Error += A == B ? 0 : 1; + } + { + glm::ivec4 B(1, A.yz, 4); + Error += A == B ? 0 : 1; + } + { + glm::ivec4 B(1, 2, A.zw); + Error += A == B ? 0 : 1; + } + + { + glm::ivec4 B(A.xyz, 4); + Error += A == B ? 0 : 1; + } + { + glm::ivec4 B(1, A.yzw); + Error += A == B ? 0 : 1; + } +# endif + + return Error; +} + +static int test_operator_increment() +{ + int Error(0); + + glm::ivec4 v0(1); + glm::ivec4 v1(v0); + glm::ivec4 v2(v0); + glm::ivec4 v3 = ++v1; + glm::ivec4 v4 = v2++; + + Error += glm::all(glm::equal(v0, v4)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v2)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v3)) ? 0 : 1; + + int i0(1); + int i1(i0); + int i2(i0); + int i3 = ++i1; + int i4 = i2++; + + Error += i0 == i4 ? 0 : 1; + Error += i1 == i2 ? 0 : 1; + Error += i1 == i3 ? 0 : 1; + + return Error; +} + +static int test_vec4_simd() +{ + int Error = 0; + + glm::vec4 const a(std::clock(), std::clock(), std::clock(), std::clock()); + glm::vec4 const b(std::clock(), std::clock(), std::clock(), std::clock()); + + glm::vec4 const c(b * a); + glm::vec4 const d(a + c); + + Error += glm::all(glm::greaterThanEqual(d, glm::vec4(0))) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_vec4_ctor(); + Error += test_bvec4_ctor(); + Error += test_vec4_size(); + Error += test_vec4_operators(); + Error += test_vec4_equal(); + Error += test_vec4_swizzle_partial(); + Error += test_vec4_simd(); + Error += test_operator_increment(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_quat_wxyz.cpp b/vendor/glm/test/core/core_force_quat_wxyz.cpp new file mode 100644 index 0000000..bcb5739 --- /dev/null +++ b/vendor/glm/test/core/core_force_quat_wxyz.cpp @@ -0,0 +1,13 @@ +#define GLM_FORCE_QUAT_DATA_WXYZ +#define GLM_FORCE_INLINE + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_size_t_length.cpp b/vendor/glm/test/core/core_force_size_t_length.cpp new file mode 100644 index 0000000..19dac89 --- /dev/null +++ b/vendor/glm/test/core/core_force_size_t_length.cpp @@ -0,0 +1,12 @@ +#define GLM_FORCE_SIZE_T_LENGTH + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_unrestricted_gentype.cpp b/vendor/glm/test/core/core_force_unrestricted_gentype.cpp new file mode 100644 index 0000000..21d6e52 --- /dev/null +++ b/vendor/glm/test/core/core_force_unrestricted_gentype.cpp @@ -0,0 +1,12 @@ +#define GLM_FORCE_UNRESTRICTED_GENTYPE + +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_force_xyzw_only.cpp b/vendor/glm/test/core/core_force_xyzw_only.cpp new file mode 100644 index 0000000..d19509d --- /dev/null +++ b/vendor/glm/test/core/core_force_xyzw_only.cpp @@ -0,0 +1,58 @@ +#define GLM_FORCE_XYZW_ONLY + +#include +#include +#include +#include +#include +#include + +static int test_comp() +{ + int Error = 0; + + { + glm::ivec1 const A(1); + Error += A.x == 1 ? 0 : 1; + } + + { + glm::ivec2 const A(1, 2); + Error += A.x == 1 ? 0 : 1; + Error += A.y == 2 ? 0 : 1; + } + + { + glm::ivec3 const A(1, 2, 3); + Error += A.x == 1 ? 0 : 1; + Error += A.y == 2 ? 0 : 1; + Error += A.z == 3 ? 0 : 1; + } + + { + glm::ivec4 const A(1, 2, 3, 4); + Error += A.x == 1 ? 0 : 1; + Error += A.y == 2 ? 0 : 1; + Error += A.z == 3 ? 0 : 1; + Error += A.w == 4 ? 0 : 1; + } + + return Error; +} + +static int test_constexpr() +{ + int Error = 0; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/core/core_func_common.cpp b/vendor/glm/test/core/core_func_common.cpp new file mode 100644 index 0000000..b8640de --- /dev/null +++ b/vendor/glm/test/core/core_func_common.cpp @@ -0,0 +1,1349 @@ +#define GLM_FORCE_EXPLICIT_CTOR +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// This file has divisions by zero to test isnan +#if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(disable : 4723) +#endif + +namespace floor_ +{ + static int test() + { + int Error = 0; + + { + float A = 1.1f; + float B = glm::floor(A); + Error += glm::equal(B, 1.f, 0.0001f) ? 0 : 1; + } + + { + double A = 1.1; + double B = glm::floor(A); + Error += glm::equal(B, 1.0, 0.0001) ? 0 : 1; + } + + { + glm::vec1 A(1.1f); + glm::vec1 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::vec1(1.0), 0.0001f)) ? 0 : 1; + } + + { + glm::dvec1 A(1.1); + glm::dvec1 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::dvec1(1.0), 0.0001)) ? 0 : 1; + } + + { + glm::vec2 A(1.1f); + glm::vec2 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::vec2(1.0), 0.0001f)) ? 0 : 1; + } + + { + glm::dvec2 A(1.1); + glm::dvec2 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::dvec2(1.0), 0.0001)) ? 0 : 1; + } + + { + glm::vec3 A(1.1f); + glm::vec3 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::vec3(1.0), 0.0001f)) ? 0 : 1; + } + + { + glm::dvec3 A(1.1); + glm::dvec3 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::dvec3(1.0), 0.0001)) ? 0 : 1; + } + + { + glm::vec4 A(1.1f); + glm::vec4 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::vec4(1.0), 0.0001f)) ? 0 : 1; + } + + { + glm::dvec4 A(1.1); + glm::dvec4 B = glm::floor(A); + + Error += glm::all(glm::equal(B, glm::dvec4(1.0), 0.0001)) ? 0 : 1; + } + + return Error; + } +}//namespace floor + +namespace modf_ +{ + static int test() + { + int Error(0); + + { + float X(1.5f); + float I(0.0f); + float A = glm::modf(X, I); + + Error += glm::equal(I, 1.0f, 0.0001f) ? 0 : 1; + Error += glm::equal(A, 0.5f, 0.0001f) ? 0 : 1; + } + + { + glm::vec4 X(1.1f, 1.2f, 1.5f, 1.7f); + glm::vec4 I(0.0f); + glm::vec4 A = glm::modf(X, I); + + Error += glm::ivec4(I) == glm::ivec4(1) ? 0 : 1; + Error += glm::all(glm::equal(A, glm::vec4(0.1f, 0.2f, 0.5f, 0.7f), 0.00001f)) ? 0 : 1; + } + + { + glm::dvec4 X(1.1, 1.2, 1.5, 1.7); + glm::dvec4 I(0.0); + glm::dvec4 A = glm::modf(X, I); + + Error += glm::ivec4(I) == glm::ivec4(1) ? 0 : 1; + Error += glm::all(glm::equal(A, glm::dvec4(0.1, 0.2, 0.5, 0.7), 0.000000001)) ? 0 : 1; + } + + { + double X(1.5); + double I(0.0); + double A = glm::modf(X, I); + + Error += glm::equal(I, 1.0, 0.0001) ? 0 : 1; + Error += glm::equal(A, 0.5, 0.0001) ? 0 : 1; + } + + return Error; + } +}//namespace modf + +namespace mod_ +{ + static int test() + { + int Error(0); + + { + float A(1.5f); + float B(1.0f); + float C = glm::mod(A, B); + + Error += glm::equal(C, 0.5f, 0.00001f) ? 0 : 1; + } + + { + float A(-0.2f); + float B(1.0f); + float C = glm::mod(A, B); + + Error += glm::equal(C, 0.8f, 0.00001f) ? 0 : 1; + } + + { + float A(3.0); + float B(2.0f); + float C = glm::mod(A, B); + + Error += glm::equal(C, 1.0f, 0.00001f) ? 0 : 1; + } + + { + glm::vec4 A(3.0); + float B(2.0f); + glm::vec4 C = glm::mod(A, B); + + Error += glm::all(glm::equal(C, glm::vec4(1.0f), 0.00001f)) ? 0 : 1; + } + + { + glm::vec4 A(3.0); + glm::vec4 B(2.0f); + glm::vec4 C = glm::mod(A, B); + + Error += glm::all(glm::equal(C, glm::vec4(1.0f), 0.00001f)) ? 0 : 1; + } + + return Error; + } +}//namespace mod_ + +namespace floatBitsToInt +{ + static int test() + { + int Error = 0; + + { + float A = 1.0f; + int B = glm::floatBitsToInt(A); + float C = glm::intBitsToFloat(B); + Error += glm::equal(A, C, 0.0001f) ? 0 : 1; + } + + { + glm::vec2 A(1.0f, 2.0f); + glm::ivec2 B = glm::floatBitsToInt(A); + glm::vec2 C = glm::intBitsToFloat(B); + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + } + + { + glm::vec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B = glm::floatBitsToInt(A); + glm::vec3 C = glm::intBitsToFloat(B); + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + } + + { + glm::vec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = glm::floatBitsToInt(A); + glm::vec4 C = glm::intBitsToFloat(B); + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + } + + return Error; + } +}//namespace floatBitsToInt + +namespace floatBitsToUint +{ + static int test() + { + int Error = 0; + + { + float A = 1.0f; + glm::uint B = glm::floatBitsToUint(A); + float C = glm::uintBitsToFloat(B); + Error += glm::equal(A, C, 0.0001f) ? 0 : 1; + } + + { + glm::vec2 A(1.0f, 2.0f); + glm::uvec2 B = glm::floatBitsToUint(A); + glm::vec2 C = glm::uintBitsToFloat(B); + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + } + + { + glm::vec3 A(1.0f, 2.0f, 3.0f); + glm::uvec3 B = glm::floatBitsToUint(A); + glm::vec3 C = glm::uintBitsToFloat(B); + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + } + + { + glm::vec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::uvec4 B = glm::floatBitsToUint(A); + glm::vec4 C = glm::uintBitsToFloat(B); + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + } + + return Error; + } +}//namespace floatBitsToUint + +namespace min_ +{ + static int test() + { + int Error = 0; + + glm::vec1 A0 = glm::min(glm::vec1(1), glm::vec1(1)); + bool A1 = glm::all(glm::equal(A0, glm::vec1(1), glm::epsilon())); + Error += A1 ? 0 : 1; + + glm::vec2 B0 = glm::min(glm::vec2(1), glm::vec2(1)); + glm::vec2 B1 = glm::min(glm::vec2(1), 1.0f); + bool B2 = glm::all(glm::equal(B0, B1, glm::epsilon())); + Error += B2 ? 0 : 1; + + glm::vec3 C0 = glm::min(glm::vec3(1), glm::vec3(1)); + glm::vec3 C1 = glm::min(glm::vec3(1), 1.0f); + bool C2 = glm::all(glm::equal(C0, C1, glm::epsilon())); + Error += C2 ? 0 : 1; + + glm::vec4 D0 = glm::min(glm::vec4(1), glm::vec4(1)); + glm::vec4 D1 = glm::min(glm::vec4(1), 1.0f); + bool D2 = glm::all(glm::equal(D0, D1, glm::epsilon())); + Error += D2 ? 0 : 1; + + return Error; + } + + int min_tern(int a, int b) + { + return a < b ? a : b; + } + + int min_int(int x, int y) + { + return y ^ ((x ^ y) & -(x < y)); + } + + static int perf(std::size_t Count) + { + std::vector A(Count); + std::vector B(Count); + + std::size_t const InternalCount = 200000; + + for(std::size_t i = 0; i < Count; ++i) + { + A[i] = glm::linearRand(-1000, 1000); + B[i] = glm::linearRand(-1000, 1000); + } + + int Error = 0; + + glm::int32 SumA = 0; + { + std::clock_t Timestamp0 = std::clock(); + + for (std::size_t j = 0; j < InternalCount; ++j) + for (std::size_t i = 0; i < Count; ++i) + SumA += min_tern(A[i], B[i]); + + std::clock_t Timestamp1 = std::clock(); + + std::printf("min_tern Time %d clocks\n", static_cast(Timestamp1 - Timestamp0)); + } + + glm::int32 SumB = 0; + { + std::clock_t Timestamp0 = std::clock(); + + for (std::size_t j = 0; j < InternalCount; ++j) + for (std::size_t i = 0; i < Count; ++i) + SumB += min_int(A[i], B[i]); + + std::clock_t Timestamp1 = std::clock(); + + std::printf("min_int Time %d clocks\n", static_cast(Timestamp1 - Timestamp0)); + } + + Error += SumA == SumB ? 0 : 1; + + return Error; + } +}//namespace min_ + +namespace max_ +{ + static int test() + { + int Error = 0; + + glm::vec1 A0 = glm::max(glm::vec1(1), glm::vec1(1)); + bool A1 = glm::all(glm::equal(A0, glm::vec1(1), glm::epsilon())); + Error += A1 ? 0 : 1; + + + glm::vec2 B0 = glm::max(glm::vec2(1), glm::vec2(1)); + glm::vec2 B1 = glm::max(glm::vec2(1), 1.0f); + bool B2 = glm::all(glm::equal(B0, B1, glm::epsilon())); + Error += B2 ? 0 : 1; + + glm::vec3 C0 = glm::max(glm::vec3(1), glm::vec3(1)); + glm::vec3 C1 = glm::max(glm::vec3(1), 1.0f); + bool C2 = glm::all(glm::equal(C0, C1, glm::epsilon())); + Error += C2 ? 0 : 1; + + glm::vec4 D0 = glm::max(glm::vec4(1), glm::vec4(1)); + glm::vec4 D1 = glm::max(glm::vec4(1), 1.0f); + bool D2 = glm::all(glm::equal(D0, D1, glm::epsilon())); + Error += D2 ? 0 : 1; + + return Error; + } +}//namespace max_ + +namespace clamp_ +{ + static int test() + { + int Error = 0; + + return Error; + } +}//namespace clamp_ + +namespace mix_ +{ + template + struct entry + { + T x; + T y; + B a; + T Result; + }; + + entry const TestBool[] = + { + {0.0f, 1.0f, false, 0.0f}, + {0.0f, 1.0f, true, 1.0f}, + {-1.0f, 1.0f, false, -1.0f}, + {-1.0f, 1.0f, true, 1.0f} + }; + + entry const TestFloat[] = + { + {0.0f, 1.0f, 0.0f, 0.0f}, + {0.0f, 1.0f, 1.0f, 1.0f}, + {-1.0f, 1.0f, 0.0f, -1.0f}, + {-1.0f, 1.0f, 1.0f, 1.0f} + }; + + entry const TestVec2Bool[] = + { + {glm::vec2(0.0f), glm::vec2(1.0f), false, glm::vec2(0.0f)}, + {glm::vec2(0.0f), glm::vec2(1.0f), true, glm::vec2(1.0f)}, + {glm::vec2(-1.0f), glm::vec2(1.0f), false, glm::vec2(-1.0f)}, + {glm::vec2(-1.0f), glm::vec2(1.0f), true, glm::vec2(1.0f)} + }; + + entry const TestBVec2[] = + { + {glm::vec2(0.0f), glm::vec2(1.0f), glm::bvec2(false), glm::vec2(0.0f)}, + {glm::vec2(0.0f), glm::vec2(1.0f), glm::bvec2(true), glm::vec2(1.0f)}, + {glm::vec2(-1.0f), glm::vec2(1.0f), glm::bvec2(false), glm::vec2(-1.0f)}, + {glm::vec2(-1.0f), glm::vec2(1.0f), glm::bvec2(true), glm::vec2(1.0f)}, + {glm::vec2(-1.0f), glm::vec2(1.0f), glm::bvec2(true, false), glm::vec2(1.0f, -1.0f)} + }; + + entry const TestVec3Bool[] = + { + {glm::vec3(0.0f), glm::vec3(1.0f), false, glm::vec3(0.0f)}, + {glm::vec3(0.0f), glm::vec3(1.0f), true, glm::vec3(1.0f)}, + {glm::vec3(-1.0f), glm::vec3(1.0f), false, glm::vec3(-1.0f)}, + {glm::vec3(-1.0f), glm::vec3(1.0f), true, glm::vec3(1.0f)} + }; + + entry const TestBVec3[] = + { + {glm::vec3(0.0f), glm::vec3(1.0f), glm::bvec3(false), glm::vec3(0.0f)}, + {glm::vec3(0.0f), glm::vec3(1.0f), glm::bvec3(true), glm::vec3(1.0f)}, + {glm::vec3(-1.0f), glm::vec3(1.0f), glm::bvec3(false), glm::vec3(-1.0f)}, + {glm::vec3(-1.0f), glm::vec3(1.0f), glm::bvec3(true), glm::vec3(1.0f)}, + {glm::vec3(1.0f, 2.0f, 3.0f), glm::vec3(4.0f, 5.0f, 6.0f), glm::bvec3(true, false, true), glm::vec3(4.0f, 2.0f, 6.0f)} + }; + + entry const TestVec4Bool[] = + { + {glm::vec4(0.0f), glm::vec4(1.0f), false, glm::vec4(0.0f)}, + {glm::vec4(0.0f), glm::vec4(1.0f), true, glm::vec4(1.0f)}, + {glm::vec4(-1.0f), glm::vec4(1.0f), false, glm::vec4(-1.0f)}, + {glm::vec4(-1.0f), glm::vec4(1.0f), true, glm::vec4(1.0f)} + }; + + entry const TestBVec4[] = + { + {glm::vec4(0.0f, 0.0f, 1.0f, 1.0f), glm::vec4(2.0f, 2.0f, 3.0f, 3.0f), glm::bvec4(false, true, false, true), glm::vec4(0.0f, 2.0f, 1.0f, 3.0f)}, + {glm::vec4(0.0f), glm::vec4(1.0f), glm::bvec4(true), glm::vec4(1.0f)}, + {glm::vec4(-1.0f), glm::vec4(1.0f), glm::bvec4(false), glm::vec4(-1.0f)}, + {glm::vec4(-1.0f), glm::vec4(1.0f), glm::bvec4(true), glm::vec4(1.0f)}, + {glm::vec4(1.0f, 2.0f, 3.0f, 4.0f), glm::vec4(5.0f, 6.0f, 7.0f, 8.0f), glm::bvec4(true, false, true, false), glm::vec4(5.0f, 2.0f, 7.0f, 4.0f)} + }; + + static int test() + { + int Error = 0; + + // Float with bool + { + for(std::size_t i = 0; i < sizeof(TestBool) / sizeof(entry); ++i) + { + float Result = glm::mix(TestBool[i].x, TestBool[i].y, TestBool[i].a); + Error += glm::equal(Result, TestBool[i].Result, glm::epsilon()) ? 0 : 1; + } + } + + // Float with float + { + for(std::size_t i = 0; i < sizeof(TestFloat) / sizeof(entry); ++i) + { + float Result = glm::mix(TestFloat[i].x, TestFloat[i].y, TestFloat[i].a); + Error += glm::equal(Result, TestFloat[i].Result, glm::epsilon()) ? 0 : 1; + } + } + + // vec2 with bool + { + for(std::size_t i = 0; i < sizeof(TestVec2Bool) / sizeof(entry); ++i) + { + glm::vec2 Result = glm::mix(TestVec2Bool[i].x, TestVec2Bool[i].y, TestVec2Bool[i].a); + Error += glm::equal(Result.x, TestVec2Bool[i].Result.x, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.y, TestVec2Bool[i].Result.y, glm::epsilon()) ? 0 : 1; + } + } + + // vec2 with bvec2 + { + for(std::size_t i = 0; i < sizeof(TestBVec2) / sizeof(entry); ++i) + { + glm::vec2 Result = glm::mix(TestBVec2[i].x, TestBVec2[i].y, TestBVec2[i].a); + Error += glm::equal(Result.x, TestBVec2[i].Result.x, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.y, TestBVec2[i].Result.y, glm::epsilon()) ? 0 : 1; + } + } + + // vec3 with bool + { + for(std::size_t i = 0; i < sizeof(TestVec3Bool) / sizeof(entry); ++i) + { + glm::vec3 Result = glm::mix(TestVec3Bool[i].x, TestVec3Bool[i].y, TestVec3Bool[i].a); + Error += glm::equal(Result.x, TestVec3Bool[i].Result.x, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.y, TestVec3Bool[i].Result.y, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.z, TestVec3Bool[i].Result.z, glm::epsilon()) ? 0 : 1; + } + } + + // vec3 with bvec3 + { + for(std::size_t i = 0; i < sizeof(TestBVec3) / sizeof(entry); ++i) + { + glm::vec3 Result = glm::mix(TestBVec3[i].x, TestBVec3[i].y, TestBVec3[i].a); + Error += glm::equal(Result.x, TestBVec3[i].Result.x, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.y, TestBVec3[i].Result.y, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.z, TestBVec3[i].Result.z, glm::epsilon()) ? 0 : 1; + } + } + + // vec4 with bool + { + for(std::size_t i = 0; i < sizeof(TestVec4Bool) / sizeof(entry); ++i) + { + glm::vec4 Result = glm::mix(TestVec4Bool[i].x, TestVec4Bool[i].y, TestVec4Bool[i].a); + Error += glm::equal(Result.x, TestVec4Bool[i].Result.x, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.y, TestVec4Bool[i].Result.y, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.z, TestVec4Bool[i].Result.z, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.w, TestVec4Bool[i].Result.w, glm::epsilon()) ? 0 : 1; + } + } + + // vec4 with bvec4 + { + for(std::size_t i = 0; i < sizeof(TestBVec4) / sizeof(entry); ++i) + { + glm::vec4 Result = glm::mix(TestBVec4[i].x, TestBVec4[i].y, TestBVec4[i].a); + Error += glm::equal(Result.x, TestBVec4[i].Result.x, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.y, TestBVec4[i].Result.y, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.z, TestBVec4[i].Result.z, glm::epsilon()) ? 0 : 1; + Error += glm::equal(Result.w, TestBVec4[i].Result.w, glm::epsilon()) ? 0 : 1; + } + } + + return Error; + } +}//namespace mix_ + +namespace step_ +{ + template + struct entry + { + EDGE edge; + VEC x; + VEC result; + }; + + entry TestVec4Scalar [] = + { + { 1.0f, glm::vec4(1.0f, 2.0f, 3.0f, 4.0f), glm::vec4(1.0f) }, + { 0.0f, glm::vec4(1.0f, 2.0f, 3.0f, 4.0f), glm::vec4(1.0f) }, + { 0.0f, glm::vec4(-1.0f, -2.0f, -3.0f, -4.0f), glm::vec4(0.0f) } + }; + + entry TestVec4Vector [] = + { + { glm::vec4(-1.0f, -2.0f, -3.0f, -4.0f), glm::vec4(-2.0f, -3.0f, -4.0f, -5.0f), glm::vec4(0.0f) }, + { glm::vec4( 0.0f, 1.0f, 2.0f, 3.0f), glm::vec4( 1.0f, 2.0f, 3.0f, 4.0f), glm::vec4(1.0f) }, + { glm::vec4( 2.0f, 3.0f, 4.0f, 5.0f), glm::vec4( 1.0f, 2.0f, 3.0f, 4.0f), glm::vec4(0.0f) }, + { glm::vec4( 0.0f, 1.0f, 2.0f, 3.0f), glm::vec4(-1.0f,-2.0f,-3.0f,-4.0f), glm::vec4(0.0f) } + }; + + static int test() + { + int Error = 0; + + // scalar + { + float const Edge = 2.0f; + + float const A = glm::step(Edge, 1.0f); + Error += glm::equal(A, 0.0f, glm::epsilon()) ? 0 : 1; + + float const B = glm::step(Edge, 3.0f); + Error += glm::equal(B, 1.0f, glm::epsilon()) ? 0 : 1; + + float const C = glm::step(Edge, 2.0f); + Error += glm::equal(C, 1.0f, glm::epsilon()) ? 0 : 1; + } + + // vec4 and float + { + for (std::size_t i = 0; i < sizeof(TestVec4Scalar) / sizeof(entry); ++i) + { + glm::vec4 Result = glm::step(TestVec4Scalar[i].edge, TestVec4Scalar[i].x); + Error += glm::all(glm::equal(Result, TestVec4Scalar[i].result, glm::epsilon())) ? 0 : 1; + } + } + + // vec4 and vec4 + { + for (std::size_t i = 0; i < sizeof(TestVec4Vector) / sizeof(entry); ++i) + { + glm::vec4 Result = glm::step(TestVec4Vector[i].edge, TestVec4Vector[i].x); + Error += glm::all(glm::equal(Result, TestVec4Vector[i].result, glm::epsilon())) ? 0 : 1; + } + } + + return Error; + } +}//namespace step_ + +namespace round_ +{ + static int test() + { + int Error = 0; + + { + float A = glm::round(0.0f); + Error += glm::equal(A, 0.0f, glm::epsilon()) ? 0 : 1; + float B = glm::round(0.5f); + Error += glm::equal(B, 1.0f, glm::epsilon()) ? 0 : 1; + float C = glm::round(1.0f); + Error += glm::equal(C, 1.0f, glm::epsilon()) ? 0 : 1; + float D = glm::round(0.1f); + Error += glm::equal(D, 0.0f, glm::epsilon()) ? 0 : 1; + float E = glm::round(0.9f); + Error += glm::equal(E, 1.0f, glm::epsilon()) ? 0 : 1; + float F = glm::round(1.5f); + Error += glm::equal(F, 2.0f, glm::epsilon()) ? 0 : 1; + float G = glm::round(1.9f); + Error += glm::equal(G, 2.0f, glm::epsilon()) ? 0 : 1; + } + + { + float A = glm::round(-0.0f); + Error += glm::equal(A, 0.0f, glm::epsilon()) ? 0 : 1; + float B = glm::round(-0.5f); + Error += glm::equal(B, -1.0f, glm::epsilon()) ? 0 : 1; + float C = glm::round(-1.0f); + Error += glm::equal(C, -1.0f, glm::epsilon()) ? 0 : 1; + float D = glm::round(-0.1f); + Error += glm::equal(D, 0.0f, glm::epsilon()) ? 0 : 1; + float E = glm::round(-0.9f); + Error += glm::equal(E, -1.0f, glm::epsilon()) ? 0 : 1; + float F = glm::round(-1.5f); + Error += glm::equal(F, -2.0f, glm::epsilon()) ? 0 : 1; + float G = glm::round(-1.9f); + Error += glm::equal(G, -2.0f, glm::epsilon()) ? 0 : 1; + } + + return Error; + } +}//namespace round_ + +namespace roundEven +{ + static int test() + { + int Error = 0; + + { + float A1 = glm::roundEven(-1.5f); + Error += glm::equal(A1, -2.0f, 0.0001f) ? 0 : 1; + + float A2 = glm::roundEven(1.5f); + Error += glm::equal(A2, 2.0f, 0.0001f) ? 0 : 1; + + float A5 = glm::roundEven(-2.5f); + Error += glm::equal(A5, -2.0f, 0.0001f) ? 0 : 1; + + float A6 = glm::roundEven(2.5f); + Error += glm::equal(A6, 2.0f, 0.0001f) ? 0 : 1; + + float A3 = glm::roundEven(-3.5f); + Error += glm::equal(A3, -4.0f, 0.0001f) ? 0 : 1; + + float A4 = glm::roundEven(3.5f); + Error += glm::equal(A4, 4.0f, 0.0001f) ? 0 : 1; + + float C7 = glm::roundEven(-4.5f); + Error += glm::equal(C7, -4.0f, 0.0001f) ? 0 : 1; + + float C8 = glm::roundEven(4.5f); + Error += glm::equal(C8, 4.0f, 0.0001f) ? 0 : 1; + + float C1 = glm::roundEven(-5.5f); + Error += glm::equal(C1, -6.0f, 0.0001f) ? 0 : 1; + + float C2 = glm::roundEven(5.5f); + Error += glm::equal(C2, 6.0f, 0.0001f) ? 0 : 1; + + float C3 = glm::roundEven(-6.5f); + Error += glm::equal(C3, -6.0f, 0.0001f) ? 0 : 1; + + float C4 = glm::roundEven(6.5f); + Error += glm::equal(C4, 6.0f, 0.0001f) ? 0 : 1; + + float C5 = glm::roundEven(-7.5f); + Error += glm::equal(C5, -8.0f, 0.0001f) ? 0 : 1; + + float C6 = glm::roundEven(7.5f); + Error += glm::equal(C6, 8.0f, 0.0001f) ? 0 : 1; + + Error += 0; + } + + { + float A7 = glm::roundEven(-2.4f); + Error += glm::equal(A7, -2.0f, 0.0001f) ? 0 : 1; + + float A8 = glm::roundEven(2.4f); + Error += glm::equal(A8, 2.0f, 0.0001f) ? 0 : 1; + + float B1 = glm::roundEven(-2.6f); + Error += glm::equal(B1, -3.0f, 0.0001f) ? 0 : 1; + + float B2 = glm::roundEven(2.6f); + Error += glm::equal(B2, 3.0f, 0.0001f) ? 0 : 1; + + float B3 = glm::roundEven(-2.0f); + Error += glm::equal(B3, -2.0f, 0.0001f) ? 0 : 1; + + float B4 = glm::roundEven(2.0f); + Error += glm::equal(B4, 2.0f, 0.0001f) ? 0 : 1; + + Error += 0; + } + + { + float A = glm::roundEven(0.0f); + Error += glm::equal(A, 0.0f, glm::epsilon()) ? 0 : 1; + float B = glm::roundEven(0.5f); + Error += glm::equal(B, 0.0f, glm::epsilon()) ? 0 : 1; + float C = glm::roundEven(1.0f); + Error += glm::equal(C, 1.0f, glm::epsilon()) ? 0 : 1; + float D = glm::roundEven(0.1f); + Error += glm::equal(D, 0.0f, glm::epsilon()) ? 0 : 1; + float E = glm::roundEven(0.9f); + Error += glm::equal(E, 1.0f, glm::epsilon()) ? 0 : 1; + float F = glm::roundEven(1.5f); + Error += glm::equal(F, 2.0f, glm::epsilon()) ? 0 : 1; + float G = glm::roundEven(1.9f); + Error += glm::equal(G, 2.0f, glm::epsilon()) ? 0 : 1; + } + + { + float A = glm::roundEven(-0.0f); + Error += glm::equal(A, 0.0f, glm::epsilon()) ? 0 : 1; + float B = glm::roundEven(-0.5f); + Error += glm::equal(B, -0.0f, glm::epsilon()) ? 0 : 1; + float C = glm::roundEven(-1.0f); + Error += glm::equal(C, -1.0f, glm::epsilon()) ? 0 : 1; + float D = glm::roundEven(-0.1f); + Error += glm::equal(D, 0.0f, glm::epsilon()) ? 0 : 1; + float E = glm::roundEven(-0.9f); + Error += glm::equal(E, -1.0f, glm::epsilon()) ? 0 : 1; + float F = glm::roundEven(-1.5f); + Error += glm::equal(F, -2.0f, glm::epsilon()) ? 0 : 1; + float G = glm::roundEven(-1.9f); + Error += glm::equal(G, -2.0f, glm::epsilon()) ? 0 : 1; + } + + { + float A = glm::roundEven(1.5f); + Error += glm::equal(A, 2.0f, glm::epsilon()) ? 0 : 1; + float B = glm::roundEven(2.5f); + Error += glm::equal(B, 2.0f, glm::epsilon()) ? 0 : 1; + float C = glm::roundEven(3.5f); + Error += glm::equal(C, 4.0f, glm::epsilon()) ? 0 : 1; + float D = glm::roundEven(4.5f); + Error += glm::equal(D, 4.0f, glm::epsilon()) ? 0 : 1; + float E = glm::roundEven(5.5f); + Error += glm::equal(E, 6.0f, glm::epsilon()) ? 0 : 1; + float F = glm::roundEven(6.5f); + Error += glm::equal(F, 6.0f, glm::epsilon()) ? 0 : 1; + float G = glm::roundEven(7.5f); + Error += glm::equal(G, 8.0f, glm::epsilon()) ? 0 : 1; + } + + { + float A = glm::roundEven(-1.5f); + Error += glm::equal(A, -2.0f, glm::epsilon()) ? 0 : 1; + float B = glm::roundEven(-2.5f); + Error += glm::equal(B, -2.0f, glm::epsilon()) ? 0 : 1; + float C = glm::roundEven(-3.5f); + Error += glm::equal(C, -4.0f, glm::epsilon()) ? 0 : 1; + float D = glm::roundEven(-4.5f); + Error += glm::equal(D, -4.0f, glm::epsilon()) ? 0 : 1; + float E = glm::roundEven(-5.5f); + Error += glm::equal(E, -6.0f, glm::epsilon()) ? 0 : 1; + float F = glm::roundEven(-6.5f); + Error += glm::equal(F, -6.0f, glm::epsilon()) ? 0 : 1; + float G = glm::roundEven(-7.5f); + Error += glm::equal(G, -8.0f, glm::epsilon()) ? 0 : 1; + } + + return Error; + } +}//namespace roundEven + +namespace isnan_ +{ + static int test() + { + int Error = 0; + + float Zero_f = 0.0; + double Zero_d = 0.0; + + { + Error += true == glm::isnan(0.0/Zero_d) ? 0 : 1; + Error += true == glm::any(glm::isnan(glm::dvec2(0.0 / Zero_d))) ? 0 : 1; + Error += true == glm::any(glm::isnan(glm::dvec3(0.0 / Zero_d))) ? 0 : 1; + Error += true == glm::any(glm::isnan(glm::dvec4(0.0 / Zero_d))) ? 0 : 1; + } + + { + Error += true == glm::isnan(0.0f/Zero_f) ? 0 : 1; + Error += true == glm::any(glm::isnan(glm::vec2(0.0f/Zero_f))) ? 0 : 1; + Error += true == glm::any(glm::isnan(glm::vec3(0.0f/Zero_f))) ? 0 : 1; + Error += true == glm::any(glm::isnan(glm::vec4(0.0f/Zero_f))) ? 0 : 1; + } + + return Error; + } +}//namespace isnan_ + +namespace isinf_ +{ + static int test() + { + int Error = 0; + + float Zero_f = 0.0; + double Zero_d = 0.0; + + { + Error += true == glm::isinf( 1.0/Zero_d) ? 0 : 1; + Error += true == glm::isinf(-1.0/Zero_d) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::dvec2( 1.0/Zero_d))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::dvec2(-1.0/Zero_d))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::dvec3( 1.0/Zero_d))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::dvec3(-1.0/Zero_d))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::dvec4( 1.0/Zero_d))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::dvec4(-1.0/Zero_d))) ? 0 : 1; + } + + { + Error += true == glm::isinf( 1.0f/Zero_f) ? 0 : 1; + Error += true == glm::isinf(-1.0f/Zero_f) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::vec2( 1.0f/Zero_f))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::vec2(-1.0f/Zero_f))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::vec3( 1.0f/Zero_f))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::vec3(-1.0f/Zero_f))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::vec4( 1.0f/Zero_f))) ? 0 : 1; + Error += true == glm::any(glm::isinf(glm::vec4(-1.0f/Zero_f))) ? 0 : 1; + } + + return Error; + } +}//namespace isinf_ + +namespace sign +{ + template + GLM_FUNC_QUALIFIER genFIType sign_if(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || + (std::numeric_limits::is_signed && std::numeric_limits::is_integer), "'sign' only accept signed inputs"); + + genFIType result; + if(x > genFIType(0)) + result = genFIType(1); + else if(x < genFIType(0)) + result = genFIType(-1); + else + result = genFIType(0); + return result; + } + + template + GLM_FUNC_QUALIFIER genFIType sign_alu1(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_signed && std::numeric_limits::is_integer, + "'sign' only accept integer inputs"); + + return (x >> 31) | (static_cast(-x) >> 31); + } + + GLM_FUNC_QUALIFIER int sign_alu2(int x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_signed && std::numeric_limits::is_integer, "'sign' only accept integer inputs"); + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4146) //cast truncates constant value +# endif + + return -(static_cast(x) >> 31) | (-static_cast(x) >> 31); + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + } + + template + GLM_FUNC_QUALIFIER genFIType sign_sub(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_signed && std::numeric_limits::is_integer, + "'sign' only accept integer inputs"); + + return (static_cast(-x) >> 31) - (static_cast(x) >> 31); + } + + template + GLM_FUNC_QUALIFIER genFIType sign_cmp(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_signed && std::numeric_limits::is_integer, + "'sign' only accept integer inputs"); + + return (x > 0) - (x < 0); + } + + template + struct type + { + genType Value; + genType Return; + }; + + int test_int32() + { + type const Data[] = + { + { std::numeric_limits::max(), 1}, + { std::numeric_limits::min(), -1}, + { 0, 0}, + { 1, 1}, + { 2, 1}, + { 3, 1}, + {-1,-1}, + {-2,-1}, + {-3,-1} + }; + + int Error = 0; + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::int32 Result = glm::sign(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::int32 Result = sign_cmp(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::int32 Result = sign_if(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::int32 Result = sign_alu1(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::int32 Result = sign_alu2(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_i32vec4() + { + type const Data[] = + { + {glm::ivec4( 1), glm::ivec4( 1)}, + {glm::ivec4( 0), glm::ivec4( 0)}, + {glm::ivec4( 2), glm::ivec4( 1)}, + {glm::ivec4( 3), glm::ivec4( 1)}, + {glm::ivec4(-1), glm::ivec4(-1)}, + {glm::ivec4(-2), glm::ivec4(-1)}, + {glm::ivec4(-3), glm::ivec4(-1)} + }; + + int Error = 0; + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::ivec4 Result = glm::sign(Data[i].Value); + Error += glm::all(glm::equal(Data[i].Return, Result)) ? 0 : 1; + } + + return Error; + } + + int test_f32vec4() + { + type const Data[] = + { + {glm::vec4( 1), glm::vec4( 1)}, + {glm::vec4( 0), glm::vec4( 0)}, + {glm::vec4( 2), glm::vec4( 1)}, + {glm::vec4( 3), glm::vec4( 1)}, + {glm::vec4(-1), glm::vec4(-1)}, + {glm::vec4(-2), glm::vec4(-1)}, + {glm::vec4(-3), glm::vec4(-1)} + }; + + int Error = 0; + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::vec4 Result = glm::sign(Data[i].Value); + Error += glm::all(glm::equal(Data[i].Return, Result, glm::epsilon())) ? 0 : 1; + } + + return Error; + } + + static int test() + { + int Error = 0; + + Error += test_int32(); + Error += test_i32vec4(); + Error += test_f32vec4(); + + return Error; + } + + int perf_rand(std::size_t Samples) + { + int Error = 0; + + std::size_t const Count = Samples; + std::vector Input, Output; + Input.resize(Count); + Output.resize(Count); + for(std::size_t i = 0; i < Count; ++i) + Input[i] = static_cast(glm::linearRand(-65536.f, 65536.f)); + + std::clock_t Timestamp0 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_cmp(Input[i]); + + std::clock_t Timestamp1 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_if(Input[i]); + + std::clock_t Timestamp2 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_alu1(Input[i]); + + std::clock_t Timestamp3 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_alu2(Input[i]); + + std::clock_t Timestamp4 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_sub(Input[i]); + + std::clock_t Timestamp5 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = glm::sign(Input[i]); + + std::clock_t Timestamp6 = std::clock(); + + std::printf("sign_cmp(rand) Time %d clocks\n", static_cast(Timestamp1 - Timestamp0)); + std::printf("sign_if(rand) Time %d clocks\n", static_cast(Timestamp2 - Timestamp1)); + std::printf("sign_alu1(rand) Time %d clocks\n", static_cast(Timestamp3 - Timestamp2)); + std::printf("sign_alu2(rand) Time %d clocks\n", static_cast(Timestamp4 - Timestamp3)); + std::printf("sign_sub(rand) Time %d clocks\n", static_cast(Timestamp5 - Timestamp4)); + std::printf("glm::sign(rand) Time %d clocks\n", static_cast(Timestamp6 - Timestamp5)); + + return Error; + } + + int perf_linear(std::size_t Samples) + { + int Error = 0; + + std::size_t const Count = Samples; + std::vector Input, Output; + Input.resize(Count); + Output.resize(Count); + for(std::size_t i = 0; i < Count; ++i) + Input[i] = static_cast(i); + + std::clock_t Timestamp0 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_cmp(Input[i]); + + std::clock_t Timestamp1 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_if(Input[i]); + + std::clock_t Timestamp2 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_alu1(Input[i]); + + std::clock_t Timestamp3 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_alu2(Input[i]); + + std::clock_t Timestamp4 = std::clock(); + + for(std::size_t i = 0; i < Count; ++i) + Output[i] = sign_sub(Input[i]); + + std::clock_t Timestamp5 = std::clock(); + + std::printf("sign_cmp(linear) Time %d clocks\n", static_cast(Timestamp1 - Timestamp0)); + std::printf("sign_if(linear) Time %d clocks\n", static_cast(Timestamp2 - Timestamp1)); + std::printf("sign_alu1(linear) Time %d clocks\n", static_cast(Timestamp3 - Timestamp2)); + std::printf("sign_alu2(linear) Time %d clocks\n", static_cast(Timestamp4 - Timestamp3)); + std::printf("sign_sub(linear) Time %d clocks\n", static_cast(Timestamp5 - Timestamp4)); + + return Error; + } + + int perf_linear_cal(std::size_t Samples) + { + int Error = 0; + + glm::int32 const Count = static_cast(Samples); + + std::clock_t Timestamp0 = std::clock(); + glm::int32 Sum = 0; + + for(glm::int32 i = 1; i < Count; ++i) + Sum += sign_cmp(i); + + std::clock_t Timestamp1 = std::clock(); + + for(glm::int32 i = 1; i < Count; ++i) + Sum += sign_if(i); + + std::clock_t Timestamp2 = std::clock(); + + for(glm::int32 i = 1; i < Count; ++i) + Sum += sign_alu1(i); + + std::clock_t Timestamp3 = std::clock(); + + for(glm::int32 i = 1; i < Count; ++i) + Sum += sign_alu2(i); + + std::clock_t Timestamp4 = std::clock(); + + for(glm::int32 i = 1; i < Count; ++i) + Sum += sign_sub(i); + + std::clock_t Timestamp5 = std::clock(); + + std::printf("Sum %d\n", static_cast(Sum)); + + std::printf("sign_cmp(linear_cal) Time %d clocks\n", static_cast(Timestamp1 - Timestamp0)); + std::printf("sign_if(linear_cal) Time %d clocks\n", static_cast(Timestamp2 - Timestamp1)); + std::printf("sign_alu1(linear_cal) Time %d clocks\n", static_cast(Timestamp3 - Timestamp2)); + std::printf("sign_alu2(linear_cal) Time %d clocks\n", static_cast(Timestamp4 - Timestamp3)); + std::printf("sign_sub(linear_cal) Time %d clocks\n", static_cast(Timestamp5 - Timestamp4)); + + return Error; + } + + static int perf(std::size_t Samples) + { + int Error(0); + + Error += perf_linear_cal(Samples); + Error += perf_linear(Samples); + Error += perf_rand(Samples); + + return Error; + } +}//namespace sign + +namespace frexp_ +{ + static int test() + { + int Error = 0; + + { + glm::vec1 const x(1024); + glm::ivec1 exp; + glm::vec1 A = glm::frexp(x, exp); + Error += glm::all(glm::equal(A, glm::vec1(0.5), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(exp, glm::ivec1(11))) ? 0 : 1; + } + + { + glm::vec2 const x(1024, 0.24); + glm::ivec2 exp; + glm::vec2 A = glm::frexp(x, exp); + Error += glm::all(glm::equal(A, glm::vec2(0.5, 0.96), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(exp, glm::ivec2(11, -2))) ? 0 : 1; + } + + { + glm::vec3 const x(1024, 0.24, 0); + glm::ivec3 exp; + glm::vec3 A = glm::frexp(x, exp); + Error += glm::all(glm::equal(A, glm::vec3(0.5, 0.96, 0.0), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(exp, glm::ivec3(11, -2, 0))) ? 0 : 1; + } + + { + glm::vec4 const x(1024, 0.24, 0, -1.33); + glm::ivec4 exp; + glm::vec4 A = glm::frexp(x, exp); + Error += glm::all(glm::equal(A, glm::vec4(0.5, 0.96, 0.0, -0.665), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(exp, glm::ivec4(11, -2, 0, 1))) ? 0 : 1; + } + + return Error; + } +}//namespace frexp_ + +namespace ldexp_ +{ + static int test() + { + int Error(0); + + { + glm::vec1 A = glm::vec1(0.5); + glm::ivec1 exp = glm::ivec1(11); + glm::vec1 x = glm::ldexp(A, exp); + Error += glm::all(glm::equal(x, glm::vec1(1024),0.00001f)) ? 0 : 1; + } + + { + glm::vec2 A = glm::vec2(0.5, 0.96); + glm::ivec2 exp = glm::ivec2(11, -2); + glm::vec2 x = glm::ldexp(A, exp); + Error += glm::all(glm::equal(x, glm::vec2(1024, .24),0.00001f)) ? 0 : 1; + } + + { + glm::vec3 A = glm::vec3(0.5, 0.96, 0.0); + glm::ivec3 exp = glm::ivec3(11, -2, 0); + glm::vec3 x = glm::ldexp(A, exp); + Error += glm::all(glm::equal(x, glm::vec3(1024, .24, 0),0.00001f)) ? 0 : 1; + } + + { + glm::vec4 A = glm::vec4(0.5, 0.96, 0.0, -0.665); + glm::ivec4 exp = glm::ivec4(11, -2, 0, 1); + glm::vec4 x = glm::ldexp(A, exp); + Error += glm::all(glm::equal(x, glm::vec4(1024, .24, 0, -1.33),0.00001f)) ? 0 : 1; + } + + return Error; + } +}//namespace ldexp_ + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::abs(1.0f) > 0.0f, "GLM: Failed constexpr"); + constexpr glm::vec1 const A = glm::abs(glm::vec1(1.0f)); + constexpr glm::vec2 const B = glm::abs(glm::vec2(1.0f)); + constexpr glm::vec3 const C = glm::abs(glm::vec3(1.0f)); + constexpr glm::vec4 const D = glm::abs(glm::vec4(1.0f)); +#endif // GLM_HAS_CONSTEXPR + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_constexpr(); + Error += sign::test(); + Error += floor_::test(); + Error += mod_::test(); + Error += modf_::test(); + Error += floatBitsToInt::test(); + Error += floatBitsToUint::test(); + Error += mix_::test(); + Error += step_::test(); + Error += max_::test(); + Error += min_::test(); + Error += clamp_::test(); + Error += round_::test(); + Error += roundEven::test(); + Error += isnan_::test(); + Error += isinf_::test(); + Error += frexp_::test(); + Error += ldexp_::test(); + +# ifdef NDEBUG + std::size_t Samples = 1000; +# else + std::size_t Samples = 1; +# endif + Error += sign::perf(Samples); + + Error += min_::perf(Samples); + + return Error; +} + diff --git a/vendor/glm/test/core/core_func_exponential.cpp b/vendor/glm/test/core/core_func_exponential.cpp new file mode 100644 index 0000000..380cdfb --- /dev/null +++ b/vendor/glm/test/core/core_func_exponential.cpp @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_pow() +{ + int Error(0); + + float A = glm::pow(2.f, 2.f); + Error += glm::equal(A, 4.f, 0.01f) ? 0 : 1; + + glm::vec1 B = glm::pow(glm::vec1(2.f), glm::vec1(2.f)); + Error += glm::all(glm::equal(B, glm::vec1(4.f), 0.01f)) ? 0 : 1; + + glm::vec2 C = glm::pow(glm::vec2(2.f), glm::vec2(2.f)); + Error += glm::all(glm::equal(C, glm::vec2(4.f), 0.01f)) ? 0 : 1; + + glm::vec3 D = glm::pow(glm::vec3(2.f), glm::vec3(2.f)); + Error += glm::all(glm::equal(D, glm::vec3(4.f), 0.01f)) ? 0 : 1; + + glm::vec4 E = glm::pow(glm::vec4(2.f), glm::vec4(2.f)); + Error += glm::all(glm::equal(E, glm::vec4(4.f), 0.01f)) ? 0 : 1; + + return Error; +} + +static int test_sqrt() +{ + int Error = 0; + + float A = glm::sqrt(4.f); + Error += glm::equal(A, 2.f, 0.01f) ? 0 : 1; + + glm::vec1 B = glm::sqrt(glm::vec1(4.f)); + Error += glm::all(glm::equal(B, glm::vec1(2.f), 0.01f)) ? 0 : 1; + + glm::vec2 C = glm::sqrt(glm::vec2(4.f)); + Error += glm::all(glm::equal(C, glm::vec2(2.f), 0.01f)) ? 0 : 1; + + glm::vec3 D = glm::sqrt(glm::vec3(4.f)); + Error += glm::all(glm::equal(D, glm::vec3(2.f), 0.01f)) ? 0 : 1; + + glm::vec4 E = glm::sqrt(glm::vec4(4.f)); + Error += glm::all(glm::equal(E, glm::vec4(2.f), 0.01f)) ? 0 : 1; + + return Error; +} + +static int test_exp() +{ + int Error = 0; + + float A = glm::exp(1.f); + Error += glm::equal(A, glm::e(), 0.01f) ? 0 : 1; + + glm::vec1 B = glm::exp(glm::vec1(1.f)); + Error += glm::all(glm::equal(B, glm::vec1(glm::e()), 0.01f)) ? 0 : 1; + + glm::vec2 C = glm::exp(glm::vec2(1.f)); + Error += glm::all(glm::equal(C, glm::vec2(glm::e()), 0.01f)) ? 0 : 1; + + glm::vec3 D = glm::exp(glm::vec3(1.f)); + Error += glm::all(glm::equal(D, glm::vec3(glm::e()), 0.01f)) ? 0 : 1; + + glm::vec4 E = glm::exp(glm::vec4(1.f)); + Error += glm::all(glm::equal(E, glm::vec4(glm::e()), 0.01f)) ? 0 : 1; + + return Error; +} + +static int test_log() +{ + int Error = 0; + + float const A = glm::log(glm::e()); + Error += glm::equal(A, 1.f, 0.01f) ? 0 : 1; + + glm::vec1 const B = glm::log(glm::vec1(glm::e())); + Error += glm::all(glm::equal(B, glm::vec1(1.f), 0.01f)) ? 0 : 1; + + glm::vec2 const C = glm::log(glm::vec2(glm::e())); + Error += glm::all(glm::equal(C, glm::vec2(1.f), 0.01f)) ? 0 : 1; + + glm::vec3 const D = glm::log(glm::vec3(glm::e())); + Error += glm::all(glm::equal(D, glm::vec3(1.f), 0.01f)) ? 0 : 1; + + glm::vec4 const E = glm::log(glm::vec4(glm::e())); + Error += glm::all(glm::equal(E, glm::vec4(1.f), 0.01f)) ? 0 : 1; + + return Error; +} + +static int test_exp2() +{ + int Error = 0; + + float A = glm::exp2(4.f); + Error += glm::equal(A, 16.f, 0.01f) ? 0 : 1; + + glm::vec1 B = glm::exp2(glm::vec1(4.f)); + Error += glm::all(glm::equal(B, glm::vec1(16.f), 0.01f)) ? 0 : 1; + + glm::vec2 C = glm::exp2(glm::vec2(4.f, 3.f)); + Error += glm::all(glm::equal(C, glm::vec2(16.f, 8.f), 0.01f)) ? 0 : 1; + + glm::vec3 D = glm::exp2(glm::vec3(4.f, 3.f, 2.f)); + Error += glm::all(glm::equal(D, glm::vec3(16.f, 8.f, 4.f), 0.01f)) ? 0 : 1; + + glm::vec4 E = glm::exp2(glm::vec4(4.f, 3.f, 2.f, 1.f)); + Error += glm::all(glm::equal(E, glm::vec4(16.f, 8.f, 4.f, 2.f), 0.01f)) ? 0 : 1; + +# if GLM_HAS_CXX11_STL + //large exponent + float F = glm::exp2(23.f); + Error += glm::equal(F, 8388608.f, 0.01f) ? 0 : 1; +# endif + + return Error; +} + +static int test_log2() +{ + int Error = 0; + + float A = glm::log2(16.f); + Error += glm::equal(A, 4.f, 0.01f) ? 0 : 1; + + glm::vec1 B = glm::log2(glm::vec1(16.f)); + Error += glm::all(glm::equal(B, glm::vec1(4.f), 0.01f)) ? 0 : 1; + + glm::vec2 C = glm::log2(glm::vec2(16.f, 8.f)); + Error += glm::all(glm::equal(C, glm::vec2(4.f, 3.f), 0.01f)) ? 0 : 1; + + glm::vec3 D = glm::log2(glm::vec3(16.f, 8.f, 4.f)); + Error += glm::all(glm::equal(D, glm::vec3(4.f, 3.f, 2.f), 0.01f)) ? 0 : 1; + + glm::vec4 E = glm::log2(glm::vec4(16.f, 8.f, 4.f, 2.f)); + Error += glm::all(glm::equal(E, glm::vec4(4.f, 3.f, 2.f, 1.f), 0.01f)) ? 0 : 1; + + return Error; +} + +static int test_inversesqrt() +{ + int Error = 0; + + float A = glm::inversesqrt(16.f) * glm::sqrt(16.f); + Error += glm::equal(A, 1.f, 0.01f) ? 0 : 1; + + glm::vec1 B = glm::inversesqrt(glm::vec1(16.f)) * glm::sqrt(16.f); + Error += glm::all(glm::equal(B, glm::vec1(1.f), 0.01f)) ? 0 : 1; + + glm::vec2 C = glm::inversesqrt(glm::vec2(16.f)) * glm::sqrt(16.f); + Error += glm::all(glm::equal(C, glm::vec2(1.f), 0.01f)) ? 0 : 1; + + glm::vec3 D = glm::inversesqrt(glm::vec3(16.f)) * glm::sqrt(16.f); + Error += glm::all(glm::equal(D, glm::vec3(1.f), 0.01f)) ? 0 : 1; + + glm::vec4 E = glm::inversesqrt(glm::vec4(16.f)) * glm::sqrt(16.f); + Error += glm::all(glm::equal(E, glm::vec4(1.f), 0.01f)) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_pow(); + Error += test_sqrt(); + Error += test_exp(); + Error += test_log(); + Error += test_exp2(); + Error += test_log2(); + Error += test_inversesqrt(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_func_geometric.cpp b/vendor/glm/test/core/core_func_geometric.cpp new file mode 100644 index 0000000..7ef9c68 --- /dev/null +++ b/vendor/glm/test/core/core_func_geometric.cpp @@ -0,0 +1,200 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace length +{ + int test() + { + float Length1 = glm::length(glm::vec1(1)); + float Length2 = glm::length(glm::vec2(1, 0)); + float Length3 = glm::length(glm::vec3(1, 0, 0)); + float Length4 = glm::length(glm::vec4(1, 0, 0, 0)); + + int Error = 0; + + Error += glm::abs(Length1 - 1.0f) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Length2 - 1.0f) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Length3 - 1.0f) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Length4 - 1.0f) < std::numeric_limits::epsilon() ? 0 : 1; + + return Error; + } +}//namespace length + +namespace distance +{ + int test() + { + float Distance1 = glm::distance(glm::vec1(1), glm::vec1(1)); + float Distance2 = glm::distance(glm::vec2(1, 0), glm::vec2(1, 0)); + float Distance3 = glm::distance(glm::vec3(1, 0, 0), glm::vec3(1, 0, 0)); + float Distance4 = glm::distance(glm::vec4(1, 0, 0, 0), glm::vec4(1, 0, 0, 0)); + + int Error = 0; + + Error += glm::abs(Distance1) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Distance2) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Distance3) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Distance4) < std::numeric_limits::epsilon() ? 0 : 1; + + return Error; + } +}//namespace distance + +namespace dot +{ + int test() + { + float Dot1 = glm::dot(glm::vec1(1), glm::vec1(1)); + float Dot2 = glm::dot(glm::vec2(1), glm::vec2(1)); + float Dot3 = glm::dot(glm::vec3(1), glm::vec3(1)); + float Dot4 = glm::dot(glm::vec4(1), glm::vec4(1)); + + int Error = 0; + + Error += glm::abs(Dot1 - 1.0f) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Dot2 - 2.0f) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Dot3 - 3.0f) < std::numeric_limits::epsilon() ? 0 : 1; + Error += glm::abs(Dot4 - 4.0f) < std::numeric_limits::epsilon() ? 0 : 1; + + return Error; + } +}//namespace dot + +namespace cross +{ + int test() + { + glm::vec3 Cross1 = glm::cross(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0)); + glm::vec3 Cross2 = glm::cross(glm::vec3(0, 1, 0), glm::vec3(1, 0, 0)); + + int Error = 0; + + Error += glm::all(glm::lessThan(glm::abs(Cross1 - glm::vec3(0, 0, 1)), glm::vec3(std::numeric_limits::epsilon()))) ? 0 : 1; + Error += glm::all(glm::lessThan(glm::abs(Cross2 - glm::vec3(0, 0,-1)), glm::vec3(std::numeric_limits::epsilon()))) ? 0 : 1; + + return Error; + } +}//namespace cross + +namespace normalize +{ + int test() + { + glm::vec3 Normalize1 = glm::normalize(glm::vec3(1, 0, 0)); + glm::vec3 Normalize2 = glm::normalize(glm::vec3(2, 0, 0)); + + glm::vec3 Normalize3 = glm::normalize(glm::vec3(-0.6, 0.7, -0.5)); + + glm::vec3 ro = glm::vec3(glm::cos(5.f) * 3.f, 2.f, glm::sin(5.f) * 3.f); + glm::vec3 w = glm::normalize(glm::vec3(0, -0.2f, 0) - ro); + glm::vec3 u = glm::normalize(glm::cross(w, glm::vec3(0, 1, 0))); + glm::vec3 v = glm::cross(u, w); + + int Error = 0; + + Error += glm::all(glm::lessThan(glm::abs(Normalize1 - glm::vec3(1, 0, 0)), glm::vec3(std::numeric_limits::epsilon()))) ? 0 : 1; + Error += glm::all(glm::lessThan(glm::abs(Normalize2 - glm::vec3(1, 0, 0)), glm::vec3(std::numeric_limits::epsilon()))) ? 0 : 1; + + return Error; + } +}//namespace normalize + +namespace faceforward +{ + int test() + { + int Error = 0; + + { + glm::vec3 N(0.0f, 0.0f, 1.0f); + glm::vec3 I(1.0f, 0.0f, 1.0f); + glm::vec3 Nref(0.0f, 0.0f, 1.0f); + glm::vec3 F = glm::faceforward(N, I, Nref); + } + + return Error; + } +}//namespace faceforward + +namespace reflect +{ + int test() + { + int Error = 0; + + { + glm::vec2 A(1.0f,-1.0f); + glm::vec2 B(0.0f, 1.0f); + glm::vec2 C = glm::reflect(A, B); + Error += glm::all(glm::equal(C, glm::vec2(1.0, 1.0), 0.0001f)) ? 0 : 1; + } + + { + glm::dvec2 A(1.0f,-1.0f); + glm::dvec2 B(0.0f, 1.0f); + glm::dvec2 C = glm::reflect(A, B); + Error += glm::all(glm::equal(C, glm::dvec2(1.0, 1.0), 0.0001)) ? 0 : 1; + } + + return Error; + } +}//namespace reflect + +namespace refract +{ + int test() + { + int Error = 0; + + { + float A(-1.0f); + float B(1.0f); + float C = glm::refract(A, B, 0.5f); + Error += glm::equal(C, -1.0f, 0.0001f) ? 0 : 1; + } + + { + glm::vec2 A(0.0f,-1.0f); + glm::vec2 B(0.0f, 1.0f); + glm::vec2 C = glm::refract(A, B, 0.5f); + Error += glm::all(glm::equal(C, glm::vec2(0.0, -1.0), 0.0001f)) ? 0 : 1; + } + + { + glm::dvec2 A(0.0f,-1.0f); + glm::dvec2 B(0.0f, 1.0f); + glm::dvec2 C = glm::refract(A, B, 0.5); + Error += glm::all(glm::equal(C, glm::dvec2(0.0, -1.0), 0.0001)) ? 0 : 1; + } + + return Error; + } +}//namespace refract + +int main() +{ + int Error(0); + + Error += length::test(); + Error += distance::test(); + Error += dot::test(); + Error += cross::test(); + Error += normalize::test(); + Error += faceforward::test(); + Error += reflect::test(); + Error += refract::test(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_func_integer.cpp b/vendor/glm/test/core/core_func_integer.cpp new file mode 100644 index 0000000..95d650c --- /dev/null +++ b/vendor/glm/test/core/core_func_integer.cpp @@ -0,0 +1,1556 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum result +{ + SUCCESS, + FAIL, + ASSERT, + STATIC_ASSERT +}; + +namespace bitfieldInsert +{ + template + struct type + { + genType Base; + genType Insert; + int Offset; + int Bits; + genType Return; + }; + + typedef type typeU32; + + typeU32 const Data32[] = + { + {0x00000000, 0xffffffff, 0, 32, 0xffffffff}, + {0x00000000, 0xffffffff, 0, 31, 0x7fffffff}, + {0x00000000, 0xffffffff, 0, 0, 0x00000000}, + {0xff000000, 0x000000ff, 8, 8, 0xff00ff00}, + {0xffff0000, 0xffff0000, 16, 16, 0x00000000}, + {0x0000ffff, 0x0000ffff, 16, 16, 0xffffffff} + }; + + static int test() + { + int Error = 0; + glm::uint count = sizeof(Data32) / sizeof(typeU32); + + for(glm::uint i = 0; i < count; ++i) + { + glm::uint Return = glm::bitfieldInsert( + Data32[i].Base, + Data32[i].Insert, + Data32[i].Offset, + Data32[i].Bits); + + Error += Data32[i].Return == Return ? 0 : 1; + } + + return Error; + } +}//bitfieldInsert + +namespace bitfieldExtract +{ + template + struct type + { + genType Value; + int Offset; + int Bits; + genType Return; + result Result; + }; + + typedef type typeU32; + + typeU32 const Data32[] = + { + {0xffffffff, 0,32, 0xffffffff, SUCCESS}, + {0xffffffff, 8, 0, 0x00000000, SUCCESS}, + {0x00000000, 0,32, 0x00000000, SUCCESS}, + {0x0f0f0f0f, 0,32, 0x0f0f0f0f, SUCCESS}, + {0x00000000, 8, 0, 0x00000000, SUCCESS}, + {0x80000000,31, 1, 0x00000001, SUCCESS}, + {0x7fffffff,31, 1, 0x00000000, SUCCESS}, + {0x00000300, 8, 8, 0x00000003, SUCCESS}, + {0x0000ff00, 8, 8, 0x000000ff, SUCCESS}, + {0xfffffff0, 0, 5, 0x00000010, SUCCESS}, + {0x000000ff, 1, 3, 0x00000007, SUCCESS}, + {0x000000ff, 0, 3, 0x00000007, SUCCESS}, + {0x00000000, 0, 2, 0x00000000, SUCCESS}, + {0xffffffff, 0, 8, 0x000000ff, SUCCESS}, + {0xffff0000,16,16, 0x0000ffff, SUCCESS}, + {0xfffffff0, 0, 8, 0x00000000, FAIL}, + {0xffffffff,16,16, 0x00000000, FAIL}, + //{0xffffffff,32, 1, 0x00000000, ASSERT}, // Throw an assert + //{0xffffffff, 0,33, 0x00000000, ASSERT}, // Throw an assert + //{0xffffffff,16,16, 0x00000000, ASSERT}, // Throw an assert + }; + + static int test() + { + int Error = 0; + + glm::uint count = sizeof(Data32) / sizeof(typeU32); + + for(glm::uint i = 0; i < count; ++i) + { + glm::uint Return = glm::bitfieldExtract( + Data32[i].Value, + Data32[i].Offset, + Data32[i].Bits); + + bool Compare = Data32[i].Return == Return; + + if(Data32[i].Result == SUCCESS && Compare) + continue; + else if(Data32[i].Result == FAIL && !Compare) + continue; + + Error += 1; + } + + return Error; + } +}//extractField + +namespace bitfieldReverse +{ +/* + GLM_FUNC_QUALIFIER unsigned int bitfieldReverseLoop(unsigned int v) + { + unsigned int Result(0); + unsigned int const BitSize = static_cast(sizeof(unsigned int) * 8); + for(unsigned int i = 0; i < BitSize; ++i) + { + unsigned int const BitSet(v & (static_cast(1) << i)); + unsigned int const BitFirst(BitSet >> i); + Result |= BitFirst << (BitSize - 1 - i); + } + return Result; + } + + GLM_FUNC_QUALIFIER glm::uint64_t bitfieldReverseLoop(glm::uint64_t v) + { + glm::uint64_t Result(0); + glm::uint64_t const BitSize = static_cast(sizeof(unsigned int) * 8); + for(glm::uint64_t i = 0; i < BitSize; ++i) + { + glm::uint64_t const BitSet(v & (static_cast(1) << i)); + glm::uint64_t const BitFirst(BitSet >> i); + Result |= BitFirst << (BitSize - 1 - i); + } + return Result; + } +*/ + template + GLM_FUNC_QUALIFIER glm::vec bitfieldReverseLoop(glm::vec const& v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitfieldReverse' only accept integer values"); + + glm::vec Result(0); + T const BitSize = static_cast(sizeof(T) * 8); + for(T i = 0; i < BitSize; ++i) + { + glm::vec const BitSet(v & (static_cast(1) << i)); + glm::vec const BitFirst(BitSet >> i); + Result |= BitFirst << (BitSize - 1 - i); + } + return Result; + } + + template + GLM_FUNC_QUALIFIER T bitfieldReverseLoop(T v) + { + return bitfieldReverseLoop(glm::vec<1, T>(v)).x; + } + + GLM_FUNC_QUALIFIER glm::uint32 bitfieldReverseUint32(glm::uint32 x) + { + x = (x & 0x55555555) << 1 | (x & 0xAAAAAAAA) >> 1; + x = (x & 0x33333333) << 2 | (x & 0xCCCCCCCC) >> 2; + x = (x & 0x0F0F0F0F) << 4 | (x & 0xF0F0F0F0) >> 4; + x = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8; + x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >> 16; + return x; + } + + GLM_FUNC_QUALIFIER glm::uint64 bitfieldReverseUint64(glm::uint64 x) + { + x = (x & 0x5555555555555555) << 1 | (x & 0xAAAAAAAAAAAAAAAA) >> 1; + x = (x & 0x3333333333333333) << 2 | (x & 0xCCCCCCCCCCCCCCCC) >> 2; + x = (x & 0x0F0F0F0F0F0F0F0F) << 4 | (x & 0xF0F0F0F0F0F0F0F0) >> 4; + x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8; + x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16; + x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32; + return x; + } + + template + struct compute_bitfieldReverseStep + { + template + GLM_FUNC_QUALIFIER static glm::vec call(glm::vec const& v, T, T) + { + return v; + } + }; + + template<> + struct compute_bitfieldReverseStep + { + template + GLM_FUNC_QUALIFIER static glm::vec call(glm::vec const& v, T Mask, T Shift) + { + return (v & Mask) << Shift | (v & (~Mask)) >> Shift; + } + }; + + template + GLM_FUNC_QUALIFIER glm::vec bitfieldReverseOps(glm::vec const& v) + { + glm::vec x(v); + x = compute_bitfieldReverseStep= 2>::call(x, static_cast(0x5555555555555555ull), static_cast( 1)); + x = compute_bitfieldReverseStep= 4>::call(x, static_cast(0x3333333333333333ull), static_cast( 2)); + x = compute_bitfieldReverseStep= 8>::call(x, static_cast(0x0F0F0F0F0F0F0F0Full), static_cast( 4)); + x = compute_bitfieldReverseStep= 16>::call(x, static_cast(0x00FF00FF00FF00FFull), static_cast( 8)); + x = compute_bitfieldReverseStep= 32>::call(x, static_cast(0x0000FFFF0000FFFFull), static_cast(16)); + x = compute_bitfieldReverseStep= 64>::call(x, static_cast(0x00000000FFFFFFFFull), static_cast(32)); + return x; + } + + template + GLM_FUNC_QUALIFIER genType bitfieldReverseOps(genType x) + { + return bitfieldReverseOps(glm::vec<1, genType, glm::defaultp>(x)).x; + } + + template + struct type + { + genType Value; + genType Return; + result Result; + }; + + typedef type typeU32; + + typeU32 const Data32[] = + { + {0x00000001, 0x80000000, SUCCESS}, + {0x0000000f, 0xf0000000, SUCCESS}, + {0x000000ff, 0xff000000, SUCCESS}, + {0xf0000000, 0x0000000f, SUCCESS}, + {0xff000000, 0x000000ff, SUCCESS}, + {0xffffffff, 0xffffffff, SUCCESS}, + {0x00000000, 0x00000000, SUCCESS} + }; + + typedef type typeU64; + + typeU64 const Data64[] = + { + {0x00000000000000ff, 0xff00000000000000, SUCCESS}, + {0x000000000000000f, 0xf000000000000000, SUCCESS}, + {0xf000000000000000, 0x000000000000000f, SUCCESS}, + {0xffffffffffffffff, 0xffffffffffffffff, SUCCESS}, + {0x0000000000000000, 0x0000000000000000, SUCCESS} + }; + + static int test32_bitfieldReverse() + { + int Error = 0; + std::size_t const Count = sizeof(Data32) / sizeof(typeU32); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint Return = glm::bitfieldReverse(Data32[i].Value); + + bool Compare = Data32[i].Return == Return; + + if(Data32[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test32_bitfieldReverseLoop() + { + int Error = 0; + std::size_t const Count = sizeof(Data32) / sizeof(typeU32); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint Return = bitfieldReverseLoop(Data32[i].Value); + + bool Compare = Data32[i].Return == Return; + + if(Data32[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test32_bitfieldReverseUint32() + { + int Error = 0; + std::size_t const Count = sizeof(Data32) / sizeof(typeU32); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint Return = bitfieldReverseUint32(Data32[i].Value); + + bool Compare = Data32[i].Return == Return; + + if(Data32[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test32_bitfieldReverseOps() + { + int Error = 0; + std::size_t const Count = sizeof(Data32) / sizeof(typeU32); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint Return = bitfieldReverseOps(Data32[i].Value); + + bool Compare = Data32[i].Return == Return; + + if(Data32[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test64_bitfieldReverse() + { + int Error = 0; + std::size_t const Count = sizeof(Data64) / sizeof(typeU64); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint64 Return = glm::bitfieldReverse(Data64[i].Value); + + bool Compare = Data64[i].Return == Return; + + if(Data64[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test64_bitfieldReverseLoop() + { + int Error = 0; + std::size_t const Count = sizeof(Data64) / sizeof(typeU64); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint64 Return = bitfieldReverseLoop(Data64[i].Value); + + bool Compare = Data64[i].Return == Return; + + if(Data32[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test64_bitfieldReverseUint64() + { + int Error = 0; + std::size_t const Count = sizeof(Data64) / sizeof(typeU64); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint64 Return = bitfieldReverseUint64(Data64[i].Value); + + bool Compare = Data64[i].Return == Return; + + if(Data64[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test64_bitfieldReverseOps() + { + int Error = 0; + std::size_t const Count = sizeof(Data64) / sizeof(typeU64); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::uint64 Return = bitfieldReverseOps(Data64[i].Value); + + bool Compare = Data64[i].Return == Return; + + if(Data64[i].Result == SUCCESS) + Error += Compare ? 0 : 1; + else + Error += Compare ? 1 : 0; + } + + return Error; + } + + static int test() + { + int Error = 0; + + Error += test32_bitfieldReverse(); + Error += test32_bitfieldReverseLoop(); + Error += test32_bitfieldReverseUint32(); + Error += test32_bitfieldReverseOps(); + + Error += test64_bitfieldReverse(); + Error += test64_bitfieldReverseLoop(); + Error += test64_bitfieldReverseUint64(); + Error += test64_bitfieldReverseOps(); + + return Error; + } + + static int perf32(glm::uint32 Count) + { + int Error = 0; + + std::vector Data; + Data.resize(static_cast(Count)); + + std::clock_t Timestamps0 = std::clock(); + + for(glm::uint32 k = 0; k < Count; ++k) + Data[k] = glm::bitfieldReverse(k); + + std::clock_t Timestamps1 = std::clock(); + + for(glm::uint32 k = 0; k < Count; ++k) + Data[k] = bitfieldReverseLoop(k); + + std::clock_t Timestamps2 = std::clock(); + + for(glm::uint32 k = 0; k < Count; ++k) + Data[k] = bitfieldReverseUint32(k); + + std::clock_t Timestamps3 = std::clock(); + + for(glm::uint32 k = 0; k < Count; ++k) + Data[k] = bitfieldReverseOps(k); + + std::clock_t Timestamps4 = std::clock(); + + std::printf("glm::bitfieldReverse: %d clocks\n", static_cast(Timestamps1 - Timestamps0)); + std::printf("bitfieldReverseLoop: %d clocks\n", static_cast(Timestamps2 - Timestamps1)); + std::printf("bitfieldReverseUint32: %d clocks\n", static_cast(Timestamps3 - Timestamps2)); + std::printf("bitfieldReverseOps: %d clocks\n", static_cast(Timestamps4 - Timestamps3)); + + return Error; + } + + static int perf64(glm::uint64 Count) + { + int Error = 0; + + std::vector Data; + Data.resize(static_cast(Count)); + + std::clock_t Timestamps0 = std::clock(); + + for(glm::uint64 k = 0; k < Count; ++k) + Data[static_cast(k)] = glm::bitfieldReverse(k); + + std::clock_t Timestamps1 = std::clock(); + + for(glm::uint64 k = 0; k < Count; ++k) + Data[static_cast(k)] = bitfieldReverseLoop(k); + + std::clock_t Timestamps2 = std::clock(); + + for(glm::uint64 k = 0; k < Count; ++k) + Data[static_cast(k)] = bitfieldReverseUint64(k); + + std::clock_t Timestamps3 = std::clock(); + + for(glm::uint64 k = 0; k < Count; ++k) + Data[static_cast(k)] = bitfieldReverseOps(k); + + std::clock_t Timestamps4 = std::clock(); + + std::printf("glm::bitfieldReverse - 64: %d clocks\n", static_cast(Timestamps1 - Timestamps0)); + std::printf("bitfieldReverseLoop - 64: %d clocks\n", static_cast(Timestamps2 - Timestamps1)); + std::printf("bitfieldReverseUint - 64: %d clocks\n", static_cast(Timestamps3 - Timestamps2)); + std::printf("bitfieldReverseOps - 64: %d clocks\n", static_cast(Timestamps4 - Timestamps3)); + + return Error; + } + + static int perf(std::size_t Samples) + { + int Error = 0; + + Error += perf32(static_cast(Samples)); + Error += perf64(static_cast(Samples)); + + return Error; + } +}//bitfieldReverse + +namespace findMSB +{ + template + struct type + { + genType Value; + retType Return; + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + static int findMSB_intrinsic(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + if(Value == 0) + return -1; + + unsigned long Result(0); + _BitScanReverse(&Result, Value); + return int(Result); + } +# endif//GLM_HAS_BITSCAN_WINDOWS + +# if GLM_ARCH & GLM_ARCH_AVX && GLM_COMPILER & GLM_COMPILER_VC + template + static int findMSB_avx(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + if(Value == 0) + return -1; + + return int(_tzcnt_u32(Value)); + } +# endif//GLM_ARCH & GLM_ARCH_AVX && GLM_PLATFORM & GLM_PLATFORM_WINDOWS + + template + static int findMSB_095(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + if(Value == genIUType(0) || Value == genIUType(-1)) + return -1; + else if(Value > 0) + { + genIUType Bit = genIUType(-1); + for(genIUType tmp = Value; tmp > 0; tmp >>= 1, ++Bit){} + return static_cast(Bit); + } + else //if(Value < 0) + { + int const BitCount(sizeof(genIUType) * 8); + int MostSignificantBit(-1); + for(int BitIndex(0); BitIndex < BitCount; ++BitIndex) + MostSignificantBit = (Value & (1 << BitIndex)) ? MostSignificantBit : BitIndex; + assert(MostSignificantBit >= 0); + return MostSignificantBit; + } + } + + template + static int findMSB_nlz1(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findMSB' only accept integer values"); + + if (x == 0) + return -1; + + int n = 0; + if (x <= 0x0000FFFF) {n = n +16; x = x <<16;} + if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;} + if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;} + if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;} + if (x <= 0x7FFFFFFF) {n = n + 1;} + return 31 - n; + } + + static int findMSB_nlz2(unsigned int x) + { + unsigned int y; + int n = 32; + + y = x >>16; if (y != 0) {n = n -16; x = y;} + y = x >> 8; if (y != 0) {n = n - 8; x = y;} + y = x >> 4; if (y != 0) {n = n - 4; x = y;} + y = x >> 2; if (y != 0) {n = n - 2; x = y;} + y = x >> 1; if (y != 0) return n - 2; + return 32 - (n - static_cast(x)); + } + + static int findMSB_pop(unsigned int x) + { + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return 31 - glm::bitCount(~x); + } + + static int perf_int(std::size_t Count) + { + type const Data[] = + { + {0x00000000, -1}, + {0x00000001, 0}, + {0x00000002, 1}, + {0x00000003, 1}, + {0x00000004, 2}, + {0x00000005, 2}, + {0x00000007, 2}, + {0x00000008, 3}, + {0x00000010, 4}, + {0x00000020, 5}, + {0x00000040, 6}, + {0x00000080, 7}, + {0x00000100, 8}, + {0x00000200, 9}, + {0x00000400, 10}, + {0x00000800, 11}, + {0x00001000, 12}, + {0x00002000, 13}, + {0x00004000, 14}, + {0x00008000, 15}, + {0x00010000, 16}, + {0x00020000, 17}, + {0x00040000, 18}, + {0x00080000, 19}, + {0x00100000, 20}, + {0x00200000, 21}, + {0x00400000, 22}, + {0x00800000, 23}, + {0x01000000, 24}, + {0x02000000, 25}, + {0x04000000, 26}, + {0x08000000, 27}, + {0x10000000, 28}, + {0x20000000, 29}, + {0x40000000, 30} + }; + + int Error(0); + + std::clock_t Timestamps0 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = glm::findMSB(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps1 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = findMSB_nlz1(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps2 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = findMSB_nlz2(static_cast(Data[i].Value)); + Error += Data[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps3 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = findMSB_095(static_cast(Data[i].Value)); + Error += Data[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps4 = std::clock(); + +# if GLM_HAS_BITSCAN_WINDOWS + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = findMSB_intrinsic(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } +# endif//GLM_HAS_BITSCAN_WINDOWS + + std::clock_t Timestamps5 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = findMSB_pop(static_cast(Data[i].Value)); + Error += Data[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps6 = std::clock(); + +# if GLM_ARCH & GLM_ARCH_AVX && GLM_COMPILER & GLM_COMPILER_VC + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = findMSB_avx(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps7 = std::clock(); +# endif + + std::printf("glm::findMSB: %d clocks\n", static_cast(Timestamps1 - Timestamps0)); + std::printf("findMSB - nlz1: %d clocks\n", static_cast(Timestamps2 - Timestamps1)); + std::printf("findMSB - nlz2: %d clocks\n", static_cast(Timestamps3 - Timestamps2)); + std::printf("findMSB - 0.9.5: %d clocks\n", static_cast(Timestamps4 - Timestamps3)); + +# if GLM_HAS_BITSCAN_WINDOWS + std::printf("findMSB - intrinsics: %d clocks\n", static_cast(Timestamps5 - Timestamps4)); +# endif//GLM_HAS_BITSCAN_WINDOWS + std::printf("findMSB - pop: %d clocks\n", static_cast(Timestamps6 - Timestamps5)); + +# if GLM_ARCH & GLM_ARCH_AVX && GLM_COMPILER & GLM_COMPILER_VC + std::printf("findMSB - avx tzcnt: %d clocks\n", static_cast(Timestamps7 - Timestamps6)); +# endif//GLM_ARCH & GLM_ARCH_AVX && GLM_PLATFORM & GLM_PLATFORM_WINDOWS + + return Error; + } + + static int test_ivec4() + { + type const Data[] = + { + {glm::ivec4(0x00000000), glm::ivec4(-1)}, + {glm::ivec4(0x00000001), glm::ivec4( 0)}, + {glm::ivec4(0x00000002), glm::ivec4( 1)}, + {glm::ivec4(0x00000003), glm::ivec4( 1)}, + {glm::ivec4(0x00000004), glm::ivec4( 2)}, + {glm::ivec4(0x00000005), glm::ivec4( 2)}, + {glm::ivec4(0x00000007), glm::ivec4( 2)}, + {glm::ivec4(0x00000008), glm::ivec4( 3)}, + {glm::ivec4(0x00000010), glm::ivec4( 4)}, + {glm::ivec4(0x00000020), glm::ivec4( 5)}, + {glm::ivec4(0x00000040), glm::ivec4( 6)}, + {glm::ivec4(0x00000080), glm::ivec4( 7)}, + {glm::ivec4(0x00000100), glm::ivec4( 8)}, + {glm::ivec4(0x00000200), glm::ivec4( 9)}, + {glm::ivec4(0x00000400), glm::ivec4(10)}, + {glm::ivec4(0x00000800), glm::ivec4(11)}, + {glm::ivec4(0x00001000), glm::ivec4(12)}, + {glm::ivec4(0x00002000), glm::ivec4(13)}, + {glm::ivec4(0x00004000), glm::ivec4(14)}, + {glm::ivec4(0x00008000), glm::ivec4(15)}, + {glm::ivec4(0x00010000), glm::ivec4(16)}, + {glm::ivec4(0x00020000), glm::ivec4(17)}, + {glm::ivec4(0x00040000), glm::ivec4(18)}, + {glm::ivec4(0x00080000), glm::ivec4(19)}, + {glm::ivec4(0x00100000), glm::ivec4(20)}, + {glm::ivec4(0x00200000), glm::ivec4(21)}, + {glm::ivec4(0x00400000), glm::ivec4(22)}, + {glm::ivec4(0x00800000), glm::ivec4(23)}, + {glm::ivec4(0x01000000), glm::ivec4(24)}, + {glm::ivec4(0x02000000), glm::ivec4(25)}, + {glm::ivec4(0x04000000), glm::ivec4(26)}, + {glm::ivec4(0x08000000), glm::ivec4(27)}, + {glm::ivec4(0x10000000), glm::ivec4(28)}, + {glm::ivec4(0x20000000), glm::ivec4(29)}, + {glm::ivec4(0x40000000), glm::ivec4(30)} + }; + + int Error(0); + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + glm::ivec4 Result0 = glm::findMSB(Data[i].Value); + Error += glm::all(glm::equal(Data[i].Return, Result0)) ? 0 : 1; + } + + return Error; + } + + static int test_int() + { + typedef type entry; + + entry const Data[] = + { + {0x00000000, -1}, + {0x00000001, 0}, + {0x00000002, 1}, + {0x00000003, 1}, + {0x00000004, 2}, + {0x00000005, 2}, + {0x00000007, 2}, + {0x00000008, 3}, + {0x00000010, 4}, + {0x00000020, 5}, + {0x00000040, 6}, + {0x00000080, 7}, + {0x00000100, 8}, + {0x00000200, 9}, + {0x00000400, 10}, + {0x00000800, 11}, + {0x00001000, 12}, + {0x00002000, 13}, + {0x00004000, 14}, + {0x00008000, 15}, + {0x00010000, 16}, + {0x00020000, 17}, + {0x00040000, 18}, + {0x00080000, 19}, + {0x00100000, 20}, + {0x00200000, 21}, + {0x00400000, 22}, + {0x00800000, 23}, + {0x01000000, 24}, + {0x02000000, 25}, + {0x04000000, 26}, + {0x08000000, 27}, + {0x10000000, 28}, + {0x20000000, 29}, + {0x40000000, 30} + }; + + int Error(0); + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(entry); ++i) + { + int Result0 = glm::findMSB(Data[i].Value); + Error += Data[i].Return == Result0 ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(entry); ++i) + { + int Result0 = findMSB_nlz1(Data[i].Value); + Error += Data[i].Return == Result0 ? 0 : 1; + } +/* + for(std::size_t i = 0; i < sizeof(Data) / sizeof(entry); ++i) + { + int Result0 = findMSB_nlz2(Data[i].Value); + Error += Data[i].Return == Result0 ? 0 : 1; + } +*/ + for(std::size_t i = 0; i < sizeof(Data) / sizeof(entry); ++i) + { + int Result0 = findMSB_095(Data[i].Value); + Error += Data[i].Return == Result0 ? 0 : 1; + } + +# if GLM_HAS_BITSCAN_WINDOWS + for(std::size_t i = 0; i < sizeof(Data) / sizeof(entry); ++i) + { + int Result0 = findMSB_intrinsic(Data[i].Value); + Error += Data[i].Return == Result0 ? 0 : 1; + } +# endif//GLM_HAS_BITSCAN_WINDOWS + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(entry); ++i) + { + int Result0 = findMSB_pop(Data[i].Value); + Error += Data[i].Return == Result0 ? 0 : 1; + } + + return Error; + } + + static int test() + { + int Error(0); + + Error += test_ivec4(); + Error += test_int(); + + return Error; + } + + static int perf(std::size_t Samples) + { + int Error(0); + + Error += perf_int(Samples); + + return Error; + } +}//findMSB + +namespace findLSB +{ + template + struct type + { + genType Value; + retType Return; + }; + + typedef type entry; + + entry const DataI32[] = + { + {0x00000001, 0}, + {0x00000003, 0}, + {0x00000002, 1}, + // {0x80000000, 31}, // Clang generates an error with this + {0x00010000, 16}, + {0x7FFF0000, 16}, + {0x7F000000, 24}, + {0x7F00FF00, 8}, + {0x00000000, -1} + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template + static int findLSB_intrinsic(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findLSB' only accept integer values"); + + if(Value == 0) + return -1; + + unsigned long Result(0); + _BitScanForward(&Result, Value); + return int(Result); + } +# endif + + template + static int findLSB_095(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'findLSB' only accept integer values"); + if(Value == 0) + return -1; + + genIUType Bit; + for(Bit = genIUType(0); !(Value & (1 << Bit)); ++Bit){} + return Bit; + } + + template + static int findLSB_ntz2(genIUType x) + { + if(x == 0) + return -1; + + return glm::bitCount(~x & (x - static_cast(1))); + } + + template + static int findLSB_branchfree(genIUType x) + { + bool IsNull(x == 0); + int const Keep(!IsNull); + int const Discard(IsNull); + + return static_cast(glm::bitCount(~x & (x - static_cast(1)))) * Keep + Discard * -1; + } + + static int test_int() + { + int Error(0); + + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = glm::findLSB(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_095(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + +# if GLM_HAS_BITSCAN_WINDOWS + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_intrinsic(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } +# endif + + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_ntz2(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_branchfree(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + + return Error; + } + + static int test() + { + int Error(0); + + Error += test_int(); + + return Error; + } + + static int perf_int(std::size_t Count) + { + int Error(0); + + std::clock_t Timestamps0 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = glm::findLSB(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps1 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_095(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps2 = std::clock(); + +# if GLM_HAS_BITSCAN_WINDOWS + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_intrinsic(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } +# endif + + std::clock_t Timestamps3 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_ntz2(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps4 = std::clock(); + + for(std::size_t k = 0; k < Count; ++k) + for(std::size_t i = 0; i < sizeof(DataI32) / sizeof(entry); ++i) + { + int Result = findLSB_branchfree(DataI32[i].Value); + Error += DataI32[i].Return == Result ? 0 : 1; + } + + std::clock_t Timestamps5 = std::clock(); + + std::printf("glm::findLSB: %d clocks\n", static_cast(Timestamps1 - Timestamps0)); + std::printf("findLSB - 0.9.5: %d clocks\n", static_cast(Timestamps2 - Timestamps1)); + +# if GLM_HAS_BITSCAN_WINDOWS + std::printf("findLSB - intrinsics: %d clocks\n", static_cast(Timestamps3 - Timestamps2)); +# endif + + std::printf("findLSB - ntz2: %d clocks\n", static_cast(Timestamps4 - Timestamps3)); + std::printf("findLSB - branchfree: %d clocks\n", static_cast(Timestamps5 - Timestamps4)); + + return Error; + } + + static int perf(std::size_t Samples) + { + int Error(0); + + Error += perf_int(Samples); + + return Error; + } +}//findLSB + +namespace uaddCarry +{ + static int test() + { + int Error(0); + + { + glm::uint x = std::numeric_limits::max(); + glm::uint y = 0; + glm::uint Carry = 0; + glm::uint Result = glm::uaddCarry(x, y, Carry); + + Error += Carry == 0 ? 0 : 1; + Error += Result == std::numeric_limits::max() ? 0 : 1; + } + + { + glm::uint x = std::numeric_limits::max(); + glm::uint y = 1; + glm::uint Carry = 0; + glm::uint Result = glm::uaddCarry(x, y, Carry); + + Error += Carry == 1 ? 0 : 1; + Error += Result == 0 ? 0 : 1; + } + + { + glm::uvec1 x(std::numeric_limits::max()); + glm::uvec1 y(0); + glm::uvec1 Carry(0); + glm::uvec1 Result(glm::uaddCarry(x, y, Carry)); + + Error += glm::all(glm::equal(Carry, glm::uvec1(0))) ? 0 : 1; + Error += glm::all(glm::equal(Result, glm::uvec1(std::numeric_limits::max()))) ? 0 : 1; + } + + { + glm::uvec1 x(std::numeric_limits::max()); + glm::uvec1 y(1); + glm::uvec1 Carry(0); + glm::uvec1 Result(glm::uaddCarry(x, y, Carry)); + + Error += glm::all(glm::equal(Carry, glm::uvec1(1))) ? 0 : 1; + Error += glm::all(glm::equal(Result, glm::uvec1(0))) ? 0 : 1; + } + + return Error; + } +}//namespace uaddCarry + +namespace usubBorrow +{ + static int test() + { + int Error(0); + + { + glm::uint x = 16; + glm::uint y = 17; + glm::uint Borrow = 0; + glm::uint Result = glm::usubBorrow(x, y, Borrow); + + Error += Borrow == 1 ? 0 : 1; + Error += Result == 1 ? 0 : 1; + } + + { + glm::uvec1 x(16); + glm::uvec1 y(17); + glm::uvec1 Borrow(0); + glm::uvec1 Result(glm::usubBorrow(x, y, Borrow)); + + Error += glm::all(glm::equal(Borrow, glm::uvec1(1))) ? 0 : 1; + Error += glm::all(glm::equal(Result, glm::uvec1(1))) ? 0 : 1; + } + + { + glm::uvec2 x(16); + glm::uvec2 y(17); + glm::uvec2 Borrow(0); + glm::uvec2 Result(glm::usubBorrow(x, y, Borrow)); + + Error += glm::all(glm::equal(Borrow, glm::uvec2(1))) ? 0 : 1; + Error += glm::all(glm::equal(Result, glm::uvec2(1))) ? 0 : 1; + } + + { + glm::uvec3 x(16); + glm::uvec3 y(17); + glm::uvec3 Borrow(0); + glm::uvec3 Result(glm::usubBorrow(x, y, Borrow)); + + Error += glm::all(glm::equal(Borrow, glm::uvec3(1))) ? 0 : 1; + Error += glm::all(glm::equal(Result, glm::uvec3(1))) ? 0 : 1; + } + + { + glm::uvec4 x(16); + glm::uvec4 y(17); + glm::uvec4 Borrow(0); + glm::uvec4 Result(glm::usubBorrow(x, y, Borrow)); + + Error += glm::all(glm::equal(Borrow, glm::uvec4(1))) ? 0 : 1; + Error += glm::all(glm::equal(Result, glm::uvec4(1))) ? 0 : 1; + } + + return Error; + } +}//namespace usubBorrow + +namespace umulExtended +{ + static int test() + { + int Error(0); + + { + glm::uint x = 2; + glm::uint y = 3; + glm::uint msb = 0; + glm::uint lsb = 0; + glm::umulExtended(x, y, msb, lsb); + + Error += msb == 0 ? 0 : 1; + Error += lsb == 6 ? 0 : 1; + } + + { + glm::uvec1 x(2); + glm::uvec1 y(3); + glm::uvec1 msb(0); + glm::uvec1 lsb(0); + glm::umulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::uvec1(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::uvec1(6))) ? 0 : 1; + } + + { + glm::uvec2 x(2); + glm::uvec2 y(3); + glm::uvec2 msb(0); + glm::uvec2 lsb(0); + glm::umulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::uvec2(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::uvec2(6))) ? 0 : 1; + } + + { + glm::uvec3 x(2); + glm::uvec3 y(3); + glm::uvec3 msb(0); + glm::uvec3 lsb(0); + glm::umulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::uvec3(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::uvec3(6))) ? 0 : 1; + } + + { + glm::uvec4 x(2); + glm::uvec4 y(3); + glm::uvec4 msb(0); + glm::uvec4 lsb(0); + glm::umulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::uvec4(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::uvec4(6))) ? 0 : 1; + } + + return Error; + } +}//namespace umulExtended + +namespace imulExtended +{ + static int test() + { + int Error(0); + + { + int x = 2; + int y = 3; + int msb = 0; + int lsb = 0; + glm::imulExtended(x, y, msb, lsb); + + Error += msb == 0 ? 0 : 1; + Error += lsb == 6 ? 0 : 1; + } + + { + glm::ivec1 x(2); + glm::ivec1 y(3); + glm::ivec1 msb(0); + glm::ivec1 lsb(0); + glm::imulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::ivec1(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::ivec1(6))) ? 0 : 1; + } + + { + glm::ivec2 x(2); + glm::ivec2 y(3); + glm::ivec2 msb(0); + glm::ivec2 lsb(0); + glm::imulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::ivec2(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::ivec2(6))) ? 0 : 1; + } + + { + glm::ivec3 x(2); + glm::ivec3 y(3); + glm::ivec3 msb(0); + glm::ivec3 lsb(0); + glm::imulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::ivec3(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::ivec3(6))) ? 0 : 1; + } + + { + glm::ivec4 x(2); + glm::ivec4 y(3); + glm::ivec4 msb(0); + glm::ivec4 lsb(0); + glm::imulExtended(x, y, msb, lsb); + + Error += glm::all(glm::equal(msb, glm::ivec4(0))) ? 0 : 1; + Error += glm::all(glm::equal(lsb, glm::ivec4(6))) ? 0 : 1; + } + + return Error; + } +}//namespace imulExtended + +namespace bitCount +{ + template + struct type + { + genType Value; + genType Return; + }; + + type const DataI32[] = + { + {0x00000001, 1}, + {0x00000003, 2}, + {0x00000002, 1}, + {0x7fffffff, 31}, + {0x00000000, 0} + }; + + template + inline int bitCount_if(T v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitCount' only accept integer values"); + + int Count(0); + for(T i = 0, n = static_cast(sizeof(T) * 8); i < n; ++i) + { + if(v & static_cast(1 << i)) + ++Count; + } + return Count; + } + + template + inline int bitCount_vec(T v) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_integer, "'bitCount' only accept integer values"); + + int Count(0); + for(T i = 0, n = static_cast(sizeof(T) * 8); i < n; ++i) + { + Count += static_cast((v >> i) & static_cast(1)); + } + return Count; + } + + template + struct compute_bitfieldBitCountStep + { + template + GLM_FUNC_QUALIFIER static glm::vec call(glm::vec const& v, T, T) + { + return v; + } + }; + + template<> + struct compute_bitfieldBitCountStep + { + template + GLM_FUNC_QUALIFIER static glm::vec call(glm::vec const& v, T Mask, T Shift) + { + return (v & Mask) + ((v >> Shift) & Mask); + } + }; + + template + static glm::vec bitCount_bitfield(glm::vec const& v) + { + glm::vec::type, Q> x(*reinterpret_cast::type, Q> const *>(&v)); + x = compute_bitfieldBitCountStep= 2>::call(x, static_cast::type>(0x5555555555555555ull), static_cast::type>( 1)); + x = compute_bitfieldBitCountStep= 4>::call(x, static_cast::type>(0x3333333333333333ull), static_cast::type>( 2)); + x = compute_bitfieldBitCountStep= 8>::call(x, static_cast::type>(0x0F0F0F0F0F0F0F0Full), static_cast::type>( 4)); + x = compute_bitfieldBitCountStep= 16>::call(x, static_cast::type>(0x00FF00FF00FF00FFull), static_cast::type>( 8)); + x = compute_bitfieldBitCountStep= 32>::call(x, static_cast::type>(0x0000FFFF0000FFFFull), static_cast::type>(16)); + x = compute_bitfieldBitCountStep= 64>::call(x, static_cast::type>(0x00000000FFFFFFFFull), static_cast::type>(32)); + return glm::vec(x); + } + + template + static int bitCount_bitfield(genType x) + { + return bitCount_bitfield(glm::vec<1, genType, glm::defaultp>(x)).x; + } + + static int perf(std::size_t Size) + { + int Error(0); + + std::vector v; + v.resize(Size); + + std::vector w; + w.resize(Size); + + + std::clock_t TimestampsA = std::clock(); + + // bitCount - TimeIf + { + for(std::size_t i = 0, n = v.size(); i < n; ++i) + v[i] = bitCount_if(static_cast(i)); + } + + std::clock_t TimestampsB = std::clock(); + + // bitCount - TimeVec + { + for(std::size_t i = 0, n = v.size(); i < n; ++i) + v[i] = bitCount_vec(i); + } + + std::clock_t TimestampsC = std::clock(); + + // bitCount - TimeDefault + { + for(std::size_t i = 0, n = v.size(); i < n; ++i) + v[i] = glm::bitCount(i); + } + + std::clock_t TimestampsD = std::clock(); + + // bitCount - TimeVec4 + { + for(std::size_t i = 0, n = v.size(); i < n; ++i) + w[i] = glm::bitCount(glm::ivec4(static_cast(i))); + } + + std::clock_t TimestampsE = std::clock(); + + { + for(std::size_t i = 0, n = v.size(); i < n; ++i) + v[i] = bitCount_bitfield(static_cast(i)); + } + + std::clock_t TimestampsF = std::clock(); + + std::printf("bitCount - TimeIf %d\n", static_cast(TimestampsB - TimestampsA)); + std::printf("bitCount - TimeVec %d\n", static_cast(TimestampsC - TimestampsB)); + std::printf("bitCount - TimeDefault %d\n", static_cast(TimestampsD - TimestampsC)); + std::printf("bitCount - TimeVec4 %d\n", static_cast(TimestampsE - TimestampsD)); + std::printf("bitCount - bitfield %d\n", static_cast(TimestampsF - TimestampsE)); + + return Error; + } + + static int test() + { + int Error(0); + + for(std::size_t i = 0, n = sizeof(DataI32) / sizeof(type); i < n; ++i) + { + int ResultA = glm::bitCount(DataI32[i].Value); + int ResultB = bitCount_if(DataI32[i].Value); + int ResultC = bitCount_vec(DataI32[i].Value); + int ResultE = bitCount_bitfield(DataI32[i].Value); + + Error += DataI32[i].Return == ResultA ? 0 : 1; + Error += DataI32[i].Return == ResultB ? 0 : 1; + Error += DataI32[i].Return == ResultC ? 0 : 1; + Error += DataI32[i].Return == ResultE ? 0 : 1; + + assert(!Error); + } + + return Error; + } +}//bitCount + +int main() +{ + int Error = 0; + + Error += ::bitCount::test(); + Error += ::bitfieldReverse::test(); + Error += ::findMSB::test(); + Error += ::findLSB::test(); + Error += ::umulExtended::test(); + Error += ::imulExtended::test(); + Error += ::uaddCarry::test(); + Error += ::usubBorrow::test(); + Error += ::bitfieldInsert::test(); + Error += ::bitfieldExtract::test(); + +# ifdef NDEBUG + std::size_t const Samples = 1000; +# else + std::size_t const Samples = 1; +# endif + + ::bitCount::perf(Samples); + ::bitfieldReverse::perf(Samples); + ::findMSB::perf(Samples); + ::findLSB::perf(Samples); + + return Error; +} diff --git a/vendor/glm/test/core/core_func_integer_bit_count.cpp b/vendor/glm/test/core/core_func_integer_bit_count.cpp new file mode 100644 index 0000000..0fa11fb --- /dev/null +++ b/vendor/glm/test/core/core_func_integer_bit_count.cpp @@ -0,0 +1,291 @@ +// This has the programs for computing the number of 1-bits +// in a word, or byte, etc. +// Max line length is 57, to fit in hacker.book. +#include +#include //To define "exit", req'd by XLC. +#include + +unsigned rotatel(unsigned x, int n) +{ + if (static_cast(n) > 63) { std::printf("rotatel, n out of range.\n"); std::exit(1);} + return (x << n) | (x >> (32 - n)); +} + +int pop0(unsigned x) +{ + x = (x & 0x55555555) + ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F); + x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF); + x = (x & 0x0000FFFF) + ((x >>16) & 0x0000FFFF); + return x; +} + +int pop1(unsigned x) +{ + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x >> 8); + x = x + (x >> 16); + return x & 0x0000003F; +} +/* Note: an alternative to the last three executable lines above is: + return x*0x01010101 >> 24; +if your machine has a fast multiplier (suggested by Jari Kirma). */ + +int pop2(unsigned x) +{ + unsigned n; + + n = (x >> 1) & 033333333333; // Count bits in + x = x - n; // each 3-bit + n = (n >> 1) & 033333333333; // field. + x = x - n; + x = (x + (x >> 3)) & 030707070707; // 6-bit sums. + return x%63; // Add 6-bit sums. +} + +/* An alternative to the "return" statement above is: + return ((x * 0404040404) >> 26) + // Add 6-bit sums. + (x >> 30); +which runs faster on most machines (suggested by Norbert Juffa). */ + +int pop3(unsigned x) +{ + unsigned n; + + n = (x >> 1) & 0x77777777; // Count bits in + x = x - n; // each 4-bit + n = (n >> 1) & 0x77777777; // field. + x = x - n; + n = (n >> 1) & 0x77777777; + x = x - n; + x = (x + (x >> 4)) & 0x0F0F0F0F; // Get byte sums. + x = x*0x01010101; // Add the bytes. + return x >> 24; +} + +int pop4(unsigned x) +{ + int n; + + n = 0; + while (x != 0) { + n = n + 1; + x = x & (x - 1); + } + return n; +} + +int pop5(unsigned x) +{ + int i, sum; + + // Rotate and sum method // Shift right & subtract + + sum = x; // sum = x; + for (i = 1; i <= 31; i++) { // while (x != 0) { + x = rotatel(x, 1); // x = x >> 1; + sum = sum + x; // sum = sum - x; + } // } + return -sum; // return sum; +} + +int pop5a(unsigned x) +{ + int sum; + + // Shift right & subtract + + sum = x; + while (x != 0) { + x = x >> 1; + sum = sum - x; + } + return sum; +} + +int pop6(unsigned x) +{ // Table lookup. + static char table[256] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + + 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8}; + + return table[x & 0xFF] + + table[(x >> 8) & 0xFF] + + table[(x >> 16) & 0xFF] + + table[(x >> 24)]; +} + +// The following works only for 8-bit quantities. +int pop7(unsigned x) +{ + x = x*0x08040201; // Make 4 copies. + x = x >> 3; // So next step hits proper bits. + x = x & 0x11111111; // Every 4th bit. + x = x*0x11111111; // Sum the digits (each 0 or 1). + x = x >> 28; // Position the result. + return x; +} + +// The following works only for 7-bit quantities. +int pop8(unsigned x) +{ + x = x*0x02040810; // Make 4 copies, left-adjusted. + x = x & 0x11111111; // Every 4th bit. + x = x*0x11111111; // Sum the digits (each 0 or 1). + x = x >> 28; // Position the result. + return x; +} + +// The following works only for 15-bit quantities. +int pop9(unsigned x) +{ + unsigned long long y; + y = x * 0x0002000400080010ULL; + y = y & 0x1111111111111111ULL; + y = y * 0x1111111111111111ULL; + y = y >> 60; + return static_cast(y); +} + +int errors; +void error(int x, int y) +{ + errors = errors + 1; + std::printf("Error for x = %08x, got %08x\n", x, y); +} + +int main() +{ +# ifdef NDEBUG + + int i, n; + static unsigned test[] = {0,0, 1,1, 2,1, 3,2, 4,1, 5,2, 6,2, 7,3, + 8,1, 9,2, 10,2, 11,3, 12,2, 13,3, 14,3, 15,4, 16,1, 17,2, + 0x3F,6, 0x40,1, 0x41,2, 0x7f,7, 0x80,1, 0x81,2, 0xfe,7, 0xff,8, + 0x4000,1, 0x4001,2, 0x7000,3, 0x7fff,15, + 0x55555555,16, 0xAAAAAAAA, 16, 0xFF000000,8, 0xC0C0C0C0,8, + 0x0FFFFFF0,24, 0x80000000,1, 0xFFFFFFFF,32}; + + std::size_t const Count = 1000000; + + n = sizeof(test)/4; + + std::clock_t TimestampBeg = 0; + std::clock_t TimestampEnd = 0; + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop0(test[i]) != test[i+1]) error(test[i], pop0(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop0: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop1(test[i]) != test[i+1]) error(test[i], pop1(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop1: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop2(test[i]) != test[i+1]) error(test[i], pop2(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop2: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop3(test[i]) != test[i+1]) error(test[i], pop3(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop3: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop4(test[i]) != test[i+1]) error(test[i], pop4(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop4: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop5(test[i]) != test[i+1]) error(test[i], pop5(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop5: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop5a(test[i]) != test[i+1]) error(test[i], pop5a(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop5a: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (pop6(test[i]) != test[i+1]) error(test[i], pop6(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop6: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if ((test[i] & 0xffffff00) == 0) + if (pop7(test[i]) != test[i+1]) error(test[i], pop7(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop7: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if ((test[i] & 0xffffff80) == 0) + if (pop8(test[i]) != test[i+1]) error(test[i], pop8(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop8: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if ((test[i] & 0xffff8000) == 0) + if (pop9(test[i]) != test[i+1]) error(test[i], pop9(test[i]));} + TimestampEnd = std::clock(); + + std::printf("pop9: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + if (errors == 0) + std::printf("Passed all %d cases.\n", static_cast(sizeof(test)/8)); + +# endif//NDEBUG +} diff --git a/vendor/glm/test/core/core_func_integer_find_lsb.cpp b/vendor/glm/test/core/core_func_integer_find_lsb.cpp new file mode 100644 index 0000000..7b42d33 --- /dev/null +++ b/vendor/glm/test/core/core_func_integer_find_lsb.cpp @@ -0,0 +1,416 @@ +#include +#include +#include //To define "exit", req'd by XLC. +#include + +int nlz(unsigned x) +{ + int pop(unsigned x); + + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return pop(~x); +} + +int pop(unsigned x) +{ + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x << 8); + x = x + (x << 16); + return x >> 24; +} + +int ntz1(unsigned x) +{ + return 32 - nlz(~x & (x-1)); +} + +int ntz2(unsigned x) +{ + return pop(~x & (x - 1)); +} + +int ntz3(unsigned x) +{ + int n; + + if (x == 0) return(32); + n = 1; + if ((x & 0x0000FFFF) == 0) {n = n +16; x = x >>16;} + if ((x & 0x000000FF) == 0) {n = n + 8; x = x >> 8;} + if ((x & 0x0000000F) == 0) {n = n + 4; x = x >> 4;} + if ((x & 0x00000003) == 0) {n = n + 2; x = x >> 2;} + return n - (x & 1); +} + +int ntz4(unsigned x) +{ + unsigned y; + int n; + + if (x == 0) return 32; + n = 31; + y = x <<16; if (y != 0) {n = n -16; x = y;} + y = x << 8; if (y != 0) {n = n - 8; x = y;} + y = x << 4; if (y != 0) {n = n - 4; x = y;} + y = x << 2; if (y != 0) {n = n - 2; x = y;} + y = x << 1; if (y != 0) {n = n - 1;} + return n; +} + +int ntz4a(unsigned x) +{ + unsigned y; + int n; + + if (x == 0) return 32; + n = 31; + y = x <<16; if (y != 0) {n = n -16; x = y;} + y = x << 8; if (y != 0) {n = n - 8; x = y;} + y = x << 4; if (y != 0) {n = n - 4; x = y;} + y = x << 2; if (y != 0) {n = n - 2; x = y;} + n = n - ((x << 1) >> 31); + return n; +} + +int ntz5(char x) +{ + if (x & 15) { + if (x & 3) { + if (x & 1) return 0; + else return 1; + } + else if (x & 4) return 2; + else return 3; + } + else if (x & 0x30) { + if (x & 0x10) return 4; + else return 5; + } + else if (x & 0x40) return 6; + else if (x) return 7; + else return 8; +} + +int ntz6(unsigned x) +{ + int n; + + x = ~x & (x - 1); + n = 0; // n = 32; + while(x != 0) + { // while (x != 0) { + n = n + 1; // n = n - 1; + x = x >> 1; // x = x + x; + } // } + return n; // return n; +} + +int ntz6a(unsigned x) +{ + int n = 32; + + while (x != 0) { + n = n - 1; + x = x + x; + } + return n; +} + +/* Dean Gaudet's algorithm. To be most useful there must be a good way +to evaluate the C "conditional expression" (a?b:c construction) without +branching. The result of a?b:c is b if a is true (nonzero), and c if a +is false (0). + For example, a compare to zero op that sets a target GPR to 1 if the +operand is 0, and to 0 if the operand is nonzero, will do it. With this +instruction, the algorithm is entirely branch-free. But the most +interesting thing about it is the high degree of parallelism. All six +lines with conditional expressions can be executed in parallel (on a +machine with sufficient computational units). + Although the instruction count is 30 measured statically, it could +execute in only 10 cycles on a machine with sufficient parallelism. + The first two uses of y can instead be x, which would increase the +useful parallelism on most machines (the assignments to y, bz, and b4 +could then all run in parallel). */ + +int ntz7(unsigned x) +{ + unsigned y, bz, b4, b3, b2, b1, b0; + + y = x & -x; // Isolate rightmost 1-bit. + bz = y ? 0 : 1; // 1 if y = 0. + b4 = (y & 0x0000FFFF) ? 0 : 16; + b3 = (y & 0x00FF00FF) ? 0 : 8; + b2 = (y & 0x0F0F0F0F) ? 0 : 4; + b1 = (y & 0x33333333) ? 0 : 2; + b0 = (y & 0x55555555) ? 0 : 1; + return bz + b4 + b3 + b2 + b1 + b0; +} + +// This file has divisions by zero to test isnan +#if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(disable : 4800) +#endif + +int ntz7_christophe(unsigned x) +{ + unsigned y, bz, b4, b3, b2, b1, b0; + + y = x & -x; // Isolate rightmost 1-bit. + bz = unsigned(!bool(y)); // 1 if y = 0. + b4 = unsigned(!bool(y & 0x0000FFFF)) * 16; + b3 = unsigned(!bool(y & 0x00FF00FF)) * 8; + b2 = unsigned(!bool(y & 0x0F0F0F0F)) * 4; + b1 = unsigned(!bool(y & 0x33333333)) * 2; + b0 = unsigned(!bool(y & 0x55555555)) * 1; + return bz + b4 + b3 + b2 + b1 + b0; +} + +/* Below is David Seal's algorithm, found at +http://www.ciphersbyritter.com/NEWS4/BITCT.HTM Table +entries marked "u" are unused. 6 ops including a +multiply, plus an indexed load. */ + +#define u 99 +int ntz8(unsigned x) +{ + static char table[64] = + {32, 0, 1,12, 2, 6, u,13, 3, u, 7, u, u, u, u,14, + 10, 4, u, u, 8, u, u,25, u, u, u, u, u,21,27,15, + 31,11, 5, u, u, u, u, u, 9, u, u,24, u, u,20,26, + 30, u, u, u, u,23, u,19, 29, u,22,18,28,17,16, u}; + + x = (x & -x)*0x0450FBAF; + return table[x >> 26]; +} + +/* Seal's algorithm with multiply expanded. +9 elementary ops plus an indexed load. */ + +int ntz8a(unsigned x) +{ + static char table[64] = + {32, 0, 1,12, 2, 6, u,13, 3, u, 7, u, u, u, u,14, + 10, 4, u, u, 8, u, u,25, u, u, u, u, u,21,27,15, + 31,11, 5, u, u, u, u, u, 9, u, u,24, u, u,20,26, + 30, u, u, u, u,23, u,19, 29, u,22,18,28,17,16, u}; + + x = (x & -x); + x = (x << 4) + x; // x = x*17. + x = (x << 6) + x; // x = x*65. + x = (x << 16) - x; // x = x*65535. + return table[x >> 26]; +} + +/* Reiser's algorithm. Three ops including a "remainder," +plus an indexed load. */ + +int ntz9(unsigned x) +{ + static char table[37] = { + 32, 0, 1, 26, 2, 23, 27, + u, 3, 16, 24, 30, 28, 11, u, 13, 4, + 7, 17, u, 25, 22, 31, 15, 29, 10, 12, + 6, u, 21, 14, 9, 5, 20, 8, 19, 18}; + + x = (x & -x)%37; + return table[x]; +} + +/* Using a de Bruijn sequence. This is a table lookup with a 32-entry +table. The de Bruijn sequence used here is + 0000 0100 1101 0111 0110 0101 0001 1111, +obtained from Danny Dube's October 3, 1997, posting in +comp.compression.research. Thanks to Norbert Juffa for this reference. */ + +int ntz10(unsigned x) { + + static char table[32] = + { 0, 1, 2,24, 3,19, 6,25, 22, 4,20,10,16, 7,12,26, + 31,23,18, 5,21, 9,15,11, 30,17, 8,14,29,13,28,27}; + + if (x == 0) return 32; + x = (x & -x)*0x04D7651F; + return table[x >> 27]; +} + +/* Norbert Juffa's code, answer to exercise 1 of Chapter 5 (2nd ed). */ + +#define SLOW_MUL +int ntz11 (unsigned int n) { + + static unsigned char tab[32] = + { 0, 1, 2, 24, 3, 19, 6, 25, + 22, 4, 20, 10, 16, 7, 12, 26, + 31, 23, 18, 5, 21, 9, 15, 11, + 30, 17, 8, 14, 29, 13, 28, 27 + }; + unsigned int k; + n = n & (-n); /* isolate lsb */ + printf("n = %d\n", n); +#if defined(SLOW_MUL) + k = (n << 11) - n; + k = (k << 2) + k; + k = (k << 8) + n; + k = (k << 5) - k; +#else + k = n * 0x4d7651f; +#endif + return n ? tab[k>>27] : 32; +} + +int errors; +void error(int x, int y) { + errors = errors + 1; + std::printf("Error for x = %08x, got %d\n", x, y); +} + +int main() +{ +# ifdef NDEBUG + + int i, m, n; + static unsigned test[] = {0,32, 1,0, 2,1, 3,0, 4,2, 5,0, 6,1, 7,0, + 8,3, 9,0, 16,4, 32,5, 64,6, 128,7, 255,0, 256,8, 512,9, 1024,10, + 2048,11, 4096,12, 8192,13, 16384,14, 32768,15, 65536,16, + 0x20000,17, 0x40000,18, 0x80000,19, 0x100000,20, 0x200000,21, + 0x400000,22, 0x800000,23, 0x1000000,24, 0x2000000,25, + 0x4000000,26, 0x8000000,27, 0x10000000,28, 0x20000000,29, + 0x40000000,30, 0x80000000,31, 0xFFFFFFF0,4, 0x3000FF00,8, + 0xC0000000,30, 0x60000000,29, 0x00011000, 12}; + + std::size_t const Count = 1000; + + n = sizeof(test)/4; + + std::clock_t TimestampBeg = 0; + std::clock_t TimestampEnd = 0; + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz1(test[i]) != test[i+1]) error(test[i], ntz1(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz1: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz2(test[i]) != test[i+1]) error(test[i], ntz2(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz2: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz3(test[i]) != test[i+1]) error(test[i], ntz3(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz3: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz4(test[i]) != test[i+1]) error(test[i], ntz4(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz4: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz4a(test[i]) != test[i+1]) error(test[i], ntz4a(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz4a: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for(std::size_t k = 0; k < Count; ++k) + for(i = 0; i < n; i += 2) + { + m = test[i+1]; + if(m > 8) + m = 8; + if(ntz5(static_cast(test[i])) != m) + error(test[i], ntz5(static_cast(test[i]))); + } + TimestampEnd = std::clock(); + + std::printf("ntz5: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz6(test[i]) != test[i+1]) error(test[i], ntz6(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz6: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz6a(test[i]) != test[i+1]) error(test[i], ntz6a(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz6a: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz7(test[i]) != test[i+1]) error(test[i], ntz7(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz7: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz7_christophe(test[i]) != test[i+1]) error(test[i], ntz7(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz7_christophe: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz8(test[i]) != test[i+1]) error(test[i], ntz8(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz8: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz8a(test[i]) != test[i+1]) error(test[i], ntz8a(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz8a: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz9(test[i]) != test[i+1]) error(test[i], ntz9(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz9: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (ntz10(test[i]) != test[i+1]) error(test[i], ntz10(test[i]));} + TimestampEnd = std::clock(); + + std::printf("ntz10: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + if (errors == 0) + std::printf("Passed all %d cases.\n", static_cast(sizeof(test)/8)); + +# endif//NDEBUG +} diff --git a/vendor/glm/test/core/core_func_integer_find_msb.cpp b/vendor/glm/test/core/core_func_integer_find_msb.cpp new file mode 100644 index 0000000..c435467 --- /dev/null +++ b/vendor/glm/test/core/core_func_integer_find_msb.cpp @@ -0,0 +1,440 @@ +#include +#include +#include // To define "exit", req'd by XLC. +#include + +#define LE 1 // 1 for little-endian, 0 for big-endian. + +int pop(unsigned x) { + x = x - ((x >> 1) & 0x55555555); + x = (x & 0x33333333) + ((x >> 2) & 0x33333333); + x = (x + (x >> 4)) & 0x0F0F0F0F; + x = x + (x << 8); + x = x + (x << 16); + return x >> 24; +} + +int nlz1(unsigned x) { + int n; + + if (x == 0) return(32); + n = 0; + if (x <= 0x0000FFFF) {n = n +16; x = x <<16;} + if (x <= 0x00FFFFFF) {n = n + 8; x = x << 8;} + if (x <= 0x0FFFFFFF) {n = n + 4; x = x << 4;} + if (x <= 0x3FFFFFFF) {n = n + 2; x = x << 2;} + if (x <= 0x7FFFFFFF) {n = n + 1;} + return n; +} + +int nlz1a(unsigned x) { + int n; + +/* if (x == 0) return(32); */ + if (static_cast(x) <= 0) return (~x >> 26) & 32; + n = 1; + if ((x >> 16) == 0) {n = n +16; x = x <<16;} + if ((x >> 24) == 0) {n = n + 8; x = x << 8;} + if ((x >> 28) == 0) {n = n + 4; x = x << 4;} + if ((x >> 30) == 0) {n = n + 2; x = x << 2;} + n = n - (x >> 31); + return n; +} +// On basic Risc, 12 to 20 instructions. + +int nlz2(unsigned x) { + unsigned y; + int n; + + n = 32; + y = x >>16; if (y != 0) {n = n -16; x = y;} + y = x >> 8; if (y != 0) {n = n - 8; x = y;} + y = x >> 4; if (y != 0) {n = n - 4; x = y;} + y = x >> 2; if (y != 0) {n = n - 2; x = y;} + y = x >> 1; if (y != 0) return n - 2; + return n - x; +} + +// As above but coded as a loop for compactness: +// 23 to 33 basic Risc instructions. +int nlz2a(unsigned x) { + unsigned y; + int n, c; + + n = 32; + c = 16; + do { + y = x >> c; if (y != 0) {n = n - c; x = y;} + c = c >> 1; + } while (c != 0); + return n - x; +} + +int nlz3(int x) { + int y, n; + + n = 0; + y = x; +L: if (x < 0) return n; + if (y == 0) return 32 - n; + n = n + 1; + x = x << 1; + y = y >> 1; + goto L; +} + +int nlz4(unsigned x) { + int y, m, n; + + y = -(x >> 16); // If left half of x is 0, + m = (y >> 16) & 16; // set n = 16. If left half + n = 16 - m; // is nonzero, set n = 0 and + x = x >> m; // shift x right 16. + // Now x is of the form 0000xxxx. + y = x - 0x100; // If positions 8-15 are 0, + m = (y >> 16) & 8; // add 8 to n and shift x left 8. + n = n + m; + x = x << m; + + y = x - 0x1000; // If positions 12-15 are 0, + m = (y >> 16) & 4; // add 4 to n and shift x left 4. + n = n + m; + x = x << m; + + y = x - 0x4000; // If positions 14-15 are 0, + m = (y >> 16) & 2; // add 2 to n and shift x left 2. + n = n + m; + x = x << m; + + y = x >> 14; // Set y = 0, 1, 2, or 3. + m = y & ~(y >> 1); // Set m = 0, 1, 2, or 2 resp. + return n + 2 - m; +} + +int nlz5(unsigned x) { + int pop(unsigned x); + + x = x | (x >> 1); + x = x | (x >> 2); + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + return pop(~x); +} + +/* The four programs below are not valid ANSI C programs. This is +because they refer to the same storage locations as two different types. +However, they work with xlc/AIX, gcc/AIX, and gcc/NT. If you try to +code them more compactly by declaring a variable xx to be "double," and +then using + + n = 1054 - (*((unsigned *)&xx + LE) >> 20); + +then you are violating not only the rule above, but also the ANSI C +rule that pointer arithmetic can be performed only on pointers to +array elements. + When coded with the above statement, the program fails with xlc, +gcc/AIX, and gcc/NT, at some optimization levels. + BTW, these programs use the "anonymous union" feature of C++, not +available in C. */ + +int nlz6(unsigned k) +{ + union { + unsigned asInt[2]; + double asDouble; + }; + int n; + + asDouble = static_cast(k) + 0.5; + n = 1054 - (asInt[LE] >> 20); + return n; +} + +int nlz7(unsigned k) +{ + union { + unsigned asInt[2]; + double asDouble; + }; + int n; + + asDouble = static_cast(k); + n = 1054 - (asInt[LE] >> 20); + n = (n & 31) + (n >> 9); + return n; +} + + /* In single qualifier, round-to-nearest mode, the basic method fails for: + k = 0, k = 01FFFFFF, 03FFFFFE <= k <= 03FFFFFF, + 07FFFFFC <= k <= 07FFFFFF, + 0FFFFFF8 <= k <= 0FFFFFFF, + ... + 7FFFFFC0 <= k <= 7FFFFFFF. + FFFFFF80 <= k <= FFFFFFFF. + For k = 0 it gives 158, and for the other values it is too low by 1. */ + +int nlz8(unsigned k) +{ + union { + unsigned asInt; + float asFloat; + }; + int n; + + k = k & ~(k >> 1); /* Fix problem with rounding. */ + asFloat = static_cast(k) + 0.5f; + n = 158 - (asInt >> 23); + return n; +} + +/* The example below shows how to make a macro for nlz. It uses an +extension to the C and C++ languages that is provided by the GNU C/C++ +compiler, namely, that of allowing statements and declarations in +expressions (see "Using and Porting GNU CC", by Richard M. Stallman +(1998). The underscores are necessary to protect against the +possibility that the macro argument will conflict with one of its local +variables, e.g., NLZ(k). */ + +int nlz9(unsigned k) +{ + union { + unsigned asInt; + float asFloat; + }; + int n; + + k = k & ~(k >> 1); /* Fix problem with rounding. */ + asFloat = static_cast(k); + n = 158 - (asInt >> 23); + n = (n & 31) + (n >> 6); /* Fix problem with k = 0. */ + return n; +} + +/* Below are three nearly equivalent programs for computing the number +of leading zeros in a word. This material is not in HD, but may be in a +future edition. + Immediately below is Robert Harley's algorithm, found at the +comp.arch newsgroup entry dated 7/12/96, pointed out to me by Norbert +Juffa. + Table entries marked "u" are unused. 14 ops including a multiply, +plus an indexed load. + The smallest multiplier that works is 0x045BCED1 = 17*65*129*513 (all +of form 2**k + 1). There are no multipliers of three terms of the form +2**k +- 1 that work, with a table size of 64 or 128. There are some, +with a table size of 64, if you precede the multiplication with x = x - +(x >> 1), but that seems less elegant. There are also some if you use a +table size of 256, the smallest is 0x01033CBF = 65*255*1025 (this would +save two instructions in the form of this algorithm with the +multiplication expanded into shifts and adds, but the table size is +getting a bit large). */ + +#define u 99 +int nlz10(unsigned x) +{ + static char table[64] = + {32,31, u,16, u,30, 3, u, 15, u, u, u,29,10, 2, u, + u, u,12,14,21, u,19, u, u,28, u,25, u, 9, 1, u, + 17, u, 4, u, u, u,11, u, 13,22,20, u,26, u, u,18, + 5, u, u,23, u,27, u, 6, u,24, 7, u, 8, u, 0, u}; + + x = x | (x >> 1); // Propagate leftmost + x = x | (x >> 2); // 1-bit to the right. + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >>16); + x = x*0x06EB14F9; // Multiplier is 7*255**3. + return table[x >> 26]; +} + +/* Harley's algorithm with multiply expanded. +19 elementary ops plus an indexed load. */ + +int nlz10a(unsigned x) +{ + static char table[64] = + {32,31, u,16, u,30, 3, u, 15, u, u, u,29,10, 2, u, + u, u,12,14,21, u,19, u, u,28, u,25, u, 9, 1, u, + 17, u, 4, u, u, u,11, u, 13,22,20, u,26, u, u,18, + 5, u, u,23, u,27, u, 6, u,24, 7, u, 8, u, 0, u}; + + x = x | (x >> 1); // Propagate leftmost + x = x | (x >> 2); // 1-bit to the right. + x = x | (x >> 4); + x = x | (x >> 8); + x = x | (x >> 16); + x = (x << 3) - x; // Multiply by 7. + x = (x << 8) - x; // Multiply by 255. + x = (x << 8) - x; // Again. + x = (x << 8) - x; // Again. + return table[x >> 26]; +} + +/* Julius Goryavsky's version of Harley's algorithm. +17 elementary ops plus an indexed load, if the machine +has "and not." */ + +int nlz10b(unsigned x) +{ + static char table[64] = + {32,20,19, u, u,18, u, 7, 10,17, u, u,14, u, 6, u, + u, 9, u,16, u, u, 1,26, u,13, u, u,24, 5, u, u, + u,21, u, 8,11, u,15, u, u, u, u, 2,27, 0,25, u, + 22, u,12, u, u, 3,28, u, 23, u, 4,29, u, u,30,31}; + + x = x | (x >> 1); // Propagate leftmost + x = x | (x >> 2); // 1-bit to the right. + x = x | (x >> 4); + x = x | (x >> 8); + x = x & ~(x >> 16); + x = x*0xFD7049FF; // Activate this line or the following 3. + // x = (x << 9) - x; // Multiply by 511. + // x = (x << 11) - x; // Multiply by 2047. + // x = (x << 14) - x; // Multiply by 16383. + return table[x >> 26]; +} + +int errors; +void error(int x, int y) +{ + errors = errors + 1; + std::printf("Error for x = %08x, got %d\n", x, y); +} + +int main() +{ +# ifdef NDEBUG + + int i, n; + static unsigned test[] = {0,32, 1,31, 2,30, 3,30, 4,29, 5,29, 6,29, + 7,29, 8,28, 9,28, 16,27, 32,26, 64,25, 128,24, 255,24, 256,23, + 512,22, 1024,21, 2048,20, 4096,19, 8192,18, 16384,17, 32768,16, + 65536,15, 0x20000,14, 0x40000,13, 0x80000,12, 0x100000,11, + 0x200000,10, 0x400000,9, 0x800000,8, 0x1000000,7, 0x2000000,6, + 0x4000000,5, 0x8000000,4, 0x0FFFFFFF,4, 0x10000000,3, + 0x3000FFFF,2, 0x50003333,1, 0x7FFFFFFF,1, 0x80000000,0, + 0xFFFFFFFF,0}; + std::size_t const Count = 1000; + + n = sizeof(test)/4; + + std::clock_t TimestampBeg = 0; + std::clock_t TimestampEnd = 0; + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz1(test[i]) != test[i+1]) error(test[i], nlz1(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz1: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz1a(test[i]) != test[i+1]) error(test[i], nlz1a(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz1a: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz2(test[i]) != test[i+1]) error(test[i], nlz2(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz2: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz2a(test[i]) != test[i+1]) error(test[i], nlz2a(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz2a: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz3(test[i]) != test[i+1]) error(test[i], nlz3(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz3: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz4(test[i]) != test[i+1]) error(test[i], nlz4(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz4: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz5(test[i]) != test[i+1]) error(test[i], nlz5(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz5: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz6(test[i]) != test[i+1]) error(test[i], nlz6(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz6: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz7(test[i]) != test[i+1]) error(test[i], nlz7(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz7: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz8(test[i]) != test[i+1]) error(test[i], nlz8(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz8: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz9(test[i]) != test[i+1]) error(test[i], nlz9(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz9: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz10(test[i]) != test[i+1]) error(test[i], nlz10(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz10: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz10a(test[i]) != test[i+1]) error(test[i], nlz10a(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz10a: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + TimestampBeg = std::clock(); + for (std::size_t k = 0; k < Count; ++k) + for (i = 0; i < n; i += 2) { + if (nlz10b(test[i]) != test[i+1]) error(test[i], nlz10b(test[i]));} + TimestampEnd = std::clock(); + + std::printf("nlz10b: %d clocks\n", static_cast(TimestampEnd - TimestampBeg)); + + if (errors == 0) + std::printf("Passed all %d cases.\n", static_cast(sizeof(test)/8)); + +# endif//NDEBUG +} diff --git a/vendor/glm/test/core/core_func_matrix.cpp b/vendor/glm/test/core/core_func_matrix.cpp new file mode 100644 index 0000000..60513d0 --- /dev/null +++ b/vendor/glm/test/core/core_func_matrix.cpp @@ -0,0 +1,329 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace glm; + +int test_matrixCompMult() +{ + int Error(0); + + { + mat2 m(0, 1, 2, 3); + mat2 n = matrixCompMult(m, m); + mat2 expected = mat2(0, 1, 4, 9); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat2x3 m(0, 1, 2, 3, 4, 5); + mat2x3 n = matrixCompMult(m, m); + mat2x3 expected = mat2x3(0, 1, 4, 9, 16, 25); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat2x4 m(0, 1, 2, 3, 4, 5, 6, 7); + mat2x4 n = matrixCompMult(m, m); + mat2x4 expected = mat2x4(0, 1, 4, 9, 16, 25, 36, 49); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat3 m(0, 1, 2, 3, 4, 5, 6, 7, 8); + mat3 n = matrixCompMult(m, m); + mat3 expected = mat3(0, 1, 4, 9, 16, 25, 36, 49, 64); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat3x2 m(0, 1, 2, 3, 4, 5); + mat3x2 n = matrixCompMult(m, m); + mat3x2 expected = mat3x2(0, 1, 4, 9, 16, 25); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat3x4 m(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + mat3x4 n = matrixCompMult(m, m); + mat3x4 expected = mat3x4(0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat4 m(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + mat4 n = matrixCompMult(m, m); + mat4 expected = mat4(0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat4x2 m(0, 1, 2, 3, 4, 5, 6, 7); + mat4x2 n = matrixCompMult(m, m); + mat4x2 expected = mat4x2(0, 1, 4, 9, 16, 25, 36, 49); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat4x3 m(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + mat4x3 n = matrixCompMult(m, m); + mat4x3 expected = mat4x3(0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121); + for (length_t l = 0; l < m.length(); ++l) + Error += all(epsilonEqual(n[l], expected[l], epsilon())) ? 0 : 1; + } + + return Error; +} + +int test_outerProduct() +{ + { glm::mat2 m = glm::outerProduct(glm::vec2(1.0f), glm::vec2(1.0f)); } + { glm::mat3 m = glm::outerProduct(glm::vec3(1.0f), glm::vec3(1.0f)); } + { glm::mat4 m = glm::outerProduct(glm::vec4(1.0f), glm::vec4(1.0f)); } + + { glm::mat2x3 m = glm::outerProduct(glm::vec3(1.0f), glm::vec2(1.0f)); } + { glm::mat2x4 m = glm::outerProduct(glm::vec4(1.0f), glm::vec2(1.0f)); } + + { glm::mat3x2 m = glm::outerProduct(glm::vec2(1.0f), glm::vec3(1.0f)); } + { glm::mat3x4 m = glm::outerProduct(glm::vec4(1.0f), glm::vec3(1.0f)); } + + { glm::mat4x2 m = glm::outerProduct(glm::vec2(1.0f), glm::vec4(1.0f)); } + { glm::mat4x3 m = glm::outerProduct(glm::vec3(1.0f), glm::vec4(1.0f)); } + + return 0; +} + +int test_transpose() +{ + int Error(0); + + { + mat2 const m(0, 1, 2, 3); + mat2 const t = transpose(m); + mat2 const expected = mat2(0, 2, 1, 3); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat2x3 m(0, 1, 2, 3, 4, 5); + mat3x2 t = transpose(m); + mat3x2 const expected = mat3x2(0, 3, 1, 4, 2, 5); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat2x4 m(0, 1, 2, 3, 4, 5, 6, 7); + mat4x2 t = transpose(m); + mat4x2 const expected = mat4x2(0, 4, 1, 5, 2, 6, 3, 7); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat3 m(0, 1, 2, 3, 4, 5, 6, 7, 8); + mat3 t = transpose(m); + mat3 const expected = mat3(0, 3, 6, 1, 4, 7, 2, 5, 8); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat3x2 m(0, 1, 2, 3, 4, 5); + mat2x3 t = transpose(m); + mat2x3 const expected = mat2x3(0, 2, 4, 1, 3, 5); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat3x4 m(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + mat4x3 t = transpose(m); + mat4x3 const expected = mat4x3(0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat4 m(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + mat4 t = transpose(m); + mat4 const expected = mat4(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat4x2 m(0, 1, 2, 3, 4, 5, 6, 7); + mat2x4 t = transpose(m); + mat2x4 const expected = mat2x4(0, 2, 4, 6, 1, 3, 5, 7); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + { + mat4x3 m(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + mat3x4 t = transpose(m); + mat3x4 const expected = mat3x4(0, 3, 6, 9, 1, 4, 7, 10, 2, 5, 8, 11); + for (length_t l = 0; l < expected.length(); ++l) + Error += all(epsilonEqual(t[l], expected[l], epsilon())) ? 0 : 1; + } + + return Error; +} + +int test_determinant() +{ + + + return 0; +} + +int test_inverse() +{ + int Error = 0; + + { + glm::mat4x4 A4x4( + glm::vec4(1, 0, 1, 0), + glm::vec4(0, 1, 0, 0), + glm::vec4(0, 0, 1, 0), + glm::vec4(0, 0, 0, 1)); + glm::mat4x4 B4x4 = inverse(A4x4); + glm::mat4x4 I4x4 = A4x4 * B4x4; + glm::mat4x4 Identity(1); + for (length_t l = 0; l < Identity.length(); ++l) + Error += all(epsilonEqual(I4x4[l], Identity[l], epsilon())) ? 0 : 1; + } + + { + glm::mat3x3 A3x3( + glm::vec3(1, 0, 1), + glm::vec3(0, 1, 0), + glm::vec3(0, 0, 1)); + glm::mat3x3 B3x3 = glm::inverse(A3x3); + glm::mat3x3 I3x3 = A3x3 * B3x3; + glm::mat3x3 Identity(1); + for (length_t l = 0; l < Identity.length(); ++l) + Error += all(epsilonEqual(I3x3[l], Identity[l], epsilon())) ? 0 : 1; + } + + { + glm::mat2x2 A2x2( + glm::vec2(1, 1), + glm::vec2(0, 1)); + glm::mat2x2 B2x2 = glm::inverse(A2x2); + glm::mat2x2 I2x2 = A2x2 * B2x2; + glm::mat2x2 Identity(1); + for (length_t l = 0; l < Identity.length(); ++l) + Error += all(epsilonEqual(I2x2[l], Identity[l], epsilon())) ? 0 : 1; + } + + return Error; +} + +int test_inverse_simd() +{ + int Error = 0; + + glm::mat4x4 const Identity(1); + + glm::mat4x4 const A4x4( + glm::vec4(1, 0, 1, 0), + glm::vec4(0, 1, 0, 0), + glm::vec4(0, 0, 1, 0), + glm::vec4(0, 0, 0, 1)); + glm::mat4x4 const B4x4 = glm::inverse(A4x4); + glm::mat4x4 const I4x4 = A4x4 * B4x4; + + Error += glm::all(glm::epsilonEqual(I4x4[0], Identity[0], 0.001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(I4x4[1], Identity[1], 0.001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(I4x4[2], Identity[2], 0.001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(I4x4[3], Identity[3], 0.001f)) ? 0 : 1; + + return Error; +} + +template +int test_inverse_perf(std::size_t Count, std::size_t Instance, char const * Message) +{ + std::vector TestInputs; + TestInputs.resize(Count); + std::vector TestOutputs; + TestOutputs.resize(TestInputs.size()); + + VEC3 Axis(glm::normalize(VEC3(1.0f, 2.0f, 3.0f))); + + for(std::size_t i = 0; i < TestInputs.size(); ++i) + { + typename MAT4::value_type f = static_cast(i + Instance) * typename MAT4::value_type(0.1) + typename MAT4::value_type(0.1); + TestInputs[i] = glm::rotate(glm::translate(MAT4(1), Axis * f), f, Axis); + //TestInputs[i] = glm::translate(MAT4(1), Axis * f); + } + + std::clock_t StartTime = std::clock(); + + for(std::size_t i = 0; i < TestInputs.size(); ++i) + TestOutputs[i] = glm::inverse(TestInputs[i]); + + std::clock_t EndTime = std::clock(); + + for(std::size_t i = 0; i < TestInputs.size(); ++i) + TestOutputs[i] = TestOutputs[i] * TestInputs[i]; + + typename MAT4::value_type Diff(0); + for(std::size_t Entry = 0; Entry < TestOutputs.size(); ++Entry) + { + MAT4 i(1.0); + MAT4 m(TestOutputs[Entry]); + for(glm::length_t y = 0; y < m.length(); ++y) + for(glm::length_t x = 0; x < m[y].length(); ++x) + Diff = glm::max(m[y][x], i[y][x]); + } + + //glm::uint Ulp = 0; + //Ulp = glm::max(glm::float_distance(*Dst, *Src), Ulp); + + std::printf("inverse<%s>(%f): %lu\n", Message, static_cast(Diff), EndTime - StartTime); + + return 0; +} + +int main() +{ + int Error = 0; + Error += test_matrixCompMult(); + Error += test_outerProduct(); + Error += test_transpose(); + Error += test_determinant(); + Error += test_inverse(); + Error += test_inverse_simd(); + +# ifdef NDEBUG + std::size_t const Samples = 1000; +# else + std::size_t const Samples = 1; +# endif//NDEBUG + + for(std::size_t i = 0; i < 1; ++i) + { + Error += test_inverse_perf(Samples, i, "mat4"); + Error += test_inverse_perf(Samples, i, "dmat4"); + } + + return Error; +} + diff --git a/vendor/glm/test/core/core_func_noise.cpp b/vendor/glm/test/core/core_func_noise.cpp new file mode 100644 index 0000000..4f0b430 --- /dev/null +++ b/vendor/glm/test/core/core_func_noise.cpp @@ -0,0 +1,7 @@ +int main() +{ + int Error = 0; + + return Error; +} + diff --git a/vendor/glm/test/core/core_func_packing.cpp b/vendor/glm/test/core/core_func_packing.cpp new file mode 100644 index 0000000..c3cd14a --- /dev/null +++ b/vendor/glm/test/core/core_func_packing.cpp @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include + +int test_packUnorm2x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.0f)); + A.push_back(glm::vec2(0.5f, 0.7f)); + A.push_back(glm::vec2(0.1f, 0.2f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint32 C = glm::packUnorm2x16(B); + glm::vec2 D = glm::unpackUnorm2x16(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 65535.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm2x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2( 1.0f, 0.0f)); + A.push_back(glm::vec2(-0.5f,-0.7f)); + A.push_back(glm::vec2(-0.1f, 0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint32 C = glm::packSnorm2x16(B); + glm::vec2 D = glm::unpackSnorm2x16(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 32767.0f * 2.0f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm4x8() +{ + int Error = 0; + + glm::uint32 Packed = glm::packUnorm4x8(glm::vec4(1.0f, 0.5f, 0.0f, 1.0f)); + glm::u8vec4 Vec(255, 128, 0, 255); + glm::uint32 & Ref = *reinterpret_cast(&Vec[0]); + + Error += Packed == Ref ? 0 : 1; + + std::vector A; + A.push_back(glm::vec4(1.0f, 0.7f, 0.3f, 0.0f)); + A.push_back(glm::vec4(0.5f, 0.1f, 0.2f, 0.3f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint32 C = glm::packUnorm4x8(B); + glm::vec4 D = glm::unpackUnorm4x8(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 255.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm4x8() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec4( 1.0f, 0.0f,-0.5f,-1.0f)); + A.push_back(glm::vec4(-0.7f,-0.1f, 0.1f, 0.7f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint32 C = glm::packSnorm4x8(B); + glm::vec4 D = glm::unpackSnorm4x8(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 127.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packHalf2x16() +{ + int Error = 0; +/* + std::vector A; + A.push_back(glm::hvec2(glm::half( 1.0f), glm::half( 2.0f))); + A.push_back(glm::hvec2(glm::half(-1.0f), glm::half(-2.0f))); + A.push_back(glm::hvec2(glm::half(-1.1f), glm::half( 1.1f))); +*/ + std::vector A; + A.push_back(glm::vec2( 1.0f, 2.0f)); + A.push_back(glm::vec2(-1.0f,-2.0f)); + A.push_back(glm::vec2(-1.1f, 1.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint C = glm::packHalf2x16(B); + glm::vec2 D = glm::unpackHalf2x16(C); + //Error += B == D ? 0 : 1; + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 127.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packDouble2x32() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::uvec2( 1, 2)); + A.push_back(glm::uvec2(-1,-2)); + A.push_back(glm::uvec2(-1000, 1100)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::uvec2 B(A[i]); + double C = glm::packDouble2x32(B); + glm::uvec2 D = glm::unpackDouble2x32(C); + Error += B == D ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_packSnorm4x8(); + Error += test_packUnorm4x8(); + Error += test_packSnorm2x16(); + Error += test_packUnorm2x16(); + Error += test_packHalf2x16(); + Error += test_packDouble2x32(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_func_swizzle.cpp b/vendor/glm/test/core/core_func_swizzle.cpp new file mode 100644 index 0000000..9758533 --- /dev/null +++ b/vendor/glm/test/core/core_func_swizzle.cpp @@ -0,0 +1,164 @@ +#define GLM_FORCE_SWIZZLE +#include +#include +#include + +static int test_ivec2_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + glm::ivec2 A(1, 2); + glm::ivec2 B = A.yx(); + glm::ivec2 C = B.yx(); + + Error += A != B ? 0 : 1; + Error += A == C ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::ivec2 A(1, 2); + glm::ivec2 B = A.yx; + glm::ivec2 C = A.yx; + + Error += A != B ? 0 : 1; + Error += B == C ? 0 : 1; + + B.xy = B.yx; + C.xy = C.yx; + + Error += B == C ? 0 : 1; + + glm::ivec2 D(0, 0); + D.yx = A.xy; + Error += A.yx() == D ? 0 : 1; + + glm::ivec2 E = A.yx; + Error += E == D ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE + + return Error; +} + +int test_ivec3_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + glm::ivec3 A(1, 2, 3); + glm::ivec3 B = A.zyx(); + glm::ivec3 C = B.zyx(); + + Error += A != B ? 0 : 1; + Error += A == C ? 0 : 1; + } +# endif + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::ivec3 const A(1, 2, 3); + glm::ivec2 B = A.yx; + glm::ivec2 C = A.yx; + + Error += A.yx() == B ? 0 : 1; + Error += B == C ? 0 : 1; + + B.xy = B.yx; + C.xy = C.yx; + + Error += B == C ? 0 : 1; + + glm::ivec2 D(0, 0); + D.yx = A.xy; + + Error += A.yx() == D ? 0 : 1; + + glm::ivec2 E(0, 0); + E.xy = A.xy(); + + Error += E == A.xy() ? 0 : 1; + Error += E.xy() == A.xy() ? 0 : 1; + + glm::ivec3 const F = A.xxx + A.xxx; + Error += F == glm::ivec3(2) ? 0 : 1; + + glm::ivec3 const G = A.xxx - A.xxx; + Error += G == glm::ivec3(0) ? 0 : 1; + + glm::ivec3 const H = A.xxx * A.xxx; + Error += H == glm::ivec3(1) ? 0 : 1; + + glm::ivec3 const I = A.xxx / A.xxx; + Error += I == glm::ivec3(1) ? 0 : 1; + + glm::ivec3 J(1, 2, 3); + J.xyz += glm::ivec3(1); + Error += J == glm::ivec3(2, 3, 4) ? 0 : 1; + + glm::ivec3 K(1, 2, 3); + K.xyz += A.xyz; + Error += K == glm::ivec3(2, 4, 6) ? 0 : 1; + } +# endif + + return Error; +} + +int test_ivec4_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + glm::ivec4 A(1, 2, 3, 4); + glm::ivec4 B = A.wzyx(); + glm::ivec4 C = B.wzyx(); + + Error += A != B ? 0 : 1; + Error += A == C ? 0 : 1; + } +# endif + + return Error; +} + +int test_vec4_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + glm::vec4 A(1, 2, 3, 4); + glm::vec4 B = A.wzyx(); + glm::vec4 C = B.wzyx(); + + Error += glm::any(glm::notEqual(A, B, 0.0001f)) ? 0 : 1; + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + + float D = glm::dot(C.wzyx(), C.xyzw()); + Error += glm::equal(D, 20.f, 0.001f) ? 0 : 1; + } +# endif + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_ivec2_swizzle(); + Error += test_ivec3_swizzle(); + Error += test_ivec4_swizzle(); + Error += test_vec4_swizzle(); + + return Error; +} + + + diff --git a/vendor/glm/test/core/core_func_trigonometric.cpp b/vendor/glm/test/core/core_func_trigonometric.cpp new file mode 100644 index 0000000..3172340 --- /dev/null +++ b/vendor/glm/test/core/core_func_trigonometric.cpp @@ -0,0 +1,10 @@ +#include + +int main() +{ + int Error = 0; + + + return Error; +} + diff --git a/vendor/glm/test/core/core_func_vector_relational.cpp b/vendor/glm/test/core/core_func_vector_relational.cpp new file mode 100644 index 0000000..0a4e7e7 --- /dev/null +++ b/vendor/glm/test/core/core_func_vector_relational.cpp @@ -0,0 +1,180 @@ +#include +#include +#include +#include +#include + +static int test_not() +{ + int Error = 0; + + { + glm::bvec1 v(false); + Error += glm::all(glm::not_(v)) ? 0 : 1; + } + + { + glm::bvec2 v(false); + Error += glm::all(glm::not_(v)) ? 0 : 1; + } + + { + glm::bvec3 v(false); + Error += glm::all(glm::not_(v)) ? 0 : 1; + } + + { + glm::bvec4 v(false); + Error += glm::all(glm::not_(v)) ? 0 : 1; + } + + return Error; +} + +static int test_less() +{ + int Error = 0; + + { + glm::vec2 const A(1, 2); + glm::vec2 const B(2, 3); + Error += glm::all(glm::lessThan(A, B)) ? 0: 1; + Error += glm::all(glm::lessThanEqual(A, B)) ? 0: 1; + } + + { + glm::vec3 const A(1, 2, 3); + glm::vec3 const B(2, 3, 4); + Error += glm::all(glm::lessThan(A, B)) ? 0: 1; + Error += glm::all(glm::lessThanEqual(A, B)) ? 0: 1; + } + + { + glm::vec4 const A(1, 2, 3, 4); + glm::vec4 const B(2, 3, 4, 5); + Error += glm::all(glm::lessThan(A, B)) ? 0: 1; + Error += glm::all(glm::lessThanEqual(A, B)) ? 0: 1; + } + + { + glm::ivec2 const A(1, 2); + glm::ivec2 const B(2, 3); + Error += glm::all(glm::lessThan(A, B)) ? 0: 1; + + glm::ivec2 const C(1, 3); + Error += glm::all(glm::lessThanEqual(A, C)) ? 0: 1; + } + + { + glm::ivec3 const A(1, 2, 3); + glm::ivec3 const B(2, 3, 4); + Error += glm::all(glm::lessThan(A, B)) ? 0: 1; + + glm::ivec3 const C(1, 3, 4); + Error += glm::all(glm::lessThanEqual(A, C)) ? 0: 1; + } + + { + glm::ivec4 const A(1, 2, 3, 4); + glm::ivec4 const B(2, 3, 4, 5); + Error += glm::all(glm::lessThan(A, B)) ? 0: 1; + + glm::ivec4 const C(1, 3, 4, 5); + Error += glm::all(glm::lessThanEqual(A, C)) ? 0: 1; + } + + return Error; +} + +static int test_greater() +{ + int Error = 0; + + { + glm::vec2 const A(1, 2); + glm::vec2 const B(2, 3); + Error += glm::all(glm::greaterThan(B, A)) ? 0: 1; + Error += glm::all(glm::greaterThanEqual(B, A)) ? 0: 1; + } + + { + glm::vec3 const A(1, 2, 3); + glm::vec3 const B(2, 3, 4); + Error += glm::all(glm::greaterThan(B, A)) ? 0: 1; + Error += glm::all(glm::greaterThanEqual(B, A)) ? 0: 1; + } + + { + glm::vec4 const A(1, 2, 3, 4); + glm::vec4 const B(2, 3, 4, 5); + Error += glm::all(glm::greaterThan(B, A)) ? 0: 1; + Error += glm::all(glm::greaterThanEqual(B, A)) ? 0: 1; + } + + { + glm::ivec2 const A(1, 2); + glm::ivec2 const B(2, 3); + Error += glm::all(glm::greaterThan(B, A)) ? 0: 1; + + glm::ivec2 const C(1, 3); + Error += glm::all(glm::greaterThanEqual(C, A)) ? 0: 1; + } + + { + glm::ivec3 const A(1, 2, 3); + glm::ivec3 const B(2, 3, 4); + Error += glm::all(glm::greaterThan(B, A)) ? 0: 1; + + glm::ivec3 const C(1, 3, 4); + Error += glm::all(glm::greaterThanEqual(C, A)) ? 0: 1; + } + + { + glm::ivec4 const A(1, 2, 3, 4); + glm::ivec4 const B(2, 3, 4, 5); + Error += glm::all(glm::greaterThan(B, A)) ? 0: 1; + + glm::ivec4 const C(1, 3, 4, 5); + Error += glm::all(glm::greaterThanEqual(C, A)) ? 0: 1; + } + + return Error; +} + +static int test_equal() +{ + int Error = 0; + + { + glm::ivec2 const A(1, 2); + glm::ivec2 const B(1, 2); + Error += glm::all(glm::equal(B, A)) ? 0: 1; + } + + { + glm::ivec3 const A(1, 2, 3); + glm::ivec3 const B(1, 2, 3); + Error += glm::all(glm::equal(B, A)) ? 0: 1; + } + + { + glm::ivec4 const A(1, 2, 3, 4); + glm::ivec4 const B(1, 2, 3, 4); + Error += glm::all(glm::equal(B, A)) ? 0: 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_not(); + Error += test_less(); + Error += test_greater(); + Error += test_equal(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_setup_force_cxx98.cpp b/vendor/glm/test/core/core_setup_force_cxx98.cpp new file mode 100644 index 0000000..32bb63c --- /dev/null +++ b/vendor/glm/test/core/core_setup_force_cxx98.cpp @@ -0,0 +1,12 @@ +#ifndef GLM_FORCE_CXX98 +# define GLM_FORCE_CXX98 +#endif +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} diff --git a/vendor/glm/test/core/core_setup_force_size_t_length.cpp b/vendor/glm/test/core/core_setup_force_size_t_length.cpp new file mode 100644 index 0000000..36010e3 --- /dev/null +++ b/vendor/glm/test/core/core_setup_force_size_t_length.cpp @@ -0,0 +1,22 @@ +#define GLM_FORCE_SIZE_T_LENGTH +#include +#include + +template +genType add(genType const& a, genType const& b) +{ + genType result(0); + for(glm::length_t i = 0; i < a.length(); ++i) + result[i] = a[i] + b[i]; + return result; +} + +int main() +{ + int Error = 0; + + glm::ivec4 v(1); + Error += add(v, v) == glm::ivec4(2) ? 0 : 1; + + return Error; +} diff --git a/vendor/glm/test/core/core_setup_message.cpp b/vendor/glm/test/core/core_setup_message.cpp new file mode 100644 index 0000000..fc93fdd --- /dev/null +++ b/vendor/glm/test/core/core_setup_message.cpp @@ -0,0 +1,230 @@ +#define GLM_FORCE_MESSAGES +#include +#include + +int test_compiler() +{ + int Error(0); + + if(GLM_COMPILER & GLM_COMPILER_VC) + { + switch(GLM_COMPILER) + { + case GLM_COMPILER_VC12: + std::printf("Visual C++ 12 - 2013\n"); + break; + case GLM_COMPILER_VC14: + std::printf("Visual C++ 14 - 2015\n"); + break; + case GLM_COMPILER_VC15: + std::printf("Visual C++ 15 - 2017\n"); + break; + case GLM_COMPILER_VC15_3: + std::printf("Visual C++ 15.3 - 2017\n"); + break; + case GLM_COMPILER_VC15_5: + std::printf("Visual C++ 15.5 - 2017\n"); + break; + case GLM_COMPILER_VC15_6: + std::printf("Visual C++ 15.6 - 2017\n"); + break; + case GLM_COMPILER_VC15_7: + std::printf("Visual C++ 15.7 - 2017\n"); + break; + case GLM_COMPILER_VC15_8: + std::printf("Visual C++ 15.8 - 2017\n"); + break; + case GLM_COMPILER_VC15_9: + std::printf("Visual C++ 15.9 - 2017\n"); + break; + case GLM_COMPILER_VC16: + std::printf("Visual C++ 16 - 2019\n"); + break; + default: + std::printf("Visual C++ version not detected\n"); + Error += 1; + break; + } + } + else if(GLM_COMPILER & GLM_COMPILER_GCC) + { + switch(GLM_COMPILER) + { + case GLM_COMPILER_GCC46: + std::printf("GCC 4.6\n"); + break; + case GLM_COMPILER_GCC47: + std::printf("GCC 4.7\n"); + break; + case GLM_COMPILER_GCC48: + std::printf("GCC 4.8\n"); + break; + case GLM_COMPILER_GCC49: + std::printf("GCC 4.9\n"); + break; + case GLM_COMPILER_GCC5: + std::printf("GCC 5\n"); + break; + case GLM_COMPILER_GCC6: + std::printf("GCC 6\n"); + break; + case GLM_COMPILER_GCC7: + std::printf("GCC 7\n"); + break; + case GLM_COMPILER_GCC8: + std::printf("GCC 8\n"); + break; + default: + std::printf("GCC version not detected\n"); + Error += 1; + break; + } + } + else if(GLM_COMPILER & GLM_COMPILER_CUDA) + { + std::printf("CUDA\n"); + } + else if(GLM_COMPILER & GLM_COMPILER_CLANG) + { + switch(GLM_COMPILER) + { + case GLM_COMPILER_CLANG34: + std::printf("Clang 3.4\n"); + break; + case GLM_COMPILER_CLANG35: + std::printf("Clang 3.5\n"); + break; + case GLM_COMPILER_CLANG36: + std::printf("Clang 3.6\n"); + break; + case GLM_COMPILER_CLANG37: + std::printf("Clang 3.7\n"); + break; + case GLM_COMPILER_CLANG38: + std::printf("Clang 3.8\n"); + break; + case GLM_COMPILER_CLANG39: + std::printf("Clang 3.9\n"); + break; + case GLM_COMPILER_CLANG40: + std::printf("Clang 4.0\n"); + break; + case GLM_COMPILER_CLANG41: + std::printf("Clang 4.1\n"); + break; + case GLM_COMPILER_CLANG42: + std::printf("Clang 4.2\n"); + break; + default: + std::printf("LLVM version not detected\n"); + break; + } + } + else if(GLM_COMPILER & GLM_COMPILER_INTEL) + { + switch(GLM_COMPILER) + { + case GLM_COMPILER_INTEL14: + std::printf("ICC 14 - 2013 SP1\n"); + break; + case GLM_COMPILER_INTEL15: + std::printf("ICC 15 - 2015\n"); + break; + case GLM_COMPILER_INTEL16: + std::printf("ICC 16 - 2017\n"); + break; + case GLM_COMPILER_INTEL17: + std::printf("ICC 17 - 20XX\n"); + break; + default: + std::printf("Intel compiler version not detected\n"); + Error += 1; + break; + } + } + else + { + std::printf("Undetected compiler\n"); + Error += 1; + } + + return Error; +} + +int test_model() +{ + int Error = 0; + + Error += ((sizeof(void*) == 4) && (GLM_MODEL == GLM_MODEL_32)) || ((sizeof(void*) == 8) && (GLM_MODEL == GLM_MODEL_64)) ? 0 : 1; + + if(GLM_MODEL == GLM_MODEL_32) + std::printf("GLM_MODEL_32\n"); + else if(GLM_MODEL == GLM_MODEL_64) + std::printf("GLM_MODEL_64\n"); + + return Error; +} + +int test_instruction_set() +{ + int Error = 0; + + std::printf("GLM_ARCH: "); + + if(GLM_ARCH & GLM_ARCH_ARM_BIT) + std::printf("ARM "); + if(GLM_ARCH & GLM_ARCH_NEON_BIT) + std::printf("NEON "); + if(GLM_ARCH & GLM_ARCH_AVX2) + std::printf("AVX2 "); + if(GLM_ARCH & GLM_ARCH_AVX) + std::printf("AVX "); + if(GLM_ARCH & GLM_ARCH_SSE42_BIT) + std::printf("SSE4.2 "); + if(GLM_ARCH & GLM_ARCH_SSE41_BIT) + std::printf("SSE4.1 "); + if(GLM_ARCH & GLM_ARCH_SSSE3_BIT) + std::printf("SSSE3 "); + if(GLM_ARCH & GLM_ARCH_SSE3_BIT) + std::printf("SSE3 "); + if(GLM_ARCH & GLM_ARCH_SSE2_BIT) + std::printf("SSE2 "); + + std::printf("\n"); + + return Error; +} + +int test_cpp_version() +{ + std::printf("__cplusplus: %d\n", static_cast(__cplusplus)); + + return 0; +} + +int test_operators() +{ + glm::ivec3 A(1); + glm::ivec3 B(1); + bool R = A != B; + bool S = A == B; + + return (S && !R) ? 0 : 1; +} + +int main() +{ + int Error = 0; + +# if !defined(GLM_FORCE_PLATFORM_UNKNOWN) && !defined(GLM_FORCE_COMPILER_UNKNOWN) && !defined(GLM_FORCE_ARCH_UNKNOWN) && !defined(GLM_FORCE_CXX_UNKNOWN) + + Error += test_cpp_version(); + Error += test_compiler(); + Error += test_model(); + Error += test_instruction_set(); + Error += test_operators(); + +# endif + + return Error; +} diff --git a/vendor/glm/test/core/core_setup_platform_unknown.cpp b/vendor/glm/test/core/core_setup_platform_unknown.cpp new file mode 100644 index 0000000..9feaee3 --- /dev/null +++ b/vendor/glm/test/core/core_setup_platform_unknown.cpp @@ -0,0 +1,21 @@ +#ifndef GLM_FORCE_PLATFORM_UNKNOWN +# define GLM_FORCE_PLATFORM_UNKNOWN +#endif +#ifndef GLM_FORCE_COMPILER_UNKNOWN +# define GLM_FORCE_COMPILER_UNKNOWN +#endif +#ifndef GLM_FORCE_ARCH_UNKNOWN +# define GLM_FORCE_ARCH_UNKNOWN +#endif +#ifndef GLM_FORCE_CXX_UNKNOWN +# define GLM_FORCE_CXX_UNKNOWN +#endif +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} diff --git a/vendor/glm/test/core/core_setup_precision.cpp b/vendor/glm/test/core/core_setup_precision.cpp new file mode 100644 index 0000000..b44bc50 --- /dev/null +++ b/vendor/glm/test/core/core_setup_precision.cpp @@ -0,0 +1,58 @@ +#define GLM_FORCE_INLINE +#define GLM_PRECISION_HIGHP_FLOAT +#include +#include + +static int test_mat() +{ + int Error = 0; + + Error += sizeof(glm::mat2) == sizeof(glm::highp_mat2) ? 0 : 1; + Error += sizeof(glm::mat3) == sizeof(glm::highp_mat3) ? 0 : 1; + Error += sizeof(glm::mat4) == sizeof(glm::highp_mat4) ? 0 : 1; + + Error += sizeof(glm::mat2x2) == sizeof(glm::highp_mat2x2) ? 0 : 1; + Error += sizeof(glm::mat2x3) == sizeof(glm::highp_mat2x3) ? 0 : 1; + Error += sizeof(glm::mat2x4) == sizeof(glm::highp_mat2x4) ? 0 : 1; + Error += sizeof(glm::mat3x2) == sizeof(glm::highp_mat3x2) ? 0 : 1; + Error += sizeof(glm::mat3x3) == sizeof(glm::highp_mat3x3) ? 0 : 1; + Error += sizeof(glm::mat3x4) == sizeof(glm::highp_mat3x4) ? 0 : 1; + Error += sizeof(glm::mat4x2) == sizeof(glm::highp_mat4x2) ? 0 : 1; + Error += sizeof(glm::mat4x3) == sizeof(glm::highp_mat4x3) ? 0 : 1; + Error += sizeof(glm::mat4x4) == sizeof(glm::highp_mat4x4) ? 0 : 1; + + return Error; +} + +static int test_vec() +{ + int Error = 0; + + Error += sizeof(glm::vec2) == sizeof(glm::highp_vec2) ? 0 : 1; + Error += sizeof(glm::vec3) == sizeof(glm::highp_vec3) ? 0 : 1; + Error += sizeof(glm::vec4) == sizeof(glm::highp_vec4) ? 0 : 1; + + return Error; +} + +static int test_dvec() +{ + int Error = 0; + + Error += sizeof(glm::dvec2) == sizeof(glm::highp_dvec2) ? 0 : 1; + Error += sizeof(glm::dvec3) == sizeof(glm::highp_dvec3) ? 0 : 1; + Error += sizeof(glm::dvec4) == sizeof(glm::highp_dvec4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_mat(); + Error += test_vec(); + Error += test_dvec(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_aligned.cpp b/vendor/glm/test/core/core_type_aligned.cpp new file mode 100644 index 0000000..dff0939 --- /dev/null +++ b/vendor/glm/test/core/core_type_aligned.cpp @@ -0,0 +1,92 @@ +#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +#include + +#if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +#include + +static_assert(sizeof(glm::bvec4) > sizeof(glm::bvec2), "Invalid sizeof"); +static_assert(sizeof(glm::ivec4) > sizeof(glm::uvec2), "Invalid sizeof"); +static_assert(sizeof(glm::dvec4) > sizeof(glm::dvec2), "Invalid sizeof"); + +static_assert(sizeof(glm::bvec4) == sizeof(glm::bvec3), "Invalid sizeof"); +static_assert(sizeof(glm::uvec4) == sizeof(glm::uvec3), "Invalid sizeof"); +static_assert(sizeof(glm::dvec4) == sizeof(glm::dvec3), "Invalid sizeof"); + +static int test_storage_aligned() +{ + int Error = 0; + + size_t size1_aligned = sizeof(glm::detail::storage<1, int, true>::type); + Error += size1_aligned == sizeof(int) * 1 ? 0 : 1; + size_t size2_aligned = sizeof(glm::detail::storage<2, int, true>::type); + Error += size2_aligned == sizeof(int) * 2 ? 0 : 1; + size_t size4_aligned = sizeof(glm::detail::storage<4, int, true>::type); + Error += size4_aligned == sizeof(int) * 4 ? 0 : 1; + + size_t align1_aligned = alignof(glm::detail::storage<1, int, true>::type); + Error += align1_aligned == 4 ? 0 : 1; + size_t align2_aligned = alignof(glm::detail::storage<2, int, true>::type); + Error += align2_aligned == 8 ? 0 : 1; + size_t align4_aligned = alignof(glm::detail::storage<4, int, true>::type); + Error += align4_aligned == 16 ? 0 : 1; + + return Error; +} + +static int test_storage_unaligned() +{ + int Error = 0; + + size_t align1_unaligned = alignof(glm::detail::storage<1, int, false>::type); + Error += align1_unaligned == sizeof(int) ? 0 : 1; + size_t align2_unaligned = alignof(glm::detail::storage<2, int, false>::type); + Error += align2_unaligned == sizeof(int) ? 0 : 1; + size_t align3_unaligned = alignof(glm::detail::storage<3, int, false>::type); + Error += align3_unaligned == sizeof(int) ? 0 : 1; + size_t align4_unaligned = alignof(glm::detail::storage<4, int, false>::type); + Error += align4_unaligned == sizeof(int) ? 0 : 1; + + return Error; +} + +static int test_vec3_aligned() +{ + int Error = 0; + + struct Struct1 + { + glm::vec4 A; + float B; + glm::vec3 C; + }; + + std::size_t const Size1 = sizeof(Struct1); + Error += Size1 == 48 ? 0 : 1; + + struct Struct2 + { + glm::vec4 A; + glm::vec3 B; + float C; + }; + + std::size_t const Size2 = sizeof(Struct2); + Error += Size2 == 48 ? 0 : 1; + + return Error; +} + +#endif + +int main() +{ + int Error = 0; + +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + Error += test_storage_aligned(); + Error += test_storage_unaligned(); + Error += test_vec3_aligned(); +# endif + + return Error; +} diff --git a/vendor/glm/test/core/core_type_cast.cpp b/vendor/glm/test/core/core_type_cast.cpp new file mode 100644 index 0000000..7ff1901 --- /dev/null +++ b/vendor/glm/test/core/core_type_cast.cpp @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include + +struct my_vec2 +{ + operator glm::vec2() { return glm::vec2(x, y); } + float x, y; +}; + +int test_vec2_cast() +{ + glm::vec2 A(1.0f, 2.0f); + glm::lowp_vec2 B(A); + glm::mediump_vec2 C(A); + glm::highp_vec2 D(A); + + glm::vec2 E = static_cast(A); + glm::lowp_vec2 F = static_cast(A); + glm::mediump_vec2 G = static_cast(A); + glm::highp_vec2 H = static_cast(A); + + my_vec2 I; + glm::vec2 J = static_cast(I); + glm::vec2 K(7.8f); + + int Error(0); + + Error += glm::all(glm::equal(A, E, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(B, F, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(C, G, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(D, H, glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_vec3_cast() +{ + glm::vec3 A(1.0f, 2.0f, 3.0f); + glm::lowp_vec3 B(A); + glm::mediump_vec3 C(A); + glm::highp_vec3 D(A); + + glm::vec3 E = static_cast(A); + glm::lowp_vec3 F = static_cast(A); + glm::mediump_vec3 G = static_cast(A); + glm::highp_vec3 H = static_cast(A); + + int Error(0); + + Error += glm::all(glm::equal(A, E, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(B, F, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(C, G, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(D, H, glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_vec4_cast() +{ + glm::vec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::lowp_vec4 B(A); + glm::mediump_vec4 C(A); + glm::highp_vec4 D(A); + + glm::vec4 E = static_cast(A); + glm::lowp_vec4 F = static_cast(A); + glm::mediump_vec4 G = static_cast(A); + glm::highp_vec4 H = static_cast(A); + + int Error(0); + + Error += glm::all(glm::equal(A, E, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(B, F, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(C, G, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(D, H, glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_std_copy() +{ + int Error = 0; + + { + std::vector High; + High.resize(64); + std::vector Medium(High.size()); + + std::copy(High.begin(), High.end(), Medium.begin()); + + *Medium.begin() = *High.begin(); + } + + { + std::vector High4; + High4.resize(64); + std::vector Medium4(High4.size()); + + std::copy(High4.begin(), High4.end(), Medium4.begin()); + + *Medium4.begin() = *High4.begin(); + } + + { + std::vector High3; + High3.resize(64); + std::vector Medium3(High3.size()); + + std::copy(High3.begin(), High3.end(), Medium3.begin()); + + *Medium3.begin() = *High3.begin(); + } + + { + std::vector High2; + High2.resize(64); + std::vector Medium2(High2.size()); + + std::copy(High2.begin(), High2.end(), Medium2.begin()); + + *Medium2.begin() = *High2.begin(); + } + + glm::dvec4 v1; + glm::vec4 v2; + + v2 = v1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_std_copy(); + Error += test_vec2_cast(); + Error += test_vec3_cast(); + Error += test_vec4_cast(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_ctor.cpp b/vendor/glm/test/core/core_type_ctor.cpp new file mode 100644 index 0000000..078fcdf --- /dev/null +++ b/vendor/glm/test/core/core_type_ctor.cpp @@ -0,0 +1,351 @@ +#include +#include +#include +#include +#include + +static int test_vec1_ctor() +{ + int Error = 0; + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + { + union pack + { + glm::vec1 f; + glm::ivec1 i; + } A, B; + + A.f = glm::vec1(0); + Error += glm::all(glm::equal(A.i, glm::ivec1(0))) ? 0 : 1; + + B.f = glm::vec1(1); + Error += glm::all(glm::equal(B.i, glm::ivec1(1065353216))) ? 0 : 1; + } +# endif//GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + + return Error; +} + +static int test_vec2_ctor() +{ + int Error = 0; + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + { + union pack + { + glm::vec2 f; + glm::ivec2 i; + } A, B; + + A.f = glm::vec2(0); + Error += glm::all(glm::equal(A.i, glm::ivec2(0))) ? 0 : 1; + + B.f = glm::vec2(1); + Error += glm::all(glm::equal(B.i, glm::ivec2(1065353216))) ? 0 : 1; + } +# endif + + return Error; +} + +static int test_vec3_ctor() +{ + int Error = 0; + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + { + union pack + { + glm::vec3 f; + glm::ivec3 i; + } A, B; + + A.f = glm::vec3(0); + Error += glm::all(glm::equal(A.i, glm::ivec3(0))) ? 0 : 1; + + B.f = glm::vec3(1); + Error += glm::all(glm::equal(B.i, glm::ivec3(1065353216))) ? 0 : 1; + } +# endif + + return Error; +} + +static int test_vec4_ctor() +{ + int Error = 0; + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE + { + union pack + { + glm::vec4 f; + glm::ivec4 i; + } A, B; + + A.f = glm::vec4(0); + Error += glm::all(glm::equal(A.i, glm::ivec4(0))) ? 0 : 1; + + B.f = glm::vec4(1); + Error += glm::all(glm::equal(B.i, glm::ivec4(1065353216))) ? 0 : 1; + } +# endif + + return Error; +} + +static int test_mat2x2_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat2x2 f; + glm::mat2x2 i; + } A, B; + + A.f = glm::mat2x2(0); + Error += glm::all(glm::equal(A.i[0], glm::vec2(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat2x2(1); + Error += glm::all(glm::equal(B.i[0], glm::vec2(1, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat2x3_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat2x3 f; + glm::mat2x3 i; + } A, B; + + A.f = glm::mat2x3(0); + Error += glm::all(glm::equal(A.i[0], glm::vec3(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat2x3(1); + Error += glm::all(glm::equal(B.i[0], glm::vec3(1, 0, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat2x4_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat2x4 f; + glm::mat2x4 i; + } A, B; + + A.f = glm::mat2x4(0); + glm::vec4 const C(0, 0, 0, 0); + Error += glm::all(glm::equal(A.i[0], C, glm::epsilon())) ? 0 : 1; + + B.f = glm::mat2x4(1); + glm::vec4 const D(1, 0, 0, 0); + Error += glm::all(glm::equal(B.i[0], D, glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat3x2_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat3x2 f; + glm::mat3x2 i; + } A, B; + + A.f = glm::mat3x2(0); + Error += glm::all(glm::equal(A.i[0], glm::vec2(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat3x2(1); + Error += glm::all(glm::equal(B.i[0], glm::vec2(1, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat3x3_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat3x3 f; + glm::mat3x3 i; + } A, B; + + A.f = glm::mat3x3(0); + Error += glm::all(glm::equal(A.i[0], glm::vec3(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat3x3(1); + Error += glm::all(glm::equal(B.i[0], glm::vec3(1, 0, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat3x4_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat3x4 f; + glm::mat3x4 i; + } A, B; + + A.f = glm::mat3x4(0); + Error += glm::all(glm::equal(A.i[0], glm::vec4(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat3x4(1); + Error += glm::all(glm::equal(B.i[0], glm::vec4(1, 0, 0, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat4x2_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat4x2 f; + glm::mat4x2 i; + } A, B; + + A.f = glm::mat4x2(0); + Error += glm::all(glm::equal(A.i[0], glm::vec2(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat4x2(1); + Error += glm::all(glm::equal(B.i[0], glm::vec2(1, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat4x3_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat4x3 f; + glm::mat4x3 i; + } A, B; + + A.f = glm::mat4x3(0); + Error += glm::all(glm::equal(A.i[0], glm::vec3(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat4x3(1); + Error += glm::all(glm::equal(B.i[0], glm::vec3(1, 0, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_mat4x4_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::mat4 f; + glm::mat4 i; + } A, B; + + A.f = glm::mat4(0); + Error += glm::all(glm::equal(A.i[0], glm::vec4(0), glm::epsilon())) ? 0 : 1; + + B.f = glm::mat4(1); + Error += glm::all(glm::equal(B.i[0], glm::vec4(1, 0, 0, 0), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +static int test_quat_ctor() +{ + int Error = 0; + +# if GLM_LANG & GLM_LANG_CXX11_FLAG + { + union pack + { + glm::quat f; + glm::quat i; + } A, B; + + A.f = glm::quat(0, 0, 0, 0); + Error += glm::all(glm::equal(A.i, glm::quat(0, 0, 0, 0), glm::epsilon())) ? 0 : 1; + + B.f = glm::quat(1, 1, 1, 1); + Error += glm::all(glm::equal(B.i, glm::quat(1, 1, 1, 1), glm::epsilon())) ? 0 : 1; + } +# endif//GLM_LANG & GLM_LANG_CXX11_FLAG + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_vec1_ctor(); + Error += test_vec2_ctor(); + Error += test_vec3_ctor(); + Error += test_vec4_ctor(); + Error += test_mat2x2_ctor(); + Error += test_mat2x3_ctor(); + Error += test_mat2x4_ctor(); + Error += test_mat3x2_ctor(); + Error += test_mat3x3_ctor(); + Error += test_mat3x4_ctor(); + Error += test_mat4x2_ctor(); + Error += test_mat4x3_ctor(); + Error += test_mat4x4_ctor(); + Error += test_quat_ctor(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_int.cpp b/vendor/glm/test/core/core_type_int.cpp new file mode 100644 index 0000000..2631509 --- /dev/null +++ b/vendor/glm/test/core/core_type_int.cpp @@ -0,0 +1,26 @@ +#include +#include + +static int test_bit_operator() +{ + int Error = 0; + + glm::ivec4 const a(1); + glm::ivec4 const b = ~a; + Error += glm::all(glm::equal(b, glm::ivec4(-2))) ? 0 : 1; + + glm::int32 const c(1); + glm::int32 const d = ~c; + Error += d == -2 ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_bit_operator(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_length.cpp b/vendor/glm/test/core/core_type_length.cpp new file mode 100644 index 0000000..4bf76cf --- /dev/null +++ b/vendor/glm/test/core/core_type_length.cpp @@ -0,0 +1,79 @@ +#include + +static int test_length_mat_non_squared() +{ + int Error = 0; + + Error += glm::mat2x3().length() == 2 ? 0 : 1; + Error += glm::mat2x4().length() == 2 ? 0 : 1; + Error += glm::mat3x2().length() == 3 ? 0 : 1; + Error += glm::mat3x4().length() == 3 ? 0 : 1; + Error += glm::mat4x2().length() == 4 ? 0 : 1; + Error += glm::mat4x3().length() == 4 ? 0 : 1; + + Error += glm::dmat2x3().length() == 2 ? 0 : 1; + Error += glm::dmat2x4().length() == 2 ? 0 : 1; + Error += glm::dmat3x2().length() == 3 ? 0 : 1; + Error += glm::dmat3x4().length() == 3 ? 0 : 1; + Error += glm::dmat4x2().length() == 4 ? 0 : 1; + Error += glm::dmat4x3().length() == 4 ? 0 : 1; + + return Error; +} + +static int test_length_mat() +{ + int Error = 0; + + Error += glm::mat2().length() == 2 ? 0 : 1; + Error += glm::mat3().length() == 3 ? 0 : 1; + Error += glm::mat4().length() == 4 ? 0 : 1; + Error += glm::mat2x2().length() == 2 ? 0 : 1; + Error += glm::mat3x3().length() == 3 ? 0 : 1; + Error += glm::mat4x4().length() == 4 ? 0 : 1; + + Error += glm::dmat2().length() == 2 ? 0 : 1; + Error += glm::dmat3().length() == 3 ? 0 : 1; + Error += glm::dmat4().length() == 4 ? 0 : 1; + Error += glm::dmat2x2().length() == 2 ? 0 : 1; + Error += glm::dmat3x3().length() == 3 ? 0 : 1; + Error += glm::dmat4x4().length() == 4 ? 0 : 1; + + return Error; +} + +static int test_length_vec() +{ + + int Error = 0; + + Error += glm::vec2().length() == 2 ? 0 : 1; + Error += glm::vec3().length() == 3 ? 0 : 1; + Error += glm::vec4().length() == 4 ? 0 : 1; + + Error += glm::ivec2().length() == 2 ? 0 : 1; + Error += glm::ivec3().length() == 3 ? 0 : 1; + Error += glm::ivec4().length() == 4 ? 0 : 1; + + Error += glm::uvec2().length() == 2 ? 0 : 1; + Error += glm::uvec3().length() == 3 ? 0 : 1; + Error += glm::uvec4().length() == 4 ? 0 : 1; + + Error += glm::dvec2().length() == 2 ? 0 : 1; + Error += glm::dvec3().length() == 3 ? 0 : 1; + Error += glm::dvec4().length() == 4 ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_length_vec(); + Error += test_length_mat(); + Error += test_length_mat_non_squared(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_type_mat2x2.cpp b/vendor/glm/test/core/core_type_mat2x2.cpp new file mode 100644 index 0000000..2f8b018 --- /dev/null +++ b/vendor/glm/test/core/core_type_mat2x2.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int test_operators() +{ + glm::mat2x2 l(1.0f); + glm::mat2x2 m(1.0f); + glm::vec2 u(1.0f); + glm::vec2 v(1.0f); + float x = 1.0f; + glm::vec2 a = m * u; + glm::vec2 b = v * m; + glm::mat2x2 n = x / m; + glm::mat2x2 o = m / x; + glm::mat2x2 p = x * m; + glm::mat2x2 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +int test_inverse() +{ + int Error(0); + + { + glm::mat2 const Matrix(1, 2, 3, 4); + glm::mat2 const Inverse = glm::inverse(Matrix); + glm::mat2 const Identity = Matrix * Inverse; + + Error += glm::all(glm::equal(Identity[0], glm::vec2(1.0f, 0.0f), glm::vec2(0.01f))) ? 0 : 1; + Error += glm::all(glm::equal(Identity[1], glm::vec2(0.0f, 1.0f), glm::vec2(0.01f))) ? 0 : 1; + } + + { + glm::mat2 const Matrix(1, 2, 3, 4); + glm::mat2 const Identity = Matrix / Matrix; + + Error += glm::all(glm::equal(Identity[0], glm::vec2(1.0f, 0.0f), glm::vec2(0.01f))) ? 0 : 1; + Error += glm::all(glm::equal(Identity[1], glm::vec2(0.0f, 1.0f), glm::vec2(0.01f))) ? 0 : 1; + } + + return Error; +} + +int test_ctr() +{ + int Error = 0; + + { + glm::mediump_mat2x2 const A(1.0f); + glm::highp_mat2x2 const B(A); + glm::mediump_mat2x2 const C(B); + + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } + +#if GLM_HAS_INITIALIZER_LISTS + glm::mat2x2 m0( + glm::vec2(0, 1), + glm::vec2(2, 3)); + + glm::mat2x2 m1{0, 1, 2, 3}; + + glm::mat2x2 m2{ + {0, 1}, + {2, 3}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3}, + {0, 1, 2, 3} + }; + + std::vector v2{ + { + { 0, 1}, + { 4, 5} + }, + { + { 0, 1}, + { 4, 5} + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat2 B(A); + glm::mat2 Identity(1.0f); + + Error += glm::all(glm::equal(B, Identity, glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +int test_size() +{ + int Error = 0; + + Error += 16 == sizeof(glm::mat2x2) ? 0 : 1; + Error += 32 == sizeof(glm::dmat2x2) ? 0 : 1; + Error += glm::mat2x2().length() == 2 ? 0 : 1; + Error += glm::dmat2x2().length() == 2 ? 0 : 1; + Error += glm::mat2x2::length() == 2 ? 0 : 1; + Error += glm::dmat2x2::length() == 2 ? 0 : 1; + + return Error; +} + +int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat2x2::length() == 2, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_operators(); + Error += test_inverse(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_mat2x3.cpp b/vendor/glm/test/core/core_type_mat2x3.cpp new file mode 100644 index 0000000..e3ad76b --- /dev/null +++ b/vendor/glm/test/core/core_type_mat2x3.cpp @@ -0,0 +1,142 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_operators() +{ + glm::mat2x3 l(1.0f); + glm::mat2x3 m(1.0f); + glm::vec2 u(1.0f); + glm::vec3 v(1.0f); + float x = 1.0f; + glm::vec3 a = m * u; + glm::vec2 b = v * m; + glm::mat2x3 n = x / m; + glm::mat2x3 o = m / x; + glm::mat2x3 p = x * m; + glm::mat2x3 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +int test_ctr() +{ + int Error(0); + +#if GLM_HAS_INITIALIZER_LISTS + glm::mat2x3 m0( + glm::vec3(0, 1, 2), + glm::vec3(3, 4, 5)); + + glm::mat2x3 m1{0, 1, 2, 3, 4, 5}; + + glm::mat2x3 m2{ + {0, 1, 2}, + {3, 4, 5}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3, 4, 5}, + {0, 1, 2, 3, 4, 5} + }; + + std::vector v2{ + { + { 0, 1, 2}, + { 4, 5, 6} + }, + { + { 0, 1, 2}, + { 4, 5, 6} + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat2x3 B(A); + glm::mat2x3 Identity(1.0f); + + Error += glm::all(glm::equal(B, Identity, glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +int test_size() +{ + int Error = 0; + + Error += 24 == sizeof(glm::mat2x3) ? 0 : 1; + Error += 48 == sizeof(glm::dmat2x3) ? 0 : 1; + Error += glm::mat2x3().length() == 2 ? 0 : 1; + Error += glm::dmat2x3().length() == 2 ? 0 : 1; + Error += glm::mat2x3::length() == 2 ? 0 : 1; + Error += glm::dmat2x3::length() == 2 ? 0 : 1; + + return Error; +} + +int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat2x3::length() == 2, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_operators(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_mat2x4.cpp b/vendor/glm/test/core/core_type_mat2x4.cpp new file mode 100644 index 0000000..ade3a44 --- /dev/null +++ b/vendor/glm/test/core/core_type_mat2x4.cpp @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_operators() +{ + glm::mat2x4 l(1.0f); + glm::mat2x4 m(1.0f); + glm::vec2 u(1.0f); + glm::vec4 v(1.0f); + float x = 1.0f; + glm::vec4 a = m * u; + glm::vec2 b = v * m; + glm::mat2x4 n = x / m; + glm::mat2x4 o = m / x; + glm::mat2x4 p = x * m; + glm::mat2x4 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +int test_ctr() +{ + int Error(0); + +#if(GLM_HAS_INITIALIZER_LISTS) + glm::mat2x4 m0( + glm::vec4(0, 1, 2, 3), + glm::vec4(4, 5, 6, 7)); + + glm::mat2x4 m1{0, 1, 2, 3, 4, 5, 6, 7}; + + glm::mat2x4 m2{ + {0, 1, 2, 3}, + {4, 5, 6, 7}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3, 4, 5, 6, 7}, + {0, 1, 2, 3, 4, 5, 6, 7} + }; + + std::vector v2{ + { + { 0, 1, 2, 3}, + { 4, 5, 6, 7} + }, + { + { 0, 1, 2, 3}, + { 4, 5, 6, 7} + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat2x4 B(A); + glm::mat2x4 Identity(1.0f); + + for(glm::length_t i = 0, length = B.length(); i < length; ++i) + Error += glm::all(glm::epsilonEqual(B[i], Identity[i], glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +static int test_size() +{ + int Error = 0; + + Error += 32 == sizeof(glm::mat2x4) ? 0 : 1; + Error += 64 == sizeof(glm::dmat2x4) ? 0 : 1; + Error += glm::mat2x4().length() == 2 ? 0 : 1; + Error += glm::dmat2x4().length() == 2 ? 0 : 1; + Error += glm::mat2x4::length() == 2 ? 0 : 1; + Error += glm::dmat2x4::length() == 2 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat2x4::length() == 2, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_operators(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} + + + diff --git a/vendor/glm/test/core/core_type_mat3x2.cpp b/vendor/glm/test/core/core_type_mat3x2.cpp new file mode 100644 index 0000000..7a40f90 --- /dev/null +++ b/vendor/glm/test/core/core_type_mat3x2.cpp @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool test_operators() +{ + glm::mat3x2 l(1.0f); + glm::mat3x2 m(1.0f); + glm::vec3 u(1.0f); + glm::vec2 v(1.0f); + float x = 1.0f; + glm::vec2 a = m * u; + glm::vec3 b = v * m; + glm::mat3x2 n = x / m; + glm::mat3x2 o = m / x; + glm::mat3x2 p = x * m; + glm::mat3x2 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +int test_ctr() +{ + int Error(0); + +#if(GLM_HAS_INITIALIZER_LISTS) + glm::mat3x2 m0( + glm::vec2(0, 1), + glm::vec2(2, 3), + glm::vec2(4, 5)); + + glm::mat3x2 m1{0, 1, 2, 3, 4, 5}; + + glm::mat3x2 m2{ + {0, 1}, + {2, 3}, + {4, 5}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3, 4, 5}, + {0, 1, 2, 3, 4, 5} + }; + + std::vector v2{ + { + { 0, 1}, + { 2, 3}, + { 4, 5} + }, + { + { 0, 1}, + { 2, 3}, + { 4, 5} + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat3x2 B(A); + glm::mat3x2 Identity(1.0f); + + Error += glm::all(glm::equal(B, Identity, glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +static int test_size() +{ + int Error = 0; + + Error += 24 == sizeof(glm::mat3x2) ? 0 : 1; + Error += 48 == sizeof(glm::dmat3x2) ? 0 : 1; + Error += glm::mat3x2().length() == 3 ? 0 : 1; + Error += glm::dmat3x2().length() == 3 ? 0 : 1; + Error += glm::mat3x2::length() == 3 ? 0 : 1; + Error += glm::dmat3x2::length() == 3 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat3x2::length() == 3, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_operators(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} + + diff --git a/vendor/glm/test/core/core_type_mat3x3.cpp b/vendor/glm/test/core/core_type_mat3x3.cpp new file mode 100644 index 0000000..99e1f41 --- /dev/null +++ b/vendor/glm/test/core/core_type_mat3x3.cpp @@ -0,0 +1,197 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_mat3x3() +{ + glm::dmat3 Mat0( + glm::dvec3(0.6f, 0.2f, 0.3f), + glm::dvec3(0.2f, 0.7f, 0.5f), + glm::dvec3(0.3f, 0.5f, 0.7f)); + glm::dmat3 Inv0 = glm::inverse(Mat0); + glm::dmat3 Res0 = Mat0 * Inv0; + + return glm::all(glm::equal(Res0, glm::dmat3(1.0), 0.01)) ? 0 : 1; +} + +static int test_operators() +{ + glm::mat3x3 l(1.0f); + glm::mat3x3 m(1.0f); + glm::vec3 u(1.0f); + glm::vec3 v(1.0f); + float x = 1.0f; + glm::vec3 a = m * u; + glm::vec3 b = v * m; + glm::mat3x3 n = x / m; + glm::mat3x3 o = m / x; + glm::mat3x3 p = x * m; + glm::mat3x3 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +static int test_inverse() +{ + int Error(0); + + { + glm::mat3 const Matrix( + glm::vec3(0.6f, 0.2f, 0.3f), + glm::vec3(0.2f, 0.7f, 0.5f), + glm::vec3(0.3f, 0.5f, 0.7f)); + glm::mat3 const Inverse = glm::inverse(Matrix); + glm::mat3 const Identity = Matrix * Inverse; + + Error += glm::all(glm::equal(Identity[0], glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.01f))) ? 0 : 1; + Error += glm::all(glm::equal(Identity[1], glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.01f))) ? 0 : 1; + Error += glm::all(glm::equal(Identity[2], glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.01f))) ? 0 : 1; + } + + { + glm::mat3 const Matrix( + glm::vec3(0.6f, 0.2f, 0.3f), + glm::vec3(0.2f, 0.7f, 0.5f), + glm::vec3(0.3f, 0.5f, 0.7f)); + glm::mat3 const Identity = Matrix / Matrix; + + Error += glm::all(glm::equal(Identity[0], glm::vec3(1.0f, 0.0f, 0.0f), glm::vec3(0.01f))) ? 0 : 1; + Error += glm::all(glm::equal(Identity[1], glm::vec3(0.0f, 1.0f, 0.0f), glm::vec3(0.01f))) ? 0 : 1; + Error += glm::all(glm::equal(Identity[2], glm::vec3(0.0f, 0.0f, 1.0f), glm::vec3(0.01f))) ? 0 : 1; + } + + return Error; +} + +static int test_ctr() +{ + int Error(0); + +#if(GLM_HAS_INITIALIZER_LISTS) + glm::mat3x3 m0( + glm::vec3(0, 1, 2), + glm::vec3(3, 4, 5), + glm::vec3(6, 7, 8)); + + glm::mat3x3 m1{0, 1, 2, 3, 4, 5, 6, 7, 8}; + + glm::mat3x3 m2{ + {0, 1, 2}, + {3, 4, 5}, + {6, 7, 8}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3, 4, 5, 6, 7, 8}, + {0, 1, 2, 3, 4, 5, 6, 7, 8} + }; + + std::vector v2{ + { + { 0, 1, 2}, + { 3, 4, 5}, + { 6, 7, 8} + }, + { + { 0, 1, 2}, + { 3, 4, 5}, + { 6, 7, 8} + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat3x3 B(A); + glm::mat3x3 Identity(1.0f); + + Error += glm::all(glm::equal(B, Identity, glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +static int test_size() +{ + int Error = 0; + + Error += 36 == sizeof(glm::mat3x3) ? 0 : 1; + Error += 72 == sizeof(glm::dmat3x3) ? 0 : 1; + Error += glm::mat3x3().length() == 3 ? 0 : 1; + Error += glm::dmat3x3().length() == 3 ? 0 : 1; + Error += glm::mat3x3::length() == 3 ? 0 : 1; + Error += glm::dmat3x3::length() == 3 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat3x3::length() == 3, "GLM: Failed constexpr"); + + constexpr glm::mat3x3 const Z(0.0f); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_mat3x3(); + Error += test_operators(); + Error += test_inverse(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_type_mat3x4.cpp b/vendor/glm/test/core/core_type_mat3x4.cpp new file mode 100644 index 0000000..97d4574 --- /dev/null +++ b/vendor/glm/test/core/core_type_mat3x4.cpp @@ -0,0 +1,149 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool test_operators() +{ + glm::mat3x4 l(1.0f); + glm::mat3x4 m(1.0f); + glm::vec3 u(1.0f); + glm::vec4 v(1.0f); + float x = 1.0f; + glm::vec4 a = m * u; + glm::vec3 b = v * m; + glm::mat3x4 n = x / m; + glm::mat3x4 o = m / x; + glm::mat3x4 p = x * m; + glm::mat3x4 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +int test_ctr() +{ + int Error(0); + +#if(GLM_HAS_INITIALIZER_LISTS) + glm::mat3x4 m0( + glm::vec4(0, 1, 2, 3), + glm::vec4(4, 5, 6, 7), + glm::vec4(8, 9, 10, 11)); + + glm::mat3x4 m1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + + glm::mat3x4 m2{ + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {8, 9, 10, 11}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} + }; + + std::vector v2{ + { + { 0, 1, 2, 3}, + { 4, 5, 6, 7}, + { 8, 9, 10, 11} + }, + { + { 0, 1, 2, 3}, + { 4, 5, 6, 7}, + { 8, 9, 10, 11} + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat3x4 B(A); + glm::mat3x4 Identity(1.0f); + + for(glm::length_t i = 0, length = B.length(); i < length; ++i) + Error += glm::all(glm::epsilonEqual(B[i], Identity[i], glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +static int test_size() +{ + int Error = 0; + + Error += 48 == sizeof(glm::mat3x4) ? 0 : 1; + Error += 96 == sizeof(glm::dmat3x4) ? 0 : 1; + Error += glm::mat3x4().length() == 3 ? 0 : 1; + Error += glm::dmat3x4().length() == 3 ? 0 : 1; + Error += glm::mat3x4::length() == 3 ? 0 : 1; + Error += glm::dmat3x4::length() == 3 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat3x4::length() == 3, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_operators(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_type_mat4x2.cpp b/vendor/glm/test/core/core_type_mat4x2.cpp new file mode 100644 index 0000000..7133edc --- /dev/null +++ b/vendor/glm/test/core/core_type_mat4x2.cpp @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_operators() +{ + glm::mat4x2 l(1.0f); + glm::mat4x2 m(1.0f); + glm::vec4 u(1.0f); + glm::vec2 v(1.0f); + float x = 1.0f; + glm::vec2 a = m * u; + glm::vec4 b = v * m; + glm::mat4x2 n = x / m; + glm::mat4x2 o = m / x; + glm::mat4x2 p = x * m; + glm::mat4x2 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +int test_ctr() +{ + int Error(0); + +#if(GLM_HAS_INITIALIZER_LISTS) + glm::mat4x2 m0( + glm::vec2(0, 1), + glm::vec2(2, 3), + glm::vec2(4, 5), + glm::vec2(6, 7)); + + glm::mat4x2 m1{0, 1, 2, 3, 4, 5, 6, 7}; + + glm::mat4x2 m2{ + {0, 1}, + {2, 3}, + {4, 5}, + {6, 7}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3, 4, 5, 6, 7}, + {0, 1, 2, 3, 4, 5, 6, 7} + }; + + std::vector v2{ + { + { 0, 1}, + { 4, 5}, + { 8, 9}, + { 12, 13} + }, + { + { 0, 1}, + { 4, 5}, + { 8, 9}, + { 12, 13} + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat4x2 B(A); + glm::mat4x2 Identity(1.0f); + + Error += glm::all(glm::equal(B, Identity, glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +static int test_size() +{ + int Error = 0; + + Error += 32 == sizeof(glm::mat4x2) ? 0 : 1; + Error += 64 == sizeof(glm::dmat4x2) ? 0 : 1; + Error += glm::mat4x2().length() == 4 ? 0 : 1; + Error += glm::dmat4x2().length() == 4 ? 0 : 1; + Error += glm::mat4x2::length() == 4 ? 0 : 1; + Error += glm::dmat4x2::length() == 4 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat4x2::length() == 4, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_operators(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} + diff --git a/vendor/glm/test/core/core_type_mat4x3.cpp b/vendor/glm/test/core/core_type_mat4x3.cpp new file mode 100644 index 0000000..1c65e7f --- /dev/null +++ b/vendor/glm/test/core/core_type_mat4x3.cpp @@ -0,0 +1,152 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_operators() +{ + glm::mat4x3 l(1.0f); + glm::mat4x3 m(1.0f); + glm::vec4 u(1.0f); + glm::vec3 v(1.0f); + float x = 1.0f; + glm::vec3 a = m * u; + glm::vec4 b = v * m; + glm::mat4x3 n = x / m; + glm::mat4x3 o = m / x; + glm::mat4x3 p = x * m; + glm::mat4x3 q = m * x; + bool R = glm::any(glm::notEqual(m, q, glm::epsilon())); + bool S = glm::all(glm::equal(m, l, glm::epsilon())); + + return (S && !R) ? 0 : 1; +} + +int test_ctr() +{ + int Error(0); + +#if(GLM_HAS_INITIALIZER_LISTS) + glm::mat4x3 m0( + glm::vec3(0, 1, 2), + glm::vec3(3, 4, 5), + glm::vec3(6, 7, 8), + glm::vec3(9, 10, 11)); + + glm::mat4x3 m1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + + glm::mat4x3 m2{ + {0, 1, 2}, + {3, 4, 5}, + {6, 7, 8}, + {9, 10, 11}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + std::vector v1{ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11} + }; + + std::vector v2{ + { + { 0, 1, 2 }, + { 4, 5, 6 }, + { 8, 9, 10 }, + { 12, 13, 14 } + }, + { + { 0, 1, 2 }, + { 4, 5, 6 }, + { 8, 9, 10 }, + { 12, 13, 14 } + } + }; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +namespace cast +{ + template + int entry() + { + int Error = 0; + + genType A(1.0f); + glm::mat4x3 B(A); + glm::mat4x3 Identity(1.0f); + + Error += glm::all(glm::equal(B, Identity, glm::epsilon())) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + Error += entry(); + + return Error; + } +}//namespace cast + +static int test_size() +{ + int Error = 0; + + Error += 48 == sizeof(glm::mat4x3) ? 0 : 1; + Error += 96 == sizeof(glm::dmat4x3) ? 0 : 1; + Error += glm::mat4x3().length() == 4 ? 0 : 1; + Error += glm::dmat4x3().length() == 4 ? 0 : 1; + Error += glm::mat4x3::length() == 4 ? 0 : 1; + Error += glm::dmat4x3::length() == 4 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat4x3::length() == 4, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += cast::test(); + Error += test_ctr(); + Error += test_operators(); + Error += test_size(); + Error += test_constexpr(); + + return Error; +} + + diff --git a/vendor/glm/test/core/core_type_mat4x4.cpp b/vendor/glm/test/core/core_type_mat4x4.cpp new file mode 100644 index 0000000..0be87f1 --- /dev/null +++ b/vendor/glm/test/core/core_type_mat4x4.cpp @@ -0,0 +1,218 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +template +static int test_operators() +{ + typedef typename matType::value_type value_type; + + value_type const Epsilon = static_cast(0.001); + + int Error = 0; + + matType const M(static_cast(2.0f)); + matType const N(static_cast(1.0f)); + vecType const U(static_cast(2.0f)); + + { + matType const P = N * static_cast(2.0f); + Error += glm::all(glm::equal(P, M, Epsilon)) ? 0 : 1; + + matType const Q = M / static_cast(2.0f); + Error += glm::all(glm::equal(Q, N, Epsilon)) ? 0 : 1; + } + + { + vecType const V = M * U; + Error += glm::all(glm::equal(V, vecType(static_cast(4.f)), Epsilon)) ? 0 : 1; + + vecType const W = U / M; + Error += glm::all(glm::equal(W, vecType(static_cast(1.f)), Epsilon)) ? 0 : 1; + } + + { + matType const O = M * N; + Error += glm::all(glm::equal(O, matType(static_cast(2.f)), Epsilon)) ? 0 : 1; + } + + return Error; +} + +template +static int test_inverse() +{ + typedef typename matType::value_type value_type; + + value_type const Epsilon = static_cast(0.001); + + int Error = 0; + + matType const Identity(static_cast(1.0f)); + matType const Matrix( + glm::vec4(0.6f, 0.2f, 0.3f, 0.4f), + glm::vec4(0.2f, 0.7f, 0.5f, 0.3f), + glm::vec4(0.3f, 0.5f, 0.7f, 0.2f), + glm::vec4(0.4f, 0.3f, 0.2f, 0.6f)); + matType const Inverse = Identity / Matrix; + matType const Result = Matrix * Inverse; + + Error += glm::all(glm::equal(Identity, Result, Epsilon)) ? 0 : 1; + + return Error; +} + +static int test_ctr() +{ + int Error = 0; + +#if GLM_HAS_TRIVIAL_QUERIES + //Error += std::is_trivially_default_constructible::value ? 0 : 1; + //Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + //Error += std::is_copy_constructible::value ? 0 : 1; + //Error += std::has_trivial_copy_constructor::value ? 0 : 1; +#endif + +#if GLM_HAS_INITIALIZER_LISTS + glm::mat4 const m0( + glm::vec4(0, 1, 2, 3), + glm::vec4(4, 5, 6, 7), + glm::vec4(8, 9, 10, 11), + glm::vec4(12, 13, 14, 15)); + + assert(sizeof(m0) == 4 * 4 * 4); + + glm::vec4 const V{0, 1, 2, 3}; + + glm::mat4 const m1{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + glm::mat4 const m2{ + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {8, 9, 10, 11}, + {12, 13, 14, 15}}; + + Error += glm::all(glm::equal(m0, m2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m1, m2, glm::epsilon())) ? 0 : 1; + + + std::vector const m3{ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}; + + glm::mat4 const m4{ + {1, 0, 0, 0}, + {0, 1, 0, 0}, + {0, 0, 1, 0}, + {0, 0, 0, 1} }; + + Error += glm::equal(m4[0][0], 1.0f, 0.0001f) ? 0 : 1; + Error += glm::equal(m4[3][3], 1.0f, 0.0001f) ? 0 : 1; + + std::vector const v1{ + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}}; + + std::vector const v2{ + { + { 0, 1, 2, 3 }, + { 4, 5, 6, 7 }, + { 8, 9, 10, 11 }, + { 12, 13, 14, 15 } + }, + { + { 0, 1, 2, 3 }, + { 4, 5, 6, 7 }, + { 8, 9, 10, 11 }, + { 12, 13, 14, 15 } + }}; + +#endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +static int test_member_alloc_bug() +{ + int Error = 0; + + struct repro + { + repro(){ this->matrix = new glm::mat4(); } + ~repro(){delete this->matrix;} + + glm::mat4* matrix; + }; + + repro Repro; + + return Error; +} + +static int test_size() +{ + int Error = 0; + + Error += 64 == sizeof(glm::mat4) ? 0 : 1; + Error += 128 == sizeof(glm::dmat4) ? 0 : 1; + Error += glm::mat4().length() == 4 ? 0 : 1; + Error += glm::dmat4().length() == 4 ? 0 : 1; + Error += glm::mat4::length() == 4 ? 0 : 1; + Error += glm::dmat4::length() == 4 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::mat4::length() == 4, "GLM: Failed constexpr"); + constexpr glm::mat4 A(1.f); + constexpr glm::mat4 B(1.f); + constexpr glm::bvec4 C = glm::equal(A, B, 0.01f); + static_assert(glm::all(C), "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_member_alloc_bug(); + Error += test_ctr(); + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_inverse(); + Error += test_inverse(); + Error += test_inverse(); + Error += test_inverse(); + + Error += test_inverse(); + Error += test_inverse(); + Error += test_inverse(); + Error += test_inverse(); + + Error += test_size(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_vec1.cpp b/vendor/glm/test/core/core_type_vec1.cpp new file mode 100644 index 0000000..77f3f84 --- /dev/null +++ b/vendor/glm/test/core/core_type_vec1.cpp @@ -0,0 +1,169 @@ +#define GLM_FORCE_SWIZZLE +#include +#include +#include +#include +#include + +static glm::vec1 g1; +static glm::vec1 g2(1); + +int test_vec1_operators() +{ + int Error = 0; + + glm::ivec1 A(1); + glm::ivec1 B(1); + { + bool R = A != B; + bool S = A == B; + + Error += (S && !R) ? 0 : 1; + } + + { + A *= 1; + B *= 1; + A += 1; + B += 1; + + bool R = A != B; + bool S = A == B; + + Error += (S && !R) ? 0 : 1; + } + + return Error; +} + +int test_vec1_ctor() +{ + int Error = 0; + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + +/* +#if GLM_HAS_INITIALIZER_LISTS + { + glm::vec1 a{ 0 }; + std::vector v = { + {0.f}, + {4.f}, + {8.f}}; + } + + { + glm::dvec2 a{ 0 }; + std::vector v = { + {0.0}, + {4.0}, + {8.0}}; + } +#endif +*/ + + { + glm::vec2 A = glm::vec2(2.0f); + glm::vec2 B = glm::vec2(2.0f, 3.0f); + glm::vec2 C = glm::vec2(2.0f, 3.0); + //glm::vec2 D = glm::dvec2(2.0); // Build error TODO: What does the specification says? + glm::vec2 E(glm::dvec2(2.0)); + glm::vec2 F(glm::ivec2(2)); + } + + return Error; +} + +static int test_vec1_size() +{ + int Error = 0; + + Error += sizeof(glm::vec1) == sizeof(glm::mediump_vec1) ? 0 : 1; + Error += 4 == sizeof(glm::mediump_vec1) ? 0 : 1; + Error += sizeof(glm::dvec1) == sizeof(glm::highp_dvec1) ? 0 : 1; + Error += 8 == sizeof(glm::highp_dvec1) ? 0 : 1; + Error += glm::vec1().length() == 1 ? 0 : 1; + Error += glm::dvec1().length() == 1 ? 0 : 1; + Error += glm::vec1::length() == 1 ? 0 : 1; + Error += glm::dvec1::length() == 1 ? 0 : 1; + + return Error; +} + +static int test_vec1_operator_increment() +{ + int Error(0); + + glm::ivec1 v0(1); + glm::ivec1 v1(v0); + glm::ivec1 v2(v0); + glm::ivec1 v3 = ++v1; + glm::ivec1 v4 = v2++; + + Error += glm::all(glm::equal(v0, v4)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v2)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v3)) ? 0 : 1; + + int i0(1); + int i1(i0); + int i2(i0); + int i3 = ++i1; + int i4 = i2++; + + Error += i0 == i4 ? 0 : 1; + Error += i1 == i2 ? 0 : 1; + Error += i1 == i3 ? 0 : 1; + + return Error; +} + +static int test_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::vec1 A = glm::vec1(1.0f); + //glm::vec1 B = A.x; + glm::vec1 C(A.x); + + //Error += glm::all(glm::equal(A, B)) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::vec1::length() == 1, "GLM: Failed constexpr"); + static_assert(glm::vec1(1.0f).x > 0.0f, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_vec1_size(); + Error += test_vec1_ctor(); + Error += test_vec1_operators(); + Error += test_vec1_operator_increment(); + Error += test_swizzle(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_vec2.cpp b/vendor/glm/test/core/core_type_vec2.cpp new file mode 100644 index 0000000..308c61f --- /dev/null +++ b/vendor/glm/test/core/core_type_vec2.cpp @@ -0,0 +1,392 @@ +#define GLM_FORCE_SWIZZLE +#include +#include +#include +#include +#include +#include +#include +#if GLM_HAS_TRIVIAL_QUERIES +# include +#endif + +static glm::ivec2 g1; +static glm::ivec2 g2(1); +static glm::ivec2 g3(1, 1); + +static int test_operators() +{ + int Error = 0; + + { + glm::ivec2 A(1); + glm::ivec2 B(1); + Error += A != B ? 1 : 0; + Error += A == B ? 0 : 1; + } + + { + glm::vec2 A(1.0f); + glm::vec2 C = A + 1.0f; + A += 1.0f; + Error += glm::all(glm::equal(A, glm::vec2(2.0f), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec2 A(1.0f); + glm::vec2 B(2.0f,-1.0f); + glm::vec2 C = A + B; + A += B; + Error += glm::all(glm::equal(A, glm::vec2(3.0f, 0.0f), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec2 A(1.0f); + glm::vec2 C = A - 1.0f; + A -= 1.0f; + Error += glm::all(glm::equal(A, glm::vec2(0.0f), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec2 A(1.0f); + glm::vec2 B(2.0f,-1.0f); + glm::vec2 C = A - B; + A -= B; + Error += glm::all(glm::equal(A, glm::vec2(-1.0f, 2.0f), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec2 A(1.0f); + glm::vec2 C = A * 2.0f; + A *= 2.0f; + Error += glm::all(glm::equal(A, glm::vec2(2.0f), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec2 A(2.0f); + glm::vec2 B(2.0f); + glm::vec2 C = A / B; + A /= B; + Error += glm::all(glm::equal(A, glm::vec2(1.0f), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec2 A(1.0f, 2.0f); + glm::vec2 B(4.0f, 5.0f); + + glm::vec2 C = A + B; + Error += glm::all(glm::equal(C, glm::vec2(5, 7), glm::epsilon())) ? 0 : 1; + + glm::vec2 D = B - A; + Error += glm::all(glm::equal(D, glm::vec2(3, 3), glm::epsilon())) ? 0 : 1; + + glm::vec2 E = A * B; + Error += glm::all(glm::equal(E, glm::vec2(4, 10), glm::epsilon())) ? 0 : 1; + + glm::vec2 F = B / A; + Error += glm::all(glm::equal(F, glm::vec2(4, 2.5), glm::epsilon())) ? 0 : 1; + + glm::vec2 G = A + 1.0f; + Error += glm::all(glm::equal(G, glm::vec2(2, 3), glm::epsilon())) ? 0 : 1; + + glm::vec2 H = B - 1.0f; + Error += glm::all(glm::equal(H, glm::vec2(3, 4), glm::epsilon())) ? 0 : 1; + + glm::vec2 I = A * 2.0f; + Error += glm::all(glm::equal(I, glm::vec2(2, 4), glm::epsilon())) ? 0 : 1; + + glm::vec2 J = B / 2.0f; + Error += glm::all(glm::equal(J, glm::vec2(2, 2.5), glm::epsilon())) ? 0 : 1; + + glm::vec2 K = 1.0f + A; + Error += glm::all(glm::equal(K, glm::vec2(2, 3), glm::epsilon())) ? 0 : 1; + + glm::vec2 L = 1.0f - B; + Error += glm::all(glm::equal(L, glm::vec2(-3, -4), glm::epsilon())) ? 0 : 1; + + glm::vec2 M = 2.0f * A; + Error += glm::all(glm::equal(M, glm::vec2(2, 4), glm::epsilon())) ? 0 : 1; + + glm::vec2 N = 2.0f / B; + Error += glm::all(glm::equal(N, glm::vec2(0.5, 2.0 / 5.0), glm::epsilon())) ? 0 : 1; + } + + { + glm::vec2 A(1.0f, 2.0f); + glm::vec2 B(4.0f, 5.0f); + + A += B; + Error += glm::all(glm::equal(A, glm::vec2(5, 7), glm::epsilon())) ? 0 : 1; + + A += 1.0f; + Error += glm::all(glm::equal(A, glm::vec2(6, 8), glm::epsilon())) ? 0 : 1; + } + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B(4.0f, 5.0f); + + B -= A; + Error += B == glm::ivec2(3, 3) ? 0 : 1; + + B -= 1.0f; + Error += B == glm::ivec2(2, 2) ? 0 : 1; + } + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B(4.0f, 5.0f); + + A *= B; + Error += A == glm::ivec2(4, 10) ? 0 : 1; + + A *= 2; + Error += A == glm::ivec2(8, 20) ? 0 : 1; + } + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B(4.0f, 16.0f); + + B /= A; + Error += B == glm::ivec2(4, 8) ? 0 : 1; + + B /= 2.0f; + Error += B == glm::ivec2(2, 4) ? 0 : 1; + } + { + glm::ivec2 B(2); + + B /= B.y; + Error += B == glm::ivec2(1) ? 0 : 1; + } + + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B = -A; + Error += B == glm::ivec2(-1.0f, -2.0f) ? 0 : 1; + } + + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B = --A; + Error += B == glm::ivec2(0.0f, 1.0f) ? 0 : 1; + } + + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B = A--; + Error += B == glm::ivec2(1.0f, 2.0f) ? 0 : 1; + Error += A == glm::ivec2(0.0f, 1.0f) ? 0 : 1; + } + + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B = ++A; + Error += B == glm::ivec2(2.0f, 3.0f) ? 0 : 1; + } + + { + glm::ivec2 A(1.0f, 2.0f); + glm::ivec2 B = A++; + Error += B == glm::ivec2(1.0f, 2.0f) ? 0 : 1; + Error += A == glm::ivec2(2.0f, 3.0f) ? 0 : 1; + } + + return Error; +} + +static int test_ctor() +{ + int Error = 0; + + { + glm::ivec2 A(1); + glm::ivec2 B(A); + Error += A == B ? 0 : 1; + } + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + +#if GLM_HAS_INITIALIZER_LISTS + { + glm::vec2 a{ 0, 1 }; + std::vector v = { + {0, 1}, + {4, 5}, + {8, 9}}; + } + + { + glm::dvec2 a{ 0, 1 }; + std::vector v = { + {0, 1}, + {4, 5}, + {8, 9}}; + } +#endif + + { + glm::vec2 A = glm::vec2(2.0f); + glm::vec2 B = glm::vec2(2.0f, 3.0f); + glm::vec2 C = glm::vec2(2.0f, 3.0); + //glm::vec2 D = glm::dvec2(2.0); // Build error TODO: What does the specification says? + glm::vec2 E(glm::dvec2(2.0)); + glm::vec2 F(glm::ivec2(2)); + } + + { + glm::vec1 const R(1.0f); + glm::vec1 const S(2.0f); + glm::vec2 const O(1.0f, 2.0f); + + glm::vec2 const A(R); + glm::vec2 const B(1.0f); + Error += glm::all(glm::equal(A, B, 0.0001f)) ? 0 : 1; + + glm::vec2 const C(R, S); + Error += glm::all(glm::equal(C, O, 0.0001f)) ? 0 : 1; + + glm::vec2 const D(R, 2.0f); + Error += glm::all(glm::equal(D, O, 0.0001f)) ? 0 : 1; + + glm::vec2 const E(1.0f, S); + Error += glm::all(glm::equal(E, O, 0.0001f)) ? 0 : 1; + } + + { + glm::vec1 const R(1.0f); + glm::dvec1 const S(2.0); + glm::vec2 const O(1.0, 2.0); + + glm::vec2 const A(R); + glm::vec2 const B(1.0); + Error += glm::all(glm::equal(A, B, 0.0001f)) ? 0 : 1; + + glm::vec2 const C(R, S); + Error += glm::all(glm::equal(C, O, 0.0001f)) ? 0 : 1; + + glm::vec2 const D(R, 2.0); + Error += glm::all(glm::equal(D, O, 0.0001f)) ? 0 : 1; + + glm::vec2 const E(1.0, S); + Error += glm::all(glm::equal(E, O, 0.0001f)) ? 0 : 1; + } + + return Error; +} + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::vec2) == sizeof(glm::mediump_vec2) ? 0 : 1; + Error += 8 == sizeof(glm::mediump_vec2) ? 0 : 1; + Error += sizeof(glm::dvec2) == sizeof(glm::highp_dvec2) ? 0 : 1; + Error += 16 == sizeof(glm::highp_dvec2) ? 0 : 1; + Error += glm::vec2().length() == 2 ? 0 : 1; + Error += glm::dvec2().length() == 2 ? 0 : 1; + Error += glm::vec2::length() == 2 ? 0 : 1; + Error += glm::dvec2::length() == 2 ? 0 : 1; + + GLM_CONSTEXPR std::size_t Length = glm::vec2::length(); + Error += Length == 2 ? 0 : 1; + + return Error; +} + +static int test_operator_increment() +{ + int Error = 0; + + glm::ivec2 v0(1); + glm::ivec2 v1(v0); + glm::ivec2 v2(v0); + glm::ivec2 v3 = ++v1; + glm::ivec2 v4 = v2++; + + Error += glm::all(glm::equal(v0, v4)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v2)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v3)) ? 0 : 1; + + int i0(1); + int i1(i0); + int i2(i0); + int i3 = ++i1; + int i4 = i2++; + + Error += i0 == i4 ? 0 : 1; + Error += i1 == i2 ? 0 : 1; + Error += i1 == i3 ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::vec2::length() == 2, "GLM: Failed constexpr"); + static_assert(glm::vec2(1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec2(1.0f, -1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec2(1.0f, -1.0f).y < 0.0f, "GLM: Failed constexpr"); +#endif + + return 0; +} + +static int test_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::vec2 A = glm::vec2(1.0f, 2.0f); + glm::vec2 B = A.xy; + glm::vec2 C(A.xy); + glm::vec2 D(A.xy()); + + Error += glm::all(glm::equal(A, B, 0.0001f)) ? 0 : 1; + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + Error += glm::all(glm::equal(A, D, 0.0001f)) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + glm::vec2 A = glm::vec2(1.0f, 2.0f); + glm::vec2 B = A.xy(); + glm::vec2 C(A.xy()); + + Error += glm::all(glm::equal(A, B, 0.0001f)) ? 0 : 1; + Error += glm::all(glm::equal(A, C, 0.0001f)) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_ctor(); + Error += test_operators(); + Error += test_operator_increment(); + Error += test_swizzle(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_vec3.cpp b/vendor/glm/test/core/core_type_vec3.cpp new file mode 100644 index 0000000..4da8187 --- /dev/null +++ b/vendor/glm/test/core/core_type_vec3.cpp @@ -0,0 +1,628 @@ +#define GLM_FORCE_SWIZZLE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static glm::vec3 g1; +static glm::vec3 g2(1); +static glm::vec3 g3(1, 1, 1); + +int test_vec3_ctor() +{ + int Error = 0; + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + +# if GLM_HAS_INITIALIZER_LISTS + { + glm::vec3 a{ 0, 1, 2 }; + std::vector v = { + {0, 1, 2}, + {4, 5, 6}, + {8, 9, 0}}; + } + + { + glm::dvec3 a{ 0, 1, 2 }; + std::vector v = { + {0, 1, 2}, + {4, 5, 6}, + {8, 9, 0}}; + } +# endif + + { + glm::ivec3 A(1); + glm::ivec3 B(1, 1, 1); + + Error += A == B ? 0 : 1; + } + + { + std::vector Tests; + Tests.push_back(glm::ivec3(glm::ivec2(1, 2), 3)); + Tests.push_back(glm::ivec3(1, glm::ivec2(2, 3))); + Tests.push_back(glm::ivec3(1, 2, 3)); + Tests.push_back(glm::ivec3(glm::ivec4(1, 2, 3, 4))); + + for(std::size_t i = 0; i < Tests.size(); ++i) + Error += Tests[i] == glm::ivec3(1, 2, 3) ? 0 : 1; + } + + { + glm::vec1 const R(1.0f); + glm::vec1 const S(2.0f); + glm::vec1 const T(3.0f); + glm::vec3 const O(1.0f, 2.0f, 3.0f); + + glm::vec3 const A(R); + glm::vec3 const B(1.0f); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + + glm::vec3 const C(R, S, T); + Error += glm::all(glm::equal(C, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const D(R, 2.0f, 3.0f); + Error += glm::all(glm::equal(D, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const E(1.0f, S, 3.0f); + Error += glm::all(glm::equal(E, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const F(1.0f, S, T); + Error += glm::all(glm::equal(F, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const G(R, 2.0f, T); + Error += glm::all(glm::equal(G, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const H(R, S, 3.0f); + Error += glm::all(glm::equal(H, O, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec1 const R(1.0); + glm::dvec1 const S(2.0); + glm::vec1 const T(3.0); + glm::vec3 const O(1.0f, 2.0f, 3.0f); + + glm::vec3 const A(R); + glm::vec3 const B(1.0); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + + glm::vec3 const C(R, S, T); + Error += glm::all(glm::equal(C, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const D(R, 2.0, 3.0); + Error += glm::all(glm::equal(D, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const E(1.0f, S, 3.0); + Error += glm::all(glm::equal(E, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const F(1.0, S, T); + Error += glm::all(glm::equal(F, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const G(R, 2.0, T); + Error += glm::all(glm::equal(G, O, glm::epsilon())) ? 0 : 1; + + glm::vec3 const H(R, S, 3.0); + Error += glm::all(glm::equal(H, O, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +float foo() +{ + glm::vec3 bar = glm::vec3(0.0f, 1.0f, 1.0f); + + return glm::length(bar); +} + +static int test_bvec3_ctor() +{ + int Error = 0; + + glm::bvec3 const A(true); + glm::bvec3 const B(true); + glm::bvec3 const C(false); + glm::bvec3 const D = A && B; + glm::bvec3 const E = A && C; + glm::bvec3 const F = A || C; + + Error += D == glm::bvec3(true) ? 0 : 1; + Error += E == glm::bvec3(false) ? 0 : 1; + Error += F == glm::bvec3(true) ? 0 : 1; + + bool const G = A == C; + bool const H = A != C; + Error += !G ? 0 : 1; + Error += H ? 0 : 1; + + return Error; +} + +static int test_vec3_operators() +{ + int Error = 0; + + { + glm::ivec3 A(1); + glm::ivec3 B(1); + bool R = A != B; + bool S = A == B; + + Error += (S && !R) ? 0 : 1; + } + + { + glm::vec3 const A(1.0f, 2.0f, 3.0f); + glm::vec3 const B(4.0f, 5.0f, 6.0f); + + glm::vec3 const C = A + B; + Error += glm::all(glm::equal(C, glm::vec3(5, 7, 9), glm::epsilon())) ? 0 : 1; + + glm::vec3 const D = B - A; + Error += glm::all(glm::equal(D, glm::vec3(3, 3, 3), glm::epsilon())) ? 0 : 1; + + glm::vec3 const E = A * B; + Error += glm::all(glm::equal(E, glm::vec3(4, 10, 18), glm::epsilon())) ? 0 : 1; + + glm::vec3 const F = B / A; + Error += glm::all(glm::equal(F, glm::vec3(4, 2.5, 2), glm::epsilon())) ? 0 : 1; + + glm::vec3 const G = A + 1.0f; + Error += glm::all(glm::equal(G, glm::vec3(2, 3, 4), glm::epsilon())) ? 0 : 1; + + glm::vec3 const H = B - 1.0f; + Error += glm::all(glm::equal(H, glm::vec3(3, 4, 5), glm::epsilon())) ? 0 : 1; + + glm::vec3 const I = A * 2.0f; + Error += glm::all(glm::equal(I, glm::vec3(2, 4, 6), glm::epsilon())) ? 0 : 1; + + glm::vec3 const J = B / 2.0f; + Error += glm::all(glm::equal(J, glm::vec3(2, 2.5, 3), glm::epsilon())) ? 0 : 1; + + glm::vec3 const K = 1.0f + A; + Error += glm::all(glm::equal(K, glm::vec3(2, 3, 4), glm::epsilon())) ? 0 : 1; + + glm::vec3 const L = 1.0f - B; + Error += glm::all(glm::equal(L, glm::vec3(-3, -4, -5), glm::epsilon())) ? 0 : 1; + + glm::vec3 const M = 2.0f * A; + Error += glm::all(glm::equal(M, glm::vec3(2, 4, 6), glm::epsilon())) ? 0 : 1; + + glm::vec3 const N = 2.0f / B; + Error += glm::all(glm::equal(N, glm::vec3(0.5, 2.0 / 5.0, 2.0 / 6.0), glm::epsilon())) ? 0 : 1; + } + + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B(4.0f, 5.0f, 6.0f); + + A += B; + Error += A == glm::ivec3(5, 7, 9) ? 0 : 1; + + A += 1; + Error += A == glm::ivec3(6, 8, 10) ? 0 : 1; + } + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B(4.0f, 5.0f, 6.0f); + + B -= A; + Error += B == glm::ivec3(3, 3, 3) ? 0 : 1; + + B -= 1; + Error += B == glm::ivec3(2, 2, 2) ? 0 : 1; + } + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B(4.0f, 5.0f, 6.0f); + + A *= B; + Error += A == glm::ivec3(4, 10, 18) ? 0 : 1; + + A *= 2; + Error += A == glm::ivec3(8, 20, 36) ? 0 : 1; + } + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B(4.0f, 4.0f, 6.0f); + + B /= A; + Error += B == glm::ivec3(4, 2, 2) ? 0 : 1; + + B /= 2; + Error += B == glm::ivec3(2, 1, 1) ? 0 : 1; + } + { + glm::ivec3 B(2); + + B /= B.y; + Error += B == glm::ivec3(1) ? 0 : 1; + } + + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B = -A; + Error += B == glm::ivec3(-1.0f, -2.0f, -3.0f) ? 0 : 1; + } + + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B = --A; + Error += B == glm::ivec3(0.0f, 1.0f, 2.0f) ? 0 : 1; + } + + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B = A--; + Error += B == glm::ivec3(1.0f, 2.0f, 3.0f) ? 0 : 1; + Error += A == glm::ivec3(0.0f, 1.0f, 2.0f) ? 0 : 1; + } + + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B = ++A; + Error += B == glm::ivec3(2.0f, 3.0f, 4.0f) ? 0 : 1; + } + + { + glm::ivec3 A(1.0f, 2.0f, 3.0f); + glm::ivec3 B = A++; + Error += B == glm::ivec3(1.0f, 2.0f, 3.0f) ? 0 : 1; + Error += A == glm::ivec3(2.0f, 3.0f, 4.0f) ? 0 : 1; + } + + return Error; +} + +int test_vec3_size() +{ + int Error = 0; + + Error += sizeof(glm::vec3) == sizeof(glm::lowp_vec3) ? 0 : 1; + Error += sizeof(glm::vec3) == sizeof(glm::mediump_vec3) ? 0 : 1; + Error += sizeof(glm::vec3) == sizeof(glm::highp_vec3) ? 0 : 1; + Error += 12 == sizeof(glm::mediump_vec3) ? 0 : 1; + Error += sizeof(glm::dvec3) == sizeof(glm::lowp_dvec3) ? 0 : 1; + Error += sizeof(glm::dvec3) == sizeof(glm::mediump_dvec3) ? 0 : 1; + Error += sizeof(glm::dvec3) == sizeof(glm::highp_dvec3) ? 0 : 1; + Error += 24 == sizeof(glm::highp_dvec3) ? 0 : 1; + Error += glm::vec3().length() == 3 ? 0 : 1; + Error += glm::dvec3().length() == 3 ? 0 : 1; + Error += glm::vec3::length() == 3 ? 0 : 1; + Error += glm::dvec3::length() == 3 ? 0 : 1; + + GLM_CONSTEXPR std::size_t Length = glm::vec3::length(); + Error += Length == 3 ? 0 : 1; + + return Error; +} + +int test_vec3_swizzle3_2() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::ivec3 v(1, 2, 3); + glm::ivec2 u; + + // Can not assign a vec3 swizzle to a vec2 + //u = v.xyz; //Illegal + //u = v.rgb; //Illegal + //u = v.stp; //Illegal + + u = v.xx; Error += (u.x == 1 && u.y == 1) ? 0 : 1; + u = v.xy; Error += (u.x == 1 && u.y == 2) ? 0 : 1; + u = v.xz; Error += (u.x == 1 && u.y == 3) ? 0 : 1; + u = v.yx; Error += (u.x == 2 && u.y == 1) ? 0 : 1; + u = v.yy; Error += (u.x == 2 && u.y == 2) ? 0 : 1; + u = v.yz; Error += (u.x == 2 && u.y == 3) ? 0 : 1; + u = v.zx; Error += (u.x == 3 && u.y == 1) ? 0 : 1; + u = v.zy; Error += (u.x == 3 && u.y == 2) ? 0 : 1; + u = v.zz; Error += (u.x == 3 && u.y == 3) ? 0 : 1; + + u = v.rr; Error += (u.r == 1 && u.g == 1) ? 0 : 1; + u = v.rg; Error += (u.r == 1 && u.g == 2) ? 0 : 1; + u = v.rb; Error += (u.r == 1 && u.g == 3) ? 0 : 1; + u = v.gr; Error += (u.r == 2 && u.g == 1) ? 0 : 1; + u = v.gg; Error += (u.r == 2 && u.g == 2) ? 0 : 1; + u = v.gb; Error += (u.r == 2 && u.g == 3) ? 0 : 1; + u = v.br; Error += (u.r == 3 && u.g == 1) ? 0 : 1; + u = v.bg; Error += (u.r == 3 && u.g == 2) ? 0 : 1; + u = v.bb; Error += (u.r == 3 && u.g == 3) ? 0 : 1; + + u = v.ss; Error += (u.s == 1 && u.t == 1) ? 0 : 1; + u = v.st; Error += (u.s == 1 && u.t == 2) ? 0 : 1; + u = v.sp; Error += (u.s == 1 && u.t == 3) ? 0 : 1; + u = v.ts; Error += (u.s == 2 && u.t == 1) ? 0 : 1; + u = v.tt; Error += (u.s == 2 && u.t == 2) ? 0 : 1; + u = v.tp; Error += (u.s == 2 && u.t == 3) ? 0 : 1; + u = v.ps; Error += (u.s == 3 && u.t == 1) ? 0 : 1; + u = v.pt; Error += (u.s == 3 && u.t == 2) ? 0 : 1; + u = v.pp; Error += (u.s == 3 && u.t == 3) ? 0 : 1; + // Mixed member aliases are not valid + //u = v.rx; //Illegal + //u = v.sy; //Illegal + + u = glm::ivec2(1, 2); + v = glm::ivec3(1, 2, 3); + //v.xx = u; //Illegal + v.xy = u; Error += (v.x == 1 && v.y == 2 && v.z == 3) ? 0 : 1; + v.xz = u; Error += (v.x == 1 && v.y == 2 && v.z == 2) ? 0 : 1; + v.yx = u; Error += (v.x == 2 && v.y == 1 && v.z == 2) ? 0 : 1; + //v.yy = u; //Illegal + v.yz = u; Error += (v.x == 2 && v.y == 1 && v.z == 2) ? 0 : 1; + v.zx = u; Error += (v.x == 2 && v.y == 1 && v.z == 1) ? 0 : 1; + v.zy = u; Error += (v.x == 2 && v.y == 2 && v.z == 1) ? 0 : 1; + //v.zz = u; //Illegal + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + return Error; +} + +int test_vec3_swizzle3_3() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::ivec3 v(1, 2, 3); + glm::ivec3 u; + + u = v; Error += (u.x == 1 && u.y == 2 && u.z == 3) ? 0 : 1; + + u = v.xyz; Error += (u.x == 1 && u.y == 2 && u.z == 3) ? 0 : 1; + u = v.zyx; Error += (u.x == 3 && u.y == 2 && u.z == 1) ? 0 : 1; + u.zyx = v; Error += (u.x == 3 && u.y == 2 && u.z == 1) ? 0 : 1; + + u = v.rgb; Error += (u.x == 1 && u.y == 2 && u.z == 3) ? 0 : 1; + u = v.bgr; Error += (u.x == 3 && u.y == 2 && u.z == 1) ? 0 : 1; + u.bgr = v; Error += (u.x == 3 && u.y == 2 && u.z == 1) ? 0 : 1; + + u = v.stp; Error += (u.x == 1 && u.y == 2 && u.z == 3) ? 0 : 1; + u = v.pts; Error += (u.x == 3 && u.y == 2 && u.z == 1) ? 0 : 1; + u.pts = v; Error += (u.x == 3 && u.y == 2 && u.z == 1) ? 0 : 1; + } +# endif//GLM_LANG + + return Error; +} + +int test_vec3_swizzle_operators() +{ + int Error = 0; + + glm::ivec3 const u = glm::ivec3(1, 2, 3); + glm::ivec3 const v = glm::ivec3(10, 20, 30); + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::ivec3 q; + + // Swizzle, swizzle binary operators + q = u.xyz + v.xyz; Error += (q == (u + v)) ? 0 : 1; + q = (u.zyx + v.zyx).zyx; Error += (q == (u + v)) ? 0 : 1; + q = (u.xyz - v.xyz); Error += (q == (u - v)) ? 0 : 1; + q = (u.xyz * v.xyz); Error += (q == (u * v)) ? 0 : 1; + q = (u.xxx * v.xxx); Error += (q == glm::ivec3(u.x * v.x)) ? 0 : 1; + q = (u.xyz / v.xyz); Error += (q == (u / v)) ? 0 : 1; + + // vec, swizzle binary operators + q = u + v.xyz; Error += (q == (u + v)) ? 0 : 1; + q = (u - v.xyz); Error += (q == (u - v)) ? 0 : 1; + q = (u * v.xyz); Error += (q == (u * v)) ? 0 : 1; + q = (u * v.xxx); Error += (q == v.x * u) ? 0 : 1; + q = (u / v.xyz); Error += (q == (u / v)) ? 0 : 1; + + // swizzle,vec binary operators + q = u.xyz + v; Error += (q == (u + v)) ? 0 : 1; + q = (u.xyz - v); Error += (q == (u - v)) ? 0 : 1; + q = (u.xyz * v); Error += (q == (u * v)) ? 0 : 1; + q = (u.xxx * v); Error += (q == u.x * v) ? 0 : 1; + q = (u.xyz / v); Error += (q == (u / v)) ? 0 : 1; + } +# endif//GLM_LANG + + // Compile errors + //q = (u.yz * v.xyz); + //q = (u * v.xy); + + return Error; +} + +int test_vec3_swizzle_functions() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + // NOTE: template functions cannot pick up the implicit conversion from + // a swizzle to the unswizzled type, therefore the operator() must be + // used. E.g.: + // + // glm::dot(u.xy, v.xy); <--- Compile error + // glm::dot(u.xy(), v.xy()); <--- Compiles correctly + + float r; + + // vec2 + glm::vec2 a(1, 2); + glm::vec2 b(10, 20); + r = glm::dot(a, b); Error += (int(r) == 50) ? 0 : 1; + r = glm::dot(glm::vec2(a.xy()), glm::vec2(b.xy())); Error += (int(r) == 50) ? 0 : 1; + r = glm::dot(glm::vec2(a.xy()), glm::vec2(b.yy())); Error += (int(r) == 60) ? 0 : 1; + + // vec3 + glm::vec3 u = glm::vec3(1, 2, 3); + glm::vec3 v = glm::vec3(10, 20, 30); + r = glm::dot(u, v); Error += (int(r) == 140) ? 0 : 1; + r = glm::dot(u.xyz(), v.zyz()); Error += (int(r) == 160) ? 0 : 1; + r = glm::dot(u, v.zyx()); Error += (int(r) == 100) ? 0 : 1; + r = glm::dot(u.xyz(), v); Error += (int(r) == 140) ? 0 : 1; + r = glm::dot(u.xy(), v.xy()); Error += (int(r) == 50) ? 0 : 1; + + // vec4 + glm::vec4 s = glm::vec4(1, 2, 3, 4); + glm::vec4 t = glm::vec4(10, 20, 30, 40); + r = glm::dot(s, t); Error += (int(r) == 300) ? 0 : 1; + r = glm::dot(s.xyzw(), t.xyzw()); Error += (int(r) == 300) ? 0 : 1; + r = glm::dot(s.xyz(), t.xyz()); Error += (int(r) == 140) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + + return Error; +} + +int test_vec3_swizzle_partial() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::vec3 const A(1, 2, 3); + glm::vec3 B(A.xy, 3); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + } + + { + glm::ivec3 const A(1, 2, 3); + glm::ivec3 const B(1, A.yz); + Error += A == B ? 0 : 1; + } + + { + glm::ivec3 const A(1, 2, 3); + glm::ivec3 const B(A.xyz); + Error += A == B ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + + return Error; +} + +static int test_operator_increment() +{ + int Error = 0; + + glm::ivec3 v0(1); + glm::ivec3 v1(v0); + glm::ivec3 v2(v0); + glm::ivec3 v3 = ++v1; + glm::ivec3 v4 = v2++; + + Error += glm::all(glm::equal(v0, v4)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v2)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v3)) ? 0 : 1; + + int i0(1); + int i1(i0); + int i2(i0); + int i3 = ++i1; + int i4 = i2++; + + Error += i0 == i4 ? 0 : 1; + Error += i1 == i2 ? 0 : 1; + Error += i1 == i3 ? 0 : 1; + + return Error; +} + +static int test_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::vec3 A = glm::vec3(1.0f, 2.0f, 3.0f); + glm::vec3 B = A.xyz; + glm::vec3 C(A.xyz); + glm::vec3 D(A.xyz()); + glm::vec3 E(A.x, A.yz); + glm::vec3 F(A.x, A.yz()); + glm::vec3 G(A.xy, A.z); + glm::vec3 H(A.xy(), A.z); + + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, E, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, F, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, G, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, H, glm::epsilon())) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + glm::vec3 A = glm::vec3(1.0f, 2.0f, 3.0f); + glm::vec3 B = A.xyz(); + glm::vec3 C(A.xyz()); + glm::vec3 D(A.xyz()); + glm::vec3 E(A.x, A.yz()); + glm::vec3 F(A.x, A.yz()); + glm::vec3 G(A.xy(), A.z); + glm::vec3 H(A.xy(), A.z); + + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, E, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, F, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, G, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, H, glm::epsilon())) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::vec3::length() == 3, "GLM: Failed constexpr"); + static_assert(glm::vec3(1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec3(1.0f, -1.0f, -1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec3(1.0f, -1.0f, -1.0f).y < 0.0f, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_vec3_ctor(); + Error += test_bvec3_ctor(); + Error += test_vec3_operators(); + Error += test_vec3_size(); + Error += test_operator_increment(); + Error += test_constexpr(); + + Error += test_swizzle(); + Error += test_vec3_swizzle3_2(); + Error += test_vec3_swizzle3_3(); + Error += test_vec3_swizzle_partial(); + Error += test_vec3_swizzle_operators(); + Error += test_vec3_swizzle_functions(); + + return Error; +} diff --git a/vendor/glm/test/core/core_type_vec4.cpp b/vendor/glm/test/core/core_type_vec4.cpp new file mode 100644 index 0000000..5d65259 --- /dev/null +++ b/vendor/glm/test/core/core_type_vec4.cpp @@ -0,0 +1,850 @@ +#define GLM_FORCE_SWIZZLE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static glm::vec4 g1; +static glm::vec4 g2(1); +static glm::vec4 g3(1, 1, 1, 1); + +template +struct mask +{ + enum{value = Value}; +}; + +enum comp +{ + X, + Y, + Z, + W +}; + +//template +//__m128 swizzle(glm::vec4 const& v) +//{ +// __m128 Src = _mm_set_ps(v.w, v.z, v.y, v.x); +// return _mm_shuffle_ps(Src, Src, mask<(int(W) << 6) | (int(Z) << 4) | (int(Y) << 2) | (int(X) << 0)>::value); +//} + +static int test_vec4_ctor() +{ + int Error = 0; + + { + glm::ivec4 A(1, 2, 3, 4); + glm::ivec4 B(A); + Error += glm::all(glm::equal(A, B)) ? 0 : 1; + } + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + +#if GLM_HAS_INITIALIZER_LISTS + { + glm::vec4 a{ 0, 1, 2, 3 }; + std::vector v = { + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {8, 9, 0, 1}}; + } + + { + glm::dvec4 a{ 0, 1, 2, 3 }; + std::vector v = { + {0, 1, 2, 3}, + {4, 5, 6, 7}, + {8, 9, 0, 1}}; + } +#endif + + { + glm::ivec4 const A(1); + glm::ivec4 const B(1, 1, 1, 1); + + Error += A == B ? 0 : 1; + } + + { + std::vector Tests; + Tests.push_back(glm::ivec4(glm::ivec2(1, 2), 3, 4)); + Tests.push_back(glm::ivec4(1, glm::ivec2(2, 3), 4)); + Tests.push_back(glm::ivec4(1, 2, glm::ivec2(3, 4))); + Tests.push_back(glm::ivec4(glm::ivec3(1, 2, 3), 4)); + Tests.push_back(glm::ivec4(1, glm::ivec3(2, 3, 4))); + Tests.push_back(glm::ivec4(glm::ivec2(1, 2), glm::ivec2(3, 4))); + Tests.push_back(glm::ivec4(1, 2, 3, 4)); + Tests.push_back(glm::ivec4(glm::ivec4(1, 2, 3, 4))); + + for(std::size_t i = 0; i < Tests.size(); ++i) + Error += Tests[i] == glm::ivec4(1, 2, 3, 4) ? 0 : 1; + } + + { + glm::vec1 const R(1.0f); + glm::vec1 const S(2.0f); + glm::vec1 const T(3.0f); + glm::vec1 const U(4.0f); + glm::vec4 const O(1.0f, 2.0f, 3.0f, 4.0f); + + glm::vec4 const A(R); + glm::vec4 const B(1.0f); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + + glm::vec4 const C(R, S, T, U); + Error += glm::all(glm::equal(C, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const D(R, 2.0f, 3.0f, 4.0f); + Error += glm::all(glm::equal(D, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const E(1.0f, S, 3.0f, 4.0f); + Error += glm::all(glm::equal(E, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const F(R, S, 3.0f, 4.0f); + Error += glm::all(glm::equal(F, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const G(1.0f, 2.0f, T, 4.0f); + Error += glm::all(glm::equal(G, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const H(R, 2.0f, T, 4.0f); + Error += glm::all(glm::equal(H, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const I(1.0f, S, T, 4.0f); + Error += glm::all(glm::equal(I, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const J(R, S, T, 4.0f); + Error += glm::all(glm::equal(J, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const K(R, 2.0f, 3.0f, U); + Error += glm::all(glm::equal(K, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const L(1.0f, S, 3.0f, U); + Error += glm::all(glm::equal(L, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const M(R, S, 3.0f, U); + Error += glm::all(glm::equal(M, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const N(1.0f, 2.0f, T, U); + Error += glm::all(glm::equal(N, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const P(R, 2.0f, T, U); + Error += glm::all(glm::equal(P, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const Q(1.0f, S, T, U); + Error += glm::all(glm::equal(Q, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const V(R, S, T, U); + Error += glm::all(glm::equal(V, O, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec1 const R(1.0f); + glm::dvec1 const S(2.0); + glm::vec1 const T(3.0); + glm::dvec1 const U(4.0); + glm::vec4 const O(1.0f, 2.0, 3.0f, 4.0); + + glm::vec4 const A(R); + glm::vec4 const B(1.0); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + + glm::vec4 const C(R, S, T, U); + Error += glm::all(glm::equal(C, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const D(R, 2.0f, 3.0, 4.0f); + Error += glm::all(glm::equal(D, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const E(1.0, S, 3.0f, 4.0); + Error += glm::all(glm::equal(E, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const F(R, S, 3.0, 4.0f); + Error += glm::all(glm::equal(F, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const G(1.0f, 2.0, T, 4.0); + Error += glm::all(glm::equal(G, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const H(R, 2.0, T, 4.0); + Error += glm::all(glm::equal(H, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const I(1.0, S, T, 4.0f); + Error += glm::all(glm::equal(I, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const J(R, S, T, 4.0f); + Error += glm::all(glm::equal(J, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const K(R, 2.0f, 3.0, U); + Error += glm::all(glm::equal(K, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const L(1.0f, S, 3.0, U); + Error += glm::all(glm::equal(L, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const M(R, S, 3.0, U); + Error += glm::all(glm::equal(M, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const N(1.0f, 2.0, T, U); + Error += glm::all(glm::equal(N, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const P(R, 2.0, T, U); + Error += glm::all(glm::equal(P, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const Q(1.0f, S, T, U); + Error += glm::all(glm::equal(Q, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const V(R, S, T, U); + Error += glm::all(glm::equal(V, O, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec1 const v1_0(1.0f); + glm::vec1 const v1_1(2.0f); + glm::vec1 const v1_2(3.0f); + glm::vec1 const v1_3(4.0f); + + glm::vec2 const v2_0(1.0f, 2.0f); + glm::vec2 const v2_1(2.0f, 3.0f); + glm::vec2 const v2_2(3.0f, 4.0f); + + glm::vec3 const v3_0(1.0f, 2.0f, 3.0f); + glm::vec3 const v3_1(2.0f, 3.0f, 4.0f); + + glm::vec4 const O(1.0f, 2.0, 3.0f, 4.0); + + glm::vec4 const A(v1_0, v1_1, v2_2); + Error += glm::all(glm::equal(A, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const B(1.0f, 2.0f, v2_2); + Error += glm::all(glm::equal(B, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const C(v1_0, 2.0f, v2_2); + Error += glm::all(glm::equal(C, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const D(1.0f, v1_1, v2_2); + Error += glm::all(glm::equal(D, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const E(v2_0, v1_2, v1_3); + Error += glm::all(glm::equal(E, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const F(v2_0, 3.0, v1_3); + Error += glm::all(glm::equal(F, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const G(v2_0, v1_2, 4.0); + Error += glm::all(glm::equal(G, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const H(v2_0, 3.0f, 4.0); + Error += glm::all(glm::equal(H, O, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec1 const v1_0(1.0f); + glm::vec1 const v1_1(2.0f); + glm::vec1 const v1_2(3.0f); + glm::vec1 const v1_3(4.0f); + + glm::vec2 const v2(2.0f, 3.0f); + + glm::vec4 const O(1.0f, 2.0, 3.0f, 4.0); + + glm::vec4 const A(v1_0, v2, v1_3); + Error += glm::all(glm::equal(A, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const B(v1_0, v2, 4.0); + Error += glm::all(glm::equal(B, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const C(1.0, v2, v1_3); + Error += glm::all(glm::equal(C, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const D(1.0f, v2, 4.0); + Error += glm::all(glm::equal(D, O, glm::epsilon())) ? 0 : 1; + + glm::vec4 const E(1.0, v2, 4.0f); + Error += glm::all(glm::equal(E, O, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +static int test_bvec4_ctor() +{ + int Error = 0; + + glm::bvec4 const A(true); + glm::bvec4 const B(true); + glm::bvec4 const C(false); + glm::bvec4 const D = A && B; + glm::bvec4 const E = A && C; + glm::bvec4 const F = A || C; + + Error += D == glm::bvec4(true) ? 0 : 1; + Error += E == glm::bvec4(false) ? 0 : 1; + Error += F == glm::bvec4(true) ? 0 : 1; + + bool const G = A == C; + bool const H = A != C; + Error += !G ? 0 : 1; + Error += H ? 0 : 1; + + return Error; +} + +static int test_operators() +{ + int Error = 0; + + { + glm::ivec4 A(1); + glm::ivec4 B(1); + bool R = A != B; + bool S = A == B; + + Error += (S && !R) ? 0 : 1; + } + + { + glm::vec4 const A(1.0f, 2.0f, 3.0f, 4.0f); + glm::vec4 const B(4.0f, 5.0f, 6.0f, 7.0f); + + glm::vec4 const C = A + B; + Error += glm::all(glm::equal(C, glm::vec4(5, 7, 9, 11), glm::epsilon())) ? 0 : 1; + + glm::vec4 const D = B - A; + Error += glm::all(glm::equal(D, glm::vec4(3, 3, 3, 3), glm::epsilon())) ? 0 : 1; + + glm::vec4 const E = A * B; + Error += glm::all(glm::equal(E, glm::vec4(4, 10, 18, 28), glm::epsilon()) )? 0 : 1; + + glm::vec4 const F = B / A; + Error += glm::all(glm::equal(F, glm::vec4(4, 2.5, 2, 7.0f / 4.0f), glm::epsilon())) ? 0 : 1; + + glm::vec4 const G = A + 1.0f; + Error += glm::all(glm::equal(G, glm::vec4(2, 3, 4, 5), glm::epsilon())) ? 0 : 1; + + glm::vec4 const H = B - 1.0f; + Error += glm::all(glm::equal(H, glm::vec4(3, 4, 5, 6), glm::epsilon())) ? 0 : 1; + + glm::vec4 const I = A * 2.0f; + Error += glm::all(glm::equal(I, glm::vec4(2, 4, 6, 8), glm::epsilon())) ? 0 : 1; + + glm::vec4 const J = B / 2.0f; + Error += glm::all(glm::equal(J, glm::vec4(2, 2.5, 3, 3.5), glm::epsilon())) ? 0 : 1; + + glm::vec4 const K = 1.0f + A; + Error += glm::all(glm::equal(K, glm::vec4(2, 3, 4, 5), glm::epsilon())) ? 0 : 1; + + glm::vec4 const L = 1.0f - B; + Error += glm::all(glm::equal(L, glm::vec4(-3, -4, -5, -6), glm::epsilon())) ? 0 : 1; + + glm::vec4 const M = 2.0f * A; + Error += glm::all(glm::equal(M, glm::vec4(2, 4, 6, 8), glm::epsilon())) ? 0 : 1; + + glm::vec4 const N = 2.0f / B; + Error += glm::all(glm::equal(N, glm::vec4(0.5, 2.0 / 5.0, 2.0 / 6.0, 2.0 / 7.0), glm::epsilon())) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B(4.0f, 5.0f, 6.0f, 7.0f); + + A += B; + Error += A == glm::ivec4(5, 7, 9, 11) ? 0 : 1; + + A += 1; + Error += A == glm::ivec4(6, 8, 10, 12) ? 0 : 1; + } + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B(4.0f, 5.0f, 6.0f, 7.0f); + + B -= A; + Error += B == glm::ivec4(3, 3, 3, 3) ? 0 : 1; + + B -= 1; + Error += B == glm::ivec4(2, 2, 2, 2) ? 0 : 1; + } + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B(4.0f, 5.0f, 6.0f, 7.0f); + + A *= B; + Error += A == glm::ivec4(4, 10, 18, 28) ? 0 : 1; + + A *= 2; + Error += A == glm::ivec4(8, 20, 36, 56) ? 0 : 1; + } + { + glm::ivec4 A(1.0f, 2.0f, 2.0f, 4.0f); + glm::ivec4 B(4.0f, 4.0f, 8.0f, 8.0f); + + B /= A; + Error += B == glm::ivec4(4, 2, 4, 2) ? 0 : 1; + + B /= 2; + Error += B == glm::ivec4(2, 1, 2, 1) ? 0 : 1; + } + { + glm::ivec4 B(2); + + B /= B.y; + Error += B == glm::ivec4(1) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = -A; + Error += B == glm::ivec4(-1.0f, -2.0f, -3.0f, -4.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = --A; + Error += B == glm::ivec4(0.0f, 1.0f, 2.0f, 3.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = A--; + Error += B == glm::ivec4(1.0f, 2.0f, 3.0f, 4.0f) ? 0 : 1; + Error += A == glm::ivec4(0.0f, 1.0f, 2.0f, 3.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = ++A; + Error += B == glm::ivec4(2.0f, 3.0f, 4.0f, 5.0f) ? 0 : 1; + } + + { + glm::ivec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = A++; + Error += B == glm::ivec4(1.0f, 2.0f, 3.0f, 4.0f) ? 0 : 1; + Error += A == glm::ivec4(2.0f, 3.0f, 4.0f, 5.0f) ? 0 : 1; + } + + return Error; +} + +static int test_equal() +{ + int Error = 0; + + { + glm::uvec4 const A(1, 2, 3, 4); + glm::uvec4 const B(1, 2, 3, 4); + Error += A == B ? 0 : 1; + Error += A != B ? 1 : 0; + } + + { + glm::ivec4 const A(1, 2, 3, 4); + glm::ivec4 const B(1, 2, 3, 4); + Error += A == B ? 0 : 1; + Error += A != B ? 1 : 0; + } + + return Error; +} + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::vec4) == sizeof(glm::lowp_vec4) ? 0 : 1; + Error += sizeof(glm::vec4) == sizeof(glm::mediump_vec4) ? 0 : 1; + Error += sizeof(glm::vec4) == sizeof(glm::highp_vec4) ? 0 : 1; + Error += 16 == sizeof(glm::mediump_vec4) ? 0 : 1; + Error += sizeof(glm::dvec4) == sizeof(glm::lowp_dvec4) ? 0 : 1; + Error += sizeof(glm::dvec4) == sizeof(glm::mediump_dvec4) ? 0 : 1; + Error += sizeof(glm::dvec4) == sizeof(glm::highp_dvec4) ? 0 : 1; + Error += 32 == sizeof(glm::highp_dvec4) ? 0 : 1; + Error += glm::vec4().length() == 4 ? 0 : 1; + Error += glm::dvec4().length() == 4 ? 0 : 1; + Error += glm::vec4::length() == 4 ? 0 : 1; + Error += glm::dvec4::length() == 4 ? 0 : 1; + + return Error; +} + +static int test_swizzle_partial() +{ + int Error = 0; + + glm::vec4 const A(1, 2, 3, 4); + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::vec4 B(A.xy, A.zw); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + } + { + glm::vec4 B(A.xy, 3.0f, 4.0f); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + } + { + glm::vec4 B(1.0f, A.yz, 4.0f); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + } + { + glm::vec4 B(1.0f, 2.0f, A.zw); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + } + + { + glm::vec4 B(A.xyz, 4.0f); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + } + { + glm::vec4 B(1.0f, A.yzw); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + + return Error; +} + +static int test_swizzle() +{ + int Error = 0; + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + { + glm::ivec4 A = glm::ivec4(1.0f, 2.0f, 3.0f, 4.0f); + glm::ivec4 B = A.xyzw; + glm::ivec4 C(A.xyzw); + glm::ivec4 D(A.xyzw()); + glm::ivec4 E(A.x, A.yzw); + glm::ivec4 F(A.x, A.yzw()); + glm::ivec4 G(A.xyz, A.w); + glm::ivec4 H(A.xyz(), A.w); + glm::ivec4 I(A.xy, A.zw); + glm::ivec4 J(A.xy(), A.zw()); + glm::ivec4 K(A.x, A.y, A.zw); + glm::ivec4 L(A.x, A.yz, A.w); + glm::ivec4 M(A.xy, A.z, A.w); + + Error += glm::all(glm::equal(A, B)) ? 0 : 1; + Error += glm::all(glm::equal(A, C)) ? 0 : 1; + Error += glm::all(glm::equal(A, D)) ? 0 : 1; + Error += glm::all(glm::equal(A, E)) ? 0 : 1; + Error += glm::all(glm::equal(A, F)) ? 0 : 1; + Error += glm::all(glm::equal(A, G)) ? 0 : 1; + Error += glm::all(glm::equal(A, H)) ? 0 : 1; + Error += glm::all(glm::equal(A, I)) ? 0 : 1; + Error += glm::all(glm::equal(A, J)) ? 0 : 1; + Error += glm::all(glm::equal(A, K)) ? 0 : 1; + Error += glm::all(glm::equal(A, L)) ? 0 : 1; + Error += glm::all(glm::equal(A, M)) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + { + glm::vec4 A = glm::vec4(1.0f, 2.0f, 3.0f, 4.0f); + glm::vec4 B = A.xyzw(); + glm::vec4 C(A.xyzw()); + glm::vec4 D(A.xyzw()); + glm::vec4 E(A.x, A.yzw()); + glm::vec4 F(A.x, A.yzw()); + glm::vec4 G(A.xyz(), A.w); + glm::vec4 H(A.xyz(), A.w); + glm::vec4 I(A.xy(), A.zw()); + glm::vec4 J(A.xy(), A.zw()); + glm::vec4 K(A.x, A.y, A.zw()); + glm::vec4 L(A.x, A.yz(), A.w); + glm::vec4 M(A.xy(), A.z, A.w); + + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, E, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, F, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, G, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, H, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, I, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, J, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, K, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, L, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(A, M, glm::epsilon())) ? 0 : 1; + } +# endif//GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR || GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + + return Error; +} + +static int test_operator_increment() +{ + int Error = 0; + + glm::ivec4 v0(1); + glm::ivec4 v1(v0); + glm::ivec4 v2(v0); + glm::ivec4 v3 = ++v1; + glm::ivec4 v4 = v2++; + + Error += glm::all(glm::equal(v0, v4)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v2)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v3)) ? 0 : 1; + + int i0(1); + int i1(i0); + int i2(i0); + int i3 = ++i1; + int i4 = i2++; + + Error += i0 == i4 ? 0 : 1; + Error += i1 == i2 ? 0 : 1; + Error += i1 == i3 ? 0 : 1; + + return Error; +} + +struct AoS +{ + glm::vec4 A; + glm::vec3 B; + glm::vec3 C; + glm::vec2 D; +}; + +static int test_perf_AoS(std::size_t Size) +{ + int Error = 0; + + std::vector In; + std::vector Out; + In.resize(Size); + Out.resize(Size); + + std::clock_t StartTime = std::clock(); + + for(std::size_t i = 0; i < In.size(); ++i) + Out[i] = In[i]; + + std::clock_t EndTime = std::clock(); + + std::printf("AoS: %d\n", static_cast(EndTime - StartTime)); + + return Error; +} + +static int test_perf_SoA(std::size_t Size) +{ + int Error = 0; + + std::vector InA; + std::vector InB; + std::vector InC; + std::vector InD; + std::vector OutA; + std::vector OutB; + std::vector OutC; + std::vector OutD; + + InA.resize(Size); + InB.resize(Size); + InC.resize(Size); + InD.resize(Size); + OutA.resize(Size); + OutB.resize(Size); + OutC.resize(Size); + OutD.resize(Size); + + std::clock_t StartTime = std::clock(); + + for(std::size_t i = 0; i < InA.size(); ++i) + { + OutA[i] = InA[i]; + OutB[i] = InB[i]; + OutC[i] = InC[i]; + OutD[i] = InD[i]; + } + + std::clock_t EndTime = std::clock(); + + std::printf("SoA: %d\n", static_cast(EndTime - StartTime)); + + return Error; +} + +namespace heap +{ + struct A + { + float f; + }; + + struct B : public A + { + float g; + glm::vec4 v; + }; + + static int test() + { + int Error = 0; + + A* p = new B; + p->f = 0.0f; + delete p; + + Error += sizeof(B) == sizeof(glm::vec4) + sizeof(float) * 2 ? 0 : 1; + + return Error; + } +}//namespace heap + +static int test_simd() +{ + int Error = 0; + + glm::vec4 const a(std::clock(), std::clock(), std::clock(), std::clock()); + glm::vec4 const b(std::clock(), std::clock(), std::clock(), std::clock()); + + glm::vec4 const c(b * a); + glm::vec4 const d(a + c); + + Error += glm::all(glm::greaterThanEqual(d, glm::vec4(0))) ? 0 : 1; + + return Error; +} + +static int test_inheritance() +{ + struct my_vec4 : public glm::vec4 + { + my_vec4() + : glm::vec4(76.f, 75.f, 74.f, 73.f) + , member(82) + {} + + int member; + }; + + int Error = 0; + + my_vec4 v; + + Error += v.member == 82 ? 0 : 1; + Error += glm::equal(v.x, 76.f, glm::epsilon()) ? 0 : 1; + Error += glm::equal(v.y, 75.f, glm::epsilon()) ? 0 : 1; + Error += glm::equal(v.z, 74.f, glm::epsilon()) ? 0 : 1; + Error += glm::equal(v.w, 73.f, glm::epsilon()) ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::vec4::length() == 4, "GLM: Failed constexpr"); + static_assert(glm::vec4(1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec4(1.0f, -1.0f, -1.0f, -1.0f).x > 0.0f, "GLM: Failed constexpr"); + static_assert(glm::vec4(1.0f, -1.0f, -1.0f, -1.0f).y < 0.0f, "GLM: Failed constexpr"); +#endif + + return 0; +} +/* +static int test_simd_gen() +{ + int Error = 0; + + int const C = static_cast(std::clock()); + int const D = static_cast(std::clock()); + + glm::ivec4 const A(C); + glm::ivec4 const B(D); + + Error += A != B ? 0 : 1; + + return Error; +} +*/ +int main() +{ + int Error = 0; + + //Error += test_simd_gen(); + +/* + { + glm::ivec4 const a1(2); + glm::ivec4 const b1 = a1 >> 1; + + __m128i const e1 = _mm_set1_epi32(2); + __m128i const f1 = _mm_srli_epi32(e1, 1); + + glm::ivec4 const g1 = *reinterpret_cast(&f1); + + glm::ivec4 const a2(-2); + glm::ivec4 const b2 = a2 >> 1; + + __m128i const e2 = _mm_set1_epi32(-1); + __m128i const f2 = _mm_srli_epi32(e2, 1); + + glm::ivec4 const g2 = *reinterpret_cast(&f2); + + std::printf("GNI\n"); + } + + { + glm::uvec4 const a1(2); + glm::uvec4 const b1 = a1 >> 1u; + + __m128i const e1 = _mm_set1_epi32(2); + __m128i const f1 = _mm_srli_epi32(e1, 1); + + glm::uvec4 const g1 = *reinterpret_cast(&f1); + + glm::uvec4 const a2(-1); + glm::uvec4 const b2 = a2 >> 1u; + + __m128i const e2 = _mm_set1_epi32(-1); + __m128i const f2 = _mm_srli_epi32(e2, 1); + + glm::uvec4 const g2 = *reinterpret_cast(&f2); + + std::printf("GNI\n"); + } +*/ + +# ifdef NDEBUG + std::size_t const Size(1000000); +# else + std::size_t const Size(1); +# endif//NDEBUG + + Error += test_perf_AoS(Size); + Error += test_perf_SoA(Size); + + Error += test_vec4_ctor(); + Error += test_bvec4_ctor(); + Error += test_size(); + Error += test_operators(); + Error += test_equal(); + Error += test_swizzle(); + Error += test_swizzle_partial(); + Error += test_simd(); + Error += test_operator_increment(); + Error += heap::test(); + Error += test_inheritance(); + Error += test_constexpr(); + + return Error; +} + diff --git a/vendor/glm/test/ext/CMakeLists.txt b/vendor/glm/test/ext/CMakeLists.txt new file mode 100644 index 0000000..d8dbdd3 --- /dev/null +++ b/vendor/glm/test/ext/CMakeLists.txt @@ -0,0 +1,52 @@ +glmCreateTestGTC(ext_matrix_relational) +glmCreateTestGTC(ext_matrix_transform) +glmCreateTestGTC(ext_matrix_common) +glmCreateTestGTC(ext_matrix_int2x2_sized) +glmCreateTestGTC(ext_matrix_int2x3_sized) +glmCreateTestGTC(ext_matrix_int2x4_sized) +glmCreateTestGTC(ext_matrix_int3x2_sized) +glmCreateTestGTC(ext_matrix_int3x3_sized) +glmCreateTestGTC(ext_matrix_int3x4_sized) +glmCreateTestGTC(ext_matrix_int4x2_sized) +glmCreateTestGTC(ext_matrix_int4x3_sized) +glmCreateTestGTC(ext_matrix_int4x4_sized) +glmCreateTestGTC(ext_matrix_uint2x2_sized) +glmCreateTestGTC(ext_matrix_uint2x3_sized) +glmCreateTestGTC(ext_matrix_uint2x4_sized) +glmCreateTestGTC(ext_matrix_uint3x2_sized) +glmCreateTestGTC(ext_matrix_uint3x3_sized) +glmCreateTestGTC(ext_matrix_uint3x4_sized) +glmCreateTestGTC(ext_matrix_uint4x2_sized) +glmCreateTestGTC(ext_matrix_uint4x3_sized) +glmCreateTestGTC(ext_matrix_uint4x4_sized) +glmCreateTestGTC(ext_quaternion_common) +glmCreateTestGTC(ext_quaternion_exponential) +glmCreateTestGTC(ext_quaternion_geometric) +glmCreateTestGTC(ext_quaternion_relational) +glmCreateTestGTC(ext_quaternion_transform) +glmCreateTestGTC(ext_quaternion_trigonometric) +glmCreateTestGTC(ext_quaternion_type) +glmCreateTestGTC(ext_scalar_common) +glmCreateTestGTC(ext_scalar_constants) +glmCreateTestGTC(ext_scalar_int_sized) +glmCreateTestGTC(ext_scalar_uint_sized) +glmCreateTestGTC(ext_scalar_integer) +glmCreateTestGTC(ext_scalar_ulp) +glmCreateTestGTC(ext_scalar_relational) +glmCreateTestGTC(ext_vec1) +glmCreateTestGTC(ext_vector_bool1) +glmCreateTestGTC(ext_vector_common) +glmCreateTestGTC(ext_vector_iec559) +glmCreateTestGTC(ext_vector_int1_sized) +glmCreateTestGTC(ext_vector_int2_sized) +glmCreateTestGTC(ext_vector_int3_sized) +glmCreateTestGTC(ext_vector_int4_sized) +glmCreateTestGTC(ext_vector_integer) +glmCreateTestGTC(ext_vector_integer_sized) +glmCreateTestGTC(ext_vector_uint1_sized) +glmCreateTestGTC(ext_vector_uint2_sized) +glmCreateTestGTC(ext_vector_uint3_sized) +glmCreateTestGTC(ext_vector_uint4_sized) +glmCreateTestGTC(ext_vector_relational) +glmCreateTestGTC(ext_vector_ulp) + diff --git a/vendor/glm/test/ext/ext_matrix_clip_space.cpp b/vendor/glm/test/ext/ext_matrix_clip_space.cpp new file mode 100644 index 0000000..ca84c19 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_clip_space.cpp @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_common.cpp b/vendor/glm/test/ext/ext_matrix_common.cpp new file mode 100644 index 0000000..df0c3fe --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_common.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +static int test_mix() +{ + int Error = 0; + + { + glm::mat4 A(2); + glm::mat4 B(4); + glm::mat4 C = glm::mix(A, B, 0.5f); + glm::bvec4 const D = glm::equal(C, glm::mat4(3), 1); + Error += glm::all(D) ? 0 : 1; + } + + { + glm::mat4 A(2); + glm::mat4 B(4); + glm::mat4 C = glm::mix(A, B, 0.5); + glm::bvec4 const D = glm::equal(C, glm::mat4(3), 1); + Error += glm::all(D) ? 0 : 1; + } + + { + glm::dmat4 A(2); + glm::dmat4 B(4); + glm::dmat4 C = glm::mix(A, B, 0.5); + glm::bvec4 const D = glm::equal(C, glm::dmat4(3), 1); + Error += glm::all(D) ? 0 : 1; + } + + { + glm::dmat4 A(2); + glm::dmat4 B(4); + glm::dmat4 C = glm::mix(A, B, 0.5f); + glm::bvec4 const D = glm::equal(C, glm::dmat4(3), 1); + Error += glm::all(D) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_mix(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int2x2_sized.cpp b/vendor/glm/test/ext/ext_matrix_int2x2_sized.cpp new file mode 100644 index 0000000..93b6e86 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int2x2_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::i8mat2x2) == 4, "int8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::i16mat2x2) == 8, "int16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::i32mat2x2) == 16, "int32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::i64mat2x2) == 32, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat2x2) < sizeof(glm::i16mat2x2) ? 0 : 1; + Error += sizeof(glm::i16mat2x2) < sizeof(glm::i32mat2x2) ? 0 : 1; + Error += sizeof(glm::i32mat2x2) < sizeof(glm::i64mat2x2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int2x3_sized.cpp b/vendor/glm/test/ext/ext_matrix_int2x3_sized.cpp new file mode 100644 index 0000000..058f57b --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int2x3_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat2x3) == 6, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat2x3) == 12, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat2x3) == 24, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat2x3) == 48, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat2x3) < sizeof(glm::i16mat2x3) ? 0 : 1; + Error += sizeof(glm::i16mat2x3) < sizeof(glm::i32mat2x3) ? 0 : 1; + Error += sizeof(glm::i32mat2x3) < sizeof(glm::i64mat2x3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int2x4_sized.cpp b/vendor/glm/test/ext/ext_matrix_int2x4_sized.cpp new file mode 100644 index 0000000..c20198d --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int2x4_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat2x4) == 8, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat2x4) == 16, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat2x4) == 32, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat2x4) == 64, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat2x4) < sizeof(glm::i16mat2x4) ? 0 : 1; + Error += sizeof(glm::i16mat2x4) < sizeof(glm::i32mat2x4) ? 0 : 1; + Error += sizeof(glm::i32mat2x4) < sizeof(glm::i64mat2x4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int3x2_sized.cpp b/vendor/glm/test/ext/ext_matrix_int3x2_sized.cpp new file mode 100644 index 0000000..1d14029 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int3x2_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat3x2) == 6, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat3x2) == 12, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat3x2) == 24, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat3x2) == 48, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat3x2) < sizeof(glm::i16mat3x2) ? 0 : 1; + Error += sizeof(glm::i16mat3x2) < sizeof(glm::i32mat3x2) ? 0 : 1; + Error += sizeof(glm::i32mat3x2) < sizeof(glm::i64mat3x2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int3x3_sized.cpp b/vendor/glm/test/ext/ext_matrix_int3x3_sized.cpp new file mode 100644 index 0000000..d82836c --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int3x3_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat3x3) == 9, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat3x3) == 18, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat3x3) == 36, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat3x3) == 72, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat3x3) < sizeof(glm::i16mat3x3) ? 0 : 1; + Error += sizeof(glm::i16mat3x3) < sizeof(glm::i32mat3x3) ? 0 : 1; + Error += sizeof(glm::i32mat3x3) < sizeof(glm::i64mat3x3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int3x4_sized.cpp b/vendor/glm/test/ext/ext_matrix_int3x4_sized.cpp new file mode 100644 index 0000000..52b7d52 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int3x4_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat3x4) == 12, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat3x4) == 24, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat3x4) == 48, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat3x4) == 96, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat3x4) < sizeof(glm::i16mat3x4) ? 0 : 1; + Error += sizeof(glm::i16mat3x4) < sizeof(glm::i32mat3x4) ? 0 : 1; + Error += sizeof(glm::i32mat3x4) < sizeof(glm::i64mat3x4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int4x2_sized.cpp b/vendor/glm/test/ext/ext_matrix_int4x2_sized.cpp new file mode 100644 index 0000000..3c4566f --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int4x2_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat4x2) == 8, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat4x2) == 16, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat4x2) == 32, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat4x2) == 64, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat4x2) < sizeof(glm::i16mat4x2) ? 0 : 1; + Error += sizeof(glm::i16mat4x2) < sizeof(glm::i32mat4x2) ? 0 : 1; + Error += sizeof(glm::i32mat4x2) < sizeof(glm::i64mat4x2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int4x3_sized.cpp b/vendor/glm/test/ext/ext_matrix_int4x3_sized.cpp new file mode 100644 index 0000000..fb882af --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int4x3_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat4x3) == 12, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat4x3) == 24, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat4x3) == 48, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat4x3) == 96, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat4x3) < sizeof(glm::i16mat4x3) ? 0 : 1; + Error += sizeof(glm::i16mat4x3) < sizeof(glm::i32mat4x3) ? 0 : 1; + Error += sizeof(glm::i32mat4x3) < sizeof(glm::i64mat4x3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_int4x4_sized.cpp b/vendor/glm/test/ext/ext_matrix_int4x4_sized.cpp new file mode 100644 index 0000000..02769ea --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_int4x4_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8mat4x4) == 16, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16mat4x4) == 32, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32mat4x4) == 64, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64mat4x4) == 128, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8mat4x4) < sizeof(glm::i16mat4x4) ? 0 : 1; + Error += sizeof(glm::i16mat4x4) < sizeof(glm::i32mat4x4) ? 0 : 1; + Error += sizeof(glm::i32mat4x4) < sizeof(glm::i64mat4x4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_projection.cpp b/vendor/glm/test/ext/ext_matrix_projection.cpp new file mode 100644 index 0000000..88f6ae9 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_projection.cpp @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include +#include + +int main() +{ + int Error = 0; + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_relational.cpp b/vendor/glm/test/ext/ext_matrix_relational.cpp new file mode 100644 index 0000000..64c0dae --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_relational.cpp @@ -0,0 +1,163 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +static int test_equal() +{ + typedef typename matType::value_type valType; + + valType const Epsilon = static_cast(0.001f); + valType const One = static_cast(1); + valType const Two = static_cast(2); + + int Error = 0; + + Error += glm::all(glm::equal(matType(One), matType(One), Epsilon)) ? 0 : 1; + Error += glm::all(glm::equal(matType(One), matType(Two), vecType(Epsilon))) ? 1 : 0; + + return Error; +} + +template +static int test_notEqual() +{ + typedef typename matType::value_type valType; + + valType const Epsilon = static_cast(0.001f); + valType const One = static_cast(1); + valType const Two = static_cast(2); + + int Error = 0; + + Error += !glm::any(glm::notEqual(matType(One), matType(One), Epsilon)) ? 0 : 1; + Error += !glm::any(glm::notEqual(matType(One), matType(Two), vecType(Epsilon))) ? 1 : 0; + + return Error; +} + + +template +static int test_equal_ulps() +{ + typedef glm::mat<4, 4, T, glm::defaultp> mat4; + + T const One(1); + mat4 const Ones(1); + + int Error = 0; + + T const ULP1Plus = glm::nextFloat(One); + Error += glm::all(glm::equal(Ones, mat4(ULP1Plus), 1)) ? 0 : 1; + + T const ULP2Plus = glm::nextFloat(ULP1Plus); + Error += !glm::all(glm::equal(Ones, mat4(ULP2Plus), 1)) ? 0 : 1; + + T const ULP1Minus = glm::prevFloat(One); + Error += glm::all(glm::equal(Ones, mat4(ULP1Minus), 1)) ? 0 : 1; + + T const ULP2Minus = glm::prevFloat(ULP1Minus); + Error += !glm::all(glm::equal(Ones, mat4(ULP2Minus), 1)) ? 0 : 1; + + return Error; +} + +template +static int test_notEqual_ulps() +{ + typedef glm::mat<4, 4, T, glm::defaultp> mat4; + + T const One(1); + mat4 const Ones(1); + + int Error = 0; + + T const ULP1Plus = glm::nextFloat(One); + Error += !glm::all(glm::notEqual(Ones, mat4(ULP1Plus), 1)) ? 0 : 1; + + T const ULP2Plus = glm::nextFloat(ULP1Plus); + Error += glm::all(glm::notEqual(Ones, mat4(ULP2Plus), 1)) ? 0 : 1; + + T const ULP1Minus = glm::prevFloat(One); + Error += !glm::all(glm::notEqual(Ones, mat4(ULP1Minus), 1)) ? 0 : 1; + + T const ULP2Minus = glm::prevFloat(ULP1Minus); + Error += glm::all(glm::notEqual(Ones, mat4(ULP2Minus), 1)) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_equal_ulps(); + Error += test_equal_ulps(); + Error += test_notEqual_ulps(); + Error += test_notEqual_ulps(); + + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_transform.cpp b/vendor/glm/test/ext/ext_matrix_transform.cpp new file mode 100644 index 0000000..cf653b7 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_transform.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include + +static int test_translate() +{ + int Error = 0; + + glm::mat4 const M(1.0f); + glm::vec3 const V(1.0f); + + glm::mat4 const T = glm::translate(M, V); + Error += glm::all(glm::equal(T[3], glm::vec4(1.0f), glm::epsilon())) ? 0 : 1; + + return Error; +} + +static int test_scale() +{ + int Error = 0; + + glm::mat4 const M(1.0f); + glm::vec3 const V(2.0f); + + glm::mat4 const S = glm::scale(M, V); + glm::mat4 const R = glm::mat4( + glm::vec4(2, 0, 0, 0), + glm::vec4(0, 2, 0, 0), + glm::vec4(0, 0, 2, 0), + glm::vec4(0, 0, 0, 1)); + Error += glm::all(glm::equal(S, R, glm::epsilon())) ? 0 : 1; + + return Error; +} + +static int test_rotate() +{ + int Error = 0; + + glm::vec4 const A(1.0f, 0.0f, 0.0f, 1.0f); + + glm::mat4 const R = glm::rotate(glm::mat4(1.0f), glm::radians(90.f), glm::vec3(0, 0, 1)); + glm::vec4 const B = R * A; + Error += glm::all(glm::equal(B, glm::vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.0001f)) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_translate(); + Error += test_scale(); + Error += test_rotate(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint2x2_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint2x2_sized.cpp new file mode 100644 index 0000000..a9bd49c --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint2x2_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::u8mat2x2) == 4, "uint8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::u16mat2x2) == 8, "uint16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::u32mat2x2) == 16, "uint32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::u64mat2x2) == 32, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat2x2) < sizeof(glm::u16mat2x2) ? 0 : 1; + Error += sizeof(glm::u16mat2x2) < sizeof(glm::u32mat2x2) ? 0 : 1; + Error += sizeof(glm::u32mat2x2) < sizeof(glm::u64mat2x2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint2x3_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint2x3_sized.cpp new file mode 100644 index 0000000..0b75893 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint2x3_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat2x3) == 6, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat2x3) == 12, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat2x3) == 24, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat2x3) == 48, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat2x3) < sizeof(glm::u16mat2x3) ? 0 : 1; + Error += sizeof(glm::u16mat2x3) < sizeof(glm::u32mat2x3) ? 0 : 1; + Error += sizeof(glm::u32mat2x3) < sizeof(glm::u64mat2x3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint2x4_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint2x4_sized.cpp new file mode 100644 index 0000000..84af4dd --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint2x4_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat2x4) == 8, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat2x4) == 16, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat2x4) == 32, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat2x4) == 64, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat2x4) < sizeof(glm::u16mat2x4) ? 0 : 1; + Error += sizeof(glm::u16mat2x4) < sizeof(glm::u32mat2x4) ? 0 : 1; + Error += sizeof(glm::u32mat2x4) < sizeof(glm::u64mat2x4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint3x2_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint3x2_sized.cpp new file mode 100644 index 0000000..3c035e2 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint3x2_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat3x2) == 6, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat3x2) == 12, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat3x2) == 24, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat3x2) == 48, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat3x2) < sizeof(glm::u16mat3x2) ? 0 : 1; + Error += sizeof(glm::u16mat3x2) < sizeof(glm::u32mat3x2) ? 0 : 1; + Error += sizeof(glm::u32mat3x2) < sizeof(glm::u64mat3x2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint3x3_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint3x3_sized.cpp new file mode 100644 index 0000000..64384ed --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint3x3_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat3x3) == 9, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat3x3) == 18, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat3x3) == 36, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat3x3) == 72, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat3x3) < sizeof(glm::u16mat3x3) ? 0 : 1; + Error += sizeof(glm::u16mat3x3) < sizeof(glm::u32mat3x3) ? 0 : 1; + Error += sizeof(glm::u32mat3x3) < sizeof(glm::u64mat3x3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint3x4_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint3x4_sized.cpp new file mode 100644 index 0000000..7f743df --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint3x4_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat3x4) == 12, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat3x4) == 24, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat3x4) == 48, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat3x4) == 96, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat3x4) < sizeof(glm::u16mat3x4) ? 0 : 1; + Error += sizeof(glm::u16mat3x4) < sizeof(glm::u32mat3x4) ? 0 : 1; + Error += sizeof(glm::u32mat3x4) < sizeof(glm::u64mat3x4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint4x2_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint4x2_sized.cpp new file mode 100644 index 0000000..2b4453f --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint4x2_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat4x2) == 8, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat4x2) == 16, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat4x2) == 32, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat4x2) == 64, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat4x2) < sizeof(glm::u16mat4x2) ? 0 : 1; + Error += sizeof(glm::u16mat4x2) < sizeof(glm::u32mat4x2) ? 0 : 1; + Error += sizeof(glm::u32mat4x2) < sizeof(glm::u64mat4x2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint4x3_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint4x3_sized.cpp new file mode 100644 index 0000000..2820bde --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint4x3_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat4x3) == 12, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat4x3) == 24, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat4x3) == 48, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat4x3) == 96, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat4x3) < sizeof(glm::u16mat4x3) ? 0 : 1; + Error += sizeof(glm::u16mat4x3) < sizeof(glm::u32mat4x3) ? 0 : 1; + Error += sizeof(glm::u32mat4x3) < sizeof(glm::u64mat4x3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_matrix_uint4x4_sized.cpp b/vendor/glm/test/ext/ext_matrix_uint4x4_sized.cpp new file mode 100644 index 0000000..8f9e239 --- /dev/null +++ b/vendor/glm/test/ext/ext_matrix_uint4x4_sized.cpp @@ -0,0 +1,28 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8mat4x4) == 16, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16mat4x4) == 32, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32mat4x4) == 64, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64mat4x4) == 128, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8mat4x4) < sizeof(glm::u16mat4x4) ? 0 : 1; + Error += sizeof(glm::u16mat4x4) < sizeof(glm::u32mat4x4) ? 0 : 1; + Error += sizeof(glm::u32mat4x4) < sizeof(glm::u64mat4x4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_quaternion_common.cpp b/vendor/glm/test/ext/ext_quaternion_common.cpp new file mode 100644 index 0000000..861aa65 --- /dev/null +++ b/vendor/glm/test/ext/ext_quaternion_common.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include + +static int test_conjugate() +{ + int Error = 0; + + glm::quat const A(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0)); + glm::quat const C = glm::conjugate(A); + Error += glm::any(glm::notEqual(A, C, glm::epsilon())) ? 0 : 1; + + glm::quat const B = glm::conjugate(C); + Error += glm::all(glm::equal(A, B, glm::epsilon())) ? 0 : 1; + + return Error; +} + +static int test_mix() +{ + int Error = 0; + + glm::quat const Q1(glm::vec3(1, 0, 0), glm::vec3(1, 0, 0)); + glm::quat const Q2(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0)); + + { + glm::quat const Q3 = glm::mix(Q1, Q2, 0.5f); + float const F3 = glm::degrees(glm::angle(Q3)); + Error += glm::equal(F3, 45.0f, 0.001f) ? 0 : 1; + + glm::quat const Q4 = glm::mix(Q2, Q1, 0.5f); + float const F4 = glm::degrees(glm::angle(Q4)); + Error += glm::equal(F4, 45.0f, 0.001f) ? 0 : 1; + } + + { + glm::quat const Q3 = glm::slerp(Q1, Q2, 0.5f); + float const F3 = glm::degrees(glm::angle(Q3)); + Error += glm::equal(F3, 45.0f, 0.001f) ? 0 : 1; + + glm::quat const Q4 = glm::slerp(Q2, Q1, 0.5f); + float const F4 = glm::degrees(glm::angle(Q4)); + Error += glm::equal(F4, 45.0f, 0.001f) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_conjugate(); + Error += test_mix(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_quaternion_exponential.cpp b/vendor/glm/test/ext/ext_quaternion_exponential.cpp new file mode 100644 index 0000000..fbcdbef --- /dev/null +++ b/vendor/glm/test/ext/ext_quaternion_exponential.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +int test_log() +{ + typedef typename quaType::value_type T; + + T const Epsilon = static_cast(0.001f); + + int Error = 0; + + quaType const Q(vecType(1, 0, 0), vecType(0, 1, 0)); + quaType const P = glm::log(Q); + Error += glm::any(glm::notEqual(Q, P, Epsilon)) ? 0 : 1; + + quaType const R = glm::exp(P); + Error += glm::all(glm::equal(Q, R, Epsilon)) ? 0 : 1; + + return Error; +} + +template +int test_pow() +{ + typedef typename quaType::value_type T; + + T const Epsilon = static_cast(0.001f); + + int Error = 0; + + quaType const Q(vecType(1, 0, 0), vecType(0, 1, 0)); + + { + T const One = static_cast(1.0f); + quaType const P = glm::pow(Q, One); + Error += glm::all(glm::equal(Q, P, Epsilon)) ? 0 : 1; + } + + { + T const Two = static_cast(2.0f); + quaType const P = glm::pow(Q, Two); + quaType const R = Q * Q; + Error += glm::all(glm::equal(P, R, Epsilon)) ? 0 : 1; + + quaType const U = glm::sqrt(P); + Error += glm::all(glm::equal(Q, U, Epsilon)) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_log(); + Error += test_log(); + Error += test_log(); + Error += test_log(); + + Error += test_log(); + Error += test_log(); + Error += test_log(); + Error += test_log(); + + Error += test_pow(); + Error += test_pow(); + Error += test_pow(); + Error += test_pow(); + + Error += test_pow(); + Error += test_pow(); + Error += test_pow(); + Error += test_pow(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_quaternion_geometric.cpp b/vendor/glm/test/ext/ext_quaternion_geometric.cpp new file mode 100644 index 0000000..73b5dea --- /dev/null +++ b/vendor/glm/test/ext/ext_quaternion_geometric.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +float const Epsilon = 0.001f; + +static int test_length() +{ + int Error = 0; + + { + float const A = glm::length(glm::quat(1, 0, 0, 0)); + Error += glm::equal(A, 1.0f, Epsilon) ? 0 : 1; + } + + { + float const A = glm::length(glm::quat(1, glm::vec3(0))); + Error += glm::equal(A, 1.0f, Epsilon) ? 0 : 1; + } + + { + float const A = glm::length(glm::quat(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0))); + Error += glm::equal(A, 1.0f, Epsilon) ? 0 : 1; + } + + return Error; +} + +static int test_normalize() +{ + int Error = 0; + + { + glm::quat const A = glm::quat(1, 0, 0, 0); + glm::quat const N = glm::normalize(A); + Error += glm::all(glm::equal(A, N, Epsilon)) ? 0 : 1; + } + + { + glm::quat const A = glm::quat(1, glm::vec3(0)); + glm::quat const N = glm::normalize(A); + Error += glm::all(glm::equal(A, N, Epsilon)) ? 0 : 1; + } + + return Error; +} + +static int test_dot() +{ + int Error = 0; + + { + glm::quat const A = glm::quat(1, 0, 0, 0); + glm::quat const B = glm::quat(1, 0, 0, 0); + float const C = glm::dot(A, B); + Error += glm::equal(C, 1.0f, Epsilon) ? 0 : 1; + } + + return Error; +} + +static int test_cross() +{ + int Error = 0; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_length(); + Error += test_normalize(); + Error += test_dot(); + Error += test_cross(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_quaternion_relational.cpp b/vendor/glm/test/ext/ext_quaternion_relational.cpp new file mode 100644 index 0000000..7f51fdc --- /dev/null +++ b/vendor/glm/test/ext/ext_quaternion_relational.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +static int test_equal() +{ + int Error = 0; + + quaType const Q(1, 0, 0, 0); + quaType const P(1, 0, 0, 0); + Error += glm::all(glm::equal(Q, P, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_notEqual() +{ + int Error = 0; + + quaType const Q(1, 0, 0, 0); + quaType const P(1, 0, 0, 0); + Error += glm::any(glm::notEqual(Q, P, glm::epsilon())) ? 1 : 0; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_quaternion_transform.cpp b/vendor/glm/test/ext/ext_quaternion_transform.cpp new file mode 100644 index 0000000..fefe88e --- /dev/null +++ b/vendor/glm/test/ext/ext_quaternion_transform.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include + +static int test_lookAt() +{ + int Error(0); + + glm::vec3 eye(0.0f); + glm::vec3 center(1.1f, -2.0f, 3.1416f); + glm::vec3 up(-0.17f, 7.23f, -1.744f); + + glm::quat test_quat = glm::quatLookAt(glm::normalize(center - eye), up); + glm::quat test_mat = glm::conjugate(glm::quat_cast(glm::lookAt(eye, center, up))); + + Error += static_cast(glm::abs(glm::length(test_quat) - 1.0f) > glm::epsilon()); + Error += static_cast(glm::min(glm::length(test_quat + (-test_mat)), glm::length(test_quat + test_mat)) > glm::epsilon()); + + // Test left-handed implementation + glm::quat test_quatLH = glm::quatLookAtLH(glm::normalize(center - eye), up); + glm::quat test_matLH = glm::conjugate(glm::quat_cast(glm::lookAtLH(eye, center, up))); + Error += static_cast(glm::abs(glm::length(test_quatLH) - 1.0f) > glm::epsilon()); + Error += static_cast(glm::min(glm::length(test_quatLH - test_matLH), glm::length(test_quatLH + test_matLH)) > glm::epsilon()); + + // Test right-handed implementation + glm::quat test_quatRH = glm::quatLookAtRH(glm::normalize(center - eye), up); + glm::quat test_matRH = glm::conjugate(glm::quat_cast(glm::lookAtRH(eye, center, up))); + Error += static_cast(glm::abs(glm::length(test_quatRH) - 1.0f) > glm::epsilon()); + Error += static_cast(glm::min(glm::length(test_quatRH - test_matRH), glm::length(test_quatRH + test_matRH)) > glm::epsilon()); + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_lookAt(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_quaternion_trigonometric.cpp b/vendor/glm/test/ext/ext_quaternion_trigonometric.cpp new file mode 100644 index 0000000..1c1d608 --- /dev/null +++ b/vendor/glm/test/ext/ext_quaternion_trigonometric.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +float const Epsilon = 0.001f; + +static int test_angle() +{ + int Error = 0; + + { + glm::quat const Q = glm::quat(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0)); + float const A = glm::degrees(glm::angle(Q)); + Error += glm::equal(A, 90.0f, Epsilon) ? 0 : 1; + } + + { + glm::quat const Q = glm::quat(glm::vec3(0, 1, 0), glm::vec3(1, 0, 0)); + float const A = glm::degrees(glm::angle(Q)); + Error += glm::equal(A, 90.0f, Epsilon) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_angle(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_quaternion_type.cpp b/vendor/glm/test/ext/ext_quaternion_type.cpp new file mode 100644 index 0000000..7e61149 --- /dev/null +++ b/vendor/glm/test/ext/ext_quaternion_type.cpp @@ -0,0 +1,113 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static int test_ctr() +{ + int Error(0); + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + +# if GLM_HAS_INITIALIZER_LISTS + { + glm::quat A{0, 1, 2, 3}; + + std::vector B{ + {0, 1, 2, 3}, + {0, 1, 2, 3}}; + } +# endif//GLM_HAS_INITIALIZER_LISTS + + return Error; +} + +static int test_two_axis_ctr() +{ + int Error = 0; + + glm::quat const q1(glm::vec3(1, 0, 0), glm::vec3(0, 1, 0)); + glm::vec3 const v1 = q1 * glm::vec3(1, 0, 0); + Error += glm::all(glm::equal(v1, glm::vec3(0, 1, 0), 0.0001f)) ? 0 : 1; + + glm::quat const q2 = q1 * q1; + glm::vec3 const v2 = q2 * glm::vec3(1, 0, 0); + Error += glm::all(glm::equal(v2, glm::vec3(-1, 0, 0), 0.0001f)) ? 0 : 1; + + glm::quat const q3(glm::vec3(1, 0, 0), glm::vec3(-1, 0, 0)); + glm::vec3 const v3 = q3 * glm::vec3(1, 0, 0); + Error += glm::all(glm::equal(v3, glm::vec3(-1, 0, 0), 0.0001f)) ? 0 : 1; + + glm::quat const q4(glm::vec3(0, 1, 0), glm::vec3(0, -1, 0)); + glm::vec3 const v4 = q4 * glm::vec3(0, 1, 0); + Error += glm::all(glm::equal(v4, glm::vec3(0, -1, 0), 0.0001f)) ? 0 : 1; + + glm::quat const q5(glm::vec3(0, 0, 1), glm::vec3(0, 0, -1)); + glm::vec3 const v5 = q5 * glm::vec3(0, 0, 1); + Error += glm::all(glm::equal(v5, glm::vec3(0, 0, -1), 0.0001f)) ? 0 : 1; + + return Error; +} + +static int test_size() +{ + int Error = 0; + + std::size_t const A = sizeof(glm::quat); + Error += 16 == A ? 0 : 1; + std::size_t const B = sizeof(glm::dquat); + Error += 32 == B ? 0 : 1; + Error += glm::quat().length() == 4 ? 0 : 1; + Error += glm::dquat().length() == 4 ? 0 : 1; + Error += glm::quat::length() == 4 ? 0 : 1; + Error += glm::dquat::length() == 4 ? 0 : 1; + + return Error; +} + +static int test_precision() +{ + int Error = 0; + + Error += sizeof(glm::lowp_quat) <= sizeof(glm::mediump_quat) ? 0 : 1; + Error += sizeof(glm::mediump_quat) <= sizeof(glm::highp_quat) ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::quat::length() == 4, "GLM: Failed constexpr"); + static_assert(glm::quat(1.0f, glm::vec3(0.0f)).w > 0.0f, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_ctr(); + Error += test_two_axis_ctr(); + Error += test_size(); + Error += test_precision(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_scalar_common.cpp b/vendor/glm/test/ext/ext_scalar_common.cpp new file mode 100644 index 0000000..d3d22fb --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_common.cpp @@ -0,0 +1,327 @@ +#include +#include +#include +#include + +#if ((GLM_LANG & GLM_LANG_CXX11_FLAG) || (GLM_COMPILER & GLM_COMPILER_VC)) +# define GLM_NAN(T) NAN +#else +# define GLM_NAN(T) (static_cast(0.0f) / static_cast(0.0f)) +#endif + +template +static int test_min() +{ + int Error = 0; + + T const N = static_cast(0); + T const B = static_cast(1); + Error += glm::equal(glm::min(N, B), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(B, N), N, glm::epsilon()) ? 0 : 1; + + T const C = static_cast(2); + Error += glm::equal(glm::min(N, B, C), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(B, N, C), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(C, N, B), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(C, B, N), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(B, C, N), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(N, C, B), N, glm::epsilon()) ? 0 : 1; + + T const D = static_cast(3); + Error += glm::equal(glm::min(D, N, B, C), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(B, D, N, C), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(C, N, D, B), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(C, B, D, N), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(B, C, N, D), N, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::min(N, C, B, D), N, glm::epsilon()) ? 0 : 1; + + return Error; +} + +template +static int test_min_nan() +{ + int Error = 0; + + T const B = static_cast(1); + T const N = static_cast(GLM_NAN(T)); + Error += glm::isnan(glm::min(N, B)) ? 0 : 1; + Error += !glm::isnan(glm::min(B, N)) ? 0 : 1; + + T const C = static_cast(2); + Error += glm::isnan(glm::min(N, B, C)) ? 0 : 1; + Error += !glm::isnan(glm::min(B, N, C)) ? 0 : 1; + Error += !glm::isnan(glm::min(C, N, B)) ? 0 : 1; + Error += !glm::isnan(glm::min(C, B, N)) ? 0 : 1; + Error += !glm::isnan(glm::min(B, C, N)) ? 0 : 1; + Error += glm::isnan(glm::min(N, C, B)) ? 0 : 1; + + T const D = static_cast(3); + Error += !glm::isnan(glm::min(D, N, B, C)) ? 0 : 1; + Error += !glm::isnan(glm::min(B, D, N, C)) ? 0 : 1; + Error += !glm::isnan(glm::min(C, N, D, B)) ? 0 : 1; + Error += !glm::isnan(glm::min(C, B, D, N)) ? 0 : 1; + Error += !glm::isnan(glm::min(B, C, N, D)) ? 0 : 1; + Error += glm::isnan(glm::min(N, C, B, D)) ? 0 : 1; + + return Error; +} + +template +static int test_max() +{ + int Error = 0; + + T const N = static_cast(0); + T const B = static_cast(1); + Error += glm::equal(glm::max(N, B), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(B, N), B, glm::epsilon()) ? 0 : 1; + + T const C = static_cast(2); + Error += glm::equal(glm::max(N, B, C), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(B, N, C), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(C, N, B), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(C, B, N), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(B, C, N), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(N, C, B), C, glm::epsilon()) ? 0 : 1; + + T const D = static_cast(3); + Error += glm::equal(glm::max(D, N, B, C), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(B, D, N, C), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(C, N, D, B), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(C, B, D, N), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(B, C, N, D), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::max(N, C, B, D), D, glm::epsilon()) ? 0 : 1; + + return Error; +} + +template +static int test_max_nan() +{ + int Error = 0; + + T const B = static_cast(1); + T const N = static_cast(GLM_NAN(T)); + Error += glm::isnan(glm::max(N, B)) ? 0 : 1; + Error += !glm::isnan(glm::max(B, N)) ? 0 : 1; + + T const C = static_cast(2); + Error += glm::isnan(glm::max(N, B, C)) ? 0 : 1; + Error += !glm::isnan(glm::max(B, N, C)) ? 0 : 1; + Error += !glm::isnan(glm::max(C, N, B)) ? 0 : 1; + Error += !glm::isnan(glm::max(C, B, N)) ? 0 : 1; + Error += !glm::isnan(glm::max(B, C, N)) ? 0 : 1; + Error += glm::isnan(glm::max(N, C, B)) ? 0 : 1; + + T const D = static_cast(3); + Error += !glm::isnan(glm::max(D, N, B, C)) ? 0 : 1; + Error += !glm::isnan(glm::max(B, D, N, C)) ? 0 : 1; + Error += !glm::isnan(glm::max(C, N, D, B)) ? 0 : 1; + Error += !glm::isnan(glm::max(C, B, D, N)) ? 0 : 1; + Error += !glm::isnan(glm::max(B, C, N, D)) ? 0 : 1; + Error += glm::isnan(glm::max(N, C, B, D)) ? 0 : 1; + + return Error; +} + +template +static int test_fmin() +{ + int Error = 0; + + T const B = static_cast(1); + T const N = static_cast(GLM_NAN(T)); + Error += glm::equal(glm::fmin(N, B), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(B, N), B, glm::epsilon()) ? 0 : 1; + + T const C = static_cast(2); + Error += glm::equal(glm::fmin(N, B, C), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(B, N, C), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(C, N, B), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(C, B, N), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(B, C, N), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(N, C, B), B, glm::epsilon()) ? 0 : 1; + + T const D = static_cast(3); + Error += glm::equal(glm::fmin(D, N, B, C), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(B, D, N, C), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(C, N, D, B), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(C, B, D, N), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(B, C, N, D), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmin(N, C, B, D), B, glm::epsilon()) ? 0 : 1; + + return Error; +} + +template +static int test_fmax() +{ + int Error = 0; + + T const B = static_cast(1); + T const N = static_cast(GLM_NAN(T)); + Error += glm::equal(glm::fmax(N, B), B, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(B, N), B, glm::epsilon()) ? 0 : 1; + + T const C = static_cast(2); + Error += glm::equal(glm::fmax(N, B, C), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(B, N, C), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(C, N, B), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(C, B, N), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(B, C, N), C, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(N, C, B), C, glm::epsilon()) ? 0 : 1; + + T const D = static_cast(3); + Error += glm::equal(glm::fmax(D, N, B, C), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(B, D, N, C), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(C, N, D, B), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(C, B, D, N), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(B, C, N, D), D, glm::epsilon()) ? 0 : 1; + Error += glm::equal(glm::fmax(N, C, B, D), D, glm::epsilon()) ? 0 : 1; + + return Error; +} + +static int test_clamp() +{ + int Error = 0; + + float A = glm::clamp(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::clamp(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::clamp(1.0f); + Error += glm::equal(C, 1.0f, 0.00001f) ? 0 : 1; + + float D = glm::clamp(-0.5f); + Error += glm::equal(D, 0.0f, 0.00001f) ? 0 : 1; + + float E = glm::clamp(1.5f); + Error += glm::equal(E, 1.0f, 0.00001f) ? 0 : 1; + + return Error; +} + +static int test_repeat() +{ + int Error = 0; + + float A = glm::repeat(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::repeat(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::repeat(1.0f); + Error += glm::equal(C, 0.0f, 0.00001f) ? 0 : 1; + + float D = glm::repeat(-0.5f); + Error += glm::equal(D, 0.5f, 0.00001f) ? 0 : 1; + + float E = glm::repeat(1.5f); + Error += glm::equal(E, 0.5f, 0.00001f) ? 0 : 1; + + float F = glm::repeat(0.9f); + Error += glm::equal(F, 0.9f, 0.00001f) ? 0 : 1; + + return Error; +} + +static int test_mirrorClamp() +{ + int Error = 0; + + float A = glm::mirrorClamp(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::mirrorClamp(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::mirrorClamp(1.1f); + Error += glm::equal(C, 0.1f, 0.00001f) ? 0 : 1; + + float D = glm::mirrorClamp(-0.5f); + Error += glm::equal(D, 0.5f, 0.00001f) ? 0 : 1; + + float E = glm::mirrorClamp(1.5f); + Error += glm::equal(E, 0.5f, 0.00001f) ? 0 : 1; + + float F = glm::mirrorClamp(0.9f); + Error += glm::equal(F, 0.9f, 0.00001f) ? 0 : 1; + + float G = glm::mirrorClamp(3.1f); + Error += glm::equal(G, 0.1f, 0.00001f) ? 0 : 1; + + float H = glm::mirrorClamp(-3.1f); + Error += glm::equal(H, 0.1f, 0.00001f) ? 0 : 1; + + float I = glm::mirrorClamp(-0.9f); + Error += glm::equal(I, 0.9f, 0.00001f) ? 0 : 1; + + return Error; +} + +static int test_mirrorRepeat() +{ + int Error = 0; + + float A = glm::mirrorRepeat(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::mirrorRepeat(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::mirrorRepeat(1.0f); + Error += glm::equal(C, 1.0f, 0.00001f) ? 0 : 1; + + float D = glm::mirrorRepeat(-0.5f); + Error += glm::equal(D, 0.5f, 0.00001f) ? 0 : 1; + + float E = glm::mirrorRepeat(1.5f); + Error += glm::equal(E, 0.5f, 0.00001f) ? 0 : 1; + + float F = glm::mirrorRepeat(0.9f); + Error += glm::equal(F, 0.9f, 0.00001f) ? 0 : 1; + + float G = glm::mirrorRepeat(3.0f); + Error += glm::equal(G, 1.0f, 0.00001f) ? 0 : 1; + + float H = glm::mirrorRepeat(-3.0f); + Error += glm::equal(H, 1.0f, 0.00001f) ? 0 : 1; + + float I = glm::mirrorRepeat(-1.0f); + Error += glm::equal(I, 1.0f, 0.00001f) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_min(); + Error += test_min(); + Error += test_min_nan(); + Error += test_min_nan(); + + Error += test_max(); + Error += test_max(); + Error += test_max_nan(); + Error += test_max_nan(); + + Error += test_fmin(); + Error += test_fmin(); + + Error += test_fmax(); + Error += test_fmax(); + + Error += test_clamp(); + Error += test_repeat(); + Error += test_mirrorClamp(); + Error += test_mirrorRepeat(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_scalar_constants.cpp b/vendor/glm/test/ext/ext_scalar_constants.cpp new file mode 100644 index 0000000..3af7099 --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_constants.cpp @@ -0,0 +1,36 @@ +#include + +template +static int test_epsilon() +{ + int Error = 0; + + valType const Test = glm::epsilon(); + Error += Test > static_cast(0) ? 0 : 1; + + return Error; +} + +template +static int test_pi() +{ + int Error = 0; + + valType const Test = glm::pi(); + Error += Test > static_cast(3.14) ? 0 : 1; + Error += Test < static_cast(3.15) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_epsilon(); + Error += test_epsilon(); + Error += test_pi(); + Error += test_pi(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_scalar_int_sized.cpp b/vendor/glm/test/ext/ext_scalar_int_sized.cpp new file mode 100644 index 0000000..b55c6ca --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_int_sized.cpp @@ -0,0 +1,43 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::int8) == 1, "int8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::int16) == 2, "int16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::int32) == 4, "int32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::int64) == 8, "int64 size isn't 8 bytes on this platform"); + static_assert(sizeof(glm::int16) == sizeof(short), "signed short size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::int32) == sizeof(int), "signed int size isn't 4 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::int8) == 1 ? 0 : 1; + Error += sizeof(glm::int16) == 2 ? 0 : 1; + Error += sizeof(glm::int32) == 4 ? 0 : 1; + Error += sizeof(glm::int64) == 8 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::int8) < sizeof(glm::int16) ? 0 : 1; + Error += sizeof(glm::int16) < sizeof(glm::int32) ? 0 : 1; + Error += sizeof(glm::int32) < sizeof(glm::int64) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_scalar_integer.cpp b/vendor/glm/test/ext/ext_scalar_integer.cpp new file mode 100644 index 0000000..f169e8a --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_integer.cpp @@ -0,0 +1,686 @@ +#include +#include +#include +#include +#include +#include + +#if GLM_LANG & GLM_LANG_CXX11_FLAG +#include + +namespace isPowerOfTwo +{ + template + struct type + { + genType Value; + bool Return; + }; + + int test_int16() + { + type const Data[] = + { + {0x0001, true}, + {0x0002, true}, + {0x0004, true}, + {0x0080, true}, + {0x0000, true}, + {0x0003, false} + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint16() + { + type const Data[] = + { + {0x0001, true}, + {0x0002, true}, + {0x0004, true}, + {0x0000, true}, + {0x0000, true}, + {0x0003, false} + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_int32() + { + type const Data[] = + { + {0x00000001, true}, + {0x00000002, true}, + {0x00000004, true}, + {0x0000000f, false}, + {0x00000000, true}, + {0x00000003, false} + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint32() + { + type const Data[] = + { + {0x00000001, true}, + {0x00000002, true}, + {0x00000004, true}, + {0x80000000, true}, + {0x00000000, true}, + {0x00000003, false} + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += test_int16(); + Error += test_uint16(); + Error += test_int32(); + Error += test_uint32(); + + return Error; + } +}//isPowerOfTwo + +namespace nextPowerOfTwo_advanced +{ + template + GLM_FUNC_QUALIFIER genIUType highestBitValue(genIUType Value) + { + genIUType tmp = Value; + genIUType result = genIUType(0); + while(tmp) + { + result = (tmp & (~tmp + 1)); // grab lowest bit + tmp &= ~result; // clear lowest bit + } + return result; + } + + template + GLM_FUNC_QUALIFIER genType nextPowerOfTwo_loop(genType value) + { + return glm::isPowerOfTwo(value) ? value : highestBitValue(value) << 1; + } + + template + struct type + { + genType Value; + genType Return; + }; + + int test_int32() + { + type const Data[] = + { + {0x0000ffff, 0x00010000}, + {-3, -4}, + {-8, -8}, + {0x00000001, 0x00000001}, + {0x00000002, 0x00000002}, + {0x00000004, 0x00000004}, + {0x00000007, 0x00000008}, + {0x0000fff0, 0x00010000}, + {0x0000f000, 0x00010000}, + {0x08000000, 0x08000000}, + {0x00000000, 0x00000000}, + {0x00000003, 0x00000004} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::int32 Result = glm::nextPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint32() + { + type const Data[] = + { + {0x00000001, 0x00000001}, + {0x00000002, 0x00000002}, + {0x00000004, 0x00000004}, + {0x00000007, 0x00000008}, + {0x0000ffff, 0x00010000}, + {0x0000fff0, 0x00010000}, + {0x0000f000, 0x00010000}, + {0x80000000, 0x80000000}, + {0x00000000, 0x00000000}, + {0x00000003, 0x00000004} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::uint32 Result = glm::nextPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int perf() + { + int Error(0); + + std::vector v; + v.resize(100000000); + + std::clock_t Timestramp0 = std::clock(); + + for(glm::uint32 i = 0, n = static_cast(v.size()); i < n; ++i) + v[i] = nextPowerOfTwo_loop(i); + + std::clock_t Timestramp1 = std::clock(); + + for(glm::uint32 i = 0, n = static_cast(v.size()); i < n; ++i) + v[i] = glm::nextPowerOfTwo(i); + + std::clock_t Timestramp2 = std::clock(); + + std::printf("nextPowerOfTwo_loop: %d clocks\n", static_cast(Timestramp1 - Timestramp0)); + std::printf("glm::nextPowerOfTwo: %d clocks\n", static_cast(Timestramp2 - Timestramp1)); + + return Error; + } + + int test() + { + int Error(0); + + Error += test_int32(); + Error += test_uint32(); + + return Error; + } +}//namespace nextPowerOfTwo_advanced + +namespace prevPowerOfTwo +{ + template + int run() + { + int Error = 0; + + T const A = glm::prevPowerOfTwo(static_cast(7)); + Error += A == static_cast(4) ? 0 : 1; + + T const B = glm::prevPowerOfTwo(static_cast(15)); + Error += B == static_cast(8) ? 0 : 1; + + T const C = glm::prevPowerOfTwo(static_cast(31)); + Error += C == static_cast(16) ? 0 : 1; + + T const D = glm::prevPowerOfTwo(static_cast(32)); + Error += D == static_cast(32) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + return Error; + } +}//namespace prevPowerOfTwo + +namespace nextPowerOfTwo +{ + template + int run() + { + int Error = 0; + + T const A = glm::nextPowerOfTwo(static_cast(7)); + Error += A == static_cast(8) ? 0 : 1; + + T const B = glm::nextPowerOfTwo(static_cast(15)); + Error += B == static_cast(16) ? 0 : 1; + + T const C = glm::nextPowerOfTwo(static_cast(31)); + Error += C == static_cast(32) ? 0 : 1; + + T const D = glm::nextPowerOfTwo(static_cast(32)); + Error += D == static_cast(32) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + return Error; + } +}//namespace nextPowerOfTwo + +namespace prevMultiple +{ + template + struct type + { + genIUType Source; + genIUType Multiple; + genIUType Return; + }; + + template + int run() + { + type const Data[] = + { + {8, 3, 6}, + {7, 7, 7} + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + T const Result = glm::prevMultiple(Data[i].Source, Data[i].Multiple); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + return Error; + } +}//namespace prevMultiple + +namespace nextMultiple +{ + static glm::uint const Multiples = 128; + + int perf_nextMultiple(glm::uint Samples) + { + std::vector Results(Samples * Multiples); + + std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now(); + + for(glm::uint Source = 0; Source < Samples; ++Source) + for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple) + { + Results[Source * Multiples + Multiple] = glm::nextMultiple(Source, Multiples); + } + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + + std::printf("- glm::nextMultiple Time %d microseconds\n", static_cast(std::chrono::duration_cast(t1 - t0).count())); + + glm::uint Result = 0; + for(std::size_t i = 0, n = Results.size(); i < n; ++i) + Result += Results[i]; + + return Result > 0 ? 0 : 1; + } + + template + GLM_FUNC_QUALIFIER T nextMultipleMod(T Source, T Multiple) + { + T const Tmp = Source - static_cast(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + + int perf_nextMultipleMod(glm::uint Samples) + { + std::vector Results(Samples * Multiples); + + std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now(); + + for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple) + for (glm::uint Source = 0; Source < Samples; ++Source) + { + Results[Source * Multiples + Multiple] = nextMultipleMod(Source, Multiples); + } + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + + std::printf("- nextMultipleMod Time %d microseconds\n", static_cast(std::chrono::duration_cast(t1 - t0).count())); + + glm::uint Result = 0; + for(std::size_t i = 0, n = Results.size(); i < n; ++i) + Result += Results[i]; + + return Result > 0 ? 0 : 1; + } + + template + GLM_FUNC_QUALIFIER T nextMultipleNeg(T Source, T Multiple) + { + if(Source > static_cast(0)) + { + T const Tmp = Source - static_cast(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + else + return Source + (-Source % Multiple); + } + + int perf_nextMultipleNeg(glm::uint Samples) + { + std::vector Results(Samples * Multiples); + + std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now(); + + for(glm::uint Source = 0; Source < Samples; ++Source) + for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple) + { + Results[Source * Multiples + Multiple] = nextMultipleNeg(Source, Multiples); + } + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + + std::printf("- nextMultipleNeg Time %d microseconds\n", static_cast(std::chrono::duration_cast(t1 - t0).count())); + + glm::uint Result = 0; + for (std::size_t i = 0, n = Results.size(); i < n; ++i) + Result += Results[i]; + + return Result > 0 ? 0 : 1; + } + + template + GLM_FUNC_QUALIFIER T nextMultipleUFloat(T Source, T Multiple) + { + return Source + (Multiple - std::fmod(Source, Multiple)); + } + + int perf_nextMultipleUFloat(glm::uint Samples) + { + std::vector Results(Samples * Multiples); + + std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now(); + + for(glm::uint Source = 0; Source < Samples; ++Source) + for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple) + { + Results[Source * Multiples + Multiple] = nextMultipleUFloat(static_cast(Source), static_cast(Multiples)); + } + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + + std::printf("- nextMultipleUFloat Time %d microseconds\n", static_cast(std::chrono::duration_cast(t1 - t0).count())); + + float Result = 0; + for (std::size_t i = 0, n = Results.size(); i < n; ++i) + Result += Results[i]; + + return Result > 0.0f ? 0 : 1; + } + + template + GLM_FUNC_QUALIFIER T nextMultipleFloat(T Source, T Multiple) + { + if(Source > static_cast(0)) + return Source + (Multiple - std::fmod(Source, Multiple)); + else + return Source + std::fmod(-Source, Multiple); + } + + int perf_nextMultipleFloat(glm::uint Samples) + { + std::vector Results(Samples * Multiples); + + std::chrono::high_resolution_clock::time_point t0 = std::chrono::high_resolution_clock::now(); + + for(glm::uint Source = 0; Source < Samples; ++Source) + for(glm::uint Multiple = 0; Multiple < Multiples; ++Multiple) + { + Results[Source * Multiples + Multiple] = nextMultipleFloat(static_cast(Source), static_cast(Multiples)); + } + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + + std::printf("- nextMultipleFloat Time %d microseconds\n", static_cast(std::chrono::duration_cast(t1 - t0).count())); + + float Result = 0; + for (std::size_t i = 0, n = Results.size(); i < n; ++i) + Result += Results[i]; + + return Result > 0.0f ? 0 : 1; + } + + template + struct type + { + genIUType Source; + genIUType Multiple; + genIUType Return; + }; + + template + int test_uint() + { + type const Data[] = + { + { 3, 4, 4 }, + { 6, 3, 6 }, + { 5, 3, 6 }, + { 7, 7, 7 }, + { 0, 1, 0 }, + { 8, 3, 9 } + }; + + int Error = 0; + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + T const Result0 = glm::nextMultiple(Data[i].Source, Data[i].Multiple); + Error += Data[i].Return == Result0 ? 0 : 1; + assert(!Error); + + T const Result1 = nextMultipleMod(Data[i].Source, Data[i].Multiple); + Error += Data[i].Return == Result1 ? 0 : 1; + assert(!Error); + } + + return Error; + } + + int perf() + { + int Error = 0; + + glm::uint const Samples = 10000; + + for(int i = 0; i < 4; ++i) + { + std::printf("Run %d :\n", i); + Error += perf_nextMultiple(Samples); + Error += perf_nextMultipleMod(Samples); + Error += perf_nextMultipleNeg(Samples); + Error += perf_nextMultipleUFloat(Samples); + Error += perf_nextMultipleFloat(Samples); + std::printf("\n"); + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += test_uint(); + Error += test_uint(); + Error += test_uint(); + Error += test_uint(); + + Error += test_uint(); + Error += test_uint(); + Error += test_uint(); + Error += test_uint(); + + return Error; + } +}//namespace nextMultiple + +namespace findNSB +{ + template + struct type + { + T Source; + int SignificantBitCount; + int Return; + }; + + template + int run() + { + type const Data[] = + { + { 0x00, 1,-1 }, + { 0x01, 2,-1 }, + { 0x02, 2,-1 }, + { 0x06, 3,-1 }, + { 0x01, 1, 0 }, + { 0x03, 1, 0 }, + { 0x03, 2, 1 }, + { 0x07, 2, 1 }, + { 0x05, 2, 2 }, + { 0x0D, 2, 2 } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + int const Result0 = glm::findNSB(Data[i].Source, Data[i].SignificantBitCount); + Error += Data[i].Return == Result0 ? 0 : 1; + assert(!Error); + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + Error += run(); + Error += run(); + Error += run(); + Error += run(); + + return Error; + } +}//namespace findNSB + +int main() +{ + int Error = 0; + + Error += findNSB::test(); + + Error += isPowerOfTwo::test(); + Error += prevPowerOfTwo::test(); + Error += nextPowerOfTwo::test(); + Error += nextPowerOfTwo_advanced::test(); + Error += prevMultiple::test(); + Error += nextMultiple::test(); + +# ifdef NDEBUG + Error += nextPowerOfTwo_advanced::perf(); + Error += nextMultiple::perf(); +# endif//NDEBUG + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/ext/ext_scalar_packing.cpp b/vendor/glm/test/ext/ext_scalar_packing.cpp new file mode 100644 index 0000000..77616e3 --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_packing.cpp @@ -0,0 +1,28 @@ +#include +#include + +int test_packUnorm() +{ + int Error = 0; + + + return Error; +} + +int test_packSnorm() +{ + int Error = 0; + + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_packUnorm(); + Error += test_packSnorm(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_scalar_relational.cpp b/vendor/glm/test/ext/ext_scalar_relational.cpp new file mode 100644 index 0000000..61f1999 --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_relational.cpp @@ -0,0 +1,106 @@ +#include +#include +#include +#include + +static int test_equal_epsilon() +{ +# if GLM_CONFIG_CONSTEXP == GLM_ENABLE + static_assert(glm::equal(1.01f, 1.02f, 0.1f), "GLM: Failed constexpr"); + static_assert(!glm::equal(1.01f, 1.02f, 0.001f), "GLM: Failed constexpr"); +# endif + + int Error = 0; + + Error += glm::equal(1.01f, 1.02f, 0.1f) ? 0 : 1; + Error += !glm::equal(1.01f, 1.02f, 0.001f) ? 0 : 1; + + return Error; +} + +static int test_notEqual_epsilon() +{ +# if GLM_CONFIG_CONSTEXP == GLM_ENABLE + static_assert(glm::notEqual(1.01f, 1.02f, 0.001f), "GLM: Failed constexpr"); + static_assert(!glm::notEqual(1.01f, 1.02f, 0.1f), "GLM: Failed constexpr"); +# endif + + int Error = 0; + + Error += glm::notEqual(1.01f, 1.02f, 0.001f) ? 0 : 1; + Error += !glm::notEqual(1.01f, 1.02f, 0.1f) ? 0 : 1; + + return Error; +} + +static int test_equal_ulps() +{ + int Error = 0; + + float const ULP1Plus = glm::nextFloat(1.0f); + Error += glm::equal(1.0f, ULP1Plus, 1) ? 0 : 1; + + float const ULP2Plus = glm::nextFloat(ULP1Plus); + Error += !glm::equal(1.0f, ULP2Plus, 1) ? 0 : 1; + + float const ULP1Minus = glm::prevFloat(1.0f); + Error += glm::equal(1.0f, ULP1Minus, 1) ? 0 : 1; + + float const ULP2Minus = glm::prevFloat(ULP1Minus); + Error += !glm::equal(1.0f, ULP2Minus, 1) ? 0 : 1; + + return Error; +} + +static int test_notEqual_ulps() +{ + int Error = 0; + + float const ULP1Plus = glm::nextFloat(1.0f); + Error += !glm::notEqual(1.0f, ULP1Plus, 1) ? 0 : 1; + + float const ULP2Plus = glm::nextFloat(ULP1Plus); + Error += glm::notEqual(1.0f, ULP2Plus, 1) ? 0 : 1; + + float const ULP1Minus = glm::prevFloat(1.0f); + Error += !glm::notEqual(1.0f, ULP1Minus, 1) ? 0 : 1; + + float const ULP2Minus = glm::prevFloat(ULP1Minus); + Error += glm::notEqual(1.0f, ULP2Minus, 1) ? 0 : 1; + + return Error; +} + +static int test_equal_sign() +{ + int Error = 0; + + Error += !glm::equal(-0.0f, 0.0f, 2) ? 0 : 1; + Error += !glm::equal(-0.0, 0.0, 2) ? 0 : 1; + + Error += !glm::equal(-1.0f, 2.0f, 2) ? 0 : 1; + Error += !glm::equal(-1.0, 2.0, 2) ? 0 : 1; + + Error += !glm::equal(-0.00001f, 1.00000f, 2) ? 0 : 1; + Error += !glm::equal(-0.00001, 1.00000, 2) ? 0 : 1; + + Error += !glm::equal(-1.0f, 1.0f, 2) ? 0 : 1; + Error += !glm::equal(-1.0, 1.0, 2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_equal_epsilon(); + Error += test_notEqual_epsilon(); + + Error += test_equal_ulps(); + Error += test_notEqual_ulps(); + + Error += test_equal_sign(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_scalar_uint_sized.cpp b/vendor/glm/test/ext/ext_scalar_uint_sized.cpp new file mode 100644 index 0000000..1122947 --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_uint_sized.cpp @@ -0,0 +1,43 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::uint8) == 1, "uint8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::uint16) == 2, "uint16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::uint32) == 4, "uint32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::uint64) == 8, "uint64 size isn't 8 bytes on this platform"); + static_assert(sizeof(glm::uint16) == sizeof(unsigned short), "unsigned short size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::uint32) == sizeof(unsigned int), "unsigned int size isn't 4 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::uint8) == 1 ? 0 : 1; + Error += sizeof(glm::uint16) == 2 ? 0 : 1; + Error += sizeof(glm::uint32) == 4 ? 0 : 1; + Error += sizeof(glm::uint64) == 8 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::uint8) < sizeof(glm::uint16) ? 0 : 1; + Error += sizeof(glm::uint16) < sizeof(glm::uint32) ? 0 : 1; + Error += sizeof(glm::uint32) < sizeof(glm::uint64) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_scalar_ulp.cpp b/vendor/glm/test/ext/ext_scalar_ulp.cpp new file mode 100644 index 0000000..a19b774 --- /dev/null +++ b/vendor/glm/test/ext/ext_scalar_ulp.cpp @@ -0,0 +1,96 @@ +#include +#include + +static int test_ulp_float_dist() +{ + int Error = 0; + + float A = 1.0f; + + float B = glm::nextFloat(A); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + float C = glm::prevFloat(B); + Error += glm::equal(A, C, 0) ? 0 : 1; + + int D = glm::floatDistance(A, B); + Error += D == 1 ? 0 : 1; + int E = glm::floatDistance(A, C); + Error += E == 0 ? 0 : 1; + + return Error; +} + +static int test_ulp_float_step() +{ + int Error = 0; + + float A = 1.0f; + + for(int i = 10; i < 1000; i *= 10) + { + float B = glm::nextFloat(A, i); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + float C = glm::prevFloat(B, i); + Error += glm::equal(A, C, 0) ? 0 : 1; + + int D = glm::floatDistance(A, B); + Error += D == i ? 0 : 1; + int E = glm::floatDistance(A, C); + Error += E == 0 ? 0 : 1; + } + + return Error; +} + +static int test_ulp_double_dist() +{ + int Error = 0; + + double A = 1.0; + + double B = glm::nextFloat(A); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + double C = glm::prevFloat(B); + Error += glm::equal(A, C, 0) ? 0 : 1; + + glm::int64 const D = glm::floatDistance(A, B); + Error += D == 1 ? 0 : 1; + glm::int64 const E = glm::floatDistance(A, C); + Error += E == 0 ? 0 : 1; + + return Error; +} + +static int test_ulp_double_step() +{ + int Error = 0; + + double A = 1.0; + + for(int i = 10; i < 1000; i *= 10) + { + double B = glm::nextFloat(A, i); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + double C = glm::prevFloat(B, i); + Error += glm::equal(A, C, 0) ? 0 : 1; + + glm::int64 const D = glm::floatDistance(A, B); + Error += D == i ? 0 : 1; + glm::int64 const E = glm::floatDistance(A, C); + Error += E == 0 ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_ulp_float_dist(); + Error += test_ulp_float_step(); + Error += test_ulp_double_dist(); + Error += test_ulp_double_step(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vec1.cpp b/vendor/glm/test/ext/ext_vec1.cpp new file mode 100644 index 0000000..fc0b931 --- /dev/null +++ b/vendor/glm/test/ext/ext_vec1.cpp @@ -0,0 +1,157 @@ +#define GLM_FORCE_SWIZZLE +#include +#include +#include + +static glm::vec1 g1; +static glm::vec1 g2(1); + +static int test_vec1_operators() +{ + int Error(0); + + glm::ivec1 A(1); + glm::ivec1 B(1); + { + bool R = A != B; + bool S = A == B; + + Error += (S && !R) ? 0 : 1; + } + + { + A *= 1; + B *= 1; + A += 1; + B += 1; + + bool R = A != B; + bool S = A == B; + + Error += (S && !R) ? 0 : 1; + } + + return Error; +} + +static int test_vec1_ctor() +{ + int Error = 0; + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + + + { + glm::ivec1 A = glm::vec1(2.0f); + + glm::ivec1 E(glm::dvec1(2.0)); + Error += A == E ? 0 : 1; + + glm::ivec1 F(glm::ivec1(2)); + Error += A == F ? 0 : 1; + } + + return Error; +} + +static int test_vec1_size() +{ + int Error = 0; + + Error += sizeof(glm::vec1) == sizeof(glm::mediump_vec1) ? 0 : 1; + Error += 4 == sizeof(glm::mediump_vec1) ? 0 : 1; + Error += sizeof(glm::dvec1) == sizeof(glm::highp_dvec1) ? 0 : 1; + Error += 8 == sizeof(glm::highp_dvec1) ? 0 : 1; + Error += glm::vec1().length() == 1 ? 0 : 1; + Error += glm::dvec1().length() == 1 ? 0 : 1; + Error += glm::vec1::length() == 1 ? 0 : 1; + Error += glm::dvec1::length() == 1 ? 0 : 1; + + GLM_CONSTEXPR std::size_t Length = glm::vec1::length(); + Error += Length == 1 ? 0 : 1; + + return Error; +} + +static int test_vec1_operator_increment() +{ + int Error(0); + + glm::ivec1 v0(1); + glm::ivec1 v1(v0); + glm::ivec1 v2(v0); + glm::ivec1 v3 = ++v1; + glm::ivec1 v4 = v2++; + + Error += glm::all(glm::equal(v0, v4)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v2)) ? 0 : 1; + Error += glm::all(glm::equal(v1, v3)) ? 0 : 1; + + int i0(1); + int i1(i0); + int i2(i0); + int i3 = ++i1; + int i4 = i2++; + + Error += i0 == i4 ? 0 : 1; + Error += i1 == i2 ? 0 : 1; + Error += i1 == i3 ? 0 : 1; + + return Error; +} + +static int test_bvec1_ctor() +{ + int Error = 0; + + glm::bvec1 const A(true); + glm::bvec1 const B(true); + glm::bvec1 const C(false); + glm::bvec1 const D = A && B; + glm::bvec1 const E = A && C; + glm::bvec1 const F = A || C; + + Error += D == glm::bvec1(true) ? 0 : 1; + Error += E == glm::bvec1(false) ? 0 : 1; + Error += F == glm::bvec1(true) ? 0 : 1; + + bool const G = A == C; + bool const H = A != C; + Error += !G ? 0 : 1; + Error += H ? 0 : 1; + + return Error; +} + +static int test_constexpr() +{ +#if GLM_HAS_CONSTEXPR + static_assert(glm::vec1::length() == 1, "GLM: Failed constexpr"); + static_assert(glm::vec1(1.0f).x > 0.0f, "GLM: Failed constexpr"); +#endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_vec1_size(); + Error += test_vec1_ctor(); + Error += test_bvec1_ctor(); + Error += test_vec1_operators(); + Error += test_vec1_operator_increment(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_bool1.cpp b/vendor/glm/test/ext/ext_vector_bool1.cpp new file mode 100644 index 0000000..43eed57 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_bool1.cpp @@ -0,0 +1,104 @@ +#include +#include + +template +static int test_operators() +{ + int Error = 0; + + genType const A(true); + genType const B(true); + { + bool const R = A != B; + bool const S = A == B; + Error += (S && !R) ? 0 : 1; + } + + return Error; +} + +template +static int test_ctor() +{ + int Error = 0; + + glm::bvec1 const A = genType(true); + + glm::bvec1 const E(genType(true)); + Error += A == E ? 0 : 1; + + glm::bvec1 const F(E); + Error += A == F ? 0 : 1; + + return Error; +} + +template +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::bvec1) == sizeof(genType) ? 0 : 1; + Error += genType().length() == 1 ? 0 : 1; + Error += genType::length() == 1 ? 0 : 1; + + return Error; +} + +template +static int test_relational() +{ + int Error = 0; + + genType const A(true); + genType const B(true); + genType const C(false); + + Error += A == B ? 0 : 1; + Error += (A && B) == A ? 0 : 1; + Error += (A || C) == A ? 0 : 1; + + return Error; +} + +template +static int test_constexpr() +{ +# if GLM_HAS_CONSTEXPR + static_assert(genType::length() == 1, "GLM: Failed constexpr"); +# endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_common.cpp b/vendor/glm/test/ext/ext_vector_common.cpp new file mode 100644 index 0000000..344b669 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_common.cpp @@ -0,0 +1,332 @@ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if ((GLM_LANG & GLM_LANG_CXX11_FLAG) || (GLM_COMPILER & GLM_COMPILER_VC)) +# define GLM_NAN(T) NAN +#else +# define GLM_NAN(T) (static_cast(0.0f) / static_cast(0.0f)) +#endif + +template +static int test_min() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const N(static_cast(0)); + vecType const B(static_cast(1)); + + Error += glm::all(glm::equal(glm::min(N, B), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, N), N, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::min(N, B, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, N, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, N, B), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, B, N), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, C, N), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(N, C, B), N, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::min(D, N, B, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, D, N, C), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, N, D, B), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(C, B, D, N), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(B, C, N, D), N, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::min(N, C, B, D), N, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_min_nan() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const B(static_cast(1)); + vecType const N(GLM_NAN(T)); + + Error += glm::all(glm::isnan(glm::min(N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, N))) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::isnan(glm::min(N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, B, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, C, N))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::min(N, C, B))) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += !glm::all(glm::isnan(glm::min(D, N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, D, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, N, D, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(C, B, D, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::min(B, C, N, D))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::min(N, C, B, D))) ? 0 : 1; + + return Error; +} + +template +static int test_max() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const N(static_cast(0)); + vecType const B(static_cast(1)); + Error += glm::all(glm::equal(glm::max(N, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, N), B, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::max(N, B, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, N, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, N, B), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, B, N), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, C, N), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(N, C, B), C, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::max(D, N, B, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, D, N, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, N, D, B), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(C, B, D, N), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(B, C, N, D), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::max(N, C, B, D), D, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_max_nan() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const B(static_cast(1)); + vecType const N(GLM_NAN(T)); + + Error += glm::all(glm::isnan(glm::max(N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, N))) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::isnan(glm::max(N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, N, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, B, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, C, N))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::max(N, C, B))) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += !glm::all(glm::isnan(glm::max(D, N, B, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, D, N, C))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, N, D, B))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(C, B, D, N))) ? 0 : 1; + Error += !glm::all(glm::isnan(glm::max(B, C, N, D))) ? 0 : 1; + Error += glm::all(glm::isnan(glm::max(N, C, B, D))) ? 0 : 1; + + return Error; +} + +template +static int test_fmin() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const B(static_cast(1)); + vecType const N(GLM_NAN(T)); + + Error += glm::all(glm::equal(glm::fmin(N, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, N), B, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::fmin(N, B, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, N, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, N, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, B, N), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, C, N), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(N, C, B), B, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::fmin(D, N, B, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, D, N, C), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, N, D, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(C, B, D, N), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(B, C, N, D), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmin(N, C, B, D), B, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_fmax() +{ + typedef typename vecType::value_type T; + + int Error = 0; + + vecType const B(static_cast(1)); + vecType const N(GLM_NAN(T)); + + Error += glm::all(glm::equal(glm::fmax(N, B), B, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, N), B, glm::epsilon())) ? 0 : 1; + + vecType const C(static_cast(2)); + Error += glm::all(glm::equal(glm::fmax(N, B, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, N, C), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, N, B), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, B, N), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, C, N), C, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(N, C, B), C, glm::epsilon())) ? 0 : 1; + + vecType const D(static_cast(3)); + Error += glm::all(glm::equal(glm::fmax(D, N, B, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, D, N, C), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, N, D, B), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(C, B, D, N), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(B, C, N, D), D, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::fmax(N, C, B, D), D, glm::epsilon())) ? 0 : 1; + + return Error; +} + +static int test_clamp() +{ + int Error = 0; + + glm::vec2 K = glm::clamp(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::clamp(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::clamp(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::clamp(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; +} + +static int test_repeat() +{ + int Error = 0; + + glm::vec2 K = glm::repeat(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::repeat(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::repeat(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::repeat(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; +} + +static int test_mirrorClamp() +{ + int Error = 0; + + glm::vec2 K = glm::mirrorClamp(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::mirrorClamp(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::mirrorClamp(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::mirrorClamp(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; +} + +static int test_mirrorRepeat() +{ + int Error = 0; + + glm::vec2 K = glm::mirrorRepeat(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::mirrorRepeat(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::mirrorRepeat(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::mirrorRepeat(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_min(); + Error += test_min(); + Error += test_min_nan(); + Error += test_min_nan(); + + Error += test_max(); + Error += test_max(); + Error += test_max_nan(); + Error += test_max_nan(); + + Error += test_fmin(); + Error += test_fmin(); + + Error += test_fmax(); + Error += test_fmax(); + + Error += test_clamp(); + Error += test_repeat(); + Error += test_mirrorClamp(); + Error += test_mirrorRepeat(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_iec559.cpp b/vendor/glm/test/ext/ext_vector_iec559.cpp new file mode 100644 index 0000000..5a9da50 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_iec559.cpp @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +static int test_operators() +{ + typedef typename genType::value_type valType; + + int Error = 0; + + { + genType const A(1); + genType const B(1); + + genType const C = A + B; + Error += glm::all(glm::equal(C, genType(2), glm::epsilon())) ? 0 : 1; + + genType const D = A - B; + Error += glm::all(glm::equal(D, genType(0), glm::epsilon())) ? 0 : 1; + + genType const E = A * B; + Error += glm::all(glm::equal(E, genType(1), glm::epsilon())) ? 0 : 1; + + genType const F = A / B; + Error += glm::all(glm::equal(F, genType(1), glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +template +static int test_ctor() +{ + typedef typename genType::value_type T; + + int Error = 0; + + glm::vec<1, T> const A = genType(1); + + glm::vec<1, T> const E(genType(1)); + Error += glm::all(glm::equal(A, E, glm::epsilon())) ? 0 : 1; + + glm::vec<1, T> const F(E); + Error += glm::all(glm::equal(A, F, glm::epsilon())) ? 0 : 1; + + genType const B = genType(1); + genType const G(glm::vec<2, T>(1)); + Error += glm::all(glm::equal(B, G, glm::epsilon())) ? 0 : 1; + + genType const H(glm::vec<3, T>(1)); + Error += glm::all(glm::equal(B, H, glm::epsilon())) ? 0 : 1; + + genType const I(glm::vec<4, T>(1)); + Error += glm::all(glm::equal(B, I, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_size() +{ + typedef typename genType::value_type T; + + int Error = 0; + + Error += sizeof(glm::vec<1, T>) == sizeof(genType) ? 0 : 1; + Error += genType().length() == 1 ? 0 : 1; + Error += genType::length() == 1 ? 0 : 1; + + return Error; +} + +template +static int test_relational() +{ + typedef typename genType::value_type valType; + + int Error = 0; + + genType const A(1); + genType const B(1); + genType const C(0); + + Error += all(equal(A, B, glm::epsilon())) ? 0 : 1; + Error += any(notEqual(A, C, glm::epsilon())) ? 0 : 1; + + return Error; +} + +template +static int test_constexpr() +{ +# if GLM_CONFIG_CONSTEXP == GLM_ENABLE + static_assert(genType::length() == 1, "GLM: Failed constexpr"); +# endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_int1_sized.cpp b/vendor/glm/test/ext/ext_vector_int1_sized.cpp new file mode 100644 index 0000000..c262f49 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_int1_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::i8vec1) == 1, "int8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::i16vec1) == 2, "int16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::i32vec1) == 4, "int32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::i64vec1) == 8, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::i8vec1) == 1 ? 0 : 1; + Error += sizeof(glm::i16vec1) == 2 ? 0 : 1; + Error += sizeof(glm::i32vec1) == 4 ? 0 : 1; + Error += sizeof(glm::i64vec1) == 8 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8vec1) < sizeof(glm::i16vec1) ? 0 : 1; + Error += sizeof(glm::i16vec1) < sizeof(glm::i32vec1) ? 0 : 1; + Error += sizeof(glm::i32vec1) < sizeof(glm::i64vec1) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_int2_sized.cpp b/vendor/glm/test/ext/ext_vector_int2_sized.cpp new file mode 100644 index 0000000..f4ad8b6 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_int2_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::i8vec2) == 2, "int8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::i16vec2) == 4, "int16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::i32vec2) == 8, "int32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::i64vec2) == 16, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::i8vec2) == 2 ? 0 : 1; + Error += sizeof(glm::i16vec2) == 4 ? 0 : 1; + Error += sizeof(glm::i32vec2) == 8 ? 0 : 1; + Error += sizeof(glm::i64vec2) == 16 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8vec2) < sizeof(glm::i16vec2) ? 0 : 1; + Error += sizeof(glm::i16vec2) < sizeof(glm::i32vec2) ? 0 : 1; + Error += sizeof(glm::i32vec2) < sizeof(glm::i64vec2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_int3_sized.cpp b/vendor/glm/test/ext/ext_vector_int3_sized.cpp new file mode 100644 index 0000000..c51bfe7 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_int3_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::i8vec3) == 3, "int8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::i16vec3) == 6, "int16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::i32vec3) == 12, "int32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::i64vec3) == 24, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::i8vec3) == 3 ? 0 : 1; + Error += sizeof(glm::i16vec3) == 6 ? 0 : 1; + Error += sizeof(glm::i32vec3) == 12 ? 0 : 1; + Error += sizeof(glm::i64vec3) == 24 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8vec3) < sizeof(glm::i16vec3) ? 0 : 1; + Error += sizeof(glm::i16vec3) < sizeof(glm::i32vec3) ? 0 : 1; + Error += sizeof(glm::i32vec3) < sizeof(glm::i64vec3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_int4_sized.cpp b/vendor/glm/test/ext/ext_vector_int4_sized.cpp new file mode 100644 index 0000000..93fd9ed --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_int4_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::i8vec4) == 4, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::i16vec4) == 8, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::i32vec4) == 16, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::i64vec4) == 32, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::i8vec4) == 4 ? 0 : 1; + Error += sizeof(glm::i16vec4) == 8 ? 0 : 1; + Error += sizeof(glm::i32vec4) == 16 ? 0 : 1; + Error += sizeof(glm::i64vec4) == 32 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::i8vec4) < sizeof(glm::i16vec4) ? 0 : 1; + Error += sizeof(glm::i16vec4) < sizeof(glm::i32vec4) ? 0 : 1; + Error += sizeof(glm::i32vec4) < sizeof(glm::i64vec4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_integer.cpp b/vendor/glm/test/ext/ext_vector_integer.cpp new file mode 100644 index 0000000..d7278d3 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_integer.cpp @@ -0,0 +1,547 @@ +#include +#include +#include +#include +#include +#include + +namespace isPowerOfTwo +{ + template + struct type + { + genType Value; + bool Return; + }; + + template + int test_int16() + { + type const Data[] = + { + { 0x0001, true }, + { 0x0002, true }, + { 0x0004, true }, + { 0x0080, true }, + { 0x0000, true }, + { 0x0003, false } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::vec const Result = glm::isPowerOfTwo(glm::vec(Data[i].Value)); + Error += glm::vec(Data[i].Return) == Result ? 0 : 1; + } + + return Error; + } + + template + int test_uint16() + { + type const Data[] = + { + { 0x0001, true }, + { 0x0002, true }, + { 0x0004, true }, + { 0x0000, true }, + { 0x0000, true }, + { 0x0003, false } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::vec const Result = glm::isPowerOfTwo(glm::vec(Data[i].Value)); + Error += glm::vec(Data[i].Return) == Result ? 0 : 1; + } + + return Error; + } + + template + int test_int32() + { + type const Data[] = + { + { 0x00000001, true }, + { 0x00000002, true }, + { 0x00000004, true }, + { 0x0000000f, false }, + { 0x00000000, true }, + { 0x00000003, false } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::vec const Result = glm::isPowerOfTwo(glm::vec(Data[i].Value)); + Error += glm::vec(Data[i].Return) == Result ? 0 : 1; + } + + return Error; + } + + template + int test_uint32() + { + type const Data[] = + { + { 0x00000001, true }, + { 0x00000002, true }, + { 0x00000004, true }, + { 0x80000000, true }, + { 0x00000000, true }, + { 0x00000003, false } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::vec const Result = glm::isPowerOfTwo(glm::vec(Data[i].Value)); + Error += glm::vec(Data[i].Return) == Result ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += test_int16<1>(); + Error += test_int16<2>(); + Error += test_int16<3>(); + Error += test_int16<4>(); + + Error += test_uint16<1>(); + Error += test_uint16<2>(); + Error += test_uint16<3>(); + Error += test_uint16<4>(); + + Error += test_int32<1>(); + Error += test_int32<2>(); + Error += test_int32<3>(); + Error += test_int32<4>(); + + Error += test_uint32<1>(); + Error += test_uint32<2>(); + Error += test_uint32<3>(); + Error += test_uint32<4>(); + + return Error; + } +}//isPowerOfTwo + +namespace prevPowerOfTwo +{ + template + int run() + { + int Error = 0; + + glm::vec const A = glm::prevPowerOfTwo(glm::vec(7)); + Error += A == glm::vec(4) ? 0 : 1; + + glm::vec const B = glm::prevPowerOfTwo(glm::vec(15)); + Error += B == glm::vec(8) ? 0 : 1; + + glm::vec const C = glm::prevPowerOfTwo(glm::vec(31)); + Error += C == glm::vec(16) ? 0 : 1; + + glm::vec const D = glm::prevPowerOfTwo(glm::vec(32)); + Error += D == glm::vec(32) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += run<1, glm::int8>(); + Error += run<2, glm::int8>(); + Error += run<3, glm::int8>(); + Error += run<4, glm::int8>(); + + Error += run<1, glm::int16>(); + Error += run<2, glm::int16>(); + Error += run<3, glm::int16>(); + Error += run<4, glm::int16>(); + + Error += run<1, glm::int32>(); + Error += run<2, glm::int32>(); + Error += run<3, glm::int32>(); + Error += run<4, glm::int32>(); + + Error += run<1, glm::int64>(); + Error += run<2, glm::int64>(); + Error += run<3, glm::int64>(); + Error += run<4, glm::int64>(); + + Error += run<1, glm::uint8>(); + Error += run<2, glm::uint8>(); + Error += run<3, glm::uint8>(); + Error += run<4, glm::uint8>(); + + Error += run<1, glm::uint16>(); + Error += run<2, glm::uint16>(); + Error += run<3, glm::uint16>(); + Error += run<4, glm::uint16>(); + + Error += run<1, glm::uint32>(); + Error += run<2, glm::uint32>(); + Error += run<3, glm::uint32>(); + Error += run<4, glm::uint32>(); + + Error += run<1, glm::uint64>(); + Error += run<2, glm::uint64>(); + Error += run<3, glm::uint64>(); + Error += run<4, glm::uint64>(); + + return Error; + } +}//namespace prevPowerOfTwo + +namespace nextPowerOfTwo +{ + template + int run() + { + int Error = 0; + + glm::vec const A = glm::nextPowerOfTwo(glm::vec(7)); + Error += A == glm::vec(8) ? 0 : 1; + + glm::vec const B = glm::nextPowerOfTwo(glm::vec(15)); + Error += B == glm::vec(16) ? 0 : 1; + + glm::vec const C = glm::nextPowerOfTwo(glm::vec(31)); + Error += C == glm::vec(32) ? 0 : 1; + + glm::vec const D = glm::nextPowerOfTwo(glm::vec(32)); + Error += D == glm::vec(32) ? 0 : 1; + + return Error; + } + + int test() + { + int Error = 0; + + Error += run<1, glm::int8>(); + Error += run<2, glm::int8>(); + Error += run<3, glm::int8>(); + Error += run<4, glm::int8>(); + + Error += run<1, glm::int16>(); + Error += run<2, glm::int16>(); + Error += run<3, glm::int16>(); + Error += run<4, glm::int16>(); + + Error += run<1, glm::int32>(); + Error += run<2, glm::int32>(); + Error += run<3, glm::int32>(); + Error += run<4, glm::int32>(); + + Error += run<1, glm::int64>(); + Error += run<2, glm::int64>(); + Error += run<3, glm::int64>(); + Error += run<4, glm::int64>(); + + Error += run<1, glm::uint8>(); + Error += run<2, glm::uint8>(); + Error += run<3, glm::uint8>(); + Error += run<4, glm::uint8>(); + + Error += run<1, glm::uint16>(); + Error += run<2, glm::uint16>(); + Error += run<3, glm::uint16>(); + Error += run<4, glm::uint16>(); + + Error += run<1, glm::uint32>(); + Error += run<2, glm::uint32>(); + Error += run<3, glm::uint32>(); + Error += run<4, glm::uint32>(); + + Error += run<1, glm::uint64>(); + Error += run<2, glm::uint64>(); + Error += run<3, glm::uint64>(); + Error += run<4, glm::uint64>(); + + return Error; + } +}//namespace nextPowerOfTwo + +namespace prevMultiple +{ + template + struct type + { + genIUType Source; + genIUType Multiple; + genIUType Return; + }; + + template + int run() + { + type const Data[] = + { + { 8, 3, 6 }, + { 7, 7, 7 } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::vec const Result0 = glm::prevMultiple(glm::vec(Data[i].Source), Data[i].Multiple); + Error += glm::vec(Data[i].Return) == Result0 ? 0 : 1; + + glm::vec const Result1 = glm::prevMultiple(glm::vec(Data[i].Source), glm::vec(Data[i].Multiple)); + Error += glm::vec(Data[i].Return) == Result1 ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += run<1, glm::int8>(); + Error += run<2, glm::int8>(); + Error += run<3, glm::int8>(); + Error += run<4, glm::int8>(); + + Error += run<1, glm::int16>(); + Error += run<2, glm::int16>(); + Error += run<3, glm::int16>(); + Error += run<4, glm::int16>(); + + Error += run<1, glm::int32>(); + Error += run<2, glm::int32>(); + Error += run<3, glm::int32>(); + Error += run<4, glm::int32>(); + + Error += run<1, glm::int64>(); + Error += run<2, glm::int64>(); + Error += run<3, glm::int64>(); + Error += run<4, glm::int64>(); + + Error += run<1, glm::uint8>(); + Error += run<2, glm::uint8>(); + Error += run<3, glm::uint8>(); + Error += run<4, glm::uint8>(); + + Error += run<1, glm::uint16>(); + Error += run<2, glm::uint16>(); + Error += run<3, glm::uint16>(); + Error += run<4, glm::uint16>(); + + Error += run<1, glm::uint32>(); + Error += run<2, glm::uint32>(); + Error += run<3, glm::uint32>(); + Error += run<4, glm::uint32>(); + + Error += run<1, glm::uint64>(); + Error += run<2, glm::uint64>(); + Error += run<3, glm::uint64>(); + Error += run<4, glm::uint64>(); + + return Error; + } +}//namespace prevMultiple + +namespace nextMultiple +{ + template + struct type + { + genIUType Source; + genIUType Multiple; + genIUType Return; + }; + + template + int run() + { + type const Data[] = + { + { 3, 4, 4 }, + { 6, 3, 6 }, + { 5, 3, 6 }, + { 7, 7, 7 }, + { 0, 1, 0 }, + { 8, 3, 9 } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::vec const Result0 = glm::nextMultiple(glm::vec(Data[i].Source), glm::vec(Data[i].Multiple)); + Error += glm::vec(Data[i].Return) == Result0 ? 0 : 1; + + glm::vec const Result1 = glm::nextMultiple(glm::vec(Data[i].Source), Data[i].Multiple); + Error += glm::vec(Data[i].Return) == Result1 ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += run<1, glm::int8>(); + Error += run<2, glm::int8>(); + Error += run<3, glm::int8>(); + Error += run<4, glm::int8>(); + + Error += run<1, glm::int16>(); + Error += run<2, glm::int16>(); + Error += run<3, glm::int16>(); + Error += run<4, glm::int16>(); + + Error += run<1, glm::int32>(); + Error += run<2, glm::int32>(); + Error += run<3, glm::int32>(); + Error += run<4, glm::int32>(); + + Error += run<1, glm::int64>(); + Error += run<2, glm::int64>(); + Error += run<3, glm::int64>(); + Error += run<4, glm::int64>(); + + Error += run<1, glm::uint8>(); + Error += run<2, glm::uint8>(); + Error += run<3, glm::uint8>(); + Error += run<4, glm::uint8>(); + + Error += run<1, glm::uint16>(); + Error += run<2, glm::uint16>(); + Error += run<3, glm::uint16>(); + Error += run<4, glm::uint16>(); + + Error += run<1, glm::uint32>(); + Error += run<2, glm::uint32>(); + Error += run<3, glm::uint32>(); + Error += run<4, glm::uint32>(); + + Error += run<1, glm::uint64>(); + Error += run<2, glm::uint64>(); + Error += run<3, glm::uint64>(); + Error += run<4, glm::uint64>(); + + return Error; + } +}//namespace nextMultiple + +namespace findNSB +{ + template + struct type + { + T Source; + int SignificantBitCount; + int Return; + }; + + template + int run() + { + type const Data[] = + { + { 0x00, 1,-1 }, + { 0x01, 2,-1 }, + { 0x02, 2,-1 }, + { 0x06, 3,-1 }, + { 0x01, 1, 0 }, + { 0x03, 1, 0 }, + { 0x03, 2, 1 }, + { 0x07, 2, 1 }, + { 0x05, 2, 2 }, + { 0x0D, 2, 2 } + }; + + int Error = 0; + + for (std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::vec const Result0 = glm::findNSB(glm::vec(Data[i].Source), glm::vec(Data[i].SignificantBitCount)); + Error += glm::vec(Data[i].Return) == Result0 ? 0 : 1; + assert(!Error); + } + + return Error; + } + + int test() + { + int Error = 0; + + Error += run<1, glm::uint8>(); + Error += run<2, glm::uint8>(); + Error += run<3, glm::uint8>(); + Error += run<4, glm::uint8>(); + + Error += run<1, glm::uint16>(); + Error += run<2, glm::uint16>(); + Error += run<3, glm::uint16>(); + Error += run<4, glm::uint16>(); + + Error += run<1, glm::uint32>(); + Error += run<2, glm::uint32>(); + Error += run<3, glm::uint32>(); + Error += run<4, glm::uint32>(); + + Error += run<1, glm::uint64>(); + Error += run<2, glm::uint64>(); + Error += run<3, glm::uint64>(); + Error += run<4, glm::uint64>(); + + Error += run<1, glm::int8>(); + Error += run<2, glm::int8>(); + Error += run<3, glm::int8>(); + Error += run<4, glm::int8>(); + + Error += run<1, glm::int16>(); + Error += run<2, glm::int16>(); + Error += run<3, glm::int16>(); + Error += run<4, glm::int16>(); + + Error += run<1, glm::int32>(); + Error += run<2, glm::int32>(); + Error += run<3, glm::int32>(); + Error += run<4, glm::int32>(); + + Error += run<1, glm::int64>(); + Error += run<2, glm::int64>(); + Error += run<3, glm::int64>(); + Error += run<4, glm::int64>(); + + + return Error; + } +}//namespace findNSB + +int main() +{ + int Error = 0; + + Error += isPowerOfTwo::test(); + Error += prevPowerOfTwo::test(); + Error += nextPowerOfTwo::test(); + Error += prevMultiple::test(); + Error += nextMultiple::test(); + Error += findNSB::test(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_integer_sized.cpp b/vendor/glm/test/ext/ext_vector_integer_sized.cpp new file mode 100644 index 0000000..52b3f4e --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_integer_sized.cpp @@ -0,0 +1,216 @@ +#include +#include +#include +#include +#include + +template +static int test_operators() +{ + int Error = 0; + + { + genType const A(1); + genType const B(1); + + bool const R = A != B; + bool const S = A == B; + Error += (S && !R) ? 0 : 1; + } + + { + genType const A(1); + genType const B(1); + + genType const C = A + B; + Error += C == genType(2) ? 0 : 1; + + genType const D = A - B; + Error += D == genType(0) ? 0 : 1; + + genType const E = A * B; + Error += E == genType(1) ? 0 : 1; + + genType const F = A / B; + Error += F == genType(1) ? 0 : 1; + } + + { + genType const A(3); + genType const B(2); + + genType const C = A % B; + Error += C == genType(1) ? 0 : 1; + } + + { + genType const A(1); + genType const B(1); + genType const C(0); + + genType const I = A & B; + Error += I == genType(1) ? 0 : 1; + genType const D = A & C; + Error += D == genType(0) ? 0 : 1; + + genType const E = A | B; + Error += E == genType(1) ? 0 : 1; + genType const F = A | C; + Error += F == genType(1) ? 0 : 1; + + genType const G = A ^ B; + Error += G == genType(0) ? 0 : 1; + genType const H = A ^ C; + Error += H == genType(1) ? 0 : 1; + } + + { + genType const A(0); + genType const B(1); + genType const C(2); + + genType const D = B << B; + Error += D == genType(2) ? 0 : 1; + genType const E = C >> B; + Error += E == genType(1) ? 0 : 1; + } + + return Error; +} + +template +static int test_ctor() +{ + typedef typename genType::value_type T; + + int Error = 0; + + genType const A = genType(1); + + genType const E(genType(1)); + Error += A == E ? 0 : 1; + + genType const F(E); + Error += A == F ? 0 : 1; + + genType const B = genType(1); + genType const G(glm::vec<2, T>(1)); + Error += B == G ? 0 : 1; + + genType const H(glm::vec<3, T>(1)); + Error += B == H ? 0 : 1; + + genType const I(glm::vec<4, T>(1)); + Error += B == I ? 0 : 1; + + return Error; +} + +template +static int test_size() +{ + int Error = 0; + + Error += sizeof(typename genType::value_type) == sizeof(genType) ? 0 : 1; + Error += genType().length() == 1 ? 0 : 1; + Error += genType::length() == 1 ? 0 : 1; + + return Error; +} + +template +static int test_relational() +{ + int Error = 0; + + genType const A(1); + genType const B(1); + genType const C(0); + + Error += A == B ? 0 : 1; + Error += A != C ? 0 : 1; + Error += all(equal(A, B)) ? 0 : 1; + Error += any(notEqual(A, C)) ? 0 : 1; + + return Error; +} + +template +static int test_constexpr() +{ +# if GLM_CONFIG_CONSTEXP == GLM_ENABLE + static_assert(genType::length() == 1, "GLM: Failed constexpr"); + static_assert(genType(1)[0] == 1, "GLM: Failed constexpr"); + static_assert(genType(1) == genType(1), "GLM: Failed constexpr"); + static_assert(genType(1) != genType(0), "GLM: Failed constexpr"); +# endif + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + Error += test_operators(); + + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + Error += test_ctor(); + + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + Error += test_size(); + + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + Error += test_relational(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_packing.cpp b/vendor/glm/test/ext/ext_vector_packing.cpp new file mode 100644 index 0000000..d7cbce2 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_packing.cpp @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include + +int test_packUnorm() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.7f)); + A.push_back(glm::vec2(0.5f, 0.1f)); + + for (std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::u16vec2 C = glm::packUnorm(B); + glm::vec2 D = glm::unpackUnorm(C); + Error += glm::all(glm::equal(B, D, 1.0f / 255.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.0f)); + A.push_back(glm::vec2(-0.5f, -0.7f)); + A.push_back(glm::vec2(-0.1f, 0.1f)); + + for (std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::i16vec2 C = glm::packSnorm(B); + glm::vec2 D = glm::unpackSnorm(C); + Error += glm::all(glm::equal(B, D, 1.0f / 32767.0f * 2.0f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_packUnorm(); + Error += test_packSnorm(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_relational.cpp b/vendor/glm/test/ext/ext_vector_relational.cpp new file mode 100644 index 0000000..f6cd307 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_relational.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template +static int test_equal() +{ + typedef typename vecType::value_type valType; + + valType const A = static_cast(1.01f); + valType const B = static_cast(1.02f); + valType const Epsilon1 = static_cast(0.1f); + valType const Epsilon2 = static_cast(0.001f); + + int Error = 0; + + Error += glm::all(glm::equal(vecType(A), vecType(B), Epsilon1)) ? 0 : 1; + Error += glm::all(glm::equal(vecType(A), vecType(B), vecType(Epsilon1))) ? 0 : 1; + + Error += !glm::any(glm::equal(vecType(A), vecType(B), Epsilon2)) ? 0 : 1; + Error += !glm::any(glm::equal(vecType(A), vecType(B), vecType(Epsilon2))) ? 0 : 1; + + return Error; +} + +template +static int test_notEqual() +{ + typedef typename vecType::value_type valType; + + valType const A = static_cast(1.01f); + valType const B = static_cast(1.02f); + valType const Epsilon1 = static_cast(0.1f); + valType const Epsilon2 = static_cast(0.001f); + + int Error = 0; + + Error += glm::all(glm::notEqual(vecType(A), vecType(B), Epsilon2)) ? 0 : 1; + Error += glm::all(glm::notEqual(vecType(A), vecType(B), vecType(Epsilon2))) ? 0 : 1; + + Error += !glm::any(glm::notEqual(vecType(A), vecType(B), Epsilon1)) ? 0 : 1; + Error += !glm::any(glm::notEqual(vecType(A), vecType(B), vecType(Epsilon1))) ? 0 : 1; + + return Error; +} + +template +static int test_constexpr() +{ +# if GLM_CONFIG_CONSTEXP == GLM_ENABLE + static_assert(glm::all(glm::equal(genType(static_cast(1.01f)), genType(static_cast(1.02f)), static_cast(0.1f))), "GLM: Failed constexpr"); +# endif + + return 0; +} + +template +static int test_equal_ulps() +{ + typedef glm::vec<4, T, glm::defaultp> vec4; + + T const One(1); + vec4 const Ones(1); + + int Error = 0; + + T const ULP1Plus = glm::nextFloat(One); + Error += glm::all(glm::equal(Ones, vec4(ULP1Plus), 1)) ? 0 : 1; + + T const ULP2Plus = glm::nextFloat(ULP1Plus); + Error += !glm::all(glm::equal(Ones, vec4(ULP2Plus), 1)) ? 0 : 1; + + T const ULP1Minus = glm::prevFloat(One); + Error += glm::all(glm::equal(Ones, vec4(ULP1Minus), 1)) ? 0 : 1; + + T const ULP2Minus = glm::prevFloat(ULP1Minus); + Error += !glm::all(glm::equal(Ones, vec4(ULP2Minus), 1)) ? 0 : 1; + + return Error; +} + +template +static int test_notEqual_ulps() +{ + typedef glm::vec<4, T, glm::defaultp> vec4; + + T const One(1); + vec4 const Ones(1); + + int Error = 0; + + T const ULP1Plus = glm::nextFloat(One); + Error += !glm::all(glm::notEqual(Ones, vec4(ULP1Plus), 1)) ? 0 : 1; + + T const ULP2Plus = glm::nextFloat(ULP1Plus); + Error += glm::all(glm::notEqual(Ones, vec4(ULP2Plus), 1)) ? 0 : 1; + + T const ULP1Minus = glm::prevFloat(One); + Error += !glm::all(glm::notEqual(Ones, vec4(ULP1Minus), 1)) ? 0 : 1; + + T const ULP2Minus = glm::prevFloat(ULP1Minus); + Error += glm::all(glm::notEqual(Ones, vec4(ULP2Minus), 1)) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_equal_ulps(); + Error += test_equal_ulps(); + Error += test_notEqual_ulps(); + Error += test_notEqual_ulps(); + + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + Error += test_equal(); + + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + Error += test_notEqual(); + + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + Error += test_constexpr(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_uint1_sized.cpp b/vendor/glm/test/ext/ext_vector_uint1_sized.cpp new file mode 100644 index 0000000..f2e4624 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_uint1_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT + static_assert(sizeof(glm::u8vec1) == 1, "uint8 size isn't 1 byte on this platform"); + static_assert(sizeof(glm::u16vec1) == 2, "uint16 size isn't 2 bytes on this platform"); + static_assert(sizeof(glm::u32vec1) == 4, "uint32 size isn't 4 bytes on this platform"); + static_assert(sizeof(glm::u64vec1) == 8, "uint64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::u8vec1) == 1 ? 0 : 1; + Error += sizeof(glm::u16vec1) == 2 ? 0 : 1; + Error += sizeof(glm::u32vec1) == 4 ? 0 : 1; + Error += sizeof(glm::u64vec1) == 8 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8vec1) < sizeof(glm::u16vec1) ? 0 : 1; + Error += sizeof(glm::u16vec1) < sizeof(glm::u32vec1) ? 0 : 1; + Error += sizeof(glm::u32vec1) < sizeof(glm::u64vec1) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_uint2_sized.cpp b/vendor/glm/test/ext/ext_vector_uint2_sized.cpp new file mode 100644 index 0000000..9c0977e --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_uint2_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8vec2) == 2, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16vec2) == 4, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32vec2) == 8, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64vec2) == 16, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::u8vec2) == 2 ? 0 : 1; + Error += sizeof(glm::u16vec2) == 4 ? 0 : 1; + Error += sizeof(glm::u32vec2) == 8 ? 0 : 1; + Error += sizeof(glm::u64vec2) == 16 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8vec2) < sizeof(glm::u16vec2) ? 0 : 1; + Error += sizeof(glm::u16vec2) < sizeof(glm::u32vec2) ? 0 : 1; + Error += sizeof(glm::u32vec2) < sizeof(glm::u64vec2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_uint3_sized.cpp b/vendor/glm/test/ext/ext_vector_uint3_sized.cpp new file mode 100644 index 0000000..4cc2e44 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_uint3_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8vec3) == 3, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16vec3) == 6, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32vec3) == 12, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64vec3) == 24, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::u8vec3) == 3 ? 0 : 1; + Error += sizeof(glm::u16vec3) == 6 ? 0 : 1; + Error += sizeof(glm::u32vec3) == 12 ? 0 : 1; + Error += sizeof(glm::u64vec3) == 24 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8vec3) < sizeof(glm::u16vec3) ? 0 : 1; + Error += sizeof(glm::u16vec3) < sizeof(glm::u32vec3) ? 0 : 1; + Error += sizeof(glm::u32vec3) < sizeof(glm::u64vec3) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_uint4_sized.cpp b/vendor/glm/test/ext/ext_vector_uint4_sized.cpp new file mode 100644 index 0000000..9e7ffe7 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_uint4_sized.cpp @@ -0,0 +1,41 @@ +#include + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::u8vec4) == 4, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::u16vec4) == 8, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::u32vec4) == 16, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::u64vec4) == 32, "int64 size isn't 8 bytes on this platform"); +#endif + +static int test_size() +{ + int Error = 0; + + Error += sizeof(glm::u8vec4) == 4 ? 0 : 1; + Error += sizeof(glm::u16vec4) == 8 ? 0 : 1; + Error += sizeof(glm::u32vec4) == 16 ? 0 : 1; + Error += sizeof(glm::u64vec4) == 32 ? 0 : 1; + + return Error; +} + +static int test_comp() +{ + int Error = 0; + + Error += sizeof(glm::u8vec4) < sizeof(glm::u16vec4) ? 0 : 1; + Error += sizeof(glm::u16vec4) < sizeof(glm::u32vec4) ? 0 : 1; + Error += sizeof(glm::u32vec4) < sizeof(glm::u64vec4) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_size(); + Error += test_comp(); + + return Error; +} diff --git a/vendor/glm/test/ext/ext_vector_ulp.cpp b/vendor/glm/test/ext/ext_vector_ulp.cpp new file mode 100644 index 0000000..6ebd1a1 --- /dev/null +++ b/vendor/glm/test/ext/ext_vector_ulp.cpp @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include + +static int test_ulp_float_dist() +{ + int Error = 0; + + glm::vec4 const A(1.0f); + + glm::vec4 const B = glm::nextFloat(A); + Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; + glm::vec4 const C = glm::prevFloat(B); + Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; + + glm::ivec4 const D = glm::floatDistance(A, B); + Error += D == glm::ivec4(1) ? 0 : 1; + glm::ivec4 const E = glm::floatDistance(A, C); + Error += E == glm::ivec4(0) ? 0 : 1; + + return Error; +} + +static int test_ulp_float_step() +{ + int Error = 0; + + glm::vec4 const A(1.0f); + + for(int i = 10; i < 1000; i *= 10) + { + glm::vec4 const B = glm::nextFloat(A, i); + Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; + glm::vec4 const C = glm::prevFloat(B, i); + Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; + + glm::ivec4 const D = glm::floatDistance(A, B); + Error += D == glm::ivec4(i) ? 0 : 1; + glm::ivec4 const E = glm::floatDistance(A, C); + Error += E == glm::ivec4(0) ? 0 : 1; + } + + return Error; +} + +static int test_ulp_double_dist() +{ + int Error = 0; + + glm::dvec4 const A(1.0); + + glm::dvec4 const B = glm::nextFloat(A); + Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; + glm::dvec4 const C = glm::prevFloat(B); + Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; + + glm::ivec4 const D(glm::floatDistance(A, B)); + Error += D == glm::ivec4(1) ? 0 : 1; + glm::ivec4 const E = glm::floatDistance(A, C); + Error += E == glm::ivec4(0) ? 0 : 1; + + return Error; +} + +static int test_ulp_double_step() +{ + int Error = 0; + + glm::dvec4 const A(1.0); + + for(int i = 10; i < 1000; i *= 10) + { + glm::dvec4 const B = glm::nextFloat(A, i); + Error += glm::any(glm::notEqual(A, B, 0)) ? 0 : 1; + glm::dvec4 const C = glm::prevFloat(B, i); + Error += glm::all(glm::equal(A, C, 0)) ? 0 : 1; + + glm::ivec4 const D(glm::floatDistance(A, B)); + Error += D == glm::ivec4(i) ? 0 : 1; + glm::ivec4 const E(glm::floatDistance(A, C)); + Error += E == glm::ivec4(0) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_ulp_float_dist(); + Error += test_ulp_float_step(); + Error += test_ulp_double_dist(); + Error += test_ulp_double_step(); + + return Error; +} diff --git a/vendor/glm/test/glm.cppcheck b/vendor/glm/test/glm.cppcheck new file mode 100644 index 0000000..12081fe --- /dev/null +++ b/vendor/glm/test/glm.cppcheck @@ -0,0 +1,6 @@ + + + + + + diff --git a/vendor/glm/test/gtc/CMakeLists.txt b/vendor/glm/test/gtc/CMakeLists.txt new file mode 100644 index 0000000..4aef24a --- /dev/null +++ b/vendor/glm/test/gtc/CMakeLists.txt @@ -0,0 +1,20 @@ +glmCreateTestGTC(gtc_bitfield) +glmCreateTestGTC(gtc_color_space) +glmCreateTestGTC(gtc_constants) +glmCreateTestGTC(gtc_epsilon) +glmCreateTestGTC(gtc_integer) +glmCreateTestGTC(gtc_matrix_access) +glmCreateTestGTC(gtc_matrix_integer) +glmCreateTestGTC(gtc_matrix_inverse) +glmCreateTestGTC(gtc_matrix_transform) +glmCreateTestGTC(gtc_noise) +glmCreateTestGTC(gtc_packing) +glmCreateTestGTC(gtc_quaternion) +glmCreateTestGTC(gtc_random) +glmCreateTestGTC(gtc_round) +glmCreateTestGTC(gtc_reciprocal) +glmCreateTestGTC(gtc_type_aligned) +glmCreateTestGTC(gtc_type_precision) +glmCreateTestGTC(gtc_type_ptr) +glmCreateTestGTC(gtc_ulp) +glmCreateTestGTC(gtc_vec1) diff --git a/vendor/glm/test/gtc/gtc_bitfield.cpp b/vendor/glm/test/gtc/gtc_bitfield.cpp new file mode 100644 index 0000000..95c41f1 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_bitfield.cpp @@ -0,0 +1,936 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace mask +{ + template + struct type + { + genType Value; + genType Return; + }; + + inline int mask_zero(int Bits) + { + return ~((~0) << Bits); + } + + inline int mask_mix(int Bits) + { + return Bits >= sizeof(int) * 8 ? 0xffffffff : (static_cast(1) << Bits) - static_cast(1); + } + + inline int mask_half(int Bits) + { + // We do the shift in two steps because 1 << 32 on an int is undefined. + + int const Half = Bits >> 1; + int const Fill = ~0; + int const ShiftHaft = (Fill << Half); + int const Rest = Bits - Half; + int const Reversed = ShiftHaft << Rest; + + return ~Reversed; + } + + inline int mask_loop(int Bits) + { + int Mask = 0; + for(int Bit = 0; Bit < Bits; ++Bit) + Mask |= (static_cast(1) << Bit); + return Mask; + } + + int perf() + { + int const Count = 100000000; + + std::clock_t Timestamp1 = std::clock(); + + { + std::vector Mask; + Mask.resize(Count); + for(int i = 0; i < Count; ++i) + Mask[i] = mask_mix(i % 32); + } + + std::clock_t Timestamp2 = std::clock(); + + { + std::vector Mask; + Mask.resize(Count); + for(int i = 0; i < Count; ++i) + Mask[i] = mask_loop(i % 32); + } + + std::clock_t Timestamp3 = std::clock(); + + { + std::vector Mask; + Mask.resize(Count); + for(int i = 0; i < Count; ++i) + Mask[i] = glm::mask(i % 32); + } + + std::clock_t Timestamp4 = std::clock(); + + { + std::vector Mask; + Mask.resize(Count); + for(int i = 0; i < Count; ++i) + Mask[i] = mask_zero(i % 32); + } + + std::clock_t Timestamp5 = std::clock(); + + { + std::vector Mask; + Mask.resize(Count); + for(int i = 0; i < Count; ++i) + Mask[i] = mask_half(i % 32); + } + + std::clock_t Timestamp6 = std::clock(); + + std::clock_t TimeMix = Timestamp2 - Timestamp1; + std::clock_t TimeLoop = Timestamp3 - Timestamp2; + std::clock_t TimeDefault = Timestamp4 - Timestamp3; + std::clock_t TimeZero = Timestamp5 - Timestamp4; + std::clock_t TimeHalf = Timestamp6 - Timestamp5; + + std::printf("mask[mix]: %d\n", static_cast(TimeMix)); + std::printf("mask[loop]: %d\n", static_cast(TimeLoop)); + std::printf("mask[default]: %d\n", static_cast(TimeDefault)); + std::printf("mask[zero]: %d\n", static_cast(TimeZero)); + std::printf("mask[half]: %d\n", static_cast(TimeHalf)); + + return TimeDefault < TimeLoop ? 0 : 1; + } + + int test_uint() + { + type const Data[] = + { + { 0, 0x00000000}, + { 1, 0x00000001}, + { 2, 0x00000003}, + { 3, 0x00000007}, + {31, 0x7fffffff}, + {32, 0xffffffff} + }; + + int Error = 0; +/* mask_zero is sadly not a correct code + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = mask_zero(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } +*/ + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = mask_mix(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = mask_half(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = mask_loop(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0; i < sizeof(Data) / sizeof(type); ++i) + { + int Result = glm::mask(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uvec4() + { + type const Data[] = + { + {glm::ivec4( 0), glm::ivec4(0x00000000)}, + {glm::ivec4( 1), glm::ivec4(0x00000001)}, + {glm::ivec4( 2), glm::ivec4(0x00000003)}, + {glm::ivec4( 3), glm::ivec4(0x00000007)}, + {glm::ivec4(31), glm::ivec4(0x7fffffff)}, + {glm::ivec4(32), glm::ivec4(0xffffffff)} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::ivec4 Result = glm::mask(Data[i].Value); + Error += glm::all(glm::equal(Data[i].Return, Result)) ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error(0); + + Error += test_uint(); + Error += test_uvec4(); + + return Error; + } +}//namespace mask + +namespace bitfieldInterleave3 +{ + template + inline RET refBitfieldInterleave(PARAM x, PARAM y, PARAM z) + { + RET Result = 0; + for(RET i = 0; i < sizeof(PARAM) * 8; ++i) + { + Result |= ((RET(x) & (RET(1U) << i)) << ((i << 1) + 0)); + Result |= ((RET(y) & (RET(1U) << i)) << ((i << 1) + 1)); + Result |= ((RET(z) & (RET(1U) << i)) << ((i << 1) + 2)); + } + return Result; + } + + int test() + { + int Error(0); + + glm::uint16 x_max = 1 << 11; + glm::uint16 y_max = 1 << 11; + glm::uint16 z_max = 1 << 11; + + for(glm::uint16 z = 0; z < z_max; z += 27) + for(glm::uint16 y = 0; y < y_max; y += 27) + for(glm::uint16 x = 0; x < x_max; x += 27) + { + glm::uint64 ResultA = refBitfieldInterleave(x, y, z); + glm::uint64 ResultB = glm::bitfieldInterleave(x, y, z); + Error += ResultA == ResultB ? 0 : 1; + } + + return Error; + } +} + +namespace bitfieldInterleave4 +{ + template + inline RET loopBitfieldInterleave(PARAM x, PARAM y, PARAM z, PARAM w) + { + RET const v[4] = {x, y, z, w}; + RET Result = 0; + for(RET i = 0; i < sizeof(PARAM) * 8; i++) + { + Result |= ((((v[0] >> i) & 1U)) << ((i << 2) + 0)); + Result |= ((((v[1] >> i) & 1U)) << ((i << 2) + 1)); + Result |= ((((v[2] >> i) & 1U)) << ((i << 2) + 2)); + Result |= ((((v[3] >> i) & 1U)) << ((i << 2) + 3)); + } + return Result; + } + + int test() + { + int Error(0); + + glm::uint16 x_max = 1 << 11; + glm::uint16 y_max = 1 << 11; + glm::uint16 z_max = 1 << 11; + glm::uint16 w_max = 1 << 11; + + for(glm::uint16 w = 0; w < w_max; w += 27) + for(glm::uint16 z = 0; z < z_max; z += 27) + for(glm::uint16 y = 0; y < y_max; y += 27) + for(glm::uint16 x = 0; x < x_max; x += 27) + { + glm::uint64 ResultA = loopBitfieldInterleave(x, y, z, w); + glm::uint64 ResultB = glm::bitfieldInterleave(x, y, z, w); + Error += ResultA == ResultB ? 0 : 1; + } + + return Error; + } +} + +namespace bitfieldInterleave +{ + inline glm::uint64 fastBitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + glm::uint64 REG1; + glm::uint64 REG2; + + REG1 = x; + REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + + REG2 = y; + REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + + return REG1 | (REG2 << 1); + } + + inline glm::uint64 interleaveBitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + glm::uint64 REG1; + glm::uint64 REG2; + + REG1 = x; + REG2 = y; + + REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + + REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + + REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + + REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + + REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + + return REG1 | (REG2 << 1); + } +/* + inline glm::uint64 loopBitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + static glm::uint64 const Mask[5] = + { + 0x5555555555555555, + 0x3333333333333333, + 0x0F0F0F0F0F0F0F0F, + 0x00FF00FF00FF00FF, + 0x0000FFFF0000FFFF + }; + + glm::uint64 REG1 = x; + glm::uint64 REG2 = y; + for(int i = 4; i >= 0; --i) + { + REG1 = ((REG1 << (1 << i)) | REG1) & Mask[i]; + REG2 = ((REG2 << (1 << i)) | REG2) & Mask[i]; + } + + return REG1 | (REG2 << 1); + } +*/ +#if GLM_ARCH & GLM_ARCH_SSE2_BIT + inline glm::uint64 sseBitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + __m128i const Array = _mm_set_epi32(0, y, 0, x); + + __m128i const Mask4 = _mm_set1_epi32(0x0000FFFF); + __m128i const Mask3 = _mm_set1_epi32(0x00FF00FF); + __m128i const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + __m128i const Mask1 = _mm_set1_epi32(0x33333333); + __m128i const Mask0 = _mm_set1_epi32(0x55555555); + + __m128i Reg1; + __m128i Reg2; + + // REG1 = x; + // REG2 = y; + Reg1 = _mm_load_si128(&Array); + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + __m128i Result; + _mm_store_si128(&Result, Reg1); + return *reinterpret_cast(&Result); + } + + inline glm::uint64 sseUnalignedBitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + __m128i const Array = _mm_set_epi32(0, y, 0, x); + + __m128i const Mask4 = _mm_set1_epi32(0x0000FFFF); + __m128i const Mask3 = _mm_set1_epi32(0x00FF00FF); + __m128i const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + __m128i const Mask1 = _mm_set1_epi32(0x33333333); + __m128i const Mask0 = _mm_set1_epi32(0x55555555); + + __m128i Reg1; + __m128i Reg2; + + // REG1 = x; + // REG2 = y; + Reg1 = _mm_loadu_si128(&Array); + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + __m128i Result; + _mm_store_si128(&Result, Reg1); + return *reinterpret_cast(&Result); + } +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + + int test() + { + int Error = 0; + +/* + { + for(glm::uint32 y = 0; y < (1 << 10); ++y) + for(glm::uint32 x = 0; x < (1 << 10); ++x) + { + glm::uint64 A = glm::bitfieldInterleave(x, y); + glm::uint64 B = fastBitfieldInterleave(x, y); + //glm::uint64 C = loopBitfieldInterleave(x, y); + glm::uint64 D = interleaveBitfieldInterleave(x, y); + + assert(A == B); + //assert(A == C); + assert(A == D); + +# if GLM_ARCH & GLM_ARCH_SSE2_BIT + glm::uint64 E = sseBitfieldInterleave(x, y); + glm::uint64 F = sseUnalignedBitfieldInterleave(x, y); + assert(A == E); + assert(A == F); + + __m128i G = glm_i128_interleave(_mm_set_epi32(0, y, 0, x)); + glm::uint64 Result[2]; + _mm_storeu_si128((__m128i*)Result, G); + assert(A == Result[0]); +# endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + } + } +*/ + { + for(glm::uint8 y = 0; y < 127; ++y) + for(glm::uint8 x = 0; x < 127; ++x) + { + glm::uint64 A(glm::bitfieldInterleave(glm::u8vec2(x, y))); + glm::uint64 B(glm::bitfieldInterleave(glm::u16vec2(x, y))); + glm::uint64 C(glm::bitfieldInterleave(glm::u32vec2(x, y))); + + Error += A == B ? 0 : 1; + Error += A == C ? 0 : 1; + + glm::u32vec2 const& D = glm::bitfieldDeinterleave(C); + Error += D.x == x ? 0 : 1; + Error += D.y == y ? 0 : 1; + } + } + + { + for(glm::uint8 y = 0; y < 127; ++y) + for(glm::uint8 x = 0; x < 127; ++x) + { + glm::int64 A(glm::bitfieldInterleave(glm::int8(x), glm::int8(y))); + glm::int64 B(glm::bitfieldInterleave(glm::int16(x), glm::int16(y))); + glm::int64 C(glm::bitfieldInterleave(glm::int32(x), glm::int32(y))); + + Error += A == B ? 0 : 1; + Error += A == C ? 0 : 1; + } + } + + return Error; + } + + int perf() + { + glm::uint32 x_max = 1 << 11; + glm::uint32 y_max = 1 << 10; + + // ALU + std::vector Data(x_max * y_max); + std::vector Param(x_max * y_max); + for(glm::uint32 i = 0; i < Param.size(); ++i) + Param[i] = glm::u32vec2(i % x_max, i / y_max); + + { + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = glm::bitfieldInterleave(Param[i].x, Param[i].y); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("glm::bitfieldInterleave Time %d clocks\n", static_cast(Time)); + } + + { + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = fastBitfieldInterleave(Param[i].x, Param[i].y); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("fastBitfieldInterleave Time %d clocks\n", static_cast(Time)); + } +/* + { + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = loopBitfieldInterleave(Param[i].x, Param[i].y); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("loopBitfieldInterleave Time %d clocks\n", static_cast(Time)); + } +*/ + { + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = interleaveBitfieldInterleave(Param[i].x, Param[i].y); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("interleaveBitfieldInterleave Time %d clocks\n", static_cast(Time)); + } + +# if GLM_ARCH & GLM_ARCH_SSE2_BIT + { + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = sseBitfieldInterleave(Param[i].x, Param[i].y); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("sseBitfieldInterleave Time %d clocks\n", static_cast(Time)); + } + + { + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = sseUnalignedBitfieldInterleave(Param[i].x, Param[i].y); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("sseUnalignedBitfieldInterleave Time %d clocks\n", static_cast(Time)); + } +# endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + + { + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = glm::bitfieldInterleave(Param[i].x, Param[i].y, Param[i].x); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("glm::detail::bitfieldInterleave Time %d clocks\n", static_cast(Time)); + } + +# if(GLM_ARCH & GLM_ARCH_SSE2_BIT && !(GLM_COMPILER & GLM_COMPILER_GCC)) + { + // SIMD + std::vector<__m128i> SimdData; + SimdData.resize(static_cast(x_max * y_max)); + std::vector<__m128i> SimdParam; + SimdParam.resize(static_cast(x_max * y_max)); + for(std::size_t i = 0; i < SimdParam.size(); ++i) + SimdParam[i] = _mm_set_epi32(static_cast(i % static_cast(x_max)), 0, static_cast(i / static_cast(y_max)), 0); + + std::clock_t LastTime = std::clock(); + + for(std::size_t i = 0; i < SimdData.size(); ++i) + SimdData[i] = glm_i128_interleave(SimdParam[i]); + + std::clock_t Time = std::clock() - LastTime; + + std::printf("_mm_bit_interleave_si128 Time %d clocks\n", static_cast(Time)); + } +# endif//GLM_ARCH & GLM_ARCH_SSE2_BIT + + return 0; + } +}//namespace bitfieldInterleave + +namespace bitfieldInterleave5 +{ + GLM_FUNC_QUALIFIER glm::uint16 bitfieldInterleave_u8vec2(glm::uint8 x, glm::uint8 y) + { + glm::uint32 Result = (glm::uint32(y) << 16) | glm::uint32(x); + Result = ((Result << 4) | Result) & 0x0F0F0F0F; + Result = ((Result << 2) | Result) & 0x33333333; + Result = ((Result << 1) | Result) & 0x55555555; + return static_cast((Result & 0x0000FFFF) | (Result >> 15)); + } + + GLM_FUNC_QUALIFIER glm::u8vec2 bitfieldDeinterleave_u8vec2(glm::uint16 InterleavedBitfield) + { + glm::uint32 Result(InterleavedBitfield); + Result = ((Result << 15) | Result) & 0x55555555; + Result = ((Result >> 1) | Result) & 0x33333333; + Result = ((Result >> 2) | Result) & 0x0F0F0F0F; + Result = ((Result >> 4) | Result) & 0x00FF00FF; + return glm::u8vec2(Result & 0x0000FFFF, Result >> 16); + } + + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave_u8vec4(glm::uint8 x, glm::uint8 y, glm::uint8 z, glm::uint8 w) + { + glm::uint64 Result = (glm::uint64(w) << 48) | (glm::uint64(z) << 32) | (glm::uint64(y) << 16) | glm::uint64(x); + Result = ((Result << 12) | Result) & 0x000F000F000F000Full; + Result = ((Result << 6) | Result) & 0x0303030303030303ull; + Result = ((Result << 3) | Result) & 0x1111111111111111ull; + + const glm::uint32 a = static_cast((Result & 0x000000000000FFFF) >> ( 0 - 0)); + const glm::uint32 b = static_cast((Result & 0x00000000FFFF0000) >> (16 - 3)); + const glm::uint32 c = static_cast((Result & 0x0000FFFF00000000) >> (32 - 6)); + const glm::uint32 d = static_cast((Result & 0xFFFF000000000000) >> (48 - 12)); + + return a | b | c | d; + } + + GLM_FUNC_QUALIFIER glm::u8vec4 bitfieldDeinterleave_u8vec4(glm::uint32 InterleavedBitfield) + { + glm::uint64 Result(InterleavedBitfield); + Result = ((Result << 15) | Result) & 0x9249249249249249ull; + Result = ((Result >> 1) | Result) & 0x30C30C30C30C30C3ull; + Result = ((Result >> 2) | Result) & 0xF00F00F00F00F00Full; + Result = ((Result >> 4) | Result) & 0x00FF0000FF0000FFull; + return glm::u8vec4( + (Result >> 0) & 0x000000000000FFFFull, + (Result >> 16) & 0x00000000FFFF0000ull, + (Result >> 32) & 0x0000FFFF00000000ull, + (Result >> 48) & 0xFFFF000000000000ull); + } + + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave_u16vec2(glm::uint16 x, glm::uint16 y) + { + glm::uint64 Result = (glm::uint64(y) << 32) | glm::uint64(x); + Result = ((Result << 8) | Result) & static_cast(0x00FF00FF00FF00FFull); + Result = ((Result << 4) | Result) & static_cast(0x0F0F0F0F0F0F0F0Full); + Result = ((Result << 2) | Result) & static_cast(0x3333333333333333ull); + Result = ((Result << 1) | Result) & static_cast(0x5555555555555555ull); + return static_cast((Result & 0x00000000FFFFFFFFull) | (Result >> 31)); + } + + GLM_FUNC_QUALIFIER glm::u16vec2 bitfieldDeinterleave_u16vec2(glm::uint32 InterleavedBitfield) + { + glm::uint64 Result(InterleavedBitfield); + Result = ((Result << 31) | Result) & 0x5555555555555555ull; + Result = ((Result >> 1) | Result) & 0x3333333333333333ull; + Result = ((Result >> 2) | Result) & 0x0F0F0F0F0F0F0F0Full; + Result = ((Result >> 4) | Result) & 0x00FF00FF00FF00FFull; + Result = ((Result >> 8) | Result) & 0x0000FFFF0000FFFFull; + return glm::u16vec2(Result & 0x00000000FFFFFFFFull, Result >> 32); + } + + int test() + { + int Error = 0; + + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + { + glm::uint16 A = bitfieldInterleave_u8vec2(glm::uint8(i), glm::uint8(j)); + glm::uint16 B = glm::bitfieldInterleave(glm::uint8(i), glm::uint8(j)); + Error += A == B ? 0 : 1; + + glm::u8vec2 C = bitfieldDeinterleave_u8vec2(A); + Error += C.x == glm::uint8(i) ? 0 : 1; + Error += C.y == glm::uint8(j) ? 0 : 1; + } + + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + { + glm::uint32 A = bitfieldInterleave_u8vec4(glm::uint8(i), glm::uint8(j), glm::uint8(i), glm::uint8(j)); + glm::uint32 B = glm::bitfieldInterleave(glm::uint8(i), glm::uint8(j), glm::uint8(i), glm::uint8(j)); + Error += A == B ? 0 : 1; +/* + glm::u8vec4 C = bitfieldDeinterleave_u8vec4(A); + Error += C.x == glm::uint8(i) ? 0 : 1; + Error += C.y == glm::uint8(j) ? 0 : 1; + Error += C.z == glm::uint8(i) ? 0 : 1; + Error += C.w == glm::uint8(j) ? 0 : 1; +*/ + } + + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + { + glm::uint32 A = bitfieldInterleave_u16vec2(glm::uint16(i), glm::uint16(j)); + glm::uint32 B = glm::bitfieldInterleave(glm::uint16(i), glm::uint16(j)); + Error += A == B ? 0 : 1; + } + + return Error; + } + + int perf_old_u8vec2(std::vector& Result) + { + int Error = 0; + + const std::clock_t BeginTime = std::clock(); + + for(glm::size_t k = 0; k < 10000; ++k) + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Error += Result[j * 256 + i] == glm::bitfieldInterleave(glm::uint8(i), glm::uint8(j)) ? 0 : 1; + + const std::clock_t EndTime = std::clock(); + + std::printf("glm::bitfieldInterleave Time %d clocks\n", static_cast(EndTime - BeginTime)); + + return Error; + } + + int perf_new_u8vec2(std::vector& Result) + { + int Error = 0; + + const std::clock_t BeginTime = std::clock(); + + for(glm::size_t k = 0; k < 10000; ++k) + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Error += Result[j * 256 + i] == bitfieldInterleave_u8vec2(glm::uint8(i), glm::uint8(j)) ? 0 : 1; + + const std::clock_t EndTime = std::clock(); + + std::printf("bitfieldInterleave_u8vec2 Time %d clocks\n", static_cast(EndTime - BeginTime)); + + return Error; + } + + int perf_old_u8vec4(std::vector& Result) + { + int Error = 0; + + const std::clock_t BeginTime = std::clock(); + + for(glm::size_t k = 0; k < 10000; ++k) + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Error += Result[j * 256 + i] == glm::bitfieldInterleave(glm::uint8(i), glm::uint8(j), glm::uint8(i), glm::uint8(j)) ? 0 : 1; + + const std::clock_t EndTime = std::clock(); + + std::printf("glm::bitfieldInterleave Time %d clocks\n", static_cast(EndTime - BeginTime)); + + return Error; + } + + int perf_new_u8vec4(std::vector& Result) + { + int Error = 0; + + const std::clock_t BeginTime = std::clock(); + + for(glm::size_t k = 0; k < 10000; ++k) + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Error += Result[j * 256 + i] == bitfieldInterleave_u8vec4(glm::uint8(i), glm::uint8(j), glm::uint8(i), glm::uint8(j)) ? 0 : 1; + + const std::clock_t EndTime = std::clock(); + + std::printf("bitfieldInterleave_u8vec4 Time %d clocks\n", static_cast(EndTime - BeginTime)); + + return Error; + } + + int perf_old_u16vec2(std::vector& Result) + { + int Error = 0; + + const std::clock_t BeginTime = std::clock(); + + for(glm::size_t k = 0; k < 10000; ++k) + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Error += Result[j * 256 + i] == glm::bitfieldInterleave(glm::uint16(i), glm::uint16(j)) ? 0 : 1; + + const std::clock_t EndTime = std::clock(); + + std::printf("glm::bitfieldInterleave Time %d clocks\n", static_cast(EndTime - BeginTime)); + + return Error; + } + + int perf_new_u16vec2(std::vector& Result) + { + int Error = 0; + + const std::clock_t BeginTime = std::clock(); + + for(glm::size_t k = 0; k < 10000; ++k) + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Error += Result[j * 256 + i] == bitfieldInterleave_u16vec2(glm::uint16(i), glm::uint16(j)) ? 0 : 1; + + const std::clock_t EndTime = std::clock(); + + std::printf("bitfieldInterleave_u16vec2 Time %d clocks\n", static_cast(EndTime - BeginTime)); + + return Error; + } + + int perf() + { + int Error = 0; + + std::printf("bitfieldInterleave perf: init\r"); + + std::vector Result_u8vec2(256 * 256, 0); + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Result_u8vec2[j * 256 + i] = glm::bitfieldInterleave(glm::uint8(i), glm::uint8(j)); + + Error += perf_old_u8vec2(Result_u8vec2); + Error += perf_new_u8vec2(Result_u8vec2); + + std::vector Result_u8vec4(256 * 256, 0); + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Result_u8vec4[j * 256 + i] = glm::bitfieldInterleave(glm::uint8(i), glm::uint8(j), glm::uint8(i), glm::uint8(j)); + + Error += perf_old_u8vec4(Result_u8vec4); + Error += perf_new_u8vec4(Result_u8vec4); + + std::vector Result_u16vec2(256 * 256, 0); + for(glm::size_t j = 0; j < 256; ++j) + for(glm::size_t i = 0; i < 256; ++i) + Result_u16vec2[j * 256 + i] = glm::bitfieldInterleave(glm::uint16(i), glm::uint16(j)); + + Error += perf_old_u16vec2(Result_u16vec2); + Error += perf_new_u16vec2(Result_u16vec2); + + std::printf("bitfieldInterleave perf: %d Errors\n", Error); + + return Error; + } + +}//namespace bitfieldInterleave5 + +static int test_bitfieldRotateRight() +{ + glm::ivec4 const A = glm::bitfieldRotateRight(glm::ivec4(2), 1); + glm::ivec4 const B = glm::ivec4(2) >> 1; + + return A == B; +} + +static int test_bitfieldRotateLeft() +{ + glm::ivec4 const A = glm::bitfieldRotateLeft(glm::ivec4(2), 1); + glm::ivec4 const B = glm::ivec4(2) << 1; + + return A == B; +} + +int main() +{ + int Error = 0; + +/* Tests for a faster and to reserve bitfieldInterleave + Error += ::bitfieldInterleave5::test(); + Error += ::bitfieldInterleave5::perf(); +*/ + Error += ::mask::test(); + Error += ::bitfieldInterleave3::test(); + Error += ::bitfieldInterleave4::test(); + Error += ::bitfieldInterleave::test(); + + Error += test_bitfieldRotateRight(); + Error += test_bitfieldRotateLeft(); + +# ifdef NDEBUG + Error += ::mask::perf(); + Error += ::bitfieldInterleave::perf(); +# endif//NDEBUG + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_color_space.cpp b/vendor/glm/test/gtc/gtc_color_space.cpp new file mode 100644 index 0000000..67650c5 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_color_space.cpp @@ -0,0 +1,78 @@ +#include +#include +#include + +namespace srgb +{ + int test() + { + int Error(0); + + glm::vec3 const ColorSourceRGB(1.0, 0.5, 0.0); + + { + glm::vec3 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceRGB); + glm::vec3 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB); + Error += glm::all(glm::epsilonEqual(ColorSourceRGB, ColorRGB, 0.00001f)) ? 0 : 1; + } + + { + glm::vec3 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceRGB, 2.8f); + glm::vec3 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB, 2.8f); + Error += glm::all(glm::epsilonEqual(ColorSourceRGB, ColorRGB, 0.00001f)) ? 0 : 1; + } + + glm::vec4 const ColorSourceRGBA(1.0, 0.5, 0.0, 1.0); + + { + glm::vec4 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceRGBA); + glm::vec4 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB); + Error += glm::all(glm::epsilonEqual(ColorSourceRGBA, ColorRGB, 0.00001f)) ? 0 : 1; + } + + { + glm::vec4 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceRGBA, 2.8f); + glm::vec4 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB, 2.8f); + Error += glm::all(glm::epsilonEqual(ColorSourceRGBA, ColorRGB, 0.00001f)) ? 0 : 1; + } + + glm::vec4 const ColorSourceGNI = glm::vec4(107, 107, 104, 131) / glm::vec4(255); + + { + glm::vec4 const ColorGNA = glm::convertSRGBToLinear(ColorSourceGNI) * glm::vec4(255); + glm::vec4 const ColorGNE = glm::convertLinearToSRGB(ColorSourceGNI) * glm::vec4(255); + glm::vec4 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceGNI); + glm::vec4 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB); + Error += glm::all(glm::epsilonEqual(ColorSourceGNI, ColorRGB, 0.00001f)) ? 0 : 1; + } + + return Error; + } +}//namespace srgb + +namespace srgb_lowp +{ + int test() + { + int Error(0); + + for(float Color = 0.0f; Color < 1.0f; Color += 0.01f) + { + glm::highp_vec3 const HighpSRGB = glm::convertLinearToSRGB(glm::highp_vec3(Color)); + glm::lowp_vec3 const LowpSRGB = glm::convertLinearToSRGB(glm::lowp_vec3(Color)); + Error += glm::all(glm::epsilonEqual(glm::abs(HighpSRGB - glm::highp_vec3(LowpSRGB)), glm::highp_vec3(0), 0.1f)) ? 0 : 1; + } + + return Error; + } +}//namespace srgb_lowp + +int main() +{ + int Error(0); + + Error += srgb::test(); + Error += srgb_lowp::test(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_constants.cpp b/vendor/glm/test/gtc/gtc_constants.cpp new file mode 100644 index 0000000..3897cd0 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_constants.cpp @@ -0,0 +1,30 @@ +#include + +int test_epsilon() +{ + int Error = 0; + + { + float Test = glm::epsilon(); + Error += Test > 0.0f ? 0 : 1; + } + + { + double Test = glm::epsilon(); + Error += Test > 0.0 ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error(0); + + //float MinHalf = 0.0f; + //while (glm::half(MinHalf) == glm::half(0.0f)) + // MinHalf += std::numeric_limits::epsilon(); + Error += test_epsilon(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_epsilon.cpp b/vendor/glm/test/gtc/gtc_epsilon.cpp new file mode 100644 index 0000000..f0e6c8a --- /dev/null +++ b/vendor/glm/test/gtc/gtc_epsilon.cpp @@ -0,0 +1,78 @@ +#include +#include +#include +#include + +int test_defined() +{ + glm::epsilonEqual(glm::vec2(), glm::vec2(), glm::vec2()); + glm::epsilonEqual(glm::vec3(), glm::vec3(), glm::vec3()); + glm::epsilonEqual(glm::vec4(), glm::vec4(), glm::vec4()); + + glm::epsilonNotEqual(glm::vec2(), glm::vec2(), glm::vec2()); + glm::epsilonNotEqual(glm::vec3(), glm::vec3(), glm::vec3()); + glm::epsilonNotEqual(glm::vec4(), glm::vec4(), glm::vec4()); + + glm::epsilonEqual(glm::vec2(), glm::vec2(), 0.0f); + glm::epsilonEqual(glm::vec3(), glm::vec3(), 0.0f); + glm::epsilonEqual(glm::vec4(), glm::vec4(), 0.0f); + glm::epsilonEqual(glm::quat(), glm::quat(), 0.0f); + + glm::epsilonNotEqual(glm::vec2(), glm::vec2(), 0.0f); + glm::epsilonNotEqual(glm::vec3(), glm::vec3(), 0.0f); + glm::epsilonNotEqual(glm::vec4(), glm::vec4(), 0.0f); + glm::epsilonNotEqual(glm::quat(), glm::quat(), 0.0f); + + return 0; +} + +template +int test_equal() +{ + int Error(0); + + { + T A = glm::epsilon(); + T B = glm::epsilon(); + Error += glm::epsilonEqual(A, B, glm::epsilon() * T(2)) ? 0 : 1; + } + + { + T A(0); + T B = static_cast(0) + glm::epsilon(); + Error += glm::epsilonEqual(A, B, glm::epsilon() * T(2)) ? 0 : 1; + } + + { + T A(0); + T B = static_cast(0) - glm::epsilon(); + Error += glm::epsilonEqual(A, B, glm::epsilon() * T(2)) ? 0 : 1; + } + + { + T A = static_cast(0) + glm::epsilon(); + T B = static_cast(0); + Error += glm::epsilonEqual(A, B, glm::epsilon() * T(2)) ? 0 : 1; + } + + { + T A = static_cast(0) - glm::epsilon(); + T B = static_cast(0); + Error += glm::epsilonEqual(A, B, glm::epsilon() * T(2)) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error(0); + + Error += test_defined(); + Error += test_equal(); + Error += test_equal(); + + return Error; +} + + diff --git a/vendor/glm/test/gtc/gtc_integer.cpp b/vendor/glm/test/gtc/gtc_integer.cpp new file mode 100644 index 0000000..769d969 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_integer.cpp @@ -0,0 +1,233 @@ +#define GLM_ENABLE_EXPERIMENTAL +#define GLM_FORCE_INLINE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace log2_ +{ + int test() + { + int Error = 0; + + int A0 = static_cast(glm::log2(16.f)); + glm::ivec1 B0(glm::log2(glm::vec1(16.f))); + glm::ivec2 C0(glm::log2(glm::vec2(16.f))); + glm::ivec3 D0(glm::log2(glm::vec3(16.f))); + glm::ivec4 E0(glm::log2(glm::vec4(16.f))); + + int A1 = glm::log2(int(16)); + glm::ivec1 B1 = glm::log2(glm::ivec1(16)); + glm::ivec2 C1 = glm::log2(glm::ivec2(16)); + glm::ivec3 D1 = glm::log2(glm::ivec3(16)); + glm::ivec4 E1 = glm::log2(glm::ivec4(16)); + + Error += A0 == A1 ? 0 : 1; + Error += glm::all(glm::equal(B0, B1)) ? 0 : 1; + Error += glm::all(glm::equal(C0, C1)) ? 0 : 1; + Error += glm::all(glm::equal(D0, D1)) ? 0 : 1; + Error += glm::all(glm::equal(E0, E1)) ? 0 : 1; + + glm::uint64 A2 = glm::log2(glm::uint64(16)); + glm::u64vec1 B2 = glm::log2(glm::u64vec1(16)); + glm::u64vec2 C2 = glm::log2(glm::u64vec2(16)); + glm::u64vec3 D2 = glm::log2(glm::u64vec3(16)); + glm::u64vec4 E2 = glm::log2(glm::u64vec4(16)); + + Error += A2 == glm::uint64(4) ? 0 : 1; + Error += glm::all(glm::equal(B2, glm::u64vec1(4))) ? 0 : 1; + Error += glm::all(glm::equal(C2, glm::u64vec2(4))) ? 0 : 1; + Error += glm::all(glm::equal(D2, glm::u64vec3(4))) ? 0 : 1; + Error += glm::all(glm::equal(E2, glm::u64vec4(4))) ? 0 : 1; + + return Error; + } + + int perf(std::size_t Count) + { + int Error = 0; + + { + std::vector Result; + Result.resize(Count); + + std::clock_t Begin = clock(); + + for(int i = 0; i < static_cast(Count); ++i) + Result[i] = glm::log2(static_cast(i)); + + std::clock_t End = clock(); + + std::printf("glm::log2: %d clocks\n", static_cast(End - Begin)); + } + + { + std::vector Result; + Result.resize(Count); + + std::clock_t Begin = clock(); + + for(int i = 0; i < static_cast(Count); ++i) + Result[i] = glm::log2(glm::ivec4(i)); + + std::clock_t End = clock(); + + std::printf("glm::log2: %d clocks\n", static_cast(End - Begin)); + } + +# if GLM_HAS_BITSCAN_WINDOWS + { + std::vector Result; + Result.resize(Count); + + std::clock_t Begin = clock(); + + for(std::size_t i = 0; i < Count; ++i) + { + glm::vec<4, unsigned long, glm::defaultp> Tmp; + _BitScanReverse(&Tmp.x, i); + _BitScanReverse(&Tmp.y, i); + _BitScanReverse(&Tmp.z, i); + _BitScanReverse(&Tmp.w, i); + Result[i] = glm::ivec4(Tmp); + } + + std::clock_t End = clock(); + + std::printf("glm::log2 inlined: %d clocks\n", static_cast(End - Begin)); + } + + + { + std::vector > Result; + Result.resize(Count); + + std::clock_t Begin = clock(); + + for(std::size_t i = 0; i < Count; ++i) + { + _BitScanReverse(&Result[i].x, i); + _BitScanReverse(&Result[i].y, i); + _BitScanReverse(&Result[i].z, i); + _BitScanReverse(&Result[i].w, i); + } + + std::clock_t End = clock(); + + std::printf("glm::log2 inlined no cast: %d clocks\n", static_cast(End - Begin)); + } + + + { + std::vector Result; + Result.resize(Count); + + std::clock_t Begin = clock(); + + for(std::size_t i = 0; i < Count; ++i) + { + _BitScanReverse(reinterpret_cast(&Result[i].x), i); + _BitScanReverse(reinterpret_cast(&Result[i].y), i); + _BitScanReverse(reinterpret_cast(&Result[i].z), i); + _BitScanReverse(reinterpret_cast(&Result[i].w), i); + } + + std::clock_t End = clock(); + + std::printf("glm::log2 reinterpret: %d clocks\n", static_cast(End - Begin)); + } +# endif//GLM_HAS_BITSCAN_WINDOWS + + { + std::vector Result; + Result.resize(Count); + + std::clock_t Begin = clock(); + + for(std::size_t i = 0; i < Count; ++i) + Result[i] = glm::log2(static_cast(i)); + + std::clock_t End = clock(); + + std::printf("glm::log2: %d clocks\n", static_cast(End - Begin)); + } + + { + std::vector Result; + Result.resize(Count); + + std::clock_t Begin = clock(); + + for(int i = 0; i < static_cast(Count); ++i) + Result[i] = glm::log2(glm::vec4(static_cast(i))); + + std::clock_t End = clock(); + + std::printf("glm::log2: %d clocks\n", static_cast(End - Begin)); + } + + return Error; + } +}//namespace log2_ + +namespace iround +{ + int test() + { + int Error = 0; + + for(float f = 0.0f; f < 3.1f; f += 0.05f) + { + int RoundFast = static_cast(glm::iround(f)); + int RoundSTD = static_cast(glm::round(f)); + Error += RoundFast == RoundSTD ? 0 : 1; + assert(!Error); + } + + return Error; + } +}//namespace iround + +namespace uround +{ + int test() + { + int Error = 0; + + for(float f = 0.0f; f < 3.1f; f += 0.05f) + { + int RoundFast = static_cast(glm::uround(f)); + int RoundSTD = static_cast(glm::round(f)); + Error += RoundFast == RoundSTD ? 0 : 1; + assert(!Error); + } + + return Error; + } +}//namespace uround + +int main() +{ + int Error(0); + + Error += ::log2_::test(); + Error += ::iround::test(); + Error += ::uround::test(); + +# ifdef NDEBUG + std::size_t const Samples(1000); + Error += ::log2_::perf(Samples); +# endif//NDEBUG + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_matrix_access.cpp b/vendor/glm/test/gtc/gtc_matrix_access.cpp new file mode 100644 index 0000000..1b966e2 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_matrix_access.cpp @@ -0,0 +1,383 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int test_mat2x2_row_set() +{ + int Error = 0; + + glm::mat2x2 m(1); + + m = glm::row(m, 0, glm::vec2( 0, 1)); + m = glm::row(m, 1, glm::vec2( 4, 5)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec2( 0, 1), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec2( 4, 5), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat2x2_col_set() +{ + int Error = 0; + + glm::mat2x2 m(1); + + m = glm::column(m, 0, glm::vec2( 0, 1)); + m = glm::column(m, 1, glm::vec2( 4, 5)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec2( 0, 1), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec2( 4, 5), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat2x3_row_set() +{ + int Error = 0; + + glm::mat2x3 m(1); + + m = glm::row(m, 0, glm::vec2( 0, 1)); + m = glm::row(m, 1, glm::vec2( 4, 5)); + m = glm::row(m, 2, glm::vec2( 8, 9)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec2( 0, 1), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec2( 4, 5), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 2), glm::vec2( 8, 9), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat2x3_col_set() +{ + int Error = 0; + + glm::mat2x3 m(1); + + m = glm::column(m, 0, glm::vec3( 0, 1, 2)); + m = glm::column(m, 1, glm::vec3( 4, 5, 6)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec3( 0, 1, 2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec3( 4, 5, 6), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat2x4_row_set() +{ + int Error = 0; + + glm::mat2x4 m(1); + + m = glm::row(m, 0, glm::vec2( 0, 1)); + m = glm::row(m, 1, glm::vec2( 4, 5)); + m = glm::row(m, 2, glm::vec2( 8, 9)); + m = glm::row(m, 3, glm::vec2(12, 13)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec2( 0, 1), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec2( 4, 5), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 2), glm::vec2( 8, 9), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 3), glm::vec2(12, 13), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat2x4_col_set() +{ + int Error = 0; + + glm::mat2x4 m(1); + + m = glm::column(m, 0, glm::vec4( 0, 1, 2, 3)); + m = glm::column(m, 1, glm::vec4( 4, 5, 6, 7)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec4( 0, 1, 2, 3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec4( 4, 5, 6, 7), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat3x2_row_set() +{ + int Error = 0; + + glm::mat3x2 m(1); + + m = glm::row(m, 0, glm::vec3( 0, 1, 2)); + m = glm::row(m, 1, glm::vec3( 4, 5, 6)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec3( 0, 1, 2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec3( 4, 5, 6), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat3x2_col_set() +{ + int Error = 0; + + glm::mat3x2 m(1); + + m = glm::column(m, 0, glm::vec2( 0, 1)); + m = glm::column(m, 1, glm::vec2( 4, 5)); + m = glm::column(m, 2, glm::vec2( 8, 9)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec2( 0, 1), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec2( 4, 5), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 2), glm::vec2( 8, 9), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat3x3_row_set() +{ + int Error = 0; + + glm::mat3x3 m(1); + + m = glm::row(m, 0, glm::vec3( 0, 1, 2)); + m = glm::row(m, 1, glm::vec3( 4, 5, 6)); + m = glm::row(m, 2, glm::vec3( 8, 9, 10)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec3( 0, 1, 2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec3( 4, 5, 6), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 2), glm::vec3( 8, 9, 10), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat3x3_col_set() +{ + int Error = 0; + + glm::mat3x3 m(1); + + m = glm::column(m, 0, glm::vec3( 0, 1, 2)); + m = glm::column(m, 1, glm::vec3( 4, 5, 6)); + m = glm::column(m, 2, glm::vec3( 8, 9, 10)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec3( 0, 1, 2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec3( 4, 5, 6), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 2), glm::vec3( 8, 9, 10), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat3x4_row_set() +{ + int Error = 0; + + glm::mat3x4 m(1); + + m = glm::row(m, 0, glm::vec3( 0, 1, 2)); + m = glm::row(m, 1, glm::vec3( 4, 5, 6)); + m = glm::row(m, 2, glm::vec3( 8, 9, 10)); + m = glm::row(m, 3, glm::vec3(12, 13, 14)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec3( 0, 1, 2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec3( 4, 5, 6), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 2), glm::vec3( 8, 9, 10), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 3), glm::vec3(12, 13, 14), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat3x4_col_set() +{ + int Error = 0; + + glm::mat3x4 m(1); + + m = glm::column(m, 0, glm::vec4( 0, 1, 2, 3)); + m = glm::column(m, 1, glm::vec4( 4, 5, 6, 7)); + m = glm::column(m, 2, glm::vec4( 8, 9, 10, 11)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec4( 0, 1, 2, 3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec4( 4, 5, 6, 7), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 2), glm::vec4( 8, 9, 10, 11), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x2_row_set() +{ + int Error = 0; + + glm::mat4x2 m(1); + + m = glm::row(m, 0, glm::vec4( 0, 1, 2, 3)); + m = glm::row(m, 1, glm::vec4( 4, 5, 6, 7)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec4( 0, 1, 2, 3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec4( 4, 5, 6, 7), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x2_col_set() +{ + int Error = 0; + + glm::mat4x2 m(1); + + m = glm::column(m, 0, glm::vec2( 0, 1)); + m = glm::column(m, 1, glm::vec2( 4, 5)); + m = glm::column(m, 2, glm::vec2( 8, 9)); + m = glm::column(m, 3, glm::vec2(12, 13)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec2( 0, 1), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec2( 4, 5), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 2), glm::vec2( 8, 9), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 3), glm::vec2(12, 13), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x3_row_set() +{ + int Error = 0; + + glm::mat4x3 m(1); + + m = glm::row(m, 0, glm::vec4( 0, 1, 2, 3)); + m = glm::row(m, 1, glm::vec4( 4, 5, 6, 7)); + m = glm::row(m, 2, glm::vec4( 8, 9, 10, 11)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec4( 0, 1, 2, 3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec4( 4, 5, 6, 7), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 2), glm::vec4( 8, 9, 10, 11), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x3_col_set() +{ + int Error = 0; + + glm::mat4x3 m(1); + + m = glm::column(m, 0, glm::vec3( 0, 1, 2)); + m = glm::column(m, 1, glm::vec3( 4, 5, 6)); + m = glm::column(m, 2, glm::vec3( 8, 9, 10)); + m = glm::column(m, 3, glm::vec3(12, 13, 14)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec3( 0, 1, 2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec3( 4, 5, 6), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 2), glm::vec3( 8, 9, 10), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 3), glm::vec3(12, 13, 14), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x4_row_set() +{ + int Error = 0; + + glm::mat4 m(1); + + m = glm::row(m, 0, glm::vec4( 0, 1, 2, 3)); + m = glm::row(m, 1, glm::vec4( 4, 5, 6, 7)); + m = glm::row(m, 2, glm::vec4( 8, 9, 10, 11)); + m = glm::row(m, 3, glm::vec4(12, 13, 14, 15)); + + Error += glm::all(glm::equal(glm::row(m, 0), glm::vec4( 0, 1, 2, 3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 1), glm::vec4( 4, 5, 6, 7), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 2), glm::vec4( 8, 9, 10, 11), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::row(m, 3), glm::vec4(12, 13, 14, 15), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x4_col_set() +{ + int Error = 0; + + glm::mat4 m(1); + + m = glm::column(m, 0, glm::vec4( 0, 1, 2, 3)); + m = glm::column(m, 1, glm::vec4( 4, 5, 6, 7)); + m = glm::column(m, 2, glm::vec4( 8, 9, 10, 11)); + m = glm::column(m, 3, glm::vec4(12, 13, 14, 15)); + + Error += glm::all(glm::equal(glm::column(m, 0), glm::vec4( 0, 1, 2, 3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 1), glm::vec4( 4, 5, 6, 7), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 2), glm::vec4( 8, 9, 10, 11), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(glm::column(m, 3), glm::vec4(12, 13, 14, 15), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x4_row_get() +{ + int Error = 0; + + glm::mat4 m(1); + + glm::vec4 A = glm::row(m, 0); + Error += glm::all(glm::equal(A, glm::vec4(1, 0, 0, 0), glm::epsilon())) ? 0 : 1; + glm::vec4 B = glm::row(m, 1); + Error += glm::all(glm::equal(B, glm::vec4(0, 1, 0, 0), glm::epsilon())) ? 0 : 1; + glm::vec4 C = glm::row(m, 2); + Error += glm::all(glm::equal(C, glm::vec4(0, 0, 1, 0), glm::epsilon())) ? 0 : 1; + glm::vec4 D = glm::row(m, 3); + Error += glm::all(glm::equal(D, glm::vec4(0, 0, 0, 1), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int test_mat4x4_col_get() +{ + int Error = 0; + + glm::mat4 m(1); + + glm::vec4 A = glm::column(m, 0); + Error += glm::all(glm::equal(A, glm::vec4(1, 0, 0, 0), glm::epsilon())) ? 0 : 1; + glm::vec4 B = glm::column(m, 1); + Error += glm::all(glm::equal(B, glm::vec4(0, 1, 0, 0), glm::epsilon())) ? 0 : 1; + glm::vec4 C = glm::column(m, 2); + Error += glm::all(glm::equal(C, glm::vec4(0, 0, 1, 0), glm::epsilon())) ? 0 : 1; + glm::vec4 D = glm::column(m, 3); + Error += glm::all(glm::equal(D, glm::vec4(0, 0, 0, 1), glm::epsilon())) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_mat2x2_row_set(); + Error += test_mat2x2_col_set(); + Error += test_mat2x3_row_set(); + Error += test_mat2x3_col_set(); + Error += test_mat2x4_row_set(); + Error += test_mat2x4_col_set(); + Error += test_mat3x2_row_set(); + Error += test_mat3x2_col_set(); + Error += test_mat3x3_row_set(); + Error += test_mat3x3_col_set(); + Error += test_mat3x4_row_set(); + Error += test_mat3x4_col_set(); + Error += test_mat4x2_row_set(); + Error += test_mat4x2_col_set(); + Error += test_mat4x3_row_set(); + Error += test_mat4x3_col_set(); + Error += test_mat4x4_row_set(); + Error += test_mat4x4_col_set(); + + Error += test_mat4x4_row_get(); + Error += test_mat4x4_col_get(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_matrix_integer.cpp b/vendor/glm/test/gtc/gtc_matrix_integer.cpp new file mode 100644 index 0000000..108016a --- /dev/null +++ b/vendor/glm/test/gtc/gtc_matrix_integer.cpp @@ -0,0 +1,8 @@ +#include + +int main() +{ + int Error = 0; + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_matrix_inverse.cpp b/vendor/glm/test/gtc/gtc_matrix_inverse.cpp new file mode 100644 index 0000000..eaec6e1 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_matrix_inverse.cpp @@ -0,0 +1,51 @@ +#include +#include + +int test_affine() +{ + int Error = 0; + + { + glm::mat3 const M( + 2.f, 0.f, 0.f, + 0.f, 2.f, 0.f, + 0.f, 0.f, 1.f); + glm::mat3 const A = glm::affineInverse(M); + glm::mat3 const I = glm::inverse(M); + glm::mat3 const R = glm::affineInverse(A); + + for(glm::length_t i = 0; i < A.length(); ++i) + { + Error += glm::all(glm::epsilonEqual(M[i], R[i], 0.01f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(A[i], I[i], 0.01f)) ? 0 : 1; + } + } + + { + glm::mat4 const M( + 2.f, 0.f, 0.f, 0.f, + 0.f, 2.f, 0.f, 0.f, + 0.f, 0.f, 2.f, 0.f, + 0.f, 0.f, 0.f, 1.f); + glm::mat4 const A = glm::affineInverse(M); + glm::mat4 const I = glm::inverse(M); + glm::mat4 const R = glm::affineInverse(A); + + for(glm::length_t i = 0; i < A.length(); ++i) + { + Error += glm::all(glm::epsilonEqual(M[i], R[i], 0.01f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(A[i], I[i], 0.01f)) ? 0 : 1; + } + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_affine(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_matrix_transform.cpp b/vendor/glm/test/gtc/gtc_matrix_transform.cpp new file mode 100644 index 0000000..b50666e --- /dev/null +++ b/vendor/glm/test/gtc/gtc_matrix_transform.cpp @@ -0,0 +1,55 @@ +#include +#include +#include + +int test_perspective() +{ + int Error = 0; + + glm::mat4 Projection = glm::perspective(glm::pi() * 0.25f, 4.0f / 3.0f, 0.1f, 100.0f); + + return Error; +} + +int test_pick() +{ + int Error = 0; + + glm::mat4 Pick = glm::pickMatrix(glm::vec2(1, 2), glm::vec2(3, 4), glm::ivec4(0, 0, 320, 240)); + + return Error; +} + +int test_tweakedInfinitePerspective() +{ + int Error = 0; + + glm::mat4 ProjectionA = glm::tweakedInfinitePerspective(45.f, 640.f/480.f, 1.0f); + glm::mat4 ProjectionB = glm::tweakedInfinitePerspective(45.f, 640.f/480.f, 1.0f, 0.001f); + + + return Error; +} + +int test_translate() +{ + int Error = 0; + + glm::lowp_vec3 v(1.0); + glm::lowp_mat4 m(0); + glm::lowp_mat4 t = glm::translate(m, v); + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_translate(); + Error += test_tweakedInfinitePerspective(); + Error += test_pick(); + Error += test_perspective(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_noise.cpp b/vendor/glm/test/gtc/gtc_noise.cpp new file mode 100644 index 0000000..6ecec22 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_noise.cpp @@ -0,0 +1,86 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +static int test_simplex_float() +{ + int Error = 0; + + glm::u8vec4 const PixelSimplex2D(glm::byte(glm::abs(glm::simplex(glm::vec2(0.f, 0.f))) * 255.f)); + glm::u8vec4 const PixelSimplex3D(glm::byte(glm::abs(glm::simplex(glm::vec3(0.f, 0.f, 0.f))) * 255.f)); + glm::u8vec4 const PixelSimplex4D(glm::byte(glm::abs(glm::simplex(glm::vec4(0.f, 0.f, 0.f, 0.f))) * 255.f)); + + return Error; +} + +static int test_simplex_double() +{ + int Error = 0; + + glm::u8vec4 const PixelSimplex2D(glm::byte(glm::abs(glm::simplex(glm::dvec2(0.f, 0.f))) * 255.)); + glm::u8vec4 const PixelSimplex3D(glm::byte(glm::abs(glm::simplex(glm::dvec3(0.f, 0.f, 0.f))) * 255.)); + glm::u8vec4 const PixelSimplex4D(glm::byte(glm::abs(glm::simplex(glm::dvec4(0.f, 0.f, 0.f, 0.f))) * 255.)); + + return Error; +} + +static int test_perlin_float() +{ + int Error = 0; + + glm::u8vec4 const PixelPerlin2D(glm::byte(glm::abs(glm::perlin(glm::vec2(0.f, 0.f))) * 255.f)); + glm::u8vec4 const PixelPerlin3D(glm::byte(glm::abs(glm::perlin(glm::vec3(0.f, 0.f, 0.f))) * 255.f)); + glm::u8vec4 const PixelPerlin4D(glm::byte(glm::abs(glm::perlin(glm::vec4(0.f, 0.f, 0.f, 0.f))) * 255.f)); + + return Error; +} + +static int test_perlin_double() +{ + int Error = 0; + + glm::u8vec4 const PixelPerlin2D(glm::byte(glm::abs(glm::perlin(glm::dvec2(0.f, 0.f))) * 255.)); + glm::u8vec4 const PixelPerlin3D(glm::byte(glm::abs(glm::perlin(glm::dvec3(0.f, 0.f, 0.f))) * 255.)); + glm::u8vec4 const PixelPerlin4D(glm::byte(glm::abs(glm::perlin(glm::dvec4(0.f, 0.f, 0.f, 0.f))) * 255.)); + + return Error; +} + +static int test_perlin_pedioric_float() +{ + int Error = 0; + + glm::u8vec4 const PixelPeriodic2D(glm::byte(glm::abs(glm::perlin(glm::vec2(0.f, 0.f), glm::vec2(2.0f))) * 255.f)); + glm::u8vec4 const PixelPeriodic3D(glm::byte(glm::abs(glm::perlin(glm::vec3(0.f, 0.f, 0.f), glm::vec3(2.0f))) * 255.f)); + glm::u8vec4 const PixelPeriodic4D(glm::byte(glm::abs(glm::perlin(glm::vec4(0.f, 0.f, 0.f, 0.f), glm::vec4(2.0f))) * 255.f)); + + return Error; +} + +static int test_perlin_pedioric_double() +{ + int Error = 0; + + glm::u8vec4 const PixelPeriodic2D(glm::byte(glm::abs(glm::perlin(glm::dvec2(0.f, 0.f), glm::dvec2(2.0))) * 255.)); + glm::u8vec4 const PixelPeriodic3D(glm::byte(glm::abs(glm::perlin(glm::dvec3(0.f, 0.f, 0.f), glm::dvec3(2.0))) * 255.)); + glm::u8vec4 const PixelPeriodic4D(glm::byte(glm::abs(glm::perlin(glm::dvec4(0.f, 0.f, 0.f, 0.f), glm::dvec4(2.0))) * 255.)); + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_simplex_float(); + Error += test_simplex_double(); + + Error += test_perlin_float(); + Error += test_perlin_double(); + + Error += test_perlin_pedioric_float(); + Error += test_perlin_pedioric_double(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_packing.cpp b/vendor/glm/test/gtc/gtc_packing.cpp new file mode 100644 index 0000000..df5b3bb --- /dev/null +++ b/vendor/glm/test/gtc/gtc_packing.cpp @@ -0,0 +1,878 @@ +#include +#include +#include +#include +#include +#include + +void print_bits(float const& s) +{ + union + { + float f; + unsigned int i; + } uif; + + uif.f = s; + + std::printf("f32: "); + for(std::size_t j = sizeof(s) * 8; j > 0; --j) + { + if(j == 23 || j == 31) + std::printf(" "); + std::printf("%d", (uif.i & (1 << (j - 1))) ? 1 : 0); + } +} + +void print_10bits(glm::uint const& s) +{ + std::printf("10b: "); + for(std::size_t j = 10; j > 0; --j) + { + if(j == 5) + std::printf(" "); + std::printf("%d", (s & (1 << (j - 1))) ? 1 : 0); + } +} + +void print_11bits(glm::uint const& s) +{ + std::printf("11b: "); + for(std::size_t j = 11; j > 0; --j) + { + if(j == 6) + std::printf(" "); + std::printf("%d", (s & (1 << (j - 1))) ? 1 : 0); + } +} + +void print_value(float const& s) +{ + std::printf("%2.5f, ", static_cast(s)); + print_bits(s); + std::printf(", "); +// print_11bits(detail::floatTo11bit(s)); +// std::printf(", "); +// print_10bits(detail::floatTo10bit(s)); + std::printf("\n"); +} + +int test_Half1x16() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(0.0f); + Tests.push_back(1.0f); + Tests.push_back(-1.0f); + Tests.push_back(2.0f); + Tests.push_back(-2.0f); + Tests.push_back(1.9f); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint16 p0 = glm::packHalf1x16(Tests[i]); + float v0 = glm::unpackHalf1x16(p0); + glm::uint16 p1 = glm::packHalf1x16(v0); + float v1 = glm::unpackHalf1x16(p1); + Error += glm::epsilonEqual(v0, v1, glm::epsilon()) ? 0 : 1; + } + + return Error; +} + +int test_Half4x16() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::vec4(1.0f)); + Tests.push_back(glm::vec4(0.0f)); + Tests.push_back(glm::vec4(2.0f)); + Tests.push_back(glm::vec4(0.1f)); + Tests.push_back(glm::vec4(0.5f)); + Tests.push_back(glm::vec4(-0.9f)); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint64 p0 = glm::packHalf4x16(Tests[i]); + glm::vec4 v0 = glm::unpackHalf4x16(p0); + glm::uint64 p1 = glm::packHalf4x16(v0); + glm::vec4 v1 = glm::unpackHalf4x16(p1); + glm::u16vec4 p2 = glm::packHalf(v0); + glm::vec4 v2 = glm::unpackHalf(p2); + + Error += glm::all(glm::equal(v0, v1, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v0, v2, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +int test_I3x10_1x2() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::ivec4(0)); + Tests.push_back(glm::ivec4(1)); + Tests.push_back(glm::ivec4(-1)); + Tests.push_back(glm::ivec4(2)); + Tests.push_back(glm::ivec4(-2)); + Tests.push_back(glm::ivec4(3)); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint32 p0 = glm::packI3x10_1x2(Tests[i]); + glm::ivec4 v0 = glm::unpackI3x10_1x2(p0); + glm::uint32 p1 = glm::packI3x10_1x2(v0); + glm::ivec4 v1 = glm::unpackI3x10_1x2(p1); + Error += glm::all(glm::equal(v0, v1)) ? 0 : 1; + } + + return Error; +} + +int test_U3x10_1x2() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::uvec4(0)); + Tests.push_back(glm::uvec4(1)); + Tests.push_back(glm::uvec4(2)); + Tests.push_back(glm::uvec4(3)); + Tests.push_back(glm::uvec4(4)); + Tests.push_back(glm::uvec4(5)); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint32 p0 = glm::packU3x10_1x2(Tests[i]); + glm::uvec4 v0 = glm::unpackU3x10_1x2(p0); + glm::uint32 p1 = glm::packU3x10_1x2(v0); + glm::uvec4 v1 = glm::unpackU3x10_1x2(p1); + Error += glm::all(glm::equal(v0, v1)) ? 0 : 1; + } + + glm::u8vec4 const v0(0xff, 0x77, 0x0, 0x33); + glm::uint32 const p0 = *reinterpret_cast(&v0[0]); + glm::uint32 const r0 = 0x330077ff; + + Error += p0 == r0 ? 0 : 1; + + glm::uvec4 const v1(0xff, 0x77, 0x0, 0x33); + glm::uint32 const p1 = glm::packU3x10_1x2(v1); + glm::uint32 const r1 = 0xc001dcff; + + Error += p1 == r1 ? 0 : 1; + + return Error; +} + +int test_Snorm3x10_1x2() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::vec4(1.0f)); + Tests.push_back(glm::vec4(0.0f)); + Tests.push_back(glm::vec4(2.0f)); + Tests.push_back(glm::vec4(0.1f)); + Tests.push_back(glm::vec4(0.5f)); + Tests.push_back(glm::vec4(0.9f)); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint32 p0 = glm::packSnorm3x10_1x2(Tests[i]); + glm::vec4 v0 = glm::unpackSnorm3x10_1x2(p0); + glm::uint32 p1 = glm::packSnorm3x10_1x2(v0); + glm::vec4 v1 = glm::unpackSnorm3x10_1x2(p1); + + Error += glm::all(glm::epsilonEqual(v0, v1, 0.01f)) ? 0 : 1; + } + + return Error; +} + +int test_Unorm3x10_1x2() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::vec4(1.0f)); + Tests.push_back(glm::vec4(0.0f)); + Tests.push_back(glm::vec4(2.0f)); + Tests.push_back(glm::vec4(0.1f)); + Tests.push_back(glm::vec4(0.5f)); + Tests.push_back(glm::vec4(0.9f)); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint32 p0 = glm::packUnorm3x10_1x2(Tests[i]); + glm::vec4 v0 = glm::unpackUnorm3x10_1x2(p0); + glm::uint32 p1 = glm::packUnorm3x10_1x2(v0); + glm::vec4 v1 = glm::unpackUnorm3x10_1x2(p1); + + Error += glm::all(glm::epsilonEqual(v0, v1, 0.001f)) ? 0 : 1; + } + + return Error; +} + +int test_F2x11_1x10() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::vec3(1.0f)); + Tests.push_back(glm::vec3(0.0f)); + Tests.push_back(glm::vec3(2.0f)); + Tests.push_back(glm::vec3(0.1f)); + Tests.push_back(glm::vec3(0.5f)); + Tests.push_back(glm::vec3(0.9f)); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint32 p0 = glm::packF2x11_1x10(Tests[i]); + glm::vec3 v0 = glm::unpackF2x11_1x10(p0); + glm::uint32 p1 = glm::packF2x11_1x10(v0); + glm::vec3 v1 = glm::unpackF2x11_1x10(p1); + Error += glm::all(glm::equal(v0, v1, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +int test_F3x9_E1x5() +{ + int Error = 0; + + std::vector Tests; + Tests.push_back(glm::vec3(1.0f)); + Tests.push_back(glm::vec3(0.0f)); + Tests.push_back(glm::vec3(2.0f)); + Tests.push_back(glm::vec3(0.1f)); + Tests.push_back(glm::vec3(0.5f)); + Tests.push_back(glm::vec3(0.9f)); + + for(std::size_t i = 0; i < Tests.size(); ++i) + { + glm::uint32 p0 = glm::packF3x9_E1x5(Tests[i]); + glm::vec3 v0 = glm::unpackF3x9_E1x5(p0); + glm::uint32 p1 = glm::packF3x9_E1x5(v0); + glm::vec3 v1 = glm::unpackF3x9_E1x5(p1); + Error += glm::all(glm::equal(v0, v1, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +int test_RGBM() +{ + int Error = 0; + + for(std::size_t i = 0; i < 1024; ++i) + { + glm::vec3 const Color(static_cast(i)); + glm::vec4 const RGBM = glm::packRGBM(Color); + glm::vec3 const Result= glm::unpackRGBM(RGBM); + + Error += glm::all(glm::equal(Color, Result, 0.01f)) ? 0 : 1; + } + + return Error; +} + +int test_packUnorm1x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec1(1.0f)); + A.push_back(glm::vec1(0.5f)); + A.push_back(glm::vec1(0.1f)); + A.push_back(glm::vec1(0.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec1 B(A[i]); + glm::uint16 C = glm::packUnorm1x16(B.x); + glm::vec1 D(glm::unpackUnorm1x16(C)); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 65535.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm1x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec1( 1.0f)); + A.push_back(glm::vec1( 0.0f)); + A.push_back(glm::vec1(-0.5f)); + A.push_back(glm::vec1(-0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec1 B(A[i]); + glm::uint16 C = glm::packSnorm1x16(B.x); + glm::vec1 D(glm::unpackSnorm1x16(C)); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 32767.0f * 2.0f)) ? 0 : 1; + } + + return Error; +} + +int test_packUnorm2x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.0f)); + A.push_back(glm::vec2(0.5f, 0.7f)); + A.push_back(glm::vec2(0.1f, 0.2f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint32 C = glm::packUnorm2x16(B); + glm::vec2 D = glm::unpackUnorm2x16(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 65535.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm2x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2( 1.0f, 0.0f)); + A.push_back(glm::vec2(-0.5f,-0.7f)); + A.push_back(glm::vec2(-0.1f, 0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint32 C = glm::packSnorm2x16(B); + glm::vec2 D = glm::unpackSnorm2x16(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 32767.0f * 2.0f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm4x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec4(1.0f)); + A.push_back(glm::vec4(0.5f)); + A.push_back(glm::vec4(0.1f)); + A.push_back(glm::vec4(0.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint64 C = glm::packUnorm4x16(B); + glm::vec4 D(glm::unpackUnorm4x16(C)); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 65535.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm4x16() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec4( 1.0f, 0.0f, -0.5f, 0.5f)); + A.push_back(glm::vec4(-0.3f,-0.7f, 0.3f, 0.7f)); + A.push_back(glm::vec4(-0.1f, 0.1f, -0.2f, 0.2f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint64 C = glm::packSnorm4x16(B); + glm::vec4 D(glm::unpackSnorm4x16(C)); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 32767.0f * 2.0f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm1x8() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec1(1.0f)); + A.push_back(glm::vec1(0.5f)); + A.push_back(glm::vec1(0.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec1 B(A[i]); + glm::uint8 C = glm::packUnorm1x8(B.x); + glm::vec1 D(glm::unpackUnorm1x8(C)); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 255.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm1x8() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec1( 1.0f)); + A.push_back(glm::vec1(-0.7f)); + A.push_back(glm::vec1(-1.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec1 B(A[i]); + glm::uint8 C = glm::packSnorm1x8(B.x); + glm::vec1 D(glm::unpackSnorm1x8(C)); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 127.f)) ? 0 : 1; + } + + return Error; +} + +int test_packUnorm2x8() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.7f)); + A.push_back(glm::vec2(0.5f, 0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint16 C = glm::packUnorm2x8(B); + glm::vec2 D = glm::unpackUnorm2x8(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 255.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm2x8() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2( 1.0f, 0.0f)); + A.push_back(glm::vec2(-0.7f,-0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint16 C = glm::packSnorm2x8(B); + glm::vec2 D = glm::unpackSnorm2x8(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 127.f)) ? 0 : 1; + } + + return Error; +} + +int test_packUnorm4x8() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec4(1.0f, 0.7f, 0.3f, 0.0f)); + A.push_back(glm::vec4(0.5f, 0.1f, 0.2f, 0.3f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint32 C = glm::packUnorm4x8(B); + glm::vec4 D = glm::unpackUnorm4x8(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 255.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm4x8() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec4( 1.0f, 0.0f,-0.5f,-1.0f)); + A.push_back(glm::vec4(-0.7f,-0.1f, 0.1f, 0.7f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint32 C = glm::packSnorm4x8(B); + glm::vec4 D = glm::unpackSnorm4x8(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 127.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.7f)); + A.push_back(glm::vec2(0.5f, 0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::u16vec2 C = glm::packUnorm(B); + glm::vec2 D = glm::unpackUnorm(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 255.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packSnorm() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2( 1.0f, 0.0f)); + A.push_back(glm::vec2(-0.5f,-0.7f)); + A.push_back(glm::vec2(-0.1f, 0.1f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::i16vec2 C = glm::packSnorm(B); + glm::vec2 D = glm::unpackSnorm(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 32767.0f * 2.0f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm2x4() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec2(1.0f, 0.7f)); + A.push_back(glm::vec2(0.5f, 0.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec2 B(A[i]); + glm::uint8 C = glm::packUnorm2x4(B); + glm::vec2 D = glm::unpackUnorm2x4(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 15.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm4x4() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec4(1.0f, 0.7f, 0.5f, 0.0f)); + A.push_back(glm::vec4(0.5f, 0.1f, 0.0f, 1.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint16 C = glm::packUnorm4x4(B); + glm::vec4 D = glm::unpackUnorm4x4(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 15.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm3x5_1x1() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec4(1.0f, 0.7f, 0.5f, 0.0f)); + A.push_back(glm::vec4(0.5f, 0.1f, 0.0f, 1.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec4 B(A[i]); + glm::uint16 C = glm::packUnorm3x5_1x1(B); + glm::vec4 D = glm::unpackUnorm3x5_1x1(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 15.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm1x5_1x6_1x5() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec3(1.0f, 0.7f, 0.5f)); + A.push_back(glm::vec3(0.5f, 0.1f, 0.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec3 B(A[i]); + glm::uint16 C = glm::packUnorm1x5_1x6_1x5(B); + glm::vec3 D = glm::unpackUnorm1x5_1x6_1x5(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 15.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUnorm2x3_1x2() +{ + int Error = 0; + + std::vector A; + A.push_back(glm::vec3(1.0f, 0.7f, 0.5f)); + A.push_back(glm::vec3(0.5f, 0.1f, 0.0f)); + + for(std::size_t i = 0; i < A.size(); ++i) + { + glm::vec3 B(A[i]); + glm::uint8 C = glm::packUnorm2x3_1x2(B); + glm::vec3 D = glm::unpackUnorm2x3_1x2(C); + Error += glm::all(glm::epsilonEqual(B, D, 1.0f / 3.f)) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_packUint2x8() +{ + int Error = 0; + + glm::u8vec2 const Source(1, 2); + + glm::uint16 const Packed = glm::packUint2x8(Source); + Error += Packed != 0 ? 0 : 1; + + glm::u8vec2 const Unpacked = glm::unpackUint2x8(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packUint4x8() +{ + int Error = 0; + + glm::u8vec4 const Source(1, 2, 3, 4); + + glm::uint32 const Packed = glm::packUint4x8(Source); + Error += Packed != 0 ? 0 : 1; + + glm::u8vec4 const Unpacked = glm::unpackUint4x8(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packUint2x16() +{ + int Error = 0; + + glm::u16vec2 const Source(1, 2); + + glm::uint32 const Packed = glm::packUint2x16(Source); + Error += Packed != 0 ? 0 : 1; + + glm::u16vec2 const Unpacked = glm::unpackUint2x16(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packUint4x16() +{ + int Error = 0; + + glm::u16vec4 const Source(1, 2, 3, 4); + + glm::uint64 const Packed = glm::packUint4x16(Source); + Error += Packed != 0 ? 0 : 1; + + glm::u16vec4 const Unpacked = glm::unpackUint4x16(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packUint2x32() +{ + int Error = 0; + + glm::u32vec2 const Source(1, 2); + + glm::uint64 const Packed = glm::packUint2x32(Source); + Error += Packed != 0 ? 0 : 1; + + glm::u32vec2 const Unpacked = glm::unpackUint2x32(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packInt2x8() +{ + int Error = 0; + + glm::i8vec2 const Source(1, 2); + + glm::int16 const Packed = glm::packInt2x8(Source); + Error += Packed != 0 ? 0 : 1; + + glm::i8vec2 const Unpacked = glm::unpackInt2x8(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packInt4x8() +{ + int Error = 0; + + glm::i8vec4 const Source(1, 2, 3, 4); + + glm::int32 const Packed = glm::packInt4x8(Source); + Error += Packed != 0 ? 0 : 1; + + glm::i8vec4 const Unpacked = glm::unpackInt4x8(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packInt2x16() +{ + int Error = 0; + + glm::i16vec2 const Source(1, 2); + + glm::int32 const Packed = glm::packInt2x16(Source); + Error += Packed != 0 ? 0 : 1; + + glm::i16vec2 const Unpacked = glm::unpackInt2x16(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packInt4x16() +{ + int Error = 0; + + glm::i16vec4 const Source(1, 2, 3, 4); + + glm::int64 const Packed = glm::packInt4x16(Source); + Error += Packed != 0 ? 0 : 1; + + glm::i16vec4 const Unpacked = glm::unpackInt4x16(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int test_packInt2x32() +{ + int Error = 0; + + glm::i32vec2 const Source(1, 2); + + glm::int64 const Packed = glm::packInt2x32(Source); + Error += Packed != 0 ? 0 : 1; + + glm::i32vec2 const Unpacked = glm::unpackInt2x32(Packed); + Error += Source == Unpacked ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_packUnorm(); + Error += test_packSnorm(); + + Error += test_packSnorm1x16(); + Error += test_packSnorm2x16(); + Error += test_packSnorm4x16(); + + Error += test_packSnorm1x8(); + Error += test_packSnorm2x8(); + Error += test_packSnorm4x8(); + + Error += test_packUnorm1x16(); + Error += test_packUnorm2x16(); + Error += test_packUnorm4x16(); + + Error += test_packUnorm1x8(); + Error += test_packUnorm2x8(); + Error += test_packUnorm4x8(); + + Error += test_packUnorm2x4(); + Error += test_packUnorm4x4(); + Error += test_packUnorm3x5_1x1(); + Error += test_packUnorm1x5_1x6_1x5(); + Error += test_packUnorm2x3_1x2(); + + Error += test_packUint2x8(); + Error += test_packUint4x8(); + Error += test_packUint2x16(); + Error += test_packUint4x16(); + Error += test_packUint2x32(); + + Error += test_packInt2x8(); + Error += test_packInt4x8(); + Error += test_packInt2x16(); + Error += test_packInt4x16(); + Error += test_packInt2x32(); + + Error += test_F2x11_1x10(); + Error += test_F3x9_E1x5(); + Error += test_RGBM(); + Error += test_Unorm3x10_1x2(); + Error += test_Snorm3x10_1x2(); + + Error += test_I3x10_1x2(); + Error += test_U3x10_1x2(); + Error += test_Half1x16(); + Error += test_Half4x16(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_quaternion.cpp b/vendor/glm/test/gtc/gtc_quaternion.cpp new file mode 100644 index 0000000..540ca42 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_quaternion.cpp @@ -0,0 +1,345 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int test_quat_angle() +{ + int Error = 0; + + { + glm::quat Q = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(0, 0, 1)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::equal(L, 1.0f, 0.01f) ? 0 : 1; + float A = glm::angle(N); + Error += glm::equal(A, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(glm::pi() * 0.25f, glm::normalize(glm::vec3(0, 1, 1))); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::equal(L, 1.0f, 0.01f) ? 0 : 1; + float A = glm::angle(N); + Error += glm::equal(A, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(glm::pi() * 0.25f, glm::normalize(glm::vec3(1, 2, 3))); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::equal(L, 1.0f, 0.01f) ? 0 : 1; + float A = glm::angle(N); + Error += glm::equal(A, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + } + + return Error; +} + +int test_quat_angleAxis() +{ + int Error = 0; + + glm::quat A = glm::angleAxis(0.f, glm::vec3(0.f, 0.f, 1.f)); + glm::quat B = glm::angleAxis(glm::pi() * 0.5f, glm::vec3(0, 0, 1)); + glm::quat C = glm::mix(A, B, 0.5f); + glm::quat D = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(0, 0, 1)); + + Error += glm::equal(C.x, D.x, 0.01f) ? 0 : 1; + Error += glm::equal(C.y, D.y, 0.01f) ? 0 : 1; + Error += glm::equal(C.z, D.z, 0.01f) ? 0 : 1; + Error += glm::equal(C.w, D.w, 0.01f) ? 0 : 1; + + return Error; +} + +int test_quat_mix() +{ + int Error = 0; + + glm::quat A = glm::angleAxis(0.f, glm::vec3(0.f, 0.f, 1.f)); + glm::quat B = glm::angleAxis(glm::pi() * 0.5f, glm::vec3(0, 0, 1)); + glm::quat C = glm::mix(A, B, 0.5f); + glm::quat D = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(0, 0, 1)); + + Error += glm::equal(C.x, D.x, 0.01f) ? 0 : 1; + Error += glm::equal(C.y, D.y, 0.01f) ? 0 : 1; + Error += glm::equal(C.z, D.z, 0.01f) ? 0 : 1; + Error += glm::equal(C.w, D.w, 0.01f) ? 0 : 1; + + return Error; +} + +int test_quat_normalize() +{ + int Error(0); + + { + glm::quat Q = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(0, 0, 1)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::equal(L, 1.0f, 0.000001f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(0, 0, 2)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::equal(L, 1.0f, 0.000001f) ? 0 : 1; + } + { + glm::quat Q = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(1, 2, 3)); + glm::quat N = glm::normalize(Q); + float L = glm::length(N); + Error += glm::equal(L, 1.0f, 0.000001f) ? 0 : 1; + } + + return Error; +} + +int test_quat_euler() +{ + int Error = 0; + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float Roll = glm::roll(q); + float Pitch = glm::pitch(q); + float Yaw = glm::yaw(q); + glm::vec3 Angles = glm::eulerAngles(q); + Error += glm::all(glm::equal(Angles, glm::vec3(Pitch, Yaw, Roll), 0.000001f)) ? 0 : 1; + } + + { + glm::dquat q(1.0, 0.0, 0.0, 1.0); + double Roll = glm::roll(q); + double Pitch = glm::pitch(q); + double Yaw = glm::yaw(q); + glm::dvec3 Angles = glm::eulerAngles(q); + Error += glm::all(glm::equal(Angles, glm::dvec3(Pitch, Yaw, Roll), 0.000001)) ? 0 : 1; + } + + return Error; +} + +int test_quat_slerp() +{ + int Error = 0; + + float const Epsilon = 0.0001f;//glm::epsilon(); + + float sqrt2 = std::sqrt(2.0f)/2.0f; + glm::quat id(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + glm::quat Y90rot(sqrt2, 0.0f, sqrt2, 0.0f); + glm::quat Y180rot(0.0f, 0.0f, 1.0f, 0.0f); + + // Testing a == 0 + // Must be id + glm::quat id2 = glm::slerp(id, Y90rot, 0.0f); + Error += glm::all(glm::equal(id, id2, Epsilon)) ? 0 : 1; + + // Testing a == 1 + // Must be 90° rotation on Y : 0 0.7 0 0.7 + glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f); + Error += glm::all(glm::equal(Y90rot, Y90rot2, Epsilon)) ? 0 : 1; + + // Testing standard, easy case + // Must be 45° rotation on Y : 0 0.38 0 0.92 + glm::quat Y45rot1 = glm::slerp(id, Y90rot, 0.5f); + + // Testing reverse case + // Must be 45° rotation on Y : 0 0.38 0 0.92 + glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.5f); + + // Testing against full circle around the sphere instead of shortest path + // Must be 45° rotation on Y + // certainly not a 135° rotation + glm::quat Y45rot3 = glm::slerp(id , -Y90rot, 0.5f); + float Y45angle3 = glm::angle(Y45rot3); + Error += glm::equal(Y45angle3, glm::pi() * 0.25f, Epsilon) ? 0 : 1; + Error += glm::all(glm::equal(Ym45rot2, Y45rot3, Epsilon)) ? 0 : 1; + + // Same, but inverted + // Must also be 45° rotation on Y : 0 0.38 0 0.92 + // -0 -0.38 -0 -0.92 is ok too + glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f); + Error += glm::all(glm::equal(Ym45rot2, -Y45rot4, Epsilon)) ? 0 : 1; + + // Testing q1 = q2 + // Must be 90° rotation on Y : 0 0.7 0 0.7 + glm::quat Y90rot3 = glm::slerp(Y90rot, Y90rot, 0.5f); + Error += glm::all(glm::equal(Y90rot, Y90rot3, Epsilon)) ? 0 : 1; + + // Testing 180° rotation + // Must be 90° rotation on almost any axis that is on the XZ plane + glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f); + float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78; + Error += glm::equal(XZ90angle, glm::pi() * 0.25f, Epsilon) ? 0 : 1; + + // Testing almost equal quaternions (this test should pass through the linear interpolation) + // Must be 0 0.00X 0 0.99999 + glm::quat almostid = glm::slerp(id, glm::angleAxis(0.1f, glm::vec3(0.0f, 1.0f, 0.0f)), 0.5f); + + // Testing quaternions with opposite sign + { + glm::quat a(-1, 0, 0, 0); + + glm::quat result = glm::slerp(a, id, 0.5f); + + Error += glm::equal(glm::pow(glm::dot(id, result), 2.f), 1.f, 0.01f) ? 0 : 1; + } + + return Error; +} + +int test_quat_slerp_spins() +{ + int Error = 0; + + float const Epsilon = 0.0001f;//glm::epsilon(); + + float sqrt2 = std::sqrt(2.0f) / 2.0f; + glm::quat id(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + glm::quat Y90rot(sqrt2, 0.0f, sqrt2, 0.0f); + glm::quat Y180rot(0.0f, 0.0f, 1.0f, 0.0f); + + // Testing a == 0, k == 1 + // Must be id + glm::quat id2 = glm::slerp(id, id, 1.0f, 1); + Error += glm::all(glm::equal(id, id2, Epsilon)) ? 0 : 1; + + // Testing a == 1, k == 2 + // Must be id + glm::quat id3 = glm::slerp(id, id, 1.0f, 2); + Error += glm::all(glm::equal(id, id3, Epsilon)) ? 0 : 1; + + // Testing a == 1, k == 1 + // Must be 90° rotation on Y : 0 0.7 0 0.7 + // Negative quaternion is representing same orientation + glm::quat Y90rot2 = glm::slerp(id, Y90rot, 1.0f, 1); + Error += glm::all(glm::equal(Y90rot, -Y90rot2, Epsilon)) ? 0 : 1; + + // Testing a == 1, k == 2 + // Must be id + glm::quat Y90rot3 = glm::slerp(id, Y90rot, 8.0f / 9.0f, 2); + Error += glm::all(glm::equal(id, Y90rot3, Epsilon)) ? 0 : 1; + + // Testing a == 1, k == 1 + // Must be 90° rotation on Y : 0 0.7 0 0.7 + glm::quat Y90rot4 = glm::slerp(id, Y90rot, 0.2f, 1); + Error += glm::all(glm::equal(Y90rot, Y90rot4, Epsilon)) ? 0 : 1; + + // Testing reverse case + // Must be 45° rotation on Y : 0 0.38 0 0.92 + // Negative quaternion is representing same orientation + glm::quat Ym45rot2 = glm::slerp(Y90rot, id, 0.9f, 1); + glm::quat Ym45rot3 = glm::slerp(Y90rot, id, 0.5f); + Error += glm::all(glm::equal(-Ym45rot2, Ym45rot3, Epsilon)) ? 0 : 1; + + // Testing against full circle around the sphere instead of shortest path + // Must be 45° rotation on Y + // certainly not a 135° rotation + glm::quat Y45rot3 = glm::slerp(id, -Y90rot, 0.5f, 0); + float Y45angle3 = glm::angle(Y45rot3); + Error += glm::equal(Y45angle3, glm::pi() * 0.25f, Epsilon) ? 0 : 1; + Error += glm::all(glm::equal(Ym45rot3, Y45rot3, Epsilon)) ? 0 : 1; + + // Same, but inverted + // Must also be 45° rotation on Y : 0 0.38 0 0.92 + // -0 -0.38 -0 -0.92 is ok too + glm::quat Y45rot4 = glm::slerp(-Y90rot, id, 0.5f, 0); + Error += glm::all(glm::equal(Ym45rot2, Y45rot4, Epsilon)) ? 0 : 1; + + // Testing q1 = q2 k == 2 + // Must be 90° rotation on Y : 0 0.7 0 0.7 + glm::quat Y90rot5 = glm::slerp(Y90rot, Y90rot, 0.5f, 2); + Error += glm::all(glm::equal(Y90rot, Y90rot5, Epsilon)) ? 0 : 1; + + // Testing 180° rotation + // Must be 90° rotation on almost any axis that is on the XZ plane + glm::quat XZ90rot = glm::slerp(id, -Y90rot, 0.5f, 1); + float XZ90angle = glm::angle(XZ90rot); // Must be PI/4 = 0.78; + Error += glm::equal(XZ90angle, glm::pi() * 1.25f, Epsilon) ? 0 : 1; + + // Testing rotation over long arc + // Distance from id to 90° is 270°, so 2/3 of it should be 180° + // Negative quaternion is representing same orientation + glm::quat Neg90rot = glm::slerp(id, Y90rot, 2.0f / 3.0f, -1); + Error += glm::all(glm::equal(Y180rot, -Neg90rot, Epsilon)) ? 0 : 1; + + return Error; +} + +static int test_quat_mul_vec() +{ + int Error(0); + + glm::quat q = glm::angleAxis(glm::pi() * 0.5f, glm::vec3(0, 0, 1)); + glm::vec3 v(1, 0, 0); + glm::vec3 u(q * v); + glm::vec3 w(u * q); + + Error += glm::all(glm::equal(v, w, 0.01f)) ? 0 : 1; + + return Error; +} + +static int test_mul() +{ + int Error = 0; + + glm::quat temp1 = glm::normalize(glm::quat(1.0f, glm::vec3(0.0, 1.0, 0.0))); + glm::quat temp2 = glm::normalize(glm::quat(0.5f, glm::vec3(1.0, 0.0, 0.0))); + + glm::vec3 transformed0 = (temp1 * glm::vec3(0.0, 1.0, 0.0) * glm::inverse(temp1)); + glm::vec3 temp4 = temp2 * transformed0 * glm::inverse(temp2); + + glm::quat temp5 = glm::normalize(temp1 * temp2); + glm::vec3 temp6 = temp5 * glm::vec3(0.0, 1.0, 0.0) * glm::inverse(temp5); + + glm::quat temp7(1.0f, glm::vec3(0.0, 1.0, 0.0)); + + temp7 *= temp5; + temp7 *= glm::inverse(temp5); + + Error += glm::any(glm::notEqual(temp7, glm::quat(1.0f, glm::vec3(0.0, 1.0, 0.0)), glm::epsilon())) ? 1 : 0; + + return Error; +} + +int test_identity() +{ + int Error = 0; + + glm::quat const Q = glm::identity(); + + Error += glm::all(glm::equal(Q, glm::quat(1, 0, 0, 0), 0.0001f)) ? 0 : 1; + Error += glm::any(glm::notEqual(Q, glm::quat(1, 0, 0, 0), 0.0001f)) ? 1 : 0; + + glm::mat4 const M = glm::identity(); + glm::mat4 const N(1.0f); + + Error += glm::all(glm::equal(M, N, 0.0001f)) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_mul(); + Error += test_quat_mul_vec(); + Error += test_quat_angle(); + Error += test_quat_angleAxis(); + Error += test_quat_mix(); + Error += test_quat_normalize(); + Error += test_quat_euler(); + Error += test_quat_slerp(); + Error += test_quat_slerp_spins(); + Error += test_identity(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_random.cpp b/vendor/glm/test/gtc/gtc_random.cpp new file mode 100644 index 0000000..60fb60c --- /dev/null +++ b/vendor/glm/test/gtc/gtc_random.cpp @@ -0,0 +1,381 @@ +#define GLM_FORCE_DEFAULT_ALIGNED_GENTYPES +#include +#include +#include +#if GLM_LANG & GLM_LANG_CXX0X_FLAG +# include +#endif + +std::size_t const TestSamples = 10000; + +int test_linearRand() +{ + int Error = 0; + + glm::int32 const Min = 16; + glm::int32 const Max = 32; + + { + glm::u8vec2 AMin(std::numeric_limits::max()); + glm::u8vec2 AMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::u8vec2 A = glm::linearRand(glm::u8vec2(Min), glm::u8vec2(Max)); + AMin = glm::min(AMin, A); + AMax = glm::max(AMax, A); + + if(!glm::all(glm::lessThanEqual(A, glm::u8vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(A, glm::u8vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(AMin, glm::u8vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(AMax, glm::u8vec2(Max))) ? 0 : 1; + assert(!Error); + } + + glm::u16vec2 BMin(std::numeric_limits::max()); + glm::u16vec2 BMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::u16vec2 B = glm::linearRand(glm::u16vec2(Min), glm::u16vec2(Max)); + BMin = glm::min(BMin, B); + BMax = glm::max(BMax, B); + + if(!glm::all(glm::lessThanEqual(B, glm::u16vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(B, glm::u16vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(BMin, glm::u16vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(BMax, glm::u16vec2(Max))) ? 0 : 1; + assert(!Error); + } + + glm::u32vec2 CMin(std::numeric_limits::max()); + glm::u32vec2 CMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::u32vec2 C = glm::linearRand(glm::u32vec2(Min), glm::u32vec2(Max)); + CMin = glm::min(CMin, C); + CMax = glm::max(CMax, C); + + if(!glm::all(glm::lessThanEqual(C, glm::u32vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(C, glm::u32vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(CMin, glm::u32vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(CMax, glm::u32vec2(Max))) ? 0 : 1; + assert(!Error); + } + + glm::u64vec2 DMin(std::numeric_limits::max()); + glm::u64vec2 DMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::u64vec2 D = glm::linearRand(glm::u64vec2(Min), glm::u64vec2(Max)); + DMin = glm::min(DMin, D); + DMax = glm::max(DMax, D); + + if(!glm::all(glm::lessThanEqual(D, glm::u64vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(D, glm::u64vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(DMin, glm::u64vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(DMax, glm::u64vec2(Max))) ? 0 : 1; + assert(!Error); + } + } + + { + glm::i8vec2 AMin(std::numeric_limits::max()); + glm::i8vec2 AMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::i8vec2 A = glm::linearRand(glm::i8vec2(Min), glm::i8vec2(Max)); + AMin = glm::min(AMin, A); + AMax = glm::max(AMax, A); + + if(!glm::all(glm::lessThanEqual(A, glm::i8vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(A, glm::i8vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(AMin, glm::i8vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(AMax, glm::i8vec2(Max))) ? 0 : 1; + assert(!Error); + } + + glm::i16vec2 BMin(std::numeric_limits::max()); + glm::i16vec2 BMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::i16vec2 B = glm::linearRand(glm::i16vec2(Min), glm::i16vec2(Max)); + BMin = glm::min(BMin, B); + BMax = glm::max(BMax, B); + + if(!glm::all(glm::lessThanEqual(B, glm::i16vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(B, glm::i16vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(BMin, glm::i16vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(BMax, glm::i16vec2(Max))) ? 0 : 1; + assert(!Error); + } + + glm::i32vec2 CMin(std::numeric_limits::max()); + glm::i32vec2 CMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::i32vec2 C = glm::linearRand(glm::i32vec2(Min), glm::i32vec2(Max)); + CMin = glm::min(CMin, C); + CMax = glm::max(CMax, C); + + if(!glm::all(glm::lessThanEqual(C, glm::i32vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(C, glm::i32vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(CMin, glm::i32vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(CMax, glm::i32vec2(Max))) ? 0 : 1; + assert(!Error); + } + + glm::i64vec2 DMin(std::numeric_limits::max()); + glm::i64vec2 DMax(std::numeric_limits::min()); + { + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::i64vec2 D = glm::linearRand(glm::i64vec2(Min), glm::i64vec2(Max)); + DMin = glm::min(DMin, D); + DMax = glm::max(DMax, D); + + if(!glm::all(glm::lessThanEqual(D, glm::i64vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(D, glm::i64vec2(Min)))) + ++Error; + assert(!Error); + } + + Error += glm::all(glm::equal(DMin, glm::i64vec2(Min))) ? 0 : 1; + Error += glm::all(glm::equal(DMax, glm::i64vec2(Max))) ? 0 : 1; + assert(!Error); + } + } + + for(std::size_t i = 0; i < TestSamples; ++i) + { + glm::f32vec2 const A(glm::linearRand(glm::f32vec2(static_cast(Min)), glm::f32vec2(static_cast(Max)))); + if(!glm::all(glm::lessThanEqual(A, glm::f32vec2(static_cast(Max))))) + ++Error; + if(!glm::all(glm::greaterThanEqual(A, glm::f32vec2(static_cast(Min))))) + ++Error; + + glm::f64vec2 const B(glm::linearRand(glm::f64vec2(Min), glm::f64vec2(Max))); + if(!glm::all(glm::lessThanEqual(B, glm::f64vec2(Max)))) + ++Error; + if(!glm::all(glm::greaterThanEqual(B, glm::f64vec2(Min)))) + ++Error; + assert(!Error); + } + + { + float ResultFloat = 0.0f; + double ResultDouble = 0.0; + for(std::size_t i = 0; i < TestSamples; ++i) + { + ResultFloat += glm::linearRand(-1.0f, 1.0f); + ResultDouble += glm::linearRand(-1.0, 1.0); + } + + Error += glm::epsilonEqual(ResultFloat, 0.0f, 0.0001f); + Error += glm::epsilonEqual(ResultDouble, 0.0, 0.0001); + assert(!Error); + } + + return Error; +} + +int test_circularRand() +{ + int Error = 0; + + { + std::size_t Max = TestSamples; + float ResultFloat = 0.0f; + double ResultDouble = 0.0; + double Radius = 2.0; + + for(std::size_t i = 0; i < Max; ++i) + { + ResultFloat += glm::length(glm::circularRand(1.0f)); + ResultDouble += glm::length(glm::circularRand(Radius)); + } + + Error += glm::epsilonEqual(ResultFloat, float(Max), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(ResultDouble, double(Max) * double(Radius), 0.01) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_sphericalRand() +{ + int Error = 0; + + { + std::size_t Max = TestSamples; + float ResultFloatA = 0.0f; + float ResultFloatB = 0.0f; + float ResultFloatC = 0.0f; + double ResultDoubleA = 0.0; + double ResultDoubleB = 0.0; + double ResultDoubleC = 0.0; + + for(std::size_t i = 0; i < Max; ++i) + { + ResultFloatA += glm::length(glm::sphericalRand(1.0f)); + ResultDoubleA += glm::length(glm::sphericalRand(1.0)); + ResultFloatB += glm::length(glm::sphericalRand(2.0f)); + ResultDoubleB += glm::length(glm::sphericalRand(2.0)); + ResultFloatC += glm::length(glm::sphericalRand(3.0f)); + ResultDoubleC += glm::length(glm::sphericalRand(3.0)); + } + + Error += glm::epsilonEqual(ResultFloatA, float(Max), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(ResultDoubleA, double(Max), 0.0001) ? 0 : 1; + Error += glm::epsilonEqual(ResultFloatB, float(Max * 2), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(ResultDoubleB, double(Max * 2), 0.0001) ? 0 : 1; + Error += glm::epsilonEqual(ResultFloatC, float(Max * 3), 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(ResultDoubleC, double(Max * 3), 0.01) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_diskRand() +{ + int Error = 0; + + { + float ResultFloat = 0.0f; + double ResultDouble = 0.0; + + for(std::size_t i = 0; i < TestSamples; ++i) + { + ResultFloat += glm::length(glm::diskRand(2.0f)); + ResultDouble += glm::length(glm::diskRand(2.0)); + } + + Error += ResultFloat < float(TestSamples) * 2.f ? 0 : 1; + Error += ResultDouble < double(TestSamples) * 2.0 ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_ballRand() +{ + int Error = 0; + + { + float ResultFloat = 0.0f; + double ResultDouble = 0.0; + + for(std::size_t i = 0; i < TestSamples; ++i) + { + ResultFloat += glm::length(glm::ballRand(2.0f)); + ResultDouble += glm::length(glm::ballRand(2.0)); + } + + Error += ResultFloat < float(TestSamples) * 2.f ? 0 : 1; + Error += ResultDouble < double(TestSamples) * 2.0 ? 0 : 1; + assert(!Error); + } + + return Error; +} +/* +#if(GLM_LANG & GLM_LANG_CXX0X_FLAG) +int test_grid() +{ + int Error = 0; + + typedef std::array colors; + typedef std::array grid; + + grid Grid; + colors Colors; + + grid GridBest; + colors ColorsBest; + + while(true) + { + for(std::size_t i = 0; i < Grid.size(); ++i) + Grid[i] = int(glm::linearRand(0.0, 8.0 * 8.0 * 8.0 - 1.0) / 64.0); + + for(std::size_t i = 0; i < Grid.size(); ++i) + ++Colors[Grid[i]]; + + bool Exit = true; + for(std::size_t i = 0; i < Colors.size(); ++i) + { + if(Colors[i] == 8) + continue; + + Exit = false; + break; + } + + if(Exit == true) + break; + } + + return Error; +} +#endif +*/ +int main() +{ + int Error = 0; + + Error += test_linearRand(); + Error += test_circularRand(); + Error += test_sphericalRand(); + Error += test_diskRand(); + Error += test_ballRand(); +/* +#if(GLM_LANG & GLM_LANG_CXX0X_FLAG) + Error += test_grid(); +#endif +*/ + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_reciprocal.cpp b/vendor/glm/test/gtc/gtc_reciprocal.cpp new file mode 100644 index 0000000..5158413 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_reciprocal.cpp @@ -0,0 +1,8 @@ +#include +#include + +int main() +{ + return 0; +} + diff --git a/vendor/glm/test/gtc/gtc_round.cpp b/vendor/glm/test/gtc/gtc_round.cpp new file mode 100644 index 0000000..60d9a85 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_round.cpp @@ -0,0 +1,458 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace isPowerOfTwo +{ + template + struct type + { + genType Value; + bool Return; + }; + + int test_int16() + { + type const Data[] = + { + {0x0001, true}, + {0x0002, true}, + {0x0004, true}, + {0x0080, true}, + {0x0000, true}, + {0x0003, false} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint16() + { + type const Data[] = + { + {0x0001, true}, + {0x0002, true}, + {0x0004, true}, + {0x0000, true}, + {0x0000, true}, + {0x0003, false} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_int32() + { + type const Data[] = + { + {0x00000001, true}, + {0x00000002, true}, + {0x00000004, true}, + {0x0000000f, false}, + {0x00000000, true}, + {0x00000003, false} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::bvec1 Result = glm::isPowerOfTwo(glm::ivec1(Data[i].Value)); + Error += glm::all(glm::equal(glm::bvec1(Data[i].Return), Result)) ? 0 : 1; + } + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::bvec2 Result = glm::isPowerOfTwo(glm::ivec2(Data[i].Value)); + Error += glm::all(glm::equal(glm::bvec2(Data[i].Return), Result)) ? 0 : 1; + } + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::bvec3 Result = glm::isPowerOfTwo(glm::ivec3(Data[i].Value)); + Error += glm::all(glm::equal(glm::bvec3(Data[i].Return), Result)) ? 0 : 1; + } + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::bvec4 Result = glm::isPowerOfTwo(glm::ivec4(Data[i].Value)); + Error += glm::all(glm::equal(glm::bvec4(Data[i].Return), Result)) ? 0 : 1; + } + + return Error; + } + + int test_uint32() + { + type const Data[] = + { + {0x00000001, true}, + {0x00000002, true}, + {0x00000004, true}, + {0x80000000, true}, + {0x00000000, true}, + {0x00000003, false} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + bool Result = glm::isPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error(0); + + Error += test_int16(); + Error += test_uint16(); + Error += test_int32(); + Error += test_uint32(); + + return Error; + } +}//isPowerOfTwo + +namespace ceilPowerOfTwo_advanced +{ + template + GLM_FUNC_QUALIFIER genIUType highestBitValue(genIUType Value) + { + genIUType tmp = Value; + genIUType result = genIUType(0); + while(tmp) + { + result = (tmp & (~tmp + 1)); // grab lowest bit + tmp &= ~result; // clear lowest bit + } + return result; + } + + template + GLM_FUNC_QUALIFIER genType ceilPowerOfTwo_loop(genType value) + { + return glm::isPowerOfTwo(value) ? value : highestBitValue(value) << 1; + } + + template + struct type + { + genType Value; + genType Return; + }; + + int test_int32() + { + type const Data[] = + { + {0x0000ffff, 0x00010000}, + {-3, -4}, + {-8, -8}, + {0x00000001, 0x00000001}, + {0x00000002, 0x00000002}, + {0x00000004, 0x00000004}, + {0x00000007, 0x00000008}, + {0x0000fff0, 0x00010000}, + {0x0000f000, 0x00010000}, + {0x08000000, 0x08000000}, + {0x00000000, 0x00000000}, + {0x00000003, 0x00000004} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::int32 Result = glm::ceilPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test_uint32() + { + type const Data[] = + { + {0x00000001, 0x00000001}, + {0x00000002, 0x00000002}, + {0x00000004, 0x00000004}, + {0x00000007, 0x00000008}, + {0x0000ffff, 0x00010000}, + {0x0000fff0, 0x00010000}, + {0x0000f000, 0x00010000}, + {0x80000000, 0x80000000}, + {0x00000000, 0x00000000}, + {0x00000003, 0x00000004} + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::uint32 Result = glm::ceilPowerOfTwo(Data[i].Value); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int perf() + { + int Error(0); + + std::vector v; + v.resize(100000000); + + std::clock_t Timestramp0 = std::clock(); + + for(glm::uint32 i = 0, n = static_cast(v.size()); i < n; ++i) + v[i] = ceilPowerOfTwo_loop(i); + + std::clock_t Timestramp1 = std::clock(); + + for(glm::uint32 i = 0, n = static_cast(v.size()); i < n; ++i) + v[i] = glm::ceilPowerOfTwo(i); + + std::clock_t Timestramp2 = std::clock(); + + std::printf("ceilPowerOfTwo_loop: %d clocks\n", static_cast(Timestramp1 - Timestramp0)); + std::printf("glm::ceilPowerOfTwo: %d clocks\n", static_cast(Timestramp2 - Timestramp1)); + + return Error; + } + + int test() + { + int Error(0); + + Error += test_int32(); + Error += test_uint32(); + + return Error; + } +}//namespace ceilPowerOfTwo_advanced + +namespace roundPowerOfTwo +{ + int test() + { + int Error = 0; + + glm::uint32 const A = glm::roundPowerOfTwo(7u); + Error += A == 8u ? 0 : 1; + + glm::uint32 const B = glm::roundPowerOfTwo(15u); + Error += B == 16u ? 0 : 1; + + glm::uint32 const C = glm::roundPowerOfTwo(31u); + Error += C == 32u ? 0 : 1; + + glm::uint32 const D = glm::roundPowerOfTwo(9u); + Error += D == 8u ? 0 : 1; + + glm::uint32 const E = glm::roundPowerOfTwo(17u); + Error += E == 16u ? 0 : 1; + + glm::uint32 const F = glm::roundPowerOfTwo(33u); + Error += F == 32u ? 0 : 1; + + return Error; + } +}//namespace roundPowerOfTwo + +namespace floorPowerOfTwo +{ + int test() + { + int Error = 0; + + glm::uint32 const A = glm::floorPowerOfTwo(7u); + Error += A == 4u ? 0 : 1; + + glm::uint32 const B = glm::floorPowerOfTwo(15u); + Error += B == 8u ? 0 : 1; + + glm::uint32 const C = glm::floorPowerOfTwo(31u); + Error += C == 16u ? 0 : 1; + + return Error; + } +}//namespace floorPowerOfTwo + +namespace ceilPowerOfTwo +{ + int test() + { + int Error = 0; + + glm::uint32 const A = glm::ceilPowerOfTwo(7u); + Error += A == 8u ? 0 : 1; + + glm::uint32 const B = glm::ceilPowerOfTwo(15u); + Error += B == 16u ? 0 : 1; + + glm::uint32 const C = glm::ceilPowerOfTwo(31u); + Error += C == 32u ? 0 : 1; + + return Error; + } +}//namespace ceilPowerOfTwo + +namespace floorMultiple +{ + template + struct type + { + genType Source; + genType Multiple; + genType Return; + genType Epsilon; + }; + + int test_float() + { + type const Data[] = + { + {3.4, 0.3, 3.3, 0.0001}, + {-1.4, 0.3, -1.5, 0.0001}, + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::float64 Result = glm::floorMultiple(Data[i].Source, Data[i].Multiple); + Error += glm::epsilonEqual(Data[i].Return, Result, Data[i].Epsilon) ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error(0); + + Error += test_float(); + + return Error; + } +}//namespace floorMultiple + +namespace ceilMultiple +{ + template + struct type + { + genType Source; + genType Multiple; + genType Return; + genType Epsilon; + }; + + int test_float() + { + type const Data[] = + { + {3.4, 0.3, 3.6, 0.0001}, + {-1.4, 0.3, -1.2, 0.0001}, + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + glm::float64 Result = glm::ceilMultiple(Data[i].Source, Data[i].Multiple); + Error += glm::epsilonEqual(Data[i].Return, Result, Data[i].Epsilon) ? 0 : 1; + } + + return Error; + } + + int test_int() + { + type const Data[] = + { + {3, 4, 4, 0}, + {7, 4, 8, 0}, + {5, 4, 8, 0}, + {1, 4, 4, 0}, + {1, 3, 3, 0}, + {4, 3, 6, 0}, + {4, 1, 4, 0}, + {1, 1, 1, 0}, + {7, 1, 7, 0}, + }; + + int Error(0); + + for(std::size_t i = 0, n = sizeof(Data) / sizeof(type); i < n; ++i) + { + int Result = glm::ceilMultiple(Data[i].Source, Data[i].Multiple); + Error += Data[i].Return == Result ? 0 : 1; + } + + return Error; + } + + int test() + { + int Error(0); + + Error += test_int(); + Error += test_float(); + + return Error; + } +}//namespace ceilMultiple + +int main() +{ + int Error(0); + + Error += isPowerOfTwo::test(); + Error += floorPowerOfTwo::test(); + Error += roundPowerOfTwo::test(); + Error += ceilPowerOfTwo::test(); + Error += ceilPowerOfTwo_advanced::test(); + +# ifdef NDEBUG + Error += ceilPowerOfTwo_advanced::perf(); +# endif//NDEBUG + + Error += floorMultiple::test(); + Error += ceilMultiple::test(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_type_aligned.cpp b/vendor/glm/test/gtc/gtc_type_aligned.cpp new file mode 100644 index 0000000..3c071ef --- /dev/null +++ b/vendor/glm/test/gtc/gtc_type_aligned.cpp @@ -0,0 +1,181 @@ +#include + +#if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE +#include +#include +#include +#include + +GLM_STATIC_ASSERT(glm::detail::is_aligned::value, "aligned_lowp is not aligned"); +GLM_STATIC_ASSERT(glm::detail::is_aligned::value, "aligned_mediump is not aligned"); +GLM_STATIC_ASSERT(glm::detail::is_aligned::value, "aligned_highp is not aligned"); +GLM_STATIC_ASSERT(!glm::detail::is_aligned::value, "packed_highp is aligned"); +GLM_STATIC_ASSERT(!glm::detail::is_aligned::value, "packed_mediump is aligned"); +GLM_STATIC_ASSERT(!glm::detail::is_aligned::value, "packed_lowp is aligned"); + +struct my_vec4_packed +{ + glm::uint32 a; + glm::vec4 b; +}; +GLM_STATIC_ASSERT(sizeof(my_vec4_packed) == sizeof(glm::uint32) + sizeof(glm::vec4), "glm::vec4 packed is not correct"); + +struct my_vec4_aligned +{ + glm::uint32 a; + glm::aligned_vec4 b; +}; +GLM_STATIC_ASSERT(sizeof(my_vec4_aligned) == sizeof(glm::aligned_vec4) * 2, "glm::vec4 aligned is not correct"); + +struct my_dvec4_packed +{ + glm::uint64 a; + glm::dvec4 b; +}; +GLM_STATIC_ASSERT(sizeof(my_dvec4_packed) == sizeof(glm::uint64) + sizeof(glm::dvec4), "glm::dvec4 packed is not correct"); + +struct my_dvec4_aligned +{ + glm::uint64 a; + glm::aligned_dvec4 b; +}; +//GLM_STATIC_ASSERT(sizeof(my_dvec4_aligned) == sizeof(glm::aligned_dvec4) * 2, "glm::dvec4 aligned is not correct"); + +struct my_ivec4_packed +{ + glm::uint32 a; + glm::ivec4 b; +}; +GLM_STATIC_ASSERT(sizeof(my_ivec4_packed) == sizeof(glm::uint32) + sizeof(glm::ivec4), "glm::ivec4 packed is not correct"); + +struct my_ivec4_aligned +{ + glm::uint32 a; + glm::aligned_ivec4 b; +}; +GLM_STATIC_ASSERT(sizeof(my_ivec4_aligned) == sizeof(glm::aligned_ivec4) * 2, "glm::ivec4 aligned is not correct"); + +struct my_u8vec4_packed +{ + glm::uint32 a; + glm::u8vec4 b; +}; +GLM_STATIC_ASSERT(sizeof(my_u8vec4_packed) == sizeof(glm::uint32) + sizeof(glm::u8vec4), "glm::u8vec4 packed is not correct"); + +static int test_copy() +{ + int Error = 0; + + { + glm::aligned_ivec4 const a(1, 2, 3, 4); + glm::ivec4 const u(a); + + Error += a.x == u.x ? 0 : 1; + Error += a.y == u.y ? 0 : 1; + Error += a.z == u.z ? 0 : 1; + Error += a.w == u.w ? 0 : 1; + } + + { + my_ivec4_aligned a; + a.b = glm::ivec4(1, 2, 3, 4); + + my_ivec4_packed u; + u.b = a.b; + + Error += a.b.x == u.b.x ? 0 : 1; + Error += a.b.y == u.b.y ? 0 : 1; + Error += a.b.z == u.b.z ? 0 : 1; + Error += a.b.w == u.b.w ? 0 : 1; + } + + return Error; +} + +static int test_ctor() +{ + int Error = 0; + +# if GLM_HAS_CONSTEXPR + { + constexpr glm::aligned_ivec4 v(1); + + Error += v.x == 1 ? 0 : 1; + Error += v.y == 1 ? 0 : 1; + Error += v.z == 1 ? 0 : 1; + Error += v.w == 1 ? 0 : 1; + } + + { + constexpr glm::packed_ivec4 v(1); + + Error += v.x == 1 ? 0 : 1; + Error += v.y == 1 ? 0 : 1; + Error += v.z == 1 ? 0 : 1; + Error += v.w == 1 ? 0 : 1; + } + + { + constexpr glm::ivec4 v(1); + + Error += v.x == 1 ? 0 : 1; + Error += v.y == 1 ? 0 : 1; + Error += v.z == 1 ? 0 : 1; + Error += v.w == 1 ? 0 : 1; + } +# endif//GLM_HAS_CONSTEXPR + + return Error; +} + +static int test_aligned_ivec4() +{ + int Error = 0; + + glm::aligned_ivec4 const v(1, 2, 3, 4); + Error += glm::all(glm::equal(v, glm::aligned_ivec4(1, 2, 3, 4))) ? 0 : 1; + + glm::aligned_ivec4 const u = v * 2; + Error += glm::all(glm::equal(u, glm::aligned_ivec4(2, 4, 6, 8))) ? 0 : 1; + + return Error; +} + +static int test_aligned_mat4() +{ + int Error = 0; + + glm::aligned_vec4 const u(1.f, 2.f, 3.f, 4.f); + Error += glm::all(glm::equal(u, glm::aligned_vec4(1.f, 2.f, 3.f, 4.f), 0.0001f)) ? 0 : 1; + + glm::aligned_vec4 const v(1, 2, 3, 4); + Error += glm::all(glm::equal(v, glm::aligned_vec4(1.f, 2.f, 3.f, 4.f), 0.0001f)) ? 0 : 1; + + glm::aligned_mat4 const m(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + glm::aligned_mat4 const t = glm::transpose(m); + glm::aligned_mat4 const expected = glm::mat4(0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15); + Error += glm::all(glm::equal(t, expected, 0.0001f)) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_ctor(); + Error += test_copy(); + Error += test_aligned_ivec4(); + Error += test_aligned_mat4(); + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/gtc/gtc_type_precision.cpp b/vendor/glm/test/gtc/gtc_type_precision.cpp new file mode 100644 index 0000000..77f0686 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_type_precision.cpp @@ -0,0 +1,1041 @@ +#include +#include +#include +#include +#include +#if GLM_HAS_OPENMP +# include +#endif + +#if GLM_HAS_STATIC_ASSERT +static_assert(sizeof(glm::lowp_u8vec1) == 1, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec1) == 1, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec1) == 1, "uint8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec1) == 2, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec1) == 2, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec1) == 2, "uint16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec1) == 4, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec1) == 4, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec1) == 4, "uint32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec1) == 8, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec1) == 8, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec1) == 8, "uint64 size isn't 8 bytes on this platform"); + + +static_assert(sizeof(glm::lowp_u8vec2) == 2, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec2) == 2, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec2) == 2, "uint8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec2) == 4, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec2) == 4, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec2) == 4, "uint16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec2) == 8, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec2) == 8, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec2) == 8, "uint32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec2) == 16, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec2) == 16, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec2) == 16, "uint64 size isn't 8 bytes on this platform"); + + +static_assert(sizeof(glm::lowp_u8vec3) == 3, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec3) == 3, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec3) == 3, "uint8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec3) == 6, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec3) == 6, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec3) == 6, "uint16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec3) == 12, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec3) == 12, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec3) == 12, "uint32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec3) == 24, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec3) == 24, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec3) == 24, "uint64 size isn't 8 bytes on this platform"); + + +static_assert(sizeof(glm::lowp_u8vec4) == 4, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec4) == 4, "int8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec4) == 4, "int8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec4) == 8, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec4) == 8, "int16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec4) == 8, "int16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec4) == 16, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec4) == 16, "int32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec4) == 16, "int32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec4) == 32, "int64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec4) == 32, "int64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec4) == 32, "int64 size isn't 8 bytes on this platform"); + + +static_assert(sizeof(glm::lowp_u8vec1) == 1, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec1) == 1, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec1) == 1, "uint8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec1) == 2, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec1) == 2, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec1) == 2, "uint16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec1) == 4, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec1) == 4, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec1) == 4, "uint32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec1) == 8, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec1) == 8, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec1) == 8, "uint64 size isn't 8 bytes on this platform"); + + +static_assert(sizeof(glm::lowp_u8vec2) == 2, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec2) == 2, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec2) == 2, "uint8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec2) == 4, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec2) == 4, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec2) == 4, "uint16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec2) == 8, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec2) == 8, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec2) == 8, "uint32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec2) == 16, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec2) == 16, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec2) == 16, "uint64 size isn't 8 bytes on this platform"); + + +static_assert(sizeof(glm::lowp_u8vec3) == 3, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec3) == 3, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec3) == 3, "uint8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec3) == 6, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec3) == 6, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec3) == 6, "uint16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec3) == 12, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec3) == 12, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec3) == 12, "uint32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec3) == 24, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec3) == 24, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec3) == 24, "uint64 size isn't 8 bytes on this platform"); + + +static_assert(sizeof(glm::lowp_u8vec4) == 4, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::mediump_u8vec4) == 4, "uint8 size isn't 1 byte on this platform"); +static_assert(sizeof(glm::highp_u8vec4) == 4, "uint8 size isn't 1 byte on this platform"); + +static_assert(sizeof(glm::lowp_u16vec4) == 8, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::mediump_u16vec4) == 8, "uint16 size isn't 2 bytes on this platform"); +static_assert(sizeof(glm::highp_u16vec4) == 8, "uint16 size isn't 2 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u32vec4) == 16, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::mediump_u32vec4) == 16, "uint32 size isn't 4 bytes on this platform"); +static_assert(sizeof(glm::highp_u32vec4) == 16, "uint32 size isn't 4 bytes on this platform"); + +static_assert(sizeof(glm::lowp_u64vec4) == 32, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::mediump_u64vec4) == 32, "uint64 size isn't 8 bytes on this platform"); +static_assert(sizeof(glm::highp_u64vec4) == 32, "uint64 size isn't 8 bytes on this platform"); + +#endif + +static int test_scalar_size() +{ + int Error = 0; + + Error += sizeof(glm::int8) != 1; + Error += sizeof(glm::int16) != 2; + Error += sizeof(glm::int32) != 4; + Error += sizeof(glm::int64) != 8; + Error += sizeof(glm::uint8) != 1; + Error += sizeof(glm::uint16) != 2; + Error += sizeof(glm::uint32) != 4; + Error += sizeof(glm::uint64) != 8; + Error += sizeof(glm::float32) != 4; + Error += sizeof(glm::float64) != 8; + + Error += sizeof(glm::lowp_int8) != 1; + Error += sizeof(glm::lowp_int16) != 2; + Error += sizeof(glm::lowp_int32) != 4; + Error += sizeof(glm::lowp_int64) != 8; + Error += sizeof(glm::lowp_uint8) != 1; + Error += sizeof(glm::lowp_uint16) != 2; + Error += sizeof(glm::lowp_uint32) != 4; + Error += sizeof(glm::lowp_uint64) != 8; + Error += sizeof(glm::lowp_float32) != 4; + Error += sizeof(glm::lowp_float64) != 8; + + Error += sizeof(glm::mediump_int8) != 1; + Error += sizeof(glm::mediump_int16) != 2; + Error += sizeof(glm::mediump_int32) != 4; + Error += sizeof(glm::mediump_int64) != 8; + Error += sizeof(glm::mediump_uint8) != 1; + Error += sizeof(glm::mediump_uint16) != 2; + Error += sizeof(glm::mediump_uint32) != 4; + Error += sizeof(glm::mediump_uint64) != 8; + Error += sizeof(glm::mediump_float32) != 4; + Error += sizeof(glm::mediump_float64) != 8; + + Error += sizeof(glm::highp_int8) != 1; + Error += sizeof(glm::highp_int16) != 2; + Error += sizeof(glm::highp_int32) != 4; + Error += sizeof(glm::highp_int64) != 8; + Error += sizeof(glm::highp_uint8) != 1; + Error += sizeof(glm::highp_uint16) != 2; + Error += sizeof(glm::highp_uint32) != 4; + Error += sizeof(glm::highp_uint64) != 8; + Error += sizeof(glm::highp_float32) != 4; + Error += sizeof(glm::highp_float64) != 8; + + return Error; +} + +static int test_fvec_size() +{ + int Error = 0; + + Error += sizeof(glm::f32vec2) != 8; + Error += sizeof(glm::f32vec3) != 12; + Error += sizeof(glm::f32vec4) != 16; + Error += sizeof(glm::f64vec2) != 16; + Error += sizeof(glm::f64vec3) != 24; + Error += sizeof(glm::f64vec4) != 32; + + Error += sizeof(glm::lowp_f32vec2) != 8; + Error += sizeof(glm::lowp_f32vec3) != 12; + Error += sizeof(glm::lowp_f32vec4) != 16; + Error += sizeof(glm::lowp_f64vec2) != 16; + Error += sizeof(glm::lowp_f64vec3) != 24; + Error += sizeof(glm::lowp_f64vec4) != 32; + + Error += sizeof(glm::mediump_f32vec2) != 8; + Error += sizeof(glm::mediump_f32vec3) != 12; + Error += sizeof(glm::mediump_f32vec4) != 16; + Error += sizeof(glm::mediump_f64vec2) != 16; + Error += sizeof(glm::mediump_f64vec3) != 24; + Error += sizeof(glm::mediump_f64vec4) != 32; + + Error += sizeof(glm::highp_f32vec2) != 8; + Error += sizeof(glm::highp_f32vec3) != 12; + Error += sizeof(glm::highp_f32vec4) != 16; + Error += sizeof(glm::highp_f64vec2) != 16; + Error += sizeof(glm::highp_f64vec3) != 24; + Error += sizeof(glm::highp_f64vec4) != 32; + + return Error; +} + +static int test_fvec_precision() +{ + int Error = 0; + + { + glm::f32vec2 v1(1.f); + glm::lowp_f32vec2 v2(v1); + glm::mediump_f32vec2 v3(v1); + glm::highp_f32vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::f32vec2(v2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f32vec2(v3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f32vec2(v4), glm::epsilon())) ? 0 : 1; + } + + { + glm::f32vec3 v1(1.f); + glm::lowp_f32vec3 v2(v1); + glm::mediump_f32vec3 v3(v1); + glm::highp_f32vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::f32vec3(v2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f32vec3(v3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f32vec3(v4), glm::epsilon())) ? 0 : 1; + } + + { + glm::f32vec4 v1(1.f); + glm::lowp_f32vec4 v2(v1); + glm::mediump_f32vec4 v3(v1); + glm::highp_f32vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::f32vec4(v2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f32vec4(v3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f32vec4(v4), glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +static int test_dvec_precision() +{ + int Error = 0; + + { + glm::f64vec2 v1(1.0); + glm::lowp_f64vec2 v2(v1); + glm::mediump_f64vec2 v3(v1); + glm::highp_f64vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::f64vec2(v2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f64vec2(v3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f64vec2(v4), glm::epsilon())) ? 0 : 1; + } + + { + glm::f64vec3 v1(1.0); + glm::lowp_f64vec3 v2(v1); + glm::mediump_f64vec3 v3(v1); + glm::highp_f64vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::f64vec3(v2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f64vec3(v3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f64vec3(v4), glm::epsilon())) ? 0 : 1; + } + + { + glm::f64vec4 v1(1.0); + glm::lowp_f64vec4 v2(v1); + glm::mediump_f64vec4 v3(v1); + glm::highp_f64vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::f64vec4(v2), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f64vec4(v3), glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::f64vec4(v4), glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +static int test_ivec_size() +{ + int Error = 0; + + Error += sizeof(glm::i8vec2) != 2; + Error += sizeof(glm::i8vec3) != 3; + Error += sizeof(glm::i8vec4) != 4; + Error += sizeof(glm::i16vec2) != 4; + Error += sizeof(glm::i16vec3) != 6; + Error += sizeof(glm::i16vec4) != 8; + Error += sizeof(glm::i32vec2) != 8; + Error += sizeof(glm::i32vec3) != 12; + Error += sizeof(glm::i32vec4) != 16; + Error += sizeof(glm::i64vec2) != 16; + Error += sizeof(glm::i64vec3) != 24; + Error += sizeof(glm::i64vec4) != 32; + + Error += sizeof(glm::lowp_i8vec2) != 2; + Error += sizeof(glm::lowp_i8vec3) != 3; + Error += sizeof(glm::lowp_i8vec4) != 4; + Error += sizeof(glm::lowp_i16vec2) != 4; + Error += sizeof(glm::lowp_i16vec3) != 6; + Error += sizeof(glm::lowp_i16vec4) != 8; + Error += sizeof(glm::lowp_i32vec2) != 8; + Error += sizeof(glm::lowp_i32vec3) != 12; + Error += sizeof(glm::lowp_i32vec4) != 16; + Error += sizeof(glm::lowp_i64vec2) != 16; + Error += sizeof(glm::lowp_i64vec3) != 24; + Error += sizeof(glm::lowp_i64vec4) != 32; + + Error += sizeof(glm::mediump_i8vec2) != 2; + Error += sizeof(glm::mediump_i8vec3) != 3; + Error += sizeof(glm::mediump_i8vec4) != 4; + Error += sizeof(glm::mediump_i16vec2) != 4; + Error += sizeof(glm::mediump_i16vec3) != 6; + Error += sizeof(glm::mediump_i16vec4) != 8; + Error += sizeof(glm::mediump_i32vec2) != 8; + Error += sizeof(glm::mediump_i32vec3) != 12; + Error += sizeof(glm::mediump_i32vec4) != 16; + Error += sizeof(glm::mediump_i64vec2) != 16; + Error += sizeof(glm::mediump_i64vec3) != 24; + Error += sizeof(glm::mediump_i64vec4) != 32; + + Error += sizeof(glm::highp_i8vec2) != 2; + Error += sizeof(glm::highp_i8vec3) != 3; + Error += sizeof(glm::highp_i8vec4) != 4; + Error += sizeof(glm::highp_i16vec2) != 4; + Error += sizeof(glm::highp_i16vec3) != 6; + Error += sizeof(glm::highp_i16vec4) != 8; + Error += sizeof(glm::highp_i32vec2) != 8; + Error += sizeof(glm::highp_i32vec3) != 12; + Error += sizeof(glm::highp_i32vec4) != 16; + Error += sizeof(glm::highp_i64vec2) != 16; + Error += sizeof(glm::highp_i64vec3) != 24; + Error += sizeof(glm::highp_i64vec4) != 32; + + return Error; +} + +static int test_ivec_precision() +{ + int Error = 0; + + { + glm::i8vec2 v1(0); + glm::lowp_i8vec2 v2(v1); + glm::mediump_i8vec2 v3(v1); + glm::highp_i8vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i8vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i8vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i8vec2(v4))) ? 0 : 1; + } + + { + glm::i8vec3 v1(0); + glm::lowp_i8vec3 v2(v1); + glm::mediump_i8vec3 v3(v1); + glm::highp_i8vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i8vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i8vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i8vec3(v4))) ? 0 : 1; + } + + { + glm::i8vec4 v1(0); + glm::lowp_i8vec4 v2(v1); + glm::mediump_i8vec4 v3(v1); + glm::highp_i8vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i8vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i8vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i8vec4(v4))) ? 0 : 1; + } + + { + glm::i16vec2 v1(0); + glm::lowp_i16vec2 v2(v1); + glm::mediump_i16vec2 v3(v1); + glm::highp_i16vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i16vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i16vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i16vec2(v4))) ? 0 : 1; + } + + { + glm::i16vec3 v1(0); + glm::lowp_i16vec3 v2(v1); + glm::mediump_i16vec3 v3(v1); + glm::highp_i16vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i16vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i16vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i16vec3(v4))) ? 0 : 1; + } + + { + glm::i16vec4 v1(0); + glm::lowp_i16vec4 v2(v1); + glm::mediump_i16vec4 v3(v1); + glm::highp_i16vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i16vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i16vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i16vec4(v4))) ? 0 : 1; + } + + { + glm::i32vec2 v1(0); + glm::lowp_i32vec2 v2(v1); + glm::mediump_i32vec2 v3(v1); + glm::highp_i32vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i32vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i32vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i32vec2(v4))) ? 0 : 1; + } + + { + glm::i32vec3 v1(0); + glm::lowp_i32vec3 v2(v1); + glm::mediump_i32vec3 v3(v1); + glm::highp_i32vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i32vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i32vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i32vec3(v4))) ? 0 : 1; + } + + { + glm::i32vec4 v1(0); + glm::lowp_i32vec4 v2(v1); + glm::mediump_i32vec4 v3(v1); + glm::highp_i32vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i32vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i32vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i32vec4(v4))) ? 0 : 1; + } + + { + glm::i64vec2 v1(0); + glm::lowp_i64vec2 v2(v1); + glm::mediump_i64vec2 v3(v1); + glm::highp_i64vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i64vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i64vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i64vec2(v4))) ? 0 : 1; + } + + { + glm::i64vec3 v1(0); + glm::lowp_i64vec3 v2(v1); + glm::mediump_i64vec3 v3(v1); + glm::highp_i64vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i64vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i64vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i64vec3(v4))) ? 0 : 1; + } + + { + glm::i64vec4 v1(0); + glm::lowp_i64vec4 v2(v1); + glm::mediump_i64vec4 v3(v1); + glm::highp_i64vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::i64vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i64vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::i64vec4(v4))) ? 0 : 1; + } + + return Error; +} + +static int test_uvec_size() +{ + int Error = 0; + + Error += sizeof(glm::u8vec2) != 2; + Error += sizeof(glm::u8vec3) != 3; + Error += sizeof(glm::u8vec4) != 4; + Error += sizeof(glm::u16vec2) != 4; + Error += sizeof(glm::u16vec3) != 6; + Error += sizeof(glm::u16vec4) != 8; + Error += sizeof(glm::u32vec2) != 8; + Error += sizeof(glm::u32vec3) != 12; + Error += sizeof(glm::u32vec4) != 16; + Error += sizeof(glm::u64vec2) != 16; + Error += sizeof(glm::u64vec3) != 24; + Error += sizeof(glm::u64vec4) != 32; + + Error += sizeof(glm::lowp_u8vec2) != 2; + Error += sizeof(glm::lowp_u8vec3) != 3; + Error += sizeof(glm::lowp_u8vec4) != 4; + Error += sizeof(glm::lowp_u16vec2) != 4; + Error += sizeof(glm::lowp_u16vec3) != 6; + Error += sizeof(glm::lowp_u16vec4) != 8; + Error += sizeof(glm::lowp_u32vec2) != 8; + Error += sizeof(glm::lowp_u32vec3) != 12; + Error += sizeof(glm::lowp_u32vec4) != 16; + Error += sizeof(glm::lowp_u64vec2) != 16; + Error += sizeof(glm::lowp_u64vec3) != 24; + Error += sizeof(glm::lowp_u64vec4) != 32; + + Error += sizeof(glm::mediump_u8vec2) != 2; + Error += sizeof(glm::mediump_u8vec3) != 3; + Error += sizeof(glm::mediump_u8vec4) != 4; + Error += sizeof(glm::mediump_u16vec2) != 4; + Error += sizeof(glm::mediump_u16vec3) != 6; + Error += sizeof(glm::mediump_u16vec4) != 8; + Error += sizeof(glm::mediump_u32vec2) != 8; + Error += sizeof(glm::mediump_u32vec3) != 12; + Error += sizeof(glm::mediump_u32vec4) != 16; + Error += sizeof(glm::mediump_u64vec2) != 16; + Error += sizeof(glm::mediump_u64vec3) != 24; + Error += sizeof(glm::mediump_u64vec4) != 32; + + Error += sizeof(glm::highp_u8vec2) != 2; + Error += sizeof(glm::highp_u8vec3) != 3; + Error += sizeof(glm::highp_u8vec4) != 4; + Error += sizeof(glm::highp_u16vec2) != 4; + Error += sizeof(glm::highp_u16vec3) != 6; + Error += sizeof(glm::highp_u16vec4) != 8; + Error += sizeof(glm::highp_u32vec2) != 8; + Error += sizeof(glm::highp_u32vec3) != 12; + Error += sizeof(glm::highp_u32vec4) != 16; + Error += sizeof(glm::highp_u64vec2) != 16; + Error += sizeof(glm::highp_u64vec3) != 24; + Error += sizeof(glm::highp_u64vec4) != 32; + + return Error; +} + +static int test_uvec_precision() +{ + int Error = 0; + + { + glm::u8vec2 v1(0); + glm::lowp_u8vec2 v2(v1); + glm::mediump_u8vec2 v3(v1); + glm::highp_u8vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u8vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u8vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u8vec2(v4))) ? 0 : 1; + } + + { + glm::u8vec3 v1(0); + glm::lowp_u8vec3 v2(v1); + glm::mediump_u8vec3 v3(v1); + glm::highp_u8vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u8vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u8vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u8vec3(v4))) ? 0 : 1; + } + + { + glm::u8vec4 v1(0); + glm::lowp_u8vec4 v2(v1); + glm::mediump_u8vec4 v3(v1); + glm::highp_u8vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u8vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u8vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u8vec4(v4))) ? 0 : 1; + } + + { + glm::u16vec2 v1(0); + glm::lowp_u16vec2 v2(v1); + glm::mediump_u16vec2 v3(v1); + glm::highp_u16vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u16vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u16vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u16vec2(v4))) ? 0 : 1; + } + + { + glm::u16vec3 v1(0); + glm::lowp_u16vec3 v2(v1); + glm::mediump_u16vec3 v3(v1); + glm::highp_u16vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u16vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u16vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u16vec3(v4))) ? 0 : 1; + } + + { + glm::u16vec4 v1(0); + glm::lowp_u16vec4 v2(v1); + glm::mediump_u16vec4 v3(v1); + glm::highp_u16vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u16vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u16vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u16vec4(v4))) ? 0 : 1; + } + + { + glm::u32vec2 v1(0); + glm::lowp_u32vec2 v2(v1); + glm::mediump_u32vec2 v3(v1); + glm::highp_u32vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u32vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u32vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u32vec2(v4))) ? 0 : 1; + } + + { + glm::u32vec3 v1(0); + glm::lowp_u32vec3 v2(v1); + glm::mediump_u32vec3 v3(v1); + glm::highp_u32vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u32vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u32vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u32vec3(v4))) ? 0 : 1; + } + + { + glm::u32vec4 v1(0); + glm::lowp_u32vec4 v2(v1); + glm::mediump_u32vec4 v3(v1); + glm::highp_u32vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u32vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u32vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u32vec4(v4))) ? 0 : 1; + } + + { + glm::u64vec2 v1(0); + glm::lowp_u64vec2 v2(v1); + glm::mediump_u64vec2 v3(v1); + glm::highp_u64vec2 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u64vec2(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u64vec2(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u64vec2(v4))) ? 0 : 1; + } + + { + glm::u64vec3 v1(0); + glm::lowp_u64vec3 v2(v1); + glm::mediump_u64vec3 v3(v1); + glm::highp_u64vec3 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u64vec3(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u64vec3(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u64vec3(v4))) ? 0 : 1; + } + + { + glm::u64vec4 v1(0); + glm::lowp_u64vec4 v2(v1); + glm::mediump_u64vec4 v3(v1); + glm::highp_u64vec4 v4(v1); + + Error += glm::all(glm::equal(v1, glm::u64vec4(v2))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u64vec4(v3))) ? 0 : 1; + Error += glm::all(glm::equal(v1, glm::u64vec4(v4))) ? 0 : 1; + } + + return Error; +} + +static int test_fmat_size() +{ + int Error = 0; + + Error += sizeof(glm::mat2) != 16; + Error += sizeof(glm::mat3) != 36; + Error += sizeof(glm::mat4) != 64; + Error += sizeof(glm::mat2x2) != 16; + Error += sizeof(glm::mat2x3) != 24; + Error += sizeof(glm::mat2x4) != 32; + Error += sizeof(glm::mat3x2) != 24; + Error += sizeof(glm::mat3x3) != 36; + Error += sizeof(glm::mat3x4) != 48; + Error += sizeof(glm::mat4x2) != 32; + Error += sizeof(glm::mat4x3) != 48; + Error += sizeof(glm::mat4x4) != 64; + + Error += sizeof(glm::fmat2) != 16; + Error += sizeof(glm::fmat3) != 36; + Error += sizeof(glm::fmat4) != 64; + Error += sizeof(glm::fmat2x2) != 16; + Error += sizeof(glm::fmat2x3) != 24; + Error += sizeof(glm::fmat2x4) != 32; + Error += sizeof(glm::fmat3x2) != 24; + Error += sizeof(glm::fmat3x3) != 36; + Error += sizeof(glm::fmat3x4) != 48; + Error += sizeof(glm::fmat4x2) != 32; + Error += sizeof(glm::fmat4x3) != 48; + Error += sizeof(glm::fmat4x4) != 64; + + Error += sizeof(glm::f32mat2) != 16; + Error += sizeof(glm::f32mat3) != 36; + Error += sizeof(glm::f32mat4) != 64; + Error += sizeof(glm::f32mat2x2) != 16; + Error += sizeof(glm::f32mat2x3) != 24; + Error += sizeof(glm::f32mat2x4) != 32; + Error += sizeof(glm::f32mat3x2) != 24; + Error += sizeof(glm::f32mat3x3) != 36; + Error += sizeof(glm::f32mat3x4) != 48; + Error += sizeof(glm::f32mat4x2) != 32; + Error += sizeof(glm::f32mat4x3) != 48; + Error += sizeof(glm::f32mat4x4) != 64; + + + Error += sizeof(glm::lowp_mat2) != 16; + Error += sizeof(glm::lowp_mat3) != 36; + Error += sizeof(glm::lowp_mat4) != 64; + Error += sizeof(glm::lowp_mat2x2) != 16; + Error += sizeof(glm::lowp_mat2x3) != 24; + Error += sizeof(glm::lowp_mat2x4) != 32; + Error += sizeof(glm::lowp_mat3x2) != 24; + Error += sizeof(glm::lowp_mat3x3) != 36; + Error += sizeof(glm::lowp_mat3x4) != 48; + Error += sizeof(glm::lowp_mat4x2) != 32; + Error += sizeof(glm::lowp_mat4x3) != 48; + Error += sizeof(glm::lowp_mat4x4) != 64; + + Error += sizeof(glm::lowp_fmat2) != 16; + Error += sizeof(glm::lowp_fmat3) != 36; + Error += sizeof(glm::lowp_fmat4) != 64; + Error += sizeof(glm::lowp_fmat2x2) != 16; + Error += sizeof(glm::lowp_fmat2x3) != 24; + Error += sizeof(glm::lowp_fmat2x4) != 32; + Error += sizeof(glm::lowp_fmat3x2) != 24; + Error += sizeof(glm::lowp_fmat3x3) != 36; + Error += sizeof(glm::lowp_fmat3x4) != 48; + Error += sizeof(glm::lowp_fmat4x2) != 32; + Error += sizeof(glm::lowp_fmat4x3) != 48; + Error += sizeof(glm::lowp_fmat4x4) != 64; + + Error += sizeof(glm::lowp_f32mat2) != 16; + Error += sizeof(glm::lowp_f32mat3) != 36; + Error += sizeof(glm::lowp_f32mat4) != 64; + Error += sizeof(glm::lowp_f32mat2x2) != 16; + Error += sizeof(glm::lowp_f32mat2x3) != 24; + Error += sizeof(glm::lowp_f32mat2x4) != 32; + Error += sizeof(glm::lowp_f32mat3x2) != 24; + Error += sizeof(glm::lowp_f32mat3x3) != 36; + Error += sizeof(glm::lowp_f32mat3x4) != 48; + Error += sizeof(glm::lowp_f32mat4x2) != 32; + Error += sizeof(glm::lowp_f32mat4x3) != 48; + Error += sizeof(glm::lowp_f32mat4x4) != 64; + + Error += sizeof(glm::mediump_mat2) != 16; + Error += sizeof(glm::mediump_mat3) != 36; + Error += sizeof(glm::mediump_mat4) != 64; + Error += sizeof(glm::mediump_mat2x2) != 16; + Error += sizeof(glm::mediump_mat2x3) != 24; + Error += sizeof(glm::mediump_mat2x4) != 32; + Error += sizeof(glm::mediump_mat3x2) != 24; + Error += sizeof(glm::mediump_mat3x3) != 36; + Error += sizeof(glm::mediump_mat3x4) != 48; + Error += sizeof(glm::mediump_mat4x2) != 32; + Error += sizeof(glm::mediump_mat4x3) != 48; + Error += sizeof(glm::mediump_mat4x4) != 64; + + Error += sizeof(glm::mediump_fmat2) != 16; + Error += sizeof(glm::mediump_fmat3) != 36; + Error += sizeof(glm::mediump_fmat4) != 64; + Error += sizeof(glm::mediump_fmat2x2) != 16; + Error += sizeof(glm::mediump_fmat2x3) != 24; + Error += sizeof(glm::mediump_fmat2x4) != 32; + Error += sizeof(glm::mediump_fmat3x2) != 24; + Error += sizeof(glm::mediump_fmat3x3) != 36; + Error += sizeof(glm::mediump_fmat3x4) != 48; + Error += sizeof(glm::mediump_fmat4x2) != 32; + Error += sizeof(glm::mediump_fmat4x3) != 48; + Error += sizeof(glm::mediump_fmat4x4) != 64; + + Error += sizeof(glm::mediump_f32mat2) != 16; + Error += sizeof(glm::mediump_f32mat3) != 36; + Error += sizeof(glm::mediump_f32mat4) != 64; + Error += sizeof(glm::mediump_f32mat2x2) != 16; + Error += sizeof(glm::mediump_f32mat2x3) != 24; + Error += sizeof(glm::mediump_f32mat2x4) != 32; + Error += sizeof(glm::mediump_f32mat3x2) != 24; + Error += sizeof(glm::mediump_f32mat3x3) != 36; + Error += sizeof(glm::mediump_f32mat3x4) != 48; + Error += sizeof(glm::mediump_f32mat4x2) != 32; + Error += sizeof(glm::mediump_f32mat4x3) != 48; + Error += sizeof(glm::mediump_f32mat4x4) != 64; + + Error += sizeof(glm::highp_mat2) != 16; + Error += sizeof(glm::highp_mat3) != 36; + Error += sizeof(glm::highp_mat4) != 64; + Error += sizeof(glm::highp_mat2x2) != 16; + Error += sizeof(glm::highp_mat2x3) != 24; + Error += sizeof(glm::highp_mat2x4) != 32; + Error += sizeof(glm::highp_mat3x2) != 24; + Error += sizeof(glm::highp_mat3x3) != 36; + Error += sizeof(glm::highp_mat3x4) != 48; + Error += sizeof(glm::highp_mat4x2) != 32; + Error += sizeof(glm::highp_mat4x3) != 48; + Error += sizeof(glm::highp_mat4x4) != 64; + + Error += sizeof(glm::highp_fmat2) != 16; + Error += sizeof(glm::highp_fmat3) != 36; + Error += sizeof(glm::highp_fmat4) != 64; + Error += sizeof(glm::highp_fmat2x2) != 16; + Error += sizeof(glm::highp_fmat2x3) != 24; + Error += sizeof(glm::highp_fmat2x4) != 32; + Error += sizeof(glm::highp_fmat3x2) != 24; + Error += sizeof(glm::highp_fmat3x3) != 36; + Error += sizeof(glm::highp_fmat3x4) != 48; + Error += sizeof(glm::highp_fmat4x2) != 32; + Error += sizeof(glm::highp_fmat4x3) != 48; + Error += sizeof(glm::highp_fmat4x4) != 64; + + Error += sizeof(glm::highp_f32mat2) != 16; + Error += sizeof(glm::highp_f32mat3) != 36; + Error += sizeof(glm::highp_f32mat4) != 64; + Error += sizeof(glm::highp_f32mat2x2) != 16; + Error += sizeof(glm::highp_f32mat2x3) != 24; + Error += sizeof(glm::highp_f32mat2x4) != 32; + Error += sizeof(glm::highp_f32mat3x2) != 24; + Error += sizeof(glm::highp_f32mat3x3) != 36; + Error += sizeof(glm::highp_f32mat3x4) != 48; + Error += sizeof(glm::highp_f32mat4x2) != 32; + Error += sizeof(glm::highp_f32mat4x3) != 48; + Error += sizeof(glm::highp_f32mat4x4) != 64; + + return Error; +} + +static int test_dmat_size() +{ + int Error = 0; + + Error += sizeof(glm::f64mat2) != 32; + Error += sizeof(glm::f64mat3) != 72; + Error += sizeof(glm::f64mat4) != 128; + Error += sizeof(glm::f64mat2x2) != 32; + Error += sizeof(glm::f64mat2x3) != 48; + Error += sizeof(glm::f64mat2x4) != 64; + Error += sizeof(glm::f64mat3x2) != 48; + Error += sizeof(glm::f64mat3x3) != 72; + Error += sizeof(glm::f64mat3x4) != 96; + Error += sizeof(glm::f64mat4x2) != 64; + Error += sizeof(glm::f64mat4x3) != 96; + Error += sizeof(glm::f64mat4x4) != 128; + + Error += sizeof(glm::lowp_f64mat2) != 32; + Error += sizeof(glm::lowp_f64mat3) != 72; + Error += sizeof(glm::lowp_f64mat4) != 128; + Error += sizeof(glm::lowp_f64mat2x2) != 32; + Error += sizeof(glm::lowp_f64mat2x3) != 48; + Error += sizeof(glm::lowp_f64mat2x4) != 64; + Error += sizeof(glm::lowp_f64mat3x2) != 48; + Error += sizeof(glm::lowp_f64mat3x3) != 72; + Error += sizeof(glm::lowp_f64mat3x4) != 96; + Error += sizeof(glm::lowp_f64mat4x2) != 64; + Error += sizeof(glm::lowp_f64mat4x3) != 96; + Error += sizeof(glm::lowp_f64mat4x4) != 128; + + Error += sizeof(glm::mediump_f64mat2) != 32; + Error += sizeof(glm::mediump_f64mat3) != 72; + Error += sizeof(glm::mediump_f64mat4) != 128; + Error += sizeof(glm::mediump_f64mat2x2) != 32; + Error += sizeof(glm::mediump_f64mat2x3) != 48; + Error += sizeof(glm::mediump_f64mat2x4) != 64; + Error += sizeof(glm::mediump_f64mat3x2) != 48; + Error += sizeof(glm::mediump_f64mat3x3) != 72; + Error += sizeof(glm::mediump_f64mat3x4) != 96; + Error += sizeof(glm::mediump_f64mat4x2) != 64; + Error += sizeof(glm::mediump_f64mat4x3) != 96; + Error += sizeof(glm::mediump_f64mat4x4) != 128; + + Error += sizeof(glm::highp_f64mat2) != 32; + Error += sizeof(glm::highp_f64mat3) != 72; + Error += sizeof(glm::highp_f64mat4) != 128; + Error += sizeof(glm::highp_f64mat2x2) != 32; + Error += sizeof(glm::highp_f64mat2x3) != 48; + Error += sizeof(glm::highp_f64mat2x4) != 64; + Error += sizeof(glm::highp_f64mat3x2) != 48; + Error += sizeof(glm::highp_f64mat3x3) != 72; + Error += sizeof(glm::highp_f64mat3x4) != 96; + Error += sizeof(glm::highp_f64mat4x2) != 64; + Error += sizeof(glm::highp_f64mat4x3) != 96; + Error += sizeof(glm::highp_f64mat4x4) != 128; + + return Error; +} + +static int test_quat_size() +{ + int Error = 0; + + Error += sizeof(glm::f32quat) != 16; + Error += sizeof(glm::f64quat) != 32; + + Error += sizeof(glm::lowp_f32quat) != 16; + Error += sizeof(glm::lowp_f64quat) != 32; + + Error += sizeof(glm::mediump_f32quat) != 16; + Error += sizeof(glm::mediump_f64quat) != 32; + + Error += sizeof(glm::highp_f32quat) != 16; + Error += sizeof(glm::highp_f64quat) != 32; + + return Error; +} + +static int test_quat_precision() +{ + int Error = 0; + + { + glm::f32quat q1(0.f, glm::vec3(0.f, 0.f, 1.f)); + glm::lowp_f32quat qA(q1); + glm::mediump_f32quat qB(q1); + glm::highp_f32quat qC(q1); + glm::f32quat q2(qA); + glm::f32quat q3(qB); + glm::f32quat q4(qC); + + Error += glm::all(glm::equal(q1, q2, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(q1, q3, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(q1, q4, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +static int test_fvec_conversion() +{ + int Error(0); + + { + glm::highp_vec4 a = glm::vec4(1, 2, 3, 4); + glm::mediump_vec4 b = glm::vec4(1, 2, 3, 4); + glm::lowp_vec4 c = b; + glm::mediump_vec4 d = c; + glm::lowp_ivec4 e = glm::ivec4(d); + glm::lowp_ivec3 f = glm::ivec3(e); + + Error += glm::all(glm::equal(b, d, glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +#if GLM_HAS_OPENMP +static int test_openmp() +{ + std::vector VectorA(1000); + std::vector VectorB(1000); + std::vector VectorC(1000); + + for (std::size_t i = 0; i < VectorA.size(); ++i) + { + VectorA[i] = glm::u8vec3(1, 1, 1); + VectorB[i] = glm::u8vec3(1, 1, 1); + } + + #pragma omp parallel for default(none) shared(VectorA, VectorB, VectorC) + for (int i = 0; i < static_cast(VectorC.size()); ++i) + { + VectorC[i] = VectorA[i] + VectorB[i]; + } + + return 0; +} +#endif//GLM_HAS_OPENMP + +int main() +{ + int Error = 0; + + Error += test_scalar_size(); + Error += test_fvec_size(); + + Error += test_fvec_precision(); + Error += test_fvec_conversion(); + + Error += test_dvec_precision(); + + Error += test_uvec_size(); + Error += test_uvec_precision(); + Error += test_ivec_size(); + Error += test_ivec_precision(); + + Error += test_fmat_size(); + Error += test_dmat_size(); + Error += test_quat_size(); + Error += test_quat_precision(); + +# if GLM_HAS_OPENMP + Error += test_openmp(); +# endif// + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_type_ptr.cpp b/vendor/glm/test/gtc/gtc_type_ptr.cpp new file mode 100644 index 0000000..6fcd305 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_type_ptr.cpp @@ -0,0 +1,335 @@ +#include +#include +#include +#include + +int test_value_ptr_vec() +{ + int Error = 0; + + { + glm::vec2 v(1.0); + float * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::vec3 v(1.0); + float * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::vec4 v(1.0); + float * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + + { + glm::dvec2 v(1.0); + double * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::dvec3 v(1.0); + double * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::dvec4 v(1.0); + double * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + + return Error; +} + +int test_value_ptr_vec_const() +{ + int Error = 0; + + { + glm::vec2 const v(1.0); + float const * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::vec3 const v(1.0); + float const * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::vec4 const v(1.0); + float const * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + + { + glm::dvec2 const v(1.0); + double const * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::dvec3 const v(1.0); + double const * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + { + glm::dvec4 const v(1.0); + double const * p = glm::value_ptr(v); + Error += p == &v[0] ? 0 : 1; + } + + return Error; +} + +int test_value_ptr_mat() +{ + int Error = 0; + + { + glm::mat2x2 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat2x3 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat2x4 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat3x2 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat3x3 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat3x4 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat4x2 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat4x3 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat4x4 m(1.0); + float * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + + return Error; +} + +int test_value_ptr_mat_const() +{ + int Error = 0; + + { + glm::mat2x2 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat2x3 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat2x4 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat3x2 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat3x3 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat3x4 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat4x2 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat4x3 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + { + glm::mat4x4 const m(1.0); + float const * p = glm::value_ptr(m); + Error += p == &m[0][0] ? 0 : 1; + } + + return Error; +} + +int test_make_pointer_mat() +{ + int Error = 0; + + float ArrayA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + double ArrayB[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + glm::mat2x2 Mat2x2A = glm::make_mat2x2(ArrayA); + glm::mat2x3 Mat2x3A = glm::make_mat2x3(ArrayA); + glm::mat2x4 Mat2x4A = glm::make_mat2x4(ArrayA); + glm::mat3x2 Mat3x2A = glm::make_mat3x2(ArrayA); + glm::mat3x3 Mat3x3A = glm::make_mat3x3(ArrayA); + glm::mat3x4 Mat3x4A = glm::make_mat3x4(ArrayA); + glm::mat4x2 Mat4x2A = glm::make_mat4x2(ArrayA); + glm::mat4x3 Mat4x3A = glm::make_mat4x3(ArrayA); + glm::mat4x4 Mat4x4A = glm::make_mat4x4(ArrayA); + + glm::dmat2x2 Mat2x2B = glm::make_mat2x2(ArrayB); + glm::dmat2x3 Mat2x3B = glm::make_mat2x3(ArrayB); + glm::dmat2x4 Mat2x4B = glm::make_mat2x4(ArrayB); + glm::dmat3x2 Mat3x2B = glm::make_mat3x2(ArrayB); + glm::dmat3x3 Mat3x3B = glm::make_mat3x3(ArrayB); + glm::dmat3x4 Mat3x4B = glm::make_mat3x4(ArrayB); + glm::dmat4x2 Mat4x2B = glm::make_mat4x2(ArrayB); + glm::dmat4x3 Mat4x3B = glm::make_mat4x3(ArrayB); + glm::dmat4x4 Mat4x4B = glm::make_mat4x4(ArrayB); + + return Error; +} + +int test_make_pointer_vec() +{ + int Error = 0; + + float ArrayA[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + int ArrayB[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + bool ArrayC[] = {true, false, true, false, true, false, true, false, true, false, true, false, true, false, true, false}; + + glm::vec2 Vec2A = glm::make_vec2(ArrayA); + glm::vec3 Vec3A = glm::make_vec3(ArrayA); + glm::vec4 Vec4A = glm::make_vec4(ArrayA); + + glm::ivec2 Vec2B = glm::make_vec2(ArrayB); + glm::ivec3 Vec3B = glm::make_vec3(ArrayB); + glm::ivec4 Vec4B = glm::make_vec4(ArrayB); + + glm::bvec2 Vec2C = glm::make_vec2(ArrayC); + glm::bvec3 Vec3C = glm::make_vec3(ArrayC); + glm::bvec4 Vec4C = glm::make_vec4(ArrayC); + + return Error; +} + +int test_make_vec1() +{ + int Error = 0; + + glm::ivec1 const v1 = glm::make_vec1(glm::ivec1(2)); + Error += v1 == glm::ivec1(2) ? 0 : 1; + + glm::ivec1 const v2 = glm::make_vec1(glm::ivec2(2)); + Error += v2 == glm::ivec1(2) ? 0 : 1; + + glm::ivec1 const v3 = glm::make_vec1(glm::ivec3(2)); + Error += v3 == glm::ivec1(2) ? 0 : 1; + + glm::ivec1 const v4 = glm::make_vec1(glm::ivec4(2)); + Error += v3 == glm::ivec1(2) ? 0 : 1; + + return Error; +} + +int test_make_vec2() +{ + int Error = 0; + + glm::ivec2 const v1 = glm::make_vec2(glm::ivec1(2)); + Error += v1 == glm::ivec2(2, 0) ? 0 : 1; + + glm::ivec2 const v2 = glm::make_vec2(glm::ivec2(2)); + Error += v2 == glm::ivec2(2, 2) ? 0 : 1; + + glm::ivec2 const v3 = glm::make_vec2(glm::ivec3(2)); + Error += v3 == glm::ivec2(2, 2) ? 0 : 1; + + glm::ivec2 const v4 = glm::make_vec2(glm::ivec4(2)); + Error += v3 == glm::ivec2(2, 2) ? 0 : 1; + + return Error; +} + +int test_make_vec3() +{ + int Error = 0; + + glm::ivec3 const v1 = glm::make_vec3(glm::ivec1(2)); + Error += v1 == glm::ivec3(2, 0, 0) ? 0 : 1; + + glm::ivec3 const v2 = glm::make_vec3(glm::ivec2(2)); + Error += v2 == glm::ivec3(2, 2, 0) ? 0 : 1; + + glm::ivec3 const v3 = glm::make_vec3(glm::ivec3(2)); + Error += v3 == glm::ivec3(2, 2, 2) ? 0 : 1; + + glm::ivec3 const v4 = glm::make_vec3(glm::ivec4(2)); + Error += v3 == glm::ivec3(2, 2, 2) ? 0 : 1; + + return Error; +} + +int test_make_vec4() +{ + int Error = 0; + + glm::ivec4 const v1 = glm::make_vec4(glm::ivec1(2)); + Error += v1 == glm::ivec4(2, 0, 0, 1) ? 0 : 1; + + glm::ivec4 const v2 = glm::make_vec4(glm::ivec2(2)); + Error += v2 == glm::ivec4(2, 2, 0, 1) ? 0 : 1; + + glm::ivec4 const v3 = glm::make_vec4(glm::ivec3(2)); + Error += v3 == glm::ivec4(2, 2, 2, 1) ? 0 : 1; + + glm::ivec4 const v4 = glm::make_vec4(glm::ivec4(2)); + Error += v4 == glm::ivec4(2, 2, 2, 2) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_make_vec1(); + Error += test_make_vec2(); + Error += test_make_vec3(); + Error += test_make_vec4(); + Error += test_make_pointer_vec(); + Error += test_make_pointer_mat(); + Error += test_value_ptr_vec(); + Error += test_value_ptr_vec_const(); + Error += test_value_ptr_mat(); + Error += test_value_ptr_mat_const(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_ulp.cpp b/vendor/glm/test/gtc/gtc_ulp.cpp new file mode 100644 index 0000000..d5074a3 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_ulp.cpp @@ -0,0 +1,99 @@ +#include +#include +#include + +int test_ulp_float_dist() +{ + int Error = 0; + + float A = 1.0f; + + float B = glm::next_float(A); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + float C = glm::prev_float(B); + Error += glm::equal(A, C, 0) ? 0 : 1; + + int D = glm::float_distance(A, B); + Error += D == 1 ? 0 : 1; + int E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + + return Error; +} + +int test_ulp_float_step() +{ + int Error = 0; + + float A = 1.0f; + + for(int i = 10; i < 1000; i *= 10) + { + float B = glm::next_float(A, i); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + float C = glm::prev_float(B, i); + Error += glm::equal(A, C, 0) ? 0 : 1; + + int D = glm::float_distance(A, B); + Error += D == i ? 0 : 1; + int E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + } + + return Error; +} + +int test_ulp_double_dist() +{ + int Error = 0; + + double A = 1.0; + + double B = glm::next_float(A); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + double C = glm::prev_float(B); + Error += glm::equal(A, C, 0) ? 0 : 1; + + glm::int64 const D = glm::float_distance(A, B); + Error += D == 1 ? 0 : 1; + glm::int64 const E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + + return Error; +} + +int test_ulp_double_step() +{ + int Error = 0; + + double A = 1.0; + + for(int i = 10; i < 1000; i *= 10) + { + double B = glm::next_float(A, i); + Error += glm::notEqual(A, B, 0) ? 0 : 1; + double C = glm::prev_float(B, i); + Error += glm::equal(A, C, 0) ? 0 : 1; + + glm::int64 const D = glm::float_distance(A, B); + Error += D == i ? 0 : 1; + glm::int64 const E = glm::float_distance(A, C); + Error += E == 0 ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_ulp_float_dist(); + Error += test_ulp_float_step(); + Error += test_ulp_double_dist(); + Error += test_ulp_double_step(); + + return Error; +} + + diff --git a/vendor/glm/test/gtc/gtc_user_defined_types.cpp b/vendor/glm/test/gtc/gtc_user_defined_types.cpp new file mode 100644 index 0000000..af39620 --- /dev/null +++ b/vendor/glm/test/gtc/gtc_user_defined_types.cpp @@ -0,0 +1,30 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2010-09-16 +// Updated : 2011-05-27 +// Licence : This source is under MIT licence +// File : test/gtc/type_ptr.cpp +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#define GLM_FORCE_RADIANS +#include + +int test_make_pointer_vec() +{ + int Error = 0; + + glm::func(); + //func(); + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_make_pointer_vec(); + + return Error; +} diff --git a/vendor/glm/test/gtc/gtc_vec1.cpp b/vendor/glm/test/gtc/gtc_vec1.cpp new file mode 100644 index 0000000..268d95e --- /dev/null +++ b/vendor/glm/test/gtc/gtc_vec1.cpp @@ -0,0 +1,8 @@ +#include + +int main() +{ + int Error = 0; + + return Error; +} diff --git a/vendor/glm/test/gtx/CMakeLists.txt b/vendor/glm/test/gtx/CMakeLists.txt new file mode 100644 index 0000000..5c8095c --- /dev/null +++ b/vendor/glm/test/gtx/CMakeLists.txt @@ -0,0 +1,58 @@ +glmCreateTestGTC(gtx) +glmCreateTestGTC(gtx_associated_min_max) +glmCreateTestGTC(gtx_closest_point) +glmCreateTestGTC(gtx_color_encoding) +glmCreateTestGTC(gtx_color_space_YCoCg) +glmCreateTestGTC(gtx_color_space) +glmCreateTestGTC(gtx_common) +glmCreateTestGTC(gtx_compatibility) +glmCreateTestGTC(gtx_component_wise) +glmCreateTestGTC(gtx_easing) +glmCreateTestGTC(gtx_euler_angle) +glmCreateTestGTC(gtx_extend) +glmCreateTestGTC(gtx_extended_min_max) +glmCreateTestGTC(gtx_exterior_product) +glmCreateTestGTC(gtx_fast_exponential) +glmCreateTestGTC(gtx_fast_square_root) +glmCreateTestGTC(gtx_fast_trigonometry) +glmCreateTestGTC(gtx_functions) +glmCreateTestGTC(gtx_gradient_paint) +glmCreateTestGTC(gtx_handed_coordinate_space) +glmCreateTestGTC(gtx_integer) +glmCreateTestGTC(gtx_intersect) +glmCreateTestGTC(gtx_io) +glmCreateTestGTC(gtx_load) +glmCreateTestGTC(gtx_log_base) +glmCreateTestGTC(gtx_matrix_cross_product) +glmCreateTestGTC(gtx_matrix_decompose) +glmCreateTestGTC(gtx_matrix_factorisation) +glmCreateTestGTC(gtx_matrix_interpolation) +glmCreateTestGTC(gtx_matrix_major_storage) +glmCreateTestGTC(gtx_matrix_operation) +glmCreateTestGTC(gtx_matrix_query) +glmCreateTestGTC(gtx_matrix_transform_2d) +glmCreateTestGTC(gtx_norm) +glmCreateTestGTC(gtx_normal) +glmCreateTestGTC(gtx_normalize_dot) +glmCreateTestGTC(gtx_number_precision) +glmCreateTestGTC(gtx_orthonormalize) +glmCreateTestGTC(gtx_optimum_pow) +glmCreateTestGTC(gtx_perpendicular) +glmCreateTestGTC(gtx_polar_coordinates) +glmCreateTestGTC(gtx_projection) +glmCreateTestGTC(gtx_quaternion) +glmCreateTestGTC(gtx_dual_quaternion) +glmCreateTestGTC(gtx_range) +glmCreateTestGTC(gtx_rotate_normalized_axis) +glmCreateTestGTC(gtx_rotate_vector) +glmCreateTestGTC(gtx_scalar_multiplication) +glmCreateTestGTC(gtx_scalar_relational) +glmCreateTestGTC(gtx_spline) +glmCreateTestGTC(gtx_string_cast) +glmCreateTestGTC(gtx_texture) +glmCreateTestGTC(gtx_type_aligned) +glmCreateTestGTC(gtx_type_trait) +glmCreateTestGTC(gtx_vec_swizzle) +glmCreateTestGTC(gtx_vector_angle) +glmCreateTestGTC(gtx_vector_query) +glmCreateTestGTC(gtx_wrap) diff --git a/vendor/glm/test/gtx/gtx.cpp b/vendor/glm/test/gtx/gtx.cpp new file mode 100644 index 0000000..1b143b6 --- /dev/null +++ b/vendor/glm/test/gtx/gtx.cpp @@ -0,0 +1,8 @@ +#include + +int main() +{ + int Error = 0; + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_associated_min_max.cpp b/vendor/glm/test/gtx/gtx_associated_min_max.cpp new file mode 100644 index 0000000..9007f8a --- /dev/null +++ b/vendor/glm/test/gtx/gtx_associated_min_max.cpp @@ -0,0 +1,10 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_closest_point.cpp b/vendor/glm/test/gtx/gtx_closest_point.cpp new file mode 100644 index 0000000..0f6303a --- /dev/null +++ b/vendor/glm/test/gtx/gtx_closest_point.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_color_encoding.cpp b/vendor/glm/test/gtx/gtx_color_encoding.cpp new file mode 100644 index 0000000..8b499be --- /dev/null +++ b/vendor/glm/test/gtx/gtx_color_encoding.cpp @@ -0,0 +1,51 @@ +#include +#include +#include +#include + +namespace srgb +{ + int test() + { + int Error(0); + + glm::vec3 const ColorSourceRGB(1.0, 0.5, 0.0); +/* + { + glm::vec3 const ColorSRGB = glm::convertLinearSRGBToD65XYZ(ColorSourceRGB); + glm::vec3 const ColorRGB = glm::convertD65XYZToLinearSRGB(ColorSRGB); + Error += glm::all(glm::epsilonEqual(ColorSourceRGB, ColorRGB, 0.00001f)) ? 0 : 1; + } +*/ + { + glm::vec3 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceRGB, 2.8f); + glm::vec3 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB, 2.8f); + Error += glm::all(glm::epsilonEqual(ColorSourceRGB, ColorRGB, 0.00001f)) ? 0 : 1; + } + + glm::vec4 const ColorSourceRGBA(1.0, 0.5, 0.0, 1.0); + + { + glm::vec4 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceRGBA); + glm::vec4 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB); + Error += glm::all(glm::epsilonEqual(ColorSourceRGBA, ColorRGB, 0.00001f)) ? 0 : 1; + } + + { + glm::vec4 const ColorSRGB = glm::convertLinearToSRGB(ColorSourceRGBA, 2.8f); + glm::vec4 const ColorRGB = glm::convertSRGBToLinear(ColorSRGB, 2.8f); + Error += glm::all(glm::epsilonEqual(ColorSourceRGBA, ColorRGB, 0.00001f)) ? 0 : 1; + } + + return Error; + } +}//namespace srgb + +int main() +{ + int Error(0); + + Error += srgb::test(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_color_space.cpp b/vendor/glm/test/gtx/gtx_color_space.cpp new file mode 100644 index 0000000..a23d2c8 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_color_space.cpp @@ -0,0 +1,20 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int test_saturation() +{ + int Error(0); + + glm::vec4 Color = glm::saturation(1.0f, glm::vec4(1.0, 0.5, 0.0, 1.0)); + + return Error; +} + +int main() +{ + int Error(0); + + Error += test_saturation(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_color_space_YCoCg.cpp b/vendor/glm/test/gtx/gtx_color_space_YCoCg.cpp new file mode 100644 index 0000000..2ca131d --- /dev/null +++ b/vendor/glm/test/gtx/gtx_color_space_YCoCg.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_common.cpp b/vendor/glm/test/gtx/gtx_common.cpp new file mode 100644 index 0000000..fd4fa99 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_common.cpp @@ -0,0 +1,161 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include + +namespace fmod_ +{ + template + GLM_FUNC_QUALIFIER genType modTrunc(genType a, genType b) + { + return a - b * glm::trunc(a / b); + } + + int test() + { + int Error(0); + + { + float A0(3.0); + float B0(2.0f); + float C0 = glm::fmod(A0, B0); + + Error += glm::abs(C0 - 1.0f) < 0.00001f ? 0 : 1; + + glm::vec4 A1(3.0); + float B1(2.0f); + glm::vec4 C1 = glm::fmod(A1, B1); + + Error += glm::all(glm::epsilonEqual(C1, glm::vec4(1.0f), 0.00001f)) ? 0 : 1; + + glm::vec4 A2(3.0); + glm::vec4 B2(2.0f); + glm::vec4 C2 = glm::fmod(A2, B2); + + Error += glm::all(glm::epsilonEqual(C2, glm::vec4(1.0f), 0.00001f)) ? 0 : 1; + + glm::ivec4 A3(3); + int B3(2); + glm::ivec4 C3 = glm::fmod(A3, B3); + + Error += glm::all(glm::equal(C3, glm::ivec4(1))) ? 0 : 1; + + glm::ivec4 A4(3); + glm::ivec4 B4(2); + glm::ivec4 C4 = glm::fmod(A4, B4); + + Error += glm::all(glm::equal(C4, glm::ivec4(1))) ? 0 : 1; + } + + { + float A0(22.0); + float B0(-10.0f); + float C0 = glm::fmod(A0, B0); + + Error += glm::abs(C0 - 2.0f) < 0.00001f ? 0 : 1; + + glm::vec4 A1(22.0); + float B1(-10.0f); + glm::vec4 C1 = glm::fmod(A1, B1); + + Error += glm::all(glm::epsilonEqual(C1, glm::vec4(2.0f), 0.00001f)) ? 0 : 1; + + glm::vec4 A2(22.0); + glm::vec4 B2(-10.0f); + glm::vec4 C2 = glm::fmod(A2, B2); + + Error += glm::all(glm::epsilonEqual(C2, glm::vec4(2.0f), 0.00001f)) ? 0 : 1; + + glm::ivec4 A3(22); + int B3(-10); + glm::ivec4 C3 = glm::fmod(A3, B3); + + Error += glm::all(glm::equal(C3, glm::ivec4(2))) ? 0 : 1; + + glm::ivec4 A4(22); + glm::ivec4 B4(-10); + glm::ivec4 C4 = glm::fmod(A4, B4); + + Error += glm::all(glm::equal(C4, glm::ivec4(2))) ? 0 : 1; + } + + // http://stackoverflow.com/questions/7610631/glsl-mod-vs-hlsl-fmod + { + for (float y = -10.0f; y < 10.0f; y += 0.1f) + for (float x = -10.0f; x < 10.0f; x += 0.1f) + { + float const A(std::fmod(x, y)); + //float const B(std::remainder(x, y)); + float const C(glm::fmod(x, y)); + float const D(modTrunc(x, y)); + + //Error += glm::epsilonEqual(A, B, 0.0001f) ? 0 : 1; + //assert(!Error); + Error += glm::epsilonEqual(A, C, 0.0001f) ? 0 : 1; + assert(!Error); + Error += glm::epsilonEqual(A, D, 0.00001f) ? 0 : 1; + assert(!Error); + } + } + + return Error; + } +}//namespace fmod_ + +int test_isdenormal() +{ + int Error = 0; + + bool A = glm::isdenormal(1.0f); + Error += !A ? 0 : 1; + + glm::bvec1 B = glm::isdenormal(glm::vec1(1.0f)); + Error += !glm::any(B) ? 0 : 1; + + glm::bvec2 C = glm::isdenormal(glm::vec2(1.0f)); + Error += !glm::any(C) ? 0 : 1; + + glm::bvec3 D = glm::isdenormal(glm::vec3(1.0f)); + Error += !glm::any(D) ? 0 : 1; + + glm::bvec4 E = glm::isdenormal(glm::vec4(1.0f)); + Error += !glm::any(E) ? 0 : 1; + + return Error; +} + +int test_openBounded() +{ + int Error = 0; + + Error += glm::all(glm::openBounded(glm::ivec2(2), glm::ivec2(1), glm::ivec2(3))) ? 0 : 1; + Error += !glm::all(glm::openBounded(glm::ivec2(1), glm::ivec2(1), glm::ivec2(3))) ? 0 : 1; + Error += !glm::all(glm::openBounded(glm::ivec2(3), glm::ivec2(1), glm::ivec2(3))) ? 0 : 1; + + return Error; +} + +int test_closeBounded() +{ + int Error = 0; + + Error += glm::all(glm::closeBounded(glm::ivec2(2), glm::ivec2(1), glm::ivec2(3))) ? 0 : 1; + Error += glm::all(glm::closeBounded(glm::ivec2(1), glm::ivec2(1), glm::ivec2(3))) ? 0 : 1; + Error += glm::all(glm::closeBounded(glm::ivec2(3), glm::ivec2(1), glm::ivec2(3))) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_isdenormal(); + Error += ::fmod_::test(); + Error += test_openBounded(); + Error += test_closeBounded(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_compatibility.cpp b/vendor/glm/test/gtx/gtx_compatibility.cpp new file mode 100644 index 0000000..e5351ce --- /dev/null +++ b/vendor/glm/test/gtx/gtx_compatibility.cpp @@ -0,0 +1,19 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + Error += glm::isfinite(1.0f) ? 0 : 1; + Error += glm::isfinite(1.0) ? 0 : 1; + Error += glm::isfinite(-1.0f) ? 0 : 1; + Error += glm::isfinite(-1.0) ? 0 : 1; + + Error += glm::all(glm::isfinite(glm::vec4(1.0f))) ? 0 : 1; + Error += glm::all(glm::isfinite(glm::dvec4(1.0))) ? 0 : 1; + Error += glm::all(glm::isfinite(glm::vec4(-1.0f))) ? 0 : 1; + Error += glm::all(glm::isfinite(glm::dvec4(-1.0))) ? 0 : 1; + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_component_wise.cpp b/vendor/glm/test/gtx/gtx_component_wise.cpp new file mode 100644 index 0000000..29c81af --- /dev/null +++ b/vendor/glm/test/gtx/gtx_component_wise.cpp @@ -0,0 +1,116 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include + +namespace compNormalize +{ + int run() + { + int Error(0); + + { + glm::vec4 const A = glm::compNormalize(glm::u8vec4(0, 127, 128, 255)); + + Error += glm::epsilonEqual(A.x, 0.0f, glm::epsilon()) ? 0 : 1; + Error += A.y < 0.5f ? 0 : 1; + Error += A.z > 0.5f ? 0 : 1; + Error += glm::epsilonEqual(A.w, 1.0f, glm::epsilon()) ? 0 : 1; + } + + { + glm::vec4 const A = glm::compNormalize(glm::i8vec4(-128, -1, 0, 127)); + + Error += glm::epsilonEqual(A.x,-1.0f, glm::epsilon()) ? 0 : 1; + Error += A.y < 0.0f ? 0 : 1; + Error += A.z > 0.0f ? 0 : 1; + Error += glm::epsilonEqual(A.w, 1.0f, glm::epsilon()) ? 0 : 1; + } + + { + glm::vec4 const A = glm::compNormalize(glm::u16vec4( + std::numeric_limits::min(), + (std::numeric_limits::max() >> 1) + 0, + (std::numeric_limits::max() >> 1) + 1, + std::numeric_limits::max())); + + Error += glm::epsilonEqual(A.x, 0.0f, glm::epsilon()) ? 0 : 1; + Error += A.y < 0.5f ? 0 : 1; + Error += A.z > 0.5f ? 0 : 1; + Error += glm::epsilonEqual(A.w, 1.0f, glm::epsilon()) ? 0 : 1; + } + + { + glm::vec4 const A = glm::compNormalize(glm::i16vec4( + std::numeric_limits::min(), + static_cast(-1), + static_cast(0), + std::numeric_limits::max())); + + Error += glm::epsilonEqual(A.x,-1.0f, glm::epsilon()) ? 0 : 1; + Error += A.y < 0.0f ? 0 : 1; + Error += A.z > 0.0f ? 0 : 1; + Error += glm::epsilonEqual(A.w, 1.0f, glm::epsilon()) ? 0 : 1; + } + + return Error; + } +}//namespace compNormalize + +namespace compScale +{ + int run() + { + int Error(0); + + { + glm::u8vec4 const A = glm::compScale(glm::vec4(0.0f, 0.2f, 0.5f, 1.0f)); + + Error += A.x == std::numeric_limits::min() ? 0 : 1; + Error += A.y < (std::numeric_limits::max() >> 2) ? 0 : 1; + Error += A.z == 127 ? 0 : 1; + Error += A.w == 255 ? 0 : 1; + } + + { + glm::i8vec4 const A = glm::compScale(glm::vec4(0.0f,-1.0f, 0.5f, 1.0f)); + + Error += A.x == 0 ? 0 : 1; + Error += A.y == -128 ? 0 : 1; + Error += A.z == 63 ? 0 : 1; + Error += A.w == 127 ? 0 : 1; + } + + { + glm::u16vec4 const A = glm::compScale(glm::vec4(0.0f, 0.2f, 0.5f, 1.0f)); + + Error += A.x == std::numeric_limits::min() ? 0 : 1; + Error += A.y < (std::numeric_limits::max() >> 2) ? 0 : 1; + Error += A.z == 32767 ? 0 : 1; + Error += A.w == 65535 ? 0 : 1; + } + + { + glm::i16vec4 const A = glm::compScale(glm::vec4(0.0f,-1.0f, 0.5f, 1.0f)); + + Error += A.x == 0 ? 0 : 1; + Error += A.y == -32768 ? 0 : 1; + Error += A.z == 16383 ? 0 : 1; + Error += A.w == 32767 ? 0 : 1; + } + + return Error; + } +}// compScale + +int main() +{ + int Error(0); + + Error += compNormalize::run(); + Error += compScale::run(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_dual_quaternion.cpp b/vendor/glm/test/gtx/gtx_dual_quaternion.cpp new file mode 100644 index 0000000..ceedc2c --- /dev/null +++ b/vendor/glm/test/gtx/gtx_dual_quaternion.cpp @@ -0,0 +1,205 @@ +#define GLM_ENABLE_EXPERIMENTAL +#define GLM_FORCE_CTOR_INIT +#include +#include +#include +#include +#include +#if GLM_HAS_TRIVIAL_QUERIES +# include +#endif + +int myrand() +{ + static int holdrand = 1; + return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff); +} + +float myfrand() // returns values from -1 to 1 inclusive +{ + return float(double(myrand()) / double( 0x7ffff )) * 2.0f - 1.0f; +} + +int test_dquat_type() +{ + glm::dvec3 vA; + glm::dquat dqA, dqB; + glm::ddualquat C(dqA, dqB); + glm::ddualquat B(dqA); + glm::ddualquat D(dqA, vA); + return 0; +} + +int test_scalars() +{ + float const Epsilon = 0.0001f; + + int Error(0); + + glm::quat src_q1 = glm::quat(1.0f,2.0f,3.0f,4.0f); + glm::quat src_q2 = glm::quat(5.0f,6.0f,7.0f,8.0f); + glm::dualquat src1(src_q1,src_q2); + + { + glm::dualquat dst1 = src1 * 2.0f; + glm::dualquat dst2 = 2.0f * src1; + glm::dualquat dst3 = src1; + dst3 *= 2.0f; + glm::dualquat dstCmp(src_q1 * 2.0f,src_q2 * 2.0f); + Error += glm::all(glm::epsilonEqual(dst1.real,dstCmp.real, Epsilon)) && glm::all(glm::epsilonEqual(dst1.dual,dstCmp.dual, Epsilon)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(dst2.real,dstCmp.real, Epsilon)) && glm::all(glm::epsilonEqual(dst2.dual,dstCmp.dual, Epsilon)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(dst3.real,dstCmp.real, Epsilon)) && glm::all(glm::epsilonEqual(dst3.dual,dstCmp.dual, Epsilon)) ? 0 : 1; + } + + { + glm::dualquat dst1 = src1 / 2.0f; + glm::dualquat dst2 = src1; + dst2 /= 2.0f; + glm::dualquat dstCmp(src_q1 / 2.0f,src_q2 / 2.0f); + Error += glm::all(glm::epsilonEqual(dst1.real,dstCmp.real, Epsilon)) && glm::all(glm::epsilonEqual(dst1.dual,dstCmp.dual, Epsilon)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(dst2.real,dstCmp.real, Epsilon)) && glm::all(glm::epsilonEqual(dst2.dual,dstCmp.dual, Epsilon)) ? 0 : 1; + } + return Error; +} + +int test_inverse() +{ + int Error(0); + + float const Epsilon = 0.0001f; + + glm::dualquat dqid = glm::dual_quat_identity(); + glm::mat4x4 mid(1.0f); + + for (int j = 0; j < 100; ++j) + { + glm::mat4x4 rot = glm::yawPitchRoll(myfrand() * 360.0f, myfrand() * 360.0f, myfrand() * 360.0f); + glm::vec3 vt = glm::vec3(myfrand() * 10.0f, myfrand() * 10.0f, myfrand() * 10.0f); + + glm::mat4x4 m = glm::translate(mid, vt) * rot; + + glm::quat qr = glm::quat_cast(m); + + glm::dualquat dq(qr); + + glm::dualquat invdq = glm::inverse(dq); + + glm::dualquat r1 = invdq * dq; + glm::dualquat r2 = dq * invdq; + + Error += glm::all(glm::epsilonEqual(r1.real, dqid.real, Epsilon)) && glm::all(glm::epsilonEqual(r1.dual, dqid.dual, Epsilon)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(r2.real, dqid.real, Epsilon)) && glm::all(glm::epsilonEqual(r2.dual, dqid.dual, Epsilon)) ? 0 : 1; + + // testing commutative property + glm::dualquat r ( glm::quat( myfrand() * glm::pi() * 2.0f, myfrand(), myfrand(), myfrand() ), + glm::vec3(myfrand() * 10.0f, myfrand() * 10.0f, myfrand() * 10.0f) ); + glm::dualquat riq = (r * invdq) * dq; + glm::dualquat rqi = (r * dq) * invdq; + + Error += glm::all(glm::epsilonEqual(riq.real, rqi.real, Epsilon)) && glm::all(glm::epsilonEqual(riq.dual, rqi.dual, Epsilon)) ? 0 : 1; + } + + return Error; +} + +int test_mul() +{ + int Error(0); + + float const Epsilon = 0.0001f; + + glm::mat4x4 mid(1.0f); + + for (int j = 0; j < 100; ++j) + { + // generate random rotations and translations and compare transformed by matrix and dualquats random points + glm::vec3 vt1 = glm::vec3(myfrand() * 10.0f, myfrand() * 10.0f, myfrand() * 10.0f); + glm::vec3 vt2 = glm::vec3(myfrand() * 10.0f, myfrand() * 10.0f, myfrand() * 10.0f); + + glm::mat4x4 rot1 = glm::yawPitchRoll(myfrand() * 360.0f, myfrand() * 360.0f, myfrand() * 360.0f); + glm::mat4x4 rot2 = glm::yawPitchRoll(myfrand() * 360.0f, myfrand() * 360.0f, myfrand() * 360.0f); + glm::mat4x4 m1 = glm::translate(mid, vt1) * rot1; + glm::mat4x4 m2 = glm::translate(mid, vt2) * rot2; + glm::mat4x4 m3 = m2 * m1; + glm::mat4x4 m4 = m1 * m2; + + glm::quat qrot1 = glm::quat_cast(rot1); + glm::quat qrot2 = glm::quat_cast(rot2); + + glm::dualquat dq1 = glm::dualquat(qrot1,vt1); + glm::dualquat dq2 = glm::dualquat(qrot2,vt2); + glm::dualquat dq3 = dq2 * dq1; + glm::dualquat dq4 = dq1 * dq2; + + for (int i = 0; i < 100; ++i) + { + glm::vec4 src_pt = glm::vec4(myfrand() * 4.0f, myfrand() * 5.0f, myfrand() * 3.0f,1.0f); + // test both multiplication orders + glm::vec4 dst_pt_m3 = m3 * src_pt; + glm::vec4 dst_pt_dq3 = dq3 * src_pt; + + glm::vec4 dst_pt_m3_i = glm::inverse(m3) * src_pt; + glm::vec4 dst_pt_dq3_i = src_pt * dq3; + + glm::vec4 dst_pt_m4 = m4 * src_pt; + glm::vec4 dst_pt_dq4 = dq4 * src_pt; + + glm::vec4 dst_pt_m4_i = glm::inverse(m4) * src_pt; + glm::vec4 dst_pt_dq4_i = src_pt * dq4; + + Error += glm::all(glm::epsilonEqual(dst_pt_m3, dst_pt_dq3, Epsilon)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(dst_pt_m4, dst_pt_dq4, Epsilon)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(dst_pt_m3_i, dst_pt_dq3_i, Epsilon)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(dst_pt_m4_i, dst_pt_dq4_i, Epsilon)) ? 0 : 1; + } + } + + return Error; +} + +int test_dual_quat_ctr() +{ + int Error(0); + +# if GLM_HAS_TRIVIAL_QUERIES + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_default_constructible::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + // Error += std::is_trivially_copy_assignable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + Error += std::is_trivially_copyable::value ? 0 : 1; + + Error += std::is_copy_constructible::value ? 0 : 1; + Error += std::is_copy_constructible::value ? 0 : 1; +# endif + + return Error; +} + +int test_size() +{ + int Error = 0; + + Error += 32 == sizeof(glm::dualquat) ? 0 : 1; + Error += 64 == sizeof(glm::ddualquat) ? 0 : 1; + Error += glm::dualquat().length() == 2 ? 0 : 1; + Error += glm::ddualquat().length() == 2 ? 0 : 1; + Error += glm::dualquat::length() == 2 ? 0 : 1; + Error += glm::ddualquat::length() == 2 ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_dual_quat_ctr(); + Error += test_dquat_type(); + Error += test_scalars(); + Error += test_inverse(); + Error += test_mul(); + Error += test_size(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_easing.cpp b/vendor/glm/test/gtx/gtx_easing.cpp new file mode 100644 index 0000000..0e98cd5 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_easing.cpp @@ -0,0 +1,65 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +namespace +{ + + template + void _test_easing() + { + T a = static_cast(0.5); + T r; + + r = glm::linearInterpolation(a); + + r = glm::quadraticEaseIn(a); + r = glm::quadraticEaseOut(a); + r = glm::quadraticEaseInOut(a); + + r = glm::cubicEaseIn(a); + r = glm::cubicEaseOut(a); + r = glm::cubicEaseInOut(a); + + r = glm::quarticEaseIn(a); + r = glm::quarticEaseOut(a); + r = glm::quinticEaseInOut(a); + + r = glm::sineEaseIn(a); + r = glm::sineEaseOut(a); + r = glm::sineEaseInOut(a); + + r = glm::circularEaseIn(a); + r = glm::circularEaseOut(a); + r = glm::circularEaseInOut(a); + + r = glm::exponentialEaseIn(a); + r = glm::exponentialEaseOut(a); + r = glm::exponentialEaseInOut(a); + + r = glm::elasticEaseIn(a); + r = glm::elasticEaseOut(a); + r = glm::elasticEaseInOut(a); + + r = glm::backEaseIn(a); + r = glm::backEaseOut(a); + r = glm::backEaseInOut(a); + + r = glm::bounceEaseIn(a); + r = glm::bounceEaseOut(a); + r = glm::bounceEaseInOut(a); + } + +} + +int main() +{ + int Error = 0; + + _test_easing(); + _test_easing(); + + return Error; +} + diff --git a/vendor/glm/test/gtx/gtx_euler_angle.cpp b/vendor/glm/test/gtx/gtx_euler_angle.cpp new file mode 100644 index 0000000..348f581 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_euler_angle.cpp @@ -0,0 +1,539 @@ +// Code sample from Filippo Ramaciotti + +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace test_eulerAngleX +{ + int test() + { + int Error = 0; + + float const Angle(glm::pi() * 0.5f); + glm::vec3 const X(1.0f, 0.0f, 0.0f); + + glm::vec4 const Y(0.0f, 1.0f, 0.0f, 1.0f); + glm::vec4 const Y1 = glm::rotate(glm::mat4(1.0f), Angle, X) * Y; + glm::vec4 const Y2 = glm::eulerAngleX(Angle) * Y; + glm::vec4 const Y3 = glm::eulerAngleXY(Angle, 0.0f) * Y; + glm::vec4 const Y4 = glm::eulerAngleYX(0.0f, Angle) * Y; + glm::vec4 const Y5 = glm::eulerAngleXZ(Angle, 0.0f) * Y; + glm::vec4 const Y6 = glm::eulerAngleZX(0.0f, Angle) * Y; + glm::vec4 const Y7 = glm::eulerAngleYXZ(0.0f, Angle, 0.0f) * Y; + Error += glm::all(glm::epsilonEqual(Y1, Y2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Y1, Y3, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Y1, Y4, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Y1, Y5, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Y1, Y6, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Y1, Y7, 0.00001f)) ? 0 : 1; + + glm::vec4 const Z(0.0f, 0.0f, 1.0f, 1.0f); + glm::vec4 const Z1 = glm::rotate(glm::mat4(1.0f), Angle, X) * Z; + glm::vec4 const Z2 = glm::eulerAngleX(Angle) * Z; + glm::vec4 const Z3 = glm::eulerAngleXY(Angle, 0.0f) * Z; + glm::vec4 const Z4 = glm::eulerAngleYX(0.0f, Angle) * Z; + glm::vec4 const Z5 = glm::eulerAngleXZ(Angle, 0.0f) * Z; + glm::vec4 const Z6 = glm::eulerAngleZX(0.0f, Angle) * Z; + glm::vec4 const Z7 = glm::eulerAngleYXZ(0.0f, Angle, 0.0f) * Z; + Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleX + +namespace test_eulerAngleY +{ + int test() + { + int Error = 0; + + float const Angle(glm::pi() * 0.5f); + glm::vec3 const Y(0.0f, 1.0f, 0.0f); + + glm::vec4 const X(1.0f, 0.0f, 0.0f, 1.0f); + glm::vec4 const X1 = glm::rotate(glm::mat4(1.0f), Angle, Y) * X; + glm::vec4 const X2 = glm::eulerAngleY(Angle) * X; + glm::vec4 const X3 = glm::eulerAngleYX(Angle, 0.0f) * X; + glm::vec4 const X4 = glm::eulerAngleXY(0.0f, Angle) * X; + glm::vec4 const X5 = glm::eulerAngleYZ(Angle, 0.0f) * X; + glm::vec4 const X6 = glm::eulerAngleZY(0.0f, Angle) * X; + glm::vec4 const X7 = glm::eulerAngleYXZ(Angle, 0.0f, 0.0f) * X; + Error += glm::all(glm::epsilonEqual(X1, X2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X3, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X4, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X5, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X6, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X7, 0.00001f)) ? 0 : 1; + + glm::vec4 const Z(0.0f, 0.0f, 1.0f, 1.0f); + glm::vec4 const Z1 = glm::eulerAngleY(Angle) * Z; + glm::vec4 const Z2 = glm::rotate(glm::mat4(1.0f), Angle, Y) * Z; + glm::vec4 const Z3 = glm::eulerAngleYX(Angle, 0.0f) * Z; + glm::vec4 const Z4 = glm::eulerAngleXY(0.0f, Angle) * Z; + glm::vec4 const Z5 = glm::eulerAngleYZ(Angle, 0.0f) * Z; + glm::vec4 const Z6 = glm::eulerAngleZY(0.0f, Angle) * Z; + glm::vec4 const Z7 = glm::eulerAngleYXZ(Angle, 0.0f, 0.0f) * Z; + Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleY + +namespace test_eulerAngleZ +{ + int test() + { + int Error = 0; + + float const Angle(glm::pi() * 0.5f); + glm::vec3 const Z(0.0f, 0.0f, 1.0f); + + glm::vec4 const X(1.0f, 0.0f, 0.0f, 1.0f); + glm::vec4 const X1 = glm::rotate(glm::mat4(1.0f), Angle, Z) * X; + glm::vec4 const X2 = glm::eulerAngleZ(Angle) * X; + glm::vec4 const X3 = glm::eulerAngleZX(Angle, 0.0f) * X; + glm::vec4 const X4 = glm::eulerAngleXZ(0.0f, Angle) * X; + glm::vec4 const X5 = glm::eulerAngleZY(Angle, 0.0f) * X; + glm::vec4 const X6 = glm::eulerAngleYZ(0.0f, Angle) * X; + glm::vec4 const X7 = glm::eulerAngleYXZ(0.0f, 0.0f, Angle) * X; + Error += glm::all(glm::epsilonEqual(X1, X2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X3, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X4, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X5, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X6, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(X1, X7, 0.00001f)) ? 0 : 1; + + glm::vec4 const Y(1.0f, 0.0f, 0.0f, 1.0f); + glm::vec4 const Z1 = glm::rotate(glm::mat4(1.0f), Angle, Z) * Y; + glm::vec4 const Z2 = glm::eulerAngleZ(Angle) * Y; + glm::vec4 const Z3 = glm::eulerAngleZX(Angle, 0.0f) * Y; + glm::vec4 const Z4 = glm::eulerAngleXZ(0.0f, Angle) * Y; + glm::vec4 const Z5 = glm::eulerAngleZY(Angle, 0.0f) * Y; + glm::vec4 const Z6 = glm::eulerAngleYZ(0.0f, Angle) * Y; + glm::vec4 const Z7 = glm::eulerAngleYXZ(0.0f, 0.0f, Angle) * Y; + Error += glm::all(glm::epsilonEqual(Z1, Z2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z3, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z4, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z5, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z6, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(Z1, Z7, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleZ + +namespace test_derivedEulerAngles +{ + bool epsilonEqual(glm::mat4 const& mat1, glm::mat4 const& mat2, glm::mat4::value_type const& epsilon) + { + return glm::all(glm::epsilonEqual(mat1[0], mat2[0], epsilon)) ? + ( + glm::all(glm::epsilonEqual(mat1[1], mat2[1], epsilon)) ? + ( + glm::all(glm::epsilonEqual(mat1[2], mat2[2], epsilon)) ? + ( + glm::all(glm::epsilonEqual(mat1[3], mat2[3], epsilon)) ? true : false + ) : false + ) : false + ) : false; + } + + template + int test(RotationFunc rotationFunc, TestDerivedFunc testDerivedFunc, const glm::vec3& basis) + { + int Error = 0; + + typedef glm::vec3::value_type value; + value const zeroAngle(0.0f); + value const Angle(glm::pi() * 0.75f); + value const negativeAngle(-Angle); + value const zeroAngleVelocity(0.0f); + value const AngleVelocity(glm::pi() * 0.27f); + value const negativeAngleVelocity(-AngleVelocity); + + typedef std::pair AngleAndAngleVelocity; + std::vector testPairs; + testPairs.push_back(AngleAndAngleVelocity(zeroAngle, zeroAngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(zeroAngle, AngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(zeroAngle, negativeAngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(Angle, zeroAngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(Angle, AngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(Angle, negativeAngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(negativeAngle, zeroAngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(negativeAngle, AngleVelocity)); + testPairs.push_back(AngleAndAngleVelocity(negativeAngle, negativeAngleVelocity)); + + for (size_t i = 0, size = testPairs.size(); i < size; ++i) + { + AngleAndAngleVelocity const& pair = testPairs.at(i); + + glm::mat4 const W = glm::matrixCross4(basis * pair.second); + glm::mat4 const rotMt = glm::transpose(rotationFunc(pair.first)); + glm::mat4 const derivedRotM = testDerivedFunc(pair.first, pair.second); + + Error += epsilonEqual(W, derivedRotM * rotMt, 0.00001f) ? 0 : 1; + } + + return Error; + } +}//namespace test_derivedEulerAngles + +namespace test_eulerAngleXY +{ + int test() + { + int Error = 0; + + glm::vec4 const V(1.0f); + + float const AngleX(glm::pi() * 0.5f); + float const AngleY(glm::pi() * 0.25f); + + glm::vec3 const axisX(1.0f, 0.0f, 0.0f); + glm::vec3 const axisY(0.0f, 1.0f, 0.0f); + + glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleX, axisX) * glm::rotate(glm::mat4(1.0f), AngleY, axisY)) * V; + glm::vec4 const V2 = glm::eulerAngleXY(AngleX, AngleY) * V; + glm::vec4 const V3 = glm::eulerAngleX(AngleX) * glm::eulerAngleY(AngleY) * V; + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleXY + +namespace test_eulerAngleYX +{ + int test() + { + int Error = 0; + + glm::vec4 const V(1.0f); + + float const AngleX(glm::pi() * 0.5f); + float const AngleY(glm::pi() * 0.25f); + + glm::vec3 const axisX(1.0f, 0.0f, 0.0f); + glm::vec3 const axisY(0.0f, 1.0f, 0.0f); + + glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleY, axisY) * glm::rotate(glm::mat4(1.0f), AngleX, axisX)) * V; + glm::vec4 const V2 = glm::eulerAngleYX(AngleY, AngleX) * V; + glm::vec4 const V3 = glm::eulerAngleY(AngleY) * glm::eulerAngleX(AngleX) * V; + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleYX + +namespace test_eulerAngleXZ +{ + int test() + { + int Error = 0; + + glm::vec4 const V(1.0f); + + float const AngleX(glm::pi() * 0.5f); + float const AngleZ(glm::pi() * 0.25f); + + glm::vec3 const axisX(1.0f, 0.0f, 0.0f); + glm::vec3 const axisZ(0.0f, 0.0f, 1.0f); + + glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleX, axisX) * glm::rotate(glm::mat4(1.0f), AngleZ, axisZ)) * V; + glm::vec4 const V2 = glm::eulerAngleXZ(AngleX, AngleZ) * V; + glm::vec4 const V3 = glm::eulerAngleX(AngleX) * glm::eulerAngleZ(AngleZ) * V; + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleXZ + +namespace test_eulerAngleZX +{ + int test() + { + int Error = 0; + + glm::vec4 const V(1.0f); + + float const AngleX(glm::pi() * 0.5f); + float const AngleZ(glm::pi() * 0.25f); + + glm::vec3 const axisX(1.0f, 0.0f, 0.0f); + glm::vec3 const axisZ(0.0f, 0.0f, 1.0f); + + glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleZ, axisZ) * glm::rotate(glm::mat4(1.0f), AngleX, axisX)) * V; + glm::vec4 const V2 = glm::eulerAngleZX(AngleZ, AngleX) * V; + glm::vec4 const V3 = glm::eulerAngleZ(AngleZ) * glm::eulerAngleX(AngleX) * V; + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleZX + +namespace test_eulerAngleYZ +{ + int test() + { + int Error = 0; + + glm::vec4 const V(1.0f); + + float const AngleY(glm::pi() * 0.5f); + float const AngleZ(glm::pi() * 0.25f); + + glm::vec3 const axisX(1.0f, 0.0f, 0.0f); + glm::vec3 const axisY(0.0f, 1.0f, 0.0f); + glm::vec3 const axisZ(0.0f, 0.0f, 1.0f); + + glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleY, axisY) * glm::rotate(glm::mat4(1.0f), AngleZ, axisZ)) * V; + glm::vec4 const V2 = glm::eulerAngleYZ(AngleY, AngleZ) * V; + glm::vec4 const V3 = glm::eulerAngleY(AngleY) * glm::eulerAngleZ(AngleZ) * V; + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleYZ + +namespace test_eulerAngleZY +{ + int test() + { + int Error = 0; + + glm::vec4 const V(1.0f); + + float const AngleY(glm::pi() * 0.5f); + float const AngleZ(glm::pi() * 0.25f); + + glm::vec3 const axisX(1.0f, 0.0f, 0.0f); + glm::vec3 const axisY(0.0f, 1.0f, 0.0f); + glm::vec3 const axisZ(0.0f, 0.0f, 1.0f); + + glm::vec4 const V1 = (glm::rotate(glm::mat4(1.0f), AngleZ, axisZ) * glm::rotate(glm::mat4(1.0f), AngleY, axisY)) * V; + glm::vec4 const V2 = glm::eulerAngleZY(AngleZ, AngleY) * V; + glm::vec4 const V3 = glm::eulerAngleZ(AngleZ) * glm::eulerAngleY(AngleY) * V; + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(V1, V3, 0.00001f)) ? 0 : 1; + + return Error; + } +}//namespace test_eulerAngleZY + +namespace test_eulerAngleYXZ +{ + int test() + { + glm::f32 first = 1.046f; + glm::f32 second = 0.52f; + glm::f32 third = -0.785f; + + glm::fmat4 rotationEuler = glm::eulerAngleYXZ(first, second, third); + + glm::fmat4 rotationInvertedY = glm::eulerAngleY(-1.f*first) * glm::eulerAngleX(second) * glm::eulerAngleZ(third); + glm::fmat4 rotationDumb = glm::fmat4(); + rotationDumb = glm::rotate(rotationDumb, first, glm::fvec3(0,1,0)); + rotationDumb = glm::rotate(rotationDumb, second, glm::fvec3(1,0,0)); + rotationDumb = glm::rotate(rotationDumb, third, glm::fvec3(0,0,1)); + + std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler)).c_str()); + std::printf("%s\n", glm::to_string(glm::fmat3(rotationDumb)).c_str()); + std::printf("%s\n", glm::to_string(glm::fmat3(rotationInvertedY)).c_str()); + + std::printf("\nRESIDUAL\n"); + std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler-(rotationDumb))).c_str()); + std::printf("%s\n", glm::to_string(glm::fmat3(rotationEuler-(rotationInvertedY))).c_str()); + + return 0; + } +}//namespace eulerAngleYXZ + +namespace test_eulerAngles +{ + template + int test(TestRotationFunc testRotationFunc, glm::vec3 const& I, glm::vec3 const& J, glm::vec3 const& K) + { + int Error = 0; + + typedef glm::mat4::value_type value; + value const minAngle(-glm::pi()); + value const maxAngle(glm::pi()); + value const maxAngleWithDelta(maxAngle - 0.0000001f); + value const minMidAngle(-glm::pi() * 0.5f); + value const maxMidAngle(glm::pi() * 0.5f); + + std::vector testEulerAngles; + testEulerAngles.push_back(glm::vec3(1.046f, 0.52f, -0.785f)); + testEulerAngles.push_back(glm::vec3(minAngle, minMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, minMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, minMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(minAngle, maxMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, maxMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, maxMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngle, minMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, minMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, minMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, minMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, minMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, maxMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, maxMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, maxMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(minAngle, 0.0f, minAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, 0.0f, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxAngle, maxAngle)); + + for (size_t i = 0, size = testEulerAngles.size(); i < size; ++i) + { + glm::vec3 const& angles = testEulerAngles.at(i); + glm::mat4 const rotationEuler = testRotationFunc(angles.x, angles.y, angles.z); + + glm::mat4 rotationDumb = glm::diagonal4x4(glm::mat4::col_type(1.0f)); + rotationDumb = glm::rotate(rotationDumb, angles.x, I); + rotationDumb = glm::rotate(rotationDumb, angles.y, J); + rotationDumb = glm::rotate(rotationDumb, angles.z, K); + + glm::vec4 const V(1.0f,1.0f,1.0f,1.0f); + glm::vec4 const V1 = rotationEuler * V; + glm::vec4 const V2 = rotationDumb * V; + + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + } + + return Error; + } +}//namespace test_extractsEulerAngles + +namespace test_extractsEulerAngles +{ + template + int test(RotationFunc rotationFunc, TestExtractionFunc testExtractionFunc) + { + int Error = 0; + + typedef glm::mat4::value_type value; + value const minAngle(-glm::pi()); + value const maxAngle(glm::pi()); + value const maxAngleWithDelta(maxAngle - 0.0000001f); + value const minMidAngle(-glm::pi() * 0.5f); + value const maxMidAngle(glm::pi() * 0.5f); + + std::vector testEulerAngles; + testEulerAngles.push_back(glm::vec3(1.046f, 0.52f, -0.785f)); + testEulerAngles.push_back(glm::vec3(minAngle, minMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, minMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, minMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(minAngle, maxMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, maxMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, maxMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngle, minMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, minMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, minMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, minMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, minMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, maxMidAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, maxMidAngle, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngleWithDelta, maxMidAngle, maxAngleWithDelta)); + testEulerAngles.push_back(glm::vec3(minAngle, 0.0f, minAngle)); + testEulerAngles.push_back(glm::vec3(minAngle, 0.0f, maxAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxAngle, minAngle)); + testEulerAngles.push_back(glm::vec3(maxAngle, maxAngle, maxAngle)); + + for (size_t i = 0, size = testEulerAngles.size(); i < size; ++i) + { + glm::vec3 const& angles = testEulerAngles.at(i); + glm::mat4 const rotation = rotationFunc(angles.x, angles.y, angles.z); + + glm::vec3 extractedEulerAngles(0.0f); + testExtractionFunc(rotation, extractedEulerAngles.x, extractedEulerAngles.y, extractedEulerAngles.z); + glm::mat4 const extractedRotation = rotationFunc(extractedEulerAngles.x, extractedEulerAngles.y, extractedEulerAngles.z); + + glm::vec4 const V(1.0f,1.0f,1.0f,1.0f); + glm::vec4 const V1 = rotation * V; + glm::vec4 const V2 = extractedRotation * V; + + Error += glm::all(glm::epsilonEqual(V1, V2, 0.00001f)) ? 0 : 1; + } + + return Error; + } +}//namespace test_extractsEulerAngles + +int main() +{ + int Error = 0; + + typedef glm::mat4::value_type value; + glm::vec3 const X(1.0f, 0.0f, 0.0f); + glm::vec3 const Y(0.0f, 1.0f, 0.0f); + glm::vec3 const Z(0.0f, 0.0f, 1.0f); + + Error += test_eulerAngleX::test(); + Error += test_eulerAngleY::test(); + Error += test_eulerAngleZ::test(); + + Error += test_derivedEulerAngles::test(glm::eulerAngleX, glm::derivedEulerAngleX, X); + Error += test_derivedEulerAngles::test(glm::eulerAngleY, glm::derivedEulerAngleY, Y); + Error += test_derivedEulerAngles::test(glm::eulerAngleZ, glm::derivedEulerAngleZ, Z); + + Error += test_eulerAngleXY::test(); + Error += test_eulerAngleYX::test(); + Error += test_eulerAngleXZ::test(); + Error += test_eulerAngleZX::test(); + Error += test_eulerAngleYZ::test(); + Error += test_eulerAngleZY::test(); + Error += test_eulerAngleYXZ::test(); + + Error += test_eulerAngles::test(glm::eulerAngleXZX, X, Z, X); + Error += test_eulerAngles::test(glm::eulerAngleXYX, X, Y, X); + Error += test_eulerAngles::test(glm::eulerAngleYXY, Y, X, Y); + Error += test_eulerAngles::test(glm::eulerAngleYZY, Y, Z, Y); + Error += test_eulerAngles::test(glm::eulerAngleZYZ, Z, Y, Z); + Error += test_eulerAngles::test(glm::eulerAngleZXZ, Z, X, Z); + Error += test_eulerAngles::test(glm::eulerAngleXZY, X, Z, Y); + Error += test_eulerAngles::test(glm::eulerAngleYZX, Y, Z, X); + Error += test_eulerAngles::test(glm::eulerAngleZYX, Z, Y, X); + Error += test_eulerAngles::test(glm::eulerAngleZXY, Z, X, Y); + + Error += test_extractsEulerAngles::test(glm::eulerAngleYXZ, glm::extractEulerAngleYXZ); + Error += test_extractsEulerAngles::test(glm::eulerAngleXZX, glm::extractEulerAngleXZX); + Error += test_extractsEulerAngles::test(glm::eulerAngleXYX, glm::extractEulerAngleXYX); + Error += test_extractsEulerAngles::test(glm::eulerAngleYXY, glm::extractEulerAngleYXY); + Error += test_extractsEulerAngles::test(glm::eulerAngleYZY, glm::extractEulerAngleYZY); + Error += test_extractsEulerAngles::test(glm::eulerAngleZYZ, glm::extractEulerAngleZYZ); + Error += test_extractsEulerAngles::test(glm::eulerAngleZXZ, glm::extractEulerAngleZXZ); + Error += test_extractsEulerAngles::test(glm::eulerAngleXZY, glm::extractEulerAngleXZY); + Error += test_extractsEulerAngles::test(glm::eulerAngleYZX, glm::extractEulerAngleYZX); + Error += test_extractsEulerAngles::test(glm::eulerAngleZYX, glm::extractEulerAngleZYX); + Error += test_extractsEulerAngles::test(glm::eulerAngleZXY, glm::extractEulerAngleZXY); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_extend.cpp b/vendor/glm/test/gtx/gtx_extend.cpp new file mode 100644 index 0000000..0c37df5 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_extend.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_extended_min_max.cpp b/vendor/glm/test/gtx/gtx_extended_min_max.cpp new file mode 100644 index 0000000..3d20f10 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_extended_min_max.cpp @@ -0,0 +1,101 @@ +#define GLM_ENABLE_EXPERIMENTAL + +#include +#include +#include +#include +#include + +// This file has divisions by zero to test isnan +#if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(disable : 4723) +#endif + +namespace fmin_ +{ + static int test() + { + int Error = 0; + + float Zero_f = 0.0f; + glm::vec1 A0 = glm::fmin(glm::vec1(1), glm::vec1(Zero_f / 0.0f)); + Error += glm::equal(A0.x, 1.0f, glm::epsilon()) ? 0 : 1; + + glm::vec1 A1 = glm::fmin(glm::vec1(Zero_f / 0.0f), glm::vec1(1)); + Error += glm::equal(A1.x, 1.0f, glm::epsilon()) ? 0 : 1; + + glm::vec2 B0 = glm::fmin(glm::vec2(1), glm::vec2(1)); + glm::vec2 B1 = glm::fmin(glm::vec2(1), 1.0f); + bool B2 = glm::all(glm::equal(B0, B1, glm::epsilon())); + Error += B2 ? 0 : 1; + + glm::vec3 C0 = glm::fmin(glm::vec3(1), glm::vec3(1)); + glm::vec3 C1 = glm::fmin(glm::vec3(1), 1.0f); + bool C2 = glm::all(glm::equal(C0, C1, glm::epsilon())); + Error += C2 ? 0 : 1; + + glm::vec4 D0 = glm::fmin(glm::vec4(1), glm::vec4(1)); + glm::vec4 D1 = glm::fmin(glm::vec4(1), 1.0f); + bool D2 = glm::all(glm::equal(D0, D1, glm::epsilon())); + Error += D2 ? 0 : 1; + + return Error; + } +}//namespace fmin_ + +namespace fmax_ +{ + static int test() + { + int Error = 0; + + float Zero_f = 0.0f; + glm::vec1 A0 = glm::fmax(glm::vec1(1), glm::vec1(Zero_f / 0.0f)); + Error += glm::equal(A0.x, 1.0f, glm::epsilon()) ? 0 : 1; + + glm::vec1 A1 = glm::fmax(glm::vec1(Zero_f / 0.0f), glm::vec1(1)); + Error += glm::equal(A0.x, 1.0f, glm::epsilon()) ? 0 : 1; + + glm::vec2 B0 = glm::fmax(glm::vec2(1), glm::vec2(1)); + glm::vec2 B1 = glm::fmax(glm::vec2(1), 1.0f); + bool B2 = glm::all(glm::equal(B0, B1, glm::epsilon())); + Error += B2 ? 0 : 1; + + glm::vec3 C0 = glm::fmax(glm::vec3(1), glm::vec3(1)); + glm::vec3 C1 = glm::fmax(glm::vec3(1), 1.0f); + bool C2 = glm::all(glm::equal(C0, C1, glm::epsilon())); + Error += C2 ? 0 : 1; + + glm::vec4 D0 = glm::fmax(glm::vec4(1), glm::vec4(1)); + glm::vec4 D1 = glm::fmax(glm::vec4(1), 1.0f); + bool D2 = glm::all(glm::equal(D0, D1, glm::epsilon())); + Error += D2 ? 0 : 1; + + return Error; + } +}//namespace fmax_ + +namespace fclamp_ +{ + static int test() + { + int Error = 0; + + float Zero_f = 0.0f; + glm::vec1 A0 = glm::fclamp(glm::vec1(1), glm::vec1(Zero_f / 0.0f), glm::vec1(2.0f)); + Error += glm::equal(A0.x, 1.0f, glm::epsilon()) ? 0 : 1; + + return Error; + } +}//namespace fclamp_ + +int main() +{ + int Error = 0; + + Error += fmin_::test(); + Error += fmax_::test(); + Error += fclamp_::test(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_extented_min_max.cpp b/vendor/glm/test/gtx/gtx_extented_min_max.cpp new file mode 100644 index 0000000..c8c7847 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_extented_min_max.cpp @@ -0,0 +1,39 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @file test/gtx/gtx_extented_min_max.cpp +/// @date 2013-10-25 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_exterior_product.cpp b/vendor/glm/test/gtx/gtx_exterior_product.cpp new file mode 100644 index 0000000..a02c983 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_exterior_product.cpp @@ -0,0 +1,14 @@ +#include +#include +#include + +int main() +{ + int Error = 0; + + float const f = glm::cross(glm::vec2(1.0f, 1.0f), glm::vec2(1.0f, 1.0f)); + Error += glm::epsilonEqual(f, 0.0f, 0.001f) ? 0 : 1; + + return Error; +} + diff --git a/vendor/glm/test/gtx/gtx_fast_exponential.cpp b/vendor/glm/test/gtx/gtx_fast_exponential.cpp new file mode 100644 index 0000000..341e26e --- /dev/null +++ b/vendor/glm/test/gtx/gtx_fast_exponential.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_fast_square_root.cpp b/vendor/glm/test/gtx/gtx_fast_square_root.cpp new file mode 100644 index 0000000..80d7fe4 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_fast_square_root.cpp @@ -0,0 +1,45 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include + +int test_fastInverseSqrt() +{ + int Error = 0; + + Error += glm::epsilonEqual(glm::fastInverseSqrt(1.0f), 1.0f, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(glm::fastInverseSqrt(1.0), 1.0, 0.01) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(glm::fastInverseSqrt(glm::vec2(1.0f)), glm::vec2(1.0f), 0.01f)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(glm::fastInverseSqrt(glm::dvec3(1.0)), glm::dvec3(1.0), 0.01)) ? 0 : 1; + Error += glm::all(glm::epsilonEqual(glm::fastInverseSqrt(glm::dvec4(1.0)), glm::dvec4(1.0), 0.01)) ? 0 : 1; + + return Error; +} + +int test_fastDistance() +{ + int Error = 0; + + float const A = glm::fastDistance(0.0f, 1.0f); + float const B = glm::fastDistance(glm::vec2(0.0f), glm::vec2(1.0f, 0.0f)); + float const C = glm::fastDistance(glm::vec3(0.0f), glm::vec3(1.0f, 0.0f, 0.0f)); + float const D = glm::fastDistance(glm::vec4(0.0f), glm::vec4(1.0f, 0.0f, 0.0f, 0.0f)); + + Error += glm::epsilonEqual(A, 1.0f, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(B, 1.0f, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C, 1.0f, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(D, 1.0f, 0.01f) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_fastInverseSqrt(); + Error += test_fastDistance(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_fast_trigonometry.cpp b/vendor/glm/test/gtx/gtx_fast_trigonometry.cpp new file mode 100644 index 0000000..8bf86ba --- /dev/null +++ b/vendor/glm/test/gtx/gtx_fast_trigonometry.cpp @@ -0,0 +1,564 @@ +#include + +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fastCos +{ + int perf(bool NextFloat) + { + const float begin = -glm::pi(); + const float end = glm::pi(); + float result = 0.f; + + const std::clock_t timestamp1 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::fastCos(i); + + const std::clock_t timestamp2 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::cos(i); + + const std::clock_t timestamp3 = std::clock(); + const std::clock_t time_fast = timestamp2 - timestamp1; + const std::clock_t time_default = timestamp3 - timestamp2; + std::printf("fastCos Time %d clocks\n", static_cast(time_fast)); + std::printf("cos Time %d clocks\n", static_cast(time_default)); + + return time_fast <= time_default ? 0 : 1; + } +}//namespace fastCos + +namespace fastSin +{ + /* + float sin(float x) { + float temp; + temp = (x + M_PI) / ((2 * M_PI) - M_PI); + return limited_sin((x + M_PI) - ((2 * M_PI) - M_PI) * temp)); + } + */ + + int perf(bool NextFloat) + { + const float begin = -glm::pi(); + const float end = glm::pi(); + float result = 0.f; + + const std::clock_t timestamp1 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::fastSin(i); + + const std::clock_t timestamp2 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::sin(i); + + const std::clock_t timestamp3 = std::clock(); + const std::clock_t time_fast = timestamp2 - timestamp1; + const std::clock_t time_default = timestamp3 - timestamp2; + std::printf("fastSin Time %d clocks\n", static_cast(time_fast)); + std::printf("sin Time %d clocks\n", static_cast(time_default)); + + return time_fast <= time_default ? 0 : 1; + } +}//namespace fastSin + +namespace fastTan +{ + int perf(bool NextFloat) + { + const float begin = -glm::pi(); + const float end = glm::pi(); + float result = 0.f; + + const std::clock_t timestamp1 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::fastTan(i); + + const std::clock_t timestamp2 = std::clock(); + for (float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::tan(i); + + const std::clock_t timestamp3 = std::clock(); + const std::clock_t time_fast = timestamp2 - timestamp1; + const std::clock_t time_default = timestamp3 - timestamp2; + std::printf("fastTan Time %d clocks\n", static_cast(time_fast)); + std::printf("tan Time %d clocks\n", static_cast(time_default)); + + return time_fast <= time_default ? 0 : 1; + } +}//namespace fastTan + +namespace fastAcos +{ + int perf(bool NextFloat) + { + const float begin = -glm::pi(); + const float end = glm::pi(); + float result = 0.f; + + const std::clock_t timestamp1 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::fastAcos(i); + + const std::clock_t timestamp2 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::acos(i); + + const std::clock_t timestamp3 = std::clock(); + const std::clock_t time_fast = timestamp2 - timestamp1; + const std::clock_t time_default = timestamp3 - timestamp2; + + std::printf("fastAcos Time %d clocks\n", static_cast(time_fast)); + std::printf("acos Time %d clocks\n", static_cast(time_default)); + + return time_fast <= time_default ? 0 : 1; + } +}//namespace fastAcos + +namespace fastAsin +{ + int perf(bool NextFloat) + { + const float begin = -glm::pi(); + const float end = glm::pi(); + float result = 0.f; + const std::clock_t timestamp1 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::fastAsin(i); + const std::clock_t timestamp2 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::asin(i); + const std::clock_t timestamp3 = std::clock(); + const std::clock_t time_fast = timestamp2 - timestamp1; + const std::clock_t time_default = timestamp3 - timestamp2; + std::printf("fastAsin Time %d clocks\n", static_cast(time_fast)); + std::printf("asin Time %d clocks\n", static_cast(time_default)); + + return time_fast <= time_default ? 0 : 1; + } +}//namespace fastAsin + +namespace fastAtan +{ + int perf(bool NextFloat) + { + const float begin = -glm::pi(); + const float end = glm::pi(); + float result = 0.f; + const std::clock_t timestamp1 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::fastAtan(i); + const std::clock_t timestamp2 = std::clock(); + for(float i = begin; i < end; i = NextFloat ? glm::nextFloat(i) : i += 0.1f) + result = glm::atan(i); + const std::clock_t timestamp3 = std::clock(); + const std::clock_t time_fast = timestamp2 - timestamp1; + const std::clock_t time_default = timestamp3 - timestamp2; + std::printf("fastAtan Time %d clocks\n", static_cast(time_fast)); + std::printf("atan Time %d clocks\n", static_cast(time_default)); + + return time_fast <= time_default ? 0 : 1; + } +}//namespace fastAtan + +namespace taylorCos +{ + using glm::qualifier; + using glm::length_t; + + glm::vec4 const AngleShift(0.0f, glm::half_pi(), glm::pi(), glm::three_over_two_pi()); + + template + GLM_FUNC_QUALIFIER glm::vec taylorSeriesNewCos(glm::vec const& x) + { + glm::vec const Powed2(x * x); + glm::vec const Powed4(Powed2 * Powed2); + glm::vec const Powed6(Powed4 * Powed2); + glm::vec const Powed8(Powed4 * Powed4); + + return static_cast(1) + - Powed2 * static_cast(0.5) + + Powed4 * static_cast(0.04166666666666666666666666666667) + - Powed6 * static_cast(0.00138888888888888888888888888889) + + Powed8 * static_cast(2.4801587301587301587301587301587e-5); + } + + template + GLM_FUNC_QUALIFIER glm::vec taylorSeriesNewCos6(glm::vec const& x) + { + glm::vec const Powed2(x * x); + glm::vec const Powed4(Powed2 * Powed2); + glm::vec const Powed6(Powed4 * Powed2); + + return static_cast(1) + - Powed2 * static_cast(0.5) + + Powed4 * static_cast(0.04166666666666666666666666666667) + - Powed6 * static_cast(0.00138888888888888888888888888889); + } + + template + GLM_FUNC_QUALIFIER glm::vec fastAbs(glm::vec x) + { + int* Pointer = reinterpret_cast(&x[0]); + Pointer[0] &= 0x7fffffff; + Pointer[1] &= 0x7fffffff; + Pointer[2] &= 0x7fffffff; + Pointer[3] &= 0x7fffffff; + return x; + } + + template + GLM_FUNC_QUALIFIER glm::vec fastCosNew(glm::vec const& x) + { + glm::vec const Angle0_PI(fastAbs(fmod(x + glm::pi(), glm::two_pi()) - glm::pi())); + return taylorSeriesNewCos6(x); +/* + vec const FirstQuarterPi(lessThanEqual(Angle0_PI, vec(glm::half_pi()))); + + vec const RevertAngle(mix(vec(glm::pi()), vec(0), FirstQuarterPi)); + vec const ReturnSign(mix(vec(-1), vec(1), FirstQuarterPi)); + vec const SectionAngle(RevertAngle - Angle0_PI); + + return ReturnSign * taylorSeriesNewCos(SectionAngle); +*/ + } + + int perf_fastCosNew(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = fastCosNew(AngleShift + glm::vec4(Begin + Steps * static_cast(i))); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("fastCosNew %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1; + return Error; + } + + template + GLM_FUNC_QUALIFIER glm::vec deterministic_fmod(glm::vec const& x, T y) + { + return x - y * trunc(x / y); + } + + template + GLM_FUNC_QUALIFIER glm::vec fastCosDeterminisctic(glm::vec const& x) + { + glm::vec const Angle0_PI(abs(deterministic_fmod(x + glm::pi(), glm::two_pi()) - glm::pi())); + glm::vec const FirstQuarterPi(lessThanEqual(Angle0_PI, glm::vec(glm::half_pi()))); + + glm::vec const RevertAngle(mix(glm::vec(glm::pi()), glm::vec(0), FirstQuarterPi)); + glm::vec const ReturnSign(mix(glm::vec(-1), glm::vec(1), FirstQuarterPi)); + glm::vec const SectionAngle(RevertAngle - Angle0_PI); + + return ReturnSign * taylorSeriesNewCos(SectionAngle); + } + + int perf_fastCosDeterminisctic(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = taylorCos::fastCosDeterminisctic(AngleShift + glm::vec4(Begin + Steps * static_cast(i))); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("fastCosDeterminisctic %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1; + return Error; + } + + template + GLM_FUNC_QUALIFIER glm::vec taylorSeriesRefCos(glm::vec const& x) + { + return static_cast(1) + - (x * x) / glm::factorial(static_cast(2)) + + (x * x * x * x) / glm::factorial(static_cast(4)) + - (x * x * x * x * x * x) / glm::factorial(static_cast(6)) + + (x * x * x * x * x * x * x * x) / glm::factorial(static_cast(8)); + } + + template + GLM_FUNC_QUALIFIER glm::vec fastRefCos(glm::vec const& x) + { + glm::vec const Angle0_PI(glm::abs(fmod(x + glm::pi(), glm::two_pi()) - glm::pi())); +// return taylorSeriesRefCos(Angle0_PI); + + glm::vec const FirstQuarterPi(lessThanEqual(Angle0_PI, glm::vec(glm::half_pi()))); + + glm::vec const RevertAngle(mix(glm::vec(glm::pi()), glm::vec(0), FirstQuarterPi)); + glm::vec const ReturnSign(mix(glm::vec(-1), glm::vec(1), FirstQuarterPi)); + glm::vec const SectionAngle(RevertAngle - Angle0_PI); + + return ReturnSign * taylorSeriesRefCos(SectionAngle); + } + + int perf_fastCosRef(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = taylorCos::fastRefCos(AngleShift + glm::vec4(Begin + Steps * static_cast(i))); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("fastCosRef %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1; + return Error; + } + + int perf_fastCosOld(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = glm::fastCos(AngleShift + glm::vec4(Begin + Steps * static_cast(i))); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("fastCosOld %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1; + return Error; + } + + int perf_cos(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = glm::cos(AngleShift + glm::vec4(Begin + Steps * static_cast(i))); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("cos %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i].x >= -1.0f && Results[i].x <= 1.0f ? 0 : 1; + return Error; + } + + int perf(std::size_t const Samples) + { + int Error = 0; + + float const Begin = -glm::pi(); + float const End = glm::pi(); + + Error += perf_cos(Begin, End, Samples); + Error += perf_fastCosOld(Begin, End, Samples); + Error += perf_fastCosRef(Begin, End, Samples); + //Error += perf_fastCosNew(Begin, End, Samples); + Error += perf_fastCosDeterminisctic(Begin, End, Samples); + + return Error; + } + + int test() + { + int Error = 0; + + //for(float Angle = -4.0f * glm::pi(); Angle < 4.0f * glm::pi(); Angle += 0.1f) + //for(float Angle = -720.0f; Angle < 720.0f; Angle += 0.1f) + for(float Angle = 0.0f; Angle < 180.0f; Angle += 0.1f) + { + float const modAngle = std::fmod(glm::abs(Angle), 360.f); + assert(modAngle >= 0.0f && modAngle <= 360.f); + float const radAngle = glm::radians(modAngle); + float const Cos0 = std::cos(radAngle); + + float const Cos1 = taylorCos::fastRefCos(glm::fvec1(radAngle)).x; + Error += glm::abs(Cos1 - Cos0) < 0.1f ? 0 : 1; + + //float const Cos2 = taylorCos::fastCosNew(glm::fvec1(radAngle)).x; + //Error += glm::abs(Cos2 - Cos0) < 0.1f ? 0 : 1; + + assert(!Error); + } + + return Error; + } +}//namespace taylorCos + +namespace taylor2 +{ + glm::vec4 const AngleShift(0.0f, glm::pi() * 0.5f, glm::pi() * 1.0f, glm::pi() * 1.5f); + + float taylorCosA(float x) + { + return 1.f + - (x * x) * (1.f / 2.f) + + (x * x * x * x) * (1.f / 24.f) + - (x * x * x * x * x * x) * (1.f / 720.f) + + (x * x * x * x * x * x * x * x) * (1.f / 40320.f); + } + + float taylorCosB(float x) + { + return 1.f + - (x * x) * (1.f / 2.f) + + (x * x * x * x) * (1.f / 24.f) + - (x * x * x * x * x * x) * (1.f / 720.f) + + (x * x * x * x * x * x * x * x) * (1.f / 40320.f); + } + + float taylorCosC(float x) + { + return 1.f + - (x * x) * (1.f / 2.f) + + ((x * x) * (x * x)) * (1.f / 24.f) + - (((x * x) * (x * x)) * (x * x)) * (1.f / 720.f) + + (((x * x) * (x * x)) * ((x * x) * (x * x))) * (1.f / 40320.f); + } + + int perf_taylorCosA(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = taylorCosA(AngleShift.x + Begin + Steps * static_cast(i)); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("taylorCosA %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i] >= -1.0f && Results[i] <= 1.0f ? 0 : 1; + return Error; + } + + int perf_taylorCosB(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = taylorCosB(AngleShift.x + Begin + Steps * static_cast(i)); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("taylorCosB %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i] >= -1.0f && Results[i] <= 1.0f ? 0 : 1; + return Error; + } + + int perf_taylorCosC(float Begin, float End, std::size_t Samples) + { + std::vector Results; + Results.resize(Samples); + + float const Steps = (End - Begin) / static_cast(Samples); + + std::clock_t const TimeStampBegin = std::clock(); + + for(std::size_t i = 0; i < Samples; ++i) + Results[i] = taylorCosC(AngleShift.x + Begin + Steps * static_cast(i)); + + std::clock_t const TimeStampEnd = std::clock(); + + std::printf("taylorCosC %d clocks\n", static_cast(TimeStampEnd - TimeStampBegin)); + + int Error = 0; + for(std::size_t i = 0; i < Samples; ++i) + Error += Results[i] >= -1.0f && Results[i] <= 1.0f ? 0 : 1; + return Error; + } + + int perf(std::size_t Samples) + { + int Error = 0; + + float const Begin = -glm::pi(); + float const End = glm::pi(); + + Error += perf_taylorCosA(Begin, End, Samples); + Error += perf_taylorCosB(Begin, End, Samples); + Error += perf_taylorCosC(Begin, End, Samples); + + return Error; + } + +}//namespace taylor2 + +int main() +{ + int Error(0); + + Error += ::taylor2::perf(1000); + Error += ::taylorCos::test(); + Error += ::taylorCos::perf(1000); + +# ifdef NDEBUG + ::fastCos::perf(false); + ::fastSin::perf(false); + ::fastTan::perf(false); + ::fastAcos::perf(false); + ::fastAsin::perf(false); + ::fastAtan::perf(false); +# endif//NDEBUG + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_functions.cpp b/vendor/glm/test/gtx/gtx_functions.cpp new file mode 100644 index 0000000..48a6af0 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_functions.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +int test_gauss_1d() +{ + int Error = 0; + + std::vector Result(20); + for(std::size_t i = 0, n = Result.size(); i < n; ++i) + Result[i] = glm::gauss(static_cast(i) * 0.1f, 0.0f, 1.0f); + + return Error; +} + +int test_gauss_2d() +{ + int Error = 0; + + std::vector Result(20); + for(std::size_t i = 0, n = Result.size(); i < n; ++i) + Result[i] = glm::gauss(glm::vec2(static_cast(i)) * 0.1f, glm::vec2(0.0f), glm::vec2(1.0f)); + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_gauss_1d(); + Error += test_gauss_2d(); + + return Error; +} + diff --git a/vendor/glm/test/gtx/gtx_gradient_paint.cpp b/vendor/glm/test/gtx/gtx_gradient_paint.cpp new file mode 100644 index 0000000..01f521b --- /dev/null +++ b/vendor/glm/test/gtx/gtx_gradient_paint.cpp @@ -0,0 +1,34 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int test_radialGradient() +{ + int Error = 0; + + float Gradient = glm::radialGradient(glm::vec2(0), 1.0f, glm::vec2(1), glm::vec2(0.5)); + Error += Gradient != 0.0f ? 0 : 1; + + return Error; +} + +int test_linearGradient() +{ + int Error = 0; + + float Gradient = glm::linearGradient(glm::vec2(0), glm::vec2(1), glm::vec2(0.5)); + Error += Gradient != 0.0f ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_radialGradient(); + Error += test_linearGradient(); + + return Error; +} + + diff --git a/vendor/glm/test/gtx/gtx_handed_coordinate_space.cpp b/vendor/glm/test/gtx/gtx_handed_coordinate_space.cpp new file mode 100644 index 0000000..e417688 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_handed_coordinate_space.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_int_10_10_10_2.cpp b/vendor/glm/test/gtx/gtx_int_10_10_10_2.cpp new file mode 100644 index 0000000..ab59bb2 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_int_10_10_10_2.cpp @@ -0,0 +1,18 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2013-10-25 +// Updated : 2013-10-25 +// Licence : This source is under MIT licence +// File : test/gtx/associated_min_max.cpp +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_integer.cpp b/vendor/glm/test/gtx/gtx_integer.cpp new file mode 100644 index 0000000..4c4225d --- /dev/null +++ b/vendor/glm/test/gtx/gtx_integer.cpp @@ -0,0 +1,108 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +/* +int test_floor_log2() +{ + int Error = 0; + + for(std::size_t i = 1; i < 1000000; ++i) + { + glm::uint A = glm::floor_log2(glm::uint(i)); + glm::uint B = glm::uint(glm::floor(glm::log2(double(i)))); // Will fail with float, lack of accuracy + + Error += A == B ? 0 : 1; + assert(!Error); + } + + return Error; +} +*/ +int test_log2() +{ + int Error = 0; + + for(std::size_t i = 1; i < 24; ++i) + { + glm::uint A = glm::log2(glm::uint(1 << i)); + glm::uint B = glm::uint(glm::log2(double(1 << i))); + + //Error += glm::equalEpsilon(double(A), B, 1.0) ? 0 : 1; + Error += glm::abs(double(A) - B) <= 24 ? 0 : 1; + assert(!Error); + + std::printf("Log2(%d) error A=%d, B=%d\n", 1 << i, A, B); + } + + std::printf("log2 error=%d\n", Error); + + return Error; +} + +int test_nlz() +{ + int Error = 0; + + for(glm::uint i = 1; i < glm::uint(33); ++i) + Error += glm::nlz(i) == glm::uint(31u) - glm::findMSB(i) ? 0 : 1; + //printf("%d, %d\n", glm::nlz(i), 31u - glm::findMSB(i)); + + return Error; +} + +int test_pow_uint() +{ + int Error = 0; + + glm::uint const p0 = glm::pow(2u, 0u); + Error += p0 == 1u ? 0 : 1; + + glm::uint const p1 = glm::pow(2u, 1u); + Error += p1 == 2u ? 0 : 1; + + glm::uint const p2 = glm::pow(2u, 2u); + Error += p2 == 4u ? 0 : 1; + + return Error; +} + +int test_pow_int() +{ + int Error = 0; + + int const p0 = glm::pow(2, 0u); + Error += p0 == 1 ? 0 : 1; + + int const p1 = glm::pow(2, 1u); + Error += p1 == 2 ? 0 : 1; + + int const p2 = glm::pow(2, 2u); + Error += p2 == 4 ? 0 : 1; + + int const p0n = glm::pow(-2, 0u); + Error += p0n == -1 ? 0 : 1; + + int const p1n = glm::pow(-2, 1u); + Error += p1n == -2 ? 0 : 1; + + int const p2n = glm::pow(-2, 2u); + Error += p2n == 4 ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_nlz(); +// Error += test_floor_log2(); + Error += test_log2(); + Error += test_pow_uint(); + Error += test_pow_int(); + + return Error; +} + diff --git a/vendor/glm/test/gtx/gtx_intersect.cpp b/vendor/glm/test/gtx/gtx_intersect.cpp new file mode 100644 index 0000000..c4a1b2a --- /dev/null +++ b/vendor/glm/test/gtx/gtx_intersect.cpp @@ -0,0 +1,88 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +int test_intersectRayPlane() +{ + int Error = 0; + glm::vec3 const PlaneOrigin(0, 0, 1); + glm::vec3 const PlaneNormal(0, 0, -1); + glm::vec3 const RayOrigin(0, 0, 0); + glm::vec3 const RayDir(0, 0, 1); + + // check that inversion of the plane normal has no effect + { + float Distance = 0; + bool const Result = glm::intersectRayPlane(RayOrigin, RayDir, PlaneOrigin, PlaneNormal, Distance); + Error += glm::abs(Distance - 1.f) <= std::numeric_limits::epsilon() ? 0 : 1; + Error += Result ? 0 : 1; + } + { + float Distance = 0; + bool const Result = glm::intersectRayPlane(RayOrigin, RayDir, PlaneOrigin, -1.f * PlaneNormal, Distance); + Error += glm::abs(Distance - 1.f) <= std::numeric_limits::epsilon() ? 0 : 1; + Error += Result ? 0 : 1; + } + + // check if plane is before of behind the ray origin + { + float Distance = 9.9999f; // value should not be changed + bool const Result = glm::intersectRayPlane(RayOrigin, RayDir, -1.f * PlaneOrigin, PlaneNormal, Distance); + Error += glm::abs(Distance - 9.9999f) <= std::numeric_limits::epsilon() ? 0 : 1; + Error += Result ? 1 : 0; // there is no intersection in front of the ray origin, only behind + } + + return Error; +} + +int test_intersectRayTriangle() +{ + int Error = 0; + + glm::vec3 const Orig(0, 0, 2); + glm::vec3 const Dir(0, 0, -1); + glm::vec3 const Vert0(0, 0, 0); + glm::vec3 const Vert1(-1, -1, 0); + glm::vec3 const Vert2(1, -1, 0); + glm::vec2 BaryPosition(0); + float Distance = 0; + + bool const Result = glm::intersectRayTriangle(Orig, Dir, Vert0, Vert1, Vert2, BaryPosition, Distance); + + Error += glm::all(glm::epsilonEqual(BaryPosition, glm::vec2(0), std::numeric_limits::epsilon())) ? 0 : 1; + Error += glm::abs(Distance - 2.f) <= std::numeric_limits::epsilon() ? 0 : 1; + Error += Result ? 0 : 1; + + return Error; +} + +int test_intersectLineTriangle() +{ + int Error = 0; + + glm::vec3 const Orig(0, 0, 2); + glm::vec3 const Dir(0, 0, -1); + glm::vec3 const Vert0(0, 0, 0); + glm::vec3 const Vert1(-1, -1, 0); + glm::vec3 const Vert2(1, -1, 0); + glm::vec3 Position(2.0f, 0.0f, 0.0f); + + bool const Result = glm::intersectLineTriangle(Orig, Dir, Vert0, Vert1, Vert2, Position); + + Error += glm::all(glm::epsilonEqual(Position, glm::vec3(2.0f, 0.0f, 0.0f), std::numeric_limits::epsilon())) ? 0 : 1; + Error += Result ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_intersectRayPlane(); + Error += test_intersectRayTriangle(); + Error += test_intersectLineTriangle(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_io.cpp b/vendor/glm/test/gtx/gtx_io.cpp new file mode 100644 index 0000000..7d90fd7 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_io.cpp @@ -0,0 +1,186 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#if GLM_LANG & GLM_LANG_CXXMS_FLAG +#include +#include +#include +#include +#include + +namespace +{ + template + std::basic_ostream& operator<<(std::basic_ostream& os, glm::qualifier const& a) + { + typename std::basic_ostream::sentry const cerberus(os); + + if (cerberus) + { + switch (a) { + case glm::highp: os << "uhi"; break; + case glm::mediump: os << "umd"; break; + case glm::lowp: os << "ulo"; break; +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + case glm::aligned_highp: os << "ahi"; break; + case glm::aligned_mediump: os << "amd"; break; + case glm::aligned_lowp: os << "alo"; break; +# endif + } + } + + return os; + } + + template + std::basic_string type_name(std::basic_ostream&, T const&) + { + std::basic_ostringstream ostr; + + if (typeid(T) == typeid(glm::qua)) { ostr << "quat"; } + else if (typeid(T) == typeid(glm::vec<2, U,P>)) { ostr << "vec2"; } + else if (typeid(T) == typeid(glm::vec<3, U,P>)) { ostr << "vec3"; } + else if (typeid(T) == typeid(glm::vec<4, U,P>)) { ostr << "vec4"; } + else if (typeid(T) == typeid(glm::mat<2, 2, U,P>)) { ostr << "mat2x2"; } + else if (typeid(T) == typeid(glm::mat<2, 3, U,P>)) { ostr << "mat2x3"; } + else if (typeid(T) == typeid(glm::mat<2, 4, U,P>)) { ostr << "mat2x4"; } + else if (typeid(T) == typeid(glm::mat<3, 2, U,P>)) { ostr << "mat3x2"; } + else if (typeid(T) == typeid(glm::mat<3, 3, U,P>)) { ostr << "mat3x3"; } + else if (typeid(T) == typeid(glm::mat<3, 4, U,P>)) { ostr << "mat3x4"; } + else if (typeid(T) == typeid(glm::mat<4, 2, U,P>)) { ostr << "mat4x2"; } + else if (typeid(T) == typeid(glm::mat<4, 3, U,P>)) { ostr << "mat4x3"; } + else if (typeid(T) == typeid(glm::mat<4, 4, U,P>)) { ostr << "mat4x4"; } + else { ostr << "unknown"; } + + ostr << '<' << typeid(U).name() << ',' << P << '>'; + + return ostr.str(); + } +} // namespace { + +template +int test_io_quat(OS& os) +{ + os << '\n' << typeid(OS).name() << '\n'; + + glm::qua const q(1, 0, 0, 0); + + { + glm::io::basic_format_saver const iofs(os); + + os << glm::io::precision(2) << glm::io::width(1 + 2 + 1 + 2) + << type_name(os, q) << ": " << q << '\n'; + } + + { + glm::io::basic_format_saver const iofs(os); + + os << glm::io::unformatted + << type_name(os, q) << ": " << q << '\n'; + } + + return 0; +} + +template +int test_io_vec(OS& os) +{ + os << '\n' << typeid(OS).name() << '\n'; + + glm::vec<2, T,P> const v2(0, 1); + glm::vec<3, T,P> const v3(2, 3, 4); + glm::vec<4, T,P> const v4(5, 6, 7, 8); + + os << type_name(os, v2) << ": " << v2 << '\n' + << type_name(os, v3) << ": " << v3 << '\n' + << type_name(os, v4) << ": " << v4 << '\n'; + + glm::io::basic_format_saver const iofs(os); + + os << glm::io::precision(2) << glm::io::width(1 + 2 + 1 + 2) + << type_name(os, v2) << ": " << v2 << '\n' + << type_name(os, v3) << ": " << v3 << '\n' + << type_name(os, v4) << ": " << v4 << '\n'; + + return 0; +} + +template +int test_io_mat(OS& os, glm::io::order_type otype) +{ + os << '\n' << typeid(OS).name() << '\n'; + + glm::vec<2, T,P> const v2_1( 0, 1); + glm::vec<2, T,P> const v2_2( 2, 3); + glm::vec<2, T,P> const v2_3( 4, 5); + glm::vec<2, T,P> const v2_4( 6, 7); + glm::vec<3, T,P> const v3_1( 8, 9, 10); + glm::vec<3, T,P> const v3_2(11, 12, 13); + glm::vec<3, T,P> const v3_3(14, 15, 16); + glm::vec<3, T,P> const v3_4(17, 18, 19); + glm::vec<4, T,P> const v4_1(20, 21, 22, 23); + glm::vec<4, T,P> const v4_2(24, 25, 26, 27); + glm::vec<4, T,P> const v4_3(28, 29, 30, 31); + glm::vec<4, T,P> const v4_4(32, 33, 34, 35); + + glm::io::basic_format_saver const iofs(os); + + os << glm::io::precision(2) << glm::io::width(1 + 2 + 1 + 2) + << glm::io::order(otype) + << "mat2x2<" << typeid(T).name() << ',' << P << ">: " << glm::mat<2, 2, T,P>(v2_1, v2_2) << '\n' + << "mat2x3<" << typeid(T).name() << ',' << P << ">: " << glm::mat<2, 3, T,P>(v3_1, v3_2) << '\n' + << "mat2x4<" << typeid(T).name() << ',' << P << ">: " << glm::mat<2, 4, T,P>(v4_1, v4_2) << '\n' + << "mat3x2<" << typeid(T).name() << ',' << P << ">: " << glm::mat<3, 2, T,P>(v2_1, v2_2, v2_3) << '\n' + << "mat3x3<" << typeid(T).name() << ',' << P << ">: " << glm::mat<3, 3, T,P>(v3_1, v3_2, v3_3) << '\n' + << "mat3x4<" << typeid(T).name() << ',' << P << ">: " << glm::mat<3, 4, T,P>(v4_1, v4_2, v4_3) << '\n' + << "mat4x2<" << typeid(T).name() << ',' << P << ">: " << glm::mat<4, 2, T,P>(v2_1, v2_2, v2_3, v2_4) << '\n' + << "mat4x3<" << typeid(T).name() << ',' << P << ">: " << glm::mat<4, 3, T,P>(v3_1, v3_2, v3_3, v3_4) << '\n' + << "mat4x4<" << typeid(T).name() << ',' << P << ">: " << glm::mat<4, 4, T,P>(v4_1, v4_2, v4_3, v4_4) << '\n'; + + os << glm::io::unformatted + << glm::io::order(otype) + << "mat2x2<" << typeid(T).name() << ',' << P << ">: " << glm::mat<2, 2, T,P>(v2_1, v2_2) << '\n' + << "mat2x3<" << typeid(T).name() << ',' << P << ">: " << glm::mat<2, 3, T,P>(v3_1, v3_2) << '\n' + << "mat2x4<" << typeid(T).name() << ',' << P << ">: " << glm::mat<2, 4, T,P>(v4_1, v4_2) << '\n' + << "mat3x2<" << typeid(T).name() << ',' << P << ">: " << glm::mat<3, 2, T,P>(v2_1, v2_2, v2_3) << '\n' + << "mat3x3<" << typeid(T).name() << ',' << P << ">: " << glm::mat<3, 3, T,P>(v3_1, v3_2, v3_3) << '\n' + << "mat3x4<" << typeid(T).name() << ',' << P << ">: " << glm::mat<3, 4, T,P>(v4_1, v4_2, v4_3) << '\n' + << "mat4x2<" << typeid(T).name() << ',' << P << ">: " << glm::mat<4, 2, T,P>(v2_1, v2_2, v2_3, v2_4) << '\n' + << "mat4x3<" << typeid(T).name() << ',' << P << ">: " << glm::mat<4, 3, T,P>(v3_1, v3_2, v3_3, v3_4) << '\n' + << "mat4x4<" << typeid(T).name() << ',' << P << ">: " << glm::mat<4, 4, T,P>(v4_1, v4_2, v4_3, v4_4) << '\n'; + + return 0; +} + +int main() +{ + int Error(0); + + Error += test_io_quat(std::cout); + Error += test_io_quat(std::wcout); + Error += test_io_quat(std::cout); + Error += test_io_quat(std::wcout); + Error += test_io_quat(std::cout); + Error += test_io_quat(std::wcout); + + Error += test_io_vec(std::cout); + Error += test_io_vec(std::wcout); + Error += test_io_vec(std::cout); + Error += test_io_vec(std::wcout); + Error += test_io_vec(std::cout); + Error += test_io_vec(std::wcout); + + Error += test_io_mat(std::cout, glm::io::column_major); + Error += test_io_mat(std::wcout, glm::io::column_major); + Error += test_io_mat(std::cout, glm::io::row_major); + Error += test_io_mat(std::wcout, glm::io::row_major); + + return Error; +} +#else + +int main() +{ + return 0; +} + +#endif// GLM_LANG & GLM_LANG_CXXMS_FLAG diff --git a/vendor/glm/test/gtx/gtx_load.cpp b/vendor/glm/test/gtx/gtx_load.cpp new file mode 100644 index 0000000..1467b9b --- /dev/null +++ b/vendor/glm/test/gtx/gtx_load.cpp @@ -0,0 +1,124 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +/* +#if GLM_CONFIG_SIMD == GLM_ENABLE + +#include +#include +#include +#include +#include + +namespace glm +{ + enum genTypeEnum + { + QUALIFIER_HIGHP, + QUALIFIER_MEDIUMP, + QUALIFIER_LOWP + }; + + template + struct genTypeTrait + {}; + + template + struct genTypeTrait > + { + static const genTypeEnum GENTYPE = QUALIFIER_HIGHP; + }; + + template + struct genTypeTrait > + { + static const genTypeEnum GENTYPE = QUALIFIER_MEDIUMP; + }; + + template + struct genTypeTrait > + { + static const genTypeEnum GENTYPE = QUALIFIER_LOWP; + }; + + template + struct load_gentype + { + + }; + +# if GLM_ARCH & GLM_ARCH_SSE_BIT + template + struct load_gentype<4, float, Q, true> + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, float, Q> load(float const* Mem) + { + vec<4, float, Q> Result; + Result.data = _mm_loadu_ps(Mem); + return Result; + } + }; +# endif//GLM_ARCH & GLM_ARCH_SSE_BIT + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType example_identity() + { + return detail::init_gentype::GENTYPE>::identity(); + } + + template + genType load(valType const* Mem) + { + + } + + aligned_vec4 loadu(float const* Mem) + { + aligned_vec4 Result; +# if GLM_ARCH & GLM_ARCH_SSE_BIT + Result.data = _mm_loadu_ps(Mem); +# else + Result[0] = *(Mem + 0); + Result[1] = *(Mem + 1); + Result[2] = *(Mem + 2); + Result[3] = *(Mem + 3); +# endif//GLM_ARCH & GLM_ARCH_SSE_BIT + return Result; + } + + aligned_vec4 loada(float const* Mem) + { + aligned_vec4 Result; +# if GLM_ARCH & GLM_ARCH_SSE_BIT + Result.data = _mm_load_ps(Mem); +# else + Result[0] = *(Mem + 0); + Result[1] = *(Mem + 1); + Result[2] = *(Mem + 2); + Result[3] = *(Mem + 3); +# endif//GLM_ARCH & GLM_ARCH_SSE_BIT + return Result; + } +}//namespace glm + +int test_vec4_load() +{ + int Error = 0; + + float Data[] = {1.f, 2.f, 3.f, 4.f}; + glm::aligned_vec4 const V = glm::loadu(Data); + Error += glm::all(glm::equal(V, glm::aligned_vec4(1.f, 2.f, 3.f, 4.f), glm::epsilon())) ? 0 : 1; + + return Error; +} +#endif +*/ +int main() +{ + int Error = 0; +/* +# if GLM_CONFIG_SIMD == GLM_ENABLE + Error += test_vec4_load(); +# endif +*/ + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_log_base.cpp b/vendor/glm/test/gtx/gtx_log_base.cpp new file mode 100644 index 0000000..37c7464 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_log_base.cpp @@ -0,0 +1,54 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include + +namespace test_log +{ + int run() + { + int Error = 0; + + { + float A = glm::log(10.f, 2.0f); + float B = glm::log2(10.f); + Error += glm::epsilonEqual(A, B, 0.00001f) ? 0 : 1; + } + + { + glm::vec1 A = glm::log(glm::vec1(10.f), glm::vec1(2.0f)); + glm::vec1 B = glm::log2(glm::vec1(10.f)); + Error += glm::all(glm::epsilonEqual(A, B, glm::vec1(0.00001f))) ? 0 : 1; + } + + { + glm::vec2 A = glm::log(glm::vec2(10.f), glm::vec2(2.0f)); + glm::vec2 B = glm::log2(glm::vec2(10.f)); + Error += glm::all(glm::epsilonEqual(A, B, glm::vec2(0.00001f))) ? 0 : 1; + } + + { + glm::vec3 A = glm::log(glm::vec3(10.f), glm::vec3(2.0f)); + glm::vec3 B = glm::log2(glm::vec3(10.f)); + Error += glm::all(glm::epsilonEqual(A, B, glm::vec3(0.00001f))) ? 0 : 1; + } + + { + glm::vec4 A = glm::log(glm::vec4(10.f), glm::vec4(2.0f)); + glm::vec4 B = glm::log2(glm::vec4(10.f)); + Error += glm::all(glm::epsilonEqual(A, B, glm::vec4(0.00001f))) ? 0 : 1; + } + + return Error; + } +}//namespace test_log + +int main() +{ + int Error(0); + + Error += test_log::run(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_matrix_cross_product.cpp b/vendor/glm/test/gtx/gtx_matrix_cross_product.cpp new file mode 100644 index 0000000..c1d0fa9 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_cross_product.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_matrix_decompose.cpp b/vendor/glm/test/gtx/gtx_matrix_decompose.cpp new file mode 100644 index 0000000..5a1884e --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_decompose.cpp @@ -0,0 +1,19 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + glm::mat4 Matrix(1); + + glm::vec3 Scale; + glm::quat Orientation; + glm::vec3 Translation; + glm::vec3 Skew(1); + glm::vec4 Perspective(1); + + glm::decompose(Matrix, Scale, Orientation, Translation, Skew, Perspective); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_matrix_factorisation.cpp b/vendor/glm/test/gtx/gtx_matrix_factorisation.cpp new file mode 100644 index 0000000..6771dba --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_factorisation.cpp @@ -0,0 +1,105 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +template +int test_qr(glm::mat m) +{ + int Error = 0; + + T const epsilon = static_cast(1e-10); + + glm::mat<(C < R ? C : R), R, T, Q> q(-999); + glm::mat r(-999); + + glm::qr_decompose(m, q, r); + + //Test if q*r really equals the input matrix + glm::mat tm = q*r; + glm::mat err = tm - m; + + for (glm::length_t i = 0; i < C; i++) + for (glm::length_t j = 0; j < R; j++) + Error += glm::abs(err[i][j]) > epsilon ? 1 : 0; + + //Test if the columns of q are orthonormal + for (glm::length_t i = 0; i < (C < R ? C : R); i++) + { + Error += (length(q[i]) - 1) > epsilon ? 1 : 0; + + for (glm::length_t j = 0; j epsilon ? 1 : 0; + } + + //Test if the matrix r is upper triangular + for (glm::length_t i = 0; i < C; i++) + for (glm::length_t j = i + 1; j < (C < R ? C : R); j++) + Error += glm::epsilonEqual(r[i][j], static_cast(0), glm::epsilon()) ? 0 : 1; + + return Error; +} + +template +int test_rq(glm::mat m) +{ + int Error = 0; + + T const epsilon = static_cast(1e-10); + + glm::mat q(-999); + glm::mat<(C < R ? C : R), R, T, Q> r(-999); + + glm::rq_decompose(m, r, q); + + //Test if q*r really equals the input matrix + glm::mat tm = r*q; + glm::mat err = tm - m; + + for (glm::length_t i = 0; i < C; i++) + for (glm::length_t j = 0; j < R; j++) + Error += glm::abs(err[i][j]) > epsilon ? 1 : 0; + + //Test if the rows of q are orthonormal + glm::mat<(C < R ? C : R), C, T, Q> tq = transpose(q); + + for (glm::length_t i = 0; i < (C < R ? C : R); i++) + { + Error += (length(tq[i]) - 1) > epsilon ? 1 : 0; + + for (glm::length_t j = 0; j epsilon ? 1 : 0; + } + + //Test if the matrix r is upper triangular + for (glm::length_t i = 0; i < (C < R ? C : R); i++) + for (glm::length_t j = R - (C < R ? C : R) + i + 1; j < R; j++) + Error += glm::epsilonEqual(r[i][j], static_cast(0), glm::epsilon()) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + //Test QR square + Error += test_qr(glm::dmat3(12.0, 6.0, -4.0, -51.0, 167.0, 24.0, 4.0, -68.0, -41.0)) ? 1 : 0; + + //Test RQ square + Error += test_rq(glm::dmat3(12.0, 6.0, -4.0, -51.0, 167.0, 24.0, 4.0, -68.0, -41.0)) ? 1 : 0; + + //Test QR triangular 1 + Error += test_qr(glm::dmat3x4(12.0, 6.0, -4.0, -51.0, 167.0, 24.0, 4.0, -68.0, -41.0, 7.0, 2.0, 15.0)) ? 1 : 0; + + //Test QR triangular 2 + Error += test_qr(glm::dmat4x3(12.0, 6.0, -4.0, -51.0, 167.0, 24.0, 4.0, -68.0, -41.0, 7.0, 2.0, 15.0)) ? 1 : 0; + + //Test RQ triangular 1 : Fails at the triangular test + Error += test_rq(glm::dmat3x4(12.0, 6.0, -4.0, -51.0, 167.0, 24.0, 4.0, -68.0, -41.0, 7.0, 2.0, 15.0)) ? 1 : 0; + + //Test QR triangular 2 + Error += test_rq(glm::dmat4x3(12.0, 6.0, -4.0, -51.0, 167.0, 24.0, 4.0, -68.0, -41.0, 7.0, 2.0, 15.0)) ? 1 : 0; + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_matrix_interpolation.cpp b/vendor/glm/test/gtx/gtx_matrix_interpolation.cpp new file mode 100644 index 0000000..38f0ce5 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_interpolation.cpp @@ -0,0 +1,59 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +#include + +static int test_axisAngle() +{ + int Error = 0; + + glm::mat4 m1(-0.9946f, 0.0f, -0.104531f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.104531f, 0.0f, -0.9946f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + glm::mat4 m2(-0.992624f, 0.0f, -0.121874f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.121874f, 0.0f, -0.992624f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + + glm::mat4 const m1rot = glm::extractMatrixRotation(m1); + glm::mat4 const dltRotation = m2 * glm::transpose(m1rot); + + glm::vec3 dltAxis(0.0f); + float dltAngle = 0.0f; + glm::axisAngle(dltRotation, dltAxis, dltAngle); + + std::cout << "dltAxis: (" << dltAxis.x << ", " << dltAxis.y << ", " << dltAxis.z << "), dltAngle: " << dltAngle << std::endl; + + glm::quat q = glm::quat_cast(dltRotation); + std::cout << "q: (" << q.x << ", " << q.y << ", " << q.z << ", " << q.w << ")" << std::endl; + float yaw = glm::yaw(q); + std::cout << "Yaw: " << yaw << std::endl; + + return Error; +} + +static int test_rotate() +{ + glm::mat4 m2(1.0); + float myAngle = 1.0f; + m2 = glm::rotate(m2, myAngle, glm::vec3(1.0f, 0.0f, 0.0f)); + glm::vec3 m2Axis; + float m2Angle; + glm::axisAngle(m2, m2Axis, m2Angle); + + return 0; +} + +int main() +{ + int Error = 0; + + Error += test_axisAngle(); + Error += test_rotate(); + + return Error; +} + + diff --git a/vendor/glm/test/gtx/gtx_matrix_major_storage.cpp b/vendor/glm/test/gtx/gtx_matrix_major_storage.cpp new file mode 100644 index 0000000..21de7f7 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_major_storage.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_matrix_operation.cpp b/vendor/glm/test/gtx/gtx_matrix_operation.cpp new file mode 100644 index 0000000..cae2ed4 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_operation.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_matrix_query.cpp b/vendor/glm/test/gtx/gtx_matrix_query.cpp new file mode 100644 index 0000000..0dda1f0 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_query.cpp @@ -0,0 +1,66 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int test_isNull() +{ + int Error(0); + + bool TestA = glm::isNull(glm::mat4(0), 0.00001f); + Error += TestA ? 0 : 1; + + return Error; +} + +int test_isIdentity() +{ + int Error(0); + + { + bool TestA = glm::isIdentity(glm::mat2(1), 0.00001f); + Error += TestA ? 0 : 1; + } + { + bool TestA = glm::isIdentity(glm::mat3(1), 0.00001f); + Error += TestA ? 0 : 1; + } + { + bool TestA = glm::isIdentity(glm::mat4(1), 0.00001f); + Error += TestA ? 0 : 1; + } + + return Error; +} + +int test_isNormalized() +{ + int Error(0); + + bool TestA = glm::isNormalized(glm::mat4(1), 0.00001f); + Error += TestA ? 0 : 1; + + return Error; +} + +int test_isOrthogonal() +{ + int Error(0); + + bool TestA = glm::isOrthogonal(glm::mat4(1), 0.00001f); + Error += TestA ? 0 : 1; + + return Error; +} + +int main() +{ + int Error(0); + + Error += test_isNull(); + Error += test_isIdentity(); + Error += test_isNormalized(); + Error += test_isOrthogonal(); + + return Error; +} + + diff --git a/vendor/glm/test/gtx/gtx_matrix_transform_2d.cpp b/vendor/glm/test/gtx/gtx_matrix_transform_2d.cpp new file mode 100644 index 0000000..f80d263 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_matrix_transform_2d.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_mixed_product.cpp b/vendor/glm/test/gtx/gtx_mixed_product.cpp new file mode 100644 index 0000000..ab59bb2 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_mixed_product.cpp @@ -0,0 +1,18 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2013-10-25 +// Updated : 2013-10-25 +// Licence : This source is under MIT licence +// File : test/gtx/associated_min_max.cpp +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_norm.cpp b/vendor/glm/test/gtx/gtx_norm.cpp new file mode 100644 index 0000000..e82102a --- /dev/null +++ b/vendor/glm/test/gtx/gtx_norm.cpp @@ -0,0 +1,81 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + + +int test_lMaxNorm() +{ + int Error(0); + + { + float norm = glm::lMaxNorm(glm::vec3(-1, -2, -3)); + Error += glm::epsilonEqual(norm, 3.f, 0.00001f) ? 0 : 1; + } + + { + float norm = glm::lMaxNorm(glm::vec3(2, 3, 1)); + Error += glm::epsilonEqual(norm, 3.f, 0.00001f) ? 0 : 1; + } + + return Error; +} + +int test_lxNorm() +{ + int Error(0); + + { + unsigned int depth_1 = 1; + float normA = glm::lxNorm(glm::vec3(2, 3, 1), depth_1); + float normB = glm::l1Norm(glm::vec3(2, 3, 1)); + Error += glm::epsilonEqual(normA, normB, 0.00001f) ? 0 : 1; + Error += glm::epsilonEqual(normA, 6.f, 0.00001f) ? 0 : 1; + } + + { + unsigned int depth_1 = 1; + float normA = glm::lxNorm(glm::vec3(-1, -2, -3), depth_1); + float normB = glm::l1Norm(glm::vec3(-1, -2, -3)); + Error += glm::epsilonEqual(normA, normB, 0.00001f) ? 0 : 1; + Error += glm::epsilonEqual(normA, 6.f, 0.00001f) ? 0 : 1; + } + + { + unsigned int depth_2 = 2; + float normA = glm::lxNorm(glm::vec3(2, 3, 1), depth_2); + float normB = glm::l2Norm(glm::vec3(2, 3, 1)); + Error += glm::epsilonEqual(normA, normB, 0.00001f) ? 0 : 1; + Error += glm::epsilonEqual(normA, 3.741657387f, 0.00001f) ? 0 : 1; + } + + { + unsigned int depth_2 = 2; + float normA = glm::lxNorm(glm::vec3(-1, -2, -3), depth_2); + float normB = glm::l2Norm(glm::vec3(-1, -2, -3)); + Error += glm::epsilonEqual(normA, normB, 0.00001f) ? 0 : 1; + Error += glm::epsilonEqual(normA, 3.741657387f, 0.00001f) ? 0 : 1; + } + + { + unsigned int oddDepth = 3; + float norm = glm::lxNorm(glm::vec3(2, 3, 1), oddDepth); + Error += glm::epsilonEqual(norm, 3.301927249f, 0.00001f) ? 0 : 1; + } + + { + unsigned int oddDepth = 3; + float norm = glm::lxNorm(glm::vec3(-1, -2, -3), oddDepth); + Error += glm::epsilonEqual(norm, 3.301927249f, 0.00001f) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error(0); + + Error += test_lMaxNorm(); + Error += test_lxNorm(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_normal.cpp b/vendor/glm/test/gtx/gtx_normal.cpp new file mode 100644 index 0000000..7a01ec0 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_normal.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_normalize_dot.cpp b/vendor/glm/test/gtx/gtx_normalize_dot.cpp new file mode 100644 index 0000000..9605863 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_normalize_dot.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_number_precision.cpp b/vendor/glm/test/gtx/gtx_number_precision.cpp new file mode 100644 index 0000000..a5a3ef2 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_number_precision.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_optimum_pow.cpp b/vendor/glm/test/gtx/gtx_optimum_pow.cpp new file mode 100644 index 0000000..c0a3fd4 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_optimum_pow.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_orthonormalize.cpp b/vendor/glm/test/gtx/gtx_orthonormalize.cpp new file mode 100644 index 0000000..0e7a8c8 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_orthonormalize.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_perpendicular.cpp b/vendor/glm/test/gtx/gtx_perpendicular.cpp new file mode 100644 index 0000000..d14cfee --- /dev/null +++ b/vendor/glm/test/gtx/gtx_perpendicular.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_polar_coordinates.cpp b/vendor/glm/test/gtx/gtx_polar_coordinates.cpp new file mode 100644 index 0000000..da2fe53 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_polar_coordinates.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_projection.cpp b/vendor/glm/test/gtx/gtx_projection.cpp new file mode 100644 index 0000000..8f9f772 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_projection.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_quaternion.cpp b/vendor/glm/test/gtx/gtx_quaternion.cpp new file mode 100644 index 0000000..80cbbac --- /dev/null +++ b/vendor/glm/test/gtx/gtx_quaternion.cpp @@ -0,0 +1,107 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include +#include +#include + +int test_quat_fastMix() +{ + int Error = 0; + + glm::quat A = glm::angleAxis(0.0f, glm::vec3(0, 0, 1)); + glm::quat B = glm::angleAxis(glm::pi() * 0.5f, glm::vec3(0, 0, 1)); + glm::quat C = glm::fastMix(A, B, 0.5f); + glm::quat D = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(0, 0, 1)); + + Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C.y, D.y, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C.z, D.z, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C.w, D.w, 0.01f) ? 0 : 1; + + return Error; +} + +int test_quat_shortMix() +{ + int Error(0); + + glm::quat A = glm::angleAxis(0.0f, glm::vec3(0, 0, 1)); + glm::quat B = glm::angleAxis(glm::pi() * 0.5f, glm::vec3(0, 0, 1)); + glm::quat C = glm::shortMix(A, B, 0.5f); + glm::quat D = glm::angleAxis(glm::pi() * 0.25f, glm::vec3(0, 0, 1)); + + Error += glm::epsilonEqual(C.x, D.x, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C.y, D.y, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C.z, D.z, 0.01f) ? 0 : 1; + Error += glm::epsilonEqual(C.w, D.w, 0.01f) ? 0 : 1; + + return Error; +} + +int test_orientation() +{ + int Error = 0; + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float p = glm::roll(q); + Error += glm::epsilonEqual(p, glm::pi() * 0.5f, 0.0001f) ? 0 : 1; + } + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float p = glm::pitch(q); + Error += glm::epsilonEqual(p, 0.f, 0.0001f) ? 0 : 1; + } + + { + glm::quat q(1.0f, 0.0f, 0.0f, 1.0f); + float p = glm::yaw(q); + Error += glm::epsilonEqual(p, 0.f, 0.0001f) ? 0 : 1; + } + + return Error; +} + +int test_rotation() +{ + int Error(0); + + glm::vec3 v(1, 0, 0); + glm::vec3 u(0, 1, 0); + + glm::quat Rotation = glm::rotation(v, u); + + float Angle = glm::angle(Rotation); + + Error += glm::abs(Angle - glm::pi() * 0.5f) < glm::epsilon() ? 0 : 1; + + return Error; +} + +int test_log() +{ + int Error(0); + + glm::quat q; + glm::quat p = glm::log(q); + glm::quat r = glm::exp(p); + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_log(); + Error += test_rotation(); + Error += test_orientation(); + Error += test_quat_fastMix(); + Error += test_quat_shortMix(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_random.cpp b/vendor/glm/test/gtx/gtx_random.cpp new file mode 100644 index 0000000..e562c31 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_random.cpp @@ -0,0 +1,99 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2011-05-31 +// Updated : 2011-05-31 +// Licence : This source is under MIT licence +// File : test/gtx/random.cpp +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +int test_signedRand1() +{ + int Error = 0; + + { + float ResultFloat = 0.0f; + double ResultDouble = 0.0f; + for(std::size_t i = 0; i < 100000; ++i) + { + ResultFloat += glm::signedRand1(); + ResultDouble += glm::signedRand1(); + } + + Error += glm::equalEpsilon(ResultFloat, 0.0f, 0.0001f); + Error += glm::equalEpsilon(ResultDouble, 0.0, 0.0001); + } + + return Error; +} + +int test_normalizedRand2() +{ + int Error = 0; + + { + std::size_t Max = 100000; + float ResultFloat = 0.0f; + double ResultDouble = 0.0f; + for(std::size_t i = 0; i < Max; ++i) + { + ResultFloat += glm::length(glm::normalizedRand2()); + ResultDouble += glm::length(glm::normalizedRand2()); + } + + Error += glm::equalEpsilon(ResultFloat, float(Max), 0.000001f) ? 0 : 1; + Error += glm::equalEpsilon(ResultDouble, double(Max), 0.000001) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int test_normalizedRand3() +{ + int Error = 0; + + { + std::size_t Max = 100000; + float ResultFloatA = 0.0f; + float ResultFloatB = 0.0f; + float ResultFloatC = 0.0f; + double ResultDoubleA = 0.0f; + double ResultDoubleB = 0.0f; + double ResultDoubleC = 0.0f; + for(std::size_t i = 0; i < Max; ++i) + { + ResultFloatA += glm::length(glm::normalizedRand3()); + ResultDoubleA += glm::length(glm::normalizedRand3()); + ResultFloatB += glm::length(glm::normalizedRand3(2.0f, 2.0f)); + ResultDoubleB += glm::length(glm::normalizedRand3(2.0, 2.0)); + ResultFloatC += glm::length(glm::normalizedRand3(1.0f, 3.0f)); + ResultDoubleC += glm::length(glm::normalizedRand3(1.0, 3.0)); + } + + Error += glm::equalEpsilon(ResultFloatA, float(Max), 0.0001f) ? 0 : 1; + Error += glm::equalEpsilon(ResultDoubleA, double(Max), 0.0001) ? 0 : 1; + Error += glm::equalEpsilon(ResultFloatB, float(Max * 2), 0.0001f) ? 0 : 1; + Error += glm::equalEpsilon(ResultDoubleB, double(Max * 2), 0.0001) ? 0 : 1; + Error += (ResultFloatC >= float(Max) && ResultFloatC <= float(Max * 3)) ? 0 : 1; + Error += (ResultDoubleC >= double(Max) && ResultDoubleC <= double(Max * 3)) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_signedRand1(); + Error += test_normalizedRand2(); + Error += test_normalizedRand3(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_range.cpp b/vendor/glm/test/gtx/gtx_range.cpp new file mode 100644 index 0000000..434731b --- /dev/null +++ b/vendor/glm/test/gtx/gtx_range.cpp @@ -0,0 +1,83 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include + +#if GLM_HAS_RANGE_FOR + +#include + +int test_vec() +{ + int Error = 0; + + { + glm::ivec3 const v(1, 2, 3); + + int count = 0; + glm::ivec3 Result(0); + for(int x : v) + { + Result[count] = x; + count++; + } + Error += count == 3 ? 0 : 1; + Error += v == Result ? 0 : 1; + } + + { + glm::ivec3 v(1, 2, 3); + for(int& x : v) + x = 0; + Error += glm::all(glm::equal(v, glm::ivec3(0))) ? 0 : 1; + } + + return Error; +} + +int test_mat() +{ + int Error = 0; + + { + glm::mat4x3 m(1.0f); + + int count = 0; + float Sum = 0.0f; + for(float x : m) + { + count++; + Sum += x; + } + Error += count == 12 ? 0 : 1; + Error += glm::equal(Sum, 3.0f, 0.001f) ? 0 : 1; + } + + { + glm::mat4x3 m(1.0f); + + for (float& x : m) { x = 0; } + glm::vec4 v(1, 1, 1, 1); + Error += glm::all(glm::equal(m*v, glm::vec3(0, 0, 0), glm::epsilon())) ? 0 : 1; + } + + return Error; +} + +int main() +{ + int Error = 0; + Error += test_vec(); + Error += test_mat(); + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif//GLM_HAS_RANGE_FOR diff --git a/vendor/glm/test/gtx/gtx_rotate_normalized_axis.cpp b/vendor/glm/test/gtx/gtx_rotate_normalized_axis.cpp new file mode 100644 index 0000000..d4eecdf --- /dev/null +++ b/vendor/glm/test/gtx/gtx_rotate_normalized_axis.cpp @@ -0,0 +1,9 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error(0); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_rotate_vector.cpp b/vendor/glm/test/gtx/gtx_rotate_vector.cpp new file mode 100644 index 0000000..becd63f --- /dev/null +++ b/vendor/glm/test/gtx/gtx_rotate_vector.cpp @@ -0,0 +1,77 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +int test_rotate() +{ + int Error = 0; + + glm::vec2 A = glm::rotate(glm::vec2(1, 0), glm::pi() * 0.5f); + glm::vec3 B = glm::rotate(glm::vec3(1, 0, 0), glm::pi() * 0.5f, glm::vec3(0, 0, 1)); + glm::vec4 C = glm::rotate(glm::vec4(1, 0, 0, 1), glm::pi() * 0.5f, glm::vec3(0, 0, 1)); + glm::vec3 D = glm::rotateX(glm::vec3(1, 0, 0), glm::pi() * 0.5f); + glm::vec4 E = glm::rotateX(glm::vec4(1, 0, 0, 1), glm::pi() * 0.5f); + glm::vec3 F = glm::rotateY(glm::vec3(1, 0, 0), glm::pi() * 0.5f); + glm::vec4 G = glm::rotateY(glm::vec4(1, 0, 0, 1), glm::pi() * 0.5f); + glm::vec3 H = glm::rotateZ(glm::vec3(1, 0, 0), glm::pi() * 0.5f); + glm::vec4 I = glm::rotateZ(glm::vec4(1, 0, 0,1 ), glm::pi() * 0.5f); + glm::mat4 O = glm::orientation(glm::normalize(glm::vec3(1)), glm::vec3(0, 0, 1)); + + return Error; +} + +int test_rotateX() +{ + int Error = 0; + + glm::vec3 D = glm::rotateX(glm::vec3(1, 0, 0), glm::pi() * 0.5f); + glm::vec4 E = glm::rotateX(glm::vec4(1, 0, 0, 1), glm::pi() * 0.5f); + + return Error; +} + +int test_rotateY() +{ + int Error = 0; + + glm::vec3 F = glm::rotateY(glm::vec3(1, 0, 0), glm::pi() * 0.5f); + glm::vec4 G = glm::rotateY(glm::vec4(1, 0, 0, 1), glm::pi() * 0.5f); + + return Error; +} + + +int test_rotateZ() +{ + int Error = 0; + + glm::vec3 H = glm::rotateZ(glm::vec3(1, 0, 0), glm::pi() * 0.5f); + glm::vec4 I = glm::rotateZ(glm::vec4(1, 0, 0,1 ), glm::pi() * 0.5f); + + return Error; +} + +int test_orientation() +{ + int Error = 0; + + glm::mat4 O = glm::orientation(glm::normalize(glm::vec3(1)), glm::vec3(0, 0, 1)); + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_rotate(); + Error += test_rotateX(); + Error += test_rotateY(); + Error += test_rotateZ(); + Error += test_orientation(); + + return Error; +} + + diff --git a/vendor/glm/test/gtx/gtx_scalar_multiplication.cpp b/vendor/glm/test/gtx/gtx_scalar_multiplication.cpp new file mode 100644 index 0000000..4aa96d6 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_scalar_multiplication.cpp @@ -0,0 +1,37 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +#if GLM_HAS_TEMPLATE_ALIASES && !(GLM_COMPILER & GLM_COMPILER_GCC) +#include + +int main() +{ + int Error(0); + glm::vec3 v(0.5, 3.1, -9.1); + + Error += glm::all(glm::equal(v, 1.0 * v, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v, 1 * v, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(v, 1u * v, glm::epsilon())) ? 0 : 1; + + glm::mat3 m(1, 2, 3, 4, 5, 6, 7, 8, 9); + glm::vec3 w = 0.5f * m * v; + + Error += glm::all(glm::equal((m*v)/2, w, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(m*(v/2), w, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal((m/2)*v, w, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal((0.5*m)*v, w, glm::epsilon())) ? 0 : 1; + Error += glm::all(glm::equal(0.5*(m*v), w, glm::epsilon())) ? 0 : 1; + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/gtx/gtx_scalar_relational.cpp b/vendor/glm/test/gtx/gtx_scalar_relational.cpp new file mode 100644 index 0000000..fc6a09a --- /dev/null +++ b/vendor/glm/test/gtx/gtx_scalar_relational.cpp @@ -0,0 +1,174 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include +#include +#include + +static int test_lessThan() +{ + int Error = 0; + + Error += glm::lessThan(0, 1) ? 0 : 1; + Error += glm::lessThan(1, 0) ? 1 : 0; + Error += glm::lessThan(0, 0) ? 1 : 0; + Error += glm::lessThan(1, 1) ? 1 : 0; + Error += glm::lessThan(0.0f, 1.0f) ? 0 : 1; + Error += glm::lessThan(1.0f, 0.0f) ? 1 : 0; + Error += glm::lessThan(0.0f, 0.0f) ? 1 : 0; + Error += glm::lessThan(1.0f, 1.0f) ? 1 : 0; + Error += glm::lessThan(0.0, 1.0) ? 0 : 1; + Error += glm::lessThan(1.0, 0.0) ? 1 : 0; + Error += glm::lessThan(0.0, 0.0) ? 1 : 0; + Error += glm::lessThan(1.0, 1.0) ? 1 : 0; + + return Error; +} + +static int test_lessThanEqual() +{ + int Error = 0; + + Error += glm::lessThanEqual(0, 1) ? 0 : 1; + Error += glm::lessThanEqual(1, 0) ? 1 : 0; + Error += glm::lessThanEqual(0, 0) ? 0 : 1; + Error += glm::lessThanEqual(1, 1) ? 0 : 1; + Error += glm::lessThanEqual(0.0f, 1.0f) ? 0 : 1; + Error += glm::lessThanEqual(1.0f, 0.0f) ? 1 : 0; + Error += glm::lessThanEqual(0.0f, 0.0f) ? 0 : 1; + Error += glm::lessThanEqual(1.0f, 1.0f) ? 0 : 1; + Error += glm::lessThanEqual(0.0, 1.0) ? 0 : 1; + Error += glm::lessThanEqual(1.0, 0.0) ? 1 : 0; + Error += glm::lessThanEqual(0.0, 0.0) ? 0 : 1; + Error += glm::lessThanEqual(1.0, 1.0) ? 0 : 1; + + return Error; +} + +static int test_greaterThan() +{ + int Error = 0; + + Error += glm::greaterThan(0, 1) ? 1 : 0; + Error += glm::greaterThan(1, 0) ? 0 : 1; + Error += glm::greaterThan(0, 0) ? 1 : 0; + Error += glm::greaterThan(1, 1) ? 1 : 0; + Error += glm::greaterThan(0.0f, 1.0f) ? 1 : 0; + Error += glm::greaterThan(1.0f, 0.0f) ? 0 : 1; + Error += glm::greaterThan(0.0f, 0.0f) ? 1 : 0; + Error += glm::greaterThan(1.0f, 1.0f) ? 1 : 0; + Error += glm::greaterThan(0.0, 1.0) ? 1 : 0; + Error += glm::greaterThan(1.0, 0.0) ? 0 : 1; + Error += glm::greaterThan(0.0, 0.0) ? 1 : 0; + Error += glm::greaterThan(1.0, 1.0) ? 1 : 0; + + return Error; +} + +static int test_greaterThanEqual() +{ + int Error = 0; + + Error += glm::greaterThanEqual(0, 1) ? 1 : 0; + Error += glm::greaterThanEqual(1, 0) ? 0 : 1; + Error += glm::greaterThanEqual(0, 0) ? 0 : 1; + Error += glm::greaterThanEqual(1, 1) ? 0 : 1; + Error += glm::greaterThanEqual(0.0f, 1.0f) ? 1 : 0; + Error += glm::greaterThanEqual(1.0f, 0.0f) ? 0 : 1; + Error += glm::greaterThanEqual(0.0f, 0.0f) ? 0 : 1; + Error += glm::greaterThanEqual(1.0f, 1.0f) ? 0 : 1; + Error += glm::greaterThanEqual(0.0, 1.0) ? 1 : 0; + Error += glm::greaterThanEqual(1.0, 0.0) ? 0 : 1; + Error += glm::greaterThanEqual(0.0, 0.0) ? 0 : 1; + Error += glm::greaterThanEqual(1.0, 1.0) ? 0 : 1; + + return Error; +} + +static int test_equal() +{ + int Error = 0; + + Error += glm::equal(0, 1) ? 1 : 0; + Error += glm::equal(1, 0) ? 1 : 0; + Error += glm::equal(0, 0) ? 0 : 1; + Error += glm::equal(1, 1) ? 0 : 1; + Error += glm::equal(0.0f, 1.0f, glm::epsilon()) ? 1 : 0; + Error += glm::equal(1.0f, 0.0f, glm::epsilon()) ? 1 : 0; + Error += glm::equal(0.0f, 0.0f, glm::epsilon()) ? 0 : 1; + Error += glm::equal(1.0f, 1.0f, glm::epsilon()) ? 0 : 1; + Error += glm::equal(0.0, 1.0, glm::epsilon()) ? 1 : 0; + Error += glm::equal(1.0, 0.0, glm::epsilon()) ? 1 : 0; + Error += glm::equal(0.0, 0.0, glm::epsilon()) ? 0 : 1; + Error += glm::equal(1.0, 1.0, glm::epsilon()) ? 0 : 1; + + return Error; +} + +static int test_notEqual() +{ + int Error = 0; + + Error += glm::notEqual(0, 1) ? 0 : 1; + Error += glm::notEqual(1, 0) ? 0 : 1; + Error += glm::notEqual(0, 0) ? 1 : 0; + Error += glm::notEqual(1, 1) ? 1 : 0; + Error += glm::notEqual(0.0f, 1.0f, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(1.0f, 0.0f, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(0.0f, 0.0f, glm::epsilon()) ? 1 : 0; + Error += glm::notEqual(1.0f, 1.0f, glm::epsilon()) ? 1 : 0; + Error += glm::notEqual(0.0, 1.0, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(1.0, 0.0, glm::epsilon()) ? 0 : 1; + Error += glm::notEqual(0.0, 0.0, glm::epsilon()) ? 1 : 0; + Error += glm::notEqual(1.0, 1.0, glm::epsilon()) ? 1 : 0; + + return Error; +} + +static int test_any() +{ + int Error = 0; + + Error += glm::any(true) ? 0 : 1; + Error += glm::any(false) ? 1 : 0; + + return Error; +} + +static int test_all() +{ + int Error = 0; + + Error += glm::all(true) ? 0 : 1; + Error += glm::all(false) ? 1 : 0; + + return Error; +} + +static int test_not() +{ + int Error = 0; + + Error += glm::not_(true) ? 1 : 0; + Error += glm::not_(false) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_lessThan(); + Error += test_lessThanEqual(); + Error += test_greaterThan(); + Error += test_greaterThanEqual(); + Error += test_equal(); + Error += test_notEqual(); + Error += test_any(); + Error += test_all(); + Error += test_not(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_simd_mat4.cpp b/vendor/glm/test/gtx/gtx_simd_mat4.cpp new file mode 100644 index 0000000..28d7ec5 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_simd_mat4.cpp @@ -0,0 +1,324 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @file test/gtx/gtx_simd_mat4.cpp +/// @date 2010-09-16 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if(GLM_ARCH != GLM_ARCH_PURE) + +std::vector test_detA(std::vector const & Data) +{ + std::vector Test(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Test.size() - 1; ++i) + Test[i] = glm::determinant(Data[i]); + + std::clock_t TimeEnd = clock(); + printf("Det A: %ld\n", TimeEnd - TimeStart); + + return Test; +} + +std::vector test_detB(std::vector const & Data) +{ + std::vector Test(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Test.size() - 1; ++i) + { + _mm_prefetch((char*)&Data[i + 1], _MM_HINT_T0); + glm::simdMat4 m(Data[i]); + glm::simdVec4 d(glm::detail::sse_slow_det_ps((__m128 const * const)&m)); + glm::vec4 v;//(d); + Test[i] = v.x; + } + + std::clock_t TimeEnd = clock(); + printf("Det B: %ld\n", TimeEnd - TimeStart); + + return Test; +} + +std::vector test_detC(std::vector const & Data) +{ + std::vector Test(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Test.size() - 1; ++i) + { + _mm_prefetch((char*)&Data[i + 1], _MM_HINT_T0); + glm::simdMat4 m(Data[i]); + glm::simdVec4 d(glm::detail::sse_det_ps((__m128 const * const)&m)); + glm::vec4 v;//(d); + Test[i] = v.x; + } + + std::clock_t TimeEnd = clock(); + printf("Det C: %ld\n", TimeEnd - TimeStart); + + return Test; +} + +std::vector test_detD(std::vector const & Data) +{ + std::vector Test(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Test.size() - 1; ++i) + { + _mm_prefetch((char*)&Data[i + 1], _MM_HINT_T0); + glm::simdMat4 m(Data[i]); + glm::simdVec4 d(glm::detail::sse_detd_ps((__m128 const * const)&m)); + glm::vec4 v;//(d); + Test[i] = v.x; + } + + std::clock_t TimeEnd = clock(); + printf("Det D: %ld\n", TimeEnd - TimeStart); + + return Test; +} + +void test_invA(std::vector const & Data, std::vector & Out) +{ + //std::vector Test(Data.size()); + Out.resize(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Out.size() - 1; ++i) + { + Out[i] = glm::inverse(Data[i]); + } + + std::clock_t TimeEnd = clock(); + printf("Inv A: %ld\n", TimeEnd - TimeStart); +} + +void test_invC(std::vector const & Data, std::vector & Out) +{ + //std::vector Test(Data.size()); + Out.resize(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Out.size() - 1; ++i) + { + _mm_prefetch((char*)&Data[i + 1], _MM_HINT_T0); + glm::simdMat4 m(Data[i]); + glm::simdMat4 o; + glm::detail::sse_inverse_fast_ps((__m128 const * const)&m, (__m128 *)&o); + Out[i] = *(glm::mat4*)&o; + } + + std::clock_t TimeEnd = clock(); + printf("Inv C: %ld\n", TimeEnd - TimeStart); +} + +void test_invD(std::vector const & Data, std::vector & Out) +{ + //std::vector Test(Data.size()); + Out.resize(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Out.size() - 1; ++i) + { + _mm_prefetch((char*)&Data[i + 1], _MM_HINT_T0); + glm::simdMat4 m(Data[i]); + glm::simdMat4 o; + glm::detail::sse_inverse_ps((__m128 const * const)&m, (__m128 *)&o); + Out[i] = *(glm::mat4*)&o; + } + + std::clock_t TimeEnd = clock(); + printf("Inv D: %ld\n", TimeEnd - TimeStart); +} + +void test_mulA(std::vector const & Data, std::vector & Out) +{ + //std::vector Test(Data.size()); + Out.resize(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Out.size() - 1; ++i) + { + Out[i] = Data[i] * Data[i]; + } + + std::clock_t TimeEnd = clock(); + printf("Mul A: %ld\n", TimeEnd - TimeStart); +} + +void test_mulD(std::vector const & Data, std::vector & Out) +{ + //std::vector Test(Data.size()); + Out.resize(Data.size()); + + std::clock_t TimeStart = clock(); + + for(std::size_t i = 0; i < Out.size() - 1; ++i) + { + _mm_prefetch((char*)&Data[i + 1], _MM_HINT_T0); + glm::simdMat4 m(Data[i]); + glm::simdMat4 o; + glm::detail::sse_mul_ps((__m128 const * const)&m, (__m128 const * const)&m, (__m128*)&o); + Out[i] = *(glm::mat4*)&o; + } + + std::clock_t TimeEnd = clock(); + printf("Mul D: %ld\n", TimeEnd - TimeStart); +} + +int test_compute_glm() +{ + return 0; +} + +int test_compute_gtx() +{ + std::vector Output(1000000); + + std::clock_t TimeStart = clock(); + + for(std::size_t k = 0; k < Output.size(); ++k) + { + float i = float(k) / 1000.f + 0.001f; + glm::vec3 A = glm::normalize(glm::vec3(i)); + glm::vec3 B = glm::cross(A, glm::normalize(glm::vec3(1, 1, 2))); + glm::mat4 C = glm::rotate(glm::mat4(1.0f), i, B); + glm::mat4 D = glm::scale(C, glm::vec3(0.8f, 1.0f, 1.2f)); + glm::mat4 E = glm::translate(D, glm::vec3(1.4f, 1.2f, 1.1f)); + glm::mat4 F = glm::perspective(i, 1.5f, 0.1f, 1000.f); + glm::mat4 G = glm::inverse(F * E); + glm::vec3 H = glm::unProject(glm::vec3(i), G, F, E[3]); + glm::vec3 I = glm::any(glm::isnan(glm::project(H, G, F, E[3]))) ? glm::vec3(2) : glm::vec3(1); + glm::mat4 J = glm::lookAt(glm::normalize(glm::max(B, glm::vec3(0.001f))), H, I); + glm::mat4 K = glm::transpose(J); + glm::quat L = glm::normalize(glm::quat_cast(K)); + glm::vec4 M = L * glm::smoothstep(K[3], J[3], glm::vec4(i)); + glm::mat4 N = glm::mat4(glm::normalize(glm::max(M, glm::vec4(0.001f))), K[3], J[3], glm::vec4(i)); + glm::mat4 O = N * glm::inverse(N); + glm::vec4 P = O * glm::reflect(N[3], glm::vec4(A, 1.0f)); + glm::vec4 Q = glm::vec4(glm::dot(M, P)); + glm::vec4 R = glm::quat(Q.w, glm::vec3(Q)) * P; + Output[k] = R; + } + + std::clock_t TimeEnd = clock(); + printf("test_compute_gtx: %ld\n", TimeEnd - TimeStart); + + return 0; +} + +int main() +{ + int Error = 0; + + std::vector Data(64 * 64 * 1); + for(std::size_t i = 0; i < Data.size(); ++i) + Data[i] = glm::mat4( + glm::vec4(glm::linearRand(glm::vec4(-2.0f), glm::vec4(2.0f))), + glm::vec4(glm::linearRand(glm::vec4(-2.0f), glm::vec4(2.0f))), + glm::vec4(glm::linearRand(glm::vec4(-2.0f), glm::vec4(2.0f))), + glm::vec4(glm::linearRand(glm::vec4(-2.0f), glm::vec4(2.0f)))); + + { + std::vector TestInvA; + test_invA(Data, TestInvA); + } + { + std::vector TestInvC; + test_invC(Data, TestInvC); + } + { + std::vector TestInvD; + test_invD(Data, TestInvD); + } + + { + std::vector TestA; + test_mulA(Data, TestA); + } + { + std::vector TestD; + test_mulD(Data, TestD); + } + + { + std::vector TestDetA = test_detA(Data); + std::vector TestDetB = test_detB(Data); + std::vector TestDetD = test_detD(Data); + std::vector TestDetC = test_detC(Data); + + for(std::size_t i = 0; i < TestDetA.size(); ++i) + if(TestDetA[i] != TestDetB[i] && TestDetC[i] != TestDetB[i] && TestDetC[i] != TestDetD[i]) + return 1; + } + + // shuffle test + glm::simdVec4 A(1.0f, 2.0f, 3.0f, 4.0f); + glm::simdVec4 B(5.0f, 6.0f, 7.0f, 8.0f); + //__m128 C = _mm_shuffle_ps(A.Data, B.Data, _MM_SHUFFLE(1, 0, 1, 0)); + + Error += test_compute_glm(); + Error += test_compute_gtx(); + float Det = glm::determinant(glm::simdMat4(1.0)); + Error += Det == 1.0f ? 0 : 1; + + glm::simdMat4 D = glm::matrixCompMult(glm::simdMat4(1.0), glm::simdMat4(1.0)); + + return Error; +} + +#else + +int main() +{ + int Error = 0; + + return Error; +} + +#endif//(GLM_ARCH != GLM_ARCH_PURE) diff --git a/vendor/glm/test/gtx/gtx_simd_vec4.cpp b/vendor/glm/test/gtx/gtx_simd_vec4.cpp new file mode 100644 index 0000000..e71a60b --- /dev/null +++ b/vendor/glm/test/gtx/gtx_simd_vec4.cpp @@ -0,0 +1,71 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @file test/gtx/gtx_simd_vec4.cpp +/// @date 2010-09-16 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include +#include +#include + +#if(GLM_ARCH != GLM_ARCH_PURE) + +int main() +{ + glm::simdVec4 A1(0.0f, 0.1f, 0.2f, 0.3f); + glm::simdVec4 B1(0.4f, 0.5f, 0.6f, 0.7f); + glm::simdVec4 C1 = A1 + B1; + glm::simdVec4 D1 = A1.swizzle(); + glm::simdVec4 E1(glm::vec4(1.0f)); + glm::vec4 F1 = glm::vec4_cast(E1); + //glm::vec4 G1(E1); + + //printf("A1(%2.3f, %2.3f, %2.3f, %2.3f)\n", A1.x, A1.y, A1.z, A1.w); + //printf("B1(%2.3f, %2.3f, %2.3f, %2.3f)\n", B1.x, B1.y, B1.z, B1.w); + //printf("C1(%2.3f, %2.3f, %2.3f, %2.3f)\n", C1.x, C1.y, C1.z, C1.w); + //printf("D1(%2.3f, %2.3f, %2.3f, %2.3f)\n", D1.x, D1.y, D1.z, D1.w); + + __m128 value = _mm_set1_ps(0.0f); + __m128 data = _mm_cmpeq_ps(value, value); + __m128 add0 = _mm_add_ps(data, data); + + glm::simdVec4 GNI(add0); + + return 0; +} + +#else + +int main() +{ + int Error = 0; + + return Error; +} + +#endif//(GLM_ARCH != GLM_ARCH_PURE) diff --git a/vendor/glm/test/gtx/gtx_spline.cpp b/vendor/glm/test/gtx/gtx_spline.cpp new file mode 100644 index 0000000..c93ee17 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_spline.cpp @@ -0,0 +1,100 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include + +namespace catmullRom +{ + int test() + { + int Error(0); + + glm::vec2 Result2 = glm::catmullRom( + glm::vec2(0.0f, 0.0f), + glm::vec2(1.0f, 0.0f), + glm::vec2(1.0f, 1.0f), + glm::vec2(0.0f, 1.0f), 0.5f); + + glm::vec3 Result3 = glm::catmullRom( + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 1.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f), 0.5f); + + glm::vec4 Result4 = glm::catmullRom( + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(1.0f, 1.0f, 0.0f, 1.0f), + glm::vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.5f); + + return Error; + } +}//catmullRom + +namespace hermite +{ + int test() + { + int Error(0); + + glm::vec2 Result2 = glm::hermite( + glm::vec2(0.0f, 0.0f), + glm::vec2(1.0f, 0.0f), + glm::vec2(1.0f, 1.0f), + glm::vec2(0.0f, 1.0f), 0.5f); + + glm::vec3 Result3 = glm::hermite( + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 1.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f), 0.5f); + + glm::vec4 Result4 = glm::hermite( + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(1.0f, 1.0f, 0.0f, 1.0f), + glm::vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.5f); + + return Error; + } +}//catmullRom + +namespace cubic +{ + int test() + { + int Error(0); + + glm::vec2 Result2 = glm::cubic( + glm::vec2(0.0f, 0.0f), + glm::vec2(1.0f, 0.0f), + glm::vec2(1.0f, 1.0f), + glm::vec2(0.0f, 1.0f), 0.5f); + + glm::vec3 Result3 = glm::cubic( + glm::vec3(0.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 0.0f, 0.0f), + glm::vec3(1.0f, 1.0f, 0.0f), + glm::vec3(0.0f, 1.0f, 0.0f), 0.5f); + + glm::vec4 Result = glm::cubic( + glm::vec4(0.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(1.0f, 0.0f, 0.0f, 1.0f), + glm::vec4(1.0f, 1.0f, 0.0f, 1.0f), + glm::vec4(0.0f, 1.0f, 0.0f, 1.0f), 0.5f); + + return Error; + } +}//catmullRom + +int main() +{ + int Error(0); + + Error += catmullRom::test(); + Error += hermite::test(); + Error += cubic::test(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_string_cast.cpp b/vendor/glm/test/gtx/gtx_string_cast.cpp new file mode 100644 index 0000000..b04c870 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_string_cast.cpp @@ -0,0 +1,155 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +int test_string_cast_vector() +{ + int Error = 0; + + { + glm::vec2 A1(1, 2); + std::string A2 = glm::to_string(A1); + Error += A2 != std::string("vec2(1.000000, 2.000000)") ? 1 : 0; + + glm::vec3 B1(1, 2, 3); + std::string B2 = glm::to_string(B1); + Error += B2 != std::string("vec3(1.000000, 2.000000, 3.000000)") ? 1 : 0; + + glm::vec4 C1(1, 2, 3, 4); + std::string C2 = glm::to_string(C1); + Error += C2 != std::string("vec4(1.000000, 2.000000, 3.000000, 4.000000)") ? 1 : 0; + + glm::dvec2 J1(1, 2); + std::string J2 = glm::to_string(J1); + Error += J2 != std::string("dvec2(1.000000, 2.000000)") ? 1 : 0; + + glm::dvec3 K1(1, 2, 3); + std::string K2 = glm::to_string(K1); + Error += K2 != std::string("dvec3(1.000000, 2.000000, 3.000000)") ? 1 : 0; + + glm::dvec4 L1(1, 2, 3, 4); + std::string L2 = glm::to_string(L1); + Error += L2 != std::string("dvec4(1.000000, 2.000000, 3.000000, 4.000000)") ? 1 : 0; + } + + { + glm::bvec2 M1(false, true); + std::string M2 = glm::to_string(M1); + Error += M2 != std::string("bvec2(false, true)") ? 1 : 0; + + glm::bvec3 O1(false, true, false); + std::string O2 = glm::to_string(O1); + Error += O2 != std::string("bvec3(false, true, false)") ? 1 : 0; + + glm::bvec4 P1(false, true, false, true); + std::string P2 = glm::to_string(P1); + Error += P2 != std::string("bvec4(false, true, false, true)") ? 1 : 0; + } + + { + glm::ivec2 D1(1, 2); + std::string D2 = glm::to_string(D1); + Error += D2 != std::string("ivec2(1, 2)") ? 1 : 0; + + glm::ivec3 E1(1, 2, 3); + std::string E2 = glm::to_string(E1); + Error += E2 != std::string("ivec3(1, 2, 3)") ? 1 : 0; + + glm::ivec4 F1(1, 2, 3, 4); + std::string F2 = glm::to_string(F1); + Error += F2 != std::string("ivec4(1, 2, 3, 4)") ? 1 : 0; + } + + { + glm::i8vec2 D1(1, 2); + std::string D2 = glm::to_string(D1); + Error += D2 != std::string("i8vec2(1, 2)") ? 1 : 0; + + glm::i8vec3 E1(1, 2, 3); + std::string E2 = glm::to_string(E1); + Error += E2 != std::string("i8vec3(1, 2, 3)") ? 1 : 0; + + glm::i8vec4 F1(1, 2, 3, 4); + std::string F2 = glm::to_string(F1); + Error += F2 != std::string("i8vec4(1, 2, 3, 4)") ? 1 : 0; + } + + { + glm::i16vec2 D1(1, 2); + std::string D2 = glm::to_string(D1); + Error += D2 != std::string("i16vec2(1, 2)") ? 1 : 0; + + glm::i16vec3 E1(1, 2, 3); + std::string E2 = glm::to_string(E1); + Error += E2 != std::string("i16vec3(1, 2, 3)") ? 1 : 0; + + glm::i16vec4 F1(1, 2, 3, 4); + std::string F2 = glm::to_string(F1); + Error += F2 != std::string("i16vec4(1, 2, 3, 4)") ? 1 : 0; + } + + { + glm::i64vec2 D1(1, 2); + std::string D2 = glm::to_string(D1); + Error += D2 != std::string("i64vec2(1, 2)") ? 1 : 0; + + glm::i64vec3 E1(1, 2, 3); + std::string E2 = glm::to_string(E1); + Error += E2 != std::string("i64vec3(1, 2, 3)") ? 1 : 0; + + glm::i64vec4 F1(1, 2, 3, 4); + std::string F2 = glm::to_string(F1); + Error += F2 != std::string("i64vec4(1, 2, 3, 4)") ? 1 : 0; + } + + return Error; +} + +int test_string_cast_matrix() +{ + int Error = 0; + + glm::mat2x2 A1(1.000000, 2.000000, 3.000000, 4.000000); + std::string A2 = glm::to_string(A1); + Error += A2 != std::string("mat2x2((1.000000, 2.000000), (3.000000, 4.000000))") ? 1 : 0; + + return Error; +} + +int test_string_cast_quaternion() +{ + int Error = 0; + + glm::quat Q0 = glm::quat(1.0f, 2.0f, 3.0f, 4.0f); + std::string S0 = glm::to_string(Q0); + Error += S0 != std::string("quat(1.000000, {2.000000, 3.000000, 4.000000})") ? 1 : 0; + + return Error; + +} + +int test_string_cast_dual_quaternion() +{ + int Error = 0; + + glm::dualquat Q0 = glm::dualquat(glm::quat(1.0f, 2.0f, 3.0f, 4.0f), glm::quat(5.0f, 6.0f, 7.0f, 8.0f)); + std::string S0 = glm::to_string(Q0); + Error += S0 != std::string("dualquat((1.000000, {2.000000, 3.000000, 4.000000}), (5.000000, {6.000000, 7.000000, 8.000000}))") ? 1 : 0; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_string_cast_vector(); + Error += test_string_cast_matrix(); + Error += test_string_cast_quaternion(); + Error += test_string_cast_dual_quaternion(); + + return Error; +} + + diff --git a/vendor/glm/test/gtx/gtx_texture.cpp b/vendor/glm/test/gtx/gtx_texture.cpp new file mode 100644 index 0000000..0b98ed7 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_texture.cpp @@ -0,0 +1,22 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +int test_levels() +{ + int Error = 0; + + int const Levels = glm::levels(glm::ivec2(3, 2)); + Error += Levels == 2 ? 0 : 1; + + return Error; +} + +int main() +{ + int Error = 0; + + Error += test_levels(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_type_aligned.cpp b/vendor/glm/test/gtx/gtx_type_aligned.cpp new file mode 100644 index 0000000..8d045c0 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_type_aligned.cpp @@ -0,0 +1,114 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +int test_decl() +{ + int Error(0); + + { + struct S1 + { + glm::aligned_vec4 B; + }; + + struct S2 + { + glm::vec4 B; + }; + + std::printf("vec4 - Aligned: %d, unaligned: %d\n", static_cast(sizeof(S1)), static_cast(sizeof(S2))); + + Error += sizeof(S1) >= sizeof(S2) ? 0 : 1; + } + + { + struct S1 + { + bool A; + glm::vec3 B; + }; + + struct S2 + { + bool A; + glm::aligned_vec3 B; + }; + + std::printf("vec3 - Aligned: %d, unaligned: %d\n", static_cast(sizeof(S1)), static_cast(sizeof(S2))); + + Error += sizeof(S1) <= sizeof(S2) ? 0 : 1; + } + + { + struct S1 + { + bool A; + glm::aligned_vec4 B; + }; + + struct S2 + { + bool A; + glm::vec4 B; + }; + + std::printf("vec4 - Aligned: %d, unaligned: %d\n", static_cast(sizeof(S1)), static_cast(sizeof(S2))); + + Error += sizeof(S1) >= sizeof(S2) ? 0 : 1; + } + + { + struct S1 + { + bool A; + glm::aligned_dvec4 B; + }; + + struct S2 + { + bool A; + glm::dvec4 B; + }; + + std::printf("dvec4 - Aligned: %d, unaligned: %d\n", static_cast(sizeof(S1)), static_cast(sizeof(S2))); + + Error += sizeof(S1) >= sizeof(S2) ? 0 : 1; + } + + return Error; +} + +template +void print(genType const& Mat0) +{ + std::printf("mat4(\n"); + std::printf("\tvec4(%2.9f, %2.9f, %2.9f, %2.9f)\n", static_cast(Mat0[0][0]), static_cast(Mat0[0][1]), static_cast(Mat0[0][2]), static_cast(Mat0[0][3])); + std::printf("\tvec4(%2.9f, %2.9f, %2.9f, %2.9f)\n", static_cast(Mat0[1][0]), static_cast(Mat0[1][1]), static_cast(Mat0[1][2]), static_cast(Mat0[1][3])); + std::printf("\tvec4(%2.9f, %2.9f, %2.9f, %2.9f)\n", static_cast(Mat0[2][0]), static_cast(Mat0[2][1]), static_cast(Mat0[2][2]), static_cast(Mat0[2][3])); + std::printf("\tvec4(%2.9f, %2.9f, %2.9f, %2.9f))\n\n", static_cast(Mat0[3][0]), static_cast(Mat0[3][1]), static_cast(Mat0[3][2]), static_cast(Mat0[3][3])); +} + +int perf_mul() +{ + int Error = 0; + + glm::mat4 A(1.0f); + glm::mat4 B(1.0f); + + glm::mat4 C = A * B; + + print(C); + + return Error; +} + +int main() +{ + int Error(0); + + Error += test_decl(); + Error += perf_mul(); + + return Error; +} diff --git a/vendor/glm/test/gtx/gtx_type_trait.cpp b/vendor/glm/test/gtx/gtx_type_trait.cpp new file mode 100644 index 0000000..9b96a36 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_type_trait.cpp @@ -0,0 +1,13 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include + +int main() +{ + int Error = 0; + + + + return Error; +} + diff --git a/vendor/glm/test/gtx/gtx_vec_swizzle.cpp b/vendor/glm/test/gtx/gtx_vec_swizzle.cpp new file mode 100644 index 0000000..0b0c8b8 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_vec_swizzle.cpp @@ -0,0 +1,11 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include + +int main() +{ + int Error = 0; + + + return Error; +} + diff --git a/vendor/glm/test/gtx/gtx_vector_angle.cpp b/vendor/glm/test/gtx/gtx_vector_angle.cpp new file mode 100644 index 0000000..4e8172b --- /dev/null +++ b/vendor/glm/test/gtx/gtx_vector_angle.cpp @@ -0,0 +1,59 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +int test_angle() +{ + int Error = 0; + + float AngleA = glm::angle(glm::vec2(1, 0), glm::normalize(glm::vec2(1, 1))); + Error += glm::epsilonEqual(AngleA, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + float AngleB = glm::angle(glm::vec3(1, 0, 0), glm::normalize(glm::vec3(1, 1, 0))); + Error += glm::epsilonEqual(AngleB, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + float AngleC = glm::angle(glm::vec4(1, 0, 0, 0), glm::normalize(glm::vec4(1, 1, 0, 0))); + Error += glm::epsilonEqual(AngleC, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + + return Error; +} + +int test_orientedAngle_vec2() +{ + int Error = 0; + + float AngleA = glm::orientedAngle(glm::vec2(1, 0), glm::normalize(glm::vec2(1, 1))); + Error += glm::epsilonEqual(AngleA, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + float AngleB = glm::orientedAngle(glm::vec2(0, 1), glm::normalize(glm::vec2(1, 1))); + Error += glm::epsilonEqual(AngleB, -glm::pi() * 0.25f, 0.01f) ? 0 : 1; + float AngleC = glm::orientedAngle(glm::normalize(glm::vec2(1, 1)), glm::vec2(0, 1)); + Error += glm::epsilonEqual(AngleC, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + + return Error; +} + +int test_orientedAngle_vec3() +{ + int Error = 0; + + float AngleA = glm::orientedAngle(glm::vec3(1, 0, 0), glm::normalize(glm::vec3(1, 1, 0)), glm::vec3(0, 0, 1)); + Error += glm::epsilonEqual(AngleA, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + float AngleB = glm::orientedAngle(glm::vec3(0, 1, 0), glm::normalize(glm::vec3(1, 1, 0)), glm::vec3(0, 0, 1)); + Error += glm::epsilonEqual(AngleB, -glm::pi() * 0.25f, 0.01f) ? 0 : 1; + float AngleC = glm::orientedAngle(glm::normalize(glm::vec3(1, 1, 0)), glm::vec3(0, 1, 0), glm::vec3(0, 0, 1)); + Error += glm::epsilonEqual(AngleC, glm::pi() * 0.25f, 0.01f) ? 0 : 1; + + return Error; +} + +int main() +{ + int Error(0); + + Error += test_angle(); + Error += test_orientedAngle_vec2(); + Error += test_orientedAngle_vec3(); + + return Error; +} + + diff --git a/vendor/glm/test/gtx/gtx_vector_query.cpp b/vendor/glm/test/gtx/gtx_vector_query.cpp new file mode 100644 index 0000000..729f9e1 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_vector_query.cpp @@ -0,0 +1,82 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include +#include + +int test_areCollinear() +{ + int Error(0); + + { + bool TestA = glm::areCollinear(glm::vec2(-1), glm::vec2(1), 0.00001f); + Error += TestA ? 0 : 1; + } + + { + bool TestA = glm::areCollinear(glm::vec3(-1), glm::vec3(1), 0.00001f); + Error += TestA ? 0 : 1; + } + + { + bool TestA = glm::areCollinear(glm::vec4(-1), glm::vec4(1), 0.00001f); + Error += TestA ? 0 : 1; + } + + return Error; +} + +int test_areOrthogonal() +{ + int Error(0); + + bool TestA = glm::areOrthogonal(glm::vec2(1, 0), glm::vec2(0, 1), 0.00001f); + Error += TestA ? 0 : 1; + + return Error; +} + +int test_isNormalized() +{ + int Error(0); + + bool TestA = glm::isNormalized(glm::vec4(1, 0, 0, 0), 0.00001f); + Error += TestA ? 0 : 1; + + return Error; +} + +int test_isNull() +{ + int Error(0); + + bool TestA = glm::isNull(glm::vec4(0), 0.00001f); + Error += TestA ? 0 : 1; + + return Error; +} + +int test_areOrthonormal() +{ + int Error(0); + + bool TestA = glm::areOrthonormal(glm::vec2(1, 0), glm::vec2(0, 1), 0.00001f); + Error += TestA ? 0 : 1; + + return Error; +} + +int main() +{ + int Error(0); + + Error += test_areCollinear(); + Error += test_areOrthogonal(); + Error += test_isNormalized(); + Error += test_isNull(); + Error += test_areOrthonormal(); + + return Error; +} + + diff --git a/vendor/glm/test/gtx/gtx_wrap.cpp b/vendor/glm/test/gtx/gtx_wrap.cpp new file mode 100644 index 0000000..2354cc8 --- /dev/null +++ b/vendor/glm/test/gtx/gtx_wrap.cpp @@ -0,0 +1,191 @@ +#define GLM_ENABLE_EXPERIMENTAL +#include +#include +#include + +namespace clamp +{ + int test() + { + int Error(0); + + float A = glm::clamp(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::clamp(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::clamp(1.0f); + Error += glm::equal(C, 1.0f, 0.00001f) ? 0 : 1; + + float D = glm::clamp(-0.5f); + Error += glm::equal(D, 0.0f, 0.00001f) ? 0 : 1; + + float E = glm::clamp(1.5f); + Error += glm::equal(E, 1.0f, 0.00001f) ? 0 : 1; + + glm::vec2 K = glm::clamp(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::clamp(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::clamp(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::clamp(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; + } +}//namespace clamp + +namespace repeat +{ + int test() + { + int Error(0); + + float A = glm::repeat(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::repeat(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::repeat(1.0f); + Error += glm::equal(C, 0.0f, 0.00001f) ? 0 : 1; + + float D = glm::repeat(-0.5f); + Error += glm::equal(D, 0.5f, 0.00001f) ? 0 : 1; + + float E = glm::repeat(1.5f); + Error += glm::equal(E, 0.5f, 0.00001f) ? 0 : 1; + + float F = glm::repeat(0.9f); + Error += glm::equal(F, 0.9f, 0.00001f) ? 0 : 1; + + glm::vec2 K = glm::repeat(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::repeat(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::repeat(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::repeat(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; + } +}//namespace repeat + +namespace mirrorClamp +{ + int test() + { + int Error(0); + + float A = glm::mirrorClamp(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::mirrorClamp(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::mirrorClamp(1.1f); + Error += glm::equal(C, 0.1f, 0.00001f) ? 0 : 1; + + float D = glm::mirrorClamp(-0.5f); + Error += glm::equal(D, 0.5f, 0.00001f) ? 0 : 1; + + float E = glm::mirrorClamp(1.5f); + Error += glm::equal(E, 0.5f, 0.00001f) ? 0 : 1; + + float F = glm::mirrorClamp(0.9f); + Error += glm::equal(F, 0.9f, 0.00001f) ? 0 : 1; + + float G = glm::mirrorClamp(3.1f); + Error += glm::equal(G, 0.1f, 0.00001f) ? 0 : 1; + + float H = glm::mirrorClamp(-3.1f); + Error += glm::equal(H, 0.1f, 0.00001f) ? 0 : 1; + + float I = glm::mirrorClamp(-0.9f); + Error += glm::equal(I, 0.9f, 0.00001f) ? 0 : 1; + + glm::vec2 K = glm::mirrorClamp(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::mirrorClamp(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::mirrorClamp(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::mirrorClamp(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; + } +}//namespace mirrorClamp + +namespace mirrorRepeat +{ + int test() + { + int Error(0); + + float A = glm::mirrorRepeat(0.5f); + Error += glm::equal(A, 0.5f, 0.00001f) ? 0 : 1; + + float B = glm::mirrorRepeat(0.0f); + Error += glm::equal(B, 0.0f, 0.00001f) ? 0 : 1; + + float C = glm::mirrorRepeat(1.0f); + Error += glm::equal(C, 1.0f, 0.00001f) ? 0 : 1; + + float D = glm::mirrorRepeat(-0.5f); + Error += glm::equal(D, 0.5f, 0.00001f) ? 0 : 1; + + float E = glm::mirrorRepeat(1.5f); + Error += glm::equal(E, 0.5f, 0.00001f) ? 0 : 1; + + float F = glm::mirrorRepeat(0.9f); + Error += glm::equal(F, 0.9f, 0.00001f) ? 0 : 1; + + float G = glm::mirrorRepeat(3.0f); + Error += glm::equal(G, 1.0f, 0.00001f) ? 0 : 1; + + float H = glm::mirrorRepeat(-3.0f); + Error += glm::equal(H, 1.0f, 0.00001f) ? 0 : 1; + + float I = glm::mirrorRepeat(-1.0f); + Error += glm::equal(I, 1.0f, 0.00001f) ? 0 : 1; + + glm::vec2 K = glm::mirrorRepeat(glm::vec2(0.5f)); + Error += glm::all(glm::equal(K, glm::vec2(0.5f), glm::vec2(0.00001f))) ? 0 : 1; + + glm::vec3 L = glm::mirrorRepeat(glm::vec3(0.5f)); + Error += glm::all(glm::equal(L, glm::vec3(0.5f), glm::vec3(0.00001f))) ? 0 : 1; + + glm::vec4 M = glm::mirrorRepeat(glm::vec4(0.5f)); + Error += glm::all(glm::equal(M, glm::vec4(0.5f), glm::vec4(0.00001f))) ? 0 : 1; + + glm::vec1 N = glm::mirrorRepeat(glm::vec1(0.5f)); + Error += glm::all(glm::equal(N, glm::vec1(0.5f), glm::vec1(0.00001f))) ? 0 : 1; + + return Error; + } +}//namespace mirrorRepeat + +int main() +{ + int Error(0); + + Error += clamp::test(); + Error += repeat::test(); + Error += mirrorClamp::test(); + Error += mirrorRepeat::test(); + + return Error; +} diff --git a/vendor/glm/test/perf/CMakeLists.txt b/vendor/glm/test/perf/CMakeLists.txt new file mode 100644 index 0000000..19c7050 --- /dev/null +++ b/vendor/glm/test/perf/CMakeLists.txt @@ -0,0 +1,6 @@ +glmCreateTestGTC(perf_matrix_div) +glmCreateTestGTC(perf_matrix_inverse) +glmCreateTestGTC(perf_matrix_mul) +glmCreateTestGTC(perf_matrix_mul_vector) +glmCreateTestGTC(perf_matrix_transpose) +glmCreateTestGTC(perf_vector_mul_matrix) diff --git a/vendor/glm/test/perf/perf_matrix_div.cpp b/vendor/glm/test/perf/perf_matrix_div.cpp new file mode 100644 index 0000000..630188d --- /dev/null +++ b/vendor/glm/test/perf/perf_matrix_div.cpp @@ -0,0 +1,153 @@ +#define GLM_FORCE_INLINE +#include +#include +#include +#include +#include +#if GLM_CONFIG_SIMD == GLM_ENABLE +#include +#include +#include +#include + +template +static void test_mat_div_mat(matType const& M, std::vector const& I, std::vector& O) +{ + for (std::size_t i = 0, n = I.size(); i < n; ++i) + O[i] = M / I[i]; +} + +template +static int launch_mat_div_mat(std::vector& O, matType const& Transform, matType const& Scale, std::size_t Samples) +{ + typedef typename matType::value_type T; + + std::vector I(Samples); + O.resize(Samples); + + for(std::size_t i = 0; i < Samples; ++i) + I[i] = Scale * static_cast(i) + Scale; + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + test_mat_div_mat(Transform, I, O); + std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); + + return static_cast(std::chrono::duration_cast(t2 - t1).count()); +} + +template +static int comp_mat2_div_mat2(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4); + packedMatType const Scale(0.01, 0.02, 0.03, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_div_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_div_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +template +static int comp_mat3_div_mat3(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9); + packedMatType const Scale(0.01, 0.02, 0.03, 0.05, 0.01, 0.02, 0.03, 0.05, 0.01); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_div_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_div_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +template +static int comp_mat4_div_mat4(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + packedMatType const Scale(0.01, 0.02, 0.05, 0.04, 0.02, 0.08, 0.05, 0.01, 0.08, 0.03, 0.05, 0.06, 0.02, 0.03, 0.07, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_div_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_div_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int main() +{ + std::size_t const Samples = 100000; + + int Error = 0; + + std::printf("mat2 / mat2:\n"); + Error += comp_mat2_div_mat2(Samples); + + std::printf("dmat2 / dmat2:\n"); + Error += comp_mat2_div_mat2(Samples); + + std::printf("mat3 / mat3:\n"); + Error += comp_mat3_div_mat3(Samples); + + std::printf("dmat3 / dmat3:\n"); + Error += comp_mat3_div_mat3(Samples); + + std::printf("mat4 / mat4:\n"); + Error += comp_mat4_div_mat4(Samples); + + std::printf("dmat4 / dmat4:\n"); + Error += comp_mat4_div_mat4(Samples); + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/perf/perf_matrix_inverse.cpp b/vendor/glm/test/perf/perf_matrix_inverse.cpp new file mode 100644 index 0000000..1a989ae --- /dev/null +++ b/vendor/glm/test/perf/perf_matrix_inverse.cpp @@ -0,0 +1,150 @@ +#define GLM_FORCE_INLINE +#include +#include +#include +#include +#include +#if GLM_CONFIG_SIMD == GLM_ENABLE +#include +#include +#include +#include + +template +static void test_mat_inverse(std::vector const& I, std::vector& O) +{ + for (std::size_t i = 0, n = I.size(); i < n; ++i) + O[i] = glm::inverse(I[i]); +} + +template +static int launch_mat_inverse(std::vector& O, matType const& Scale, std::size_t Samples) +{ + typedef typename matType::value_type T; + + std::vector I(Samples); + O.resize(Samples); + + for(std::size_t i = 0; i < Samples; ++i) + I[i] = Scale * static_cast(i) + Scale; + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + test_mat_inverse(I, O); + std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); + + return static_cast(std::chrono::duration_cast(t2 - t1).count()); +} + +template +static int comp_mat2_inverse(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Scale(0.01, 0.02, 0.03, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_inverse(SISD, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_inverse(SIMD, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +template +static int comp_mat3_inverse(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Scale(0.01, 0.02, 0.03, 0.05, 0.01, 0.02, 0.03, 0.05, 0.01); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_inverse(SISD, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_inverse(SIMD, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +template +static int comp_mat4_inverse(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Scale(0.01, 0.02, 0.05, 0.04, 0.02, 0.08, 0.05, 0.01, 0.08, 0.03, 0.05, 0.06, 0.02, 0.03, 0.07, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_inverse(SISD, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_inverse(SIMD, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int main() +{ + std::size_t const Samples = 100000; + + int Error = 0; + + std::printf("glm::inverse(mat2):\n"); + Error += comp_mat2_inverse(Samples); + + std::printf("glm::inverse(dmat2):\n"); + Error += comp_mat2_inverse(Samples); + + std::printf("glm::inverse(mat3):\n"); + Error += comp_mat3_inverse(Samples); + + std::printf("glm::inverse(dmat3):\n"); + Error += comp_mat3_inverse(Samples); + + std::printf("glm::inverse(mat4):\n"); + Error += comp_mat4_inverse(Samples); + + std::printf("glm::inverse(dmat4):\n"); + Error += comp_mat4_inverse(Samples); + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/perf/perf_matrix_mul.cpp b/vendor/glm/test/perf/perf_matrix_mul.cpp new file mode 100644 index 0000000..d6b1f10 --- /dev/null +++ b/vendor/glm/test/perf/perf_matrix_mul.cpp @@ -0,0 +1,154 @@ +#define GLM_FORCE_INLINE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if GLM_CONFIG_SIMD == GLM_ENABLE +#include +#include +#include +#include + +template +static void test_mat_mul_mat(matType const& M, std::vector const& I, std::vector& O) +{ + for (std::size_t i = 0, n = I.size(); i < n; ++i) + O[i] = M * I[i]; +} + +template +static int launch_mat_mul_mat(std::vector& O, matType const& Transform, matType const& Scale, std::size_t Samples) +{ + typedef typename matType::value_type T; + + std::vector I(Samples); + O.resize(Samples); + + for(std::size_t i = 0; i < Samples; ++i) + I[i] = Scale * static_cast(i); + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + test_mat_mul_mat(Transform, I, O); + std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); + + return static_cast(std::chrono::duration_cast(t2 - t1).count()); +} + +template +static int comp_mat2_mul_mat2(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4); + packedMatType const Scale(0.01, 0.02, 0.03, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_mul_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_mul_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +template +static int comp_mat3_mul_mat3(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9); + packedMatType const Scale(0.01, 0.02, 0.03, 0.05, 0.01, 0.02, 0.03, 0.05, 0.01); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_mul_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_mul_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +template +static int comp_mat4_mul_mat4(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + packedMatType const Scale(0.01, 0.02, 0.03, 0.05, 0.01, 0.02, 0.03, 0.05, 0.01, 0.02, 0.03, 0.05, 0.01, 0.02, 0.03, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_mul_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_mul_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +int main() +{ + std::size_t const Samples = 100000; + + int Error = 0; + + std::printf("mat2 * mat2:\n"); + Error += comp_mat2_mul_mat2(Samples); + + std::printf("dmat2 * dmat2:\n"); + Error += comp_mat2_mul_mat2(Samples); + + std::printf("mat3 * mat3:\n"); + Error += comp_mat3_mul_mat3(Samples); + + std::printf("dmat3 * dmat3:\n"); + Error += comp_mat3_mul_mat3(Samples); + + std::printf("mat4 * mat4:\n"); + Error += comp_mat4_mul_mat4(Samples); + + std::printf("dmat4 * dmat4:\n"); + Error += comp_mat4_mul_mat4(Samples); + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/perf/perf_matrix_mul_vector.cpp b/vendor/glm/test/perf/perf_matrix_mul_vector.cpp new file mode 100644 index 0000000..8e555f8 --- /dev/null +++ b/vendor/glm/test/perf/perf_matrix_mul_vector.cpp @@ -0,0 +1,154 @@ +#define GLM_FORCE_INLINE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if GLM_CONFIG_SIMD == GLM_ENABLE +#include +#include +#include +#include + +template +static void test_mat_mul_vec(matType const& M, std::vector const& I, std::vector& O) +{ + for (std::size_t i = 0, n = I.size(); i < n; ++i) + O[i] = M * I[i]; +} + +template +static int launch_mat_mul_vec(std::vector& O, matType const& Transform, vecType const& Scale, std::size_t Samples) +{ + typedef typename matType::value_type T; + + std::vector I(Samples); + O.resize(Samples); + + for(std::size_t i = 0; i < Samples; ++i) + I[i] = Scale * static_cast(i); + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + test_mat_mul_vec(Transform, I, O); + std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); + + return static_cast(std::chrono::duration_cast(t2 - t1).count()); +} + +template +static int comp_mat2_mul_vec2(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4); + packedVecType const Scale(0.01, 0.02); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_mul_vec(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_mul_vec(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedVecType const A = SISD[i]; + packedVecType const B = packedVecType(SIMD[i]); + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +template +static int comp_mat3_mul_vec3(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9); + packedVecType const Scale(0.01, 0.02, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_mul_vec(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_mul_vec(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedVecType const A = SISD[i]; + packedVecType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +template +static int comp_mat4_mul_vec4(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + packedVecType const Scale(0.01, 0.02, 0.03, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_mul_vec(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_mul_vec(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedVecType const A = SISD[i]; + packedVecType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +int main() +{ + std::size_t const Samples = 100000; + + int Error = 0; + + std::printf("mat2 * vec2:\n"); + Error += comp_mat2_mul_vec2(Samples); + + std::printf("dmat2 * dvec2:\n"); + Error += comp_mat2_mul_vec2(Samples); + + std::printf("mat3 * vec3:\n"); + Error += comp_mat3_mul_vec3(Samples); + + std::printf("dmat3 * dvec3:\n"); + Error += comp_mat3_mul_vec3(Samples); + + std::printf("mat4 * vec4:\n"); + Error += comp_mat4_mul_vec4(Samples); + + std::printf("dmat4 * dvec4:\n"); + Error += comp_mat4_mul_vec4(Samples); + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/perf/perf_matrix_transpose.cpp b/vendor/glm/test/perf/perf_matrix_transpose.cpp new file mode 100644 index 0000000..2fdc782 --- /dev/null +++ b/vendor/glm/test/perf/perf_matrix_transpose.cpp @@ -0,0 +1,150 @@ +#define GLM_FORCE_INLINE +#include +#include +#include +#include +#include +#if GLM_CONFIG_SIMD == GLM_ENABLE +#include +#include +#include +#include + +template +static void test_mat_transpose(std::vector const& I, std::vector& O) +{ + for (std::size_t i = 0, n = I.size(); i < n; ++i) + O[i] = glm::transpose(I[i]); +} + +template +static int launch_mat_transpose(std::vector& O, matType const& Scale, std::size_t Samples) +{ + typedef typename matType::value_type T; + + std::vector I(Samples); + O.resize(Samples); + + for(std::size_t i = 0; i < Samples; ++i) + I[i] = Scale * static_cast(i) + Scale; + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + test_mat_transpose(I, O); + std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); + + return static_cast(std::chrono::duration_cast(t2 - t1).count()); +} + +template +static int comp_mat2_transpose(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Scale(0.01, 0.02, 0.03, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_transpose(SISD, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_transpose(SIMD, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +template +static int comp_mat3_transpose(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Scale(0.01, 0.02, 0.03, 0.05, 0.01, 0.02, 0.03, 0.05, 0.01); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_transpose(SISD, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_transpose(SIMD, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +template +static int comp_mat4_transpose(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Scale(0.01, 0.02, 0.05, 0.04, 0.02, 0.08, 0.05, 0.01, 0.08, 0.03, 0.05, 0.06, 0.02, 0.03, 0.07, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_mat_transpose(SISD, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_mat_transpose(SIMD, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedMatType const A = SISD[i]; + packedMatType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + assert(!Error); + } + + return Error; +} + +int main() +{ + std::size_t const Samples = 100000; + + int Error = 0; + + std::printf("glm::transpose(mat2):\n"); + Error += comp_mat2_transpose(Samples); + + std::printf("glm::transpose(dmat2):\n"); + Error += comp_mat2_transpose(Samples); + + std::printf("glm::transpose(mat3):\n"); + Error += comp_mat3_transpose(Samples); + + std::printf("glm::transpose(dmat3):\n"); + Error += comp_mat3_transpose(Samples); + + std::printf("glm::transpose(mat4):\n"); + Error += comp_mat4_transpose(Samples); + + std::printf("glm::transpose(dmat4):\n"); + Error += comp_mat4_transpose(Samples); + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/test/perf/perf_vector_mul_matrix.cpp b/vendor/glm/test/perf/perf_vector_mul_matrix.cpp new file mode 100644 index 0000000..20991df --- /dev/null +++ b/vendor/glm/test/perf/perf_vector_mul_matrix.cpp @@ -0,0 +1,154 @@ +#define GLM_FORCE_INLINE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if GLM_CONFIG_SIMD == GLM_ENABLE +#include +#include +#include +#include + +template +static void test_vec_mul_mat(matType const& M, std::vector const& I, std::vector& O) +{ + for (std::size_t i = 0, n = I.size(); i < n; ++i) + O[i] = I[i] * M; +} + +template +static int launch_vec_mul_mat(std::vector& O, matType const& Transform, vecType const& Scale, std::size_t Samples) +{ + typedef typename matType::value_type T; + + std::vector I(Samples); + O.resize(Samples); + + for(std::size_t i = 0; i < Samples; ++i) + I[i] = Scale * static_cast(i); + + std::chrono::high_resolution_clock::time_point t1 = std::chrono::high_resolution_clock::now(); + test_vec_mul_mat(Transform, I, O); + std::chrono::high_resolution_clock::time_point t2 = std::chrono::high_resolution_clock::now(); + + return static_cast(std::chrono::duration_cast(t2 - t1).count()); +} + +template +static int comp_vec2_mul_mat2(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4); + packedVecType const Scale(0.01, 0.02); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_vec_mul_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_vec_mul_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedVecType const A = SISD[i]; + packedVecType const B = packedVecType(SIMD[i]); + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +template +static int comp_vec3_mul_mat3(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9); + packedVecType const Scale(0.01, 0.02, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_vec_mul_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_vec_mul_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedVecType const A = SISD[i]; + packedVecType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +template +static int comp_vec4_mul_mat4(std::size_t Samples) +{ + typedef typename packedMatType::value_type T; + + int Error = 0; + + packedMatType const Transform(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + packedVecType const Scale(0.01, 0.02, 0.03, 0.05); + + std::vector SISD; + std::printf("- SISD: %d us\n", launch_vec_mul_mat(SISD, Transform, Scale, Samples)); + + std::vector SIMD; + std::printf("- SIMD: %d us\n", launch_vec_mul_mat(SIMD, Transform, Scale, Samples)); + + for(std::size_t i = 0; i < Samples; ++i) + { + packedVecType const A = SISD[i]; + packedVecType const B = SIMD[i]; + Error += glm::all(glm::equal(A, B, static_cast(0.001))) ? 0 : 1; + } + + return Error; +} + +int main() +{ + std::size_t const Samples = 100000; + + int Error = 0; + + std::printf("vec2 * mat2:\n"); + Error += comp_vec2_mul_mat2(Samples); + + std::printf("dvec2 * dmat2:\n"); + Error += comp_vec2_mul_mat2(Samples); + + std::printf("vec3 * mat3:\n"); + Error += comp_vec3_mul_mat3(Samples); + + std::printf("dvec3 * dmat3:\n"); + Error += comp_vec3_mul_mat3(Samples); + + std::printf("vec4 * mat4:\n"); + Error += comp_vec4_mul_mat4(Samples); + + std::printf("dvec4 * dmat4:\n"); + Error += comp_vec4_mul_mat4(Samples); + + return Error; +} + +#else + +int main() +{ + return 0; +} + +#endif diff --git a/vendor/glm/util/autoexp.txt b/vendor/glm/util/autoexp.txt new file mode 100644 index 0000000..5a07bed --- /dev/null +++ b/vendor/glm/util/autoexp.txt @@ -0,0 +1,28 @@ +[Visualizer] + +glm::detail::tvec2<*>{ + preview ( + #(#($c.x,$c.y)) + ) + children ( + #([x]: $c.x,[y]: $c.y) + ) +} + +glm::detail::tvec3<*>{ + preview ( + #($e.x,$e.y,$e.z) + ) + children ( + #([x]: $e.x,[y]: $e.y,[z]: $e.z) + ) +} + +glm::detail::tvec4<*>{ + preview ( + #($c.x,$c.y,$c.z,$c.w) + ) + children ( + #([x]: $e.x,[y]: $e.y,[z]: $e.z, #([w]: $e.w)) + ) +} diff --git a/vendor/glm/util/autoexp.vc2010.dat b/vendor/glm/util/autoexp.vc2010.dat new file mode 100644 index 0000000..e28d31d --- /dev/null +++ b/vendor/glm/util/autoexp.vc2010.dat @@ -0,0 +1,3896 @@ +; AutoExp.Dat - templates for automatically expanding data +; Copyright(c) Microsoft Corporation. All Rights Reserved. +;--------------------------------------------------------------- +; +; While debugging, Data Tips and items in the Watch and Variable +; windows are automatically expanded to show their most important +; elements. The expansion follows the format given by the rules +; in this file. You can add rules for your types or change the +; predefined rules. +; +; For good examples, read the rules in this file. +; +; To find what the debugger considers the type of a variable to +; be, add it to the Watch window and look at the Type column. +; +; An AutoExpand rule is a line with the name of a type, an equals +; sign, and text with replaceable parts in angle brackets. The +; part in angle brackets names a member of the type and an +; optional Watch format specifier. +; +; AutoExpand rules use the following syntax. The equals sign (=), +; angle brackets (<>), and comma are taken literally. Square +; brackets ([]) indicate optional items. +; +; type=[text]... +; +; type Name of the type (may be followed by <*> for template +; types such as the ATL types listed below). +; +; text Any text.Usually the name of the member to display, +; or a shorthand name for the member. +; +; member Name of a member to display. +; +; format Watch format specifier. One of the following: +; +; Letter Description Sample Display +; ------ -------------------------- ------------ ------------- +; d,i Signed decimal integer 0xF000F065,d -268373915 +; u Unsigned decimal integer 0x0065,u 101 +; o Unsigned octal integer 0xF065,o 0170145 +; x,X Hexadecimal integer 61541,X 0X0000F065 +; l,h long or short prefix for 00406042,hx 0x0c22 +; d, i, u, o, x, X +; f Signed floating-point 3./2.,f 1.500000 +; e Signed scientific-notation 3./2.,e 1.500000e+000 +; g Shorter of e and f 3./2.,g 1.5 +; c Single character 0x0065,c 'e' +; s Zero-terminated string pVar,s "Hello world" +; su Unicode string pVar,su "Hello world" +; +; For details of other format specifiers see Help under: +; "format specifiers/watch variable" +; +; The special format <,t> specifies the name of the most-derived +; type of the object. This is especially useful with pointers or +; references to a base class. +; +; If there is no rule for a class, the base classes are checked for +; a matching rule. +; +; There are some special entries allowed in the AutoExpand section: +; $BUILTIN is used to display more complex types that need to do more +; than just show a member variable or two. +; $ADDIN allows external DLLs to be added to display even more complex +; types via the EE Add-in API. The first argument is the DLL name, the +; second argument is the name of the export from the DLL to use. For +; further information on this API see the sample called EEAddIn. +; +; WARNING: if hexadecimal mode is on in the watch window, all numbers here are +; evaluated in hex, e.g. 42 becomes 0x42 + +[AutoExpand] + +; from windef.h +tagPOINT =x= y= +tagRECT =top= bottom= left= right= + +; from winuser.h +tagMSG =msg= wp= lp= + +; intrinsics +__m64 = +__m128=$BUILTIN(M128) +__m128i=$BUILTIN(M128I) +__m128d=$BUILTIN(M128D) + +; from afxwin.h +CDC =hDC= attrib= +CPaintDC =<,t> hWnd= +CPoint =x= y= +CRect =top= bottom= left= right= +CSize =cx= cy= +CWnd =<,t> hWnd= +CWinApp =<,t> +CWinThread =<,t> h= proc= + +; from afxcoll.h +CPtrList =cnt= + +; from afxstat_.h +CProcessLocalObject =<,t> +CThreadLocalObject =<,t> + +; from afx.h +CArchiveException =cause= +CFile =hFile= name= +CFileException =cause= OS Error=m_lOsError +CMemFile =pos= size= +CObject =<,t> +CRuntimeClass = +CStdioFile =FILE*= name= +CTimeSpan =time= +CTime =time= + +; from afxcoll.h +CByteArray =count= +CStringList =count= +; same for all CXXXArray classes +; same for CXXXList +; same for CMapXXToXX + +; various string classes from MFC & ATL + +_com_error= +_bstr_t=m_wstr,su> (m_RefCount,u>) +_com_ptr_t<*>= +_LARGE_INTEGER= +_ULARGE_INTEGER= +ATL::CComPtr<*>=

+ +ATL::CComQIPtr<*>=

+ +tagVARIANT=$BUILTIN(VARIANT) +VARIANT=$BUILTIN(VARIANT) +_GUID=$BUILTIN(GUID) + +; see EEAddIn sample for how to use these +;_SYSTEMTIME=$ADDIN(EEAddIn.dll,AddIn_SystemTime) +;_FILETIME=$ADDIN(EEAddIn.dll,AddIn_FileTime) + +[Visualizer] +; This section contains visualizers for STL and ATL containers +; DO NOT MODIFY +ATL::CStringT|CSimpleStringT|ATL::CSimpleStringT{ + preview ([$e.m_pszData,s]) + stringview ([$e.m_pszData,sb]) +} +ATL::CStringT|CSimpleStringT|ATL::CSimpleStringT|ATL::CStringT|CSimpleStringT|ATL::CSimpleStringT{ + preview ([$e.m_pszData,su]) + stringview ([$e.m_pszData,sub]) +} +ATL::CComBSTR{ + preview ([$e.m_str,su]) + stringview ([$e.m_str,sub]) +} + + +; Many visualizers use nested #()s. +; Why not use #(foo, bar) instead of #(#(foo), #(bar))? +; The former alphabetically sorts its fields, while the latter does not. + +;------------------------------------------------------------------------------ +; std::pair from +;------------------------------------------------------------------------------ +std::pair<*>{ + ; pair is previewed with "(, )". + preview ( + #( + "(", + $e.first, + ", ", + $e.second, + ")" + ) + ) + + ; We gloss over the fact that first and second are actually stored in _Pair_base. + children ( + #( + #(first : $e.first), + #(second : $e.second) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::plus, etc. from +;------------------------------------------------------------------------------ +; STL functors are previewed with their names. +; They have no state, so they have no children. +std::plus<*>{ + preview ( "plus" ) + children ( #array(expr: 0, size: 0) ) +} +std::minus<*>{ + preview ( "minus" ) + children ( #array(expr: 0, size: 0) ) +} +std::multiplies<*>{ + preview ( "multiplies" ) + children ( #array(expr: 0, size: 0) ) +} +std::divides<*>{ + preview ( "divides" ) + children ( #array(expr: 0, size: 0) ) +} +std::modulus<*>{ + preview ( "modulus" ) + children ( #array(expr: 0, size: 0) ) +} +std::negate<*>{ + preview ( "negate" ) + children ( #array(expr: 0, size: 0) ) +} +std::equal_to<*>{ + preview ( "equal_to" ) + children ( #array(expr: 0, size: 0) ) +} +std::not_equal_to<*>{ + preview ( "not_equal_to" ) + children ( #array(expr: 0, size: 0) ) +} +std::greater<*>{ + preview ( "greater" ) + children ( #array(expr: 0, size: 0) ) +} +std::less<*>{ + preview ( "less" ) + children ( #array(expr: 0, size: 0) ) +} +std::greater_equal<*>{ + preview ( "greater_equal" ) + children ( #array(expr: 0, size: 0) ) +} +std::less_equal<*>{ + preview ( "less_equal" ) + children ( #array(expr: 0, size: 0) ) +} +std::logical_and<*>{ + preview ( "logical_and" ) + children ( #array(expr: 0, size: 0) ) +} +std::logical_or<*>{ + preview ( "logical_or" ) + children ( #array(expr: 0, size: 0) ) +} +std::logical_not<*>{ + preview ( "logical_not" ) + children ( #array(expr: 0, size: 0) ) +} + +;------------------------------------------------------------------------------ +; std::not1() from +; std::not2() from +;------------------------------------------------------------------------------ +; STL negators are previewed with "not[12]()". +; They have a child with the fake name of [pred], so that the +; stored functor can be inspected. +std::unary_negate<*>{ + preview ( + #( + "not1(", + $e._Functor, + ")" + ) + ) + + children ( + #([pred] : $e._Functor) + ) +} +std::binary_negate<*>{ + preview ( + #( + "not2(", + $e._Functor, + ")" + ) + ) + + children ( + #([pred] : $e._Functor) + ) +} + +;------------------------------------------------------------------------------ +; std::bind1st() from +; std::bind2nd() from +;------------------------------------------------------------------------------ +; STL binders are previewed with "bind1st(, )" or "bind2nd(, )". +; We gloss over the fact that they derive from unary_function. +std::binder1st<*>{ + preview ( + #( + "bind1st(", + $e.op, + ", ", + $e.value, + ")" + ) + ) + + children ( + #( + #(op : $e.op), + #(value : $e.value) + ) + ) +} +std::binder2nd<*>{ + preview ( + #( + "bind2nd(", + $e.op, + ", ", + $e.value, + ")" + ) + ) + + children ( + #( + #(op : $e.op), + #(value : $e.value) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::ptr_fun() from +;------------------------------------------------------------------------------ +; STL function pointer adaptors are previewed with "ptr_fun()". +; Function pointers have no children, so the adaptors have no children. +std::pointer_to_unary_function<*>|std::pointer_to_binary_function<*>{ + preview ( + #( + "ptr_fun(", + $e._Pfun, + ")" + ) + ) + + children ( #array(expr: 0, size: 0) ) +} + +;------------------------------------------------------------------------------ +; std::mem_fun() from +; std::mem_fun_ref() from +;------------------------------------------------------------------------------ +; See ptr_fun(). +std::mem_fun_t<*>|std::mem_fun1_t<*>|std::const_mem_fun_t<*>|std::const_mem_fun1_t<*>{ + preview ( + #( + "mem_fun(", + $e._Pmemfun, + ")" + ) + ) + + children ( #array(expr: 0, size: 0) ) +} +std::mem_fun_ref_t<*>|std::mem_fun1_ref_t<*>|std::const_mem_fun_ref_t<*>|std::const_mem_fun1_ref_t<*>{ + preview ( + #( + "mem_fun_ref(", + $e._Pmemfun, + ")" + ) + ) + + children ( #array(expr: 0, size: 0) ) +} + +;------------------------------------------------------------------------------ +; std::auto_ptr from +;------------------------------------------------------------------------------ +std::auto_ptr<*>{ + ; An empty auto_ptr is previewed with "empty". + ; Otherwise, it is previewed with "auto_ptr ". + preview ( + #if ($e._Myptr == 0) ( + "empty" + ) #else ( + #( + "auto_ptr ", + *$e._Myptr + ) + ) + ) + + ; An empty auto_ptr has no children. + ; Otherwise, it has a single child, its stored pointer, with a fake name of [ptr]. + children ( + #if ($e._Myptr == 0) ( + #array(expr: 0, size: 0) + ) #else ( + #([ptr] : $e._Myptr) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::basic_string from +;------------------------------------------------------------------------------ +; basic_string is previewed with its stored string. +; It has [size] and [capacity] children, followed by [0], [1], [2], etc. children +; displaying its stored characters. +; The ($e._Myres) < ($e._BUF_SIZE) test determines whether the Small String Optimization +; is in effect. +; NOTE: The parentheses in ($e._Myres) < ($e._BUF_SIZE) are necessary. +std::basic_string{ + preview ( #if (($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,s] ) #else ( [$e._Bx._Ptr,s] )) + stringview ( #if (($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,sb] ) #else ( [$e._Bx._Ptr,sb] )) + + children ( + #( + #([size] : $e._Mysize), + #([capacity] : $e._Myres), + #if (($e._Myres) < ($e._BUF_SIZE)) ( + #array(expr: $e._Bx._Buf[$i], size: $e._Mysize) + ) #else ( + #array(expr: $e._Bx._Ptr[$i], size: $e._Mysize) + ) + ) + ) +} +std::basic_string|std::basic_string{ + preview ( #if (($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,su] ) #else ( [$e._Bx._Ptr,su] )) + stringview ( #if (($e._Myres) < ($e._BUF_SIZE)) ( [$e._Bx._Buf,sub] ) #else ( [$e._Bx._Ptr,sub] )) + + children ( + #( + #([size] : $e._Mysize), + #([capacity] : $e._Myres), + #if (($e._Myres) < ($e._BUF_SIZE)) ( + #array(expr: $e._Bx._Buf[$i], size: $e._Mysize) + ) #else ( + #array(expr: $e._Bx._Ptr[$i], size: $e._Mysize) + ) + ) + ) +} +std::_String_iterator|std::_String_const_iterator{ + preview ( [$e._Ptr,s] ) + stringview ( [$e._Ptr,sb] ) + children ( #([ptr] : $e._Ptr) ) +} +std::_String_iterator|std::_String_const_iterator|std::_String_iterator|std::_String_const_iterator{ + preview ( [$e._Ptr,su] ) + stringview ( [$e._Ptr,sub] ) + children ( #([ptr] : $e._Ptr) ) +} + +;------------------------------------------------------------------------------ +; std::vector from +;------------------------------------------------------------------------------ +; Despite its packed representation, vector is visualized like vector. +std::vector{ + preview ( + #( + "[", + $e._Mysize, + "](", + #array( + expr: (bool)(($e._Myvec._Myfirst[$i / _VBITS] >> ($i % _VBITS)) & 1), + size: $e._Mysize + ), + ")" + ) + ) + + children ( + #( + #([size] : $e._Mysize), + #([capacity] : ($e._Myvec._Myend - $e._Myvec._Myfirst) * _VBITS), + #array( + expr: (bool)(($e._Myvec._Myfirst[$i / _VBITS] >> ($i % _VBITS)) & 1), + size: $e._Mysize + ) + ) + ) +} +std::_Vb_reference<*>|std::_Vb_iterator<*>|std::_Vb_const_iterator<*>{ + preview ( + (bool)((*$e._Myptr >> $e._Myoff) & 1) + ) + + children ( + #( + #([ptr] : $e._Myptr), + #([offset] : $e._Myoff) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::vector from +;------------------------------------------------------------------------------ +; vector is previewed with "[]()". +; It has [size] and [capacity] children, followed by its elements. +; The other containers follow its example. +std::vector<*>{ + preview ( + #( + "[", + $e._Mylast - $e._Myfirst, + "](", + #array( + expr: $e._Myfirst[$i], + size: $e._Mylast - $e._Myfirst + ), + ")" + ) + ) + + children ( + #( + #([size] : $e._Mylast - $e._Myfirst), + #([capacity] : $e._Myend - $e._Myfirst), + #array( + expr: $e._Myfirst[$i], + size: $e._Mylast - $e._Myfirst + ) + ) + ) +} +std::_Vector_iterator<*>|std::_Vector_const_iterator<*>{ + preview ( + *$e._Ptr + ) + + children ( + #([ptr] : $e._Ptr) + ) +} + +;------------------------------------------------------------------------------ +; std::deque from +;------------------------------------------------------------------------------ +std::deque<*>{ + preview ( + #( + "[", + $e._Mysize, + "](", + #array( + expr: $e._Map[(($i + $e._Myoff) / $e._EEN_DS) % $e._Mapsize][($i + $e._Myoff) % $e._EEN_DS], + size: $e._Mysize + ), + ")" + ) + ) + + children ( + #( + #array( + expr: $e._Map[(($i + $e._Myoff) / $e._EEN_DS) % $e._Mapsize][($i + $e._Myoff) % $e._EEN_DS], + size: $e._Mysize + ) + ) + ) +} +std::_Deque_iterator<*,*>|std::_Deque_const_iterator<*,*>{ + preview ( + #if ($e._Myoff >= ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Myoff + ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Mysize) ( + "end" + ) #else ( + ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Map[($e._Myoff / ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_EEN_DS) % ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Mapsize][$e._Myoff % ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_EEN_DS] + ) + ) + + children ( + #if ($e._Myoff >= ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Myoff + ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Mysize) ( + #array(expr: 0, size: 0) + ) #else ( + #( + #([index] : $e._Myoff - ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Myoff), + #([ptr] : &((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Map[($e._Myoff / ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_EEN_DS) % ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_Mapsize][$e._Myoff % ((std::deque<$T1,$T2> *)$e._Myproxy->_Mycont)->_EEN_DS] ) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::list from +;------------------------------------------------------------------------------ +std::list<*>{ + preview ( + #( + "[", + $e._Mysize, + "](", + #list( + head: $e._Myhead->_Next, + size: $e._Mysize, + next: _Next + ) : $e._Myval, + ")" + ) + ) + + children ( + #list( + head: $e._Myhead->_Next, + size: $e._Mysize, + next: _Next + ) : $e._Myval + ) +} +std::_List_iterator<*>|std::_List_const_iterator<*>{ + preview ( $e._Ptr->_Myval ) + children ( #([ptr] : &$e._Ptr->_Myval) ) +} + +;------------------------------------------------------------------------------ +; std::queue from +; std::stack from +;------------------------------------------------------------------------------ +std::queue<*>|std::stack<*>{ + preview ( $e.c ) + children ( #(c : $e.c) ) +} + +;------------------------------------------------------------------------------ +; std::priority_queue from +;------------------------------------------------------------------------------ +std::priority_queue<*>{ + preview ( $e.c ) + + children ( + #( + #(c [heap]: $e.c), + #(comp : $e.comp) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::map from +; std::multimap from +; std::set from +; std::multiset from +;------------------------------------------------------------------------------ +std::map<*>|std::multimap<*>|std::set<*>|std::multiset<*>{ + preview ( + #( + "[", + $e._Mysize, + "](", + #tree( + head: $e._Myhead->_Parent, + skip: $e._Myhead, + left: _Left, + right: _Right, + size: $e._Mysize + ) : $e._Myval, + ")" + ) + ) + + children ( + #( + #([comp] : $e.comp), + #tree( + head: $e._Myhead->_Parent, + skip: $e._Myhead, + left: _Left, + right: _Right, + size: $e._Mysize + ) : $e._Myval + ) + ) +} +std::_Tree_iterator<*>|std::_Tree_const_iterator<*>{ + preview ( $e._Ptr->_Myval ) + children ( #([ptr] : &$e._Ptr->_Myval) ) +} + +;------------------------------------------------------------------------------ +; std::bitset from +;------------------------------------------------------------------------------ +std::bitset<*>{ + preview ( + #( + "[", + $e._EEN_BITS, + "](", + #array( + expr: [($e._Array[$i / $e._Bitsperword] >> ($i % $e._Bitsperword)) & 1,d], + size: $e._EEN_BITS + ), + ")" + ) + ) + + children ( + #array( + expr: [($e._Array[$i / $e._Bitsperword] >> ($i % $e._Bitsperword)) & 1,d], + size: $e._EEN_BITS + ) + ) +} +std::bitset<*>::reference{ + preview ( + [($e._Pbitset->_Array[$i / $e._Pbitset->_Bitsperword] >> ($e._Mypos % $e._Pbitset->_Bitsperword)) & 1,d] + ) + + children ( + #( + #([bitset] : $e._Pbitset), + #([pos] : $e._Mypos) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::reverse_iterator from +;------------------------------------------------------------------------------ +std::reverse_iterator >|std::reverse_iterator >{ + preview ( + #( + "reverse_iterator to ", + $e.current._Ptr[-1] + ) + ) + + children ( + #( + #([to] : $e.current._Ptr - 1), + #(current : $e.current) + ) + ) +} +std::reverse_iterator >|std::reverse_iterator >{ + preview ( + #( + "reverse_iterator to ", + #if ($e.current._Myoff != 0) ( + (bool)((*$e.current._Myptr >> ($e.current._Myoff - 1)) & 1) + ) #else ( + (bool)(($e.current._Myptr[-1] >> (_VBITS - 1)) & 1) + ) + ) + ) + + children ( + #if ($e.current._Myoff != 0) ( + #( + #([to ptr] : $e.current._Myptr), + #([to offset] : $e.current._Myoff - 1), + #(current : $e.current) + ) + ) #else ( + #( + #([to ptr] : $e.current._Myptr - 1), + #([to offset] : _VBITS - 1), + #(current : $e.current) + ) + ) + ) +} +std::reverse_iterator >|std::reverse_iterator >{ + preview ( + #( + "reverse_iterator to ", + $e.current._Ptr[-1] + ) + ) + + children ( + #( + #([to] : $e.current._Ptr - 1), + #(current : $e.current) + ) + ) +} +std::reverse_iterator >|std::reverse_iterator >{ + preview ( + #( + "reverse_iterator to ", + #if ($e.current._Myoff == ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_Myoff) ( + "end" + ) #else ( + ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_Map[(($e.current._Myoff - 1) / ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_EEN_DS) % ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_Mapsize][($e.current._Myoff - 1) % ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_EEN_DS] + ) + ) + ) + + children ( + #if ($e.current._Myoff == ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_Myoff) ( + #(current : $e.current) + ) #else ( + #( + #([to index] : ($e.current._Myoff - 1) - ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_Myoff), + #([to ptr] : &((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_Map[(($e.current._Myoff - 1) / ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_EEN_DS) % ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_Mapsize][($e.current._Myoff - 1) % ((std::deque<$T1,$T2> *)$e.current._Myproxy->_Mycont)->_EEN_DS] ), + #(current : $e.current) + ) + ) + ) +} +std::reverse_iterator >|std::reverse_iterator >{ + preview ( + #( + "reverse_iterator to ", + $e.current._Ptr->_Prev->_Myval + ) + ) + + children ( + #( + #([to] : &$e.current._Ptr->_Prev->_Myval), + #(current : $e.current) + ) + ) +} +std::reverse_iterator >|std::reverse_iterator >{ + preview ( + #( + "reverse_iterator to ", + #if ($e.current._EEN_IDL == 0) ( + $e.current._Ptr[-1] + ) #else ( + #if ($e.current._Idx == 0) ( + "end" + ) #else ( + $e.current._Ptr[$e.current._Idx - 1] + ) + ) + ) + ) + + children ( + #if ($e.current._EEN_IDL == 0) ( + #( + #([to] : $e.current._Ptr - 1), + #(current : $e.current) + ) + ) #else ( + #if ($e.current._Idx == 0) ( + #(current : $e.current) + ) #else ( + #( + #([to] : $e.current._Ptr + $e.current._Idx - 1), + #(current : $e.current) + ) + ) + ) + ) +} +std::reverse_iterator<*>{ + preview ( + #( + "reverse_iterator current ", + $e.current + ) + ) + + children ( + #(current : $e.current) + ) +} + +;------------------------------------------------------------------------------ +; std::complex from +;------------------------------------------------------------------------------ +std::complex<*>{ + preview ( + #if ($e._Val[1] == 0) ( + ; Purely real. + $e._Val[0] + ) #else ( + #if ($e._Val[0] == 0) ( + ; Purely imaginary. + #if ($e._Val[1] < 0) ( + #("-i*", -$e._Val[1]) + ) #else ( + #("i*", $e._Val[1]) + ) + ) #else ( + ; Mixed. + #if ($e._Val[1] < 0) ( + #($e._Val[0], "-i*", -$e._Val[1]) + ) #else ( + #($e._Val[0], "+i*", $e._Val[1]) + ) + ) + ) + ) + + children ( + #( + #(real : $e._Val[0]), + #(imag : $e._Val[1]) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::valarray from +;------------------------------------------------------------------------------ +std::valarray<*>{ + preview ( + #( + "[", + $e._Mysize, + "](", + #array( + expr: $e._Myptr[$i], + size: $e._Mysize + ), + ")" + ) + ) + + children ( + #array( + expr: $e._Myptr[$i], + size: $e._Mysize + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::reference_wrapper from +;------------------------------------------------------------------------------ +std::tr1::reference_wrapper<*>{ + preview ( + #if ($e._Callee._EEN_INDIRECT == 1) ( + ; For ordinary T, reference_wrapper stores a T * _Callee._Ptr + ; which is non-null. Actual references are previewed with what they + ; refer to, so reference_wrapper is previewed with dereferencing its + ; stored pointer. + *$e._Callee._Ptr + ) #else ( + ; When T is a pointer to data member type, reference_wrapper + ; stores a T _Callee._Object directly. + $e._Callee._Object + ) + ) + + children ( + #if ($e._Callee._EEN_INDIRECT == 1) ( + ; Actual references have the same children as what they refer to. + ; Unfortunately, there appears to be no way to imitate this exactly. + ; Therefore, we make reference_wrapper appear to have a single + ; child, its stored pointer, with a fake name of [ptr]. + #([ptr] : $e._Callee._Ptr) + ) #else ( + ; When T is a pointer to data member type, T has no children, + ; so we make reference_wrapper appear to have no children. + #array(expr: 0, size: 0) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::shared_ptr from +;------------------------------------------------------------------------------ +std::tr1::_Ref_count<*>{ + preview ( "default" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ref_count_del<*>{ + preview ( "custom deleter" ) + children ( #([deleter] : $e._Dtor) ) +} +std::tr1::_Ref_count_del_alloc<*>{ + preview ( "custom deleter, custom allocator" ) + children ( + #( + #([deleter] : $e._Dtor), + #([allocator] : $e._Myal) + ) + ) +} +std::tr1::_Ref_count_obj<*>{ + preview ( "make_shared" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ref_count_obj_alloc<*>{ + preview ( "allocate_shared" ) + children ( #([allocator] : $e._Myal) ) +} +std::tr1::shared_ptr<*>{ + preview ( + ; shared_ptr stores a T * _Ptr . + #if ($e._Ptr == 0) ( + ; A default-constructed shared_ptr has a null _Ptr and a null _Rep, + ; and is formally said to be empty. + ; A shared_ptr constructed from a null pointer has a null _Ptr + ; and a NON-null _Rep . It is formally said to own the null pointer. + ; We preview both with "empty". + "empty" + ) #else ( + ; Raw pointers are previewed with " ". + ; auto_ptr is previewed with "auto_ptr ". + ; Following these examples, shared_ptr is previewed with + ; "shared_ptr [N strong refs, M weak refs]". + #( + "shared_ptr ", + *$e._Ptr, + " [", + $e._Rep->_Uses, + #if ($e._Rep->_Uses == 1) (" strong ref") #else (" strong refs"), + #if ($e._Rep->_Weaks - 1 > 0) ( + #( + ", ", + $e._Rep->_Weaks - 1, + #if ($e._Rep->_Weaks - 1 == 1) (" weak ref") #else (" weak refs") + ) + ), + "] [", + *$e._Rep, + "]" + ) + ; Note: _Rep->_Uses counts how many shared_ptrs share ownership of the object, + ; so we directly display it as the strong reference count. + ; _Rep->_Weaks counts how many shared_ptrs and weak_ptrs share ownership of + ; the "representation object" (or "control block"). All of the shared_ptrs are + ; counted as a single owner. That is, _Weaks is initialized to 1, and when + ; _Uses falls to 0, _Weaks is decremented. This avoids incrementing and decrementing + ; _Weaks every time that a shared_ptr gains or loses ownership. Therefore, + ; _Weaks - 1 is the weak reference count, the number of weak_ptrs that are observing + ; the shared object. + ) + ) + + children ( + #if ($e._Ptr == 0) ( + ; We make empty shared_ptrs (and shared_ptrs that own + ; the null pointer) appear to have no children. + #array(expr: 0, size: 0) + ) #else ( + #( + ; We make shared_ptr appear to have two children: + + ; Its stored pointer, with a fake name of [ptr]. + #([ptr] : $e._Ptr), + + ; Its deleter and allocator, which may be default or custom. + #([deleter and allocator] : *$e._Rep) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::weak_ptr from +;------------------------------------------------------------------------------ +std::tr1::weak_ptr<*>{ + preview ( + #if ($e._Ptr == 0) ( + "empty" + ) #elif ($e._Rep->_Uses == 0) ( + ; weak_ptr is just like shared_ptr, except that a weak_ptr can be expired. + #( + "expired [", + *$e._Rep, + "]" + ) + ) #else ( + #( + "weak_ptr ", + *$e._Ptr, + " [", + $e._Rep->_Uses, + #if ($e._Rep->_Uses == 1) (" strong ref") #else (" strong refs"), + #if ($e._Rep->_Weaks - 1 > 0) ( + #( + ", ", + $e._Rep->_Weaks - 1, + #if ($e._Rep->_Weaks - 1 == 1) (" weak ref") #else (" weak refs") + ) + ), + "] [", + *$e._Rep, + "]" + ) + ) + ) + + children ( + #if ($e._Ptr == 0) ( + #array(expr: 0, size: 0) + ) #elif ($e._Rep->_Uses == 0) ( + ; When a weak_ptr is expired, we show its deleter and allocator. + ; The deleter has already been used, but the control block has not yet been deallocated. + #([deleter and allocator] : *$e._Rep) + ) #else ( + #( + #([ptr] : $e._Ptr), + #([deleter and allocator] : *$e._Rep) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::mem_fn() from +;------------------------------------------------------------------------------ +; Note that when mem_fn() is given a data member pointer, it returns a _Call_wrapper<_Callable_pmd<*> > . +; Data member pointers themselves don't have useful previews, so we don't attempt to visualize this. +; When mem_fn() is given a member function pointer, it returns a _Mem_fn[N], which we can visualize. +std::tr1::_Mem_fn1<*>|std::tr1::_Mem_fn2<*>|std::tr1::_Mem_fn3<*>|std::tr1::_Mem_fn4<*>|std::tr1::_Mem_fn5<*>|std::tr1::_Mem_fn6<*>|std::tr1::_Mem_fn7<*>|std::tr1::_Mem_fn8<*>|std::tr1::_Mem_fn9<*>|std::tr1::_Mem_fn10<*>{ + preview ( + ; We preview the functor returned by mem_fn() with "mem_fn()". + #( + "mem_fn(", + $e._Callee._Object, + ")" + ) + ) + + children ( + ; Member function pointers have no children. + #array(expr: 0, size: 0) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::bind() from +;------------------------------------------------------------------------------ +; bind() placeholders are previewed with their names. +; They have no state, so they have no children. +std::tr1::_Ph<1>{ + preview ( "_1" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<2>{ + preview ( "_2" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<3>{ + preview ( "_3" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<4>{ + preview ( "_4" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<5>{ + preview ( "_5" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<6>{ + preview ( "_6" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<7>{ + preview ( "_7" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<8>{ + preview ( "_8" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<9>{ + preview ( "_9" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::_Ph<10>{ + preview ( "_10" ) + children ( #array(expr: 0, size: 0) ) +} + +; The functor returned by bind(f, t1, t2) is previewed with "bind(f, t1, t2)". +; It has children with the fake names of [f], [t1], [t2], etc. +std::tr1::_Bind<*,*,std::tr1::_Bind0<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind0<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind1<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind1<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind2<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind2<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind3<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind3<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind4<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind4<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ", ", $e._Bx._Vx3, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2), + #([t4] : $e._Bx._Vx3) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind5<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind5<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ", ", $e._Bx._Vx3, + ", ", $e._Bx._Vx4, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2), + #([t4] : $e._Bx._Vx3), + #([t5] : $e._Bx._Vx4) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind6<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind6<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ", ", $e._Bx._Vx3, + ", ", $e._Bx._Vx4, + ", ", $e._Bx._Vx5, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2), + #([t4] : $e._Bx._Vx3), + #([t5] : $e._Bx._Vx4), + #([t6] : $e._Bx._Vx5) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind7<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind7<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ", ", $e._Bx._Vx3, + ", ", $e._Bx._Vx4, + ", ", $e._Bx._Vx5, + ", ", $e._Bx._Vx6, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2), + #([t4] : $e._Bx._Vx3), + #([t5] : $e._Bx._Vx4), + #([t6] : $e._Bx._Vx5), + #([t7] : $e._Bx._Vx6) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind8<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind8<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ", ", $e._Bx._Vx3, + ", ", $e._Bx._Vx4, + ", ", $e._Bx._Vx5, + ", ", $e._Bx._Vx6, + ", ", $e._Bx._Vx7, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2), + #([t4] : $e._Bx._Vx3), + #([t5] : $e._Bx._Vx4), + #([t6] : $e._Bx._Vx5), + #([t7] : $e._Bx._Vx6), + #([t8] : $e._Bx._Vx7) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind9<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind9<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ", ", $e._Bx._Vx3, + ", ", $e._Bx._Vx4, + ", ", $e._Bx._Vx5, + ", ", $e._Bx._Vx6, + ", ", $e._Bx._Vx7, + ", ", $e._Bx._Vx8, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2), + #([t4] : $e._Bx._Vx3), + #([t5] : $e._Bx._Vx4), + #([t6] : $e._Bx._Vx5), + #([t7] : $e._Bx._Vx6), + #([t8] : $e._Bx._Vx7), + #([t9] : $e._Bx._Vx8) + ) + ) +} +std::tr1::_Bind<*,*,std::tr1::_Bind10<*> >|std::tr1::_Bind_fty<*,*,std::tr1::_Bind10<*> >{ + preview ( + #( + "bind(", $e._Bx._Callee._Object, + ", ", $e._Bx._Vx0, + ", ", $e._Bx._Vx1, + ", ", $e._Bx._Vx2, + ", ", $e._Bx._Vx3, + ", ", $e._Bx._Vx4, + ", ", $e._Bx._Vx5, + ", ", $e._Bx._Vx6, + ", ", $e._Bx._Vx7, + ", ", $e._Bx._Vx8, + ", ", $e._Bx._Vx9, + ")" + ) + ) + + children ( + #( + #([f] : $e._Bx._Callee._Object), + #([t1] : $e._Bx._Vx0), + #([t2] : $e._Bx._Vx1), + #([t3] : $e._Bx._Vx2), + #([t4] : $e._Bx._Vx3), + #([t5] : $e._Bx._Vx4), + #([t6] : $e._Bx._Vx5), + #([t7] : $e._Bx._Vx6), + #([t8] : $e._Bx._Vx7), + #([t9] : $e._Bx._Vx8), + #([t10] : $e._Bx._Vx9) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::function from +;------------------------------------------------------------------------------ +std::tr1::_Impl_no_alloc0<*>|std::tr1::_Impl_no_alloc1<*>|std::tr1::_Impl_no_alloc2<*>|std::tr1::_Impl_no_alloc3<*>|std::tr1::_Impl_no_alloc4<*>|std::tr1::_Impl_no_alloc5<*>|std::tr1::_Impl_no_alloc6<*>|std::tr1::_Impl_no_alloc7<*>|std::tr1::_Impl_no_alloc8<*>|std::tr1::_Impl_no_alloc9<*>|std::tr1::_Impl_no_alloc10<*>{ + preview ( $e._Callee._Object ) + children ( #([functor] : $e._Callee._Object) ) +} +std::tr1::_Impl0<*>|std::tr1::_Impl1<*>|std::tr1::_Impl2<*>|std::tr1::_Impl3<*>|std::tr1::_Impl4<*>|std::tr1::_Impl5<*>|std::tr1::_Impl6<*>|std::tr1::_Impl7<*>|std::tr1::_Impl8<*>|std::tr1::_Impl9<*>|std::tr1::_Impl10<*>{ + preview ( $e._Callee._Object ) + children ( + #( + #([functor] : $e._Callee._Object), + #([allocator] : $e._Myal) + ) + ) +} +std::tr1::function<*>{ + preview ( + #if ($e._Impl == 0) ( + ; Detecting empty functions is trivial. + "empty" + ) #else ( + *$e._Impl + ) + ) + + children ( + #if ($e._Impl == 0) ( + ; We make empty functions appear to have no children. + #array(expr: 0, size: 0) + ) #else ( + #([functor and allocator] : *$e._Impl) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::tuple from +;------------------------------------------------------------------------------ +; tuple is visualized like pair, except that we have to give fake names to tuple's children. +std::tr1::tuple{ + preview ( + "()" + ) + + children ( + #array(expr: 0, size: 0) + ) +} +std::tr1::tuple<*,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value + ) + ) +} +std::tr1::tuple<*,*,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,*,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value, + [3] : $e._Impl._Tail._Tail._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,*,*,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value, + [3] : $e._Impl._Tail._Tail._Tail._Value, + [4] : $e._Impl._Tail._Tail._Tail._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,*,*,*,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value, + [3] : $e._Impl._Tail._Tail._Tail._Value, + [4] : $e._Impl._Tail._Tail._Tail._Tail._Value, + [5] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,*,*,*,*,std::tr1::_Nil,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value, + [3] : $e._Impl._Tail._Tail._Tail._Value, + [4] : $e._Impl._Tail._Tail._Tail._Tail._Value, + [5] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + [6] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,*,*,*,*,*,std::tr1::_Nil,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value, + [3] : $e._Impl._Tail._Tail._Tail._Value, + [4] : $e._Impl._Tail._Tail._Tail._Tail._Value, + [5] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + [6] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value, + [7] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,*,*,*,*,*,*,std::tr1::_Nil>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value, + [3] : $e._Impl._Tail._Tail._Tail._Value, + [4] : $e._Impl._Tail._Tail._Tail._Tail._Value, + [5] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + [6] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value, + [7] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + [8] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value + ) + ) +} +std::tr1::tuple<*,*,*,*,*,*,*,*,*,*>{ + preview ( + #( + "(", $e._Impl._Value, + ", ", $e._Impl._Tail._Value, + ", ", $e._Impl._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ", ", $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + ")" + ) + ) + + children ( + #( + [0] : $e._Impl._Value, + [1] : $e._Impl._Tail._Value, + [2] : $e._Impl._Tail._Tail._Value, + [3] : $e._Impl._Tail._Tail._Tail._Value, + [4] : $e._Impl._Tail._Tail._Tail._Tail._Value, + [5] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Value, + [6] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Value, + [7] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + [8] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value, + [9] : $e._Impl._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Tail._Value + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::array from +;------------------------------------------------------------------------------ +std::tr1::array<*>{ + preview ( + ; An actual array is previewed with its address. + ; array is previewed like vector. + #( + "[", + $e._EEN_SIZE, + "](", + #array(expr: $e._Elems[$i], size: $e._EEN_SIZE), + ")" + ) + ) + + children ( + ; Just like an actual array. + #array(expr: $e._Elems[$i], size: $e._EEN_SIZE) + ) +} +std::_Array_iterator<*>|std::_Array_const_iterator<*>{ + preview ( + #if ($e._EEN_IDL == 0) ( + *$e._Ptr + ) #else ( + #if ($e._Idx == $e._EEN_SIZE) ( + ; array iterators are represented by _Ptr + _Idx, + ; and they know how large their parent arrays are. Therefore, detecting + ; end iterators is trivial. + "end" + ) #else ( + ; Like vector iterators, array iterators are previewed with what they point to. + $e._Ptr[$e._Idx] + ) + ) + ) + + children ( + #if ($e._EEN_IDL == 0) ( + #([ptr] : $e._Ptr) + ) #else ( + #if ($e._Idx == $e._EEN_SIZE) ( + ; We make end iterators appear to have no children. + #array(expr: 0, size: 0) + ) #else ( + ; An array iterator is conceptually a pointer, so we make it appear to store one. + #([ptr] : $e._Ptr + $e._Idx) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; stdext::hash_map from +; stdext::hash_multimap from +; stdext::hash_set from +; stdext::hash_multiset from +;------------------------------------------------------------------------------ +stdext::hash_map<*>|stdext::hash_multimap<*>|stdext::hash_set<*>|stdext::hash_multiset<*>{ + preview ( + #( + "[", + $e._List._Mysize, + "](", + #list( + head: $e._List._Myhead->_Next, + size: $e._List._Mysize, + next: _Next + ) : $e._Myval, + ")" + ) + ) + + children ( + #list( + head: $e._List._Myhead->_Next, + size: $e._List._Mysize, + next: _Next + ) : $e._Myval + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::unordered_map from +; std::tr1::unordered_multimap from +; std::tr1::unordered_set from +; std::tr1::unordered_multiset from +;------------------------------------------------------------------------------ +std::hash<*>{ + preview ( "hash" ) + children ( #array(expr: 0, size: 0) ) +} +std::tr1::unordered_map<*>|std::tr1::unordered_multimap<*>|std::tr1::unordered_set<*>|std::tr1::unordered_multiset<*>{ + preview ( + #( + "[", + $e._List._Mysize, + "](", + #list( + head: $e._List._Myhead->_Next, + size: $e._List._Mysize, + next: _Next + ) : $e._Myval, + ")" + ) + ) + + children ( + #( + #([hash] : $e.comp._Hashobj), + #([equal] : $e.comp._Keyeqobj), + #list( + head: $e._List._Myhead->_Next, + size: $e._List._Mysize, + next: _Next + ) : $e._Myval + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::basic_regex from +;------------------------------------------------------------------------------ +std::tr1::basic_regex<*>{ + preview ( + #if ($e._Rep == 0) ( + ; Default construction creates an empty basic_regex. + "empty" + ) #elif ($e._EEN_VIS == 1) ( + ; By default, _ENHANCED_REGEX_VISUALIZER is defined to be 1 in debug and 0 in ship. + ; When it is 1, basic_regex stores the string from which it was constructed. + ; When it is 0, basic_regex stores only the resulting finite state machine. + $e._Visualization + ) #else ( + ; basic_regex contains many static const flags, which would be shown in the preview by default. + ; Its actual members are _Rep and _Traits. _Rep holds the finite state machine, so we + ; use it to preview basic_regex. (It does contain some human-readable information.) + *$e._Rep + ) + ) + + children ( + #if ($e._Rep == 0) ( + ; We make empty basic_regexes appear to have no children. + #array(expr: 0, size: 0) + ) #elif ($e._EEN_VIS == 1) ( + ; We want to hide those static const flags. + ; We also want to give _Visualization a fake name. + #( + #([str] : $e._Visualization), + #(_Rep : $e._Rep), + #(_Traits : $e._Traits) + ) + ) #else ( + ; We want to hide those static const flags. + #( + _Rep : $e._Rep, + _Traits : $e._Traits + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::sub_match from +;------------------------------------------------------------------------------ +std::tr1::sub_match|std::tr1::sub_match|std::tr1::sub_match|std::tr1::sub_match|std::tr1::sub_match|std::tr1::sub_match{ + preview ( + ; It would be nice if we could preview sub_match with its str(). + ; However, visualizers cannot handle strings represented by pointer pairs. + ; Therefore, our preview contains more limited information. + #if ($e.matched) ( + ; If this sub_match participated in a match, + ; we preview it with its length(). + $e.second - $e.first + ) #else ( + ; Otherwise, we preview it with its matched bool (i.e. "false"). + ; (Why not length() (i.e. "0")? It's meaningful to have + ; matched == true and length() == 0. + "false" + ) + ) + + children ( + #( + ; sub_match's three data members are public, but we list them here + ; (a) to display matched before first and second, and + ; (b) to gloss over the fact that sub_match derives from std::pair. + #(matched : $e.matched), + #(first : $e.first), + #(second : $e.second) + ) + ) +} +std::tr1::sub_match >|std::tr1::sub_match >{ + preview ( + #if ($e.matched) ( + ; We visualize ssub_match and wssub_match just like csub_match and wcsub_match, + ; except that when determining the length(), we can't subtract iterators. + ; We have to subtract their stored pointers. + $e.second._Ptr - $e.first._Ptr + ) #else ( + "false" + ) + ) + + children ( + #( + #(matched : $e.matched), + #(first : $e.first), + #(second : $e.second) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::match_results from +;------------------------------------------------------------------------------ +std::tr1::match_results<*>{ + preview ( + ; A match_results object is empty iff its vector _Matches is empty. + #if ($e._Matches._Myfirst == $e._Matches._Mylast) ( + "empty" + ) #else ( + ; We preview a non-empty match_results object with its vector. + $e._Matches + ) + ) + + children ( + #if ($e._Matches._Myfirst == $e._Matches._Mylast) ( + ; We make empty match_results appear to have no children. + #array(expr: 0, size: 0) + ) #else ( + ; As match_results has operator[](), prefix(), and suffix() member functions, + ; we make it appear to directly contain [0], [1], [2], etc. elements, + ; as well as [prefix] and [suffix] elements. + #( + #array(expr: $e._Matches._Myfirst[$i], size: $e._Matches._Mylast - $e._Matches._Myfirst), + #([prefix] : $e._Prefix), + #([suffix] : $e._Suffix) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::regex_iterator from +;------------------------------------------------------------------------------ +std::tr1::regex_iterator<*>{ + preview ( + #if ($e._MyRe == 0) ( + ; We represent end-of-sequence regex_iterators with null regex pointers. + "end" + ) #else ( + ; Dereferenceable regex_iterators return match_results when dereferenced, + ; so we'll preview them with that. + $e._MyVal + ) + ) + + children ( + #if ($e._MyRe == 0) ( + ; We make end-of-sequence regex_iterators appear to have no children. + #array(expr: 0, size: 0) + ) #else ( + ; For ease of understanding, we make dereferenceable regex_iterators + ; appear to have data members with the "for exposition only" names from TR1. + #( + #([begin] : $e._Begin), + #([end] : $e._End), + #([pregex] : $e._MyRe), + #([flags] : $e._Flags), + #([match] : $e._MyVal) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::tr1::regex_token_iterator from +;------------------------------------------------------------------------------ +std::tr1::regex_token_iterator<*>{ + preview ( + #if ($e._Res == 0) ( + ; We represent end-of-sequence regex_token_iterators with null result pointers. + "end" + ) #else ( + ; Dereferenceable regex_token_iterators return *result when dereferenced, + ; so we'll preview them with that. + *$e._Res + ) + ) + + children ( + #if ($e._Res == 0) ( + ; We make end-of-sequence regex_token_iterators appear to have no children. + #array(expr: 0, size: 0) + ) #else ( + ; For ease of understanding, we make dereferenceable regex_token_iterators + ; appear to have data members with the "for exposition only" names from TR1. + #( + #([position] : $e._Pos), + #([result] : $e._Res), + #([suffix] : $e._Suffix), + #([N] : $e._Cur), + #([subs] : $e._Subs) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::identity, etc. from +;------------------------------------------------------------------------------ +std::identity<*>{ + preview ( "identity" ) + children ( #array(expr: 0, size: 0) ) +} +std::bit_and<*>{ + preview ( "bit_and" ) + children ( #array(expr: 0, size: 0) ) +} +std::bit_or<*>{ + preview ( "bit_or" ) + children ( #array(expr: 0, size: 0) ) +} +std::bit_xor<*>{ + preview ( "bit_xor" ) + children ( #array(expr: 0, size: 0) ) +} + +;------------------------------------------------------------------------------ +; std::unique_ptr from +;------------------------------------------------------------------------------ +std::unique_ptr<*>{ + preview ( + #if ($e._Myptr == 0) ( + "empty" + ) #else ( + #( + "unique_ptr ", + *$e._Myptr + ) + ) + ) + + children ( + #if ($e._Myptr == 0) ( + #array(expr: 0, size: 0) + ) #else ( + #([ptr] : $e._Myptr) + ) + ) +} + +;------------------------------------------------------------------------------ +; std::forward_list from +;------------------------------------------------------------------------------ +std::forward_list<*>{ + preview ( + #( + "(", + #list( + head: $e._Myhead, + next: _Next + ) : $e._Myval, + ")" + ) + ) + + children ( + #list( + head: $e._Myhead, + next: _Next + ) : $e._Myval + ) +} +std::_Flist_iterator<*>|std::_Flist_const_iterator<*>{ + preview ( + #if ($e._Ptr == 0) ( + "end" + ) #else ( + $e._Ptr->_Myval + ) + ) + + children ( + #if ($e._Ptr == 0) ( + #array(expr: 0, size: 0) + ) #else ( + #([ptr] : &$e._Ptr->_Myval) + ) + ) +} + + +;------------------------------------------------------------------------------ +; PROPVARIANT +;------------------------------------------------------------------------------ +; Visualizers for VT_VECTOR C arrays +tagCAC|tagCAUB|tagCAI|tagCAUI|tagCAL|tagCAUL|tagCAFLT|tagCADBL|tagCACY|tagCADATE|tagCABSTR|tagCABSTRBLOB|tagCABOOL|tagCASCODE|tagCAPROPVARIANT|tagCAH|tagCAUH|tagCALPSTR|tagCALPWSTR|tagCAFILETIME|tagCACLIPDATA|tagCACLSID{ + preview( + #( + "[", $e.cElems , "](", + #array + ( + expr : ($e.pElems)[$i], + size : $e.cElems + ), + ")" + ) + ) + children + ( + #array + ( + expr : ($e.pElems)[$i], + size : $e.cElems + ) + ) +} +; Visualizers for SAFE ARRAY +tagSAFEARRAY|SAFEARRAY{ + preview( + #if ($e.fFeatures & 0x0080) ; FADF_HAVEVARTYPE + ( + ; Switch on the variant type field - which is stored 4 bytes + ; before the beginning of the SAFEARRAY type + #switch( ((unsigned *)&($e))[-1] ) + #case 0x2 ; VT_I2 | VT_ARRAY + ( + #( + "safearray of I2 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((signed short *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x3 ; VT_I4 | VT_ARRAY + ( + #( + "safearray of I4 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((signed int *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x4 ; VT_R4 | VT_ARRAY + ( + #( + "safearray of R4 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((float *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x5 ; VT_R8 | VT_ARRAY + ( + #( + "safearray of R8 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((double *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x6 ; VT_CY | VT_ARRAY + ( + #( + "safearray of CY = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((CY *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x7 ; VT_DATE | VT_ARRAY + ( + #( + "safearray of DATE = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((DATE *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x8 ; VT_BSTR | VT_ARRAY + ( + #( + "safearray of BSTR = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((wchar_t **)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0xa ; VT_ERROR | VT_ARRAY + ( + #( + "safearray of ERROR = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((long *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0xb ; VT_BOOL | VT_ARRAY + ( + #( + "safearray of BOOL = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((short *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0xc ; VT_VARIANT | VT_ARRAY + ( + #( + "safearray of VARIANT = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((tagVARIANT *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x10 ; VT_I1 | VT_ARRAY + ( + #( + "safearray of I1 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((signed char *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x11 ; VT_UI1 | VT_ARRAY + ( + #( + "safearray of UI1 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((unsigned char *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x12 ; VT_UI2 | VT_ARRAY + ( + #( + "safearray of UI2 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((unsigned short *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x13 ; VT_UI4 | VT_ARRAY + ( + #( + "safearray of UI4 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((unsigned int *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x14 ; VT_I8 | VT_ARRAY + ( + #( + "safearray of I8 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((signed __int64 *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x15 ; VT_UI8 | VT_ARRAY + ( + #( + "safearray of UI8 = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((unsigned __int64 *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x16 ; VT_INT | VT_ARRAY + ( + #( + "safearray of INT = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((int *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x17 ; VT_UINT | VT_ARRAY + ( + #( + "safearray of UINT = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((unsigned *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x1e ; VT_LPSTR | VT_ARRAY + ( + #( + "safearray of LPSTR = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((char **)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x1f ; VT_LPWSTR | VT_ARRAY + ( + #( + "safearray of LPWSTR = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((wchar_t **)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x40 ; VT_FILETIME | VT_ARRAY + ( + #( + "safearray of FILETIME = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((FILETIME *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x47 ; VT_CLIPDATA | VT_ARRAY + ( + #( + "safearray of CLIPDATA = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((CLIPDATA *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + #case 0x48 ; VT_CLSID | VT_ARRAY + ( + #( + "safearray of CLSID = [", + ; output the rank array + #array( expr: $e.rgsabound[$i].cElements, size: $e.cDims), + "](", + ; output the data elements + #array( + expr: ((CLSID *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ), + ")" + ) + ) + ) + #elif ($e.fFeatures & 0x0100) ; FADF_BSTR + ( + #("safearray of BSTR = ",#array(expr: $e.rgsabound[$i].cElements, size: $e.cDims) : #("[",$e,"]"), "(", #array(expr: ((wchar_t * *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ), ")") + ) + #elif ($e.fFeatures & 0x0200) ; FADF_UNKNOWN + ( + #("safearray of IUnknown* = [",#array(expr: $e.rgsabound[$i].cElements, size: $e.cDims), "](", #array(expr: ((IUnknown * *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ), ")") + ) + #elif ($e.fFeatures & 0x0400) ; FADF_DISPATCH + ( + #("safearray of IDispatch* = [",#array(expr: $e.rgsabound[$i].cElements, size: $e.cDims), "](", #array(expr: ((IDispatch * *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ), ")") + ) + #elif ($e.fFeatures & 0x0800) ; FADF_VARIANT + ( + #("safearray of VARIANT = ",#array(expr: $e.rgsabound[$i].cElements, size: $e.cDims) : #("[",$e,"]"), "(", #array(expr: ((tagVARIANT *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ), ")") + ) + ) + children + ( + #( ;[actual members]: [$e,!], + #if ($e.fFeatures & 0x0080) ; FADF_HAVEVARTYPE + ( + #switch( ((unsigned *)&($e))[-1] ) ; for some reason the VT field is before the SAFEARRAY struct + #case 2 ; VT_I2|VT_ARRAY + ( + #array( + expr: ((signed short *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 3 ; VT_I4|VT_ARRAY + ( + #array( + expr: ((signed int *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 4 ; VT_R4|VT_ARRAY + ( + #array( + expr: ((float *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 5 ; VT_R8|VT_ARRAY + ( + #array( + expr: ((double *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x10 ; VT_I1|VT_ARRAY + ( + #array( + expr: ((signed char *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x11 ; VT_UI1|VT_ARRAY + ( + #array( + expr: ((unsigned char *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x12 ; VT_UI2|VT_ARRAY + ( + #array( + expr: ((unsigned short *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x13 ; VT_UI4|VT_ARRAY + ( + #array( + expr: ((unsigned int *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x14 ; VT_I8|VT_ARRAY + ( + #array( + expr: ((signed __int64 *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x15 ; VT_UI8|VT_ARRAY + ( + #array( + expr: ((unsigned __int64 *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x1e ; VT_LPSTR|VT_ARRAY + ( + #array( + expr: ((char * *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x1f ; VT_LPWSTR|VT_ARRAY + ( + #array( + expr: ((wchar_t **)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0xc ; VT_VARIANT|VT_ARRAY + ( + #array( + expr: ((tagVARIANT *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0xb ; VT_BOOL|VT_ARRAY + ( + #array( + expr: ((short *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0xa ; VT_ERROR|VT_ARRAY + ( + #array( + expr: ((long *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 6 ; VT_CY|VT_ARRAY + ( + #array( + expr: ((CY *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 7 ; VT_DATE|VT_ARRAY + ( + #array( + expr: ((DATE *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x40 ; VT_FILETIME|VT_ARRAY + ( + #array( + expr: ((FILETIME *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x48 ; VT_CLSID|VT_ARRAY + ( + #array( + expr: ((CLSID *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x47 ; VT_CF|VT_ARRAY + ( + #array( + expr: ((CLIPDATA *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 8 ; VT_BSTR|VT_ARRAY + ( + #array( + expr: ((wchar_t * *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x16 ; VT_INT|VT_ARRAY + ( + #array( + expr: ((int *)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #case 0x17 ; VT_UINT|VT_ARRAY + ( + #array( + expr: ((unsigned int*)$e.pvData)[$i], + size: $e.rgsabound[$r].cElements, + rank: $e.cDims, + base: $e.rgsabound[$r].lLbound + ) + ) + #default + ( + #([actual members]: [$e,!]) + ) + #except + ( + #([actual members]: [$e,!]) + ) + ) + #elif ($e.fFeatures & 0x0100) ; FADF_BSTR + ( + #array(expr: ((wchar_t * *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ) + ) + #elif ($e.fFeatures & 0x0200) ; FADF_UNKNOWN + ( + #array(expr: ((IUnknown * *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ) + ) + #elif ($e.fFeatures & 0x0400) ; FADF_DISPATCH + ( + #array(expr: ((IDispatch * *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ) + ) + #elif ($e.fFeatures & 0x0800) ; FADF_VARIANT + ( + #array(expr: ((tagVARIANT *)$e.pvData)[$i], size: $e.rgsabound[$r].cElements, rank: $e.cDims, base: $e.rgsabound[$r].lLbound ) + ) + ) + ) +} +tagPROPVARIANT|tagVARIANT|PROPVARIANT|VARIANT{ + preview( + #switch ($e.vt) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Base Types ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + #case 0 ( #("Empty") ) ; VT_EMPTY + #case 1 ( #("NULL") ) ; VT_NULL + #case 2 ( #("I2 = ", $e.iVal) ) ; VT_I2 + #case 3 ( #("I4 = ", $e.lVal) ) ; VT_I4 + #case 4 ( #("R4 = ", $e.fltVal) ) ; VT_R4 + #case 5 ( #("R8 = ", $e.dblVal) ) ; VT_R8 + #case 6 ( #("CY = ", $e.cyVal) ) ; VT_CY + #case 7 ( #("DATE = ", $e.date) ) ; VT_DATE + #case 8 ( #("BSTR = ", $e.bstrVal) ) ; VT_BSTR + #case 9 ( #("DISPATCH = ", $e.pdispVal) ) ; VT_DISPATCH + #case 10 ( #("ERROR = ", $e.scode) ) ; VT_ERROR + #case 0xB ( #("BOOL = ", $e.boolVal) ) ; VT_BOOL + #case 0xC ( #("VARIANT ") ) ; VT_VARIANT + #case 0xD ( #("UNKNOWN = ", $e.punkVal) ) ; VT_UNKOWN + #case 0xE ( #("DECIMAL = ", $e.decVal) ) ; VT_DECIMAL + #case 0x10 ( #("I1 = ", $e.cVal) ) ; VT_I1 + #case 0x11 ( #("UI1 = ", $e.bVal) ) ; VT_UI1 + #case 0x12 ( #("UI2 = ", $e.uiVal) ) ; VT_UI2 + #case 0x13 ( #("UI4 = ", $e.ulVal) ) ; VT_UI4 + #case 0x14 ( #("I8 = ", *(__int64*)&$e.dblVal) ) ; VT_I8 + #case 0x15 ( #("UI8 = ", *(unsigned __int64*)&$e.dblVal) ) ; VT_UI8 + #case 0x16 ( #("INT = ", $e.intVal) ) ; VT_INT + #case 0x17 ( #("UINT = ", $e.uintVal) ) ; VT_UINT + #case 0x18 ( #("VOID ") ) ; VT_VOID + #case 0x19 ( #("HRESULT ") ) ; VT_HRESULT + #case 0x1A ( #("PTR ") ) ; VT_PTR + #case 0x1B ( #("SAFEARRAY ") ) ; VT_SAFEARRAY + #case 0x1C ( #("CARRAY ") ) ; VT_CARRAY + #case 0x1D ( #("USERDEFINED ") ) ; VT_USERDEFINED + #case 0x1E ( #("LPSTR = ", $e.pszVal) ) ; VT_LPSTR + #case 0x1F ( #("LPWSTR = ", $e.pwszVal) ) ; VT_LPWSTR + #case 0x24 ( #("RECORD ") ) ; VT_RECORD + #case 0x26 ( #("UINT_PTR ") ) ; VT_UINT_PTR + #case 0x40 ( #("FILETIME = ", $e.filetime) ) ; VT_FILETIME + #case 0x42 ( #("STREAM = ", $e.pStream) ) ; VT_STREAM + #case 0x43 ( #("STORAGE = ", $e.pStorage) ) ; VT_STORAGE + #case 0x44 ( #("STREAMED_OBJECT = ", $e.pStream) ) ; VT_STREAMED_OBJECT + #case 0x45 ( #("STORED_OBJECT = ", $e.pStorage) ) ; VT_STORED_OBJECT + #case 0x46 ( #("BLOB_OBJECT = ", $e.blob ) ) ; VT_BLOB_OBJECT + #case 0x47 ( #("CF = ", $e.pclipdata) ) ; VT_CF + #case 0x48 ( #("CLSID = ", $e.puuid) ) ; VT_CLSID + #case 0x49 ( #("VERSIONED_STREAM = ", $e.pVersionedStream) ) ; VT_VERSIONED_STREAM + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Vector types ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + #case 0x1002 ( #("vector of I2 = ", $e.cai) ) ; VT_I2|VT_VECTOR + #case 0x1003 ( #("vector of I4 = ", $e.cal) ) ; VT_I4|VT_VECTOR + #case 0x1004 ( #("vector of R4 = ", $e.caflt) ) ; VT_R4|VT_VECTOR + #case 0x1005 ( #("vector of R8 = ", $e.cadbl) ) ; VT_R8|VT_VECTOR + #case 0x1010 ( #("vector of I1 = ", $e.cac) ) ; VT_I1|VT_VECTOR + #case 0x1011 ( #("vector of UI1 = ", $e.caub) ) ; VT_UI1|VT_VECTOR + #case 0x1012 ( #("vector of UI2 = ", $e.caui) ) ; VT_UI2|VT_VECTOR + #case 0x1013 ( #("vector of UI4 = ", $e.caul) ) ; VT_UI4|VT_VECTOR + #case 0x1014 ( #("vector of I8 = ", $e.cah) ) ; VT_I8|VT_VECTOR + #case 0x1015 ( #("vector of UI8 = ", $e.cauh) ) ; VT_UI8|VT_VECTOR + #case 0x101E ( #("vector of LPSTR = ", $e.calpstr) ) ; VT_LPSTR|VT_VECTOR + #case 0x101F ( #("vector of LPWSTR = ", $e.calpwstr) ) ; VT_LPWSTR|VT_VECTOR + #case 0x100C ( #("vector of VARIANT ", $e.capropvar) ) ; VT_VARIANT|VT_VECTOR + #case 0x100B ( #("vector of BOOL = ", $e.cabool) ) ; VT_BOOL|VT_VECTOR + #case 0x100A ( #("vector of ERROR = ", $e.cascode) ) ; VT_ERROR|VT_VECTOR + #case 0x1006 ( #("vector of CY = ", $e.cacy) ) ; VT_CY|VT_VECTOR + #case 0x1007 ( #("vector of DATE = ", $e.cadate) ) ; VT_DATE|VT_VECTOR + #case 0x1040 ( #("vector of FILETIME = ", $e.cafiletime) ) ; VT_FILETIME|VT_VECTOR + #case 0x1048 ( #("vector of CLSID = ", $e.cauuid) ) ; VT_CLSID|VT_VECTOR + #case 0x1047 ( #("vector of CF = ", $e.caclipdata) ) ; VT_CF|VT_VECTOR + #case 0x1008 ( #("vector of BSTR = ", $e.cabstr) ) ; VT_BSTR|VT_VECTOR + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Byref Types ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + #case 0x4016 ( #("byref of INT = ", $e.pintVal) ) ; VT_INT|VT_BYREF + #case 0x4017 ( #("byref of UINT = ", $e.puintVal) ) ; VT_UINT|VT_BYREF + #case 0x4002 ( #("byref of I2 = ", $e.piVal) ) ; VT_I2|VT_BYREF + #case 0x4003 ( #("byref of I4 = ", $e.plVal) ) ; VT_I4|VT_BYREF + #case 0x4004 ( #("byref of R4 = ", $e.pfltVal) ) ; VT_R4|VT_BYREF + #case 0x4005 ( #("byref of R8 = ", $e.pdblVal) ) ; VT_R8|VT_BYREF + #case 0x4010 ( #("byref of I1 = ", $e.pcVal) ) ; VT_I1|VT_BYREF + #case 0x4011 ( #("byref of UI1 = ", $e.pbVal) ) ; VT_UI1|VT_BYREF + #case 0x4012 ( #("byref of UI2 = ", $e.puiVal) ) ; VT_UI2|VT_BYREF + #case 0x4013 ( #("byref of UI4 = ", $e.pulVal) ) ; VT_UI4|VT_BYREF + #case 0x4014 ( #("byref of I8 = ", (__int64*)$e.pdblVal) ) ; VT_I8|VT_BYREF + #case 0x4015 ( #("byref of UI8 = ", (unsigned __int64*)$e.pudblVal) ) ; VT_UI8|VT_BYREF + #case 0x400C ( #("byref of VARIANT ", $e.pvarVal) ) ; VT_VARIANT|VT_BYREF + #case 0x400B ( #("byref of BOOL = ", $e.pboolVal) ) ; VT_BOOL|VT_BYREF + #case 0x400A ( #("byref of ERROR = ", $e.pscode) ) ; VT_ERROR|VT_BYREF + #case 0x4006 ( #("byref of CY = ", $e.pcyVal) ) ; VT_CY|VT_BYREF + #case 0x4007 ( #("byref of DATE = ", $e.pdate) ) ; VT_DATE|VT_BYREF + #case 0x4008 ( #("byref of BSTR = ", $e.pbstrVal) ) ; VT_BSTR|VT_BYREF + #case 0x400E ( #("byref of DECIMAL = ", $e.pdecVal) ) ; VT_DECIMAL|VT_BYREF + #case 0x400D ( #("byref of UNKNOWN = ", $e.ppunkVal) ) ; VT_UNKOWN|VT_BYREF + #case 0x4009 ( #("byref of DISPATCH = ", $e.ppdispVal) ) ; VT_DISPATCH|VT_BYREF + #case 0x6000 ( #("byref of ARRAY = ", $e.pparray) ) ; VT_ARRAY|VT_BYREF + #default + ( + #if ($e.vt & 0x2000) ( $e.parray) + #else ( #("Unknown vt type = ", $e.vt)) + ) + ) + children( + #( + vt: $e.vt, + #switch ($e.vt) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Base Types ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + #case 0x2 ( #(I2 : $e.iVal) ) ; VT_I2 + #case 0x3 ( #(I4 : $e.lVal) ) ; VT_I4 + #case 0x4 ( #(R4 : $e.fltVal) ) ; VT_R4 + #case 0x5 ( #(R8 : $e.dblVal) ) ; VT_R8 + #case 0x6 ( #(CY : $e.cyVal) ) ; VT_CY + #case 0x7 ( #(DATE : $e.date) ) ; VT_DATE + #case 0x8 ( #(BSTR : $e.bstrVal) ) ; VT_BSTR + #case 0x9 ( #(DISPATCH : $e.pdispVal) ) ; VT_DISPATCH + #case 0xA ( #(ERROR : $e.scode) ) ; VT_ERROR + #case 0xB ( #(BOOL : $e.boolVal) ) ; VT_BOOL + #case 0xD ( #(UNKNOWN : $e.punkVal) ) ; VT_UNKOWN + #case 0xE ( #(DECIMAL : $e.decVal) ) ; VT_DECIMAL + #case 0x10 ( #(I1 : $e.cVal) ) ; VT_I1 + #case 0x11 ( #(UI1 : $e.bVal) ) ; VT_UI1 + #case 0x12 ( #(UI2 : $e.uiVal) ) ; VT_UI2 + #case 0x13 ( #(UI4 : $e.ulVal) ) ; VT_UI4 + #case 0x14 ( #(I8 : *(__int64*)&$e.dblVal) ) ; VT_I8 + #case 0x15 ( #(UI8 : *(unsigned __int64*)&$e.dblVal) ) ; VT_UI8 + #case 0x16 ( #(INT : $e.intVal) ) ; VT_INT + #case 0x17 ( #(UINT : $e.uintVal) ) ; VT_UINT + #case 0x1E ( #(LPSTR : $e.pszVal) ) ; VT_LPSTR + #case 0x1F ( #(LPWSTR : $e.pwszVal) ) ; VT_LPWSTR + #case 0x40 ( #(FILETIME : $e.filetime) ) ; VT_FILETIME + #case 0x42 ( #(STREAM : $e.pStream) ) ; VT_STREAM + #case 0x43 ( #(STORAGE : $e.pStorage) ) ; VT_STORAGE + #case 0x44 ( #(STREAMED_OBJECT : $e.pStream) ) ; VT_STREAMED_OBJECT + #case 0x45 ( #(STORED_OBJECT : $e.pStorage) ) ; VT_STORED_OBJECT + #case 0x46 ( #(BLOB_OBJECT : $e.blob ) ) ; VT_BLOB_OBJECT + #case 0x47 ( #(CF : $e.pclipdata) ) ; VT_CF + #case 0x48 ( #(CLSID : $e.puuid) ) ; VT_CLSID + #case 0x49 ( #(VERSIONED_STREAM : $e.pVersionedStream) ) ; VT_VERSIONED_STREAM + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Vector types ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + #case 0x1002 ( #(vector of I2 : $e.cai) ) ; VT_I2|VT_VECTOR + #case 0x1003 ( #(vector of I4 : $e.cal) ) ; VT_I4|VT_VECTOR + #case 0x1004 ( #(vector of R4 : $e.caflt) ) ; VT_R4|VT_VECTOR + #case 0x1005 ( #(vector of R8 : $e.cadbl) ) ; VT_R8|VT_VECTOR + #case 0x1010 ( #(vector of I1 : $e.cac) ) ; VT_I1|VT_VECTOR + #case 0x1011 ( #(vector of UI1 : $e.caub) ) ; VT_UI1|VT_VECTOR + #case 0x1012 ( #(vector of UI2 : $e.caui) ) ; VT_UI2|VT_VECTOR + #case 0x1013 ( #(vector of UI4 : $e.caul) ) ; VT_UI4|VT_VECTOR + #case 0x1014 ( #(vector of I8 : $e.cah) ) ; VT_I8|VT_VECTOR + #case 0x1015 ( #(vector of UI8 : $e.cauh) ) ; VT_UI8|VT_VECTOR + #case 0x101E ( #(vector of LPSTR : $e.calpstr) ) ; VT_LPSTR|VT_VECTOR + #case 0x101F ( #(vector of LPWSTR : $e.calpwstr) ) ; VT_LPWSTR|VT_VECTOR + #case 0x100C ( #(vector of VARIANT : $e.capropvar) ) ; VT_VARIANT|VT_VECTOR + #case 0x100B ( #(vector of BOOL : $e.cabool) ) ; VT_BOOL|VT_VECTOR + #case 0x100A ( #(vector of ERROR : $e.cascode) ) ; VT_ERROR|VT_VECTOR + #case 0x1006 ( #(vector of CY : $e.cacy) ) ; VT_CY|VT_VECTOR + #case 0x1007 ( #(vector of DATE : $e.cadate) ) ; VT_DATE|VT_VECTOR + #case 0x1040 ( #(vector of FILETIME : $e.cafiletime) ) ; VT_FILETIME|VT_VECTOR + #case 0x1048 ( #(vector of CLSID : $e.cauuid) ) ; VT_CLSID|VT_VECTOR + #case 0x1047 ( #(vector of CF : $e.caclipdata) ) ; VT_CF|VT_VECTOR + #case 0x1008 ( #(vector of BSTR : $e.cabstr) ) ; VT_BSTR|VT_VECTOR + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ;; Byref Types ;; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + #case 0x4016 ( #(byref of INT : $e.pintVal) ) ; VT_INT|VT_BYREF + #case 0x4017 ( #(byref of UINT : $e.puintVal) ) ; VT_UINT|VT_BYREF + #case 0x4002 ( #(byref of I2 : $e.piVal) ) ; VT_I2|VT_BYREF + #case 0x4003 ( #(byref of I4 : $e.plVal) ) ; VT_I4|VT_BYREF + #case 0x4004 ( #(byref of R4 : $e.pfltVal) ) ; VT_R4|VT_BYREF + #case 0x4005 ( #(byref of R8 : $e.pdblVal) ) ; VT_R8|VT_BYREF + #case 0x4010 ( #(byref of I1 : $e.pcVal) ) ; VT_I1|VT_BYREF + #case 0x4011 ( #(byref of UI1 : $e.pbVal) ) ; VT_UI1|VT_BYREF + #case 0x4012 ( #(byref of UI2 : $e.puiVal) ) ; VT_UI2|VT_BYREF + #case 0x4013 ( #(byref of UI4 : $e.pulVal) ) ; VT_UI4|VT_BYREF + #case 0x4014 ( #(byref of I8 : (__int64*)$e.pdblVal) ) ; VT_I8|VT_BYREF + #case 0x4015 ( #(byref of UI8 : (unsigned __int64*)$e.pdblVal) ) ; VT_UI8|VT_BYREF + #case 0x400C ( #(byref of VARIANT : $e.pvarVal) ) ; VT_VARIANT|VT_BYREF + #case 0x400B ( #(byref of BOOL : $e.pboolVal) ) ; VT_BOOL|VT_BYREF + #case 0x400A ( #(byref of ERROR : $e.pscode) ) ; VT_ERROR|VT_BYREF + #case 0x4006 ( #(byref of CY : $e.pcyVal) ) ; VT_CY|VT_BYREF + #case 0x4007 ( #(byref of DATE : $e.pdate) ) ; VT_DATE|VT_BYREF + #case 0x4008 ( #(byref of BSTR : $e.pbstrVal) ) ; VT_BSTR|VT_BYREF + #case 0x400E ( #(byref of DECIMAL : $e.pdecVal) ) ; VT_DECIMAL|VT_BYREF + #case 0x400D ( #(byref of UNKNOWN : $e.ppunkVal) ) ; VT_UNKOWN|VT_BYREF + #case 0x4009 ( #(byref of DISPATCH : $e.ppdispVal) ) ; VT_DISPATCH|VT_BYREF + #case 0x6000 ( #(byref of ARRAY : $e.pparray) ) ; VT_ARRAY|VT_BYREF + + ; the following are either empty or invalid vt values for a variant + ; #case 0 ( #(Empty :) ) ; VT_EMPTY + ; #case 0x1 ( #(NULL :) ) ; VT_NULL + ; #case 0xC ( #(VARIANT :) ) ; VT_VARIANT + ; #case 0x18 ( #(VOID :) ) ; VT_VOID + ; #case 0x19 ( #(HRESULT :) ) ; VT_HRESULT + ; #case 0x1A ( #(PTR :) ) ; VT_PTR + ; #case 0x1B ( #(SAFEARRAY :) ) ; VT_SAFEARRAY + ; #case 0x1C ( #(CARRAY :) ) ; VT_CARRAY + ; #case 0x1D ( #(USERDEFINED :) ) ; VT_USERDEFINED + ; #case 0x24 ( #(RECORD :) ) ; VT_RECORD + ; #case 0x26 ( #(UINT_PTR :) ) ; VT_UINT_PTR + #default + ( + #if ($e.vt & 0x2000 ) + ( #(safearray: $e.parray)) + #else + ( + #( + [raw members]: [$e,!] ; unformatted data members + ) + ) + ) + #except + ( + #( + [raw members]: [$e,!] ; unformatted data members + ) + ) + ) + ) +} + +; Visualizers for data structures in namespace Concurrency +;------------------------------------------------------------------------------ +; Concurrency::message from +;------------------------------------------------------------------------------ +Concurrency::message<*>{ + preview ( + #( + $e.payload + ) + ) + + children ( + #( + #(payload: $e.payload), + #([msg_id]: $e._M_id) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::multi_link_registry from +;------------------------------------------------------------------------------ +Concurrency::multi_link_registry<*>{ + preview ( + #( + "[", + $e._M_vector._M_index, + "](", + #array( + expr: *($e._M_vector._M_array[$i]), + size: $e._M_vector._M_index + ), + ")" + ) + ) + + children ( + #( + #([size]: $e._M_vector._M_index), + #array( + expr: *($e._M_vector._M_array[$i]), + size: $e._M_vector._M_index + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::_Queue from +;------------------------------------------------------------------------------ +Concurrency::details::_Queue<*>{ + preview ( + #( + "[", + $e._M_count, + "](", + #list( + head: $e._M_pHead, + next: _M_pNext, + size: _M_count + ), + ")" + ) + ) + + children ( + #( + #([size]: $e._M_count), + #list( + head: $e._M_pHead, + next: _M_pNext, + size: _M_count + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::unbounded_buffer from +;------------------------------------------------------------------------------ +Concurrency::unbounded_buffer<*>{ + preview ( + #( + $e._M_messageBuffer + ) + ) + + children ( + #( + #(unprocessed_messages: $e._M_messageProcessor._M_queuedMessages._M_queue), + #(messages: $e._M_messageBuffer), + #(message_filter: *($e._M_pFilter)), + #(linked_sources: $e._M_connectedSources._M_links), + #(linked_targets: $e._M_connectedTargets), + #(reserving_target: *($e._M_pReservedFor)), + #(Scheduler: *($e._M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_messageProcessor._M_pScheduleGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::overwrite_buffer from +;------------------------------------------------------------------------------ +Concurrency::overwrite_buffer<*>{ + preview ( + #( + $e._M_pMessage + ) + ) + + children ( + #( + #(value: *($e._M_pMessage)), + #(unprocessed_messages: $e._M_messageProcessor._M_queuedMessages._M_queue), + #(message_filter: *($e._M_pFilter)), + #(linked_sources: $e._M_connectedSources._M_links), + #(linked_targets: $e._M_connectedTargets), + #(reserving_target: *($e._M_pReservedFor)), + #(reserved_message: *($e._M_pReservedMessage)), + #(Scheduler: *($e._M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_messageProcessor._M_pScheduleGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::single_assignment from +;------------------------------------------------------------------------------ +Concurrency::single_assignment<*>{ + preview ( + #( + $e._M_pMessage + ) + ) + + children ( + #( + #(value: *($e._M_pMessage)), + #(unprocessed_messages: $e._M_messageProcessor._M_queuedMessages._M_queue), + #(message_filter: *($e._M_pFilter)), + #(linked_sources: $e._M_connectedSources._M_links), + #(linked_targets: $e._M_connectedTargets), + #(reserving_target: *($e._M_pReservedFor)), + #(Scheduler: *($e._M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_messageProcessor._M_pScheduleGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::call from +;------------------------------------------------------------------------------ +Concurrency::call<*>{ + preview ( + #( + $e._M_pFunc + ) + ) + + children ( + #( + #(call_method: $e._M_pFunc), + #(unprocessed_messages: $e._M_messageProcessor._M_queuedMessages._M_queue), + #(message_filter: *($e._M_pFilter)), + #(linked_sources: $e._M_connectedSources._M_links), + #(Scheduler: *($e._M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_messageProcessor._M_pScheduleGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::transformer from +;------------------------------------------------------------------------------ +Concurrency::transformer<*>{ + preview ( + #( + $e._M_pFunc + ) + ) + + children ( + #( + #(transform_method: $e._M_pFunc), + #(unprocessed_messages: $e._M_messageProcessor._M_queuedMessages._M_queue), + #(messages: $e._M_messageBuffer), + #(message_filter: *($e._M_pFilter)), + #(linked_sources: $e._M_connectedSources._M_links), + #(linked_target: *($e._M_connectedTargets._M_connectedLink)), + #(reserving_target: *($e._M_pReservedFor)), + #(Scheduler: *($e._M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_messageProcessor._M_pScheduleGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::choice from +;------------------------------------------------------------------------------ +Concurrency::choice<*>{ + preview ( + #( + "[", + #if ($e._M_pSingleAssignment->_M_fIsInitialized) ("initialized") + #else ("not_initialized"), + "] ", + $e._M_sourceTuple + ) + ) + + children ( + #( + #([input_count]: $e._M_pSingleAssignment->_M_connectedSources._M_links._M_vector._M_index), + #(index: $e._M_pSingleAssignment->_M_pMessage->payload), + #(source_tuple: $e._M_sourceTuple), + #(linked_sources: $e._M_pSingleAssignment->_M_connectedSources._M_links), + #(linked_targets: $e._M_pSingleAssignment->_M_connectedTargets), + #(reserving_target: *($e._M_pSingleAssignment->_M_pReservedFor)), + #(Scheduler: *($e._M_pScheduler)), + #(ScheduleGroup: *($e._M_pScheduleGroup)), + #([raw _M_pSourceChoices] : $e._M_pSourceChoices) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::join<*,*>::_MessageArray from +;------------------------------------------------------------------------------ +Concurrency::join<*,*>::_MessageArray{ + preview ( + #( + "[", + $e._M_count, + "](", + #array( + expr: *(((Concurrency::message<$T1>**)$e._M_messages)[$i]), + size: $e._M_count + ), + ")" + ) + ) + + children ( + #( + #([size]: $e._M_count), + #array( + expr: *(((Concurrency::message<$T1>**)$e._M_messages)[$i]), + size: $e._M_count + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::join<*,*>::_SavedMessageIdArray from +;------------------------------------------------------------------------------ +Concurrency::join<*,*>::_SavedMessageIdArray{ + preview ( + #( + "[", + $e._M_count, + "](", + #array( + expr: ((int*)$e._M_savedIds)[$i], + size: $e._M_count + ), + ")" + ) + ) + + children ( + #( + #([size]: $e._M_count), + #array( + expr: ((int*)$e._M_savedIds)[$i], + size: $e._M_count + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::join from +;------------------------------------------------------------------------------ +Concurrency::join<*,*>{ + preview ( + #( + "[", + $e._M_messageArray._M_count - $e._M_messagesRemaining, + "/", + $e._M_messageArray._M_count, + "](", + #array( + expr: *($e._M_connectedSources._M_links._M_vector._M_array[$i]), + size: $e._M_connectedSources._M_links._M_vector._M_index + ), + ")" + ) + ) + + children ( + #( + #([join_type]: (Concurrency::join_type)$T2), + #([offer_count]: $e._M_messageArray._M_count - $e._M_messagesRemaining), + #(offer_IDs: $e._M_savedMessageIdArray), + #([input_count]: $e._M_messageArray._M_count), + #(input_values: $e._M_messageArray), + #(messages: $e._M_messageBuffer), + #(message_filter: *($e._M_pFilter)), + #(linked_sources: $e._M_connectedSources._M_links), + #(linked_target: $e._M_connectedTargets._M_connectedLink), + #(reserving_target: *($e._M_pReservedFor)), + #(Scheduler: *($e._M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_messageProcessor._M_pScheduleGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::multitype_join from +;------------------------------------------------------------------------------ +Concurrency::multitype_join<*,*>{ + preview ( + #( + "[", + $e._M_pJoinNode->_M_connectedSources._M_links._M_vector._M_index - $e._M_pJoinNode->_M_counter, + "/", + $e._M_pJoinNode->_M_connectedSources._M_links._M_vector._M_index, + "]", + $e._M_sourceTuple + ) + ) + + children ( + #( + #([join_type]: (Concurrency::join_type)$T2), + #([offer_count]: $e._M_pJoinNode->_M_connectedSources._M_links._M_vector._M_index - $e._M_pJoinNode->_M_counter), + #([input_count]: $e._M_pJoinNode->_M_connectedSources._M_links._M_vector._M_index), + #(source_tuple: $e._M_sourceTuple), + #(messages: $e._M_pJoinNode->_M_messageBuffer), + #(linked_sources: $e._M_pJoinNode->_M_connectedSources._M_links), + #(linked_target: $e._M_pJoinNode->_M_connectedTargets._M_connectedLink), + #(reserving_target: *($e._M_pJoinNode->_M_pReservedFor)), + #(Scheduler: *($e._M_pJoinNode->_M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_pJoinNode->_M_messageProcessor._M_pScheduleGroup)), + #([raw _M_pSourceJoins] : $e._M_pSourceJoins) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::timer from +;------------------------------------------------------------------------------ +Concurrency::timer<*>{ + preview ( + #( + $e._M_state + ) + ) + + children ( + #( + #(state: $e._M_state), + #(value: $e._M_value), + #(repeating: $e._M_fRepeating), + #(interval_ms: $e._M_ms), + #(linked_target: *($e._M_connectedTargets._M_connectedLink)), + #(reserving_target: *($e._M_pReservedFor)), + #(Scheduler: *($e._M_messageProcessor._M_pScheduler)), + #(ScheduleGroup: *($e._M_messageProcessor._M_pScheduleGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::SchedulerBase from +; Concurrency::details::ThreadScheduler from +; Concurrency::details::UMSThreadScheduler from +;------------------------------------------------------------------------------ +Concurrency::details::SchedulerBase|Concurrency::details::ThreadScheduler|Concurrency::details::UMSThreadScheduler{ + preview ( + #( + "[", + $e.m_id, + "] ", + #if ($e.m_schedulerKind == 0) ("ThreadScheduler") + #else ("UmsScheduler"), + #if ($e.m_id == $e.s_pDefaultScheduler->m_id) (", default") + #else ("") + ) + ) + + children ( + #( + #(ID: $e.m_id), + #(SchedulerPolicy: $e.m_policy), + #(VirtualProcessorCount: $e.m_virtualProcessorCount), + #(ReferenceCount: $e.m_refCount), + #([isDefaultScheduler]: $e.m_id == $e.s_pDefaultScheduler->m_id) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::ScheduleGroupBase from +; Concurrency::details::CacheLocalScheduleGroup from +; Concurrency::details::FairScheduleGroup from +;------------------------------------------------------------------------------ +Concurrency::details::ScheduleGroupBase|Concurrency::details::CacheLocalScheduleGroup|Concurrency::details::FairScheduleGroup{ + preview ( + #( + "[", + $e.m_id, + "]", + #if ($e.m_kind & 4) (" AnonymousScheduleGroup") + #else ("") + ) + ) + + children ( + #( + #(ID: $e.m_id), + #(Scheduler: *($e.m_pScheduler)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::ContextBase from +; Concurrency::details::InternalContextBase from +; Concurrency::details::ThreadInternalContext from +; Concurrency::details::UMSThreadInternalContext from +;------------------------------------------------------------------------------ +Concurrency::details::ContextBase|Concurrency::details::InternalContextBase|Concurrency::details::ThreadInternalContext|Concurrency::details::UMSThreadInternalContext{ + preview ( + #( + "[", + $e.m_threadId, + "] ", + #if ($e.m_blockedState == 0) ("not_concrt_blocked") + #elif ($e.m_blockedState == 1) ("concrt_blocked") + #elif ($e.m_blockedState == 2) ("ums_sync_blocked") + #elif ($e.m_blockedState == 4) ("ums_async_blocked") + #else ("") + ) + ) + + children ( + #( + #(ID: $e.m_id), + #(ThreadID: $e.m_threadId), + #(Scheduler: *($e.m_pScheduler)), + #(ScheduleGroup: *($e.m_pGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::ExternalContextBase from +;------------------------------------------------------------------------------ +Concurrency::details::ExternalContextBase{ + preview ( + #( + "[", + $e.m_threadId, + "] ", + #if ($e.m_contextSwitchingFence == 1) ("concrt_blocked") + #else ("not_concrt_blocked") + ) + ) + + children ( + #( + #(ID: $e.m_id), + #(ThreadID: $e.m_threadId), + #(Scheduler: *($e.m_pScheduler)), + #(ScheduleGroup: *($e.m_pGroup)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::SchedulerPolicy from +;------------------------------------------------------------------------------ +Concurrency::SchedulerPolicy{ + preview ( + #( + $e._M_pPolicyBag->_M_values._M_specificValues._M_schedulerKind, + ", Min=", + $e._M_pPolicyBag->_M_values._M_specificValues._M_minConcurrency, + ", Max=", + $e._M_pPolicyBag->_M_values._M_specificValues._M_maxConcurrency + ) + ) + + children ( + #( + #(SchedulerKind: $e._M_pPolicyBag->_M_values._M_specificValues._M_schedulerKind), + #(MinConcurrency: $e._M_pPolicyBag->_M_values._M_specificValues._M_minConcurrency), + #(MaxConcurrency: $e._M_pPolicyBag->_M_values._M_specificValues._M_maxConcurrency), + #(TargetOversubscriptionFactor: $e._M_pPolicyBag->_M_values._M_specificValues._M_targetOversubscriptionFactor), + #(LocalContextCacheSize: $e._M_pPolicyBag->_M_values._M_specificValues._M_localContextCacheSize), + #(ContextStackSize: $e._M_pPolicyBag->_M_values._M_specificValues._M_contextStackSize), + #(ContextPriority: $e._M_pPolicyBag->_M_values._M_specificValues._M_contextPriority), + #(SchedulingProtocol: $e._M_pPolicyBag->_M_values._M_specificValues._M_schedulingProtocol), + #(DynamicProgressFeedback: $e._M_pPolicyBag->_M_values._M_specificValues._M_dynamicProgressFeedback) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::event from +;------------------------------------------------------------------------------ +Concurrency::event{ + preview ( + #( + #if ($e._M_pWaitChain == 1) ("set") + #else ("not_set") + ) + ) + + children ( + #( + #([is_set]: ($e._M_pWaitChain == 1)), + #([has_waiters]: (($e._M_pWaitChain != 0) && ($e._M_pWaitChain != 1))) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::critical_section from +;------------------------------------------------------------------------------ +Concurrency::critical_section{ + preview ( + #( + #if ($e._M_pHead != 0) ("locked") + #else ("not_locked") + ) + ) + + children ( + #( + #([is_locked]: ($e._M_pHead != 0)), + #(OwningContext: *((Concurrency::Context*)($e._M_activeNode[0]))) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::critical_section::scoped_lock from +;------------------------------------------------------------------------------ +Concurrency::critical_section::scoped_lock{ + preview ( + #( + $e._M_critical_section + ) + ) + + children ( + #( + CriticalSection: $e._M_critical_section + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::reader_writer_lock from +;------------------------------------------------------------------------------ +Concurrency::reader_writer_lock{ + preview ( + #( + #if (($e._M_lockState < 8) && ($e._M_lockState & 2)) ("held_by_writer") + #elif ($e._M_lockState >= 8) ( + #( + "held_by_reader(s) [", + ($e._M_lockState / 8), + "]" + ) + ) + #else ("not_held") + ) + ) + + children ( + #( + #([is_reader_lock_held]: ($e._M_lockState >= 8)), + #([num_reader_lock_holders]: ($e._M_lockState / 8)), + #([is_writer_lock_held]: ($e._M_lockState < 8) && ($e._M_lockState & 2)), + #(OwningWriterContext: *((Concurrency::Context*)($e._M_activeWriter[0]))) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::reader_writer_lock::scoped_lock from +; Concurrency::reader_writer_lock::scoped_lock_read from +;------------------------------------------------------------------------------ +Concurrency::reader_writer_lock::scoped_lock|Concurrency::reader_writer_lock::scoped_lock_read{ + preview ( + #( + $e._M_reader_writer_lock + ) + ) + + children ( + #( + ReaderWriterLock: $e._M_reader_writer_lock + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::_TaskCollectionBase from +;------------------------------------------------------------------------------ +Concurrency::details::_TaskCollectionBase{ + preview ( + #( + #if ((((int)$e._M_pException & ~0x3) != 0) && (((int)$e._M_pException & ~0x3) != 0xC)) ("exception") + #else ("no_exception") + ) + ) + + children ( + #( + #([has_exception]: (((int)$e._M_pException & ~0x3) != 0) && (((int)$e._M_pException & ~0x3) != 0xC)), + #(CreatingContext: *((Concurrency::Context*)$e._M_pOwningContext)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::task_group from +; Concurrency::structured_task_group from +;------------------------------------------------------------------------------ +Concurrency::task_group|Concurrency::structured_task_group{ + preview ( + #( + #if ((((int)$e._M_task_collection._M_pException & ~0x3) != 0) && (((int)$e._M_task_collection._M_pException & ~0x3) != 0xC)) ("exception") + #else ("no_exception") + ) + ) + + children ( + #( + #([has_exception]: (((int)$e._M_task_collection._M_pException & ~0x3) != 0) && (((int)$e._M_task_collection._M_pException & ~0x3) != 0xC)), + #(CreatingContext: *((Concurrency::Context*)$e._M_task_collection._M_pOwningContext)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::task_handle from +;------------------------------------------------------------------------------ +Concurrency::task_handle<*>{ + preview ( + #( + $e._M_function + ) + ) + + children ( + #( + #(Function: $e._M_function), + #(RuntimeOwnsLifetime: $e._M_fRuntimeOwnsLifetime), + #(TaskCollection: *($e._M_pTaskCollection)) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::combinable from +;------------------------------------------------------------------------------ +Concurrency::combinable<*>{ + preview( + #( + "(", + #array( + expr: *($e._M_buckets[$i]), + size: $e._M_size + ) : #list( + head: $e, + next: _M_chain + ) : $e._M_value, + ")" + ) + ) + children( + #( + #array( + expr: *($e._M_buckets[$i]), + size: $e._M_size + ) : #list( + head: $e, + next: _M_chain + ) : $e._M_value, + #(InitFunction : $e._M_fnInitialize) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::concurrent_vector from +;------------------------------------------------------------------------------ +Concurrency::concurrent_vector<*,*>{ + preview( + #( + "[", + $e._My_early_size._M_value, + "](", + #array ( + expr: #( + #if (($i >> 1) == 0) ((($T1*)$e._My_segment._M_value[0]._My_array)[$i]) + #else ((($T1*)$e._My_segment._M_value[__log2($i)]._My_array)[$i - (0x1 << __log2($i))]) + ), + size: $e._My_early_size._M_value + ), + ")" + ) + ) + children( + #( + [size] : $e._My_early_size._M_value, + #array ( + expr: #( + #if (($i >> 1) == 0) ((($T1*)$e._My_segment._M_value[0]._My_array)[$i]) + #else ((($T1*)$e._My_segment._M_value[__log2($i)]._My_array)[$i - (0x1 << __log2($i))]) + ), + size: $e._My_early_size._M_value + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::_Vector_iterator from +;------------------------------------------------------------------------------ +Concurrency::details::_Vector_iterator,*>{ + preview( + #( + #if (($e._My_index >> 1) == 0) ((($T1*)$e._My_vector->_My_segment._M_value[0]._My_array)[$e._My_index]) + #else ((($T1*)$e._My_vector->_My_segment._M_value[__log2($e._My_index)]._My_array)[$e._My_index - (0x1 << __log2($e._My_index))]) + ) + ) + children( + #( + [ptr]: #if (($e._My_index >> 1) == 0) (&((($T1*)$e._My_vector->_My_segment._M_value[0]._My_array)[$e._My_index])) + #else (&((($T1*)$e._My_vector->_My_segment._M_value[__log2($e._My_index)]._My_array)[$e._My_index - (0x1 << __log2($e._My_index))])) + + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::concurrent_queue from +;------------------------------------------------------------------------------ +Concurrency::concurrent_queue<*,*>{ + preview + ( + #( + "[", + $e._My_rep->_Tail_counter._M_value - $e._My_rep->_Head_counter._M_value, + "](", + #array + ( + expr : #if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 0) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 1) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 2) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 3) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 4) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 5) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 6) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 7) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 8) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 9) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 10) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 11) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 12) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 13) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 14) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 15) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 16) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 17) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 18) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 19) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1])))))))))))))))))))), + size : #if ($e._My_rep->_Tail_counter._M_value-$e._My_rep->_Head_counter._M_value < 20*8*$e._Items_per_page) ($e._My_rep->_Tail_counter._M_value-$e._My_rep->_Head_counter._M_value) + #else (20*8*$e._Items_per_page) + ), + ")" + ) + ) + children + ( + #( + #([unsafe_size]: $e._My_rep->_Tail_counter._M_value-$e._My_rep->_Head_counter._M_value), + #array + ( + expr : #if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 0) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 1) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 2) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 3) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 4) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 5) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 6) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 7) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 8) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 9) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 10) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 11) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 12) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 13) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 14) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 15) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 16) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 17) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 18) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else (#if (($i+($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)))/(8*$e._Items_per_page)-($e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>(8*($e._Items_per_page-1)))*($i%8+$e._My_rep->_Head_counter._M_value%(8*$e._Items_per_page)>=(8*$e._Items_per_page)) == 19) ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1]) + #else ((($T1*)(($e._My_rep->_Array[(($i+$e._My_rep->_Head_counter._M_value)*3%8)]._Head_page._M_value->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next->_Next) + 1))[(($i+$e._My_rep->_Head_counter._M_value)&-8)/8&$e._Items_per_page-1])))))))))))))))))))), + size : #if ($e._My_rep->_Tail_counter._M_value-$e._My_rep->_Head_counter._M_value < 20*8*$e._Items_per_page) ($e._My_rep->_Tail_counter._M_value-$e._My_rep->_Head_counter._M_value) + #else (20*8*$e._Items_per_page) + ) + ) + ) +} + +;------------------------------------------------------------------------------ +; Concurrency::details::_Concurrent_queue_iterator from +;------------------------------------------------------------------------------ +Concurrency::details::_Concurrent_queue_iterator,*>{ + preview( + #( + *(($T1*)$e._My_item) + ) + ) + children( + #( + [ptr]: (($T1*)$e._My_item) + + ) + ) +} + +; This section lets you define your own errors for the HRESULT display. +; You need to list the error code in unsigned decimal, followed by the message. +; Changes will take effect the next time you redisplay the variable. + +[hresult] +;1234=my custom error code + +[Visualizer] + +glm::detail::tvec2<*>{ + preview ( + #(#($c.x,$c.y)) + ) + children ( + #([x]: $c.x,[y]: $c.y) + ) +} + +glm::detail::tvec3<*>{ + preview ( + #($e.x,$e.y,$e.z) + ) + children ( + #([x]: $e.x,[y]: $e.y,[z]: $e.z) + ) +} + +glm::detail::tvec4<*>{ + preview ( + #($c.x,$c.y,$c.z,$c.w) + ) + children ( + #([x]: $e.x,[y]: $e.y,[z]: $e.z, #([w]: $e.w)) + ) +} diff --git a/vendor/glm/util/glm.natvis b/vendor/glm/util/glm.natvis new file mode 100644 index 0000000..7687f8b --- /dev/null +++ b/vendor/glm/util/glm.natvis @@ -0,0 +1,65 @@ + + + + + + + + + + + + + {x} + + x + + + + + {x}, {y} + + x + y + + + + + {x}, {y}, {z} + + x + y + z + + + + + {x}, {y}, {z}, {w} + + x + y + z + w + + + + + {x}, {y}, {z}, {w} + + x + y + z + w + + + + + (({real.x}, {real.y}, {real.z}), {real.w}), (({dual.x}, {dual.y}, {dual.z}), {dual.w}) + + real + dual + + + + + diff --git a/vendor/glm/util/usertype.dat b/vendor/glm/util/usertype.dat new file mode 100644 index 0000000..cb44de3 --- /dev/null +++ b/vendor/glm/util/usertype.dat @@ -0,0 +1,407 @@ +attribute +const +uniform +varying +break +continue +do +for +while +if +else +in +out +inout +float +int +void +bool +true +false +discard +return +mat2 +mat3 +mat4 +mat2x2 +mat3x3 +mat4x4 +mat2x3 +mat3x2 +mat2x4 +mat4x2 +mat3x4 +mat4x3 +vec2 +vec3 +vec4 +ivec2 +ivec3 +ivec4 +uvec2 +uvec3 +uvec4 +bvec2 +bvec3 +bvec4 +sampler1D +sampler2D +sampler3D +samplerCube +sampler1DShadow +sampler2DShadow +struct + +asm +class +union +enum +typedef +template +this +packed +goto +switch +default +inline +noinline +volatile +public +static +extern +external +interface +long +short +double +half +fixed +unsigned +input +output +sampler2DRect +sampler3DRect +sampler2DRectShadow +sizeof +cast +namespace +using + +layout +location +smooth +flat +noperspective +centroid +invariant +lowp +mediump +highp +precision +patch +sample +subroutine + +hvec2 +hvec3 +hvec4 +fvec2 +fvec3 +fvec4 +dvec2 +dvec3 +dvec4 + +on + +final +abstract +limited +access +self + +uchar +schar +uint +sint + +int8 +int16 +int32 +int64 + +sint8 +sint16 +sint32 +sint64 + +uint8 +uint16 +uint32 +uint64 + +float16 +float32 +float64 + +quat +hquat +fquat +dquat + +handle +handle8 +handle16 +handle32 +handle64 + +flag +flag8 +flag16 +flag32 +flag64 + +import +export + +hmat2 +hmat3 +hmat4 + +fmat2 +fmat3 +fmat4 + +dmat2 +dmat3 +dmat4 + +hmat2x3 +hmat3x2 +hmat2x4 +hmat4x2 +hmat3x4 +hmat4x3 + +fmat2x3 +fmat3x2 +fmat2x4 +fmat4x2 +fmat3x4 +fmat4x3 + +dmat2x3 +dmat3x2 +dmat2x4 +dmat4x2 +dmat3x4 +dmat4x3 + +null +pi +epsilon +infinite +self + +byte +word +dword +qword + +new_object +new_array +delete_object +delete_array + +int8 +int16 +int32 +int64 + +i8 +i16 +i32 +i64 + +i8vec2 +i8vec3 +i8vec4 + +i16vec2 +i16vec3 +i16vec4 + +i32vec2 +i32vec3 +i32vec4 + +i64vec2 +i64vec3 +i64vec4 + +uint8 +uint16 +uint32 +uint64 + +u8 +u16 +u32 +u64 + +u8vec2 +u8vec3 +u8vec4 + +u16vec2 +u16vec3 +u16vec4 + +u32vec2 +u32vec3 +u32vec4 + +u64vec2 +u64vec3 +u64vec4 + +float16 +float32 +float64 + +f16 +f32 +f64 + +f16vec2 +f16vec3 +f16vec4 + +f32vec2 +f32vec3 +f32vec4 + +f64vec2 +f64vec3 +f64vec4 + +f16mat2 +f16mat3 +f16mat4 + +f16mat2x3 +f16mat2x4 +f16mat3x2 +f16mat3x4 +f16mat4x2 +f16mat4x3 + +f32mat2 +f32mat3 +f32mat4 + +f32mat2x3 +f32mat2x4 +f32mat3x2 +f32mat3x4 +f32mat4x2 +f32mat4x3 + +f64mat2 +f64mat3 +f64mat4 + +f64mat2x3 +f64mat2x4 +f64mat3x2 +f64mat3x4 +f64mat4x2 +f64mat4x3 + +f16quat +f32quat +f64quat + +bool1 +bool2 +bool3 +bool4 + +bool1x1 +bool2x2 +bool3x3 +bool4x4 + +bool2x3 +bool2x4 +bool3x2 +bool3x4 +bool4x2 +bool4x3 + +int1 +int2 +int3 +int4 + +int1x1 +int2x2 +int3x3 +int4x4 + +int2x3 +int2x4 +int3x2 +int3x4 +int4x2 +int4x3 + +half1 +half2 +half3 +half4 + +half2x2 +half3x3 +half4x4 + +half2x3 +half2x4 +half3x2 +half3x4 +half4x2 +half4x3 + +float1 +float2 +float3 +float4 + +float1x1 +float2x2 +float3x3 +float4x4 + +float2x3 +float2x4 +float3x2 +float3x4 +float4x2 +float4x3 + +double1 +double2 +double3 +double4 + +double1x1 +double2x2 +double3x3 +double4x4 + +double2x3 +double2x4 +double3x2 +double3x4 +double4x2 +double4x3 diff --git a/vendor/premake/bin/LICENSE.txt b/vendor/premake/bin/LICENSE.txt new file mode 100644 index 0000000..f445f59 --- /dev/null +++ b/vendor/premake/bin/LICENSE.txt @@ -0,0 +1,27 @@ +Copyright (c) 2003-2019 Jason Perkins and individual contributors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of Premake nor the names of its contributors may be + used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/premake/bin/premake5.exe b/vendor/premake/bin/premake5.exe new file mode 100644 index 0000000000000000000000000000000000000000..f081fe1f6c990b2eb01ef5f3143857176e479bcf GIT binary patch literal 1371136 zcmeFadwf*Y)i-`7nIr=Y%m4`lh!`|nG$>%AToUR8azhAA49uWhq7`wBR1szb6=LWl zk4z3jX^XA4TA|w3wzgVD4XI)RGy!50E|!a^VAXcVL5)HoNMwHBwe~raGvN}S=l4E; zy{~@AoU^ZMuf6uV?X~wQx_yHZt0;;Y|H5HKslhM(=itAW|6?&JN}nrh`zTv_{C!xB zX~y4&&Gy{8Jay@^2ku#R=MPfvy7T_~AMmDr|L)XfzWY<}y+1W~R!Qm)9$0ku^}T!d zOw*cnmhbc>UipU+`oB&7c_Sv`eUtyT5l8uV?ufDYt$zClBkcGclk@wLz4`a0kv;hL z&m$H5?mm9!h(Y*Gyz-ADp2x30=hq{T;rG9C=8Q<<_ZLRe@2&UV<)Oa1j?9^-C^Jm) z%5Oi~yim_OuEdynnffToh#rd4+>4WQ7se}!9ghyA5tisVMp2N;|LMPqBS|6^sj-S< z4Hu-cRDpjZKU^;}kf^Mqr@e{Fap3iW|Bfdrg)T+e@Mxm4^ny%7!m7mRxdWUp1HMcB zcfI%Sm0o04499o~E*dKlgWu9Ug>-FQK{DMJF0K%S*)w>P;syu#uX zB`;bOJc#v=BRkLH-)RpNSOVkK0!wUxxg_lCaEh@g;@@dCm6}Tz&Qm{KKwzN%GOJif zmFA$5xshRQbTCOaIxO_6-eL`yYG{!(=2(bs{8OxUuFds}U8>I#%lG7RoI(dOVvbt6A}w8{*P?_))=qd-x}vNXY3C3P%ZxY_FY1t!-DVl4tIpb(Xm_b6t2T}0?piTp*vHk`EYAkB?E>RDms7nG?7E^0^X_|tByiQ0N zlLkkhMj zmm`p4Q46@Bf2CC^Pe74Omq}p~D(!?_n@|5I?fw(iT4IJJG_z{6TllEOnO3zuFcCCY zfGl;U-Jfr@`yb{8o5ja-Op3>f{#}g)#QT)Sf)x4@zZeGs-D$y~X4a<4*}8|uGBX;! zeA%3YuUTwFb85b|>|0l(vUh+(0qGAwYt*HfdxTpoJMR*IdS6j!5&owI5FHN8PfH7w zrUtF^>OYDp7Ri+~KZ${Yw2a+VN6R0{s0-w#S=G|CoWP7UyGC}ghebOUnQBpU)9g>( z>J+u#XW#&`dcbB^Y<*4CDX6Ge_TT1z)U1@-)u|T$O0(ikz;J0z`Lh&nY`7o=%~(}5 z@2|5`Z&@?a5?8G&UC6lB7datX`w#1f@ts%#j`NlJURl_MQ6!5r8c=&+6$bREIcR;G z2UOsXR|4pFr!`}DBWW#4MqO3dw*E8#Kxc`zD;0H~B`5YU#+U5h6IPoWr%F;y(ubH# zLp*e+9O9m^ae!*MReat6d;+7YMZAJS;9A@a7fWE|H=%^KO3#|Tqy1-N!8+zg&mGE*&n2 zba-{7!>L#+h8}y$9%IpC%N-^K2se!G+joG;sn)0pNB+h*F{8q-E~xMhSFrncrt+Ak zn;`)TYDR(17u&APRg~(!lkC31mHWN@s*6pNoF-o%e|?O)QWTehdvp2@lQ^-uuAg4rX*VS-5`qTrb&e+Uy^?Z6UA;Kij4hLb+(P$L-rwfWa^-|n2i0vDA-h9M^)X* z@s9fA=Ga{mXIhu1+OBjEu~pLa(fnyz0F8ozRBh-M`yZTD5y261&hIu{6ogiXk{a2yUPY+{`L|wq4f=mgyLc^WB4` zC$dTCAAXw%9vnC8*s^Si;zg)Yrns@@u3f;?K>T=in$^g##E-(zPp~+!e)<$-oqK3! zWI;&LCKrcnus<5?oU>8jTfTkFvu-Jip0B~P^!Ykok1BTmcDwg?C7`Xo-?BCoz2q?7 z67@YOi~dI~ir4C2ZBcyjr5SZtA!>=4sk4BoGf_Oa5*=M$D*tMxNpZ0z1rdEGb-%)@ zT7s@Nv5~NFKyBgi=i{9eo&xX%bi2^oCu^$J*F!C`Hkt^NkhKZwRBI`K$f%o$2bwFn zWC1T0={FEHb1YT+y~F*FSrzYz&F#1 zg z;%bx2&GaG0t^f|EN2?7}?f$9ILZsTzBo-8zq=Kq8iD3laat(j8=gV1b(h(R-xsf$| z1Ie+TjS$!vwGtW)%4iZ}J?IY|=#49AoQSDOG`x+MZF3Rnyq8qhg>el}~1rXT11N^H1x!2||H!Hp#kyW5hw|gc4 zFi7+mb=oL#>^7Pq3lHvNEIiB>kH_OcA@S8V^ho30g)A)do#u(a2d0OF4zVTtrUYiE zrDo+@RxiiQXM|(-WSoXpH3M2oZdx)iqO1qatFxfXs!g$bgQ({W13v#Fq$r8Kps`S# zco;MRSvFd2hj2>;JdkbqR3G|%9g7BWcdTS4FZ6p2U z)LR%lv}7~sM{mr<6wS0Up_fJLNcmQ@m6!Ont*-@qmUJ+tbxQ6_N~)eBranvfwPH2U z+PM2yc-s}0b`;nH+fy39RErYH)~mNb*|yqV^4VSDp|5x~sttyfAr(d%&j||&T4|m} zxIL@@!aw-NH8hl2`nqfp6Twt?UD_(2Ab3#{1QB)%2gERgXsdi28Bq0!qd3)@!b!XS zI2&x4Y8~}iA!svBt8+R6V?&$DEa9X#DRVDn?)RB9PKVMPr;wmm0)wkg`^@Uski_|B zn45Lpo*T&c0ZZ_m2^5==+p{E`v=h})nZ!4>**cB5I6BrCt2Et+E?dN(heZrGIebmN ztT{0nJ^Ck)dSf==-VSs?zr}ySm5G|EtbWyypaj<@f{Qg0CnNpX4njpfYs8HXUg?bv zGIJDPir8@^R`J~N%~VB%vRL(LjHA}6u7C0>>c`hx{0fC2oU7I)pf9Ln;)6M6PIwdv zP}h>Hj@l|8!1GC4d0ZhD6$(w*j^YL4TC(Gi^chIBBwK$Mt6;DERY4enVww<1SBVn3}JKu|?`c}Xu3 z1(BEQO2j1j;`R*YTIuo?Yjc9ra}_5gBZyz$>c#q6T@SEGJ-|B{q*z=co&aKLEJ~T9M68uB zEG%bkT?5+d>QRuqB`~Wh_o4Z%t1#kf`=q{_67MuYe}ocW7Xv-Ms}i42 z8qMukel+0rINwdAu{D#jxhgHuoo@GkX0QLoEG9@<8y@c&$@qWrFb^J3w6)H_V%Spuv z-1m1KaW-{3L5>*f{W@YSF7a>3F2W(EZ8gyA^d#{(Up~}1&PCMMlmGp`-jPG>?Ca6a zzWQ=sZ*gC_hQ8V%aJD|reQo$}4Xm_lXMH+5dmfzL>Dk7e9Xi-KFqJxcS(`w|cP5=8 zVtCEs2X6p#D=o1;5;F>93dCZ_7Mz`ytnL!Zc~Yvz$%g}jG>ipgR?)bI-KY#6l@sH*H$I|#a zI`Ln5HI4rX>K`2I;JclJuRa$J*L;Hh<@&Y3)Emsk)hssk`uH0=O}$S0Kb?^JCDtie z2Z%dGE~NXfq6DkclgM=T0C!{M#d(8S0GNHa**T=iT5`WXBzYEI&5$5k=jc-4^@$Vv8`!t@t6 z=FlDteDsUtk4OG2r5}+wIO0F2jx1u%D!BZ6kA|WF{C8;&EjdQP2b!~p2G*DZyM%t0 z(w1Dr6BB{Ic=H{mTKo-dP+EWg7bu4_+tj^T^~(p?>?WJNr>$=c+z7V5Jzy+n?OXO)R>SfX z=^wP&<85{eYzGYA*0+!U3wu_>vd=sfnC`Nez+|EaG3gPI2G*}+4OZZ@MdYHB^nz5Z zSF7r_=3olyKQgE9gEg246U`2fn>*EcE3~}iTKm@y#VI~M#R!EOZ1tZH`}(M}5>att zv3YqcRC6r87_t9h^g~+=}EdWNm|1#$0V6f1h)x3NV{L40bjLqJIoZ|I>wCTZJE6Zaq{|EJA6y4rhgpEZ1gn4bLN6 zuFWEw;ENC(yLGPRQp?GPGZ5U=$x!)N#`d5pOl~%GwgH`O-6(s!5Ill!%?Wc1ZH16; z^Q@STZteHinr)#vTsCfa$@cb&Fn$w_Dtl~j!;!RdLC!9Q7p1Q?ap;4)Kn&ncC= zeP>|`fo9SVdTLMtq-+OeCptY9E(eBt*WYNki6{Yi>6;I_4LZ+DnjJ-LYcz`mcnN|X z!t(jz>rbOsizEoV9oI=iA3yU4tOv<}TEvz=8PPD7+)459nd}ZtEOM>-f7xzGDYJ2!QYxh_~bpk~oZW#`Sj9biA-02k_EEW{po zA^)a&7$&M#-v6at{Qi#s>JYKa7UKUGCBMc_{-0pr|2EXmYFzdiDR!*f?1<2tCe(R5 zmX<|h97%clPmCg6rrjTg$$B2709RRmH>Rywj5*60aMXmo^q zD392UWZ)hs`9K-@6HpS08ewfYdI-+Cywq$Yd|nJ+1O%+?J!J}9xV-zEZlQ$(aqIu6 zEq$NbOspf_m3pg_#i97e=gcgLrolEf!O#Zsz5qA+*5=i>M&st>O*(G2QZ>oSc45RW zF^ZO8Z<-z~LbV+`f}@LdHO#$ON)7ST|LCe!uAWrn;XJplhNbHn_e9Dj>q*08S1gl)e^S2@hj(LnSN z5KUeO^AcG+hpu3zTH+4Hb(Oi_r9LD2^$>Z()7Z8U#HrXw5;$j8s=6{=78! zS~%LkO%&t8G^RjU(sZWcM-dxeicHuh5RIoDP&>uC6#(-v(N!}Xl@n__Xe>QSF;f?f zE|@siir|N4G5$sqY-@X5>Q^O7YX+KQej?g_r>mI#JIx#m;8DtAL-A$ive+^Org$1! z@P*{cBD3oOc;K9FvA=;Wo)Wfp++v4(^(@WMtR1&_StfyRJ+v#99g;+&PEU-I3V{~0 z8(z3|X;^YZHXs_i_z{vCE7L|JiT*>y-jmHRo35f^6M6G)%UC!WM;F6B-Gt&W75@TZ zS(ygGt$4!Zq!5K53&@J##ka6yo6btn8D=Y047yXBE!YfZ^h*;~s_jnD zq}7o8?3^uaZs8mQ>k$N>NNW;n0O2IS2Wl!jX=14`VE-_ZnVb=J@NW__SeDq= zw^d@#iKb-?=zj-Lj|EK`b>1P)vTV0_8fkbh@mvXe-z|dj6_j3rIpmpxhA0=vN0bu1 zK<>wiie4ZmCPros>$G#`PTj7}+$g7*i|6iVuHU#z&D>}?bK}r?WabRZ?Z`L!%+Yeg z%&kO!-OSu?P?XnMX{k1Iw79#Ux#)HF7<}J`x$K*C=7w{CyW}6cCd@-KEhM`O}NAl);`6K;gTEV>{NN9%~|M zyQskPnlOh7CQH-4uTwpgv0J?HHPxbRqoK4*bf8dec8VL=Z$XKJfd97EW%P~*qrp=a zrcP^~M|I?Yt~{w&dM*(UwG%Xmyr(H|XQEUfo5ku=G*I0@X%<(E(Zk}j*a0*XaV`-) zS%19MlSUjAlD6FHN}mArr9NyHo7p0v>7KlZ|;x&>h<) zNJhB3rN<<+Es=R2hy*P$J{iV6o6s4?fC+pXkED?GRo0xNy@k~yP8V1l-c-U2)Wy?N z;>_OuYQkwpT&%a36IfUeIs+Ea*l~T@5L^I-r7FB~T(H0t32K3HRtc=2rzk4awR7I# z-ckQ=M4n;PrgAtI=E)%5Vi=`g!z`T*^b#>bt7P1^h<=+cf?KKGwTQezpu}LGC0!?R z+aiuWi)vE4%VgBvLaH!%NsM;QYgDRRlQVhohD+Ot^(>TNr+r+Np4A4(49r#U@yIrF*BdY&bmV(Kj3$t1w< z5$}9tD;7LlhF?*9*1@XND>KxoiRHH7^vtY!FL~5%soMY8DUgv>CdCD(m=KXv2R0tB zHpiY0HL67&S4{Zgv@q^4nRO$<{ zCFFg#s`b;5PAfO7wo-OI;li$|Tl5}LGw!CY=VPEdPPaacu|pCkJ3Z@o-h0&Z*pQU% z^lU_uOZ*o!T}a{y%p%HdPS4Yv`~Z@Pt~bek>&P6uyn6HbH6~JtlYyWgLSd;`m4-0b zF|{wq1|I9affvz$WTc%zg6R}Kdp2fOUpQ8q#d}`>*45V5pU{fl?Mp3|9<65a6$0x5 z31BCBlyiZFX9Q&zqwJ+x?ZvHDqSa7ZRC}8*(Vk(3&qEi}e0H9VuMj4efJ8c}Q|eDA zmXJ%_t`ZcGsAm!o zia-M)!j6&Wjn(`1 z%DzK=w2l|aj@3C<+6x0s?Z}by0_m;C=(i1rh79^A_Lv#MkAaTfMIMripc6$QRKo9a zi=E^eUu}inf^#CYgJzW>hp$ zOcl6yrq~bTq)_9OM0!JLXuysk=iwQ>*u|HyR7fk^sq?26vFd6QS>}k;v+4okEn*;q zXE(0sT-0NZq&cHStUkn^Y@+aXQj7Tf34j5QHEFXYTC{CE!*YOf2qo|RhUm+z>#x9w zk-!O`E_lT-rFv-LQ?h2WSh|^Ok{R+Jsf#V_Qk(e=O^13wn+q|IYD;FR9o4c`{e+Me zITdx>OlmhmH(b9Nw0tMoiW|qAh}xxr%@7O&kZ#WsEW;9!$4a6VY{yz6 zEbTh^wW#jSJbZ*NlxEW>n+gC(yKr5qOM@U*g0i?)<4f;wbs$ z!w#`87VU&HU!&b^4TXLQ1n{RNTotL_Tes}P-k1eDJkO(d&2Kvs&U_>FUNBz}p)4)r zd~qm+)_ng+e-yT=9+a#@ya?Kq(=p1m2-qZ$}UD0BwdQJZQqRg=o$#=3^_tIOARMcVYvNsK2ilqM@B;mA&`uZ#82m zeJ~X80$wfFG-S?BGqZS>%eWNF+t@gsJK;4_$$z02NhP@&KC>C0_ahzL=3xuHS+_UuOx^0Ag#qq*$7 zTiBpP;v}&YILk06;3b;*q>~B3i&dyu^W|o>QJrZ?uU8jZv$ijv9~)L1)9djR8_e#T zb#|FczAl>?%(tse6XU%@X$P z6W4*EvTSU;EatId@Fil?sSC(gw`W)o4JIwrB`99qjfr=P2e`RJQ#tuyjOS}sTj9-+ z@qY;g9L;gotJUrmsXfk6J0do9dL{k?6EdH|pVb!7nzjQmIv0NIUg`j+_z5gG47MA+ zXU1R{==t`E@wQ4hE2nypJ{y$Pn znkS6?T^HT|?k4^T6a}{{Eq&mFtb;sju_?zQK4cm)N3bRN3(iB}oKP?iJkhB>YNaTM zyCM7nc^#m);8gp>SZ{Cg{<_7lK%__mY9V_DLVH+^%~Qy09L9fc36VykX}JZ91(k60 z?hDj}4!CiB1xT|=twIsGCIwjfU!vSJ3ulV1hkXCoDQfk zkkCMb{*n1MWitI)(OdVi!NC@Lg#GwCtKm_{|2Uu*koFQ71^VFQRr-nPXHf{^u|E!l zOb88QE)JKR*tJjN+hs=%Rn+A}E zA{=iIybyWCXDx_V5XZXW4%AsdtWrIIRRX5{pS6HG z;*v?H@Fi&cp^?ndM`0(-=p1iP!aL3)inpm2xrnfW98Q-fm1Kyx25XNUf(U<3 z<+}BbYw`u+(Rc8YLG5+Z~!_@8mA1F3A)*0lg)KMm_v0f1T$RTRk~FFU6_ zk5K>;E&5_8G=ejaL)EICF9%Z1%vaZQAdFmMB+FlHUNHVr_nA0SZ6xFFw*T>mj!WnQ^aH*-< z;-Fy5^aiNM2zI%Z#*T)t?XEY}4ig)qQJ2T0uVI;xr%1eoT{@{bt9$&dao%LQPX;m5 zc6Hqb0RjqHu@P8k!LAN|lHo6?gc(SV9+-atIzg%XdXNMR#L08~*pEY?Xg8Y8vcB*> zl5z(yZXz)Bqtf@Ln&j;Q`EAtE(suv9Y`)(9y5j-7HL#{eTbpjN0aQTR068@LmB3W@6*9}t-;4Tg+!D{JPTQjX+F-{2|4NGxHa}d|I!c8W+Lj`C>ar~#@nI0k_UO4#dXMIiEG!)H=;L# z4F&0Y%O36!@}xf&mPM_nB4kf-G0!4iw@)CjhB3hX*ZEImY8v`#D~IS~wEvW&<#V3H zNelnW4*{2cUxKaj71%epGXX)PcxWYeHMH>{%CP2PtNfSBF!p&)(7rCWJw3cG@mRi@K$(e?m23r3O*l2#SjH~KuYfx?L%lKo<-Baum ze}FPYkZeaGPaQY;b563fB4$lG9Z`9QWD8hb6AW7+tEsPu+|~Hk(a zpUtA8kIujHsampshdq=Eq)xz_ROc+}T#Nr>8xB7-h1Ha2$UTIvcL8_K638c!04K3aD#z0;>c8IT4j|EnDoH>ekMMM^edn&rj z0PT5w3U44PyTi-PE&+Z5=MB02)aG!8xQQwd$|l2s;NQVUAot_@HB{F#hb{~-fUu%@Hs1jH&n(vrAhd zAS#m6Zn04|(JbyGn?Pq*<&;`Tx2E;;pEcR4euo+HPf%=CzoG}?OW22jY$L0PJq?&6 zxloyN&r~d-!7U%QRH~Y8+@Qw|Z}sklck9VL+6TC@YJx z^-a(&+){Cm!@y)R{bexqbP0~Mmi76lNrdev_TFy6BC+Fs5|=wTUGqo8P9=W?49@f; zm>{sD6w-fgb>k@+;eDwGsGbSVG*!pvv)|*ZNa223;Yo(VxU~Yb7JJSuw!|5F@;$|E(D{H1+u8HE z?DXsTkxp4%5%uUmS~Y~hCNXRk6Bk`_hg*8akxgT`8iOvnm_??X;ewAVd&s5GBtCr< zbzyD5wu!ddLGRcnfQYwYa>QT8vwD~Ty^Xd4#8X8)3WLIh^0YYQoc@Sf?aJ--0Q2qG zp)zW#KfykztTvZ{0Vqz-aWEhRkM*6v{W?WaBTgg52ov6&qW2_9#Z?^!Bd|>IjJ?C5 zh)T#J=EB~dYN5R`XXPD8g>(7}hCZzeU2|8o2_J-aI1VUi=`jy3aQWufNeh#W1i2>cp zr-KJiqc0fXeCJ6B=90cvzO3S0uNh)4^7` z1Em3+t*Vx);o>Zx6}QznpY3#vl9Qqu!j<_6;9pObFR2Xf73*twFkLR9noG61l8t_5 zLmd_k>AZLy(qUAM&TRO%6YlG_R# zDDk`iYH^9>q(2(yNTX6I-)hWb!3`_sP!O&3%SsvzR;Jm(C!HWv4>3$oYdC3!1E(14 zytj}Gh*QCyQgAj4h0~}oQd_?Tb5ANnK}1a1`D~jP8c8nhi?dXm9pjCwI6L1L+n|hb zARN#aBAR~JK+^;Jb<*?@kQa#t_;PT0hfew86s#ki?Av*0=GsH@s+%4wsD@Q*Q4=pF zgLtVi)IGsAQl#$RA41&-DPAxAMB$J;a;aPyJzslcVWDZAZlsDFqB_Pc#>X(5gvjBo z;09#1;N&Cody{thQ9rrZEG8lrGt|47W&JZa3qeD@sD~sX?%n9PD+8o*0EK?p|4W)H&Cts1*i$lH%Smu zp>yRQkj{Z+huGHiT@-s(78bwV!VPz>a||gzabh7I#w|3H^8>BIb)p1IOn7ojI4(V7 z@rJ=ol1wgGLW}+it)`@li_G;qwobGtsEP0f6nw={pwU=2Be>Vm;KD zQ?VG9-)d1@lDw;w<5+!Pfy8f((DpiB1iou)-v`|S5HE#tTzb}qg!M?iQlY;5oz+2P9)%zcsWT%X$8P>JRP>se5hnqb%5V@wcB$FeS>QOk8CBo z#CqtPSmb3LVip`|wm0gWE|@-|{T3G4fOx9ao2$bLN3mNx zR{%Ftn|K;O;hPX_y&XlJ;qh>_hJEdx zNY+T?)Z3U_SeELIL>W4n9E2h@t+o(jAx}+pd$V+%**%9tBUQL=} z^3C_3KkrSd&WV{cCB`=k*ARFu)j6?~ro{TDU@Yl7FlbxV>@eva?KGrG4jNJ>{sN1V zup!exB}Bo5OwC!wvriRzpeR;{FzHoLP6;(p))zMueg*#0jEJst_zCD1C@{{UOVpw? zHTQ~EYiHM5f4;Dmag8CK>|Kn;u*Ptn04atw27Uq`ZkY*c3>gq3Z(v;e+fCly9N8#0 z7w8^GX;h%RrYzGkbct1vtHgZhR#00dLh+dSxWpooxB5Dq!^zSRc=S1BfMw#y1x$fi zx+#FG*bvW${RjAXNR2{c6~G;-TP@`jJZ(T120LSfqwy6Ca+_t2|Ft=p3pq zZmacmtnYklF{Z(jhG%`5gVjQRCshss30QH{R*AoF>awKioM(x6elnp27p!BHzDyLS zvYSyB&6ao^XwzkARQwKY0x8DHEW=T)iX{$gPrU~zM+ET!+T@NCsj=CzvC@mMPkJ>)*c>w4bS38&Ri~C7s*ykmVbK2HtqP13pcSoB1fSZIUmHKE@V>`(jy`;Rh zt^W^*qqP-(u&Z08P)qnB7{f`qEc!_Vuf}<7DSnapE$iaYlL3L#L*G~kCpl1*^kL#l z;iM%j8R!*7Py_fyLHUf@(TcN{@Aj;u*%w=Q9Yn3)i%+G-bff1oe_z+R%tQ)s+WRb~ zqgnhHq&j}W?fkP6Z~8oAORp@>^E_Y(-z2W)9YIKZUr&F095JVgg*%Y_qRci&XUFK- zTV(d9yh|6U4ct;~v*%5j-C)c%Q(Urae5cI*oiRJECXTZ&+>n&|i&_s>i=9qD8dpjt zyqZuk0TzcNkWk_(n;#x8HlB`SwT1#EuBpy9t<4Kp)_Jc^A0Nzzz}Pkd%rrb+JzOGs z-NqcN!JMIlhBV}b74=F;h?$XiKHU!#%){Y_LAU`0@+|B-6;85Xw$-9`zU??~56(tR zn1e0860rbnBOOf0G+wP=IFI4e(M|q>Vnj88c`Zli-~$zt=Huf6B_IvZ;q4}P%kthU zafg$vOoLv_Jh&=(e0d!XIIQB)HmSF5^hE+v;1D$%DcsK`J{r#XK%49qmn}D#0S;n8 zxf!js2sEr8Me*YkOPTe+{#y|&>HxzM?}2oK;I6noj4WzA9fqov34&u!hJ{vHj_%7W zB9r%$%Z?APKXMwI5n{ZA6xV6mF;wFfEzy*{q&b==5kIor0eRfUU-3P~_j$yZgg((9Ht)f#Nabg%1M$8O zpeLP29|f|Y)jEN@vj2n+mYs%LA4UwK+6HAZm}9E$n}cg2ahFZ{u3%o9vlx+M?ds&& zC>}l(%sb_Dg_G`}y0K_vE~Op>CFh-x95PsS0{4%=wb&6(nopTnIC$nFZO$?iU*3QQ z(G-{T(C09mqLFv4fpe;@HZ@en(SstsyaKqNZe189BD&n5JmeH4Fk@e8RZ@8YDcFwf4Wf zyD{S=yl?M-MM8~fL!4tbCdCyf&et4Z51UWTmwijBKA0_C#wa5lkFcn*)V?oU{YCe! zHh!(OYQJ==ey!CLven$~TYXS(HSyA|UZ=I%E?fO#NVgamf>v>BUouP|K4h_!SQEw6 zzS4c&WAL8>VeAiqx`sW*6vf-aC8|@ItxB>ou4YL;e4jB^ruhv_)7fxR_7wcKLGaw> z60>DhNE)zfE&;6p`CzbFBvOcxdlFF*oG@3WUyT!_wl{M61rqQVU)?d|X8=CFV>A{b zXS#WPTS25~$fXM?99~OBlel+4sc6i%CgWMkD^T)G^xBx$&R2QCN+P|4mN9^HQZZVo zBz*XRShIiiDU)xIR#M!Nnm__5fL+IY_-ugcW^oo`A%YaZLmtN3`DhGzlM%kz4Yw?7 z)43%vNz^ZPc@`1$UIzPVzyPJpgCEA}WDK-1uY;B;k{59<%y92;+?0!(weva_+McM3 z`oa)_NnaS^1zd!)XmnJI{=>qcJjN>>)uICEAMq(Q6H>vVozVT*T?!@)Q)M4J?={ty zJnd4o%}vXNbctx8N$UU-@H|fU98DSo6kJjy+Sb>hrB?XUqz_R)Kd=V@>(H%s%*t_-(hi`8HSL<_`YTPAy zj7CkQ)o9VYuYm>PAHHBJxOzP+mD>DEj6LgNWr9O2MyPwm%`{3EU3y-}NRPVnoXnJH zztvK7U{F=~5$#L=-K*dGZvMNqk`T9$rFY3$C?69Vp-I?IEcXVA&+G-Zn7B1D4w~Nj zIS=>-Y+N$E)+nhUma7RKP`(`bZ?IWGlmavK7Z|jplpu-lVr*YTq_{>a5icX#qnC#A zzR>qCfHIXQwdX}ARmvvEJ zUa&zSUnbyX2ETB@Tq@vTEu7T*q!eDmwkqsR(V_OliMXN2R)9YgxtCK6&v>$UWH1zK ze99&V+W?8h;y(GBoN*cp4y{8GM%{K49XrvRmiADAye|{WFp;36|50%?`W@{ocA?Ki ztBycOzC#Z5nzgW{pMm*X$q zM*$$s6phFtniDx6+9&AfOH;nbuuX4Nn!W*M{`Zt7+xiiZdJy;hKLcAGOwZG;A|GPT z00zw%>2D7hKp{t^F+An}=h4qo5D?^9G93L}19t;3XRY;u=)oEC_VT?Z^7ASK0J0tN zo!#hnlhKA}73%AegB|nGD22AfF2Mu7{Djby_FlHf$-jYcv^&-~l<;y3VvgM6&byf> zwF=6jgqJzN(u!kAs7fa>aH;4@&L zTUse#mKmofPPaT%gw86mZ%};KXMN>$s151$&Y-y`?kD^8A})onblk~I;g30R(E-1( z)v+qA`B}>?%XWnNK$p~fHsoOSR2p!#_jUk9xH^Qcfv9kXj>XsYoVR3-M%h?jS64Wc z@!CInF2ujPwf8Ofr8NEDFY!$D4}FlrOEFCBGyL*S2Ad=Swtp4PsIEe+2PGXLJQa0R zOq}mCSJ7iXrXU!LXp6q@^wI2zm3t-CjTimodWXkFbgU&n%~fk;BVfL#!JA z1)B)w(~tOOC^%Pr{eWDGPBoxfH|1Hfv+dQH&uKItr56}wEh4bZAm%0iaKXy7a3K4P z1fD9w6%-7mb{*yuGWb($`&~wy(k`0HAcSgSvEU+=w7(G3|)Xk+Lf@ng6Z zU>ovyEYch_eh5VqNV+`IPK0?j0A8FjK}-nFLCv(6#cWOSWo-EmpWvNpJxH}^i=6kA zOK@h86h9dYM{5?ln?qqLVBt|}3p&J7d@+yhYx~qJ-2PI&CUO|Cc9Wdwj^5o)^ffvF zZ7wvaefGw%-HrX{-y=ht#@hkunU5pWCdRuGA>EuzwKWc`9(C9`AnDqu6t;-gTFhjN z*#1wRu&f_ODTSbS{Vb?UJTM1EB;9Cd{kxn1RpZHgNdPFT0E$bD1DF63y0z{gLwhyk z2@?lykoq)lVPnqvQ`@^P_!4Oy!o5uXI{LmUyr)pCsWR@OMm&wbE;CBmE<~4nrQWF8 zH)(Bcrl878E897t3Bf0*9kKEv1-sn2@tcn{ijpcfz88rEK;3&y6t-ADV*8kp5Bqrb zMMp)SvW^JADKEo6eW!&o!F%QrO$_394kTV?JDjSiu!tM7_Hyz zZzP=E?7une!?`ScMYTk|VkJ$A|1o^*sz+mi86=^E?7;#H?b>5=#a8)qq~KPlt%r#i zw{yJDVs-4|tZ}}fi{b7_TC6UOS)BD?jL+t;Gh;gyiM|gFUy1ZSSMxrqE>?Rk&azOQ z-Bjlm)G4Go*nF)+o!wD&Y?b$gL4SD`a$y&0ABY3R5(51WZ3}h5j)mkY2N6mByXM4L zfFCrcVa1(=?l8Ytw}a))Rhl<1D$vv45MJ4LL$&#P@Td03o{y78Uzi?-7pMG27c}H- zgo!#b`1EZa1zv0-u;k_cP>-@``_adU;QA0WZDKe0{#fCF5iJDIoN1MFXXJF-p zPYyKdr+#ljg%EDgJ0zZ_K*VkXpj;nfq;UiAuM1*CR8>#=)9$js9q}o)fMj?Qhppghi z0FbF*Egc|6kp1tGW{sGa?iz7Er3J5Lk$7>=LR;0_()A%LuG5A!>m9NZ6L9 z%CHR7cnIi2h6s}Oiu;>Lq=G6C4&(Jfi+P&_1<=m-W#ejU|Jl@4^0O_=(XoDrgHOeH z<-wO*Gg~A7+vtKOK$z73_J?I7&p4ghC55coKtPL4i%*4&dG?o|#1q0^-=02O|of zW7DFp5PBruyNYC~IDj7xWIBtjD;db-F>j^a{dTBh{+-Fj?Rsn%p3`ENen zi!B(Qi3@b&Ch>z;y9`mT-x~8(7~;$6(OdFkNkr=VI!nPIr7)~aqr;n*^-=x|%D|-; zlWl!A8fzVkKf%g0J2e(gs(`G3+ch=fr3A`|C-X>T6q+0lZ<3Q}Ru9A2OGFX!IN;i7 z1uU9^oD^7va`PPR&6YwOeV`CUokDX=jrhw*gkz4b#@*KwfcnLo=h9y&vSVqt#*XAd zB+zpz>RH1{m8cM+;`5Qd*^56YJc2 z3FTz%U?au~pgXT2zUZd>U;aWGu&9QOho9JoSrgFbZwltG?V9NMTgu{^r2&qY0hz!> zj7!``$#MsBA*yX164`{6QSH>1;ZV^u%L3qTOy%LzhD1OjQ zi;Jm6j^c>{sW9E)H<LB*Ew!&J&mOyZyFJ0 zVhtk+3meEv5uP!iY&m4;av*WqjgwLA5fbM`(;}+LzP)7NrfvN`BJscB4;U05zRq@v z`5b^q7ngZEogU=x5YMDQcqj-!_B#Bcmv@+0hXfZsGxiDa;}&n-N=VVeerVt>&lb*k zj&qFYa(VW0PT+zZqd(}EFjoH0_=7I#4yt(I8kUk+Oc_<(;0#mTn_#*59> zfC&$o_&}THU}P-ivjnx&rpiVWx^FZSjq*l!3J^}$!(U{hyA6yR3azH)bfqfzTVDiK z!M;5J_*%sGmlIVX9*QptaEZ30c*Qdc0J+4ccqB@~jbFZ)g*)6b;&n?VMPxRQ!(ZIa zV)Be8;M+x74^kykDFm{QON<|&S-7~O0f$L{AJ4B&5h$bwiwn~1sOTpPX@KgXBDy|9 z`;ok)>#mMk(m6$do0c?mE1U|M0Fs1)ee@I3CB4}g(OBJ@(8QHDMc)Ww+m5@FlA3Vi z_Kd{p9E0K4g)qj=;qjVLhifZ6v(bo_9R(we z)+Gv|sse4L+;!JoF!9arjVhPqFOl!*K_9`*1dp!-;Y2p9*onbT zVNA=k+{hX7BAPSSmTl{CKPd=_ea81pN3zbjNQhPssEJFW8-Y%#=PUQ)M!{Xd$4vFd z<6_~6-%~v>wjLomAUy<_+W0sw_K0oUuIhx?BRDx3LO`_Iw06Ne-0$D{Z*!nX@Iy=W zfI!iS%Khq`wyp7K8o_hkk<|m#dYnhug-?)2Mm9i>4CN4&L@gGz!?C`$XfHRj4}Swi zZEK76^Xq|yq5NRpPAD2LAdsRuZ+~^sf$9bCRL|KJ$ZM<4+lwZu^I8IVC#v(B19_r4 zuPKoCNi{)p-qpyu;ObJ8iG;#tmm}^kaLyXdj;2Wzq@xBea~qBfAN? zpUC9nS~AtzgXH&R@?kCcZ%D2~u*K7!rA*_S*$^rW&UqR{k$4tUeo3jrd^86x(@R7) z;d^?&lT-_Ot+9+H`G2KFace@py#=?y6m^g`O>XtBD_Vw7BAAZKX=e+L+9k`g1blRg zAbugo50*&IS38C{-@Bu=SbyBV`2tdKkOQ9NDpD@0j=JPl1^e>Ub6JON1&GOS{}QK? zDPVu`Kq`(;Mfto4C=9+v8ET_nP%M7WtUidvhcBqXj0D8uw^J;B&q;lJnf`W)#lOWg zX{O0H(%(+8__xGNni=C8Om0O>^_192`LVv9WL%PMgDn_D<_Z@70P*jp5DzL2-EF{NuTWEfo#agv}}A%HGfW1~qn8aQ2811E@g zBz?>tvHB&V0teXeoF<+`0cNd+Tw_SAqzaT=5`co7C4cMG#nqseP@8aInA z&!b}J!2$6+-U*>ZpJoS;c`}8N2@1svtnjzd?bir$SC5Em4#oj!NHy_g0(yZQE#mXN z-hr^HQ7(O7HGP15ZEjD5^!iSQ?6urRkn+US2NA9M7Cp|A=Mf7`U`{A^dhurRAuSFh zs0Xz}*|J>v*R!e%Omxd#yV@)vsc(%z@T2&vW9qew%#Sb`gHom8V z!;ijk!AHYrv1_*#-;VJOxOkTAHRH60Aash?reIP)Jr>+4L6V)UZ~Z=`+QXO^wS~{7 z3`RtAKkaBrAAHUm=VUR8PYe!M-%_|`Cm=*L&AT{zxcB=tRJ*!Qv|n%s#!;f~g?Btt#M1pS@L%F^XeR1m zbr1WRTZ{_km7eAZI5P>HT=FG5Xt(kyIIENSEIM&Cp#UUsv1Hm>J8oW2O(3v58KgSe z`0For?A=y;Kkl5G;|xqm2^2eNDEMGSO6&U|FnVFhp>bf+;#^{Lj)n;DeL51(%MEnk zU@Q=jN--jrHmzwBy9iQ2_k|h^7*G-E&$FHlYfM(UqHm78>$7$pQkbswKg55P3JiSt zz-Z^wNe7xFkwqM*1RY2UexH&_z`@7>{mwv!8{1-aV70@nm|Z+qV1;3S4sY-T;Dt`o zAm1roz*;1usm^zEEwcsO@6>j=A=}nB6XiDxS3~r$@yS>;oJL{z^bmS2_!f0BYw?DQ zFk0lH%q$siRXvLt@ow;c+=tf`&InHkQdL_e9VbHl%E?q3ob)E!wmPS{&4JUc+ty8{ zGHP3~n1*-I6RxZtQ1K?Gj~d4zAOCaOul4nOro<+u8MfU)_Ro8*dN?-1=XK0z?)bdAH2nsJqCKPEpHD3`qh2D z6Ag?~rD}iqh|TYVhhuP+s0WlwM05@lqx{U|6Tv4;=qdJq`nASgWx@1=ox(1f!!lN) zAWPpPCmNsb4Zj@@w@xNjiYd^?Amyv%r*h`g_c&b*DE$}(>)*=ck03FrQyHiih^I;Z z@zdcb6=4nDNk71SWnV#LU4>H(!+f#%p_6>XVKBDj2JjU93gVGDkJnyNZknWBO~iIw zN%c^7#kt|$9u?ZLayu@m-y=r>~lqgt9Lkx`zEJ1_=UxL6{MPP zTv-p#3DSK;5+AmqJ%KAqvAf6}lvzB-IkO#`0JK=@ydP(svH5qP1Bs8J`L=Di59Tb> zKJ9W0bc;eAVqedSbEUW);oSAU7qfgF%l4JdW9)F-fZ1D4;QSasKN>7I`GyAbW6D-L zMFL^`3CwVuSKiK9+Q!CgU^J^8%M`!MZ{Yg~t}L)^JLwYlM&KEM4~#`# zfT&Vi)fH52b;q*(MsOs@z+Sl%#xr>zikJXqO=3M?)0yP*P`LqH@Gau-x%ZnLdz4k>p9+k z`Oljk>RqvFJl0tJOuVc(Nv=K*=nF5t9u+rVFOQVMzIvXFEqt!SXUW*@Z;!#}x&1=% z4#kXn`{Iub^=ybuXoVhwJH9$vafbv&W@R0*RpLgHi2mh2A7lIBzlpHWcojAnm5Rqq zc!E1hDH~HPQtEg&^*wbL}In3S)&80c;= z;El?cJiV&swX;6;UA3uMo(^Y+Mm8DU_PQXRVEC+*Mi-xo6gLA{S+{3^v zeb)1f7;i$w&0~Bq1v4?^sw7ZEs4tJ-+q2@)Fpd~C#EzNja+iqrhVjhMfw|ZZ;d9wx z+&*Oe-r|6K>ED<2d-W^^56kcEaCjTgNS7MZ7wJoJK@Kh*!F?lHAFj&d^BFf}bXB58 z;T*YJ+&)Psy4x@iG8co?np6CR?Poevo1b;E{I9_$C>c||o8l}lZ%UtjJ6gVITZ(i{ z$Y43&Xe7^DR88IE>M z1x`Q+|3o)P!Yst0+j-qg;<#$TNYWJCg|6E`&3pS%QGhewYgud0ab&eD6Nd3wFy0(TIL`u* zemEK=z7QP@((NZhKXK^U_eCkL1ngV_8T%_H4)+ZMW*_zSqVtrdDLL7zeeIMQc^^*i zXUKkav>wb3tcT~Unm#L) z@3fnE>1lHD`(QonX}}j*+1CJ1gQ))-QM@(yS_k+>b!>KzRp#v8<>u^EU+mP-mlatE zc|B*VMBF5u983cq)LppbIxA~IhxZ!UN>-cq%Ic|M?Eq$CwTtJ#N{CHZ8=ueeH+I_E z_^J8$tkr+ibJYpZGe>G2U74Ng9fIKvV78YFRC1^2gllcy` z6XYY%?EX<7aoiubf#eXDdiASG?7R0hxOg7X` zOHswD{-$ev)&|q{Qwkb#OxNawe%ff7w{Xk?MDI43t_@Yyrh;`~$X?mYrTW1AXBrwc z6m3}td5QbawlKotXOpkx{Z}2zjTqN){3;4XWSHm}a?F44zvz$`$uIeebMUaOACpKo z2aBx5upOM@!`m^LOU?LX#OQxgPBIU_Q(Iwu8vGU}DYhc$i`NiS-^e?FaXKSeeDGVC zjgd=$e>4K4Ar872ToL_98hRM1()(-chs>hxPn2ZiwAjwM{hc@Q z{w~gMG31|+^u=Unld&a{iAD`N}qKe~HX5TOg!zn@JZAmA@7%w3`%h!84WZ8mP?!a$xog2}(UvbgspDq{Co z(Y3B(&3}tpkvi%I$pva>OVkv1-(tDeVzQydo`x2`r?og*4mNzaTNp=cEiN&%So3Bl zj3=PJU;=eB?gx6_rKC5IL}NIP7YNfl;=rFA>J~M9wQfH#bo&ged2;&pK@CB(F7X1+ zM_``u3?Yr}k!{!mLC^(}I*gp@IPDjp?I~#H!y|1q ziEBp7DKTRW!k!yUBe{Hpc)_1^2HPZhrJ{Jd|1nFRHy+zO>JDdNWC` zHHpp0(7t{(Hk6Fhr|#Ret04UIpiWfE3N;h9UBO>kzLx;LwyKG23QvGla{#csdd z*0%?~!H~6Y*=Jb|%ZF(4>0;lXf+@kf2aLAeS13w)K`O2lu;P4n4n$S`N9Oc>n8-u` zXvcT#-Kox7DT<`l{N73$%a^N=*17P@BTPF+GPJ_U16{9QZ-t4lKXCh@9VrQ~vPiJv7<2JPky z!osk`p_wMpw~Ft0!BLrop{D-trjCnM~1tMAdZV;itEFvHlb^)7a6fnzh$(u$oZIT|H#9HR5qZ_JH72>lpe z+)9QD1%5nxKX7t+ak}P(XgiE7bj7)@b0xs$MjFnaX&=X+L&Y8YF4gY;N87u=M^#;m z|C7ul8IplBNQ9`dMhF@k)YQ-l4$4d(lkiRmBv>J!wKPqs7sCue4M}i&!)b5Wj0-6~*S|OG43%!;dS>ih0ccs-ILJ zI6$#>y!K--OO7U2PJcwr68JZLXtubK#!tw{94LC7`o!ot*3H)ttVL(hsQ%cfu98?> zQtB1wmr6QDKPFr3GpZ=ngvv$Izwr)sBWexkGZwRvO3aoW&-Oa&Q5-DN0w7b#Y~$dS zfm^wnRK=txDjv4}&Z)ggfh~L5S5(=Ihv5mB3iW~&^5O&B?TmE?so?`b8i!2;Dabf^ zV|@)*~3f1E4+l z1@_In>w6RuVYM$o(3?Pzt^JG0cWYw74kXNhP`v{7g)v@v_6#Xq#b&Q{S=Jyi6`(P# zkB|QtkR`MvbfbXC7WmShRltDez54r)%;zGXexU;GVH342Ve!9ybl(1d1y%~&pMKLc z8gSsJdrPeLTR*yl2Pr|3$4`HB+S^DQD?0U~lNUxky!&7D)ZC&Sz!jqHP_ zrh)e{l>(mWwuLm_XqY?B3NDeme33vI>z);Jae{z%1bx#hKY{iB%A#>||>) zDoXi(VlVd}Kd{+U3=PENuDN(UYY%oN(crC4OP-)-es7$X;*$qHawKXfHQxVBlAEXH zwF=t~yaWnr;Tf623pt-w)92``R6G&dksD>bf?JT|;xC2cA-RYkC5Sc_Yq^|MnmIez6~)sP#?u{D>C%A!VGtxd_*Oz(qu!MlR2EhQB|Pt2`cSb9 zATdbX+5-z%K4oS-PQkHl|L6Zh0YM?+Bhytk<6ha;k%QCk8r65fpH|nWBhLBG8H;)c zGC2{z8Qp<_#2;5^@>c9ktjvPmEpxD(EQ!B)ToQ?aaB zCMV-&Y+R7?5k?Y$RGgC`n%CD>l3NbTaDiPhULGK)D3)6>v*$72(0%>FoG#Xp!c!8& z_;BC`OnuYi=EPX$D|6zm&h$qdoAu1?lAkHjEx~j4@@j3wq28HC&&K96`)PHO zE!&^4tVPG*OwuF8F&p<-c$k-aq!+Fa6HAK;W%_qn0LRAx`q4+{JNz9cVY0b4PW{~2 zLDoSQ6WMP`k8=xDXE{Yt@+%mhMZt(o-CvZq2v(83;5jagtdbM*({ z9RpxTJ_t6*k*fPfWwIx`V=~##awquvk9(a-3(Y|s??QiZFvj~xlcYW3NuUnd5&@_9 z9f?^%I#a+pW^4DlcYU^}TRB1t_T+N)gcHZe_0`5xJ3%_8Yovu(s}7h6+W#gnzaq+z z$vIb3P}CAPU!>nf?+SuCnTShO`1>FFsH{iMDzQMLF0=<_v4o~DHFXD#i?tYconwmE zn~_CGWGx@tXUq2@m^QGRkt%%A9I%7NpC)}!rsNvKC7I|VG7B<&T{4{_wn2a%Zyamy z&Nj9v3HyPVb^6L-&;EwR`TOk$FuqU4hRZU(_lpe|#`oQ(@%`aw$|Z+G`;#zUDeTyO zSbMl*T#QbMf@N}i@xXbBs*{7pU7JAo1fA4D;|sj8fMm`O1t1d&9$6pF4h3%E75ms4 z!@pHv?S3+akBnJrr2R)YgekL=3-wO%uzD@U-m5*;wPUKiSA55iO2~1x4&Whz2_feS zdsNIWMF+;V@ed7Fi=;g#GKKxSZeLCN5`0IzdUc83T&~wH#_dY?SKx598+Lmnyz(T< zFtM%~YCYp_C=`>F<60#1K3+u1-w$=9$Vqp{HQn`Kp-WzJ&rMZcisEh=%-uH&)A#M zd3A2_n;WAUW}>S=Rll? z+TmX{&l{Xz9AS2Mi1`(0eZ%(S+6S~rvBN295uFU^}1#D^?as3dG{Ugae~ zY@e~!O7|h3Yya`*`3ax(r7LJi=fI`yu7boGF8P2o7miDFn(>vsNh@OIOdOZy$OoiJ z8JFhg32Any_H?{vAD2eA(pV>z3$1wGxQ|BaRbKsFeNluA%>e?Nyebi{gBktXUXzq0D(igRnQ=&8RG!gKlByDwL>EUx zGMT9|`boFQO1IcdSN>t?mZ@|Z{gGmCxN5OpRiVF2d-VNgQ8YB;9kZ3%u0>Ul0;LEuV z`40MOxNx`)H@cVW)GI%EQsL=tk9Mmsn}L7i;oRTR$ft#da4dIBpSEl1NMv&gL}xiM zYBeHQq2vBO`_J~GziYd;$(^=q>HFd;5OF1(dDg~zRaH!HGR7QnvgNFxY$$AgXmL&O@m6DC@(-{=G`< zUpgow@QC7|RBoi$v1kNrug0*w=KQOy;-KjfIpxS{ybb>(1Qt#V$1VFJ>va1r{RmzmSj+E7 zFH*QBvZ}^te~W0p2jF=|-8=I4w>#!WmL=`nktXhT zXY$WrgMA?Xk73NK6Kn$V`vBB(`vHy#FP1{Yt?*K%y>hD%aPJI z!z+)~ROs*YlnTkR89!Z@tT56M-YN`XR(0J;8RC*x6gL>^jd|bc%Vz6k1y-(bX-9a; zGng_za3$oV1>J?#b}4rVz1M3~N)5gAguceW;eF>wV-5nAgP{|$3#u}{6QDM@p&W4p z=(RH$`iw7rGg&b5>PYEJoH-v^dEB`2v1DPPLp`oQhF*Fcm(bFeh_g@H$fji5Kt%E# zG`{j`NcOAns(Y@FS2abt>SRYAiP_Cw2hlG&BndWwV! z+M-_F>(vjSUa=FoP}B!A^dzw5Xy`5%M|Y6^vYur20P*x9eRu6BpQw8m!)*xvv}9;` zbyeYE(?j=Ywh4;Jo22xI&Hjq;C# z+QXe4jS=>V)mZsBo)Sk z&|7Ghr(0{g3zAihlb#?zMV%KkGIqV7uxNBPlG$jYBMe6C))6~8KLL(=ChOQpMKq<3 zqq?kKR~RRcDUwC=Fqcg+7H(wPq=CrS=oKXdFFwrC3>z2g-6lPoJ13Ct3w1cyOP!1o z6XqMkVaJ1d+DLiHNTbWRT)C|{ddghDgzz|%&1Ze#D z`qk1uD$S$pzwjqZWAw}wH!$B^gdgLT>@YisUoCp-V`pg`7J9_1=}_y9#H(S!fttvv zEJ-5MJ8zFgJl)R&?1X(_pRtxViJN8abzdeB3|_n8vZ#p^m)0Ps)e<{lp%;+c`Cusxs}>F+D6w_4KxgF4(?b@7(*O6vlO2 zeXL&`Y%TrQ@rhlx?Toibv$b4}$SKs7f_#Y+SMB`~$Al;4y{A)K*6Hcemh^j&2)9hB zT{F;hJyI1^5<-~WpW)tFtl5n9ysdlqm!hEX%o+{uMBP%KX-`$7`?G;!ey84?NiCkP zX7g;p=-m9JIlHAgQJZ&#I#WEo&8dO~M3gCY?b-MeI&5mYj@m$H;dDYBNdY7i1Y~vz zeD=>>CaUaZj`6~Xc>Th5dtL~93b}+^?>T*pvv89zuNZ0m1d=d#!^md0UgXl;C7%+h zryMo{M;UypcC2rNfKtKFsV{Nq6=c~GUby8v`3LezRtoblb3{R2>o9XOoe7V~y;u4* z+l}(C@dDE8<(aydBX0%zUF6{>mGNiQXMH!1#EpL(^Br$5oQJkt;S&rvG`GTqtpVo? z5OUQAw+ZYBw#wUvzl1AXYxa_e!x59pxmESV{!t&1Pnbkukly1tC?*Y<)x}L3oHWwY-|%*%%&i~Au7S^(5I6;{99lj(9ZMHa z7ZwkFoA5~?BlZpxWD<4qaT4`;`WoI|TYIzBE)!ldeiCt`j~$G@lHeP19xeCVwz_3D zh*95U+tw>il{vjcG%U_U`0ZB0>M44f^8Y4w=>cPBKw;3BK{d-)^MQCqQv6czfDnY{ ztR4rQ7(N3bqlm<&*{EfAvt}=JW_$)UelFdyeW-JRjgMx1l0R80!`gmmYG6WWXg!gZ zIbu_hm&7tg(;tRJ;`@lYfMr|nv=Z?h`v8Uu6IdzrXQWc*2NP6L!m~y)MUzlm#GD;x zjA7vq6N#J+LV_*pe}^>5{y|L|ZBLPveyB_mCx1}l#PV4TBm;vtB(*ts*ft_GDlpB2 zqMPuth5HQ8B6E=B$Wa0UoAt@~gwDE%>3en}Ynh)R@~WAtv`?-``EiV+Dl5d~)$?u1 zuMUbe1@lPUT;)aJf7W9(U!@DHmS!~1=P1fQh9RI$ehr}95D>~~lv zF+`^;i;)Ay0yG9H*-X<)ge51HG_v~S9|(0O>7AU_Ix3Znub*m4kH?P(&RF=7A?7Ix zN1~HW47uDZ!p5LeS*A>Ou`@&s$3_Y{aTz+GsuI4eT0bUX=b zVT;aGDlC_=nnJ}_K!o8FOa`z7Rfhb;m?}s}Hp-tA-?N$HB^dJh5CxYzsef|lOcFL< zb8La}r_sjdqcwkjZe|fVMBfmD*6Kc)VL@m&~x9XT?yt2k8bCgiO^@% zOCc-W@I9C4&eppe4s3OHEl3NeD_srasxNSjK8&{ax>)7&L!HB+Gw#Nj+OBZco8k=+ zadOcSlz7v~j*ksgSI7VK;5Vd6YxY71-+seuJHzi?eo3UZCE1hh34h5JfgY`|3u8CY zI-Qvsbm)+l(3$n{2xj52(|Tj@5qN&pN)K>GgS%6?bSq0P3S&phzm4=zl5%rmTb~o? zS5d4y`g<;PCb#h-`a5Ly_k`+iylktFFYxviet+T@b00|b9T@LPAf5u!9+o4H{IWut zaL$)CwPN_qcW}AXMIt#PkAyNc_Xqij`MMDifh8dauvDBm}b%(+?XuD9H^m@bRA0t^Ag2ygHSrA*xqyqXQWy6TTewYRg z9By%mqA~pxj505>#Vw~(mODcGyy1nh=-qLXl(YAeDz0~-yh^oLW2KJL1#b19zsvU; zH&c#{^xZC7^8{Z0PBL|mZAz@aWG6nJNtF&(7@z&1{M)Vk9|SL`8oAN$U4pVG25FcM zqza0aQbH&h#P>Sia$q)hmpkHjSJbB(kE8QZ`h7CBzGi3RXL?Iqp-V^{au5}#{j;gz zBG*-Sx?=ixAI#dI=5`bi1o%34D4G;J!N9A4IP0lUm}EwtIOfgwOT_~Rww=$9I_01_ zSL~cQnwn%a)mm>7dyyRfGzu>#%%ZB1HGm1MFLVpbIJdG1ZP7RgF+MR(=t`&Y*MA2j znEvX=F#bJUxGy?I*9fWI^AHX1FWfhGA%?$f$)P;5#3c*QWUg?!SJWvcB$v8afx^r- zcGe&sZk6b4Q`slG9;& zl_5p|me>V+(T@=3H)i9d=nK>ZWDa#4S3LGN=L(dC$3AXlice75KbF44j0xWekJ6WE zA4Ol{bMee{PcIDf(0L@#)V5$s`RI4-g@mE19o48Xh4)zip>i{g5A|J7&kO zkB#kRr^-?sfs4k3H2Xq|3TalB9lon#?8qjMA697Y68CcbNSJ+MX1F|oV2vHzJ;-uC zWN=M-HJ+Z%{R{o6g&7J(bFdChQ+8)A<2DA|G&<81tKU~;jKE|IUm{y<)4nXNoA_L@ z4qmQ*)X1HWaVEY&yi6+wb6NVg6N(0!apfR{8OG=DSJ-E^=SmnnE2^BE{T{|YViM=B zfXZbnL%15Vo&UdltH(_Uvwbu!aRo}FeI|irHw=9hm2Q@zua_aFxC#_78#-B6b2rf2lYjxBypyY#EbCL3IAG= zM3d-od>lQ6s_OPIM>MC%g)^H2S6GqvCZF=B*aI2W(Bz9gXEuF`ez4k@wMjid{o;=0 zG144cuM?a1^4nJP^eOt%!SF(4mM6mtGk5rh+KW=l^zmgeJ}a(L{eqK6!q_Kq8EOnK?{+6xiicR3 z5nf0T%DLqtu`EAdVrkZ|*79T&^F>Uz;QHN^un`%|`Brs}N?kY>L;f54CKtHLlegGchK`aFk`QG%M`S5^)3` zMqvcDWvj#f%pGL`mpi<6HH^Ntt9QNbpT2%Z*ZPd!_2H${mG6+d%BZ4+yZ=ThOz`!W z`=`^-aM@~Nna;o+iA1IDs+g7C@(N|%X!Ij0rbr<+@1N(EWX+?|`BUmbOd(~sp4=dg z-fUT9<}w1?J2-AIi>{-eh6%u~HJ1s6-7ShaCYD@{lUGw0ibYK0g3Gb((r+GYy(cxP z!LKi4FQUxdeeBnicaanRMi-eR@lr&Nh*0s;P>0jgADl{R{esrJK&=dgX(@)jj$G`l zEUz6Iza>tY?><*`Xv>g4_&EqR(Xt~;PFTlY>l?Z6e=Au-uMxq+d7PW zk*mElBY2^xe@ZjNPA_<31Y4(PNIM)UC7P9xgVIN-RkXP#ldk5ZV%HV^I9a=$=9;CR zT_QiNt|=VRH@QPY6SVtt*zgdf;L*Pmq`*(K8Mc#b67;3c!o&8ZE?y-?wvnV2P1@3~ z{9cy+@KUFhN*tez(jfI)xtd+}W@qQ$(#Je+`|}99@Yt)RPKw>(pO0LH&Lxz8IGD3X zlyoQ=mi6cF4_B*-4j30As#PWy(Y(&r)9uwRPk(r&OItG9m}2FBlP>lhkQ8Xfj?#>F z|9q4w3tF3RObZr2Et|Sn1DZDqu>Bk3&w(ewSKHhrr~|Ymu<%O*3Iy7&=J{5d&_P04 ztC!nOdTkHz`z60Feuw$}iQjs_x0&BR^LvP&&=7O{2mXK-IY!Ua{@i3ZC%wglOo&?Y ziAFVFn2XAgUbs}@#NynlDv$LRd{Im_a#pPKMJH7Pe-gb?X`~xX5k&=WYyX*9oC;RN zn70_88S~3IX#A!@*x~pVg!U%1?~XswKGRtJ$PKD#G{>FL9BaRVaO?u%d)RY&9dbUb zTjWEc$Uxg+3X&{>D)11gfSXM+q8I)P?kB|=D)l|SpL`JEt<;ZPh0|usWB{wxVLnQb zA=bddcZyIYE3WC0{65adn;#lV4O|x*x*~WLC-0q2YML&5wx_@4Vp=6iqC;V+8AvCG zox8=KL0ER$oK($xlnk>y)vlInYxJg_Oi!n-!6zxvVRCp5Mv-gvl71qA1f9DdSXX6( z{G!a@|EQohvA^;DeBw>uDVE{$LuaIUXRZh~iToL1c2ZM=)xvt3r&?q`1a7QVTg{mE z0eK!My2XVAw5iCm%++$EUefMDbyw!qOM0b2awxoN6ZzJTsx4?9Dl%cT65pCyHLIyH z{AA@|`b0`kTDy8e+z(l#ire9y(jmsdR?$;>Qm)3rH|P_6=rvm5dExrdl#T>y1#hVj z+X_5f2|P$sz>-fY-VOqKlj6ze=r*N}DG(Z#WcoJ9BolPRK9meo_4HFd(oc#MIX%4y zH2aJR;`M1IvhWYw<2*}hH#ctzx>JCzC95oTvvAv!rA(G`r}0fms*tc`+c<@niGQZW zG85>_l5!;xq8R(g>}|ZcMc#mt&QOs9*MqD`_O{@KG;VHka1!d`ERq;Px)GfeyC9S! zUg2*eKIhz|Kw6KF^FC=kytlcITyCx-7muzZnp#ID2%#C6|5=%viQ<}P1wUKNJWf8{Z z_OP!`+qE}bxhm}2XjUuvWg4%tW@zkr%35^S9o@z3`32AGOwVCvd%`8v^d(!{RV{#o|F@bR4(Sh3`tDx=Z2Za;Nb zp+4>OD{RBPE@Y#raCrG$s7v!ZJ%d}Dnc4O}Sev!>{k2T*Z!tyHddz0zsJ<4Ggc=kl z?R=kruDrt7{1pa;U6uqX$Y&jef4wZU*X`MoiJqau1rJ=tS=#w~MNi$`bQ$3fFWK`b zg;EbP%(Xak+YeBY-lb}Z+krC(z)MC4weN;$og9Za7UuF#Nh)iUP@VJ1)% z+25#W=ff*y`j`Vo`;_pn#+uMuHIvI zIAO6d;S+juFmz%LW*{ZGFeSL5U>w%PENR{1xI$~&E%U{Td~l9%cSbfVq?qEL62=d1 zP7bjXu5ON8<*;)lh{0vatpq9yTyyWtGS8>c@<_c?bZWZe@kjLi6p&TPW=kCB@t>)> zOHEpHqg6mMX0q&4NhYDjv$>87HSVJ+QmBMKM=~o+vY(cEHfA+FVv(>h2WpS)xHUn6 zKbl%W?IlA>4kIRkgca1KV7~lSOLt+Wd|70vGP zyMN7Nk3Wmu@<@+A+q}4b%S)Es%E;1OW6cf|8)+nGEU2c@*6r&_3dh^24i#aAVteF1 z*djJt?%() zZcB>pG)vXACw$XG$8*~KGt_Ayg&lGyR!p*gu12dEm?KGkLMSR*U}8^l4lDcaetHm{ z{#Z^h8{R-sy(wadhurM<*!3}do$W>0c7M(&RjOZHW8A7T0TFzMVA=YN3b9ZqMZlY|BE{$%`m5933h2|f zy)^=DfG*naoTdAnx!ODjN1;yQJeW?DUtu;P9Gta+@e!&8hPKZ69QxQa*~G=D(ir%N z^PQLst{g7xu$T}0a31^}^Fv=yP!(QsvPPe*pAG$azD@}ARBhMuk!2`cXEy#53P^Xd zPZX}hNj^9yr|0>WyF1^WWgAzvXJrlA-22W^Z)Hsr!FBZK2H@n8sH!1TPp{ zh@IE^l9OISvC(FBI1iLk@!DJTZpH7c-+2p-{5HRD^4rSqxBP655Bp0}ACi-~*vG(2 z*30K{oj_h3UNfxUlT(D%-biz{UOW$OWA4V`mdT!itto_+4=loT&*eGT^fpSXt*$Uu ze%ki?7#Yz-Vn1v&3z289=^#!>phzz+&|Qz~heEH<$M~Z0I&Igz1r7o4_AD+D#{zxP zJl(NPD9$g$$08L_Yr8tbE7>Y*_lg%(d}Y+1?;M!c8J)E4jS)eFvuVL8kxF3`tBtpn zU|1HsX{^Lza67LT)o9w&f*?^laS_CVcge7Rw905!=B~2#&E5Sblbra-THJeandQAm zu<`Q_L)m?T)LI*s6yV(MlRTLGL9v&1>5g7llPSBU!f@K|VZMU%!jsaqaWBqdiO@MP zDVi?8S^T&|dX2r+qFGQH!F+AIlYYyQ=91HKYrH5j=|{J{Cf%>81k}G`axo!xzoe#t zs%`g6qc!(}$3M6GY|Z@s%>4k@SGd}el2THz3`pV60UF49t|x;54H!MuK(*K`=4qOPQK$m)K(#73wTBSJd18htpzO$jB8QT3n05q&F8&cE&&yfrA zuV`wddIT0xM=|^r6ZjTrVkKr#*lzhJB_hoBnD!sDL!D=$*FGu6)X}^rMXDOT{7Hzf zEqd{jQ{^({$rQP`o)kGvH04P=-9(}xrL%{8puJr^JE0*kbVAUj{5U@C>;nT2^Lw7( zEByY%?*za1_?_jKL0QgULSoo}w=QgXkmQ#-m4J$#&~ia0 zwKG=4aP&=V2AljqmELLbW7PWs;vjuXreb^p@L&RaF(qYMf~IA%b$BoToz8O@UvF7~ z+h%^Ju&IMv%k^&A_H+`|`9>Ju8nJ>aS4>=Weq}-D+2n;rAB(d|g)bQi4p-FWF>VrF zzWQFF&QNQMpH9sS&%l~OCL?pab93rz#h+x3642vFt za+3)X2;=uBDgQ}TpWd>{`xXaf3Cv)BX1`*(~j)&ew<8AbtpQ1AYjM-T)jRoAsC zq!>1kwAgB@>mIWn5u-CQ_($sg)hy#T=+!y)es;F?#IsVyc-$-5g?CVdM(mkYbmFe# zhWN)P%E4n^+5Hp7j&*FjC7$OzfGlP*@UYF9aod-3Yw4^qR}lfi!ri^ z%c!rMK4b_R7{@4Uz5<4tkiU)qmYF+hHwG`1fGuv_e|wCj5Buw)>57Y#pf8iPC(5Qj z<_)-KK0QJp)o|H#Yo@`zPOcw`1>9-PPz{nCs~B;jbg7+CMFG~{tLAi`NnXHN3}8Wu zo~hHL{Uc;Y9g#J+EOYZT-n;Tkhm>d_BpvP@@$?7W%VWTvVHPeNAfRDaplxpyqJqd7 zIfY*i-9Sx}Ijp3v>qE%xP-0m7j|pAR$M=*_u{m?6d4!CQYPCE6?SpP$EH7x-z3R~P{OGp zBR|^Xby2Df0z9+oH=;)od*;n3HjumI8VwIi!0)w4JDK)K_5XAWN3=eRZ&rpA>9yc$T095It;AXzsAbz$ z=90p~{v5bm|2mOIi@Zc%n$uI_1l){9hxv)fSLKuVhNuH(d@LssEcI+yi5-qaDy z@l?C4=Ja^o#{@aNvg+gU7%t1}DJv-D-njR68q`FX5gFbjqS@s!Eep!!)4zR@jy#iP z?$xhimI9;P9Kl#@hPln-4u=Hp%tOJx`2|VOpGXX%@*cMozhCPb-9e8h%8hq<86EoYqeM#*Vanw;BVsc zBmF48r37C$n#A~C0<^U?3DV9TKdvmHb1FHVc!-YJAOx{#uIvq3h4Q2 zIR%e^7jC^OM~2UMx`|Q_7~iVqa*N2H?#aA3p)hAPidt+SHa_u zJ9JNuEifZe%;AFJ;!I_QBIwnf-IDCvFn@aDQaZ1Lr+z?6@g{KT{ri>R=}#YscoS| zS^TABNR6kDPd1s6Di>3siEzOi9XpEWb^9I8Tzk7eMaQu_6<=}*pilsk3ck^4%&Eh* z?jC;*k4Q)qwyqERG2B@f-aISpFW}*hu>W>6pc_ytLGHu;Ro(tTQrMr{?q@2j*2{Ri zQ7^llRQj@2;iY)i-yU9Cr!Q*K7Yv7&4l{h;gB@GTc2IFz=8QaO2*HjoH_r;MAtbSn z<<`(-!E06n;GZq#WtqmaV#N-5knh$2+>GTNM3Gt46sd-LG|J5v0AAU{D|&{YiHO-U zLIU5a5jl@R2w9pnJdrJq$m6Zj`7{ARVMlkF!`bbhm!uzL{Ynj&tqYd{gt9xj%TkiU zjqaYZ97)$xra%>LnH4Tu6$S+KzpO4?ma8MnDVc(vpK{++#`F*dfxjOA3iDEDUYr7{9=}P-{2R=d8+%pCfL!WrJ@*;%n!ld= zPM9~`4aV7X=VTUPUvk%;F{3e$;zZnSU9qY!6_S8u@HnB)lb{wybT{a zXS1q4IzhOx);3y%XeH4=%rqcUdE)a~ofi^nF0dhBZ+5rWI`x{S(A@>LKmnH6lA#DQ zI~Yb`9h3CNCP^CjgYGYY_OB}8ij!f5F;tBpt7VHVaK#77Wv?cLdYfl~j+cJShxD>7z2|aiWxYua_FCuL5ty595fIi|5+$L1bzG54LQIo)mwP zg#Lq#;a_MqeDkOEa)QH#UK_Nd4#3328G8^pW!M>*#L&fFiH(UDnOX2aT+1Wyg_vU@ z2vvv_C+QehEL*2~F?=JS(Hd{l_v-IJ3fMLxldBfnf-+3y!eu$CBg3A(TQAiQsR}7W14*=#;3_2Ud>oCOy^|$zEpt8FxPa0vlmiK$WB(EBf831_@!!XA zBfOw?;4_pJ^CH~O3TJu|=J3|?BK$js#Zo-h|PM7{ljkfFVRFTwnG1~dZIPsW(MI(Xh zJY8G!aozJqs@-9nN!`dHnb@g4#ZKB{6E#;)(~Fj-9Eb{=f9#VuHe8MJ=s%%f?EECaODQ{SqRE}(tj{0P@G1!jaIf^>TvFgmSTuRw zX~{)1*MOo42Fa4oM7&f~l1$xfL&4_1MVE7Y*}mp1mFoGO=6Cn#ch4(Z3z#u|zz}Jv zy(j-bkATTWLdpMb^a43{Pv1E4tR@@QLzJA1zV5p)F zU_-_#QSFvxaqeF+LT!||>Pdzlo8e+;S%|Z-9>I?LS}zQS`+vEjY^* z5GjJPthg-}?+ABAt*ui=VF+d2FSv;#erU+uas^97eshlgYJAJSh(*>61=eRAWI58C zbL{Ucj#ke9i`NkRF+1K`SN^LUDTumz5flxNW+v9KS-yz4N{3snGRr3xMZAKym(d0! z?R~~Zt9ZQ4i8Xb18ryqbQ>zmdqh^&_gNE!4uO%Gv|Xk?}oJAyXXVwm#!Uphhhg+9?h|xqctpN&s=M z?Ei`rwtnWPrUCqrM5=gRtFM+;W5y^A58uo>mKk0&zSYQ_tcL5QL*Zh#pl@f`L%;$E zlnw;F1#AV>v8M5^%mLpD4~L2~9ZLO%(J~Is!ywbVnL*d?>5PITja0l|FJWr$hl!<| zBuD-mi?m|S2*F2_UwKm4EFgIY_J?<@_jES60tHXX_;SDLQ=-A>Gj3AA5izM4jtpLG zZS~hD`R`COtu7DJQ*C?`i{;qzvj{h~*yQ6X^ADYuDScwOUIDq+-AaDr4rnvQz!5HX zx)PzR#(pyAJd@6m#w?5zmcx&z!Nab6bnrf53jHIsv**@k2JRGjMza$12ABWus~~#8 z2i37hVUII92?%^Qi{b4v{!9dBDhz&=2|tz{jPZkNnZ+#Bg)Jz;l8LAM)7=o^&0;S3 zUfiQpug$h&OnSt)PlS#L%|eDFkZZb3lv%u-J(_3njnJ7s)7lr#5od74Ifm^q)3jn| zq}WXymN2Fk2Y2|V=O(q61!OjqZ7@=YWVsXr(nLI$VY2WcHbe;N_cAraNEb-v_aol2 z1uw5333Uz9?`zG81UhWw={101QM_)y)25e+3RFag;WX@<`;1P$bLxeJc%*6t@f((iCD~blsUC08aEKRq0~l_tX7rkF{QUIPd|wX8os9S_kYc(6V+rM#G5$n!YF!(Usx%t0o349Y-EI&QYB3$n z5?eBy50@ulu9x4Xmb7rH;fgV;Rs#h;PssWy1W8FU8&^Ylv7l}z-p&(c8q;!B)I%68|Vu~?kd2y#g9GNhsh3EIOff#|Af@+u%_ zPeMsLsxh?|gd0~|cV>fxo(VB?)u54|94Q(Ji&@?z9(-72WZ^#Oh!*NM5on`A2Bpk7 z(&(0*lps}>iYO77ynxtBVQq)g%N1=qvgHFTQHZR%7Irs~|GuT0gRR zjy@Gug(-E@50hl$3exl$KSV@E)1W`(nN}aDF$T-5JP7*h+@AwS3-qb@hE`ERMa1u* z3=#AHK#jAr-m?L|TZ~P}GaeQ!71i6}yW-?rgoqO`1Gr z!8}9?7#m4Jk!+Zjs%j-dhQ~iuj}6b>tDqD#kdjxEaYg4F4t)!VXNjf9CG(PO3&}QG z$@Da{w9qqNNvS4WyiDN>*C&;4pm>KVm9&uCgs0fso)CXw6vtCIP=g~xCKx5e(ZT!L z)Xtf+T^WK@>l5bq96?CgooSfW5mBVm9a%YOyt$5UElu)t24{!1Qq0A$Z2FQxV|dSb z<%n~)=`11@m}N_Z1=Tb)z8#?xv(=XE1(9%Oi=I$x!*fpL$r$evV`GZera>A_4gF=@ z>8Y5TsdjCYc5QS;R*A!74&u>g=ffn8cC5Y{|IembR=aFb~=Y6{v?bdwm-_ZNFcW$G(u3W+t}|iF4^Qu zWrZ+vyiBf_vvZ9%UKK#_;Th-4t8??XrMmUnHC^93^-Re!+le9;Qn{W=_$j{wZZ2`Djk94U zJ(Dev>E_KMCd$vD9_gj6Wg?-iMmD9X)xuhRDvUa{yAUp{Nl2F*hLTE)Q2j?3X%7CkU^)8frmLyt+8(>CZi&t8L3<%`IS2o7 zR%mkJ3Odq|Y9>q!=NLy|`U5!^b_bny;mA(fadCyxME`Iz<0z3Th-G05UOn(l%0#=Z zygpk_`BIaDcOg12JUsGvJ70_`vE)d5*6Ee(!qqMqz34lr$;A+vGi}*mJD5?nZKOX9wN6{KR2)rkM4v2#5qTT&30=hAKOll9K*X*s! z64ECIJ8O=!QswYerR75c0K|kEI6;+)?M`t%}p7w~xM1uHbB%4*B$-ioh)4*~d8u04A*u8g z(KevWRyM8|2rMQUODg$b`mJt;ykvSIc9}N{IJC$f$rQ+S4csF0f*Uh7OK`F*r6T(4 zSRxRSQ1HM^V)UeS7pG!Sj=A{s9aSl(x*UOvEd%ol2vXhp`upuwDY~yBT$~-gxx&IW z1mCBM$&ss1RVL}#x?P#1XEM88`T}?BZKg|QQFgep0^x}wIp%DU1V`mOKo>2lGTwnl zGY3d0kz}tcXCx|(Ij_-vNqj^Nl(GAj(Jcn}S1Cb7z`)3zZlQ~J3H`at)q1zX5h)TU zA9?v%dHGovap60=dhY(KXA2Y(S zY=Pff9VZk(?}+M1;XY3faRxBoJYRyW=DSnuP_?{HW(m`MuYMZR#6<44VWg8|yU}Lz z+8T2kz>44}6q8c+Uy4>O8Gb~7X3hBRuhMLu z7g|!AUiAz$ycnlC@#(78?-T#q_B`?H^V;*ZkI|k6&6t(Yp3NWD9_$k&+|Bj4=pyIU z7dV0!dloucv?hlqdDCdzC2Z^f0n{zMvch;&(L|@bA)B4I6M~cZj|nH>=#0bbntejw z@7_Do;262iIA`Wk(Oo5Le13mu{f!?||F1uy{uq45*8f*?Gc&e+wKoQwA}r zeVhoU+V=}-AI3=t*`$4)B$|e+@MmM~`)<5_7mD(M$PwSeBqr8AL?0jCKDA?pCipX- zY=x@TXX<}kKcRfO-bX=I#;RB`I2-I6iCzj5YL=A{=tyZSVI1~R#vUnS{iiCX6W&dN z((glG{IG=dtx;t0i!YAtKk^b&MF81Uqg1UHr}<)9^xAy9FE-2F>k{$cxaR2!))ML~ zcys6swo&?JdW$2PZJiZ((D?2twMAq==E6#4$`SyB%UcfoWwCot3UC~G{M-CDRv^KUg{>nPlttbd zy-D(EZFjKth}hpRYtRCT`0&B`GvoO`Z7~U2n`lU+GRp>ZY=v)p*{V=$dmF@Ktq14( zB^sFVm`GEK5%jqg8fb0%6lN0A`ncT8VS#;un>fAJwZab1Bohe)YROmoY_ox69@icG zmh+p$uZW+#$7VD+$)4s&8~sa3O-oWlR_MLpO9`|3U3gn;hy%IV>roE10VdjYv+L<( zxfUB>OK8Y}hXLqPp%+X17I~g5&)!JYpwYULbgX-!dxlDaU($;QTeqayg15!9YHe3i z6v;8U=O$8h+*m@Efr;`^JQ&)0ynZSX){npw6c~jHz|aD1`(K2+5W9D&Piu3<3Q6N; zK;p!P?lDSmgeyL-Dx9dfi;?daA0H4j(W?e!X_ZBFxh$&7T~G7YCN9u0=b4_<%~g?2 z$4&Aj-9Z*Yci4mfas`>=yM%JdixZI?;@5S$-_xswzC}6qLuIPRe|5(TWINaNc<5|i z<5s1k zp%niW0-o$+lF4=@Pb#OhESa4Z#>lM-#|C~T1ICv~(d3GHGvt!qILGk*6R+WL5kt+( zwNq4XyDz2N=g7pH5ThZA3@`IaN#Q%4-M&;?cS({Pqal~xqxvA7iF1_itDZm)^bhWU z&n@lm(?78Nv@N%#TeZ7W(G^fGQ7|ZNS5rK{r}NJa``~WjV)J_hGn0IrVVR^obUQ1P zMOOrx3Jyo=DlpwM7W~0vzv=>t8~gV^CXh$9KA3C`{J*7rFhDBdgC*wQXF`UCbi$$k z(fCTef+qVHTX509Ljuz@{C&*b2GThzPM@qL5U#K&-GyGvg#@^Rg+gy+TQc&v6m7hT z;6l-xz*OXjH8nEzji0L;Vl2LstE8|RHG5bdZTBnbN4%<$@5Cde;RaJ@M z4?)sP?`ONXX80ET#tUC93}%LdnJtsq>%F)sBV!4nXhIz$p~JBOsQWhUs5X2@X@so5 zN`H5hHV|Vw2{#Z`d8S$U#EjE{IfWgChfT1paY}uxi6^O0@6Fhc1LzW0;VXp)!%H$- z(p8NPd-s$-s^oRM)rcNrfMXmY_2ED-&O#k67m$44rW}Ns>`PNZXF3`QBU^Zw(J6JF zexB~G8Tc~Quun{Dc`J0ryXiF(3Tp;F!)vodp@&4$^p)U#g4_;JviMa%1&I?|>D~Tf za|z+u2$dV7kF9r)u%0CcBvgdG)EOnX$}m0=SZ-=_lY$reLp_dAm(%lJ(^0m<7M$ZN zB2}vTASp6tTU?CUDzEtSoJ8w~lFRrXA*m~IwngNJc_ouEoQ`L-AC%%e#0UR_YoyX0 z+M5zyiG_LzyWo3>AHGrBzSjWfclfvcPyA+j7MXMN|Gk5bWHm241aMy*G&I&iwNt3n?p=dgk`bXo9K{L~Or@dDu;Q$t$@ zF>#GERH2SR^j4y7Y3sPl_32j14!x6vJaxKR8Vu4V3}NFk66A7wJB?{x23VrjL@EdK z`}0>0cb>%w(AUp|YM!WK22rT-pQ5*jHA^s}3~jU-=>`!hR+;98Yug*PjuzXt_ibLA ztpQiogiqIh+GqO#zZLxc&d*L~C-Ae`#N&fY;$I4G4g^q4Nr}6ID13TzXxj9!@251kkGH({>i7roFa??xAM zv)6e4u%fPR71PHms;kpr96Bgw7M>jyxV^7L^KEl$?h+p+>-)DCE($|6CY05>R?(Ma^<< zXBn-i9Yq!_5H=w<@Ks61fj5(+e(Xu=#|txG+*i#u*ZZ<+V*Q>_0tzBEU4sP z7VYRa&Pwnhfh{euTH%t!O}VoKM0&|?H>VMjKmo;ctW0NgrFosv6xB)^EY(>+;;RDE zp|Kz$&Y=aOebHKs^ZSiuG?eI2@Gv4{3;0CHbIOk}CeMoel%uCAVT|HuaC8|XjG;|A z2t>)0g~`}Jl?c}b!ZbwnZaL<*#_;*QyG9byGjc9<=o;!7?-`zL{fwEG8mC7$|P+pF@i*Z3OB<$;58Zw;S`9Ws7Y#zE`ScPj`U zrqj=SUYSlqW@&SdX?$FeXnJf~PZQ=eOECANZKuO&OomdDVh1Jixtl`goDJxFLvN*Z z4%kE8&IL!_3Y~Q}Or?EiIjIYy2WMpA$dTi49zYCWW>yP2WLyvZqg6r@VV@Ntn?B%kR5B5iURwGj&~t#IE! zwT#0dQ2M`6v<&3Q)5k%?S^p3b*;GkIvcb(Is3Q@a((Od>bjX~XQiNs;wHB}xIsd>p zQRE^ounzB@+?M+oucMbm9#%I(|K3u%&s*7$nja~~Wr}nV_~)pc$;ivvavztRGX%%U zEf0t=|J%%crOK_|0e9s0i4a;zQv^Z+pZc_c=Y@j(Uj@WW0fd;Xj}(})xC`!q zB~A<1#Bt>?i~U$!>6JbSuE-70I7s*xpkd;QdUrlFOkC-goH1y~1JL-2ncKt_^-e+K z=5e^PNO+DIB%A{WKklUY$0)&+l%vF42{YkXtaoxl@7^I0Onj`>yYqWzj`eZL8S9-q z(7Rumxy`Xw?-ItkcFb6R5fhzw4>Jb-B1HG&jCE`g|B&^GNcyUW({$mC3iy>{o6BVu zzr~ob$RWIo>FBp;s=0St59wSC%8CA1R?Bi(1w{$h;z&EA1tF1x^)x zMoqkct7!NNGFI?CYX+HTNOftPT@j-|O-RzL&gRrl9I$=d&i-Q>$Z#fhHit&8GCM2% zUTt+&PBHx{@oq*tyV~lk1jtw=Yunh)t|Rm9@y@POovn`-Af3IPjO(Pc8D!27Fei5Q zAq;Y*v-Oh(rpO}laYprj-O;+yj&86zx`B>%p`{t^=!S%j)}7zcjdU~+@90L=QJlH0 z0;Hn>I=WFhT1ZC=$9MF{VyPh=)doH(G#iFnf)`9X-Kp42Fm#`o)%C((ap@EO3T|iI zverMAzd{F~@b^MJDcqLZD$|N(xh+=&chO71-iOt#@jN<0)lseOza-D*Y%Or>Y!I^+ITtur}W&#xk^#4&>Ck z2i_98_kSObJEgY@jt_HZ!BK9Fue=(EW49!V!SObK>#^EUiIuE2}nJp#>#)jI{y zs?ppEpk_MV%q3t&7IVmU`gxSH4?WImhAg9F(`N+27ikZCj~4>vNwE_Ya@2~apeGF; z1@ypgND8bk(jKZ;nY;}NnM4Z}&ot1^Qyid^2fi+3_T$XJ@pw6w?@wSRX2}|QCCewp zW{q5@7E|K|wF|!kT#6nEegoO3`PU`u6A=5`nhA9 z9WZJ8Nv>H;$iQDn&Ly`2H=&wq*m&C z6eQF;3xcZu1!|2qSLz|j8H1xd0LKYtZZRr(AXmKujy%ZHCsr%9KnXDBVY!kgmMd5N zcbe_x%S51LaCVs%uneGOMzEWu1BcVTqrMR*h-+e z-qVLjkwx~z#k`A*^;4*Iv01DAuwHUhtduUnN(nLCyrZ^&8)s)zh7;!WZZaq_KgEg)p!NI~uW z##3IacXzrw|29c-MI8U_v|4&fLPJ~gbkcY^Q2IU}JF z%A7~d1oB#?a>27$Gf&XC<8&mpODgDo~w3Rt&7c#~4_^w252RboKtlbKPka0ZrP2>1$8Uh@E==PV)VIIt38O^rKHmA3R7pBG7& zjQ!sj`#3}&C7LzG{YHx0A?F$WLRB4+AlGBCd7%&u1lS_n$`p?9Al^b^YK{phM!_}D zS~C*qCl+urTXBwR|5tOs#^UP0wNg5eXPBs4#X|ifadvUM5Vvwyyr}KBOZIA!_GWV= zf_?*2N>ro;u$Qvi5#1MRs8o^gV5h{oN#jI-9NLm?Yo4To`NU%pr(NLu+*C-# z1=zu`$+7gE2;qtl)tgRhNQos`!`qTY+DQLor;$wvp!^>3r=;RApv6iz{z!lWWhG7` zCDzVCN=;aUf$3Okb0ESLZ9A@sHvM`#=G0}m;PfoL(J^I^8!@oWLi;nbB^AdF+vZDA zILs}{bu|@e4^0p|?=m-!vo>Eo@V=0pvP|ZbOMB?AJTy(@qf9aF{#SV%ozgPNnbtH~ zwsAFx#R|eTvwOTB4Sz=1(JYplFfzY3bggoi*;AG!eIbhXCChTd z(-O9-hj~paWFbxv6XcMMv&&*_F!mpjMN4a&k2X{-T#|rnbc#3-YWbuG_8>0+6mQ#d z^Q4FzijbSgvK-?+tBk(@0ab>4AZZy=vpj(c0KujzE`Uo@#Yn73#SX{~)5dF+@<^-{ zd5>TTRJPV}vZa9}CfWWgQ}@4wYzx{5>HZVKJ87e&h}0BxlAx$Sn_QGb1UyROle?Nn zR6c3uMAaq};KF6hIRG}9R2uqhtt22V#m3bvrV3?9RCeb=Em=0Ltz>FldAFK z(7m&D$4+#o2%ciARe0kJ9FnW_=j~~#trnGs zy94UQk!u&%-Wz&-Ox@&vsk6&vuNTw!mlm48IP3f9LnTg+AN=@VjLZagO*o z7vo*U?_ZYtY)hArcB#+y_%fd@vx2hueYujn{9?8XauxdppLtkChL}kAt{LEP9h;m} zQ4~L?VquCEZJG0e7r6CgIeN9v)bIl zrfc^APFVP%47Dx=G zd1D_J#~;D}7gqReZd#ti??LV_<9ZFhzjA*)S6foD-H|eC_?9|)Yu&|8Ry0S2Fgbcv z9md)B)B%a*I{`&nFe7w#t}T!fxqDXh2EB-dUT??^FQ0|hEnmV$;V6RI5;dl#PMx(A zdi#K}2@cc>7-G6n{y~TT3jQ1ufcRihrPzHC-=L|dtb(CoQ@Gf?tTHdF%?qYznCZ*W zCMm|n6nv_zfM{ZROtht19?uSpm>KW8R zB6(DH7UC5UyyTQW%Nw{Ip8_G^_`L^K5o3vwd0 z6D*sdoQNhXTYWoWEDso$kdDJm*w1)VLdWe|=^1i`x^q-U&tO9v5$Id*xzUFAYH>vv zEB>mOr_brW1p=%3e-Y1MeiqzEOShtFN^qo<;h}V{dqp?Y&Zlj+~C&N zobbH2375(e(kzwOASS4mCV;9m2C8`kcmohq6(BhM%7mCq&dHRmwC7VT@Ju3Hj#;yz z&Qn)#@x0gYFX9g00!VJumsN-l_rmOOO$;j3X@N5EOZq77KGo?BbXl7CJ>~|T5b3{y zg`A=j)u$+1%BWdofiScc^BNp{R|{ZkR*#xFsR^a<2mAdO6y^xB7oOU&DDB8`JI=pb zhXkCPoSO>^M`HGn#lUk8@SLn?&QZvLMb(fo6YYRM)Z_MSayGoAj*}neEECV*rkfK` z&7T0j8)ESLltMKkv73NP2XN{r^oV0AFY@bU4;>%5D9kJ)Fjo~SNkOfGIj zy1#^WOjNi|m?dx+EUuQ&im@YcwxF9W9GTnfZq6@!QTNX}Rg$G3otdQubOJn(%cvqz znFJ$gb`y<+awUhW8Dn^_o;j2Nt^-D%B=t1An%1P%{fi4h_%>Ktew)=MqK3tUWquo5l6Y*pJn%F+WpzJ zoyU`v*NTY&YWxWWh-p=!5IznOvTeR5vMClHRw0#UAr(iV8DF9<34LBBBmmE);ii}5 zajlnv9SH?n2xgU!6AyExN@Cu`pgNs`3P)6Zi%09zCm|*%z_ZtfWwG&QtT1?x+o>bK?_qww;Md0QX?|jzr!4ctbnk=y2;fZnL(PkA9F2Ne zs{jVp`YM<%c^7<7;#mU!ch)D^<2SEjNiu_!>3?KNE6`iA$ut}MXIf^d!Y1RZ(PwI*Kol;G>EuU=8=2 zZupT-2=iOARa1iZ($;YZsoE88*5;;r4egF?<8vaSE;gi+W$cD@sPa(IDUZBg_m%?1oHZ!=UUkFvBv!PR8b5d-E z8{I76x9D4kcS1D*dojh$SH;Cxl}~}b8>O_oII9x4R61@!LZZc<-~aa-ey$cbCxdEs zY4-MMGOof|-Ck)IN zS4oNI(z6VFAdUgEMBBA61>5^U`*xf(4&jG$2y$k(bLdSnFmuiIXK&TyWq#M8Ayffho5e_roHWUw zDS>dUKiZEuKCu`8qZN_)?HuFByCE^pIQWmLVd8Ourv0#r|BBP_3hd6*@T@}yT((ZR ziQpo#qcWxS_0#Q@DLcw;oR{1%d0tB6L|jT*Umwb~r*~PKLDWZLWs<`Y)f}(aC(;>X zK3iMs*d5D1Umd;MdL~udF7DPl{DCJ$P1jzM%RvHV^U0JYVbTb3Dt$vXRBzj}?lyMf zm~P55k{bejF_khg2+uKH>;wpYg5~C5dt-e0w;kb%5OhausG(9ke&Md0pV5ou1|mo2Dp%8gxNLrJPwj(7`h zuy=(08_cKC@k7Zf9H+2f!6Ei*PJ$0>av-~eVPy5c2kz4m430dplUFL-v$0tjbqc>& z%NX6z)$nP?=u@10$#LtsLs*}x!!Px+5>Gc0nL(Vo#T~^B`v_Kex&wbD2x7RbgaMB% z^YV;bLQf*?5YYk%A6-t!&c<>!_j0JfSc*aacVD(W${En7KbHx9jkM^SHtJ^|>HJ&D z=@Ej|r)WPv9Zh*keW-HUt6X|le)rnQ4o1Dz(^;!6>E(FJMXvvkws(P#vbY-mce9&h zfrVWlLe!|KM2iNM7E~}n6GAS4z+yC!Dxj^>ZE9Ofb^&Whf}04-<5u2Qt+uwceQn>i zZ(n<}7O_=AEa6fUF0JDIQZExjH7JFEl>EPE=6QBEAyPlTPyf+n_j#UqX3m^BbLPyM zbBR~`%qpe%o%Ro?5Scg;x*>6Gm6buyMjH8Ums|kY2r!YeYy*Vqu`=Rr^2hI%d(rnG z;8@cQdWA(+)d9A~OGmjEJpc=b4-$iFYh|%#YvtuGHG+j5BqVA}m^1zA7#k0Ld6T~U zhq+93Tlj zGRBN2^3M>!|5MB>YOa+4XmfNwuIE>Y>5=XQIzqpC)jV=;1XU+D^p$Fv2!X9ACe#J0 zC{KHmY8gN6$UF z&v4}#C@&}J6$c)MgoSoStS>vTRw5+e2jTq^;%FIBM%YylN=^Msa8MT9S~kN8O=a!u zDAUBFK7|w&yB!J6%VWt!YEvCEbt{iRKofLKd>H~F%sW=+PSlh@dl_mrqF}sYmh`*K z?`G&|GwV*#!hArz2~HE*_-lU6aN3S$SvzL7b)V(g@xbBZ zMcahu9B_CJQP-QUa78EL0==oZt-s&1&15=t5|GyV;|l~U?GC+@kD2Zl_O3ZDc}g3z zP^4r>yY;{53@F(>44yy)(!)&=g3WtseP7zV4U%_Qn&D^*{P9|!C4T4KFHnum+-1EG zl?ZXKAwP!sayMHh_sa1S_&PbBw;3X4NV$zxbw*5ON5(twb*VU1VBe1RQbcQP*3X}@ z_qCrlG0J4d?NT>WhFkiPeLtd-)ny@#cB#^2Jz2UQrzv@MPV!lHv{z#rw(f9v;C5L% z9%$>%Jbc8k_$0ck{hn&hdOx1U3;*07luUCb0*<#pz15WIdTFE&n-*5=mlq%8z|X{o z(XnkNaOuRh*|y>o^^LD*yNH!KLspa(zQem@IYP_kh_MTGc+x9ssz7tB@07sWwTulC z?9^Md1e?bfTLv31RTI#QWa6~7bjczK+>oIbQ!US*6ehO!?fDPHI^Bnla}?b6My3aM zvqkNxm#yJd6H0Ldbl$gyt6!asOtT<)p4Q8Yb0&Py_I9R+gu(ha;fVWpYQV7%;yFBT4dLO+ew!<)3|fn{$JYvUkC4a0hNtDaKRdab<&Bs zBi2ag$boM*wt{(0S@5@Ut=m_QS)M(Eo;I%>#*NIPGT(|DwSVbjOaZHR%J$mC67rF& z?>wd1D)oJq#B#%<{zH{0c(N={QFbJsfSSBK8AMFk?&-DPxY>Cl(#c|#Q+TTcHf}qf zSt6Lw%s70LIrqs?N4}RfL7)$lytvvrs?K6Gtd$b+v}kMnX_DH3oD$++>DdvR?ut$? zL2*{Jb@_)5&I`BheS>JYr$OjC`$VkG=jn7x<`->gFrf_>wrR&7xu)m5>Kc;EUGt{id9$(Bs-lB9 zwy!=GzowV41UQp!DcVhNx;BCoue}cHvbGiOER~D%xriO{1@3qYXe1W(>)C;cGeXRU zK<%Nx#P}ao^J~0t*=52n@ntp$*-N%nBr?2DR z2dA$Bh06k;-xrwJ!Pkyuf#ZMHuPCmbUlv&LN?_v7Wq}uaxOx5bjmrYBZsXUi=@|0% zbo1-V>0GD3{q(^1{%+prdA;bBz@4|saIHQ@8*c?BQm}rXkKeD^zp;8a{@SuYg?Vigj;^lrZM=f9v?sZxohz4)w7S{>#MS522Obq z-_u$NGpwDxkGH*(xq&TT?EQRC$9$|DT#=h&t8&LiYpoFEOEB+-In10r5%i%eOP2fA z90ljiD=*>BX9=`7W%~@-%Pb$+rpRLD(--w0!g_o`ytc17MriGMef{1wntHImkaTyR zU1j3_T7D2^TdR1~w!25$u%mWZy2Kr{Qlg7qMCcDIhy>+IRJw%;23A%`Fw73gYd6hay=d)Bzm61YZ(Q zUiKfm0gWj?27yv?c&w|)CINwt!dB(R%5j$l)=bix*RhfIsqfLM1~f+xC6dp0wCWSP`*WCc1eKhmnnkl z_0n}qvafR>3OB$_u2PSDhvDC$J}o^lfAmKJInMKmRq_~h1{i~#q+~du50U2!Y{e(+ zGe6dpLn;a%NANk(;Z6jEo>3{*ucc%n?26@5xsMpwBSHviH)^rTi=epa)~|CK%?{Yw zNo0qK9NkY0sn7q&W}<;s>56`_{%f46=U7B^lz}s*32dSXDC_sMX$m}@z=&?^IrJU0 z@RS&TVZp;XDeqOtxdEk%K3LvKb=J-jO%Nux8v=3xwrN+vHPxjT7#!;eg2BYK97e3F z;Ltu#f~jVroAva@8v6*kug?!2V3TXCIs!D7FM)b4$&d>0hpr&dhAZ}7KKql~{sL#` zT)%M~u;fWe>Jq)ob~F==s7=QvW>5LQbmyHcG+Tez->=qCPUvmT{`?F4^G)L<&Zv~WL1a~)4I=U+pUWBt;n}72^F#h@DDe2{DDCw41MX^zZ%Vd9JA zgn3Zp3{Hx44^j2vM%rZ$@4M&g;f2=_#kNNB6Um_emAh;o@-+o@=pw9^PX3YDewIkh zwn$v550ykZ3AFsTEPj|lU#fkth;9&u(#%Xej#Kw=4uAel_LB1p)TV@BqS9Z?)E zC?<`=WUsg{b~~!(;R1M|HH&J|0bNk+t+{r}_-z3oY4njkqWQiZ)AtqJUM;v+mabikfcml`Vbs7wDU%d=jUu4S|9lz;>5 z2`kwd=4#39-1Rj&dfu56^4`x=M@Lh1%Y8CnxCOHr3 zpXL121f%&Y%LVZww#v?CN35+swu_^QmE)FY7A^4AlbFp9AHr68sYg}MX3Aa|Qer33wnROF{C|N#(VoxZW8rT3+KTn$w{>13zhy%lP)X_lf zlT4{!;xUU3oQ(2R|E%>YibS>_v8@Cs;n2$;drlGo*!CQq1gvpL_EboA-og4YoU3Bv z_qv$&iQRl#PcdSPA-ma-9T!y-$i12ADRpS~R-xThL({Ha$HS~i0J0c()-bC5SFrcW zB-aIwbPpePdk%FA2jMJiO2646?!*E7A+4J9O<(2XoNp^R<^Y`AadTU$MX$UST}13T zjJqAVkq#B^IK7=7V#0pJy<)D2Tw92#^J?Ii``o*GszW?dv(hRVX+;kbq>A*Ii~ZOT zkReB-i5ye9Cg$=Vf%S-c4q^Ge z;;e*s+-_xU^K6ebba9*T&^;OKX3!GE`rIpDx3)@jAfc|EvhT z+tHDMwJ*T|`wQ-!+yJSUlSw6rlsER893A_oP+y%cSN+kP{-`7rmLNwZGqTCeI^fof zKL~LL2i^Uj$LzZzRbAtsP#&CMSIyOk^5BTn)s*t!loJ}Nb!vq^iB@#@dE9>v?+Y!o z;h2_utgE+!GHKAM|M0HEgfKFJjFxSvzP;3SBcHGFxr5I{IxL_2`TYo=Kl0hZXCI&U z_>AOP9v^4ERa-B?EJVb8+Ix-lWpDhJ06O@*8bdJ_1e{? z*hyd8#+X=tzYfjF^{JnWQa_hCKh=FJi00%JUeab%JLSDE^FIz^KB6tXytr5NIs})M zn3z(l?Z;$ayozGmZ2Y-fhPjKY$qdYkh$5vOQ6hBGqVtvB`YfnXvfUOoZX||fn zmxyW-5OIVx-^I|HS5>ftHaXff#v3d^$Lhzc(<|VGe2H*E=7kU}IEPQ3^1vG*Cy159j)h(hs)Z3clU{>m!Y*g^oGNE= z@bi*~#YP~|(o8{+PpxTY^Ae#syXO>&ioWj@T{N;t7Zb~TY6wi+hwex68xTPm8gZ=m zQ*FxXgJLOXdZjNKkZ9$X>XoKj)-A-kK&vn{D$DA*lkVgt%CbVtMno-@d6o!~PJATJ zQEM6*JH})O-!4~%TmCZ8aeXZP66%QH(g)Ocew68&LLL-InvYx%9bRD@!u5<|vxRn{`AA`)e5=*leEH-+ z>!l3k`U-dPs)(=n+CZ!ELP&H0MbA4VMmNm_ zBUPMv3~xR%IhxsD-q$m^GS+`)(|Lg>?dKUpSlqm;Co8s%L(E!qE}K6LyuBHU$Nlu$ zZ9VRpI%TVSPDRhR*%Ej<0xdtG1^SmLzE^q_pS(V+_|}NGI264BI4h=XFTNl;%r*?{ z8CG1#HiKNr`_p=!5xIH&IJ5o*p4^h~$Jf`8ze!bK5EXcAivc@>^PDzV)9OA~U{;$4 zOC}JiZU3?ZwIjs?vDQp;e}S6uP$m;xG1Bl68C82;E@e~a{I(gAUZ4H3)xK3Ch*<}s zBzE?xaWHvkvD`-hZ{3!Bk4dy0ld0nP#Q<0!^0*_6Lb>+wUzZxBpJk6NW zZ=$Wv6w!Ako3cGA~seKpv9^HKOf~c?bNg>Lfky8#OO5M#z zA?`M7+xpQQSv4P>9KC6MsZh7K_}b{A^$Rm%Z5c@-2nJgA@+MX=XfRjzGEbown?44R zZQ$XLybp*nuW#%N>leC9Q#C}N>HZ#7ByVIGek6u9t9zGi2t2tb_U>e+@|ut6pnv(4 zz}jC@e2v~+EI-HG4XhOn!EyqG3lair*K?Jq$R>2t-A(+IUGsC+hk=Km&1icg!*le3 zv9AD++tZ&0&6Gn9*g=BW^{k_PjTGrsl6=TFHxPfQrIAdO&)9saL#%n@;SVfOf^ST6(b9ooq?XjSJ)w9ZApAwe7+acAj89%F6|VS z^e9)tZYgVW3s4%`&k`FVae6Y;pG<`y&6)NjA40{yMT0h;+Q#V6G zNo1Z;qt}g{YV}CrYf)+e?ovL16nTi8yFSWq*Xw&LVRASa1w3k^hNUSXvq;geis{!K#V z6ukCsI>dS-`Ez(5JzhcJ$x?T0^NX>*`GK`!GQp~T*E+qbhxuZ`&E2$*zQ-CLu|+ zHyrTzWREm7KB~US@Cz=wPzENh>Q$1@r@Kp#HK-%~lOcntVWr97H$l+2QvAZvG5JG1 zUy;)Kh$Fr4mT%3GW~!82~VN9K!**0=3`x8Mpw{P~*`EBedU zkr!jf%6Cyd7SPn>LwgF_GxiMMUA<1i+fL=p>`nV=9SfB%l|SMW4)_-nb_dCC0c`mM zrObfDRMYF}1lIa%5oJ)3)cSRKU~-prsk_&s3WbtG;a*KtPc=KKH2-Fynz`qNxOJu%zpRq@@OVv0$4o!vT}aeJ6Y^{Id0|Dt^l8iI5rifY z^2O&D#8!D-(J{cAi-}vOnvtWG)jj80KCLCnh~pN*+4VSF0IV_MSGUr!xBu-nXq9@S zzf3cyboA|^x?$=7i}fIV`!E>;4%tdNN;u4rj%ib#j*_Y7%IIrLCYvkmI?+)ANK$f| z`N}n4CFVhqeb3fmF6_~Gy=BrA+1}X4GEr{vo5lkel8V=<%LTWm2 zqt+B{{Zwv%Y30>X0W8|)+(yif! zN8WvoTc8|89Sm#-7qO?O*+_)GgtBhSpK^%vy|b)EsM1IT=$l@3jGVl_)tMYYMgkRN z=qx(i@U9l6kcGS}EN_eiCYysCu{%>ke^Vd%Vh@M`i6m*L@b#}q<}W)PO_x{&&Su4o zkCOal6_A$M3Xls$ZwcgmQ9W8)*dz)uF=xIaCb?y@`$(%&s8>QVEJ6pwT)!$2>PKXY zkAvZhrglF5mHm-o_5krL9Div^l!liVy&9MOp#!z&vEIea-k@i~@Hl8^f*v?u(na+fMBFZRq(OKzNm_D6Bce2Eh~nkl2Qq9yqa zkJB*L1=kfFSzTzKRbR34BEWN?OL!Bys(A-Psym>03LwTC^Nmcde$PG3z19EmJ%C=J z{Uc9a%)5!TL0I1gD|F0uin?1EbiC@Ah^tP0hT4 z?U?!w8;ZKon|MDM z@7uZX2xzoB<7a#~yks+AXTEW=Q7r}(2T{3jl(|a0F;L&`!t|o;-Arrgw3$=(6>V8Q z!CHNg{T%etuaA`rKY(7^4ZS>H^g;bwV!lE4^2%Ixt3;-qu+u7Dm+-D5PdlN_TN(s( z*~?dE7j27v5iPVtqCH@Ue|V8EN^p4*&AFk8KhW|LZ>%4FnUBOg$Nv>*c}6bhxG$@6 zN6%#v1X}*6Z)99nl@UEfXO;e6eZzBE6;XYE$Zwjnn*1nd)?3%?H=)g^*W@+iui-Sg z|B9wu0ve&86QL36sK8%grvaD#V^+KpA2La|K$+**nXocgVrji@K_-B2t@M(wzJyq_ zjV1A=J{V4QfAk#U$lJ$ydgVIHHFvunk&- zde+Y_Za&~?*%p0kU1etSsZC`zeE?ECM>c@5zKJWz^;vF|33g4fzW3{EtlMmW1@>ub zg223>7-z+DIX@OfWA3`SnOn=eIo5)b_=xz@l6bvO5^ims)-hZA*Ksm|$ zli~Z9NeZlsSESAZ;jb@j{9V_lE%y>4Fr^!eEOiw2~Bg)dP~+L%!PC8XYw6rI?62X!TqPfYTgluC}0 zQj`hheYJ_(f;0Mgt$u8*G3X-qX!J^_hMv#Jt*zylhE8+tIki$H70YvUi_uf{HmoL=4=Ezkw` zpHOfZq0gUH1<)NJ(k)!cNGvZ(*wzC0icNL5-pjcupTG0j#OHlJt`m<Zec09LQRm8_zKI^$Vt2wN=%Y|2N8w3ZjB#q9}T- zK{>>)>qq$4{wBJMWqz$eKWL-;U}~@ou|N$|P*FAFF*u7=L$Fd-vVK;dSCBkzXe6gf zWuBx|Wzp)shDRL8(&#A#AHf&AQ~DwM+wpvaE3H0eH+d`trWx0^cQT|zG#8;D2dFg3 z)=x`Ot&ZeiSC(&Ah7X=yU)m%v^&!39O#Vn~ZZT4>KcLFw09ALs*qW6MMSSd=sZy8% z9klCDL#wGj*5QwR<(NDA0~@Z*bdnrV(n%TalMDxE#tg@)wmdYKTt=4vi284~-XQc? z!#@TfRK{EE-Na#3ZWDCadiu?^_(ruZk<&y!i63YJ~XQ!FqjePP7!Wv z79peUGQq(^V9HGVw`JB>W}!bD;nXu^Tk9*cKS3Gazb!+Quam;Vb9OlbIh4cE0Np21 z@?>GbNq(odIXZr^>~}Un2>Q-K=SLMHgToUYd?OO$_)D#VENZLshO2%z+m)(R9)j}h zY6lG?hC;cNa790B2IYhjs41N4v%<5G4o|G!`){lNPn7We+g46q0zEMYMC_6wFIak# z4E=+-tzZq_ovC!BHR6FK>ph{UIS~?0dgMvjP(0xqU5z|`&lE9{W*lc8=4(MP?j3~$ zZTZI$Kc)Fb?)aRW)*M&7*|38tWp7IvUztgIUq#JWH;LJg*x`z0)3Ob= z;m@r@+a+lm4nHz)R^WfhkFI@b25xwD{T~pgM-upLiK$FXK~x5T0*R7$&jx`;f};?) z5Q}2IB<{pz5;F)9{n0hjO=Gq)Ck?EbVzeU0QXc~pMp{X6$Ue`&B$y~?87vbd?pd9K zzooTAVxs$L2g`U#?jUJxF%ksO}M=ct~dFCunlC(Ith9yt>1bQr}#Zke};eTNx(X=w^+`1tN?uJR; zOyqxogNQF0=o-MJA{*$cK|rSfrVfpNA|Osrf}BDwzmog`!j!XdO!hv&Oa$jo^(p8w zh7MvgyPMv zP2zYH8aRDCmgYR{)^5Us;Hu^LQmr`k_0Cu9Ej<1i}bSxEclvRW>0 zN?y+5@@9ak=JO06{g>g&kTd-BKhs|^F^8DwF9|EBSzFON`n6*--s)LJ#~T7YGZRy< z*yyDeRI69^qP;<1JY~<}sK032%8LWP!mev;;8*2-YbS?lezd<=Q{P0i#m_W=3_P}2{hd(v@vCKZ4Dl2t$P-7jw(`-4$5bS|Vn^BvjPI>1&$-DsrLd^>-@I4k(f=>`|ZWwB&S7M0%E(QH7XzxL0b8 zzv%j<)0F@3KU%0{1k{9N6dol7S-fSgBZ7a@NgKt@XQ~d?j_{7vU$s1YmqIz z%{OEoLp=APSFq;XgywVRO;*nL!!S}9sQUw5jHARdcbQQ^*yTo{fLK?N75ivh!>&Qo zAaTblOiEcC`#dYpWS2EUxN${s|K#xf0NKA{s`~jmdLArkUvt!req#05tHK-XN8fZF zS>AhZ8d>dHbM#YEVst3^@-0pYyPty3{UwHx9VLv7gqB$%syP^E&O#J!iFunD{qWFw<%&7W!_ z13imti~+zIPvNA{g4H+`%w0-EZ!}h7Rp3p`AuFRlep=wMx!&0Jk~ooB(Oj)4iK!qe z7hzGI>hRzC`;C!g5MmM&$1e5lJ(?wHc6WY zuQS*2cS&7odN;}@t9BaMVLzLw=#OVW%>iq{G-CG!9t)NbjBMc!5DhZ#vCg_uJU4ArBP?BkRQ!!7>yXKKo- z%V&6Hh;zlRDtVxCwvMe;$mxljWwEk24v7>qo{V?CjCUFrS^U*OU55S^BBx9rAFXGE zYf=MDpvGxSQX{OFt@!w*`XuIK#(IJoYl7`~XFK|Kv)nzldx`xn!!AD)Gc%+n)?Bk} zCx^kF4}m8UE`ZAlh)o?S`9=qxoayE}wM<(}i`nIpW(!a?m>4YrAIj2kKgIkcKQHvb~}=CZ9<^*FB`JR8KRf(iD^WtmtTbK5AJ1-@c2Q! z95kmckx7fO#fd#Tm7a;s{gBg^a2Yw1 zxdTR3P7~wfyO{x)F-XUAPUv``Wt+6l+(h}L6~^g9D-{GD+f5zkQ%9`tLck2P3cLe= zT{sZf9qc0p49-@s`@+E^GbE%>3yL(P`6oacIU6WR1spkTXb5#~58&0**ZmD@8UW)H z1E}wof9Ei$&mm9>k$!>;0Efx zeY&h9Uci{)NwG=MlIKL;nFQby3)^Fx-H{3~nj1SlHaZ&7A>`dS0nFL6W+`bqM!Pni z&7DEhW)6d&nncB1g{9P{eTJ?Ixsl{1DS6F=c;vK5QWn?RGfSqMB!ZixdB~?79&)`5 z;Fu&2(f&mAO9n9`zFen{8!m=7>+;7<~-PASGBvh;T_058OI6C%w#>o*l_Jyf=BinHs%DT(!~$i=T%7%Mp{Xe+I}e zd=L#QTmp76S3ANCW)B?$+2OUs-5T8S;J@#<%?^XP#R{r>8(mi_l`a zsMYpp2DbDLl76x!=u%eMp%BhVQku{RAKjbea3}I&qUvfs92uA7aKd~!${*kTJ>D~% zO@jEPV+@bFL2XDN-XW%;8ChvVl6DW#Mp3ej&z!6Vp$(~F$fXh@h>ypj;A~hPIgK*4YJEU11SJ)nwi{6RNu8m!+=b|BFuu-!4z`&+YN>|9|u^!=A797QyCC{vmkN zZU`%lHh<3!XE4R+UFj#1ScZ_rWEeyi8*&&9-62N*EdJ5+Vn_QUOTqi2vc*brZhpa$ zFHecPJ=4uQXx3s|c4;dq5mcAPcI3z2tzBYm8MG+a^7B`T;iL57c?qsr__?@O|3J(IT0RnnklYS-e<+t->Q#6f&g>$?+N6$y=tcFSxWOhghhSd3;Q3@L*Cp5<7WF-ypYd=8J~J_M7a{Gp7(a}*w{aSm2motf1}HV})FPmuMT8dm`UT)V0WCzG zOGnEgE@MYm+xV2-A}^jl)QhhUeDOKCOyV3;JzK7l_!be36)HadyehA_q-x^)SY(I* zCdeoN2eTbyPzCrHqL#{H7_GU#R9A0mPw}Zuz^|h4q7>;D8`6JBo?JKJNtJmb>8@1i zfG0PYC%5n!6CEH<5zG45Am~Xd1?KY z-QAcQzbod(P5l+?D&0l9SH62_x0Hrf@-wyC7T%vebtvF=mShJ_9cY7e%MoqB1kA-%Hw+v$&EGH2;WFhRY z@Jc=(6ogIxa{`xdAOP6M^cTB~1Lzh-en`c4u_Q5M?x8ip&~Tj)n-*&cW@kqe-a8UG zrL;5Deo@oUSOfO_sp?WdHaz6^04oo=b}H+ykf~R;`O* z&hREZ+~BRh`$W7sa!wLt;0;IzQh2+>;0?htg|`y~OGMm&@TC;a;^T@Ce*-NSuzj-5 z6rozIq5BpG)_wy{j37B_lNKcN_`)JnNNkAB%q{Zvm}D1<>4I=m8UBp;H+&+JWY`;- zA-j;P^?P;~SU!g8g1vmCcj0+7d^`IAIDTfV@Akmj&%^8h`Dp|4U3@)}Ewr27=4}Je z79ZDL#!FB5DAx1b6LRj?v+D_r>0LeBpTJnj)w4yXI_P=g2@G*uJ&!WbUu7T5!OcE( zGe6q?PAnl*$FUOc@t*s5`fC&}-Ft=WcB%r%Ojp(|CMITp*rpBcU7CDo_fBL`eva$@ zDes94Ilvd0x&nS?(}T~yOKpxnV{~J;L?1d7v-!eVrk9Vh7B+{1fbUL#)%i~}$ zej@0$?v=%19O&5#0E6*)X$qg%?|jrB`I3%Y__HC3R-_dzRrl?svR&}6POvDGYz&94 zp_%G(#eF$t;w&ZZ9v~BTsvm(zb-n$j;YSY|ezcY+T4dj}&fHibH?-7f-?*6@8;(3) z>Ke{WseG)|^}CIw|NqMJ8Ot_Q(O&cq@D$oR%I8!3p2+7SK9}&B!RJeSX7QQJXB(gS z0@ujopL^s;{y*_ALvHDRPJDLqJNhM$mqM9#!7RSBNBV{hA30*A-{I$C5`;UaWGG%s=5E*8paV% z^t<*r+}S8Q=`#(NatB&|Cu`G5mfxI#%Wt#J!u4-?N}%Og*{P%tVE0k(XwMu+IPO$$ zumWf#X&%r5^1#qWnS^#3a1v;32E>imflueflMcyOyUYk$ottLxj`{(d04P3-)>N`#)N>_5xC#vM^R3#dhS2>mZP*>9Ui7I*d znPgWl6G%onmAtJhxy-2q&R(rv(+bl8G@zG~b>ta6IYw8cnjzGjOa1gsjnOkV$rZzN zAJ>A#!}~IGQ#f{3?~JH_qZD+2k!ZSa0;qkxQItE*vyWpzY5I>7mq#OVcn~>S6S6+C zhIN|wcdK9Lk_`o{`jRXX#RhO{$&^!L2Z(~y?-VW|tz5ZEa!RW`K5hW0 zLr9Erav>5UCl@JDt#%QtoOfl**}gPB&QP;i86P!ExAYw(?stXgXt^(iv@MiQZM&>5`A@2JqX0;45eNunlK zox%y9n0rfnQ3+Xf1fLZ#1c+nkm7~71i&4Z#K=M{-uj^8t$vJ-Np#SNgQsf#u$`8Mw z)}6|4)-Ye9rdK`jdwfX6N~?nKv>2TnD(MTzd4nr(@8(4&o~hV}=4oeY?J2dhrdE|x zg|;|guR|oI*DyEABzY;X)w!$HcP8q65=`sLx{OUN;+C>g&1Aa=nQ`;dI?txN%*_ju zH_yhtVY#n9$$iBRQQ^UI?OkLA3A{hnlxSO9voq@Y0=5T|rs3Wj; zwcI(-aAi|=QQwLR{HX|F8GD6vD*|=s96CRcF-!r!KF>}m3A+tV++pZQX)u4Kv8IRWTa$(_eZp~&sJjB2&_cGlvH z{aa?c9JIDI98aA`=L{V0YsQ~!y#ME1JwgM=`zn-wCye)uWsi-p;ofrC&_Yh%Q2b z)KrRf8mHm))1feE%M^%HfFYbD9|7*jr{x71!d%@rFE(^F=@*xGK%nv#rW!Qhik10; z)oPo5!Nl=)MpF+PmF3A%?toz%&OoL#NRB)_RS&w@)RFt6R^59FFs#z_?6XR|cD$it z(m_3Oy+CKejEFckt3Y&#(?FqL+bZeQ9YJ+#@{;#4Ig>`E9-nOoB~5q?yHr%INi&K!pfeb~{&UJsyU z*xrvr8+qGXw;Mw44E%62d2JvRc`H|aH~G$pB;`avd5!ATBPrgTXFF`FQ+@BKjgQF4 zx_{NE2cf+*V(e6No$3ND_luaBVm@)XydE0sBuo-fnrsG{)@pTijkY=9DTdald!c6 zhO7+Dr=vHW&ge9p61aPXyvpE^8++o4VclP}FVWpknvS+yPC@VfFJ6LSVG$WvD;}8B z(E>I!HF;60-i9&BWLM)ExRWz4Wl-h{@0DO3PY0!I49+#2McyS`y2*!Q;2po>m#1s& z-m4Z$@w|Lpd=fAeaJQYHYH-gQ)ly*YGx4MvdLG-$p=Q&c8kXhp7 z5O<>C`lf8|OmnTM2ANYq#$>Z!OttjevxaWzw81U8V|!giAg-ZZPx5KYpAc;d)EgW_ z4fFj=Q&zxkOoM|)$T3VB`fG+^GX+F!yjyJ#S)a*Z8sk@OjR4VphQKZMGvK8r$jI4%63s=_*R4Xy zKu9F#KD#f)IBnh18Gbq$q-^9#bKtp6<<(c|xe>95)a^;RS?nB!FYlk){z1 zckw8<`*!B0{3z;;E-X3{oo4{KEFF+%0_lLDTJ?~(NQ3x0o*0SjLIY{fc?nj(h3a!a z2V~~rj63wjMlkJ2_SjO_*7Q$p?Q5Iu3Rgi>)oT180@|s560r%$Szn0nh;2GySt>bj z_ZRwN-9d6+FRTUCx#}<=BVeNAHU!uedoQTQ0AON1e!@j<_2VS?LU1^C^;p;jMi1ld zqTS2iC8|G9vI0Sz2qb@XVDu>7B%=Sjpv8|*bDz86G*WF`g~U^ z({?=&-uIi?E=+24({TxjBgRT146D0G0hbt~-FK!YTpJDPCWub|?0BS_;2^%=uNJ%o zF$dLCbEnm-W>T3!_*{eV#xnb%`n0rTE>F$A#-25S7IEwpW+$Vr z%Z%3azg`;i>9ZUWYJx>a8UnD(-W4h9$HJ|rcM-1o8-%MCj$Z$DxOGUTLcWUAx|yoi zQ*TaDU(*E;H&RFaIm|~$7WM%A|1EI5T}EO zkU7H5npS$SuSkg>a$bkf@q*@NY*SR;NC!)^43?tB5*264A(g=sy(2+gf5^{K&`07Y z8yRPBD@=^1#B~~1xR=YZCf4w*cyeg^XI_Br64hq!;+Ekh0>w(d`d@h>8y&c8;;Q2W zMbgiB@?SiWI6`{2WA4`am-ScP65Fy%-80uvgvp4;JtkF`S|XKINs_Hx;++ydb($+O zN>dG$ipjK?uqJ;B8XWo&Pnc@V$?=alDnn?IK|%Z@ZH`>2JXFnt9Hg@HNVUYd*D>75 za1@_r>*){*HR-ZO@RZ22p^z%p#N)3!E&z5aIHgQ(*z#ovqJ(D~#>^If6AnClbwvNU zMfQE$AO{l6mHGnrZl>rx)TX1KNXcN&?`)Xns;`YmgK5D4m~u}7)6cFJApCXxoBkyn z4109G4OCN$UR{2hhUdEiPqljKCnv&l|3G;DQ0L;UJT0RADNlC$)w0t6mY=NV-J9sL zP^i=@_rI%)=+bwaB1xb4@Pm+OjjH;3ibS39(e`CH*SugIAVx>*vzcso)5b^LG(3fh zK+DgdI&`TFQRh{%n8#0sjt8nWI&7?}(+1QeTfzY~oouidn3|lyHt~ODuvgnS`2kyF zMp@ACZM{p*?^$N>9C;W#@0zlmk)J+?ac>iY)*>06`HX!AepfQ~-L-N@6H3`oFEFr! zUbvMzy!jfTfZHM8JlW^A9E2&x`fgf&7NMTBN~n*(An%jaCgH#0@Btzau~c~4domN= zqTR~yWtkG4>bNf*%OYGF++fUL@XY4rB!qX-RRb{n>jAa>AX(cd7_+w)>Y5;7p)Mes z`jOnw+oC(ENXw@%#Tr!zQ?#+4&rhMq@gl~6M4?Lc(T{n5FyhgN48miT+|e^)$51bn zpYXzs+!2yDWF?d++(Z2_TVpU+vysn(J#HEz%{wU{IT$h>w)sf;QMtekp&+oa&5X-m|VUDyyR?@mG-NIHL7BWGm&O^r{hpx_i7;YfW6Nm#X;*m07%=7VH zIN6vN8NdzudooMoRadRqx~6J2U=`wxn4^9m&$qF%=Aq1?wN675JW4F+7Yh4#tv$2A zph=Id4F4pyC#>U@{fHnn>P)VTE1_2-Q2d{Bh&{Qja980@)^AzV^KjoQ+7XC}5-3sC zFL5Y3RTT1Kqroo6C+mM%w+Nm|8v4USJRM9!l7(&HwlEt!9ZckSxgU;s z$6j8xrGm8O-(LSj?Vtw*zfN^(rXvEJs4J{dUuL6hq?M$uuv3lWY{o1gNnIiN4wE;N zx}#3DpHpyC65Uaa`Ue9}ZI14!Q$6Ul8xOR+CMZtrHpC)P#_%-cbQy-e);)o{sAHy%ekPjiAb2RJw1{gedOxIz3LEL(aaGIMATuxQ8YAH|Ptp4rf0_Uvu6k6W z9bOL-2>6flz?B6OD43|GH|YmuJaGDtK3mR<33w20{u8@PtT%E= z`hK=BMtqCKwK=xsHFZ|0Cf^|6~&m%PmGd>g`G#{-^i5}M_)`R=hVR4i2OBkYEvKQ$1lxd5kQ&G-Ou zb+0RuO*sF(E{Ox|!;6JDz>WcCGO%0v6imvWde$cOv;XWr?i^_dQ5l{Q_@4V=mB)@kBhXsKC0Yx= zUetcBd8jO)K~hY#9VeRvdbhPA|h zTi6OugLvyQYErm>$iHkPM&>){@kYxCRdWS-LVg1%^vx-I2W62bG;O7GEhXXl z(^*V>J=dKo<9soqgnpBYJ2z)I4F+0T(?>1x4X2sYrI}s0SfQ=wXeAY}q9SOutP_I( z0#;-IEdeX|5|5~ffEB({Q0lIUyUA>zmjy7dj<1w17`9JXiquf224``565YKwoPh2m z{IX`s^4f6B!I;ll<%_)|CkkEt4)9BoPj7SZnHl{mtEQJDr1=hv>Wc;}9Q`ZPm-um< z@1;N#-mlkp>D7F{S{@YQGm%0hol*E&n~0_ZcKB8F;w~t?3`6n|W@^cJ*IIWzr-0&T9Nq zwzqCJlZ?$~d^ocmCZTr%(l`RnrcH+s7wLVG--bVG;lzN`rJg_P4ABe+*i5{} z`@GQ$Q22-@a3zZ@s1#+NmqtyDjWord3BD7)N0U^o+P5Ut?qK}gl5DIo*;uqb5&9Rn z4JDsl<2)0aWn_nGv5v{p8~yb;8wQPcBl4W?M;!5@Q;njAL~XC-Q?u^V$L<+-K&Kbk)$*1#DPiNX> zTp}D5Q~Hu*{NO?T6M5C9=QmIuIrNRY2jo-fxJG322VZYqU(b{-zV42ClDz=I?x}L%To>$lj2;ajk}KDJzy=Mq#6@ zDIlKTy?PKJFi1*j)s#R|sR6sQg#tPBAO^(yeM(q8^CvynQgS}9U(pO%mR=~K!J0OtqgixOX~~zBmyiHFWX3UHjYU@df zkcR=x;ti;Seb{l3P-AOj)z`F0AQ7ItLPSfKXfiSuofW!tjXjrypi~HI6lqB4&Q`?? z6h7a-HYtwUI)azEGhj#se|j|QGHTTVz=8y2{~%fbX92$UL!f1%nh;p2iJF)xvs*3t z?7&$n+fm{@@RFg5JcH3_jzq2E*u;#qY!k6BGldU*Knu=xMAmjswA?&-i6`0ugwvf~ z)yWkHgapPCEhBZ+W!9=AtYDx)R~Pnvx!M(O)`<@mLM7pRu4`3Al3)z|YX5SGhMho8 zt=C?hcxVfgp)xCzcOm*pVf$IK@?$DVF!@Fe%{=}7lZ$`XR zEdv_;UZ6z`Wu2kHze0PG88y}oAGh5?g%Cu-twvkZtT4G$m!g`E|cH_+fKnn zD?`kJFL5v^9kpkHo&z>{!^>pO444ITAT){(F$-k90kz%N44wtgop9&R`i|D7$@0lt zzvGVKzijNSsvL4ZYSTf?2CLF|H1srp`%LO}h$bE5aGz>f?SzrQMY6m9n?|Ov%hLKl zy}|otDu=GpVbiB=}H|#DC+LR=lYvFVs`B zXI#m$IMMWe#id?MSyUyOp0q#TKfTIZ?}>}^5}p%GqqJ@gWG4?@eY{_N#5q$M2ciE& zKeM&Hpl#CobW@+0<|R)|$C#RzEOlz;9M{J3zurp{n&{>oLSxtelw3C2Ye*+LIklUz z)^mxfAQ{XFMQ_$?Im-$T69(D_PZ$n9igsW~&`~c-`Yg03LDJ_Y%?Se3Q`E8iUE!{q zu7==&_;Ye1Ie(z>EDAOes~jcU+S_GEoEob$()=+8$_pY7>%l7M#iPgB_kZ!KB-eHL zkLj4B|B=cY{aW>i-ch~t4~K|ucQE3O-fE=zojglv2QNfBD3Sbo&ez((#EZ7R$!A^bNE@PWYMQFa3u$8}dZrwt zjbQ7GO#v}Ds~@IyX=7jL8O@KP7aE3Rz_4uvInAvXD3jeFhSYf(cp2-_S$c3US* z>%wyKe#(3n%N7Gom%5&pZBF>!KmrxrT)L1WXl8ZR*d|L-g5`JmdZjQo))Q>|$g2ve+(uXq zxNzu~r6ZHe4oSt$zVst@=NeO8&M1BOu4DIR8)#6ijl_LCO3Z)lWR^pM<7bOH#e8T; zey}yg4~D|8!E8od26!zKjQ+&sV6<2;dg;Hx=p{giAUBZ2u7kz~p%jC2?xr8xbg4N> z+zN#Y{iU(fm%ANKknc?T{>UkeKXc>tWqLh0VZV1|o-Dydyf}4= zP=OX=KKn&kfnDJej#bh{(MQ=^vt*m2g<9UAn5L=lUx|6BC3pL*RZW+tay(L^Whn2a zS+{7$>XsA9lQY%}SHLBwQQVMgr}~Go>pF;lB3nNplJq?^_#vOb^VXJ{DTj#CSQ~h3 ztQ`cvYkkl&drJSIEhUkBvQC`kuC&?;HWxQXXT@H>qV4T0&z=znco_Y=L~?wiDdB%= z?;9gNi1mA#CYYEGD^D+)`X~Pzb6hLNcwS{LWyB{Fwyn&#bq=Y_PvX~(SF~CLN>QTM zVr5tWmiH2NO>Ywf1Uow=!vv_V=a9}H*UQks@~q#7aOvg&TlwvCr4_^Pi_yoklfOATl6Fm03-bTQ}EBhzI}RYOuOR zTnzS%)z$E8>~4(4#!Ao!q}ae+2Z0w$_~Tf@ck`1>(%NJ;aQBN`VL^5vuvX4YW1DqC zsMwx<4!HfRI2(P0yC}?KKb7wnnxxowb{$3Kn=Ucm-D;EX)bO#sC-f)n96#XJDl(S&z>-2CwKtvAz_JQ6_Ie1Ot_J z*tg{_--Y(aBuN@5nr6y4-lfN}M)g%W7vQc(E(D|+RU#w*sQ!5|KlLy><16;8q@Pu{ zya}q)93@h!m2VX~!cHOZY1Imu&?hb@-=Rc=S$XEd@JqVxpChNzU0a3t9E`C8`7gYU zhbSwr1D-SjGwpB83&JZNYQr8|FRrqxF7-QWDrdLRF=92T=8K@yZj-f+fFd3iFq?b^ zLR%vXdb!Tirp>Q3gmo;~@BE#SF!rbcV~+|2XnWJswB{&B{hq@e*e&z(I;cwX39L)Y zv~?+cyDX&p#(Xhk51Y#kDHohaCy@BC@qRfDT&SMZglf394W;fk9%Emq1O^=+e}G8m z;6H~dy?TzB`BlJ*s<%sQci0VR10s<))Xq1O1C*O`M9D)MJ)k|H^r7&hOh*PO57wCr zM%Z~ajBN6@zPLPFFDM)}fq)XsW@L6fFLe3=^Q-j`^K>fgQ!=v#t!;;&$8Kls9a7hh zDSJF^V?Pjn`GI&1eTAF0lh^0@2~UhY+s}i$ujWeoIs^l2tK?1Lx;sbgh+ZzQi8w}v zAsB`nYU=zp{%OsxZ*D%)9BBOox15Ta-Z743?Cf6d7XOL$$#N}!=Muk;%Mr6*te*zZ zw>Ax9;Og{#$5gOtG`-y%8IgP|@(vsT9pI{6O*28mj-F!D|HWQ#t(q!miCoxvsOfxs znZQc@+3T;I=BA_gGa1Mt@5S2tVfVDTPuh&`8Sz4Nq69qFg{(R3oitkGUw6`w$7Uv( zFXe<1W+t`3AjKum#p*h3604aN$x|nFA2JayhWnT^SE+SEI$XWRRh{Q5l}k1wX9_v= z<4;JwTUfLqpSRxO718xUK18w;w=pfSs=HoGlFwv0JU_=w0LbUJ+Up9mMTa>IIw;Go zK1GMql7uVvDk;U9YCyuF`n2^~j@c7juZ^ywd-9{M$S@OK4UC*tDNOdoW`uVvU2(#Sjtey zG)ZHfJT)iQ>B#=uESnV)b6QOV^8@jznUKgSwd#9sYi?%mhk%Dz#wcq`J~~0A`f3bnR}h7}>PD%X?%{<6xJ2M*?VR77=%srmb%d*U$KJlFmtTgC z#be=3&3GNoDs#s+c=|G^8`9wEDveX{xn{q%*Jwqe?ym{UE-Zw_(}Dg|e5JDq6A@_n z7I>Q>_X90!`I*oq>#h%}z?a0LN1T3^vk}+|cCkkjhz3|EY5l`Qy#r`$rI%^?hxv6Z zE803KM_v={Ln0w?EDX2MON4~KaIlFSd%Q;70r|w9&J)#)7Wl(AQKCj!We#a*0@3|x z21-bjE|ipr`BqqNSbd4|W_m`tON_)wm~~2y?q6g|;+kdvU;b@i`}pmMC}Ds2B_~l! zZFrq-{bfV_W-S*0gg!}@QyYGe=Mu0TGp1wVhjrm!Q#hoy|D25QDEe|x^o^G3wb8!e zMZ9SU@5gS+*@^YPs7JR`Jqx>nGz_Y`<*rttjZUi2>~)KycEJxkYD)N*v>E<2{~%P{ zDF?<;fA~=@LF!5_4N@<7MJk>oFOf!Ctg`_*b)>lDTPMYdgc-8J6zNotifMoJm}B8z z?m&Je+kJtY22w~eQ`s3WEkA2}`=i$Ly6Y-SUayx_(m{lk;M1`=lG-I#s}$fzD=|?O zT#ZymcIj0NB^#ncP1#}RrcRp$O)bTdO{i;@7$9uAaBn2Zo$VE+~*uX8nD!JY` zdaQe%Ki<#!=u_847*7s!`fKe?Jo_Z|?CSyt0m@DZGH2L2^*X!1rY9RRsj>bKAF}~w zK8VPQ8-*GT4T=mOy(ko_?mxv(P5N>yd7rV`t**kYQU50K ztW?*1lLTKQNY$&_5@s|`9!TQ$n>3GXw-X)-KYX)qW4`QPUVAi4_8|E(l|iDoUz2zU z|90yGXG_vNjRYci!3SmELN={vFvQ-VW0595UA`AdkM$0#a8Wa8Sy?vMj{GESp-XLj zHaYEW6WQb<)TNFzf_Bzs$8dQ27tA6=zI1s_7NMH(EjS6H=bJ~%C>o*tO<-F)WLer< z@g^zytQC>Pfgb0a+v9^-$zA5n8+dmwty-NJFS?S4Flk z@Ae{h^Pce1q>CiuZIp>#IwA&VMZkOF5hHHNpC{F(J=dbcyJd6pRL&n}yQ-a2^Nb;1 zWIuMEyeP6e)H_@|Mm&+vXql<%=OK?ILCfYygPGNRtR~!(=^MGd7MtE<)-Lr0y2{P# zxHn>HN{tAoIAI3+p40E!>?CbpB7LNbKbxMMi5_$3zSJGf@HJHTEQW36&VQc;< zasnK3({m_b)$qU4JyDmwuDOoA=pWq6-K1DGkz<``xh_@Mz>uYhR3F`7sJT_qWd*wCEZ<5BzAMQyYvXpsClp>VJ6>oqp|9euhXl&th=yQ{cN$#UZa^t8t5$SaF(|QjI?BVdrrM^r-RD@JFr2Rd~h+P z^p558yXb0iM%skEr^gWXy{iV!%A1p~70PQt+}dsIbgCnWD)wp|xzq?g&l&_&Ly1KG z%!rJ}1+G)wpl7Y5teO=r@l#0)lmbUpbnI`_0kz-GyZLn)>Sk@D;#ekD+#(y;*LMqd@x}VGOgeG7_kEa?<}H!2vPGhstp)TIvqhJRoUDUU74ZTN2HD<&6YUE0k~)} zu&+m{)LuzW?-^rH_3%A6 z)5jfhS8tEUussg6N{~AI@&m1h8DqhVUIAN}Vfx4ISRDPE@%`B%@okdfIxh5<8tKXS zHr=kxnuFSGMr>vb5aj@2q#nX4N&K_Osnw1x;du_&leMhkO+E-Z58lxNho~AWzz;Pd zNS(0r!5~DvvXfn#U9YBU?LnqGxUDhPX(pv(C^(p#zCSsg6*&A{@5d!Kyl8GkL0{|h@bOW5MYiX3D zLaVck2!s51Ku(}EEV5}(kL>^~WNvUKU)(FO*emj#uj<%h0fHW_s2tq{0a09YdB~M6 zEbJ!)FPbEFvFcjcFg)!I1S@+nGXySpND0}#B)ZO+Lo+kIr1&f8JyeqEiICDS*!=m- zkF3&Ad}dyJVMtHR;_nOAVpl+v40*p{YBu6V0ID9lF@~iLT5)x7Kik7{Wl$y9lQ}My zNjw@4%Xm#m$ISl+|4P{!$;qj+J^BTHPU%|H)6$w`R{STuI)Au?rUq(FCrRtJxk@;n z4XM@D;hLNQEvC%M)pOf4&brhqh7r^quT@h}D27FG6c%1mtG=x#TMjZsTDDrFuX{78 zPi71BJ;s5h?*zBkw;}eS)ymHaUrTd)Jz}NCwo6^pVUNJ|hIMJ)ZDam61C(7f+zU|Z9H;ywySxY*cKO)@%PT4W&#iX-#}H6t z4bZkKUFv1-v($*K%8zfu(>Xy*3#i!)cYJ1p@`KIscebO zKGs&8fA#_%4&^C)Di3VwQ`3*Ooq-1QcK1qJGK~KW!}uF*Yn*ynFO6gz_4Zsb1(G~| zhISscc0q5WuBuU?3k4jG!%!p{-;k^Zp<9K0yJaDK8fdTG~Zi-(WM3S~MGnJjp(QQu3p@fr3+wQ8#Fl+S79 zmy>iW(x-u9Xg$rOsjpZvZj^>;Z_R!Y+!L+GC=gOVI@|WJja)7rOWZ5BDcvqxzCqqD zgI0xJf_9{K_TiVHSEM_&D21(L{|vsmShNhj=7rR!z9qW`S%m$tcw0z8C=^MgLK;80 zP*|UAd~nZiJ1-5v^jDpOJ2FllxD0I;S0bxaS`$se2Z1G-eI`@6@mY(N`msSw5+6Sh zwn&M5H0-^Vxl3A`><1*YmCVXiXe&{VKiaM*&`$M)Y^>+XK@(Zi9^f3%6c#s1S={jG zrFhs!b*kBUXKmU$zK?y!FYjFGyi=X_4$JY!w38$6kq*^!Z5kJyO5}S=YZ(;R%%`}YG*;m-`|{*r_FFzJ!a&?-Cl9mP`piYuPRw&H zr95D5vtMwmQ~qfwZn5{3*6A7h~IU6jEziS%@0Mf+`vQI^l?OWxP-pd zsCPe&j2gZ{|Nj42`xd|^tF!;4N!tK{H%P!JRVoIpwnDX43aQ$A%RRM_;wKl~9E%+~ zgalAaDW)AwU!rW&&27%z+~%B{x=#`D)&grmv_*7+;$7!X4QjavMX>q*p69&po1_%= z`+uKXX!4%(p38Hd+j-7&p64C@-o)Sc;JcK+9Bg4LuGQDVZ1>D>QThV0Q{Inx)*wJ6 zT^(-p)CVn<(RrZ1!)j+pSeK9H{lieth#WJWlp}wyI z6I-X7r_MG9&kptV2hMAqo-%cIN^m&tjR%~qC6=ib7UbY4KWTZl(PIk!G&)XQcoJ#5 zYjH6r?{{gW=XO{pnkT^E#y7z6;|0i38*KD|BA? z!YECDK!Z;g+zOV`+3J`&GI(~=p1>KcUh~vyb8tkcEhW^R(zGY|5&X(i$F_xbAk#YD zYW^wl59Bc3RhLH?%#IR>(pQbGe>=IK`t<4{S#NjDD5Dznsek4ET{*4dzcq>lveV=?z!!V_3CLs&&NtL^b@Liq&c8Q&GLNWyqr-Sq> zi)|s9fM@x5HiDj+5p|0tL7BS<&%VU+`iafsF)?&hor%XE;&Es@EommRKjy6Bxo0)b zcn`J+Of3k~w<8vHa~<&j6@TqfI@-&@TG+i}l)@yUzDdqE*dq3c#y;2%M}XYYUXbc}RZ83e~nehfMAvv$FXYzdz@$Y90wos6K z=VF*eV+(;>*)bSV|1<-Ecr5-B2YHshi*!-r^%VW3D%$b_ksaRZ8f=;n5Cszfp}mcZ zYuNr^cT9PAHT^^?&RBPCQaUOfgNCDb8co!841J4h((zCR#x$tDTuKtq(3fw@i}{b- zhs|6eFrL)Tzy&xtM^w^h9WzYg?lf8&+;12}Rr}Sg->9nXsH8&+TA)+3)R)I4t%klH zNh<%fkmPa-x%zDeb8rIdiC3XW;@1enRl}MWi@I3AMMn}{klB1CfCM0`eLB=qjTc87 zFAjq(L7i4FrXA>qD`C*4hkU9PZ&_1Kno`L4V(e!J+sM+*&A~Ua527S-Bb&P>frAel zz`_4_@tdB6r|N)>YzczXz%{3eH?s2z2q1&RZ@M1~GU%=>Bv(q(3m-{ z;?)#WHlus#GVG$;*qMe1UmT->u?W9_cr1x<|djUH?)zabBW%aT`8`RE4WX zM`#}0FOvV}D<<*@myZ8FaUK*bMk>wiKPKJ&)y`zcf5XchH?ipcKp(upJ2kg|z=}M< zN5IG9gn30e$F`!F2z*=XIBshl&)ehKy7oLcHNLxQZ1xGY3$G$M5(M$|TFa~AuA7;! zAc9Mm^d=a7%QsTv)G~4)U~**fov<3>s*E^e`N;%Y7r7qt{Gjn3IzLESmaibxGy`?U)~Y9oj2*#ejgomaB`CHCK|wxEw)ucUZgj+LH zz-uobcwa_i%2ZXmgR>8JaG2Zj9h^+MICD)6-4=RO;s7vPUbH&O9M_?CBy(KaKS+;o z$#HwZadBgdv+Dvpnc%o*NRB&9mDSo%YNbSBwoGg%HG9SZ``YguJy}n zH!H5sK3oA0s(b&z>x#Adue|-pWjhi5xT=6#Ii%o%Ww=UV^2MDRJkLpR4u=KR^G^M{ zi`9-(e8gcXesm1hgYM1%-dHC7ss&d#a%STCYAi_gAo7xwsdKF=XOy zD1K$uc;We#KM+?%5NjsyvoQMDFsOxWAK)t^dmqE>h;$Vkkgm3p5JW3ZE$#^^xL+Kj z`GbT5)gWC~aFtE%zwopN^E`VIAP&5=WoBBe!gF|SD#jOm$h^RvMdR^`q383fjGdaE zEAOn3E%9$o;1bfW@62fe1=Fljy;Oj2X0TK>X?#eT-<&GwOIdDnkZ3$u7l!6Z9V-=*tm^eGBExW z-ABhXT{v^aB53-I|FP^6lW$O2b7dz113E#_g&RG#YH@&3UT4hgcfNxO^zdj{hGhIv z&>nHOb%51N)ynfJ0MJ2Prh2g?)Hfk;X{hhIKpJIGzjj;W)I~_9td#F9@w^gnx2BX7 zP6(!YURhx-X`H$+7)8=xs^#(70?x&e;uL)M7cGZTccoo4p*w$u_G1-(X!bbLFdm zayo9O+|#D+gH;V4m3eKR{>6*%0B)R@l$ciG(}d5D@p%BBzv8nQpMT=B2cLKGIe^b_ z%+55-oHA^fWf=am;*&aTSlY1kVYVT|hH8LH*gueeQe?RqVcXtl9npAvQOhhi1K*2F zNQ+>lR>}_{kY)ugvCNA!q-;b8&I!RW$|j$=Lfuu#@#Zn?^HDK6sj(cp@&$n7a3CF~z>3P~WB3C@?Rn}NJ0gcx)<&G?f`z1jD)AO( zHxyTWQ02Cd4KMPf@u8a;Zw3*? zhuSSJ(T6$~y;KybuX{0mzurgScYr9R9N<4ZD8LJwp@Rrm>I@yvT$6>@z_-G4yKuhU zmC@hcf}kGAFQm5+wDiw*lG~Mkqee^FXBf0Z4RU*MFov(06Isz#Ulm!E5y|feT@?!e zEH*s4?QrxWa-w-LlHZvh&iww-r-vN(rEQ& zsH3}f^(tjkvD4GL=7(zi!3=n61ePF|VD>h|=TNlYvWG%~Ml?lS2Jp1;)1)o2QnTgX2T}{ejV~#VJ!uQi7vH{jq?pwb(MX#Dbk1 z+jtjlV>fmaI%JXTVwzptLTQv%NrX|0`gr+^nw9vE%Fo#!l6m~1Jx2XF(w^^0YPw=!A@p;dL zzTs>sb1Q`tlqO1BS2$5-vn#w#X-da$5DgG}E3l=9(sH)?%*yjyLv6c5eOIh{2%POP zbcG&&i$7{HGWn%cd3GzIvoOBavkS%rOIvR@N9J(;d6sPI?N)?MxoBhS$fo?WRPj*f1%6kZhWB(6(aSn71)b+Xpx(-Ax(k;STvTg ztdk(4^EdFpi?HhI-r%{Bij=y3FZ12Nto^tcKbCCVb7_ew>#`El zJNQeV?Rh088(?R_-!eRZSStg}wEryM@;@``rEI(qZC!v*DLyx%&2{*g%+?g^!2c{n zh4KHSJW#h%%!gSBeuadL^8Po1$)xACu?1n8FS|WF%TA|DfmNVRFNo4xBVNgu7qJk! zjc%4N#QT*M>fTTfag-EKnsKbuLmcJ!$v|0a%G5L*D;@s|Crl;gsTFjrbi6;1(^`@; zwStb7j>iJyv}2_+AtAEgwQN)0MYqAQaXlt3_IMIBevX&N9M!YCejHq`zYFmRMxEV` zY-JRW1qvSaGSWLiE!&Hv8nJ*E2U&i|qf@SNJEAjFTY|i$&sGXw3cA!jY z91bNFb}aZ?8Y`ZH9|nLWd}Txp0$}S5XVcE$5LQAV3N6Z}<2ZJPnw$408YJBX%*i_n zaGoRMJCG!JUEKwrdx0pNbRFF0Iac3ea1E9-yl3!JuM4L0S~K6lX?en_JT=n%aWLvkz8U`aNq-uH2irpEQ84+l$s6C6yR7@p z#lehvoOX>}e`QER73OFh=Yw0Kh7&m>YsEiMX81CWMG5aGvFm$!6bfF1Rt$EB^B>wr zH}Awv@d>yEJO(?zt*d6kmb4XtIcU>~8@jKUP(BsAYuv=jLvljwEJN68m`AmFcGOSe zU>BJyFQjX&CCEaa;iet=0%af8&eXw% zDpXJiB3n1MEa@)XG1!}s&Z2ZFky5)lI^&>apuwTVDT z@i;z~1=`a@lV7*^WjY2Bzn6uzXu%Vmpn%Wvlw_7|Vb2dC()5BjzQbpd3MoG-wY`6YXsNcuTokCY>JB{-=x zs@(^KGALs+0kFIeB;ylnQ9wqR@*`w}d5kbq?nZMdG~n0y|GG(u=n@ai2l~m&4Zx~O zYGAhX{Jc$zXltK{8s#U|Sw}3}!j({O`|2#=Rk@b-&dPj7p~dcSWscu8m3Fj?UEw(y zot2qr$0WWZX+3dYpSX}+;+53oh3pb9;K`}$h0CF8J1x>OJ92rI_eRQ(P~3=cuunAn zxj&Y-A0U9Q>8z7e79LT4L>te>!eJ8v7pavtPo;JFTw*-;Ld8_)*g$nOnKN6hmKN*K zSfx#!buzkI*;F>nTcM6Jvjq@hV@t<^fL zFcmE0pE#e?|LE^STWRDy{M}^ zzdQ8FrQ&MnSKxxM2?n7DsVi|%=tS-VnBIVAxT|*cZ}3#RBxl4g`~Qi*g~8O4bBXvH zb|XAQYtJHdQa8bWl7&IDzA{ptRwI;X*vU4*<8*@#QRVBP(*{Ok1{l7mzz6{)jehkT zXB!_t4MRGd>en;8q=&R@ynH?SOjjeLQo($9h;!psR zhaToNl}FamUt^GL6S~qk8O)PKyQ#>ClKQ<6l0RNAOE#fI9#P&bD@6S?z%GJm_BQ=4 z%rdxD&|R2U#p^Z9D89kJZX<%iK!(`GnT&Mgq{IdwQY3uhkOiaO5z{kAX04!yZ{uMS z1;q67f1n~0e2|0nIqG_wx&Q*jYSMFT+fJE z10zDQG-UUT;gU%g7*zOv_X7NhY;a#szc#qpQ37(Vv&lUlPv}2qv~didj~G&GJRchJAQ(?JyQ*%8z#82VSJ8PUPj_BrE5V zjn}Yv^peaf6pIf6N44$IrHF^*4rG(z9m<8%9Jz-FQj2uG8C1K-Cw4QJw-Y4PW6@G% zcPw17TD^zI?vd4(pA~81X^|^TFBC%*(`1Ro$b!}paEOV?30FV{k6jeV$1t-ie^5GZ_rEj+aA`WB)1K<}UOevHm65_0pkT2t@hU;D8Xbi$NE~CZA`0bww3`O!- z@kakwaU88t--5k~w*1?z^VA<$!%N*(GC{eNtgXm=)CRVHTxLHC0xWov>N;3s;wS2N zwI{j8lWOhBZ+m5(+sC1CnT2R6dao5X&m*jc-ULEYKfG=m1g%%EA`U!cHNCyC7l-%d zy-F=o_u2D~E>R}!Sg9zrsg3A_6~m77OAaaX+m>`%ugYC5-z^t!-4 zZ!Z*RW|qJ@9#V4JLw!Tnq=wpZk=&xKmfJt1ENE{jyD9~OCe&f6g65B&Qfb`W$jY0= z?02l>M^N6Ynp#aQ)~hPm9*;oxsryiCu#R)Tb;oE;?{3xKFa&SJdX;}QAcXz#T&8;q zvgl|q(&6LZej|bKVy+MeVG_IH^Wp;zC@%-qH*3`jo2SCM9D)=1vW8N-xcg;OM|4=t z<74H9 z?tcQqj;8uI^XMZr2vxb}2$l}U7t+sK(<^!3ay)P?Hc@vC0m?^a9jW$;|6Z*h7DTU3 z9On;EC1IQkXq*Ytn5h-dwy9&FXG4kLd6Z%z&67cRiFGp*np&*QIU$q;15Wa1&WFVZ zH*exn+(EJA=f;u4_khxd&{5X=@RJPc6)>xm!EFkYx(#9#6NW>~E|wOzvG6sd#Ups5 zM%-iLX@L{i`P!WoJee$JN4o~pu;rLyh2wDM1$;h z6s!vDF*V6>pnVWMgC(GI!zqJU8lNn|NnHB|dxU*U8&>{G^x7Cm-SR9@)LVTG;NTML zs;LP?c8qsOp`67<*iT}x$gj)mV*qLg+ClNuFTcV*__Oj76McpP(C?R(n4ZCh7L3-5 z?c;}P!?@>uTzv~UjMCb%kH2%i6Qc`CA1Z{{Z7Yf zb16UYCp>8MObogS*`bhn6P|O$s|P-qs6Pl^PKxbeoULW|V!PgvKB3xMiFk2AJ~8en zyUJ`b0@wKu&`ibSC%}~L0s8tUe3f*}_}I2NK<8x}muu(y6izb(XvEu#*~m5x)XVb9 zl+&PXNXi?<;a>rvz{PPhS!p^7?|R6KEC`cEyk_YJ-YvrpaHe|!j=k!oljvOcYCH}g z0eI+ds4wjqxFCfAl7`!5$M2 zQ6o~;=io2N`bx*|6X~%5G&ofz&SZG(>b}7+*Vr5k!fZW9>OTe2NOpO zZg)3n9AdYow?^T01KK;L1H|U=P8Iu>jL}a$Xq*OO2W2IEyJ6K zTgDcaz}B+B#@RO2S39gW+IRlwCp=S2&`#_I60gjCee^60`+7|7EL>|Qxj^^6nCDy% zRC0soh;Hn!)qSmH?kR=E!91A3_A7T?i(1fa+?szej@qyC3d=98Br*XaoH*A<$(y7n z7ZnR{P@1yvx99uxRs!h1`0*(N^7DZF7*NYTIiPuXi3jA@pg{9A7c+ccOaeqQ6u>YD zoCF1$KkFksAQw{ZGYGThx&z`c_Iem^PZ)@f+F1nrOv0VpVIKxr(Yh8aa8C^?C|!mr z0%uV_xZ(;|Gt+uA{){Gl5{ z7H;cILw)3+zlD+IS|^PsEVI0GGw}}OxWn+t{Qqg6 z4%n!DinNFJ30MQ#AJ&P~i?LYGAp-JF>HqSr#vg|JF~lB`9S4)*b~mT$J!l9(*dt5e zU9YWCDc!|0ZKjptqRvtpSHgq%?3JgfR(OWZm_FsV`&Q!veAkX_-q|o5Z^Lj;?Ev-a z5F?|Wh$>I~@i1uWLHYd`_+IVbA%ASZk3+LdOuxftEj}CZxp5}WkMJp(1-%G=AHXMw z=e782!QcJ(y9=KHK2d!Bj?a(r`2*^I59Qb4b0&zyWFCFm|58#cD6?{TYFheen^u$l z4$;1k9zArJef03rBNWHzk)!SO^bGoE)M%$vW)k%^+&ZE|j^pqR@QDjZbsa&R&WeMp z(24Zm1>kt9t#OJeurM+Ux^y)ZTodo#;m=|TRPo_gpcp2hhKoZdEP)B0IW}d^99yJ1 z*8ECvvbyzr97pYdS?v55u~o(~H=Ankd-0-9T2N?T(s=U`;EF7-lf|CT0diYV`?Vdv zG=8IR1{~lyH5hYv;Suq#li;3^6suy;qROFs*rv=osg%9022ZxwQ`q9|`Lf{(j51Q$ z4{ah`j?8JCf8&u|w)P&JHNeEDly5C*$;ic^@EUep4$t2Dch!YQLTj9+z{R1MtziPA znCEyy1{^aYwa1oh#EV;zD5rROht(DHbk~25`sO=y1ztbz*}Q@D#q0gL{}~8^YIdCBXq2=&XN(s8#8iczeabI?#mlumzzaVa^{IwG%`o2u1^xeD@p}r!x%a*=-Y#%L!x(yc{=>$)?yA7Sg!IsY1 z*5lyO3T8UDroF8wQ0=6Gz#L=m`-n@6rEMkG$tZ;zLnzIl05k9R-VR-d9Pp^O6iMO z{Po!FnU>o;Zz>@dzG2A;YhhG#W1T^&*hGLua0sfDz4A11`<9Fp&%uUEBEEjY zGUbsIHgzlJ;B5cgCT)?Rx0Vb(?v!}gRsW`0Lk0k$r-*hhMo(M%m^IMuGN`16-gWvbYlSaBUyq|FpAKs^`H z6i$i~O?R>Z`~qAVTpvXxoN{Mt^Mtu_4;0AS8n5_r2@}DC03^0i*jh?FkEUw~k86H2 zvX5E%<#;_Cn0DCCN=rjq$`(>ZCAtvQBqVufl1wr*@)rp0DuFNsJv*^>#9(OLsTem% z5bNtEc;151qGBeXxn@kn&IrRy`PB~yHHv7)vYWgZkRu%f7z8zpuybc(%dfEfHi@L;hp^Bn6%oB9fmd@ZNG!{oSXfkr%P$3@a$M|eW5VBi_j;I z7eqBW1eo=O>N;hi23eXgxJP+k=~1u85^sIZwUP!?bzX^SlCQ)xthU7TEIz&3N7p|n9eZK0l!K7vC}_JZ-g#B1dg&Gc0LV> zu-3wI&z}7v_#g6`tnyh7A)PQ>^7~R7uEeTPwq$cUd?Ev%{w8d)|ijDCzxMo_E5tggWazW%l9lyd#+V zTjAgV_#NW5e!kk9{mu-X9v?go^{)Ltw$K`zNh$Au0nh6A#jqEL^^w!+yd$^0qXrM4 zb=`?9}OJIB7G zzN)E?4JG_4w00JGu@&iC=oSmIJ@4@xUNb@6mEAQB>q^5=+o696181ud?b{(qwB9$;!61dCqEo>OAu^3q!4D<7&LE>0ybfx_ z5E7`&`}i*VzfexE(b3L`UZNX4<%%0AS296p8GJnhhbV3G)DK)M7wo#-(udn@bMkhA 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
f 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

-c_vJ`Q7XXS=^f`H4LVvb&~;!Ir6Y~x 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�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 literal 0 HcmV?d00001 diff --git a/vktest/assets/shaders/frag.spv b/vktest/assets/shaders/frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..cb13e606fc0041e24ff6a63c0ec7dcca466732aa GIT binary patch literal 608 zcmYk2-Acni5QWF4X=`f#Ea;t7ycCKTDuPr|k=z98&jTzmSv3-qkfefleKw!U8^Lqd zM6xiMowMKWoQc&s=!$HJBLkVr-i9y>RhEyZ#pOoG7cGcxpci- z6=azz%FkG|cT$BXyDr^Eah^9ANY~wFol{aae=CB0CHh!OT|D_gP z+~OR21h80hrn;VD8qTwCCKI#Y!M+1+hS&wqxmmOS4Bs9y{~Y!6s%8&r}b+jR|9Frfp`-zA4wdsf#gY+O!Jqbx*sUEbn)A_jXXs znnoc+GiN4?xT*hNgD3&4%Qj_?WDWh*<^M?BG*iaw`Ume{`B^v&(jX80>~qi$Q-ARB zOW4aZG;K8A@v+x^?e~U5Kg)l_p&v&{==Y;ks_0vYZgNZ)CB68(KQ3^j81Kn3j=7*d zhJ!51qd}sr#5B#ad~XmBQW1{kb%oDj|0GO5glQgr7Zh9a#N?_^h@B|(oI}A!Nq!pr zRCm;rIc8VxFph>tQI-cuFC67KMRMnHJjyvbFV2reKb)g9WixM+J{>U&XZtA)&JO8a z@f&fjJZrjiBaZ&y@K#4(aP(j~VmQvtQ^u7?=ZT>Ya`!9D{;M+9f>h|%RKqujmlU<+ zUD>kg^~efLZc&(5&U)t(R6aF93&G?vi3^O0HG(uprF$(35Az%kuPLXINAWXJ=Td^6<<6=KYP& za7EadU+Sk-)Ls>Wqi@Xe*D7ptmcKrxB?r%bD>A-C9UA(*AcPBEG~}PiQ%`p*IH zx+g;qkB0vEeZaqyhCR0`PHx0)R~$2+sERor$k3AGp1C{rVb+H-&XY5vFED!B*JH)D aFJ|49(K|dE=H8RRQ_tCe|LN49%Kifb=6Edt literal 0 HcmV?d00001 diff --git a/vktest/compileShaders.bat b/vktest/compileShaders.bat new file mode 100644 index 0000000..fb487e1 --- /dev/null +++ b/vktest/compileShaders.bat @@ -0,0 +1,4 @@ +C:/VulkanSDK/1.2.162.1/Bin32/glslc.exe assets/shaders/shader.vert -o assets/shaders/vert.spv +C:/VulkanSDK/1.2.162.1/Bin32/glslc.exe assets/shaders/shader.frag -o assets/shaders/frag.spv +pause + diff --git a/vktest/premake5.lua b/vktest/premake5.lua new file mode 100644 index 0000000..0997390 --- /dev/null +++ b/vktest/premake5.lua @@ -0,0 +1,67 @@ +project "vktest" + kind "ConsoleApp" + language "C++" + cppdialect "C++17" + staticruntime "on" + + targetdir ("%{wks.location}/bin/" .. outputdir .. "/%{prj.name}") + objdir ("%{wks.location}/bin-int/" .. outputdir .. "/%{prj.name}") + + files + { + "src/**.h", + "src/**.c", + "src/**.hpp", + "src/**.cpp", + } + + defines + { + "_CRT_SECURE_NO_WARNINGS", + } + + includedirs + { + "src", + "C:/VulkanSDK/1.2.162.1/Include", + "%{wks.location}/vendor/glfw/include", + "%{wks.location}/vendor/glm", + } + + libdirs + { + "%{wks.location}/vendor/glfw/lib-vc2019", + "C:/VulkanSDK/1.2.162.1/Lib" + } + + links + { + "vulkan-1.lib", + "glfw3.lib" + } + + filter "system:windows" + systemversion "latest" + + defines + { + } + + filter "configurations:Debug" + defines "SU_DEBUG" + runtime "Debug" + buildoptions "/MDd" + symbols "on" + + filter "configurations:Release" + defines "SU_RELEASE" + runtime "Release" + buildoptions "/MD" + optimize "on" + + filter "configurations:Dist" + defines "SU_DIST" + runtime "Release" + buildoptions "/MD" + optimize "on" + diff --git a/vktest/src/main.cpp b/vktest/src/main.cpp new file mode 100644 index 0000000..0c03079 --- /dev/null +++ b/vktest/src/main.cpp @@ -0,0 +1,1139 @@ +#pragma warning(disable : 26812) //enum is unscoped +#define GLFW_INCLUDE_VULKAN +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const uint32_t WIDTH = 960; +const uint32_t HEIGHT = 540; +const int MAX_FRAMES_IN_FLIGHT = 2; + +#ifdef NDEBUG +const bool enableValidationLayers = false; +#else +const bool enableValidationLayers = true; +#endif + +static std::vector readFile(const std::string& filename) +{ + std::ifstream file(filename, std::ios::ate | std::ios::binary); + + if (!file.is_open()) + { + throw std::runtime_error("Failed to open file!"); + } + + size_t fileSize = (size_t)file.tellg(); + std::vector buffer(fileSize); + file.seekg(0); + file.read(buffer.data(), fileSize); + file.close(); + return buffer; +} + +VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, + const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, + const VkAllocationCallbacks* pAllocator, + VkDebugUtilsMessengerEXT* pDebugMessenger) +{ + auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + if (func != nullptr) + { + return func(instance, pCreateInfo, pAllocator, pDebugMessenger); + } + else + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } +} + +void DestroyDebugUtilsMessengerEXT(VkInstance instance, + VkDebugUtilsMessengerEXT debugMessenger, + const VkAllocationCallbacks* pAllocator) +{ + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + if (func != nullptr) + { + func(instance, debugMessenger, pAllocator); + } +} + +struct QueueFamilyIndices +{ + std::optional graphicsFamily; + std::optional presentFamily; + + bool isComplete() + { + return graphicsFamily.has_value() + && presentFamily.has_value(); + } +}; + +struct SwapChainSupportDetails +{ + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector presentModes; +}; + +class HelloTriangleApplication +{ +private: + GLFWwindow* window; + VkInstance instance; + VkDebugUtilsMessengerEXT debugMessenger; + VkSurfaceKHR surface; + VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; + VkDevice device; + VkQueue graphicsQueue; + VkQueue presentQueue; + VkSwapchainKHR swapChain; + VkFormat swapChainImageFormat; + VkExtent2D swapChainExtent; + std::vector swapChainImages; + std::vector swapChainImageViews; + std::vector swapChainFramebuffers; + VkRenderPass renderPass; + VkPipelineLayout pipelineLayout; + VkPipeline graphicsPipeline; + VkCommandPool commandPool; + std::vector commandBuffers; + std::vector imageAvailableSemaphores; + std::vector renderFinishedSemaphores; + std::vector inFlightFences; + std::vector imagesInFlight; + size_t currentFrame = 0; + +public: + void run() + { + initWindow(); + initVulkan(); + mainLoop(); + cleanup(); + } + +private: + static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData) + { + std::cerr << "Vulkan: " << pCallbackData->pMessage << std::endl; + return VK_FALSE; + } + +private: + void initWindow() + { + glfwInit(); + + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + + window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); + } + + void initVulkan() + { + createInstance(); + setupDebugMessenger(); + createSurface(); + pickPhysicalDevice(); + createLogicalDevice(); + createSwapChain(); + createImageViews(); + createRenderPass(); + createGraphicsPipeline(); + createFramebuffers(); + createCommandPool(); + createCommandBuffers(); + createSyncObjects(); + } + + void mainLoop() + { + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + drawFrame(); + } + + vkDeviceWaitIdle(device); + } + + void cleanup() + { + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); + vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); + vkDestroyFence(device, inFlightFences[i], nullptr); + } + + vkDestroyCommandPool(device, commandPool, nullptr); + + for (auto framebuffer : swapChainFramebuffers) + { + vkDestroyFramebuffer(device, framebuffer, nullptr); + } + + vkDestroyPipeline(device, graphicsPipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyRenderPass(device, renderPass, nullptr); + + for (auto imageView : swapChainImageViews) + { + vkDestroyImageView(device, imageView, nullptr); + } + + vkDestroySwapchainKHR(device, swapChain, nullptr); + vkDestroyDevice(device, nullptr); + + if (enableValidationLayers) + { + DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); + } + + vkDestroySurfaceKHR(instance, surface, nullptr); + vkDestroyInstance(instance, nullptr); + + glfwDestroyWindow(window); + glfwTerminate(); + } + + +private: + void createInstance() + { + //get and check required instance extensions + std::vector requiredExtensions = getRequiredInstanceExtensions(); + if (!checkRequiredInstanceExtensions(requiredExtensions)) + { + throw std::runtime_error("Vulkan required instance extensions are not available!"); + } + + //check for validation layer support + if (enableValidationLayers && !checkRequiredValidationLayers()) + { + throw std::runtime_error("Vulkan validation layers are not available!"); + } + + //structs used to create a vulkan instance + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "Hello Triangle"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "No Engine"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + createInfo.enabledExtensionCount = static_cast(requiredExtensions.size()); + createInfo.ppEnabledExtensionNames = requiredExtensions.data(); + + //setup an additional debug messenger specifically for the vkCreateInstance and vkDestroyInstance calls + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo; + if (enableValidationLayers) + { + auto& validationLayers = getRequiredValidationLayers(); + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + + configureDebugMessenger(debugCreateInfo); + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo; + } + else + { + createInfo.enabledLayerCount = 0; + createInfo.pNext = nullptr; + } + + //create vulkan instance + if (vkCreateInstance(&createInfo, nullptr, &instance)) + { + throw std::runtime_error("Failed to create Vulkan instance!"); + } + } + + void setupDebugMessenger() + { + if (!enableValidationLayers) return; + + VkDebugUtilsMessengerCreateInfoEXT createInfo; + configureDebugMessenger(createInfo); + + if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) + { + throw std::runtime_error("Failed to setup Vulkan debug messenger!"); + } + } + + void createSurface() + { + if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan window surface!"); + } + } + + void pickPhysicalDevice() + { + uint32_t deviceCount = 0; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + + if (deviceCount == 0) + { + throw std::runtime_error("No GPUs with Vulkan support found!"); + } + + std::vector devices(deviceCount); + vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + + std::multimap rankedDevices; + for (const auto& device : devices) + { + uint32_t score = rateDevice(device); + rankedDevices.insert(std::make_pair(score, device)); + } + + //check if the best device has required features (score > 0) + if (rankedDevices.rbegin()->first > 0) + { + physicalDevice = rankedDevices.rbegin()->second; + } + else + { + throw std::runtime_error("No GPUs with required Vulkan features found!"); + } + } + + void createLogicalDevice() + { + QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); + + std::vector queueCreateInfos; + std::set uniqueQueueFamilies = { queueFamilyIndices.graphicsFamily.value(), queueFamilyIndices.presentFamily.value() }; + + float queuePriority = 1.0f; + for (uint32_t queueFamily : uniqueQueueFamilies) + { + VkDeviceQueueCreateInfo queueCreateInfo{}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamily; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + queueCreateInfos.push_back(queueCreateInfo); + } + + VkPhysicalDeviceFeatures deviceFeatures{}; + + VkDeviceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + + createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); + createInfo.pQueueCreateInfos = queueCreateInfos.data(); + createInfo.pEnabledFeatures = &deviceFeatures; + + auto& deviceExtensions = getRequiredDeviceExtensions(); + createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); + createInfo.ppEnabledExtensionNames = deviceExtensions.data(); + + if (enableValidationLayers) + { + auto& validationLayers = getRequiredValidationLayers(); + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + } + else + { + createInfo.enabledLayerCount = 0; + } + + if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan logical device!"); + } + + vkGetDeviceQueue(device, queueFamilyIndices.graphicsFamily.value(), 0, &graphicsQueue); + vkGetDeviceQueue(device, queueFamilyIndices.presentFamily.value(), 0, &presentQueue); + } + + void createSwapChain() + { + SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice); + + VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); + VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); + VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities); + + uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; + if (swapChainSupport.capabilities.maxImageCount > 0 + && imageCount > swapChainSupport.capabilities.maxImageCount) + { + imageCount = swapChainSupport.capabilities.maxImageCount; + } + + VkSwapchainCreateInfoKHR createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = surface; + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() }; + + if (indices.graphicsFamily != indices.presentFamily) + { + createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + createInfo.queueFamilyIndexCount = 2; + createInfo.pQueueFamilyIndices = queueFamilyIndices; + } + else + { + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + createInfo.queueFamilyIndexCount = 0; + createInfo.pQueueFamilyIndices = nullptr; + } + + createInfo.preTransform = swapChainSupport.capabilities.currentTransform; + createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; + createInfo.oldSwapchain = VK_NULL_HANDLE; + + if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan swap chain!"); + } + + //get the actual imageCount and swap chain images + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr); + swapChainImages.resize(imageCount); + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data()); + + swapChainImageFormat = surfaceFormat.format; + swapChainExtent = extent; + } + + void createImageViews() + { + swapChainImageViews.resize(swapChainImages.size()); + + for (size_t i = 0; i < swapChainImages.size(); i++) + { + VkImageViewCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = swapChainImages[i]; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = swapChainImageFormat; + createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan swap chain image views!"); + } + } + } + + void createRenderPass() + { + VkAttachmentDescription colorAttachment{}; + colorAttachment.format = swapChainImageFormat; + colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + VkAttachmentReference colorAttachmentRef{}; + colorAttachmentRef.attachment = 0; + colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass{}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachmentRef; + + VkRenderPassCreateInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.attachmentCount = 1; + renderPassInfo.pAttachments = &colorAttachment; + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpass; + + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + renderPassInfo.dependencyCount = 1; + renderPassInfo.pDependencies = &dependency; + + if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan render pass!"); + } + } + + void createGraphicsPipeline() + { + auto vertShaderCode = readFile("assets/shaders/vert.spv"); + auto fragShaderCode = readFile("assets/shaders/frag.spv"); + + VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); + VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); + + VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertShaderStageInfo.module = vertShaderModule; + vertShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; + fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragShaderStageInfo.module = fragShaderModule; + fragShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo shaderStages[] = { vertShaderStageInfo, fragShaderStageInfo }; + + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputInfo.vertexBindingDescriptionCount = 0; + vertexInputInfo.pVertexBindingDescriptions = nullptr; + vertexInputInfo.vertexAttributeDescriptionCount = 0; + vertexInputInfo.pVertexAttributeDescriptions = nullptr; + + VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssembly.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = (float)swapChainExtent.width; + viewport.height = (float)swapChainExtent.height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor{}; + scissor.offset = { 0, 0 }; + scissor.extent = swapChainExtent; + + VkPipelineViewportStateCreateInfo viewportState{}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizer{}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + rasterizer.depthBiasConstantFactor = 0.0f; + rasterizer.depthBiasClamp = 0.0f; + rasterizer.depthBiasSlopeFactor = 0.0f; + + VkPipelineMultisampleStateCreateInfo multisampling{}; + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + multisampling.minSampleShading = 1.0f; + multisampling.pSampleMask = nullptr; + multisampling.alphaToCoverageEnable = VK_FALSE; + multisampling.alphaToOneEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState colorBlendAttachment{}; + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_FALSE; + colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD; + colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo colorBlending{}; + colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlending.logicOpEnable = VK_FALSE; + colorBlending.logicOp = VK_LOGIC_OP_COPY; + colorBlending.attachmentCount = 1; + colorBlending.pAttachments = &colorBlendAttachment; + colorBlending.blendConstants[0] = 0.0f; + colorBlending.blendConstants[1] = 0.0f; + colorBlending.blendConstants[2] = 0.0f; + colorBlending.blendConstants[3] = 0.0f; + + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 0; + pipelineLayoutInfo.pSetLayouts = nullptr; + pipelineLayoutInfo.pushConstantRangeCount = 0; + pipelineLayoutInfo.pPushConstantRanges = nullptr; + + if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan pipeline layout!"); + } + + VkGraphicsPipelineCreateInfo pipelineInfo{}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.stageCount = 2; + pipelineInfo.pStages = shaderStages; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &inputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &rasterizer; + pipelineInfo.pMultisampleState = &multisampling; + pipelineInfo.pDepthStencilState = nullptr; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.pDynamicState = nullptr; + pipelineInfo.layout = pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + pipelineInfo.basePipelineIndex = -1; + + if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan graphics pipeline!"); + } + + vkDestroyShaderModule(device, fragShaderModule, nullptr); + vkDestroyShaderModule(device, vertShaderModule, nullptr); + } + + void createFramebuffers() + { + swapChainFramebuffers.resize(swapChainImageViews.size()); + + for (size_t i = 0; i < swapChainImageViews.size(); i++) + { + VkImageView attachments[] = + { + swapChainImageViews[i] + }; + + VkFramebufferCreateInfo framebufferInfo{}; + framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebufferInfo.renderPass = renderPass; + framebufferInfo.attachmentCount = 1; + framebufferInfo.pAttachments = attachments; + framebufferInfo.width = swapChainExtent.width; + framebufferInfo.height = swapChainExtent.height; + framebufferInfo.layers = 1; + + if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan framebuffer!"); + } + } + } + + void createCommandPool() + { + QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); + + VkCommandPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); + poolInfo.flags = 0; + + if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan command pool!"); + } + } + + void createCommandBuffers() + { + commandBuffers.resize(swapChainFramebuffers.size()); + + VkCommandBufferAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.commandPool = commandPool; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = (uint32_t)commandBuffers.size(); + + if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) + { + throw std::runtime_error("Failed to allocate Vulkan command buffers!"); + } + + for (size_t i = 0; i < commandBuffers.size(); i++) + { + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + beginInfo.flags = 0; + beginInfo.pInheritanceInfo = nullptr; + + if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) + { + throw std::runtime_error("Failed to begin Vulkan command buffer!"); + } + + VkRenderPassBeginInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassInfo.renderPass = renderPass; + renderPassInfo.framebuffer = swapChainFramebuffers[i]; + renderPassInfo.renderArea.offset = { 0, 0 }; + renderPassInfo.renderArea.extent = swapChainExtent; + + VkClearValue clearColor = { 0.0f, 0.0f, 0.0f, 1.0f }; + renderPassInfo.clearValueCount = 1; + renderPassInfo.pClearValues = &clearColor; + + vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); + vkCmdDraw(commandBuffers[i], 3, 1, 0, 0); + vkCmdEndRenderPass(commandBuffers[i]); + + if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) + { + throw std::runtime_error("Failed to record Vulkan command buffer!"); + } + } + } + + void createSyncObjects() + { + imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); + renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); + inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); + imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE); + + VkSemaphoreCreateInfo semaphoreInfo{}; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fenceInfo{}; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS + || vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS + || vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan synchronization objects for a frame!"); + } + } + } + + void drawFrame() + { + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + + uint32_t imageIndex; + vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + + if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) + { + vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX); + } + + imagesInFlight[imageIndex] = inFlightFences[currentFrame]; + + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + + VkSemaphore waitSemaphores[] = { imageAvailableSemaphores[currentFrame] }; + VkPipelineStageFlags waitStages[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT }; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffers[imageIndex]; + + VkSemaphore signalSemaphores[] = { renderFinishedSemaphores[currentFrame] }; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + + vkResetFences(device, 1, &inFlightFences[currentFrame]); + + if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) + { + throw std::runtime_error("Failed to submit Vulkan draw command buffer!"); + } + + VkPresentInfoKHR presentInfo{}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = signalSemaphores; + + VkSwapchainKHR swapChains[] = { swapChain }; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + presentInfo.pImageIndices = &imageIndex; + presentInfo.pResults = nullptr; + + vkQueuePresentKHR(presentQueue, &presentInfo); + + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; + } + + +private: + std::vector getRequiredInstanceExtensions() + { + uint32_t requiredExtensionsCount = 0; + const char** requiredExtensions = glfwGetRequiredInstanceExtensions(&requiredExtensionsCount); + + std::vector extensions(requiredExtensions, requiredExtensions + requiredExtensionsCount); + + if (enableValidationLayers) + { + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + + return extensions; + } + + const std::vector& getRequiredValidationLayers() const + { + static std::vector validationLayers = + { + "VK_LAYER_KHRONOS_validation" + }; + return validationLayers; + } + + const std::vector& getRequiredDeviceExtensions() const + { + static std::vector deviceExtensions = + { + VK_KHR_SWAPCHAIN_EXTENSION_NAME + }; + return deviceExtensions; + } + + bool checkRequiredInstanceExtensions(std::vector requiredExtensions) + { + uint32_t extensionCount = 0; + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); + + std::vector extensions(extensionCount); + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + + for (const auto& requiredExtensionName : requiredExtensions) + { + bool extensionFound = false; + for (const auto& extension : extensions) + { + if (strcmp(requiredExtensionName, extension.extensionName) == 0) + { + extensionFound = true; + break; + } + } + if (!extensionFound) + { + return false; + } + } + return true; + } + + bool checkRequiredDeviceExtensions(VkPhysicalDevice device) + { + uint32_t extensionCount; + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); + + std::vector extensions(extensionCount); + vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, extensions.data()); + + auto& requiredExtensions = getRequiredDeviceExtensions(); + for (const auto& requiredExtensionName : requiredExtensions) + { + bool extensionFound = false; + for (const auto& extension : extensions) + { + if (strcmp(requiredExtensionName, extension.extensionName) == 0) + { + extensionFound = true; + break; + } + } + if (!extensionFound) + { + return false; + } + } + return true; + } + + bool checkRequiredValidationLayers() + { + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + std::vector availableLayers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + + auto& validationLayers = getRequiredValidationLayers(); + for (const auto& layerName : validationLayers) + { + bool layerFound = false; + for (const auto& layerProperties : availableLayers) + { + if (strcmp(layerName, layerProperties.layerName) == 0) + { + layerFound = true; + break; + } + } + if (!layerFound) + { + return false; + } + } + return true; + } + + void configureDebugMessenger(VkDebugUtilsMessengerCreateInfoEXT& createInfo) + { + createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + + createInfo.messageSeverity = + //VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + + createInfo.messageType = + VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + + createInfo.pfnUserCallback = debugCallback; + createInfo.pUserData = this; + } + + uint32_t rateDevice(VkPhysicalDevice device) + { + VkPhysicalDeviceProperties deviceProperties; + vkGetPhysicalDeviceProperties(device, &deviceProperties); + + VkPhysicalDeviceFeatures deviceFeatures; + vkGetPhysicalDeviceFeatures(device, &deviceFeatures); + + uint32_t score = 0; + + //prefer dedicated gpus + if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) + { + score += 1000; + } + + //max texture size affects graphics quality + score += deviceProperties.limits.maxImageDimension2D; + + //geometry shader support is required + if (!deviceFeatures.geometryShader) + { + return 0; + } + + //ensure required queue families are supported + QueueFamilyIndices queueFamilyIndices = findQueueFamilies(device); + if (!queueFamilyIndices.isComplete()) + { + return 0; + } + + //ensure required device extensions are pressent + if (!checkRequiredDeviceExtensions(device)) + { + return 0; + } + + //ensure swap chain capabilities (at least one supported image format and one supported presentation mode for now) + SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device); + if (swapChainSupport.formats.empty() + || swapChainSupport.presentModes.empty()) + { + return 0; + } + + return score; + } + + QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) + { + QueueFamilyIndices indices; + + uint32_t queueFamiliesCount = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamiliesCount, nullptr); + + std::vector queueFamilies(queueFamiliesCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamiliesCount, queueFamilies.data()); + + uint32_t i = 0; + for (const auto& queueFamily : queueFamilies) + { + if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + indices.graphicsFamily = i; + } + + VkBool32 presentSupport = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); + if (presentSupport) + { + indices.presentFamily = i; + } + + i++; + } + + return indices; + } + + SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) + { + SwapChainSupportDetails details; + + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); + + uint32_t formatCount; + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); + + if (formatCount != 0) + { + details.formats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); + } + + uint32_t presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); + + if (presentModeCount != 0) + { + details.presentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data()); + } + + return details; + } + + VkSurfaceFormatKHR chooseSwapSurfaceFormat(std::vector formats) + { + for (const auto& format : formats) + { + if (format.format == VK_FORMAT_B8G8R8A8_SRGB && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + return format; + } + } + return formats[0]; + } + + VkPresentModeKHR chooseSwapPresentMode(std::vector presentModes) + { + for (const auto& presentMode : presentModes) + { + //triple buffering + if (presentMode == VK_PRESENT_MODE_MAILBOX_KHR) + { + return presentMode; + } + } + + //fallback to classic vsync + return VK_PRESENT_MODE_FIFO_KHR; + } + + VkExtent2D chooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities) + { + if (capabilities.currentExtent.width != UINT32_MAX) + { + return capabilities.currentExtent; + } + else + { + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + VkExtent2D actualExtent = { + static_cast(width), + static_cast(height) + }; + + actualExtent.width = std::max(capabilities.minImageExtent.width, std::min(capabilities.maxImageExtent.width, actualExtent.width)); + actualExtent.height = std::max(capabilities.minImageExtent.height, std::min(capabilities.maxImageExtent.height, actualExtent.height)); + + return actualExtent; + } + } + + VkShaderModule createShaderModule(const std::vector& code) + { + VkShaderModuleCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = code.size(); + createInfo.pCode = reinterpret_cast(code.data()); + + VkShaderModule shaderModule; + if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) + { + throw std::runtime_error("Failed to create Vulkan shader module!"); + } + return shaderModule; + } +}; + +int main() +{ + HelloTriangleApplication app; + + try + { + app.run(); + } + catch (const std::exception& e) + { + std::cerr << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file

~h)c2f)dCkdg+3Mh9$+%LxB~fiFE9_~;&S3g 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 KOk;ul3;!QO&RvwCCIZzF+=r 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 F{tt<&GRgn| literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2017/glfw3.dll b/vendor/glfw/lib-vc2017/glfw3.dll new file mode 100644 index 0000000000000000000000000000000000000000..9b1c80349e7fe21162fcc99fb4115cd32e24ba26 GIT binary patch literal 225280 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�n+6hnV`hL3K@@ixM8+m_dMxpmkKK9+kIIb{#Hy@8wsrYKf{&gz8hHsjFW2TMK8)6(+m=5#tSO=r%WE@pE65-?YLn?k3 z<9HXNh%y>6#;Q1D{9(p)f^i_pIF@4c?q&?^VT|`O4)igOJi<8kdyJX4GJ4;}=zCPf zYwTC?k12cyW8j^P1Am~7|B%u9E_J+@vHy=4)9+>+_+!SA_b`tC38Q!)qi=vQ@P5Yl z2N=^IWE}kv^S4V6O2`#V9Y2qM))}JNyhl67zaMhIQkjJ%wI7Y zpJfc3VC?@J#`NbH$3D-P`2yp}-!jI($T;vN#?euQf5$lfWk&HNqwgOW<6mJ+f0c3U zBxB}ljNWfBRz1b&`zB-SKQaz{i*a;}ar~bc#djD-6vm(C-0aHNor$BP(8r!mH-GkPy$tSV;gpTU@(sqk`zvlPx&c!k0_ zjALF#F^_RnVf;#!Za!oDDs_CdN_P!oW&xvdEo0yfjQ!U!j$F?;egmV|V60li7{7@z zeKX_eV#e_$jNYY;Rm)Vo!v0%T{B0^;p|PBgy(<`fD;WcKFvfifOBmCo>UHu8VjR7jF;m6pUB_5eqmFACeRYgtJ!3|pZzCVa z>ls_`VeG$`G2Os8wuw<}Ve|zU1NSj{8yUwGW}5g|Y-Jo(nAyh1#tuf`n;2W~XB>Dl z(5Fd7f3<6VqZU5u^WjQvr@ z(HP@+oY9+L^d%WvQ;dNgb$&Nv)gH!pFJrooaqJOB@m5CP?=x1tO~pT|j{6z=-_AJl z7-QxgjNU(B^!*`Y;9ZQZdl}<@#5nM7#?e1!?0*kq`cG8+dl@tDWAwhC(f0wyzy}%Q zA7V^@m~reQj2Hr9zJ8Rk^<#_!f5tfaIAi9|8I8YS45S(R_cM+hPAKFMf&nlbPh#{R!z9QbR-(a$nw zPB0puV+?$rvHuH0IPg8j(SK&loMJTog)#82 zjQ!td9Qgrb=7)^lamK2DXEc7q82B+`>uJXRpD?DMVI2J_W9C`Lv7a%DUoiTfQ}{gN zxWbYD;N!6u7&940<5!G#@v~g<<0{_kiqEL{`L1|T%;mur1xI;w{B^E)uS#zq-b>|IKOMg~PyDhx z@ylKDDm(erm07m@b$kf|x#COn#FyoX_veYnHjAA3W7|c}_*Hr0u`MHKdTh1G8INre zIpg1$CmvfQa;C@jh@A0v<%!2uik#`I^2Ar?iC>o|9z&}+^RLYlUzaC-eV+IYdEz(b ziLcKSe@~wHd-KFMUo1WFZ!11}yAVD5_}ihROA0`D z82DrRQT*%qXZJxwzKPDxg@2Bvg%S(rVgEV8UZ4TRMf;5j|N9!OUqU=NhoZezRS4UC zB9VWkZ-Smhdcq9oe-I{obRqN>(i8p_Xc@wU*JFCRD(T0 z6sEmEKULuja2=H7Fs`-xC9?Z0BHu;70L@y4eK^46jd&h}2|o<-Av_LTY;gWQ;QLf~ z4EQq;m51=(776hg+>7u(K~EuU_g`f9Z8VPkO3QBsKaoG-04R4dRjS6FXir59}N17@q_$NRE2&Zp_|K;1THws|`cq8PP zuBAP4Uj(IbU)n3DeJ2ra1APYZgdxyLgzY|%?EaC+Ptwmo8KfcfuE1X5TOlXF)u8zZ z(_Xs>i1a;H&!itqB&uxVg??d=B!gilK zBIN|A{W1|g30jOY5dIUW5@EvUK@AAoeJzn+rX=VA#1p;?6i1lwLn=&2`~TjFc)R~2 z@|83P4O0=yN%#iP0)z=GK+6%PJ%ieZ6X9n-A3{Eae+L>ynD7UnFCa|&3$^bi!n;9F zA)fGF&^W?`9iTG^(_X|+f`|{aC$X%O!?ZW?11d~=6o0A0v>&k(MCobo;lF`u!B5(Q zIAaaR(_X~YDs1=LL_VGdL2L0`gd?B;!i3)dg%GCwhWN2-E&T?SIPdXNvqyEkmREIG&NP6*Ph{VIOD|;eMd@n?yLh z0kQ#KLWDPg41@`90r?OntWfb)z>k8cE~kON1wFo^(BU75`~+RQ8S;d9!rMUaLAVO| zub>fx?Y@VeL7etgM7SdW`9vDR2xvLNgl`9}MVRpV`@kQB`+>g%kv_qOHSs9uIh2|9 zxt=1zd!c=-wSHMwX~=8Cm?DsXg{g;1!ecyWcTqzzMrnx zhBDw!i4V!oj{my5cCwn5)uAB!n9YlVLRW8_NcxCBxMOWMnq)>J`Xy9=OtXR z1Nk6q_m4z=l8Wxfvm>66{2!4oB)cCZ@{hC&G#~MV9|A2$nD!w*@&La_+DrT#NIpC8 zT@UiRraizv1yOluU+WF$Rs9L-2;vEU4$2^$0p9;!$aV?%349Jjx+nu&`#!~I;Jyz*446V@40aFVkzhPsBZ7x>qpvj~p@Q;*}lBE8+0 z5cwFo@8h^H;tBVGHd3Cz-ZXR|r3VfigziE*u2H|m__M=4jP0#@12~&sg4iN4K z{ym6%1rd%BAxt<9BELX{i6N8|VZtAPyk*$C47~m@>3TJ@xkMg@PfI$_G0}re42=Ln~Y#hUP zctEm_0B0X(o_K-RJi+hR0RA`VxpK(KCxrN05b3B<;BP>5EtXh{I*_c7K<#^o@C4{M zo{R7|pizVgSB)S&!d1Y(1d%L_0Ox!X@6nHY0TUp)*9h=M5almECBzyK#oPVwkbj>K ze;RzjwS-4NV+a#|3G^JoginKt@GOM?1zLcx_zc#Ff#_M{z|Vn-k>2hbhy3hlzd3{- z|7+X}*AfnaoIFUc$cs?M0aIiz-a`HPGXT9|QXThRah0 zd|ZXoz@LDK4;kR2pMyVgr0)k_@p-aw!8hRjpe~f575LdNp#CC_-OmvDA38P)*+Uw_ ze*isz@E9=qcPJ;qap1?l40%GHcHd0ovuXO1(20mATnGx$eSt?nDTGIWzXZ`cGX4SW zGKk7t1&o2H%yHlcLB#WM;19ood=Nhl^n8`mdx0MYQ5w5{AMy$G*h#cm74UTc`~qk% z!h~DChB}L|-6s+GD*7AHEW{Ij5o91d3jEGDU~3^f4t)E!&~C1RegOK$ptliEIRBrx zUKqf6-&SGZmq6Dc{U|W?9VNrS?}O-h$AMd(=JE%Ce+T*u@*D$R|6NXF_a{VthNgWF zIs|D5H-ly&{{Zl7|BUo>El~RoB3%4`pzDx^ko*9(B5d~uwE4%dVL*EkPdNXl&>;vL zz_eoBQ$ zisADIME4>eF&jaYC;5tbs|u6Pn3F0z2JD;3>HC3SSK)D>cQ$;?;9i8!T;UOG>At|# z@CQTrlV2FW7e37qPyS){g6Ll4CnhwPFr~tTf26|i0X_$!{tn@F*YdT5 zJ{2bH15w%D3T%c?A@bQp_&jJM%98=kzmC%o-mSs`;K#1V-a@2#9C!*ux{GlB4ICzX zAAA?}BaLCOpQQnW$=?$BP&xr#5t3gd3KNoVBLis&4}v-oetrKuG^9t=?|csSN#)BC zKcfix35i=r3&rnyoLAA&+PizZyYy$)?p#{3(zg_!bHUaKEQ7prsr>fzQX?t7k#u1R z<(*6W!pWs~-!*&YTKcY5cUxDVfefO_JD1|yL2Hujond^jcSUyuJD`)Xjud@QVofmF zy>fTSQUlv(A{|)Ks$3rM-H?@GtW72G*+JT?pmMwE9J!UhyTXa3Mo)xR`X=#g9l@?- zc&TxRna|og^513c9gZ@sy~BJsT)y@W%{LrmzmDt}pGV9>Z0Di)A&ivBaOE%}j6yLV zP<3$Q!IKBa4?cSk2d$`YB;x7fv^TvVZKRi_ed)?{ReEDOklvAQO?Rf_>E3jIdT)9l zy)T_k52r`cC(@(olj*Vasq}dI*>om-HZArS@AvLsu;19fY`<@R<^HPu8}|qH@7UkE zzjJ?lfA9YO{d@Nh?BBOPy?=QB$o>=iNB5uHKeqqW{_*|K?$7K$yI&kAKHxpD;DB*p z*#X~y$^%sgHXaBZ*m0osK<9z@f!+iC2lgHqII!Zl?Uk=0|$2;Y(3a{Fn+N2VE@6r2L}%BJD5H=d~oF8 ziG!oyz}Uf4k_(xGXAg?O;z94=fB$o*fj2iVt}YEjVNxT6V~HsPa(Np^b+Ehjtul zJ=BS}(0i!=(B4A>hxQ#x9~wS1a_GdN(L*N>jU765X#CK#hcbuG9uh;vL*AhUL&ngu zA>UBtP}R`Jp}^3Nq1K_!q4-emQ2)^0p@E@&L+PR6p^>2zL!(0{hsK6Z4UG>yJCqqZ zJ0uPlANC$zaM(D!?6B`}<>9Ks8xIE#?>O9gxbtxQaPQ&%!+Q@89Nu?0eR%lr$l()* zM-QJoJa+ih;qk-I9?l#-dsqw?4||6f3>(AChJC}8!&So@hXcbqhFga_hvUP&!~Mg1 zhX;oD4X1~Phew7_437?<93C4!H9S82>~LoI?65dee8hWX!4c!gvLn7Dl}DrnN5+pldn9w@>=ALa_^9{j zf}_UKWk-ESE00zk-FP%`bjQ)wqn$_NM|+R7&C(M~nI%Z~YuRUWH4w((ft*p6eZ$2yP2kM$nwKeqSSz_ESD z(#M96jT}31Z1mX4V`Ilo9UDLP?6J(Tv&Y2o;^W@q3yvGdmmT*VuRLCLeB<%J@g2uo zk9QuAAMZWhe|+!pf#ds*r;iUGA31*F_~`MI$1}%^pD>=Nd?N5f=M();?0aJ5iIY!^ OKXLX6)TUSU_x}N7urICv literal 0 HcmV?d00001 diff --git a/vendor/glfw/lib-vc2017/glfw3.lib b/vendor/glfw/lib-vc2017/glfw3.lib new file mode 100644 index 0000000000000000000000000000000000000000..c2d0114010704885b0e4673d80c4c4e8e4517339 GIT binary patch literal 646850 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 z�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 z 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