From dc6292b46f85247ed46ac05cbba83d53124560b6 Mon Sep 17 00:00:00 2001 From: Archie Hilton Date: Fri, 19 Apr 2024 22:35:25 +0100 Subject: [PATCH] Add glm; go back to basic glfw window context --- CMakeLists.txt | 3 +- ...son => cache-v2-1b82f29f01ef9ec5257e.json} | 2 +- ...> cmakeFiles-v1-d8eb8a68cb214ae78945.json} | 3 + ...=> codemodel-v2-85416805ba45eaaf28c6.json} | 19 +- ...ectory-glm-Debug-ab70d989331aa8f80f5f.json | 14 + ...on => index-2024-04-19T21-11-10-0092.json} | 12 +- ...-Exponent-Debug-3135f7fb60ef72779ad7.json} | 4 + build/CMakeCache.txt | 2 +- build/CMakeFiles/Makefile.cmake | 2 + build/CMakeFiles/Makefile2 | 18 + build/CMakeFiles/TargetDirectories.txt | 6 + build/cmake_install.cmake | 5 + .../CMakeDirectoryInformation.cmake | 16 + build/glm/CMakeFiles/progress.marks | 1 + build/glm/Makefile | 188 ++ build/glm/cmake_install.cmake | 39 + .../Exponent.dir/compiler_depend.internal | 130 - .../Exponent.dir/compiler_depend.make | 450 +-- .../CMakeFiles/Exponent.dir/includes_CXX.rsp | 2 +- build/src/CMakeFiles/Exponent.dir/main.cc.obj | Bin 285779 -> 259595 bytes .../src/CMakeFiles/Exponent.dir/main.cc.obj.d | 130 +- build/src/CMakeFiles/Exponent.dir/objects.a | Bin 314636 -> 288338 bytes build/src/Exponent.exe | Bin 1473175 -> 1447757 bytes glm/CMakeLists.txt | 69 + glm/common.hpp | 539 ++++ glm/copying.txt | 54 + glm/detail/_features.hpp | 394 +++ glm/detail/_fixes.hpp | 27 + glm/detail/_noise.hpp | 81 + glm/detail/_swizzle.hpp | 804 +++++ glm/detail/_swizzle_func.hpp | 682 ++++ glm/detail/_vectorize.hpp | 162 + glm/detail/compute_common.hpp | 50 + glm/detail/compute_vector_decl.hpp | 190 ++ glm/detail/compute_vector_relational.hpp | 30 + glm/detail/func_common.inl | 792 +++++ glm/detail/func_common_simd.inl | 231 ++ glm/detail/func_exponential.inl | 152 + glm/detail/func_exponential_simd.inl | 37 + glm/detail/func_geometric.inl | 243 ++ glm/detail/func_geometric_simd.inl | 163 + glm/detail/func_integer.inl | 392 +++ glm/detail/func_integer_simd.inl | 65 + glm/detail/func_matrix.inl | 443 +++ glm/detail/func_matrix_simd.inl | 252 ++ glm/detail/func_packing.inl | 189 ++ glm/detail/func_packing_simd.inl | 6 + glm/detail/func_trigonometric.inl | 197 ++ glm/detail/func_trigonometric_simd.inl | 0 glm/detail/func_vector_relational.inl | 87 + glm/detail/func_vector_relational_simd.inl | 6 + glm/detail/glm.cpp | 263 ++ glm/detail/qualifier.hpp | 229 ++ glm/detail/setup.hpp | 1188 +++++++ glm/detail/type_float.hpp | 68 + glm/detail/type_half.hpp | 16 + glm/detail/type_half.inl | 241 ++ glm/detail/type_mat2x2.hpp | 177 ++ glm/detail/type_mat2x2.inl | 536 ++++ glm/detail/type_mat2x3.hpp | 159 + glm/detail/type_mat2x3.inl | 510 +++ glm/detail/type_mat2x4.hpp | 161 + glm/detail/type_mat2x4.inl | 520 +++ glm/detail/type_mat3x2.hpp | 167 + glm/detail/type_mat3x2.inl | 532 ++++ glm/detail/type_mat3x3.hpp | 184 ++ glm/detail/type_mat3x3.inl | 601 ++++ glm/detail/type_mat3x4.hpp | 166 + glm/detail/type_mat3x4.inl | 578 ++++ glm/detail/type_mat4x2.hpp | 171 + glm/detail/type_mat4x2.inl | 574 ++++ glm/detail/type_mat4x3.hpp | 171 + glm/detail/type_mat4x3.inl | 598 ++++ glm/detail/type_mat4x4.hpp | 189 ++ glm/detail/type_mat4x4.inl | 706 +++++ glm/detail/type_mat4x4_simd.inl | 6 + glm/detail/type_quat.hpp | 193 ++ glm/detail/type_quat.inl | 424 +++ glm/detail/type_quat_simd.inl | 208 ++ glm/detail/type_vec1.hpp | 308 ++ glm/detail/type_vec1.inl | 553 ++++ glm/detail/type_vec2.hpp | 402 +++ glm/detail/type_vec2.inl | 915 ++++++ glm/detail/type_vec3.hpp | 436 +++ glm/detail/type_vec3.inl | 1070 +++++++ glm/detail/type_vec4.hpp | 508 +++ glm/detail/type_vec4.inl | 1142 +++++++ glm/detail/type_vec4_simd.inl | 788 +++++ glm/exponential.hpp | 110 + glm/ext.hpp | 267 ++ glm/ext/_matrix_vectorize.hpp | 128 + glm/ext/matrix_clip_space.hpp | 522 ++++ glm/ext/matrix_clip_space.inl | 595 ++++ glm/ext/matrix_common.hpp | 39 + glm/ext/matrix_common.inl | 34 + glm/ext/matrix_double2x2.hpp | 23 + glm/ext/matrix_double2x2_precision.hpp | 49 + glm/ext/matrix_double2x3.hpp | 18 + glm/ext/matrix_double2x3_precision.hpp | 31 + glm/ext/matrix_double2x4.hpp | 18 + glm/ext/matrix_double2x4_precision.hpp | 31 + glm/ext/matrix_double3x2.hpp | 18 + glm/ext/matrix_double3x2_precision.hpp | 31 + glm/ext/matrix_double3x3.hpp | 23 + glm/ext/matrix_double3x3_precision.hpp | 49 + glm/ext/matrix_double3x4.hpp | 18 + glm/ext/matrix_double3x4_precision.hpp | 31 + glm/ext/matrix_double4x2.hpp | 18 + glm/ext/matrix_double4x2_precision.hpp | 31 + glm/ext/matrix_double4x3.hpp | 18 + glm/ext/matrix_double4x3_precision.hpp | 31 + glm/ext/matrix_double4x4.hpp | 23 + glm/ext/matrix_double4x4_precision.hpp | 49 + glm/ext/matrix_float2x2.hpp | 23 + glm/ext/matrix_float2x2_precision.hpp | 49 + glm/ext/matrix_float2x3.hpp | 18 + glm/ext/matrix_float2x3_precision.hpp | 31 + glm/ext/matrix_float2x4.hpp | 18 + glm/ext/matrix_float2x4_precision.hpp | 31 + glm/ext/matrix_float3x2.hpp | 18 + glm/ext/matrix_float3x2_precision.hpp | 31 + glm/ext/matrix_float3x3.hpp | 23 + glm/ext/matrix_float3x3_precision.hpp | 49 + glm/ext/matrix_float3x4.hpp | 18 + glm/ext/matrix_float3x4_precision.hpp | 31 + glm/ext/matrix_float4x2.hpp | 18 + glm/ext/matrix_float4x2_precision.hpp | 31 + glm/ext/matrix_float4x3.hpp | 18 + glm/ext/matrix_float4x3_precision.hpp | 31 + glm/ext/matrix_float4x4.hpp | 23 + glm/ext/matrix_float4x4_precision.hpp | 49 + glm/ext/matrix_int2x2.hpp | 38 + glm/ext/matrix_int2x2_sized.hpp | 70 + glm/ext/matrix_int2x3.hpp | 33 + glm/ext/matrix_int2x3_sized.hpp | 49 + glm/ext/matrix_int2x4.hpp | 33 + glm/ext/matrix_int2x4_sized.hpp | 49 + glm/ext/matrix_int3x2.hpp | 33 + glm/ext/matrix_int3x2_sized.hpp | 49 + glm/ext/matrix_int3x3.hpp | 38 + glm/ext/matrix_int3x3_sized.hpp | 70 + glm/ext/matrix_int3x4.hpp | 33 + glm/ext/matrix_int3x4_sized.hpp | 49 + glm/ext/matrix_int4x2.hpp | 33 + glm/ext/matrix_int4x2_sized.hpp | 49 + glm/ext/matrix_int4x3.hpp | 33 + glm/ext/matrix_int4x3_sized.hpp | 49 + glm/ext/matrix_int4x4.hpp | 38 + glm/ext/matrix_int4x4_sized.hpp | 70 + glm/ext/matrix_integer.hpp | 91 + glm/ext/matrix_integer.inl | 38 + glm/ext/matrix_projection.hpp | 149 + glm/ext/matrix_projection.inl | 106 + glm/ext/matrix_relational.hpp | 132 + glm/ext/matrix_relational.inl | 88 + glm/ext/matrix_transform.hpp | 171 + glm/ext/matrix_transform.inl | 207 ++ glm/ext/matrix_uint2x2.hpp | 38 + glm/ext/matrix_uint2x2_sized.hpp | 70 + glm/ext/matrix_uint2x3.hpp | 33 + glm/ext/matrix_uint2x3_sized.hpp | 49 + glm/ext/matrix_uint2x4.hpp | 33 + glm/ext/matrix_uint2x4_sized.hpp | 49 + glm/ext/matrix_uint3x2.hpp | 33 + glm/ext/matrix_uint3x2_sized.hpp | 49 + glm/ext/matrix_uint3x3.hpp | 38 + glm/ext/matrix_uint3x3_sized.hpp | 70 + glm/ext/matrix_uint3x4.hpp | 33 + glm/ext/matrix_uint3x4_sized.hpp | 49 + glm/ext/matrix_uint4x2.hpp | 33 + glm/ext/matrix_uint4x2_sized.hpp | 49 + glm/ext/matrix_uint4x3.hpp | 33 + glm/ext/matrix_uint4x3_sized.hpp | 49 + glm/ext/matrix_uint4x4.hpp | 38 + glm/ext/matrix_uint4x4_sized.hpp | 70 + glm/ext/quaternion_common.hpp | 135 + glm/ext/quaternion_common.inl | 144 + glm/ext/quaternion_common_simd.inl | 18 + glm/ext/quaternion_double.hpp | 39 + glm/ext/quaternion_double_precision.hpp | 42 + glm/ext/quaternion_exponential.hpp | 63 + glm/ext/quaternion_exponential.inl | 89 + glm/ext/quaternion_float.hpp | 39 + glm/ext/quaternion_float_precision.hpp | 36 + glm/ext/quaternion_geometric.hpp | 70 + glm/ext/quaternion_geometric.inl | 36 + glm/ext/quaternion_relational.hpp | 62 + glm/ext/quaternion_relational.inl | 35 + glm/ext/quaternion_transform.hpp | 47 + glm/ext/quaternion_transform.inl | 24 + glm/ext/quaternion_trigonometric.hpp | 65 + glm/ext/quaternion_trigonometric.inl | 37 + glm/ext/scalar_common.hpp | 181 ++ glm/ext/scalar_common.inl | 170 + glm/ext/scalar_constants.hpp | 40 + glm/ext/scalar_constants.inl | 24 + glm/ext/scalar_int_sized.hpp | 70 + glm/ext/scalar_integer.hpp | 92 + glm/ext/scalar_integer.inl | 243 ++ glm/ext/scalar_packing.hpp | 32 + glm/ext/scalar_packing.inl | 0 glm/ext/scalar_reciprocal.hpp | 135 + glm/ext/scalar_reciprocal.inl | 107 + glm/ext/scalar_relational.hpp | 68 + glm/ext/scalar_relational.inl | 40 + glm/ext/scalar_uint_sized.hpp | 70 + glm/ext/scalar_ulp.hpp | 77 + glm/ext/scalar_ulp.inl | 291 ++ glm/ext/vector_bool1.hpp | 30 + glm/ext/vector_bool1_precision.hpp | 34 + glm/ext/vector_bool2.hpp | 18 + glm/ext/vector_bool2_precision.hpp | 31 + glm/ext/vector_bool3.hpp | 18 + glm/ext/vector_bool3_precision.hpp | 31 + glm/ext/vector_bool4.hpp | 18 + glm/ext/vector_bool4_precision.hpp | 31 + glm/ext/vector_common.hpp | 228 ++ glm/ext/vector_common.inl | 147 + glm/ext/vector_double1.hpp | 31 + glm/ext/vector_double1_precision.hpp | 36 + glm/ext/vector_double2.hpp | 18 + glm/ext/vector_double2_precision.hpp | 31 + glm/ext/vector_double3.hpp | 18 + glm/ext/vector_double3_precision.hpp | 34 + glm/ext/vector_double4.hpp | 18 + glm/ext/vector_double4_precision.hpp | 35 + glm/ext/vector_float1.hpp | 31 + glm/ext/vector_float1_precision.hpp | 36 + glm/ext/vector_float2.hpp | 18 + glm/ext/vector_float2_precision.hpp | 31 + glm/ext/vector_float3.hpp | 18 + glm/ext/vector_float3_precision.hpp | 31 + glm/ext/vector_float4.hpp | 18 + glm/ext/vector_float4_precision.hpp | 31 + glm/ext/vector_int1.hpp | 32 + glm/ext/vector_int1_sized.hpp | 49 + glm/ext/vector_int2.hpp | 18 + glm/ext/vector_int2_sized.hpp | 49 + glm/ext/vector_int3.hpp | 18 + glm/ext/vector_int3_sized.hpp | 49 + glm/ext/vector_int4.hpp | 18 + glm/ext/vector_int4_sized.hpp | 49 + glm/ext/vector_integer.hpp | 149 + glm/ext/vector_integer.inl | 85 + glm/ext/vector_packing.hpp | 32 + glm/ext/vector_packing.inl | 0 glm/ext/vector_reciprocal.hpp | 135 + glm/ext/vector_reciprocal.inl | 105 + glm/ext/vector_relational.hpp | 107 + glm/ext/vector_relational.inl | 75 + glm/ext/vector_uint1.hpp | 32 + glm/ext/vector_uint1_sized.hpp | 49 + glm/ext/vector_uint2.hpp | 18 + glm/ext/vector_uint2_sized.hpp | 49 + glm/ext/vector_uint3.hpp | 18 + glm/ext/vector_uint3_sized.hpp | 49 + glm/ext/vector_uint4.hpp | 18 + glm/ext/vector_uint4_sized.hpp | 49 + glm/ext/vector_ulp.hpp | 112 + glm/ext/vector_ulp.inl | 74 + glm/fwd.hpp | 1233 ++++++++ glm/geometric.hpp | 116 + glm/glm.cppm | 2675 ++++++++++++++++ glm/glm.hpp | 137 + glm/gtc/bitfield.hpp | 266 ++ glm/gtc/bitfield.inl | 635 ++++ glm/gtc/color_space.hpp | 56 + glm/gtc/color_space.inl | 84 + glm/gtc/constants.hpp | 170 + glm/gtc/constants.inl | 173 + glm/gtc/epsilon.hpp | 60 + glm/gtc/epsilon.inl | 80 + glm/gtc/integer.hpp | 43 + glm/gtc/integer.inl | 33 + glm/gtc/matrix_access.hpp | 60 + glm/gtc/matrix_access.inl | 62 + glm/gtc/matrix_integer.hpp | 433 +++ glm/gtc/matrix_inverse.hpp | 50 + glm/gtc/matrix_inverse.inl | 118 + glm/gtc/matrix_transform.hpp | 36 + glm/gtc/matrix_transform.inl | 3 + glm/gtc/noise.hpp | 61 + glm/gtc/noise.inl | 807 +++++ glm/gtc/packing.hpp | 728 +++++ glm/gtc/packing.inl | 951 ++++++ glm/gtc/quaternion.hpp | 173 + glm/gtc/quaternion.inl | 208 ++ glm/gtc/quaternion_simd.inl | 0 glm/gtc/random.hpp | 82 + glm/gtc/random.inl | 303 ++ glm/gtc/reciprocal.hpp | 24 + glm/gtc/round.hpp | 160 + glm/gtc/round.inl | 155 + glm/gtc/type_aligned.hpp | 1315 ++++++++ glm/gtc/type_precision.hpp | 2094 +++++++++++++ glm/gtc/type_precision.inl | 6 + glm/gtc/type_ptr.hpp | 230 ++ glm/gtc/type_ptr.inl | 386 +++ glm/gtc/ulp.hpp | 155 + glm/gtc/ulp.inl | 173 + glm/gtc/vec1.hpp | 30 + glm/gtx/associated_min_max.hpp | 205 ++ glm/gtx/associated_min_max.inl | 354 +++ glm/gtx/bit.hpp | 96 + glm/gtx/bit.inl | 92 + glm/gtx/closest_point.hpp | 47 + glm/gtx/closest_point.inl | 45 + glm/gtx/color_encoding.hpp | 52 + glm/gtx/color_encoding.inl | 45 + glm/gtx/color_space.hpp | 70 + glm/gtx/color_space.inl | 144 + glm/gtx/color_space_YCoCg.hpp | 58 + glm/gtx/color_space_YCoCg.inl | 107 + glm/gtx/common.hpp | 74 + glm/gtx/common.inl | 125 + glm/gtx/compatibility.hpp | 131 + glm/gtx/compatibility.inl | 62 + glm/gtx/component_wise.hpp | 77 + glm/gtx/component_wise.inl | 147 + glm/gtx/dual_quaternion.hpp | 272 ++ glm/gtx/dual_quaternion.inl | 352 +++ glm/gtx/easing.hpp | 217 ++ glm/gtx/easing.inl | 436 +++ glm/gtx/euler_angles.hpp | 333 ++ glm/gtx/euler_angles.inl | 899 ++++++ glm/gtx/extend.hpp | 40 + glm/gtx/extend.inl | 48 + glm/gtx/extended_min_max.hpp | 135 + glm/gtx/extended_min_max.inl | 138 + glm/gtx/exterior_product.hpp | 43 + glm/gtx/exterior_product.inl | 26 + glm/gtx/fast_exponential.hpp | 93 + glm/gtx/fast_exponential.inl | 136 + glm/gtx/fast_square_root.hpp | 96 + glm/gtx/fast_square_root.inl | 75 + glm/gtx/fast_trigonometry.hpp | 77 + glm/gtx/fast_trigonometry.inl | 142 + glm/gtx/float_notmalize.inl | 13 + glm/gtx/functions.hpp | 54 + glm/gtx/functions.inl | 30 + glm/gtx/gradient_paint.hpp | 51 + glm/gtx/gradient_paint.inl | 36 + glm/gtx/handed_coordinate_space.hpp | 48 + glm/gtx/handed_coordinate_space.inl | 26 + glm/gtx/hash.hpp | 146 + glm/gtx/hash.inl | 175 ++ glm/gtx/integer.hpp | 74 + glm/gtx/integer.inl | 185 ++ glm/gtx/intersect.hpp | 90 + glm/gtx/intersect.inl | 200 ++ glm/gtx/io.hpp | 210 ++ glm/gtx/io.inl | 452 +++ glm/gtx/log_base.hpp | 46 + glm/gtx/log_base.inl | 16 + glm/gtx/matrix_cross_product.hpp | 45 + glm/gtx/matrix_cross_product.inl | 37 + glm/gtx/matrix_decompose.hpp | 50 + glm/gtx/matrix_decompose.inl | 234 ++ glm/gtx/matrix_factorisation.hpp | 67 + glm/gtx/matrix_factorisation.inl | 84 + glm/gtx/matrix_interpolation.hpp | 58 + glm/gtx/matrix_interpolation.inl | 146 + glm/gtx/matrix_major_storage.hpp | 117 + glm/gtx/matrix_major_storage.inl | 166 + glm/gtx/matrix_operation.hpp | 101 + glm/gtx/matrix_operation.inl | 176 ++ glm/gtx/matrix_query.hpp | 75 + glm/gtx/matrix_query.inl | 119 + glm/gtx/matrix_transform_2d.hpp | 79 + glm/gtx/matrix_transform_2d.inl | 68 + glm/gtx/mixed_product.hpp | 39 + glm/gtx/mixed_product.inl | 15 + glm/gtx/norm.hpp | 86 + glm/gtx/norm.inl | 95 + glm/gtx/normal.hpp | 39 + glm/gtx/normal.inl | 15 + glm/gtx/normalize_dot.hpp | 47 + glm/gtx/normalize_dot.inl | 16 + glm/gtx/number_precision.hpp | 44 + glm/gtx/optimum_pow.hpp | 50 + glm/gtx/optimum_pow.inl | 22 + glm/gtx/orthonormalize.hpp | 47 + glm/gtx/orthonormalize.inl | 29 + glm/gtx/pca.hpp | 112 + glm/gtx/pca.inl | 343 ++ glm/gtx/perpendicular.hpp | 39 + glm/gtx/perpendicular.inl | 10 + glm/gtx/polar_coordinates.hpp | 46 + glm/gtx/polar_coordinates.inl | 36 + glm/gtx/projection.hpp | 41 + glm/gtx/projection.inl | 10 + glm/gtx/quaternion.hpp | 172 + glm/gtx/quaternion.inl | 159 + glm/gtx/range.hpp | 96 + glm/gtx/raw_data.hpp | 49 + glm/gtx/raw_data.inl | 2 + glm/gtx/rotate_normalized_axis.hpp | 66 + glm/gtx/rotate_normalized_axis.inl | 58 + glm/gtx/rotate_vector.hpp | 121 + glm/gtx/rotate_vector.inl | 187 ++ glm/gtx/scalar_multiplication.hpp | 80 + glm/gtx/scalar_relational.hpp | 34 + glm/gtx/scalar_relational.inl | 88 + glm/gtx/spline.hpp | 63 + glm/gtx/spline.inl | 60 + glm/gtx/std_based_type.hpp | 66 + glm/gtx/std_based_type.inl | 6 + glm/gtx/string_cast.hpp | 45 + glm/gtx/string_cast.inl | 497 +++ glm/gtx/texture.hpp | 44 + glm/gtx/texture.inl | 17 + glm/gtx/transform.hpp | 58 + glm/gtx/transform.inl | 23 + glm/gtx/transform2.hpp | 87 + glm/gtx/transform2.inl | 125 + glm/gtx/type_aligned.hpp | 980 ++++++ glm/gtx/type_aligned.inl | 6 + glm/gtx/type_trait.hpp | 83 + glm/gtx/type_trait.inl | 61 + glm/gtx/vec_swizzle.hpp | 2784 +++++++++++++++++ glm/gtx/vector_angle.hpp | 55 + glm/gtx/vector_angle.inl | 45 + glm/gtx/vector_query.hpp | 64 + glm/gtx/vector_query.inl | 154 + glm/gtx/wrap.hpp | 35 + glm/gtx/wrap.inl | 6 + glm/integer.hpp | 212 ++ glm/mat2x2.hpp | 9 + glm/mat2x3.hpp | 9 + glm/mat2x4.hpp | 9 + glm/mat3x2.hpp | 9 + glm/mat3x3.hpp | 8 + glm/mat3x4.hpp | 8 + glm/mat4x2.hpp | 9 + glm/mat4x3.hpp | 8 + glm/mat4x4.hpp | 9 + glm/matrix.hpp | 161 + glm/packing.hpp | 173 + glm/simd/common.h | 240 ++ glm/simd/exponential.h | 20 + glm/simd/geometric.h | 130 + glm/simd/integer.h | 115 + glm/simd/matrix.h | 1028 ++++++ glm/simd/neon.h | 155 + glm/simd/packing.h | 8 + glm/simd/platform.h | 469 +++ glm/simd/trigonometric.h | 9 + glm/simd/vector_relational.h | 8 + glm/trigonometric.hpp | 210 ++ glm/vec2.hpp | 14 + glm/vec3.hpp | 14 + glm/vec4.hpp | 15 + glm/vector_relational.hpp | 121 + include/linmath.h | 605 ---- src/CMakeLists.txt | 2 +- src/main.cc | 142 +- 456 files changed, 67155 insertions(+), 1408 deletions(-) rename build/.cmake/api/v1/reply/{cache-v2-8fe5fb14bc891c988897.json => cache-v2-1b82f29f01ef9ec5257e.json} (99%) rename build/.cmake/api/v1/reply/{cmakeFiles-v1-53d8ee3c2964d8bce0e5.json => cmakeFiles-v1-d8eb8a68cb214ae78945.json} (99%) rename build/.cmake/api/v1/reply/{codemodel-v2-5f54dda50eca1bfcd26a.json => codemodel-v2-85416805ba45eaaf28c6.json} (89%) create mode 100644 build/.cmake/api/v1/reply/directory-glm-Debug-ab70d989331aa8f80f5f.json rename build/.cmake/api/v1/reply/{index-2024-04-08T19-34-14-0256.json => index-2024-04-19T21-11-10-0092.json} (86%) rename build/.cmake/api/v1/reply/{target-Exponent-Debug-c5ae450747adb8fbe53a.json => target-Exponent-Debug-3135f7fb60ef72779ad7.json} (95%) create mode 100644 build/glm/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 build/glm/CMakeFiles/progress.marks create mode 100644 build/glm/Makefile create mode 100644 build/glm/cmake_install.cmake create mode 100644 glm/CMakeLists.txt create mode 100644 glm/common.hpp create mode 100644 glm/copying.txt create mode 100644 glm/detail/_features.hpp create mode 100644 glm/detail/_fixes.hpp create mode 100644 glm/detail/_noise.hpp create mode 100644 glm/detail/_swizzle.hpp create mode 100644 glm/detail/_swizzle_func.hpp create mode 100644 glm/detail/_vectorize.hpp create mode 100644 glm/detail/compute_common.hpp create mode 100644 glm/detail/compute_vector_decl.hpp create mode 100644 glm/detail/compute_vector_relational.hpp create mode 100644 glm/detail/func_common.inl create mode 100644 glm/detail/func_common_simd.inl create mode 100644 glm/detail/func_exponential.inl create mode 100644 glm/detail/func_exponential_simd.inl create mode 100644 glm/detail/func_geometric.inl create mode 100644 glm/detail/func_geometric_simd.inl create mode 100644 glm/detail/func_integer.inl create mode 100644 glm/detail/func_integer_simd.inl create mode 100644 glm/detail/func_matrix.inl create mode 100644 glm/detail/func_matrix_simd.inl create mode 100644 glm/detail/func_packing.inl create mode 100644 glm/detail/func_packing_simd.inl create mode 100644 glm/detail/func_trigonometric.inl create mode 100644 glm/detail/func_trigonometric_simd.inl create mode 100644 glm/detail/func_vector_relational.inl create mode 100644 glm/detail/func_vector_relational_simd.inl create mode 100644 glm/detail/glm.cpp create mode 100644 glm/detail/qualifier.hpp create mode 100644 glm/detail/setup.hpp create mode 100644 glm/detail/type_float.hpp create mode 100644 glm/detail/type_half.hpp create mode 100644 glm/detail/type_half.inl create mode 100644 glm/detail/type_mat2x2.hpp create mode 100644 glm/detail/type_mat2x2.inl create mode 100644 glm/detail/type_mat2x3.hpp create mode 100644 glm/detail/type_mat2x3.inl create mode 100644 glm/detail/type_mat2x4.hpp create mode 100644 glm/detail/type_mat2x4.inl create mode 100644 glm/detail/type_mat3x2.hpp create mode 100644 glm/detail/type_mat3x2.inl create mode 100644 glm/detail/type_mat3x3.hpp create mode 100644 glm/detail/type_mat3x3.inl create mode 100644 glm/detail/type_mat3x4.hpp create mode 100644 glm/detail/type_mat3x4.inl create mode 100644 glm/detail/type_mat4x2.hpp create mode 100644 glm/detail/type_mat4x2.inl create mode 100644 glm/detail/type_mat4x3.hpp create mode 100644 glm/detail/type_mat4x3.inl create mode 100644 glm/detail/type_mat4x4.hpp create mode 100644 glm/detail/type_mat4x4.inl create mode 100644 glm/detail/type_mat4x4_simd.inl create mode 100644 glm/detail/type_quat.hpp create mode 100644 glm/detail/type_quat.inl create mode 100644 glm/detail/type_quat_simd.inl create mode 100644 glm/detail/type_vec1.hpp create mode 100644 glm/detail/type_vec1.inl create mode 100644 glm/detail/type_vec2.hpp create mode 100644 glm/detail/type_vec2.inl create mode 100644 glm/detail/type_vec3.hpp create mode 100644 glm/detail/type_vec3.inl create mode 100644 glm/detail/type_vec4.hpp create mode 100644 glm/detail/type_vec4.inl create mode 100644 glm/detail/type_vec4_simd.inl create mode 100644 glm/exponential.hpp create mode 100644 glm/ext.hpp create mode 100644 glm/ext/_matrix_vectorize.hpp create mode 100644 glm/ext/matrix_clip_space.hpp create mode 100644 glm/ext/matrix_clip_space.inl create mode 100644 glm/ext/matrix_common.hpp create mode 100644 glm/ext/matrix_common.inl create mode 100644 glm/ext/matrix_double2x2.hpp create mode 100644 glm/ext/matrix_double2x2_precision.hpp create mode 100644 glm/ext/matrix_double2x3.hpp create mode 100644 glm/ext/matrix_double2x3_precision.hpp create mode 100644 glm/ext/matrix_double2x4.hpp create mode 100644 glm/ext/matrix_double2x4_precision.hpp create mode 100644 glm/ext/matrix_double3x2.hpp create mode 100644 glm/ext/matrix_double3x2_precision.hpp create mode 100644 glm/ext/matrix_double3x3.hpp create mode 100644 glm/ext/matrix_double3x3_precision.hpp create mode 100644 glm/ext/matrix_double3x4.hpp create mode 100644 glm/ext/matrix_double3x4_precision.hpp create mode 100644 glm/ext/matrix_double4x2.hpp create mode 100644 glm/ext/matrix_double4x2_precision.hpp create mode 100644 glm/ext/matrix_double4x3.hpp create mode 100644 glm/ext/matrix_double4x3_precision.hpp create mode 100644 glm/ext/matrix_double4x4.hpp create mode 100644 glm/ext/matrix_double4x4_precision.hpp create mode 100644 glm/ext/matrix_float2x2.hpp create mode 100644 glm/ext/matrix_float2x2_precision.hpp create mode 100644 glm/ext/matrix_float2x3.hpp create mode 100644 glm/ext/matrix_float2x3_precision.hpp create mode 100644 glm/ext/matrix_float2x4.hpp create mode 100644 glm/ext/matrix_float2x4_precision.hpp create mode 100644 glm/ext/matrix_float3x2.hpp create mode 100644 glm/ext/matrix_float3x2_precision.hpp create mode 100644 glm/ext/matrix_float3x3.hpp create mode 100644 glm/ext/matrix_float3x3_precision.hpp create mode 100644 glm/ext/matrix_float3x4.hpp create mode 100644 glm/ext/matrix_float3x4_precision.hpp create mode 100644 glm/ext/matrix_float4x2.hpp create mode 100644 glm/ext/matrix_float4x2_precision.hpp create mode 100644 glm/ext/matrix_float4x3.hpp create mode 100644 glm/ext/matrix_float4x3_precision.hpp create mode 100644 glm/ext/matrix_float4x4.hpp create mode 100644 glm/ext/matrix_float4x4_precision.hpp create mode 100644 glm/ext/matrix_int2x2.hpp create mode 100644 glm/ext/matrix_int2x2_sized.hpp create mode 100644 glm/ext/matrix_int2x3.hpp create mode 100644 glm/ext/matrix_int2x3_sized.hpp create mode 100644 glm/ext/matrix_int2x4.hpp create mode 100644 glm/ext/matrix_int2x4_sized.hpp create mode 100644 glm/ext/matrix_int3x2.hpp create mode 100644 glm/ext/matrix_int3x2_sized.hpp create mode 100644 glm/ext/matrix_int3x3.hpp create mode 100644 glm/ext/matrix_int3x3_sized.hpp create mode 100644 glm/ext/matrix_int3x4.hpp create mode 100644 glm/ext/matrix_int3x4_sized.hpp create mode 100644 glm/ext/matrix_int4x2.hpp create mode 100644 glm/ext/matrix_int4x2_sized.hpp create mode 100644 glm/ext/matrix_int4x3.hpp create mode 100644 glm/ext/matrix_int4x3_sized.hpp create mode 100644 glm/ext/matrix_int4x4.hpp create mode 100644 glm/ext/matrix_int4x4_sized.hpp create mode 100644 glm/ext/matrix_integer.hpp create mode 100644 glm/ext/matrix_integer.inl create mode 100644 glm/ext/matrix_projection.hpp create mode 100644 glm/ext/matrix_projection.inl create mode 100644 glm/ext/matrix_relational.hpp create mode 100644 glm/ext/matrix_relational.inl create mode 100644 glm/ext/matrix_transform.hpp create mode 100644 glm/ext/matrix_transform.inl create mode 100644 glm/ext/matrix_uint2x2.hpp create mode 100644 glm/ext/matrix_uint2x2_sized.hpp create mode 100644 glm/ext/matrix_uint2x3.hpp create mode 100644 glm/ext/matrix_uint2x3_sized.hpp create mode 100644 glm/ext/matrix_uint2x4.hpp create mode 100644 glm/ext/matrix_uint2x4_sized.hpp create mode 100644 glm/ext/matrix_uint3x2.hpp create mode 100644 glm/ext/matrix_uint3x2_sized.hpp create mode 100644 glm/ext/matrix_uint3x3.hpp create mode 100644 glm/ext/matrix_uint3x3_sized.hpp create mode 100644 glm/ext/matrix_uint3x4.hpp create mode 100644 glm/ext/matrix_uint3x4_sized.hpp create mode 100644 glm/ext/matrix_uint4x2.hpp create mode 100644 glm/ext/matrix_uint4x2_sized.hpp create mode 100644 glm/ext/matrix_uint4x3.hpp create mode 100644 glm/ext/matrix_uint4x3_sized.hpp create mode 100644 glm/ext/matrix_uint4x4.hpp create mode 100644 glm/ext/matrix_uint4x4_sized.hpp create mode 100644 glm/ext/quaternion_common.hpp create mode 100644 glm/ext/quaternion_common.inl create mode 100644 glm/ext/quaternion_common_simd.inl create mode 100644 glm/ext/quaternion_double.hpp create mode 100644 glm/ext/quaternion_double_precision.hpp create mode 100644 glm/ext/quaternion_exponential.hpp create mode 100644 glm/ext/quaternion_exponential.inl create mode 100644 glm/ext/quaternion_float.hpp create mode 100644 glm/ext/quaternion_float_precision.hpp create mode 100644 glm/ext/quaternion_geometric.hpp create mode 100644 glm/ext/quaternion_geometric.inl create mode 100644 glm/ext/quaternion_relational.hpp create mode 100644 glm/ext/quaternion_relational.inl create mode 100644 glm/ext/quaternion_transform.hpp create mode 100644 glm/ext/quaternion_transform.inl create mode 100644 glm/ext/quaternion_trigonometric.hpp create mode 100644 glm/ext/quaternion_trigonometric.inl create mode 100644 glm/ext/scalar_common.hpp create mode 100644 glm/ext/scalar_common.inl create mode 100644 glm/ext/scalar_constants.hpp create mode 100644 glm/ext/scalar_constants.inl create mode 100644 glm/ext/scalar_int_sized.hpp create mode 100644 glm/ext/scalar_integer.hpp create mode 100644 glm/ext/scalar_integer.inl create mode 100644 glm/ext/scalar_packing.hpp create mode 100644 glm/ext/scalar_packing.inl create mode 100644 glm/ext/scalar_reciprocal.hpp create mode 100644 glm/ext/scalar_reciprocal.inl create mode 100644 glm/ext/scalar_relational.hpp create mode 100644 glm/ext/scalar_relational.inl create mode 100644 glm/ext/scalar_uint_sized.hpp create mode 100644 glm/ext/scalar_ulp.hpp create mode 100644 glm/ext/scalar_ulp.inl create mode 100644 glm/ext/vector_bool1.hpp create mode 100644 glm/ext/vector_bool1_precision.hpp create mode 100644 glm/ext/vector_bool2.hpp create mode 100644 glm/ext/vector_bool2_precision.hpp create mode 100644 glm/ext/vector_bool3.hpp create mode 100644 glm/ext/vector_bool3_precision.hpp create mode 100644 glm/ext/vector_bool4.hpp create mode 100644 glm/ext/vector_bool4_precision.hpp create mode 100644 glm/ext/vector_common.hpp create mode 100644 glm/ext/vector_common.inl create mode 100644 glm/ext/vector_double1.hpp create mode 100644 glm/ext/vector_double1_precision.hpp create mode 100644 glm/ext/vector_double2.hpp create mode 100644 glm/ext/vector_double2_precision.hpp create mode 100644 glm/ext/vector_double3.hpp create mode 100644 glm/ext/vector_double3_precision.hpp create mode 100644 glm/ext/vector_double4.hpp create mode 100644 glm/ext/vector_double4_precision.hpp create mode 100644 glm/ext/vector_float1.hpp create mode 100644 glm/ext/vector_float1_precision.hpp create mode 100644 glm/ext/vector_float2.hpp create mode 100644 glm/ext/vector_float2_precision.hpp create mode 100644 glm/ext/vector_float3.hpp create mode 100644 glm/ext/vector_float3_precision.hpp create mode 100644 glm/ext/vector_float4.hpp create mode 100644 glm/ext/vector_float4_precision.hpp create mode 100644 glm/ext/vector_int1.hpp create mode 100644 glm/ext/vector_int1_sized.hpp create mode 100644 glm/ext/vector_int2.hpp create mode 100644 glm/ext/vector_int2_sized.hpp create mode 100644 glm/ext/vector_int3.hpp create mode 100644 glm/ext/vector_int3_sized.hpp create mode 100644 glm/ext/vector_int4.hpp create mode 100644 glm/ext/vector_int4_sized.hpp create mode 100644 glm/ext/vector_integer.hpp create mode 100644 glm/ext/vector_integer.inl create mode 100644 glm/ext/vector_packing.hpp create mode 100644 glm/ext/vector_packing.inl create mode 100644 glm/ext/vector_reciprocal.hpp create mode 100644 glm/ext/vector_reciprocal.inl create mode 100644 glm/ext/vector_relational.hpp create mode 100644 glm/ext/vector_relational.inl create mode 100644 glm/ext/vector_uint1.hpp create mode 100644 glm/ext/vector_uint1_sized.hpp create mode 100644 glm/ext/vector_uint2.hpp create mode 100644 glm/ext/vector_uint2_sized.hpp create mode 100644 glm/ext/vector_uint3.hpp create mode 100644 glm/ext/vector_uint3_sized.hpp create mode 100644 glm/ext/vector_uint4.hpp create mode 100644 glm/ext/vector_uint4_sized.hpp create mode 100644 glm/ext/vector_ulp.hpp create mode 100644 glm/ext/vector_ulp.inl create mode 100644 glm/fwd.hpp create mode 100644 glm/geometric.hpp create mode 100644 glm/glm.cppm create mode 100644 glm/glm.hpp create mode 100644 glm/gtc/bitfield.hpp create mode 100644 glm/gtc/bitfield.inl create mode 100644 glm/gtc/color_space.hpp create mode 100644 glm/gtc/color_space.inl create mode 100644 glm/gtc/constants.hpp create mode 100644 glm/gtc/constants.inl create mode 100644 glm/gtc/epsilon.hpp create mode 100644 glm/gtc/epsilon.inl create mode 100644 glm/gtc/integer.hpp create mode 100644 glm/gtc/integer.inl create mode 100644 glm/gtc/matrix_access.hpp create mode 100644 glm/gtc/matrix_access.inl create mode 100644 glm/gtc/matrix_integer.hpp create mode 100644 glm/gtc/matrix_inverse.hpp create mode 100644 glm/gtc/matrix_inverse.inl create mode 100644 glm/gtc/matrix_transform.hpp create mode 100644 glm/gtc/matrix_transform.inl create mode 100644 glm/gtc/noise.hpp create mode 100644 glm/gtc/noise.inl create mode 100644 glm/gtc/packing.hpp create mode 100644 glm/gtc/packing.inl create mode 100644 glm/gtc/quaternion.hpp create mode 100644 glm/gtc/quaternion.inl create mode 100644 glm/gtc/quaternion_simd.inl create mode 100644 glm/gtc/random.hpp create mode 100644 glm/gtc/random.inl create mode 100644 glm/gtc/reciprocal.hpp create mode 100644 glm/gtc/round.hpp create mode 100644 glm/gtc/round.inl create mode 100644 glm/gtc/type_aligned.hpp create mode 100644 glm/gtc/type_precision.hpp create mode 100644 glm/gtc/type_precision.inl create mode 100644 glm/gtc/type_ptr.hpp create mode 100644 glm/gtc/type_ptr.inl create mode 100644 glm/gtc/ulp.hpp create mode 100644 glm/gtc/ulp.inl create mode 100644 glm/gtc/vec1.hpp create mode 100644 glm/gtx/associated_min_max.hpp create mode 100644 glm/gtx/associated_min_max.inl create mode 100644 glm/gtx/bit.hpp create mode 100644 glm/gtx/bit.inl create mode 100644 glm/gtx/closest_point.hpp create mode 100644 glm/gtx/closest_point.inl create mode 100644 glm/gtx/color_encoding.hpp create mode 100644 glm/gtx/color_encoding.inl create mode 100644 glm/gtx/color_space.hpp create mode 100644 glm/gtx/color_space.inl create mode 100644 glm/gtx/color_space_YCoCg.hpp create mode 100644 glm/gtx/color_space_YCoCg.inl create mode 100644 glm/gtx/common.hpp create mode 100644 glm/gtx/common.inl create mode 100644 glm/gtx/compatibility.hpp create mode 100644 glm/gtx/compatibility.inl create mode 100644 glm/gtx/component_wise.hpp create mode 100644 glm/gtx/component_wise.inl create mode 100644 glm/gtx/dual_quaternion.hpp create mode 100644 glm/gtx/dual_quaternion.inl create mode 100644 glm/gtx/easing.hpp create mode 100644 glm/gtx/easing.inl create mode 100644 glm/gtx/euler_angles.hpp create mode 100644 glm/gtx/euler_angles.inl create mode 100644 glm/gtx/extend.hpp create mode 100644 glm/gtx/extend.inl create mode 100644 glm/gtx/extended_min_max.hpp create mode 100644 glm/gtx/extended_min_max.inl create mode 100644 glm/gtx/exterior_product.hpp create mode 100644 glm/gtx/exterior_product.inl create mode 100644 glm/gtx/fast_exponential.hpp create mode 100644 glm/gtx/fast_exponential.inl create mode 100644 glm/gtx/fast_square_root.hpp create mode 100644 glm/gtx/fast_square_root.inl create mode 100644 glm/gtx/fast_trigonometry.hpp create mode 100644 glm/gtx/fast_trigonometry.inl create mode 100644 glm/gtx/float_notmalize.inl create mode 100644 glm/gtx/functions.hpp create mode 100644 glm/gtx/functions.inl create mode 100644 glm/gtx/gradient_paint.hpp create mode 100644 glm/gtx/gradient_paint.inl create mode 100644 glm/gtx/handed_coordinate_space.hpp create mode 100644 glm/gtx/handed_coordinate_space.inl create mode 100644 glm/gtx/hash.hpp create mode 100644 glm/gtx/hash.inl create mode 100644 glm/gtx/integer.hpp create mode 100644 glm/gtx/integer.inl create mode 100644 glm/gtx/intersect.hpp create mode 100644 glm/gtx/intersect.inl create mode 100644 glm/gtx/io.hpp create mode 100644 glm/gtx/io.inl create mode 100644 glm/gtx/log_base.hpp create mode 100644 glm/gtx/log_base.inl create mode 100644 glm/gtx/matrix_cross_product.hpp create mode 100644 glm/gtx/matrix_cross_product.inl create mode 100644 glm/gtx/matrix_decompose.hpp create mode 100644 glm/gtx/matrix_decompose.inl create mode 100644 glm/gtx/matrix_factorisation.hpp create mode 100644 glm/gtx/matrix_factorisation.inl create mode 100644 glm/gtx/matrix_interpolation.hpp create mode 100644 glm/gtx/matrix_interpolation.inl create mode 100644 glm/gtx/matrix_major_storage.hpp create mode 100644 glm/gtx/matrix_major_storage.inl create mode 100644 glm/gtx/matrix_operation.hpp create mode 100644 glm/gtx/matrix_operation.inl create mode 100644 glm/gtx/matrix_query.hpp create mode 100644 glm/gtx/matrix_query.inl create mode 100644 glm/gtx/matrix_transform_2d.hpp create mode 100644 glm/gtx/matrix_transform_2d.inl create mode 100644 glm/gtx/mixed_product.hpp create mode 100644 glm/gtx/mixed_product.inl create mode 100644 glm/gtx/norm.hpp create mode 100644 glm/gtx/norm.inl create mode 100644 glm/gtx/normal.hpp create mode 100644 glm/gtx/normal.inl create mode 100644 glm/gtx/normalize_dot.hpp create mode 100644 glm/gtx/normalize_dot.inl create mode 100644 glm/gtx/number_precision.hpp create mode 100644 glm/gtx/optimum_pow.hpp create mode 100644 glm/gtx/optimum_pow.inl create mode 100644 glm/gtx/orthonormalize.hpp create mode 100644 glm/gtx/orthonormalize.inl create mode 100644 glm/gtx/pca.hpp create mode 100644 glm/gtx/pca.inl create mode 100644 glm/gtx/perpendicular.hpp create mode 100644 glm/gtx/perpendicular.inl create mode 100644 glm/gtx/polar_coordinates.hpp create mode 100644 glm/gtx/polar_coordinates.inl create mode 100644 glm/gtx/projection.hpp create mode 100644 glm/gtx/projection.inl create mode 100644 glm/gtx/quaternion.hpp create mode 100644 glm/gtx/quaternion.inl create mode 100644 glm/gtx/range.hpp create mode 100644 glm/gtx/raw_data.hpp create mode 100644 glm/gtx/raw_data.inl create mode 100644 glm/gtx/rotate_normalized_axis.hpp create mode 100644 glm/gtx/rotate_normalized_axis.inl create mode 100644 glm/gtx/rotate_vector.hpp create mode 100644 glm/gtx/rotate_vector.inl create mode 100644 glm/gtx/scalar_multiplication.hpp create mode 100644 glm/gtx/scalar_relational.hpp create mode 100644 glm/gtx/scalar_relational.inl create mode 100644 glm/gtx/spline.hpp create mode 100644 glm/gtx/spline.inl create mode 100644 glm/gtx/std_based_type.hpp create mode 100644 glm/gtx/std_based_type.inl create mode 100644 glm/gtx/string_cast.hpp create mode 100644 glm/gtx/string_cast.inl create mode 100644 glm/gtx/texture.hpp create mode 100644 glm/gtx/texture.inl create mode 100644 glm/gtx/transform.hpp create mode 100644 glm/gtx/transform.inl create mode 100644 glm/gtx/transform2.hpp create mode 100644 glm/gtx/transform2.inl create mode 100644 glm/gtx/type_aligned.hpp create mode 100644 glm/gtx/type_aligned.inl create mode 100644 glm/gtx/type_trait.hpp create mode 100644 glm/gtx/type_trait.inl create mode 100644 glm/gtx/vec_swizzle.hpp create mode 100644 glm/gtx/vector_angle.hpp create mode 100644 glm/gtx/vector_angle.inl create mode 100644 glm/gtx/vector_query.hpp create mode 100644 glm/gtx/vector_query.inl create mode 100644 glm/gtx/wrap.hpp create mode 100644 glm/gtx/wrap.inl create mode 100644 glm/integer.hpp create mode 100644 glm/mat2x2.hpp create mode 100644 glm/mat2x3.hpp create mode 100644 glm/mat2x4.hpp create mode 100644 glm/mat3x2.hpp create mode 100644 glm/mat3x3.hpp create mode 100644 glm/mat3x4.hpp create mode 100644 glm/mat4x2.hpp create mode 100644 glm/mat4x3.hpp create mode 100644 glm/mat4x4.hpp create mode 100644 glm/matrix.hpp create mode 100644 glm/packing.hpp create mode 100644 glm/simd/common.h create mode 100644 glm/simd/exponential.h create mode 100644 glm/simd/geometric.h create mode 100644 glm/simd/integer.h create mode 100644 glm/simd/matrix.h create mode 100644 glm/simd/neon.h create mode 100644 glm/simd/packing.h create mode 100644 glm/simd/platform.h create mode 100644 glm/simd/trigonometric.h create mode 100644 glm/simd/vector_relational.h create mode 100644 glm/trigonometric.hpp create mode 100644 glm/vec2.hpp create mode 100644 glm/vec3.hpp create mode 100644 glm/vec4.hpp create mode 100644 glm/vector_relational.hpp delete mode 100644 include/linmath.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 264dd69..73691a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,5 @@ cmake_minimum_required(VERSION 3.21) project(Exponent CXX) add_subdirectory(glfw) -add_subdirectory(src) \ No newline at end of file +add_subdirectory(src) +add_subdirectory(glm) \ No newline at end of file diff --git a/build/.cmake/api/v1/reply/cache-v2-8fe5fb14bc891c988897.json b/build/.cmake/api/v1/reply/cache-v2-1b82f29f01ef9ec5257e.json similarity index 99% rename from build/.cmake/api/v1/reply/cache-v2-8fe5fb14bc891c988897.json rename to build/.cmake/api/v1/reply/cache-v2-1b82f29f01ef9ec5257e.json index 92fe2c9..c753e3e 100644 --- a/build/.cmake/api/v1/reply/cache-v2-8fe5fb14bc891c988897.json +++ b/build/.cmake/api/v1/reply/cache-v2-1b82f29f01ef9ec5257e.json @@ -1079,7 +1079,7 @@ } ], "type" : "INTERNAL", - "value" : "5" + "value" : "6" }, { "name" : "CMAKE_OBJCOPY", diff --git a/build/.cmake/api/v1/reply/cmakeFiles-v1-53d8ee3c2964d8bce0e5.json b/build/.cmake/api/v1/reply/cmakeFiles-v1-d8eb8a68cb214ae78945.json similarity index 99% rename from build/.cmake/api/v1/reply/cmakeFiles-v1-53d8ee3c2964d8bce0e5.json rename to build/.cmake/api/v1/reply/cmakeFiles-v1-d8eb8a68cb214ae78945.json index 11b4dd0..4c2db05 100644 --- a/build/.cmake/api/v1/reply/cmakeFiles-v1-53d8ee3c2964d8bce0e5.json +++ b/build/.cmake/api/v1/reply/cmakeFiles-v1-d8eb8a68cb214ae78945.json @@ -250,6 +250,9 @@ }, { "path" : "src/CMakeLists.txt" + }, + { + "path" : "glm/CMakeLists.txt" } ], "kind" : "cmakeFiles", diff --git a/build/.cmake/api/v1/reply/codemodel-v2-5f54dda50eca1bfcd26a.json b/build/.cmake/api/v1/reply/codemodel-v2-85416805ba45eaaf28c6.json similarity index 89% rename from build/.cmake/api/v1/reply/codemodel-v2-5f54dda50eca1bfcd26a.json rename to build/.cmake/api/v1/reply/codemodel-v2-85416805ba45eaaf28c6.json index 33d21e3..f30c2c1 100644 --- a/build/.cmake/api/v1/reply/codemodel-v2-5f54dda50eca1bfcd26a.json +++ b/build/.cmake/api/v1/reply/codemodel-v2-85416805ba45eaaf28c6.json @@ -9,7 +9,8 @@ "childIndexes" : [ 1, - 4 + 4, + 5 ], "hasInstallRule" : true, "jsonFile" : "directory-.-Debug-d0094a50bb2071803777.json", @@ -83,6 +84,17 @@ [ 0 ] + }, + { + "build" : "glm", + "jsonFile" : "directory-glm-Debug-ab70d989331aa8f80f5f.json", + "minimumCMakeVersion" : + { + "string" : "3.21" + }, + "parentIndex" : 0, + "projectIndex" : 0, + "source" : "glm" } ], "name" : "Debug", @@ -96,7 +108,8 @@ "directoryIndexes" : [ 0, - 4 + 4, + 5 ], "name" : "Exponent", "targetIndexes" : @@ -126,7 +139,7 @@ { "directoryIndex" : 4, "id" : "Exponent::@145eef247bfb46b6828c", - "jsonFile" : "target-Exponent-Debug-c5ae450747adb8fbe53a.json", + "jsonFile" : "target-Exponent-Debug-3135f7fb60ef72779ad7.json", "name" : "Exponent", "projectIndex" : 0 }, diff --git a/build/.cmake/api/v1/reply/directory-glm-Debug-ab70d989331aa8f80f5f.json b/build/.cmake/api/v1/reply/directory-glm-Debug-ab70d989331aa8f80f5f.json new file mode 100644 index 0000000..b04b50c --- /dev/null +++ b/build/.cmake/api/v1/reply/directory-glm-Debug-ab70d989331aa8f80f5f.json @@ -0,0 +1,14 @@ +{ + "backtraceGraph" : + { + "commands" : [], + "files" : [], + "nodes" : [] + }, + "installers" : [], + "paths" : + { + "build" : "glm", + "source" : "glm" + } +} diff --git a/build/.cmake/api/v1/reply/index-2024-04-08T19-34-14-0256.json b/build/.cmake/api/v1/reply/index-2024-04-19T21-11-10-0092.json similarity index 86% rename from build/.cmake/api/v1/reply/index-2024-04-08T19-34-14-0256.json rename to build/.cmake/api/v1/reply/index-2024-04-19T21-11-10-0092.json index 0079f3a..8e8897a 100644 --- a/build/.cmake/api/v1/reply/index-2024-04-08T19-34-14-0256.json +++ b/build/.cmake/api/v1/reply/index-2024-04-19T21-11-10-0092.json @@ -26,7 +26,7 @@ "objects" : [ { - "jsonFile" : "codemodel-v2-5f54dda50eca1bfcd26a.json", + "jsonFile" : "codemodel-v2-85416805ba45eaaf28c6.json", "kind" : "codemodel", "version" : { @@ -35,7 +35,7 @@ } }, { - "jsonFile" : "cache-v2-8fe5fb14bc891c988897.json", + "jsonFile" : "cache-v2-1b82f29f01ef9ec5257e.json", "kind" : "cache", "version" : { @@ -44,7 +44,7 @@ } }, { - "jsonFile" : "cmakeFiles-v1-53d8ee3c2964d8bce0e5.json", + "jsonFile" : "cmakeFiles-v1-d8eb8a68cb214ae78945.json", "kind" : "cmakeFiles", "version" : { @@ -90,7 +90,7 @@ "responses" : [ { - "jsonFile" : "cache-v2-8fe5fb14bc891c988897.json", + "jsonFile" : "cache-v2-1b82f29f01ef9ec5257e.json", "kind" : "cache", "version" : { @@ -99,7 +99,7 @@ } }, { - "jsonFile" : "codemodel-v2-5f54dda50eca1bfcd26a.json", + "jsonFile" : "codemodel-v2-85416805ba45eaaf28c6.json", "kind" : "codemodel", "version" : { @@ -117,7 +117,7 @@ } }, { - "jsonFile" : "cmakeFiles-v1-53d8ee3c2964d8bce0e5.json", + "jsonFile" : "cmakeFiles-v1-d8eb8a68cb214ae78945.json", "kind" : "cmakeFiles", "version" : { diff --git a/build/.cmake/api/v1/reply/target-Exponent-Debug-c5ae450747adb8fbe53a.json b/build/.cmake/api/v1/reply/target-Exponent-Debug-3135f7fb60ef72779ad7.json similarity index 95% rename from build/.cmake/api/v1/reply/target-Exponent-Debug-c5ae450747adb8fbe53a.json rename to build/.cmake/api/v1/reply/target-Exponent-Debug-3135f7fb60ef72779ad7.json index f2479de..ea3580b 100644 --- a/build/.cmake/api/v1/reply/target-Exponent-Debug-c5ae450747adb8fbe53a.json +++ b/build/.cmake/api/v1/reply/target-Exponent-Debug-3135f7fb60ef72779ad7.json @@ -64,6 +64,10 @@ { "backtrace" : 2, "path" : "E:/OneDrive/Documents/Projects/Exponent/glfw/include" + }, + { + "backtrace" : 2, + "path" : "E:/OneDrive/Documents/Projects/Exponent" } ], "language" : "CXX", diff --git a/build/CMakeCache.txt b/build/CMakeCache.txt index b5cb3f1..cb48371 100644 --- a/build/CMakeCache.txt +++ b/build/CMakeCache.txt @@ -489,7 +489,7 @@ CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 //ADVANCED property for variable: CMAKE_NM CMAKE_NM-ADVANCED:INTERNAL=1 //number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=5 +CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=6 //ADVANCED property for variable: CMAKE_OBJCOPY CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 //ADVANCED property for variable: CMAKE_OBJDUMP diff --git a/build/CMakeFiles/Makefile.cmake b/build/CMakeFiles/Makefile.cmake index 22d4427..33ac17c 100644 --- a/build/CMakeFiles/Makefile.cmake +++ b/build/CMakeFiles/Makefile.cmake @@ -53,6 +53,7 @@ set(CMAKE_MAKEFILE_DEPENDS "E:/OneDrive/Documents/Projects/Exponent/glfw/CMakeLists.txt" "E:/OneDrive/Documents/Projects/Exponent/glfw/docs/CMakeLists.txt" "E:/OneDrive/Documents/Projects/Exponent/glfw/src/CMakeLists.txt" + "E:/OneDrive/Documents/Projects/Exponent/glm/CMakeLists.txt" "E:/OneDrive/Documents/Projects/Exponent/src/CMakeLists.txt" ) @@ -73,6 +74,7 @@ set(CMAKE_MAKEFILE_PRODUCTS "glfw/src/CMakeFiles/CMakeDirectoryInformation.cmake" "glfw/docs/CMakeFiles/CMakeDirectoryInformation.cmake" "src/CMakeFiles/CMakeDirectoryInformation.cmake" + "glm/CMakeFiles/CMakeDirectoryInformation.cmake" ) # Dependency information for all targets: diff --git a/build/CMakeFiles/Makefile2 b/build/CMakeFiles/Makefile2 index d91d866..f2876b4 100644 --- a/build/CMakeFiles/Makefile2 +++ b/build/CMakeFiles/Makefile2 @@ -64,16 +64,19 @@ CMAKE_BINARY_DIR = E:\OneDrive\Documents\Projects\Exponent\build # The main recursive "all" target. all: glfw/all all: src/all +all: glm/all .PHONY : all # The main recursive "preinstall" target. preinstall: glfw/preinstall preinstall: src/preinstall +preinstall: glm/preinstall .PHONY : preinstall # The main recursive "clean" target. clean: glfw/clean clean: src/clean +clean: glm/clean .PHONY : clean #============================================================================= @@ -126,6 +129,21 @@ glfw/src/clean: glfw/src/CMakeFiles/glfw.dir/clean glfw/src/clean: glfw/src/CMakeFiles/update_mappings.dir/clean .PHONY : glfw/src/clean +#============================================================================= +# Directory level rules for directory glm + +# Recursive "all" directory target. +glm/all: +.PHONY : glm/all + +# Recursive "preinstall" directory target. +glm/preinstall: +.PHONY : glm/preinstall + +# Recursive "clean" directory target. +glm/clean: +.PHONY : glm/clean + #============================================================================= # Directory level rules for directory src diff --git a/build/CMakeFiles/TargetDirectories.txt b/build/CMakeFiles/TargetDirectories.txt index 7f45a89..ba9f66c 100644 --- a/build/CMakeFiles/TargetDirectories.txt +++ b/build/CMakeFiles/TargetDirectories.txt @@ -32,3 +32,9 @@ E:/OneDrive/Documents/Projects/Exponent/build/src/CMakeFiles/list_install_compon E:/OneDrive/Documents/Projects/Exponent/build/src/CMakeFiles/install.dir E:/OneDrive/Documents/Projects/Exponent/build/src/CMakeFiles/install/local.dir E:/OneDrive/Documents/Projects/Exponent/build/src/CMakeFiles/install/strip.dir +E:/OneDrive/Documents/Projects/Exponent/build/glm/CMakeFiles/edit_cache.dir +E:/OneDrive/Documents/Projects/Exponent/build/glm/CMakeFiles/rebuild_cache.dir +E:/OneDrive/Documents/Projects/Exponent/build/glm/CMakeFiles/list_install_components.dir +E:/OneDrive/Documents/Projects/Exponent/build/glm/CMakeFiles/install.dir +E:/OneDrive/Documents/Projects/Exponent/build/glm/CMakeFiles/install/local.dir +E:/OneDrive/Documents/Projects/Exponent/build/glm/CMakeFiles/install/strip.dir diff --git a/build/cmake_install.cmake b/build/cmake_install.cmake index a21e640..0283a2d 100644 --- a/build/cmake_install.cmake +++ b/build/cmake_install.cmake @@ -47,6 +47,11 @@ if(NOT CMAKE_INSTALL_LOCAL_ONLY) include("E:/OneDrive/Documents/Projects/Exponent/build/src/cmake_install.cmake") endif() +if(NOT CMAKE_INSTALL_LOCAL_ONLY) + # Include the install script for the subdirectory. + include("E:/OneDrive/Documents/Projects/Exponent/build/glm/cmake_install.cmake") +endif() + if(CMAKE_INSTALL_COMPONENT) set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") else() diff --git a/build/glm/CMakeFiles/CMakeDirectoryInformation.cmake b/build/glm/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000..a7058c8 --- /dev/null +++ b/build/glm/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "MinGW Makefiles" Generator, CMake Version 3.28 + +# Relative path conversion top directories. +set(CMAKE_RELATIVE_PATH_TOP_SOURCE "E:/OneDrive/Documents/Projects/Exponent") +set(CMAKE_RELATIVE_PATH_TOP_BINARY "E:/OneDrive/Documents/Projects/Exponent/build") + +# Force unix paths in dependencies. +set(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/build/glm/CMakeFiles/progress.marks b/build/glm/CMakeFiles/progress.marks new file mode 100644 index 0000000..573541a --- /dev/null +++ b/build/glm/CMakeFiles/progress.marks @@ -0,0 +1 @@ +0 diff --git a/build/glm/Makefile b/build/glm/Makefile new file mode 100644 index 0000000..0b674b4 --- /dev/null +++ b/build/glm/Makefile @@ -0,0 +1,188 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "MinGW Makefiles" Generator, CMake Version 3.28 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# Allow only one "make -f Makefile2" at a time, but pass parallelism. +.NOTPARALLEL: + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Disable VCS-based implicit rules. +% : %,v + +# Disable VCS-based implicit rules. +% : RCS/% + +# Disable VCS-based implicit rules. +% : RCS/%,v + +# Disable VCS-based implicit rules. +% : SCCS/s.% + +# Disable VCS-based implicit rules. +% : s.% + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Command-line flag to silence nested $(MAKE). +$(VERBOSE)MAKESILENT = -s + +#Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +SHELL = cmd.exe + +# The CMake executable. +CMAKE_COMMAND = "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" + +# The command to remove a file. +RM = "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E rm -f + +# Escaping for special characters. +EQUALS = = + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = E:\OneDrive\Documents\Projects\Exponent + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = E:\OneDrive\Documents\Projects\Exponent\build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "No interactive CMake dialog available..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E echo "No interactive CMake dialog available." +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Running CMake to regenerate build system..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# Special rule for the target list_install_components +list_install_components: + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Available install components are: \"Unspecified\"" +.PHONY : list_install_components + +# Special rule for the target list_install_components +list_install_components/fast: list_install_components +.PHONY : list_install_components/fast + +# Special rule for the target install +install: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -P cmake_install.cmake +.PHONY : install + +# Special rule for the target install +install/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Install the project..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -P cmake_install.cmake +.PHONY : install/fast + +# Special rule for the target install/local +install/local: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local + +# Special rule for the target install/local +install/local/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing only the local directory..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake +.PHONY : install/local/fast + +# Special rule for the target install/strip +install/strip: preinstall + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip + +# Special rule for the target install/strip +install/strip/fast: preinstall/fast + @$(CMAKE_COMMAND) -E cmake_echo_color "--switch=$(COLOR)" --cyan "Installing the project stripped..." + "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake +.PHONY : install/strip/fast + +# The main all target +all: cmake_check_build_system + cd /d E:\OneDrive\Documents\Projects\Exponent\build && $(CMAKE_COMMAND) -E cmake_progress_start E:\OneDrive\Documents\Projects\Exponent\build\CMakeFiles E:\OneDrive\Documents\Projects\Exponent\build\glm\\CMakeFiles\progress.marks + cd /d E:\OneDrive\Documents\Projects\Exponent\build && $(MAKE) $(MAKESILENT) -f CMakeFiles\Makefile2 glm/all + $(CMAKE_COMMAND) -E cmake_progress_start E:\OneDrive\Documents\Projects\Exponent\build\CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + cd /d E:\OneDrive\Documents\Projects\Exponent\build && $(MAKE) $(MAKESILENT) -f CMakeFiles\Makefile2 glm/clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + cd /d E:\OneDrive\Documents\Projects\Exponent\build && $(MAKE) $(MAKESILENT) -f CMakeFiles\Makefile2 glm/preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + cd /d E:\OneDrive\Documents\Projects\Exponent\build && $(MAKE) $(MAKESILENT) -f CMakeFiles\Makefile2 glm/preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + cd /d E:\OneDrive\Documents\Projects\Exponent\build && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 1 +.PHONY : depend + +# Help Target +help: + @echo The following are some of the valid targets for this Makefile: + @echo ... all (the default if no target is provided) + @echo ... clean + @echo ... depend + @echo ... edit_cache + @echo ... install + @echo ... install/local + @echo ... install/strip + @echo ... list_install_components + @echo ... rebuild_cache +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + cd /d E:\OneDrive\Documents\Projects\Exponent\build && $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles\Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/build/glm/cmake_install.cmake b/build/glm/cmake_install.cmake new file mode 100644 index 0000000..8333f6c --- /dev/null +++ b/build/glm/cmake_install.cmake @@ -0,0 +1,39 @@ +# Install script for directory: E:/OneDrive/Documents/Projects/Exponent/glm + +# Set the install prefix +if(NOT DEFINED CMAKE_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX "C:/Program Files (x86)/Exponent") +endif() +string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + if(BUILD_TYPE) + string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + else() + set(CMAKE_INSTALL_CONFIG_NAME "Debug") + endif() + message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +endif() + +# Set the component getting installed. +if(NOT CMAKE_INSTALL_COMPONENT) + if(COMPONENT) + message(STATUS "Install component: \"${COMPONENT}\"") + set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + else() + set(CMAKE_INSTALL_COMPONENT) + endif() +endif() + +# Is this installation the result of a crosscompile? +if(NOT DEFINED CMAKE_CROSSCOMPILING) + set(CMAKE_CROSSCOMPILING "FALSE") +endif() + +# Set default install directory permissions. +if(NOT DEFINED CMAKE_OBJDUMP) + set(CMAKE_OBJDUMP "C:/msys64/ucrt64/bin/objdump.exe") +endif() + diff --git a/build/src/CMakeFiles/Exponent.dir/compiler_depend.internal b/build/src/CMakeFiles/Exponent.dir/compiler_depend.internal index 1d22067..a60528d 100644 --- a/build/src/CMakeFiles/Exponent.dir/compiler_depend.internal +++ b/build/src/CMakeFiles/Exponent.dir/compiler_depend.internal @@ -7,160 +7,31 @@ src/CMakeFiles/Exponent.dir/main.cc.obj C:/msys64/ucrt64/include/_mingw_mac.h C:/msys64/ucrt64/include/_mingw_off_t.h C:/msys64/ucrt64/include/_mingw_secapi.h - C:/msys64/ucrt64/include/_mingw_stat64.h - C:/msys64/ucrt64/include/_timeval.h - C:/msys64/ucrt64/include/c++/13.2.0/backward/binders.h - C:/msys64/ucrt64/include/c++/13.2.0/bit - C:/msys64/ucrt64/include/c++/13.2.0/bits/alloc_traits.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/allocator.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/char_traits.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/charconv.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/concept_check.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/cpp_type_traits.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_forced.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_init_exception.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_defines.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_ptr.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/functexcept.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/functional_hash.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/hash_bytes.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/invoke.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/ios_base.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/istream.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/localefwd.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/memory_resource.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/memoryfwd.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/move.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/nested_exception.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/new_allocator.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream_insert.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/postypes.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/predefined_ops.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/ptr_traits.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/range_access.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/refwrap.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/requires_hosted.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/specfun.h C:/msys64/ucrt64/include/c++/13.2.0/bits/std_abs.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_algobase.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_construct.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_function.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_funcs.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_types.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_pair.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf_iterator.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/string_view.tcc - C:/msys64/ucrt64/include/c++/13.2.0/bits/stringfwd.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator_args.h - C:/msys64/ucrt64/include/c++/13.2.0/bits/utility.h - C:/msys64/ucrt64/include/c++/13.2.0/cctype - C:/msys64/ucrt64/include/c++/13.2.0/cerrno - C:/msys64/ucrt64/include/c++/13.2.0/clocale - C:/msys64/ucrt64/include/c++/13.2.0/cmath - C:/msys64/ucrt64/include/c++/13.2.0/cstddef - C:/msys64/ucrt64/include/c++/13.2.0/cstdio C:/msys64/ucrt64/include/c++/13.2.0/cstdlib - C:/msys64/ucrt64/include/c++/13.2.0/cwchar - C:/msys64/ucrt64/include/c++/13.2.0/cwctype - C:/msys64/ucrt64/include/c++/13.2.0/debug/assertions.h - C:/msys64/ucrt64/include/c++/13.2.0/debug/debug.h - C:/msys64/ucrt64/include/c++/13.2.0/exception - C:/msys64/ucrt64/include/c++/13.2.0/ext/alloc_traits.h - C:/msys64/ucrt64/include/c++/13.2.0/ext/atomicity.h - C:/msys64/ucrt64/include/c++/13.2.0/ext/numeric_traits.h - C:/msys64/ucrt64/include/c++/13.2.0/ext/string_conversions.h - C:/msys64/ucrt64/include/c++/13.2.0/ext/type_traits.h - C:/msys64/ucrt64/include/c++/13.2.0/initializer_list - C:/msys64/ucrt64/include/c++/13.2.0/ios - C:/msys64/ucrt64/include/c++/13.2.0/iosfwd - C:/msys64/ucrt64/include/c++/13.2.0/iostream - C:/msys64/ucrt64/include/c++/13.2.0/istream - C:/msys64/ucrt64/include/c++/13.2.0/limits - C:/msys64/ucrt64/include/c++/13.2.0/math.h - C:/msys64/ucrt64/include/c++/13.2.0/new - C:/msys64/ucrt64/include/c++/13.2.0/ostream C:/msys64/ucrt64/include/c++/13.2.0/pstl/pstl_config.h - C:/msys64/ucrt64/include/c++/13.2.0/stdexcept C:/msys64/ucrt64/include/c++/13.2.0/stdlib.h - C:/msys64/ucrt64/include/c++/13.2.0/streambuf - C:/msys64/ucrt64/include/c++/13.2.0/string - C:/msys64/ucrt64/include/c++/13.2.0/string_view - C:/msys64/ucrt64/include/c++/13.2.0/system_error - C:/msys64/ucrt64/include/c++/13.2.0/tr1/bessel_function.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/beta_function.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/ell_integral.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/exp_integral.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/gamma.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/hypergeometric.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/legendre_function.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/modified_bessel_func.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_hermite.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_laguerre.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/riemann_zeta.tcc - C:/msys64/ucrt64/include/c++/13.2.0/tr1/special_function_util.h - C:/msys64/ucrt64/include/c++/13.2.0/tuple - C:/msys64/ucrt64/include/c++/13.2.0/type_traits - C:/msys64/ucrt64/include/c++/13.2.0/typeinfo - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/atomic_word.h - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++allocator.h C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++config.h - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++locale.h C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/cpu_defines.h - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_base.h - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_inline.h - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/error_constants.h - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr-default.h - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr.h C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/os_defines.h C:/msys64/ucrt64/include/corecrt.h - C:/msys64/ucrt64/include/corecrt_startup.h C:/msys64/ucrt64/include/corecrt_stdio_config.h C:/msys64/ucrt64/include/corecrt_wstdlib.h C:/msys64/ucrt64/include/crtdefs.h - C:/msys64/ucrt64/include/ctype.h C:/msys64/ucrt64/include/errno.h C:/msys64/ucrt64/include/limits.h - C:/msys64/ucrt64/include/locale.h C:/msys64/ucrt64/include/malloc.h - C:/msys64/ucrt64/include/math.h - C:/msys64/ucrt64/include/process.h - C:/msys64/ucrt64/include/pthread.h - C:/msys64/ucrt64/include/pthread_compat.h - C:/msys64/ucrt64/include/pthread_signal.h - C:/msys64/ucrt64/include/pthread_time.h - C:/msys64/ucrt64/include/pthread_unistd.h C:/msys64/ucrt64/include/sdks/_mingw_ddk.h C:/msys64/ucrt64/include/sec_api/stdio_s.h C:/msys64/ucrt64/include/sec_api/stdlib_s.h C:/msys64/ucrt64/include/sec_api/string_s.h - C:/msys64/ucrt64/include/sec_api/sys/timeb_s.h - C:/msys64/ucrt64/include/sec_api/wchar_s.h - C:/msys64/ucrt64/include/signal.h C:/msys64/ucrt64/include/stddef.h C:/msys64/ucrt64/include/stdint.h C:/msys64/ucrt64/include/stdio.h C:/msys64/ucrt64/include/stdlib.h C:/msys64/ucrt64/include/string.h C:/msys64/ucrt64/include/swprintf.inl - C:/msys64/ucrt64/include/sys/timeb.h - C:/msys64/ucrt64/include/sys/types.h - C:/msys64/ucrt64/include/time.h C:/msys64/ucrt64/include/vadefs.h - C:/msys64/ucrt64/include/wchar.h - C:/msys64/ucrt64/include/wctype.h C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/limits.h C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/mm_malloc.h C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/stddef.h @@ -168,5 +39,4 @@ src/CMakeFiles/Exponent.dir/main.cc.obj C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/syslimits.h E:/OneDrive/Documents/Projects/Exponent/glfw/include/GLFW/glfw3.h E:/OneDrive/Documents/Projects/Exponent/include/glad/gl.h - E:/OneDrive/Documents/Projects/Exponent/include/linmath.h diff --git a/build/src/CMakeFiles/Exponent.dir/compiler_depend.make b/build/src/CMakeFiles/Exponent.dir/compiler_depend.make index 58529e1..bc52bad 100644 --- a/build/src/CMakeFiles/Exponent.dir/compiler_depend.make +++ b/build/src/CMakeFiles/Exponent.dir/compiler_depend.make @@ -6,439 +6,79 @@ src/CMakeFiles/Exponent.dir/main.cc.obj: E:/OneDrive/Documents/Projects/Exponent C:/msys64/ucrt64/include/_mingw_mac.h \ C:/msys64/ucrt64/include/_mingw_off_t.h \ C:/msys64/ucrt64/include/_mingw_secapi.h \ - C:/msys64/ucrt64/include/_mingw_stat64.h \ - C:/msys64/ucrt64/include/_timeval.h \ - C:/msys64/ucrt64/include/c++/13.2.0/backward/binders.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bit \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/alloc_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/allocator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/char_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/charconv.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/concept_check.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/cpp_type_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_forced.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_init_exception.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_defines.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_ptr.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/functexcept.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/functional_hash.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/hash_bytes.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/invoke.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ios_base.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/istream.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/localefwd.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/memory_resource.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/memoryfwd.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/move.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/nested_exception.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/new_allocator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream_insert.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/postypes.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/predefined_ops.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ptr_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/range_access.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/refwrap.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/requires_hosted.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/specfun.h \ C:/msys64/ucrt64/include/c++/13.2.0/bits/std_abs.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_algobase.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_construct.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_function.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_funcs.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_types.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_pair.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf_iterator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/string_view.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stringfwd.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator_args.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/utility.h \ - C:/msys64/ucrt64/include/c++/13.2.0/cctype \ - C:/msys64/ucrt64/include/c++/13.2.0/cerrno \ - C:/msys64/ucrt64/include/c++/13.2.0/clocale \ - C:/msys64/ucrt64/include/c++/13.2.0/cmath \ - C:/msys64/ucrt64/include/c++/13.2.0/cstddef \ - C:/msys64/ucrt64/include/c++/13.2.0/cstdio \ C:/msys64/ucrt64/include/c++/13.2.0/cstdlib \ - C:/msys64/ucrt64/include/c++/13.2.0/cwchar \ - C:/msys64/ucrt64/include/c++/13.2.0/cwctype \ - C:/msys64/ucrt64/include/c++/13.2.0/debug/assertions.h \ - C:/msys64/ucrt64/include/c++/13.2.0/debug/debug.h \ - C:/msys64/ucrt64/include/c++/13.2.0/exception \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/alloc_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/atomicity.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/numeric_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/string_conversions.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/type_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/initializer_list \ - C:/msys64/ucrt64/include/c++/13.2.0/ios \ - C:/msys64/ucrt64/include/c++/13.2.0/iosfwd \ - C:/msys64/ucrt64/include/c++/13.2.0/iostream \ - C:/msys64/ucrt64/include/c++/13.2.0/istream \ - C:/msys64/ucrt64/include/c++/13.2.0/limits \ - C:/msys64/ucrt64/include/c++/13.2.0/math.h \ - C:/msys64/ucrt64/include/c++/13.2.0/new \ - C:/msys64/ucrt64/include/c++/13.2.0/ostream \ C:/msys64/ucrt64/include/c++/13.2.0/pstl/pstl_config.h \ - C:/msys64/ucrt64/include/c++/13.2.0/stdexcept \ C:/msys64/ucrt64/include/c++/13.2.0/stdlib.h \ - C:/msys64/ucrt64/include/c++/13.2.0/streambuf \ - C:/msys64/ucrt64/include/c++/13.2.0/string \ - C:/msys64/ucrt64/include/c++/13.2.0/string_view \ - C:/msys64/ucrt64/include/c++/13.2.0/system_error \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/bessel_function.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/beta_function.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/ell_integral.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/exp_integral.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/gamma.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/hypergeometric.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/legendre_function.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/modified_bessel_func.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_hermite.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_laguerre.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/riemann_zeta.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/special_function_util.h \ - C:/msys64/ucrt64/include/c++/13.2.0/tuple \ - C:/msys64/ucrt64/include/c++/13.2.0/type_traits \ - C:/msys64/ucrt64/include/c++/13.2.0/typeinfo \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/atomic_word.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++allocator.h \ C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++config.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++locale.h \ C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/cpu_defines.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_base.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_inline.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/error_constants.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr-default.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr.h \ C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/os_defines.h \ C:/msys64/ucrt64/include/corecrt.h \ - C:/msys64/ucrt64/include/corecrt_startup.h \ C:/msys64/ucrt64/include/corecrt_stdio_config.h \ C:/msys64/ucrt64/include/corecrt_wstdlib.h \ C:/msys64/ucrt64/include/crtdefs.h \ - C:/msys64/ucrt64/include/ctype.h \ C:/msys64/ucrt64/include/errno.h \ C:/msys64/ucrt64/include/limits.h \ - C:/msys64/ucrt64/include/locale.h \ C:/msys64/ucrt64/include/malloc.h \ - C:/msys64/ucrt64/include/math.h \ - C:/msys64/ucrt64/include/process.h \ - C:/msys64/ucrt64/include/pthread.h \ - C:/msys64/ucrt64/include/pthread_compat.h \ - C:/msys64/ucrt64/include/pthread_signal.h \ - C:/msys64/ucrt64/include/pthread_time.h \ - C:/msys64/ucrt64/include/pthread_unistd.h \ C:/msys64/ucrt64/include/sdks/_mingw_ddk.h \ C:/msys64/ucrt64/include/sec_api/stdio_s.h \ C:/msys64/ucrt64/include/sec_api/stdlib_s.h \ C:/msys64/ucrt64/include/sec_api/string_s.h \ - C:/msys64/ucrt64/include/sec_api/sys/timeb_s.h \ - C:/msys64/ucrt64/include/sec_api/wchar_s.h \ - C:/msys64/ucrt64/include/signal.h \ C:/msys64/ucrt64/include/stddef.h \ C:/msys64/ucrt64/include/stdint.h \ C:/msys64/ucrt64/include/stdio.h \ C:/msys64/ucrt64/include/stdlib.h \ C:/msys64/ucrt64/include/string.h \ C:/msys64/ucrt64/include/swprintf.inl \ - C:/msys64/ucrt64/include/sys/timeb.h \ - C:/msys64/ucrt64/include/sys/types.h \ - C:/msys64/ucrt64/include/time.h \ C:/msys64/ucrt64/include/vadefs.h \ - C:/msys64/ucrt64/include/wchar.h \ - C:/msys64/ucrt64/include/wctype.h \ C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/limits.h \ C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/mm_malloc.h \ C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/stddef.h \ C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/stdint.h \ C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/syslimits.h \ E:/OneDrive/Documents/Projects/Exponent/glfw/include/GLFW/glfw3.h \ - E:/OneDrive/Documents/Projects/Exponent/include/glad/gl.h \ - E:/OneDrive/Documents/Projects/Exponent/include/linmath.h + E:/OneDrive/Documents/Projects/Exponent/include/glad/gl.h -C:/msys64/ucrt64/include/c++/13.2.0/bits/ptr_traits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_defines.h: - E:/OneDrive/Documents/Projects/Exponent/src/main.cc: +E:/OneDrive/Documents/Projects/Exponent/include/glad/gl.h: + +C:/msys64/ucrt64/include/stdio.h: + C:/msys64/ucrt64/include/_mingw_secapi.h: -C:/msys64/ucrt64/include/c++/13.2.0/bits/nested_exception.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/move.h: - C:/msys64/ucrt64/include/_mingw.h: -C:/msys64/ucrt64/include/_mingw_mac.h: - -C:/msys64/ucrt64/include/c++/13.2.0/initializer_list: - -C:/msys64/ucrt64/include/c++/13.2.0/bit: - -E:/OneDrive/Documents/Projects/Exponent/glfw/include/GLFW/glfw3.h: - -C:/msys64/ucrt64/include/limits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/backward/binders.h: - -C:/msys64/ucrt64/include/swprintf.inl: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/invoke.h: - -C:/msys64/ucrt64/include/_mingw_off_t.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.h: - -C:/msys64/ucrt64/include/_mingw_stat64.h: - -C:/msys64/ucrt64/include/_timeval.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/functexcept.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_forced.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/alloc_traits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/allocator.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/utility.h: - -C:/msys64/ucrt64/include/corecrt_startup.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/hash_bytes.h: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/gamma.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/char_traits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator_args.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/charconv.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/concept_check.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/functional_hash.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/cpp_type_traits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_init_exception.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/exception.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_funcs.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_ptr.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/ios_base.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/istream.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/localefwd.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_algobase.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/memory_resource.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/memoryfwd.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/new_allocator.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream_insert.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/postypes.h: - -C:/msys64/ucrt64/include/c++/13.2.0/new: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/predefined_ops.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/specfun.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/range_access.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/refwrap.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/requires_hosted.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/std_abs.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_construct.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/ext/atomicity.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stringfwd.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_function.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator.h: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/riemann_zeta.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_types.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_pair.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf_iterator.h: - -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr.h: - -C:/msys64/ucrt64/include/c++/13.2.0/bits/string_view.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/cctype: - -C:/msys64/ucrt64/include/c++/13.2.0/cerrno: - -C:/msys64/ucrt64/include/c++/13.2.0/clocale: - -C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/mm_malloc.h: - -C:/msys64/ucrt64/include/c++/13.2.0/cmath: - -C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/syslimits.h: - -C:/msys64/ucrt64/include/pthread_unistd.h: - -C:/msys64/ucrt64/include/c++/13.2.0/cstddef: - -C:/msys64/ucrt64/include/c++/13.2.0/cstdio: - -C:/msys64/ucrt64/include/c++/13.2.0/cstdlib: - -C:/msys64/ucrt64/include/c++/13.2.0/cwchar: - -C:/msys64/ucrt64/include/c++/13.2.0/cwctype: - -C:/msys64/ucrt64/include/c++/13.2.0/debug/assertions.h: - -C:/msys64/ucrt64/include/sec_api/wchar_s.h: - -C:/msys64/ucrt64/include/c++/13.2.0/debug/debug.h: - -C:/msys64/ucrt64/include/c++/13.2.0/exception: - -C:/msys64/ucrt64/include/c++/13.2.0/ext/alloc_traits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/ext/numeric_traits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/ext/string_conversions.h: - -C:/msys64/ucrt64/include/c++/13.2.0/ext/type_traits.h: - -C:/msys64/ucrt64/include/c++/13.2.0/ios: - -C:/msys64/ucrt64/include/pthread_compat.h: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/exp_integral.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/iosfwd: - -C:/msys64/ucrt64/include/c++/13.2.0/tuple: - -C:/msys64/ucrt64/include/c++/13.2.0/iostream: - -C:/msys64/ucrt64/include/c++/13.2.0/istream: - -C:/msys64/ucrt64/include/c++/13.2.0/limits: - -C:/msys64/ucrt64/include/c++/13.2.0/math.h: - -C:/msys64/ucrt64/include/c++/13.2.0/ostream: +C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/limits.h: C:/msys64/ucrt64/include/c++/13.2.0/pstl/pstl_config.h: -C:/msys64/ucrt64/include/c++/13.2.0/stdexcept: +C:/msys64/ucrt64/include/string.h: + +C:/msys64/ucrt64/include/_mingw_mac.h: + +C:/msys64/ucrt64/include/swprintf.inl: + +C:/msys64/ucrt64/include/corecrt_wstdlib.h: + +C:/msys64/ucrt64/include/_mingw_off_t.h: + +C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/syslimits.h: + +C:/msys64/ucrt64/include/c++/13.2.0/cstdlib: + +C:/msys64/ucrt64/include/c++/13.2.0/bits/std_abs.h: C:/msys64/ucrt64/include/c++/13.2.0/stdlib.h: -C:/msys64/ucrt64/include/c++/13.2.0/streambuf: - -C:/msys64/ucrt64/include/c++/13.2.0/string: - -C:/msys64/ucrt64/include/c++/13.2.0/string_view: - -C:/msys64/ucrt64/include/c++/13.2.0/system_error: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/bessel_function.tcc: - -C:/msys64/ucrt64/include/stdint.h: - -C:/msys64/ucrt64/include/locale.h: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/beta_function.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/ell_integral.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/hypergeometric.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/legendre_function.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/modified_bessel_func.tcc: - -E:/OneDrive/Documents/Projects/Exponent/include/linmath.h: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_hermite.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_laguerre.tcc: - -C:/msys64/ucrt64/include/c++/13.2.0/tr1/special_function_util.h: - -C:/msys64/ucrt64/include/c++/13.2.0/type_traits: - -C:/msys64/ucrt64/include/c++/13.2.0/typeinfo: - -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/atomic_word.h: - -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++allocator.h: - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++config.h: -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++locale.h: - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/cpu_defines.h: -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_base.h: +C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/stddef.h: -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_inline.h: - -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/error_constants.h: - -C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr-default.h: - -C:/msys64/ucrt64/include/wchar.h: +C:/msys64/ucrt64/include/sdks/_mingw_ddk.h: C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/os_defines.h: @@ -446,60 +86,30 @@ C:/msys64/ucrt64/include/corecrt.h: C:/msys64/ucrt64/include/corecrt_stdio_config.h: -C:/msys64/ucrt64/include/corecrt_wstdlib.h: - C:/msys64/ucrt64/include/crtdefs.h: -C:/msys64/ucrt64/include/ctype.h: - C:/msys64/ucrt64/include/errno.h: +E:/OneDrive/Documents/Projects/Exponent/glfw/include/GLFW/glfw3.h: + +C:/msys64/ucrt64/include/limits.h: + C:/msys64/ucrt64/include/malloc.h: -C:/msys64/ucrt64/include/math.h: - -C:/msys64/ucrt64/include/process.h: - -C:/msys64/ucrt64/include/sec_api/sys/timeb_s.h: - -C:/msys64/ucrt64/include/pthread.h: - -C:/msys64/ucrt64/include/pthread_signal.h: - -C:/msys64/ucrt64/include/pthread_time.h: - -C:/msys64/ucrt64/include/sdks/_mingw_ddk.h: - C:/msys64/ucrt64/include/sec_api/stdio_s.h: C:/msys64/ucrt64/include/sec_api/stdlib_s.h: C:/msys64/ucrt64/include/sec_api/string_s.h: -C:/msys64/ucrt64/include/signal.h: +C:/msys64/ucrt64/include/stdlib.h: C:/msys64/ucrt64/include/stddef.h: -C:/msys64/ucrt64/include/stdio.h: - -C:/msys64/ucrt64/include/stdlib.h: - -C:/msys64/ucrt64/include/string.h: - -C:/msys64/ucrt64/include/sys/timeb.h: - -C:/msys64/ucrt64/include/sys/types.h: - -C:/msys64/ucrt64/include/time.h: +C:/msys64/ucrt64/include/stdint.h: C:/msys64/ucrt64/include/vadefs.h: -C:/msys64/ucrt64/include/wctype.h: - -C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/limits.h: - -C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/stddef.h: +C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/mm_malloc.h: C:/msys64/ucrt64/lib/gcc/x86_64-w64-mingw32/13.2.0/include/stdint.h: - -E:/OneDrive/Documents/Projects/Exponent/include/glad/gl.h: diff --git a/build/src/CMakeFiles/Exponent.dir/includes_CXX.rsp b/build/src/CMakeFiles/Exponent.dir/includes_CXX.rsp index 7cc51e0..2efb863 100644 --- a/build/src/CMakeFiles/Exponent.dir/includes_CXX.rsp +++ b/build/src/CMakeFiles/Exponent.dir/includes_CXX.rsp @@ -1 +1 @@ --IE:/OneDrive/Documents/Projects/Exponent/include -IE:/OneDrive/Documents/Projects/Exponent/glfw/include +-IE:/OneDrive/Documents/Projects/Exponent/include -IE:/OneDrive/Documents/Projects/Exponent/glfw/include -IE:/OneDrive/Documents/Projects/Exponent diff --git a/build/src/CMakeFiles/Exponent.dir/main.cc.obj b/build/src/CMakeFiles/Exponent.dir/main.cc.obj index d1626ce778861cf64b49459b20e5dc45cc0a5088..d214c7eb22ce38fc8a8efcbfb45c127ddb8c01c3 100644 GIT binary patch literal 259595 zcmdqKd3@Ye_5VL zo^$TK=dSPjUb6hM9Yg%@n4+1X3up1stkB`TE&aWGX#VA07z(w|2!*b@mje3tz06Q3 zCsfmP`10o7W+RjCr!Z7Aa`;(2J;<~6!83h4z;fNv;D&Na^I|DW_6iU0mvUdv2!#&) zQ&29i@bIo=xxuGGp;LF5sf16aurQQYctpO`z5JGp&}&bJLL*sP?lSUAVJK_y5etqI zg7XP?tkFKPK*=r2v#08p&wjXeM(ESyv^~~Pa`{IJxo?yC$4M^hcrCZ9l{@k)LT)~t z)eNOb_oxCPS4tx1rIIU<1?K!c{F|V?n!+QFmifyfx%Wu!ZIeH8d#Esrr#>M(9H$cMQvg3Kut&t$V%f;USet!v0$A7-sfM|QmATxt;&>l0aJ>l4{! zSMI{mW$PX;+BRCYE?h$=z^Lu{tW~lvBO8=#FJw)Wb+CB=vJH|gKsF}XSCNfNR)#D@ z&V}^2NUnUDlAVsMP_na;l}UCEvPQ`+LAF7%?;#tJ>;`08CHn=kQOWK?HYV9a$i^jm z9NC0q&mo(X>}6zAl1(5BQOAOMcpq7&WS=49fdKR}sj6N5WlOd*vK-0gA`%xxOU6TkYZF6~y@qU9vUib*>T7=Nmh<*vt$j(h9o-+*_dR!;Be*3i->&E9O<)u$u2`SB-vHS zMkMkZd)w4U(-vwo$SRkc~-pDY9|Nu0%E= z+4qr6N_HKxyiCzvct~;eP$1cFkkv@`AhOJ;u=z)1d6K<|tVyyrkhMzoA7uTKeU5BI zvN<#qx$=!kwmY(M$qqy|A=v_ClahTE*_32UkcDExXD1`elx!ukCdtl0)+*T`vM$Mf zh-^TzUkVl%`P_nRvt*AU8;YtBl0AxSQnF`}mCY4Cdl^}iWN#oFmh1y$Ba+RcY1EZ{t7Kn7HY(XZ$i^f)1lhP` z`N$?DI}X{TWJ{1uN!EZYL>novmTE?pC0RSNY{||;mLu6ZWVw=Ei!4vFn~;@Bb~~~f z$?ihdDA@zZnk0J!S*v7EA{&rw4B4P$uOZtY8869PTiPhur^tpR%cQB<=?zP^3$hW( z_CdB)vcr*$N_H%=Ny*BQO-Xh#vWcB!J3}@pSv#^R$#`ky${zZXuz4}EOv%2BEK9N< zA>YkHn5whhZm3yO7;(ALy}D*8MkHH|4mT?jh>$3S^^_{Set^y6X&c@y*DFB;#!(=j&m~?ngEv*<;AIO7<+WQORCL zHYVAd$i^l60NI3OA=(~sWtfy~4zel9c0(5OgwOUvmMPic$g(6m23fXb31m5vorEk` zvach{ldKh4fn+_%3MKm%vNFjoM^+=*HOLwzyAfHFWWPk#niC4Wm9e4h;zx2$|9$e~ z8MLLV9?v*|_Vl3{^DdvO<}Q)}_7t*y$^M2cm+ozX-do7%86;%?L)I@@oOViFUIrxF z3mNafLwb40Hb_>2Y>@UaL9YSXxMXJ|%c6ZJ&^rfNp=A6BmMg=sWW1Z@*r;T;BkQN@ zP)P4S!DyWbjCZV@&5hKbf&B&9xMZ&&n~>~nWK)ub=)obE-X^L{NN*0Z8oA}L7qXDt z9ykj*>TbQ=;GWH>&d*f= zdjQ#hY#O7;Hp!y=4Oup2cbXA^76)nsh{=}z4w`5p8OYXW$TrhmXJ9+i9;9mtS+Y2X zAj_7l2w9F~jmUB(>qeF**%inNB)dg0y3&U-JR}%3dtfghE0pYQWZWe{ZzeT-=a)>$ z_CQu9*`dg4B>Nh&M#)Y>)+E_-WUZ2|LDnVNI%M2kpnN|@HXzxrkPS-4`C?{#FGB;$QeXLGY;F&Zo!8$TB6HK$a!hC&;oT+ky6bT|MMTmV+!;vW3Xym6EvW=46j%$g(BlZDHrn9LYXKmMhtglx?S%C)s|; z3MBgqvO>u!kd;Z+gseugK4guOtwYu%+4ac!CA$aNh8)qB9znKIvgeR(lI#^^nN! z&_1FbzKblA*fc{a4Jm3U-Bqq2uSXLbNd|_D+mH=QHjHc}L+Jeh*{EbMAS;l=`s>J= zB>MmvKW6~>4AD-Zt1iBe3v35uO_J?_EL*Nh7a+@#EP*UnvPNXtw08`7S%oZDvTq^F zlk5s)h4OmuT4eo_-H5D9uAYC1te>`zrfE7Ps+!K>^0N1SG%+BX#}mkgB>OwEe%U-e zLY65nB4+On)x1@*-H=U6b|A7E*{qI2)-PEC*{Edo$R;K0L{=cLBhN=RF4?unHp`~^ z3uId*djQ#_WX~X*lI(S48)V&njBH#ozFK$Ptw}c3J&|=ub{MjL$&M9_u9BhK)F9g+ z*_p^TO4fmFOtL{_p$xpK?R>UDvX_u$%5M55vW+wbg3T#p zJRSp^yC%WTCEJXwOR~F>^-K0JvH{7SLdFR|K3_yOB-tCth9!F+*@$Ez8p&Ndn~-d0 zWZCkL!GXxiBs&_}pk$@UHcHlrY_r@oZ$maD*?Gu@CA$LIh-B9z+bY?wk&R0BFtRbp zo<%k;*=xuqB>Mo_q-3+{)YZ|HWZB3`7!blKmZ7qh#+RYm#g>ow|Bxm26LBU6LJ!tY5O@kqt=3 z*>>p-O4f{QgJeC(HcECWvQ3g*gKV>8eCqNtB-#DQh9!Fn*@$GXAj`>_c1cOyLoF$9 zl}p2q(8QD+zUIt>EN7Ad7)tj+mMhs&$OH<3-qtAqEE zO-UBp2kIzWUL5a(Y?EZiAPZ%R=3kF2OR`nSvL(9+S&n2sM3yVroyf{0`vbC8$;OZk zO7<^g8zlP#SxENV_`cxJLCJEFZIG-A*|211AS;kpKj$GElxz^$gk(QKHYwSi$jaoE z$}`9|N%jh|5y?J8wpFq@`+?7DS$>;z=}@~Y`HWHq#T2*Y|m zvPQ{%h-`>1fkE#!WW$m@glt4!{k(`QQ%-4bAj^{M17u~A&DbA(Em;<_LCHL18zh^L zY^!7i$VMeAMK&&11dYfhBwK}SQnCw>O-Xh&vJg#NP)9c-%arV1WLc6ufh=3HmyzX2 zHi;}(vY7`!9py>3E3yK~4nbBZ*>T9qB&$YNBiUKV8YSyP#%mt%=Q?Dql3j?PA%PMlOT2|5bgD_kFugjyCFzLow!sffka^&qFP0P3~M;rUu*U6S2~tdMRaLlgKtvT?at^faGf!hzS zqluvzBIys24TJ@oc@R`dSwyfLWUZ1dMm8u}lVG!j&30s&vPv#QmL+HXA0gvcalo~= zBO8+J0c2Tn|Mh8Po8+wj60(hQ#(WJ~UY5wq45}Y@J;=A8A)jAHHXvureUWXHv*Izx zHcM8EY><|=(=?q!P18A5R@dohVuEBK%jY4>mZQfyWaBf1-VcyXNOlvlNy&bNY)Z2G zk#)&t{G?!+A}=o@8<5T89b{Ru3CuVcsxn8iY-Id~3HWRQvNFj|L{=l&GGvXCori2t zHpg!xE89ur<;TcsBpX7;534~L9zoV5*hO7;%2F3Dyb0{-lmY*%ChlFdg}C?A|C zKvpJMDY6`T0s+d`fNW59#Z|~QNOlpjjgno1Y?EZSA=@n3Z;=g2_B^syIcvO$tV^^}p#wFVqS+?9;I2>7yWXB?FlxzvI zCdulNZIrAD*(S+WBO8}&0NJEuKS0K}XTfK;BFmEOL1a0SJ&P<)vNw?LH4a;SMvFzJ`j0&shmWOI=X${}hWWc*$}G^^u~ZI-MaS*skP zI+2aaVdxTMU2{cx8{e#WO8YO!GS(9W>BWsoHRb*X~eTb}Ive-iK^?+m^vO&of zAlo2W0@+5%PDQp!ven2oOLif$A<4dvY*@0*$VMc)AK6yPo<=q**{jILB%4AuE?ImL z_NPLS)&JU4x8YlYl<<3uL*HJ%}t%vQcCO zlD&qkP_mDZl}Q%Q2Vd7nHV;{&WckRNB&$N!Dp@PCF3B!I)-Ty6WCM~tfNW5*F=QJg z`wy~>lFd01{IW^1Tx6RiD?v6SSrf8h$-aqfM6zp;ZIx^Y*{EbsA{&!z0@=7^vyOtY zPe_)7tWYlF3XqLTR)%a$vQv1=&W)o3ix_hvR#plNS2Fit7OL_8#MQ6|zye z}UWK+bZar;+|+n<%I+1JoSjjWQ7kY&jga`b3$U$$g> zBWsfBEkKqdSGr}$awR(hS)OD)$U?HZE=86p*$v31 zd{!e@&pRP&lx(^$1RQ{R8>QZH$c7|48QHL8{m4cn`w_COlHG}HRI(?K@z+P7d%uD# zQ?gHxWl6U4vEa{K$qq-BCs{GF0?AH8mYpT?*@vt^va66aeo5%vfUHTfA!NBb3%wC! znY#$~46;qT3HA=M3CTW3Ho3dd%ce2H4T+&W1Y3w~vt)(Hw#vQdrO3u4TZL>u&O{d? z8NEAuw;?1fnP=>+Y{NSWckR(Br8ESF4?KbCL~*hEF@?BZz9W->{?`5lHHDMLbAt@ zjmg!*E66s>)xtJp8|9*Kw?gn|pq3?-XWH)|%aQC>WVw?49$B7b zPGXCcdytQ#4B?-1(m0%SRoU5+eQvTKm>w-CYRPmvW!b{Dcj z$sR>kCfOLW8p+;4)+pJ`5~znJ$-acFRkD4NbxF1mS-)h9kqt=Jh%8&Kx(ATuNOm)_ zP4dF|Ze*J!`y;Y($zDY^xRa>A50Gt;ES3O&Zj@{uvQ3hG71?IVPDM5(**VCDCEJK> zM6!F4ZIx^c*{Eb6Asdq{yA;YkF4^(OrsS1M1+pA@<#0N(T*+1=%aiOPWCfCKL{=!- zuaT8W_IqSCl8qs2l_GM&Uk{yJsU$O+U0m&MX4NA5K*#^ljN48P2 z>yd4e>^I1UBpXFGEZMur2KEyDZ$=sV%oEH*#&40rxce1k{gTxp8<1=@vO&q#A=@C? z&B!)N_7Jj7#HP9YB2n5872gsZNA(=J(GV&J_Y_LD53)?TnQ#=c&9o^H%u=5EW3LyV zpB3tDd@S)PomRF&8I3%}6b9=}6xnl)RBF zdn`dY4TbporFriAr8V}?%a*MV57J_-jJJiWGB~O52rYQk`SEmavh!Htc{W1ECi%C* zNL`tDzHHs^ws;qXLiBfN*C(F8cqC)pNZG^VGi^r8)+Hv(EIa%+{LX+jFI87P~Q>K5tHnx$2cwa+a$~X;PY+U zbm|*bY$aK0;1tHn*KM^1ldSxX1@f0FbB=SSSGD68I=dmo+ zc4G3aZ!6ac_fRVO&m$`b@*hNA_wcr7#V306sIg9|Y??+}b|qEKm5C|N;0K>>+eS_P z`y-c(^qQL4iPBR=TS?4Th~Hzn%B~ETtB#x)p~I8);Z{0q(TAgS*rgB0DCu!d`mw|V z`bU>Qw}vev(Zm-AGXb#qytc;MoxjK10H6T_E|tj*M?7nu48 zt1|3(&&awkmr2NeE4}P2UzUW1$^JCLnL*(h(+Jb`i_L|$JaZah9s^C5weYNIgz3(z z7M>w}F(ZX9vV*e5ZYo)tZMEH*((cR@c5{NV#%?Ov{e4;K<5a@AL1F9TRKkZ^;aM`r zvr^FAPOSQ5+qQKyJgje^*@hMd zG@Lzl;kIpfzVxT^{O()idBM-+`N_A-^Q-TW=MUZ~&qEK%^WO%}BU>eZ_;Gpu_8;Z> zY0t{@bN?dG7rY|RH~vGOf9nl-e)WVr&-ifLwu#q1P8#!P@_>r#B0aAtul|n4^Y4%f z`?r)95Mpvsa_bthOK5g3Sy!2RAx+R!H+{QZe12|5A5SG&_wg)d2XFcH_(HXYQ-Pg? zVp~{TMcv0k=9U>bGt4Q2Ei>(D*<&U9=TJ?dw=Z$BSE5wsr7tTkq=TE!cqO<&?HSTb^f8-&qjtTj&E5eZGx8-$=f* zk?)(xce%}9?(F8f+~)ha&39?#`$^@yl=2}VKezdi+x$M?0^~N|&n+FgJXALKtg`N@ zZ0>F8ZfjO`(Al-NrmerFT_xPt-d@_gjO(MMrM;!Mh3lVzs!h`_)UmOqj%%AcRw|XY zp60XK)lqlzIg9&NtZ3opP(mjzg~aleEv4@r7bPX z&uU(_%9Xjat)s1nn}2D0pZ@J!$tji659geIx$gK!opyJ2^cu&PcK7x4s-C)}rNjDv zNlWkI&Q9ui9V|{~#qECAq0^GiKJvU_iSBOI4=KL1y|cO3M3;B;wybRFHfI%WD_eV2 zUPw%xsGQJAWpkJEkv_B{6zdD<*5f06Zn>&#lDFKR>o!VeU4&|#9MRdnc4cQrU2j`g zmuf&1SJ&I!*1_$Bj_X_c6CG=;J$+_Vqcd`p&9OcMNn#*bzPed8Rc*7PWlc+aO>=ki zYHI4;pd9af8qYE{Yq4ic+@J5qCd*przV+ zt0=!JwnujxWxB_77*&;(oy%L=**u)FwtvbA!I^_jNqIv_I8l|Sinfjxzn=K)3Vu@=0Gi^$MGR|BREY zYB|SvzN)i(b#uF#!t5biGRItUdkE3WgjQ4@HzJ%LdkE58>n2)to$Bu1)=rA6Y3}K% zZ|&~vTghXN?Ow{DJ<*-dohfy7R@d9v-NM=M&p35;R^Q#+(L-ZGup_%5ky*K~Fj^^z}n@}y(!SAA^SK@AO=z6hQ8GIU~uYMXng9&0*#RAs{% zyURc2oWq%fTnZnm=Ix)dui;E+F5=pBaFH5({8N$UB2^1M6lpG!X)Y3JE>d;mG}Xca z&P0aP0>g(gO|{VQp-fXPIDDwnY-wKZrm|W(QH?=mu4P%TDm(wG9MFL(FaO#IRYr=? zDbaydHP&f0*ln6eZD%j7MU+W(#J1{|HMgrMb)aL~dV18HR!7T{WxXzQb*;_IThwUB zdU|1LmMP}UjKStijV?4t_)7}^gmdrCI92~dATFIls)+84%jut>mTILI={1Nu!?g4Y z#34*;p-5{XrnOKx)@rHN>7QUW7GYYtX*xknOE*l1FfH9IEmE!0Kf$zAn{-Gu4tIuW z>D8}8n3i4x6XMxl`_`@lbfmFEk=8l97SNJ*RX~z-Xw>=0WRebzIv<%xwLn-@)`qHW~m}s!Q$hWPVff4a->n5P1RRgexzHL?cCK_z3p~yrlmz!hX zwyyG}Z7t_?b$0Vgs;Ik#YOuGjyQQbLrKgQo6)Lv7d2OP-WwkzC+}5$&ND)-ml4?p) z7a+xSi9^t@T8vQDYa;6U&Po!paY{~K6xr-hN+tS|hgRd1k2)U8IFc@Sin=L(Tq-^> z`Q%f3(c|Y%ui>NxYLJkKS|HQ1Qm@_BTF_Tlr|SC99C01+Qooz77S^;ZcNr<~@g1bs z5WW#JNms8}(bK}-rFmIr$e)J0+d8}3dTEA-jPXPrkRz(bR^K+oSRdMcWzUsQbqnz2 z19h>8yB|AIU1fqN$*!s_B>;)2^CF&nY*xvD$z?FMb9EOrtDY8aJ6Q9Q@Nr7@S<6b8eN?|E&f_GMKli>yhKeQog&&ww~+_@Ns$F1 zhMSa(N>)>yTnh0x5{OB*#GOJ4sewyGE#whB5R+s{FZ40vdM=fENqN$1Ci4O7fGQbEQyHp7gLQg_8252Vo(k#^OLslAqMbEQONmPL0!2NDbFADk)ET z@UClKO;_>7ooiaU_0_i8RkXW<>Ll@vzUJPxPPO-Fw;bzQy693|ji9tI5*S5n413)j zbJ^?(d)ghlLW`kTWj-(-t8vH8)NCXW!=_{uS63j0h3ZGnS`7>A1a6Vr<@}=6Pl`zJE;4&e=5?{{o02jP2Hb;DALsZ zSnb50)YsC@`z5@ZahEvyprpCCnTgs|r5VGV>jjC9Wvlv}?X;;aBHBo`Mrlpq%h8E1 zM01WNt{*5L`O&=R={637Ss*c$MDKxZ8e?j@J6F=S9~sl<4r>Sc zSf2wHIWfyWy@b(OQtK_Q30kt~;&8p_MP4d7@|9k!xTThhY3OKML0dzl&QZz-Ez5OQ z*rtx8jTG<##hJX9cdY2F=rsGMCeBu?wjm^RR9$CZx7z(DJ37Xyn7qiOOr)AVNW+|3 z6)dgk(A>L75Q*Km#W-sa<4n8pYo@$M=a5X&F61g71d0N?0?;gAcOW^ox(nh=snkBC zJLZDe6YlEn7=T)k7@(IT_5?Ka^1}diLFSIZl)5CdKzYKPsL9+NgNB;GEkF&ub`<&1 zQF;V3DmqHvtZL|i?y|JGy=}SZKv+p?(^f`so@~c$E$*3e(lW2tL+fuloaLA(}^&hTnc{y zAsY0;{uHfzVZUkTdbl;cp+8j@NhO(|N;2Ohq^9*^S{Kr#b7x0$doArwsdbG4dN-Yh zczgel9PQ8j=3a^)VehkYOerm`c?|#qvWZ^Za+baG$}u`c5oLVGI~1H?ds{DA1GVDT zmSw9TiuX12J>_;<+1quzy5+BDxD`C0;W>8^I9F8<=ei1&A>N*4Z9UIIqTD!iB$mLB zg+i!Ey%EEv^jxctmZ$PPEs9ckUfrstMMzhRS$tW4L#{9{loSxUe&#(Yb>W{Jt*-i$ zqtzvUa&$%WTGdEsl?ITDNimoO6BY0U3DK2TZ%buc7puvNMSpOA^+1bGcF|aq^WDC|8Xm80prGNfot}uCUyF zVbi&tG>!_+u!z*6qmQJR8m&;Eet7? zG*OqEXLqDnaxPMN+C0c3RQ)-Qw@md&3|EG36S};kr?)F+uP1p4{BlTens{;byMi%n9tp^X#hKsd}ouV6)rH&NU#VCB!bYpr!Ow zTZ>5*1{BIO&kK}eDyh!B8~fUh%ICIAz>K9w<-5_;#TW?~GwkINC#GCWmqNOLNjqF3 zhjfXwrgIfJ%9NWnfz%je=U~dJ+HPK00*O)nZ2Y1?Jh(a4l0?;-YIRI?QhfQY=KUHy z?zm$vr9OeD+G+im7NV^5#C>CCniaw%>~I6p&VpYMHR%hijUI+B1MxX5~t zxH{39bf#?m=x8dWaxHmO?{DfcJ1LI6AtUw3mlT&QsQoGh&A28bwV#vX*rK^Tq)quJ zjFbb5JNtM;h)#oU(4I?*)ou$$^F>2a948Wt)VSJS2fTZyLd0hi+`TXN^x z(ReDb_KCwmD&gR zd~0mm4rW_WM)-{x#xIVBEaef{YF!Li1dMNJD6Zd{=DwbmR0e73(6>4z zF_}?&RqmLZuQ^eBOYRte+6yv3-wZG(>b{#h1`V^>rpj%&iRu>yY@~i}E|J*qzLcJ=5DQc1Wv1qrZQcpv>GowPKpi4?+ z#r6!#8Tu=-2(`S zrO2J0t^;zZa)+at6gMPA9_+}b$Cs2^W~($c(<4|KmNvcgspdQ^?CjBHiz2pUHSdSL{(Mhdk+L|JD6uCAcht? zHj=i`RGs)yC3GWYCB6IAL(64;0g_+v;__oOy|&fe$*<92EV+RiF-NxbbnzmVdsCl& zG*re=L$Mbguw~@dygc{uDh5(?xAarWvja&X;8wT$p&!wxXg;fjvrK|IqJ}>0;>Vfs zL)lnC?*iJoGV!#oRu2iNHm-gz3w3yE6|9lO45*lJauW5x*z88ke<^R2B3LuB!MYbUny7 zarj|d5n-Nl(7hqB4@&vdzOlC`{Em`hch7XN;Qk)z@bJV#7^RPcAonwUk%qBu?TeA+ zDPt=FvBsdkIl>XT1U)=bQTh;L3&l}5kn+sJab~Z`o|uE-JTLzAol&&9l^TqvS2+@8+_6a28 z-+c`xq}D7cbyPn}N%X>x_R;A^uN~aP6Up2ptSgcqb4IF0=(M_Oz~(y_sY|M#*++9G zG4(7z#+zi4;&lS*aWB)7xI)x9c#m6vcqYuQMSQ?}B>HhWEr@sYd?{#jS`3<-E4@}>k-PUc#@3e9fAAT;8NRH>`h^lE4(+HR7JYwt0`ZN-$??t{wY5+ zi!AAG?rLpY#;<4aYrCd#6M$^^bDEotQc^R6Arns@0V=x8#}>H?Pyn`2M!vJGx_&xnr*xy~ zO5^T(Bmq4t`1YJiARQMUNJ2K4q~#-d%RZQp%+eF%66hx7d{?n$Io(G~%Tf><)uHY{ z)tgTdP-!V5_|AuJ5d=Ecbhgt*Ep7REkC`P&q02K*ihyVPp)kq0>2oI|Iogf9Q_1~>!*CcD>IFkaKu4&wwUcf#>q%wy# ztsk@nlYR;TwRG)K_bn+E&bDrNTw;?6ah1kXva2^Mpq5s)+DxQ#j~;H4Vs%3gM)SpV zQXF^kU?g8OCB=cDDZjm%R4WO2MJb}B8;oINL#;4^QK=R1%|feT;_QViu4%O8;Cey3 z*Q|$=21-q>v(*#y(9+2(Fiz@4121F6GTvWL1lH$ji$g0VE$Drv;Hq9}nMC}hJ!HdN z6}e^uNFQ#G^!WY2U23URduS$5m)2_Ef%}=`!AmhMK^Ith5Y;b17W1Qyq*d2N8~b#% zd9Hnfpt`H2V@X9$qVBNb%A63KRlu1$tSin59kBfH1D1#C=}{Jy*#Y_ze<+lZIWwHO zaMsL>n*X04*FqVuPIHWYK>24u9^+9SkGr)z`}c-@IMly$4+w?$D~SAiBmL)Z5%TZo zA)yd|6Oe!Rq|fs4m-+a2DgA9n{yrZ6{(=t5=$L=|j|+wB>6m|?rf(`Y(J}x2hy>c{ zn15e5fjAxWZ~aN3&?R)tzZWm1Z_Cm#|DMnk3SCFX{QGcoD72Z5`FD6lD0CMc^Y2S5 zL!l8m=HFBMLZK(=n1A1)|6_E_zqBw4y++6U%ZX0X5C6_v8w!0&hy1&k{_~%e<=?C5 z|Ci~QfB$}dD8zpOhJVlbRw#5R9rN!E^uK_P`S)-1zl4tY_pl2?A^xo1Ww&I6!qj>> zsRNc&HRKe}pTFQMISUpYzVPt8oWoZ4_I0!zw~`+~ZCggC&E3mdkL&1MM$bOy9JVsF z53BJ<4edWRYya)Iq@t*VmPK9Noy$TQzsTw&5avE}pd#(`2J8y{Y+1%_yIs!cyA;Gu zqu_e_pTR*Wd>aLGGa}1c=@Vt~pVEm^rCY?^UA^7Dh1+*ye}Fti5+_S4(aOeX5IW zAI!xyc~GUEn~~`Z=!h9%ou6!aHjf7MR$aKa%nK@TuJZmU$Z)VPo2q=ERQLHhXne!V2tf9%4%pCr{ zGGLX)EK? z%w3yEBmN{&iabkyX)BcRS>|q>-}oygzO8pfTTA=$P{!w4fo0dyzHUY+n!Pj0#CM=i z_EBV?j?IYfKA&Uv)v>A;LK!onyO(fmfsr-QGoyQ)&e2smnj8?ym=)dO4Qg@m79*-6 z!%>~twZAIdm1y8Ad+1G$4N zaLnP+JwDbkJ^Z+0MqYG}I#LNYQgHB@XD+Ew(WFq4SlqCrrnb5`l(8u4ox?KUq#*J$ z3NpBobif|aM_lR*MSo2qq3~OD9_RD$77F4VdB{v2UMP_>mnLfK%B!o+TySPy=(y<4 z?BNt_LFj8~*}_m!TDB-uoR;N>5^33yp(Sb9Lds`(TDBl`Vj8xH^eWS`1)=J+Y+>l6 zv}{qRE)C14^cvE#1)-DEvW1~j(y~RN)6%m1(CKN}k)bowvZF%Hn$4&wt)ga8T-;Ep zo7?iJ_sfip!i2sGFXx3$OFGII*O>O6O*kE+51fS67vk*Hiy1s;Es=X(y6_ z_NaFzEh@sxDTwq^puGp)P*zWBNYtL9O|Oo6SFy%5tZ@r#sF4Bu?Q4`%LXC+Mt=JLu zo?ykNS@AWYs1h}WRND2mMOAgB)wPwSiA2fbqT&;^iB3^0vR+hQUt7MoqPn<8IT zqTa$NrSlaEA{7+)4ML4oHXTx5+)!GoniF~A8@gP^WezSbsxxh-TjxJ0KsjAvBzmIW z?VR!*obo8A>|CSsz(aTj57$X~sPoh5je7rKD<83yonpd@Yfs4rARm2EFQ4?nM^g|v zJ&lD71d&ok&*(wrt8Q8m!Y6 z&y9NBZ1Ehnc!jf=%Jrn62BPwsL`8X(X$9v+z2C6@y{!K`s}IH0{SV9e&0sm}XmqQv zE%SWQ$tlx@n*3g%^Xu1%80o$hG;L@@Rk<0t27>180H@t?VUqdOee~DS5)&v zMI+0%qu%e?-d48v54IOD0Mp!J)=iw$0OQ%981#_S$W&BYRBzhdx~O*u{ei6T5fnte zMnQ6ePo-S0GkJN`Yh~@#tbGw{tG=oRFzhpE!luCU#gVBbl zcR45VT~6XLPC|_@Um*C{E}dN=%ImAhdP!0mS5f=tG~VYlj?A*fP-Xc72`Q1J)YO2= zW4W&BtD{~mSq`5}LF5~phN@(qmNIz7u1;-Em2O>qHO&U5nSGD?Ijdj8>O(2iIen?# zu-H%i`%!O{)n8!scb&SM8C4dHdT~)jMMZg?8K-`L!-qwt(_a(y4x~Rk7M@Q*q>uvL zWmUn{rHQWB;<7~XiQx3Q`l9*}f2@ZXQ%W|X zM^)eN*G0WDG7_$&Akxm}lyd?B`pUObhZXn}s(&_g4IBEcH00N!Z#T8cQq%3Ok9vP+ zYp=1j&z&{Zkku&3N6vGuT%}8OTfQOc?M;8pD!d;Bkpc>IsgydOhQfEdVOjZ1yQSQy zZ;E=Sv-(-AevVYI?aYo;aqBI>PVYwc|9vJ}=-YYKV}h7#K(ZjE|FZ0K$_^mGbCs$ETE$ThCpqTc`5 z(l)lV`>x3a47RYk`b1T6d4;a)+x3McBt(lbwc6GEmr<{gY=%##Ao5LTU3o5j=Or6d zxnSm3QSSyeb2FQHMVe8z{J>vCsiQQBl+&efQ88cZn`NlZ?yqqXR9wMQCl{61*PUXo z(ubn+a_Mi^g%6`Z4ZfvxkWtL@nVJw6_?H@_P6KdNeQmYz)g5vOF0ZMnD6*^h-$cCu zwtFcBksq*4m2o}_g`f0C2VU+iTC6jBXVklkb+)k1Q>?=qlzw14v(_;!@UE!$CM*4$ zl|E)A4nkoskcPRMzB}q=XEUZCvXBBbO!$FFqr{|fPt>bqrCL@xot0EMOe0a*G2_a; zwExGF-(<Q8g?T#~57YH8E8W3L53myU8fD%L`&**kpIP!HmYifszn$=rFmJoo zeNivIJ1J#R5ZRN04D3tFyqU}Ik9tS4j%PoopH_sQSWS4>SU#JS&4&C zxI9n+4W^bKjCwy}`5RdNE|%vFXFm{$G%Pl$JVfgs)_Q@p##u{UK429z7$^NU>V3kZ zA^H=UkzFXzBb*wHIgklhFOAUk56Om)Vyz<9!f`@*$u4;wj(T5b(PkE1!=hDO0vE^x zte<`t^{!^EYgy|i*5V)(Zjye=H*WepjsGnED2tD?xa$Qz3Vw6Kjn-( z$QhCCSe=TD*lK!0H)gbH8t)%z|A%dU#5Q-@i)_lqt4@VYTQg7U7K}D+WBpUqTSBJ7 z6%<5Puu<7q)u}M*TI^H0#R{vY_)pXNhppbkRv%!iu5tQD(yA^0sBWghs&T+GQSW`W zI>lDM${3Ytm+?x{5q#%+_ zfu4eb-MS{&2+o#fkNCV&CP&REt)Vo|?CD-B(>% zQ(ob3%F|xQOX4DpIPH?xB}(ktV}a?w|3~9Lr}7e~GHaeKQXnaHnkrFgbfGc&x2QLt zOoj6(h@6qmsIvD3EiW>bUygd0vgOO!@`KY_{(|Q1D#|+K?@{j!PT_4%VV4}?5I?hN zYr#3h+O<9zk9uDtYvB?KBIl&A>l;@&|KcfF-@Fp_ZsZhh;S^p?mqH+!FPIkJu(2hw zp87}B+i4$4Z&wN;U!y>GMU{Y`%J$2Fwyn2bje4uub~oGpSqj^J0{;&supWCY>OIG) zjBzTv?3-MIKv`5$)1_B)ioS#+SNRwGuSdP3$#(d73L>X-D#|A+P}g1V;>!(LHK(YR zy)g4nTK}?{OWDky*^Cyt{?YW*FA5()!s)Ia--vqKIQd!oQS$py;Lj@=X-iR4 z-k7K`lgUKXD-*hdLy)iM>G z*K!c0e>Md%F49^$Pt!@oUR6i84s}}&#k_57 zZPvkLEtdkYrh2xrt4zYp1@d5!_=`>O70Icw5F~dEyOn^ zjIU?LyiIKPXKeRwwyUzm#)VzmG1MKwSuu5s7)@F(J5D$`ZP9Te$vj2(n4K&oyGLdU z0q7plXxg2>qv$o5FG@JK~g%=E^i^`=0g5lhyw6yB#-XIW8wFZBebQzxW9OK6BuR&lVZ9Sr z&+Xp1+y);d`f^M?M`c`9UROl7qIDnKML1Cty#>p6zl_kXDTJV|^n*Iu-fk&UGNS5n z9(ZIRTeLi#w7DeTJ*J*Ra`~+(sxK}prYp_{o25NsYX2;y1V8#wn#EwKlU0^XkKZfiUCqMRvheLJ>@NYa+dDOxmKXD$Vf8<=`ahjITvnHW zCV9B3*giqEcg&k}IH~SLL1aD!fs}DwkirN*Vnk!BvZ!lfUd%h44W7jYFHB=lwK?#G zUTbIrIil7n-(n%MPt1FO%|FcMpJDTA%;lp{`2T3hZK{U!%tLU-#rwv*4_NVktoY?4 zY(bT_a(2L5R+~$xTawP+elhPj(he`CAkv)14(`#h*Q_yFZTrW(K{jo+{M%WOg$h=opBd82}Qqn`Y8HsjVI=hC*t>Nph|lw8CLAuVEo&<5UVFofJUn*j3=%BvW%zK`b|0^f|zD(XZ*W@8lvLsPjQDh!V&(m|Z9yc7q{mTV0FK-dqK9Yh+ zf&$$DV8F0yW`Den?!v!&~)77JT94+PJzefke{HJY>2@rS!_*hxK5{1ON<*R`_ zB{d?Q$>T&CON%OstE+2E?4|tiG4&vXscWB_diz>T-OCJOvjQrNsple+s8KG8sXLVc zY_Itj>&0FYHOj>)Q(kCNF41eRpt8M}lnACw*I#7|v_DE?-rGk~(|eDCNaQHnE#1Yx z?Goe*)>^2wmeBZ5vf+a$h?FL4`5RuKulD>+vSl&#%(g5~5^kd)a)C=OxIwB+YZI_t z33jTfZrRQqZ0Aw7qeinNJJm~6Ll^g5YGU35>%POfGYV{xmD^zODmA*Mo1cVz#4*!O zYq6bLXj*9<_7BI5Vm-D|f<~tyre4x8wMNlKd}+-4DP=gknS#i$%R1cqCmUw8IyvS& z&9cw4>}yUIRu3#|3^&HSPgywQXcFFu0zFN^U4OV*=SN{H>8iihq;yKmJDOC&$Fp*s zQ&v+pCg(rqiC50LYn@8#AGUE3+qh2JaO(lvjD17qdRN;xE#^JUHXdagoITkF=S;91(Ep_XjiCAxSZf}0X$<&+0pHEZOT+*Qm*ap7?k%1f^PXgr&#=i!Y0|kuTBDsMfAgvdC!W&UhPrzD{!nwwJMdVtJfDI{ zH3k0Vd8#8*WlIuO;(Fz*nA$kio*@W6G#4hz0urzhv^+NN7o3G(QK0q^ALMMnYKja} zi@^52hn z%JLfbSbaOz9yvn^nB1V;YFz5j+aCI9u%i0v%JSmk>IS}5t!vE=6CE*czvIaBxfDbe zQ=o@k)uL42;J8qj`QapO#7?kYnE@y}-dQNcon( zp)GGu!FsJb=ACjpW#kMBBIi>O%!u#0fJu|GE>DkkTWS%0GwVb@hrQJQImu@@$w`;w z7bvz#QrWWw=+o7nI%Pl6H9FDMVs+NoIWceL*C=c46hzijpuM3gL+w?k@`idHFHxdz z3z%-uAM=LT(A{k4X=zBcAaxtY&rOOK*w)7OexFTDQ4r%+JEzd*2llwBl`XEWriZkv z%Fi_O<+(BMP!bI`e{sOa~y+$?)kzR~_> z%)5!Tf6m$uIBk_QpN7IY?(PR?I$+0GIiJ=)BpiN+g2;>_oA(rMHwN@YpV7X6#(&ZY z&!-?#D7E=C6n>oozxevK2E1MVt(e!!7FM%`Z#xTa?WR6c;9KBlNZ~2bftYs-Yv0D& z_d9Jq3Wa&Q)+Nn5lWzr9n@jxKc!aF<_)#iHslGwbLIfYj# zP?P2^#Wv5%m>OwSpzdR;Bh`!K*jQ5CK)cnhA6y#q^2tv4XbK`#Y|-xrs!CjKXhqYA zF4L9hV4}9xy}}incNtq;PeC>tb3&yR)%32G?SX?a?^i5$Ck2tM6hO-Ax<~4ngxAsj z7i+!AS|2;DfP#4;Q(b85`ng;W6u!-r?`*D5ma;E4(XKqbP^{iQcKzDq>57=wUqX30 zpMuD>6zGyDN2)+gs+hDj>Mz8NsVjBYcCxetswpck<`<|F^?VD#K9Bkx?PVv(kEJb1 z)E<@Z{QKRQH#b4K+L?k#E(PFUHP$5SnoMkpK!wv1&^~{A zEnWYy#pl`Lo6@4}nxtg2u~BEk)h!{L)DM%A(vMtP)gL9PYHsy^9Mo^9sHfXZ{PwLi zah>kdE_Gg7*f+;ruW_~a6Po{*Pyz3zAo2tSu&k1GmeP)?x$9%zhiv5&wvtsQtjPL8 zD`HB#fv$f^F?>7)kveHYO^K-rM9WM639?Nw?>x3Jz!vx;OS&lOrbLw!xMZ4UaJez& zy}*`VWXu0`mi;E4qKsfUX@t2+yGxb`uauHBej3oIUVH-G4Xh|yoG?%8-b~|PIc4#D z3L@8003(g+fGMUSZKS5Y7VP{i=8dqOKd_y@vmM^e(c57uOsIPq(DZN7Q-dp+UE><P*pUkgXM#ox z-hZ&e#V>Wk^{Yc((2FF0rISo6Yh3#4Kua`9)8ts)P)jNECp0LIo>Cf$&5Ku18L}u) zi=~6<0EQQNaS*U0zvFO6Z11IP>NGaRtGM3(2UC!>-)MWmvf4uM(4fn3XW$|=kW1_5 zyT~b=zfUNL99$`i>0d7Tx0F>=kb{P?OzVp!uKMmyU41sydjeIVZfxkw4c)csXmdt3%p-qbM0qolt|Otxfde^}dbj!P13@YCF~eOY7mzEqOt4vj7B{dE0b zMI|_cf=E9FFu}2kZkjct}seGzMplA=#)-q@2EzV4+TGTh6(lsrO znyJ!p1L1FD-oYdpKAeI`u{0q^Lsb;(hLOMmVA@&Z;efE&Y4c|nYxQ@5QYQ(zZ2w+o z+Z8P+X;&eS#JtQJD&7thME0csI=)JAz`*<+3v{6@O#_}g(xjUakNoP|K z0e_6;masy(RXE)$C?|rJ+pvSN?MXfC`ZeT)%&wFiTK^On z3i-~KE!9&o?@yeOXDNuh$C*$ss4CC-iwfyE+96F;Ew#A-qcQ)_=T&_0RMMyp+W zKcm;)t{|FP%g-iTCS7a!xn#?*?eKie`&liO>sAUPk5ix>pykkf^{51+9r=+lx-24T|C;Q0Cu8&RVsbtLJ3lYQyxe-q!(kLePNG1M4}mIB zjV!4i*i`De_`jHU0b9M8t^Op1)ug&ewq?ukH+oovZ9UDl-b`UDsXo}2?+R<@<-pKD zK9z#5Uj7~!TZ59e2FCT+iXB5*G;`T2sZ+MEPUvy%A2IKa1}f$~6hx*dfQs<<%hZvo z4L|UEN~&rK-k4cRYh*VhzDoO_ODWO$6h!JN(24p>CAC2E7tC_CoAh`FtvT$D)@yYC zpDka?mTz#DRbG{Oc~P5e${Kn-<~`1ao?=52DGUXwKUiK{{r?P9g19x{FP7hk%_}&W zk~@w9wOBrh4zyR~I@##cfL~6JA?P}shj|RE$aDx*{f5|18)Yl-HZ_2 zz_BIzSIm2rQ=8z_KI7DscU2QfnUEdO-->yAHIm{!6hw}q0GgWIOfiYu2LCoa|HX=@ zvSO!Hls(#d$Mk@A==zTpzsHK3rJ}4qqv-nLzhmB3*8CG|{zGcYLc*;@vt*?WK$HHv zwEuSsS=pI_$YB&fJ6BGVtufh@H8dHxd4!TCt@i>A&4{QQHg1CW&vZhr@b3o(A~aQD zYxBP`?_XTDce!k{PPJuI#ges&>hk*h1HI|vMlzJN>3pcuNhxC+$VY(@5$#wPP6diy zrQTbv_n(#fIOg3?#R!j35cxY7NR`D8QVersB=!A~|51)kBV#*I5IKkf=p?D_R4uKp zpqsC>Y%Q;#%Xr{KdrLXcTtFsFBdp@UUu~_xLtUCAWwwS)E?4GP@>tkEYJA@R%M^F$cPoXM1XjNr7 zX`8KuP+S$;cZ=OIvJE05?tPn$U%|$2bjDR_0$H-EuJzA|tGBz7jW^issF@_e*8j!U zw@K@2PYQHXY%a};d;6bG>IYL0Ihq2!y{2}Ud`%8`nBvk zomWiSraF=fD7s03AJ&P)y*t?AJ#6tsXL0)ru_`lU+I~7a?){GqZDT{bpFufL^R2&f z2(+TW7@ryUjwYq>@f1WFQ>X{3EilqY<6b|jpU>*orce*Grr>xVi+jVY{~+uCC51i= z`ek(YM0d}4Tz$h(SDG6A{r7d|#NnkWeSL-x{_YT0572?Cc}8w-9G)Xpde*}`#^DiC zMa+|KS#fxJR0A_9>=cIwM-?&Gm|u#+LzEgAm7U}2vo(-0v#+{0KM*lb%1!8;Lt=DfI9#ir`mR4beEm&jkplqkU7aql{|b|YJR zBH5b%sH`45ILFS%HnU_gsl@Z*-Un>>e{6Wavyw{ug$&DKDJSlgk)d!U1(DO)q#I3= zvP7DcE4aSjC+=O!%9pe9uuz7q_#>058Z2#{d1yn`=f3fMpJQud6sS*SzhN!foYd(j z+)W4GkG|x;jN~&ZQ1ZLcfocOmdD9p7kMEn$3P)RoN~@p>?X;5oet^!IX-{?j)9?pM zK!cTfj!zZmpwvu!6F67Os2xZ>;vFoB*nU*z50L_PcTchT0S51E9vVRILurS__dRJj zIcF&a%9|~8fbVS5f(SpAez-K0bb+UfafFmI>qYxdY9IWw+rI%WHC@P zf-a1!2aI*K_}J9;qPTjbIEfnN{J46E7_dq7$hdcE3pwIU3L^B^Byj5Ir_)U{QR&%b z&{1*kJFN3P*4Zp|;CW}IW3u-Znum`T#_WQvfX06|HqORAkjCH{Xa2IZxR-Wx+}n8t z>19(8$)!N|!79viRpR9G68lNXV{kenbNoRhzx^JI12#8#erZY9>Q@D-E-FzUyf3de zA9OwrXAOD|ri7kjs4Z_a-S&8#U43f2|23RQnfmvL3WKStHdj+!mk{=gg7yPqCZWYL zp(W+T)#f|T#c_B!m=@CZS?iLx*RzuR+fPB{ItuiBAvjI(3`}oN-=4n|?&a(@OBdM0tGP-&pe>Rx{LQ%j!R60B?PejU~0^ z?hT<6;@)1Q5Z;G^$Wg4SrXc4MKV_w5YUjkbSIb%_vsSy)a%GlUwn{4E-XLpT$y#?f zEtl4`N!u!@jC+4#BhRvt51kR0v^L^S{hX*34f?z)K5w_P$T8{P8prF$W{eAK^w6otRO*!KD`$3$JV}p{5}LuV76(JCXvf1kJsvtm z8cKMQ&_hwZ=&Xs#>e^El)9SR`Uf4Ip)#s9pGV;Zz)Y2cuuzww5sgR==6Ve@QV--&y8S3NrunObsfC0KXfLGv8k9)0bXf+%9wlm~Etg?MW>fwBytux}@J#6iM zw)Ud5rWzPqQ;TBT#%M;H#Mh)bhCc0HkWn4hQ7-_|&oD?zFv2AhhaJrBUFQOn)Oo4V6e?T*38SMr3*>P_L z>#btF^PHag0Bnka+eu+n-1`Zu-Nb75IyE;bq)Kz4-F;|J>sLEntfum^`HU_yzbgg0 zG)eOV*2zLU40ojU_(J3H&bWHrG*$WRkldBl;|q<)zY+H~QO?3Y<2>Hy^5{NUn$iW< z?cLh#DRN-nLhGUS&*o=+gUs(ufp&rOFn)nWw1`F4&An;eyvQ`)zPPuHEQeb;jf-3w z&dvBqb(x0s^_sN4USxcIPTYHp(|D58_@_%ltyf%-%2$hQRrIH=ibbX>*2ca0-IPWi z1(6dd@EgDX3E7ls*!nm(ZGG4;@17U;zRPKRpVPS0r6KDhZKdSfO8I8mO362sa(>*K z;)Fiqg!byOg^`t#wr1R?doM^^Gx?@wz7u?yl27TG!_r*IyX-ZlOGeZ=)dc zgv+h#1=IUK-}?WewEnMIU_b79aopRfmy+6*g2;RdbSP9l|%`{3=j(;M4qE#5SHtVFRvY&;~wpeI;!p zvyK0uz#bN_4e=V`J9KX&)3%57!lns-S8t8#S_?}1Phsfw-G;b# z4P`F;V+tZeE}NV)B zp=KxHpWwxkQ8Q!w^>Ov*285a&t!}{EGe*sHiA{0!X9R?r9jb4{TQXYB|D5+taricw z4^8=gO7}DNmM#;Yg18xPwCG1=@r42!@Xn>0+?9ez9tD2W*LNA<@fNKtUr4wm?w!Q? zOId#v>-!fcs9IZJR;}C4&*SRldhLdqqPjZzGG2AV67%(q&3Lt}KEmb(3tKb4z)4t& zmD(Uo4n2>Gwt#|2DFxa!s%gXal~r>S)-U7U za@K2Oy$hrs%!y9Vwt-*K{U6r5k@fD8dg^Z?7?-Kf5!2t$N|;vsYrI}kR(SwO7+(wt zU$CzB1-*%&eQ-yTx)m@Mev@S3)M|dLf?p!IliKv5w(+TE=U11OxJ#JlTdcl>X~B1k z3Kb$I3-^dDNC{))UR+hFoYa+{YIb{uMWfQU{QbS4EqIsMylqllT1t&Zm*75GM)fv| z=EeNSx3tjxIFzJ%W#s|9Us_X5?biQTz=NV0R@dlnK%vA#0SWc`>k{fWCi&k6xZY#Z zSsMv39_2N8SdiNCO8S$obgzZ(4;0nXcLv<6BEQ2e^qSi8>RJ*!)&5BxGravi?wxi4 zHQy!*B7GF-@k71tj@>2st(-^V-Va#wN33}lYpPk(-<9AlXC^z!xVqQiUX{}&`Ga0T zm>!~K%rgXbAO6v}_X(#G`WB_K3k5nAx5q0JaLT56Jw{uNq!T`#wHu|j8WCXc-sI7m zF#T+6+&hmg46ubCNDF)&k~)1m7(E{Mwy^d?tUV^RlSU+2e$$7Zpz^bY&;Xa80w_N$ zvI3d6^V%P&{G<~;p0yjLwn`svF$GN6)&7%l@0)DmLN;-YGyzMkByCdze~Nqev-$|D zzbMsJ4sdK09PsP2@*usnp$--U~fCtDYalKgYdmIhpG?nfqlju4Zr_Ko-gE&io~P_1Nv1 zvA8$mVoGW@1(5?OfD*at!JU9WQnrr%n!b+gF3pQ^Z#5^?%}HG)lX7*0EBQcDwxV82 zUs3J~`2XVGUpcLpIjzrRTCSp0QByWO|0?-!>1)gG+Pob15|>a~Cr}XSpa5JbYb$+~ zxxJger>`=*c{3jO?&kFFB%ZfUvF*;=auyJX7_OZ5%&(bl+rtdf=CqwP(E32 z=_}9e_Pm8vF$1|ix@qEMLw5q5`ln(gPtafFe};>9^{ANn?3vd595-WX zi|A>sT6#9dE}6E`gWB`$(iEs!lZEEMBdO$>*@3EH_oVt;WVamVrYy6a=Xac= z{w`vm3S4i`N?B$*Y40>g{h9ipvMuwMQkL1yz&p=Te+V(CY|H%Rlx4PePj;E3{^DU! z*_L@%QRcuF^8d%!dB8_e<#GH4NFZi=NrJeL>~50X4S^6sv7mH`v``c*2!SMICCzLS zf)zv$EFj1s*s+2g4-sq!>Zz!wVg*GH?07a53#iEb{xkERo!OmP&d=v2-1q-`|5xU{ zH?PfXjzx2bi`JLr^%S|Ohoc1Fj}$ zeRa3^t|nj0$=5T-_9eO2IUF%nS^PX+cbo9t5#AQ-Vex%Oar{JabXtz|(xY7aLlN|w z1xjN*L3h81D^=TP@%2a8^uf4fj3F=d2-p4=D|t~`ZBN~eBd&PqW$`T_FPD**<>W;= zRHB(Rk{6}<=IQPram7o%#kY;T{ENK2OI~PCUH)ZNE@&JzpQ8MTAie#AUldec*6~|3 zr_$wB?)V~5z|yn(_3+#i7wHogCHRN5;HTa}tcNI{iqtKz2Q9uS6mmK)87&-2vsOsA z&fH1T+IoS-cQ^UlK>l7<{l)8+^e>&$DQDtSwZ<#EG`-6;v$W^wLf?whtmAyWd!%1f?P&HmQxUEV5`}~ zl7mcER|nOX;)*T4$0_KO6!Z->sMN$X^(QI3x**%z;`@ah{7w$+D>-h-fo9Pl(ScGL zC8+-hlRg-ijPd%=nsu9`&`OoSU54b(w_QSq@6LjZYOD!C`#o5 zQbhRaCBDV|v=6N*WKi-{rhOny!RHvJ@TckeTYUL9Ai0IOWDLc{sE<=>vl38xt3ydj zxy3h&g4a;+izv8so24qNy;pLS(h?&lc7Vlq3k6+ALAR+v;}fpLdap#UI8hQX(Bk`q zynIPsepS6_;~s@y>&B}nXG<>_^2XC3l%cxuG$lcz_#SN0Y(OPwlty);uEh0jxLZC+ z``k=$quig9b@xZ_hWq7Hv`^3kH%jdpq8&OUN|a2Us(qFwXq4{wH0>ZFQKGmRs(q>^ zX!z}-VHW8pu9bSK&z1UK(Qu3Ay`n@%O1?%|G(W|Yq)}2d(jxtGwQ+1p&PG|JpR6{~ zD2_&3q+h5u62YBMMYC6zpwhm5R$-BTHkYFuhex1xEB*|0Nrn7O zk-mi@z5XC~&SSMh82Ljf+D~AOv-mpQhz8OXmyAMOG|Ti-kErh7aVwWz1Cc);CC4z{ z;u}RS&L9`nQG4aE(6Lfd75?_YFdtm1%k8e4)i5A}` zift>!wo8qTHW%f1r5y%sKRy*d0Z=h6{N&X@8rS02H~WPN<9muoHH5^C%@du zzx*@_^&g?qPr@Z*sv16(llXgvlP#L}3^BW+q>)u0#S~rjkyZR+!Blij6#bJF{Tuq| zDGmDMPps5?KGWj+%*GlVThP{{vnPbzdKb&sSye%0wD$U_+ZBM9Ll|Jwsi{`D#xKRmuuD176txErJo<;NaWZb9( zouTdVRIAb>oNtldqEw4SKJ&`s&zag@j)U@Cd6q>pSB@K%SgVZk%6kU0wKHWkDEIVp zjPlCIE~~ZkWHl&vI5kFj<-?Y>@+?`O*D}uQT%)}5bhu9Yoa0#4m6fPbUU@Qnf%e&^ z2IaiYGs-JZh3mD?Gc_pZwZSN_JP~fxKEu?YoYy9!yz(@-SvyeXpz196LZiI$B)CO8 zl2(IqUSmdiL zi}Zq@+FCT9(YnGSy~n3DDLv6*i{^Db*&W})E78-`XgX&4w3ZyxRTkg9x1ra40GEty zxM+G^+FyzHwVKay{mtV0kOJ+cKtJmPX;$!&1_V;Fv?L)*WKp`Sr3qPrNy*aH30WeG z66l(QEJ^SD^8Wj^7T?9UBY_KX$#?`8%~LqOgd+V*dcH^(&G|&6T=K`=?R6I4YvgYy z`Rja#i9c!5@c%eXnujm5_=@2*y%d*>sj7d;p_DdtKBArYaw@r_TyF7QNM72>%Ok26 zDMj&I$6Xyesr^SLCG~prixkNoiloarE()WhN{qI3;*}_Q#=RopKE@U5NOq+~I{2$r zc~zoRts4@mR@|=Cl~oB9Ocf~A?C%NHEN)jEtWHRzvM9sV?M935zbJ|HA8^UYywkW$ z;)S4u=E}83UW8Gzr<#+>eyv#~;9TuPUZY05lOGXhc@_a&a zt(h0-LTU!b>ny%;6nqi|Z%z&_{pxEPo%xR6RsDzHxZk`}yMUua7q9PXo4ZS1$5L;+ z&Y9Bg?v_`pOf*WdJfR(~M_l)yl;-1-u@V=}WKk+< zeYK}Nsf|s39B!~khmCcqRV7L7@qUZ%Q;P2^iZAP4@V#z~buz59$4J z$(WYXmuW5x8t{V_-&N%H8gjeom~ImuFH$-an*2i+-!Ag_5qV6%k2C#$HhHZ_ZuSpb zd|~)W?}JN5m4U~EmTA`PwZ6GnAF=rE$WCY!XH|@vCg1Ky(e+Zy8z|=Y)tJ>*DGwW@ z*{A-(tt@dNT%Pg9KSQulyXKIzY%Z%c&HOR6sP#zCU|ce$;UZVyc-%>I;KT$d-&Ry+ znE$Z&7L&iFd8I`90xOQU2hYyt@RPETrQy{b)d`IN=?1-bk$xjd?OsacxhV0_l?X^ZcK z`w=W3myCY6$YrE?62wC&F+F4PO{5@GDM(ZeA|+n4BBg}mw)HF`it;U1ZHmi(%H=Ni zc5GBicbi4})$}a4@X-jUUqmzI~7-Qs=i41szK?g)7jTB0(lTAYQ-gEIW7sMXHbOkx$eIW zijdbNUbpymkmJ|M@wcjDeGzI;-zmvfmo45fC`Vqkc+=u5cnHoTxMWn|BBxqkj@qMk z?3@d8r$J%zy2e`;-xcJ12|2${bsm3IssGa7DfK|z+Xe-$E&#k^@$Dn;Uy%1M4|CGv zowfR}1n+9aeb=DWlh>`^(>_C#>??=Tc$?>ai*Fthklu_-#x-hEq`o2XT%Fzn7vnCA z?_u)r5AyJD0}sjlqk1roQ?Xl4g{~c{B97<-IU+-mT4O#;;YmH$wa3(x+JZka^`oA) z`qBgAgY8Y>NzK{56rR+aePZfK_4BEzAJxle=3e4C``p}5JZE2|@T8XY zmnl4{rTvwGC(Hts-AfbdCF&P=_)VQ=W)r{g^N5Aqca5Bj+8%zr+AQ)_np># zqC)p^weNMxQIj$E;Rp8*+7*8J@Sl28^MH08Sg|RO?H{$P`)pF4+COR6fEAna&_1Xg z?pG``zU$tw$vW*|gziEe-Y*K<9O3oWUa}R3=ok}q7R(?;; z8$VM2&<;qHU_2iAGdXX(iho4AimwFYb?v{B^TtohquLdGIhfjLg;jHeQL!oaEzPPq z!p0`0NIF?HhZhx_a^E^zHHX*Oqy+0?)f`(?Y|4F0w`z{9u}KM*Vbz>Xlx@O8uEFina@=2lpnB@TkUbOJGsZu#H{3aWW`w(>dBQXlZ-2$!_js`7OOA6D-Xam zZsmV!l~${-bTjfZ0GEuZxM<2qDk$}XIm&p##G7)DZC2mq$!Neu zE>d;0Y;Y6RBm22>2^lz73ZuK#w~?H0Cg-oJ&ebo07&+$>IbJT2War%F_pth`TjAV= zOGa;8ZVrZopma8$SWuu)$Xm5`?HtA_rK>S4LW%a#9 zF}zPP98hCW3rPDBWL*qgN_l3bR6b$2Qjhbkz5!1nj+1c7I0F~CoDSz0*2r>oJIrsD z&Y~sXfbt0(d%!$)J~b7z`ZiJQTPgNkYV7n=chc9H;}?TlRX#yISXF@jk^G3K;KzZB zoD2HJBjbSlJTA2Q${|lbkpfnz0X6Fz+JZ%loVg<0JPO!C0k2R4YTjkn1?1um$;E9@ zY|3I**y?+c{Ju(lzgGR~>#cV3tBZzbMiH~h%hTXutFQOdh^8Md8I`ysG;I0Mt4SxQ zj`(|<)nIi(TVh&Glun?J)wh`v@)RZH12rM~I&N0c)vp2dHLYrD6)Bagh(XD#lYoA5 zWiXQPZ7-8=d$L3~PU&y(43_#;-9x?HOr;&j46yp%dj{q6Aubt*aglG-F~=}cbQS%S zVcS5f^hxXFWJ95J1cS`(RE7FIrNL$iCW+$aM6)ui;6ptp;YM6;)GVP;oSbZ$7WFK~ zDF!1VInVL)7(-0c!b9~_G16FMm=<*n>@?G~s4HPZt-jk%F!rLB%P`Zllyl!O+^lb? z;Ps^usC|nKBT^gONYmu1jb)TsW2q=tTgzy()&h-Er%uQ7ZyRc6D=rzUaFJ`KG;-8m z47y-)qulH<<|U){wiRa0PB%b5!|F@hjud6!l97i?Vp~Zbo6A*3_f46xR^RF5WgK~# zXW&H|%xVsAXnWvsJcb=7k71Kr9282%$D4K1<9Gx&!E6Kvh2mtQsS_RvRmvkFgOsRa zok^xnc$PU?ek>U{Q74;IOr2=^v#IhuGH|5331`YTAz2nb%ypL4_rr6zPe0?5VSAqM zcB+Y;bhkCnNRQhF2dDUT_)mQK$;*Q{waT+f2?`lfxjP%2?O0uWH<3uD}eOb2NsyP6xu_`e( zXjhuzW+lyyc(V0QcFk*PP1^OQcwpr@(`?neEUU39F<+=%b&8vn;bn_edRbO3Esa$P z9Mi5nsb=muTdkV+Vl`GJaGPPCd3xAx)w~xQ56pRl?pOsT7?u4$=kX`0(o z)gUgn_WmPDGPS0owXLN_EV333#Hy1TzP`DxYIIxU9I@Eyuhkk_YLpyq+FDzy=G4jQ5?5Obj%sYfYvx89#kJO+J-fvdBEb<& zjn&cCXj5ZV{p6ZPWJxTu_8pk0n$%X)vOrvK4YV3sDiE*(KLE1Q8o4h~Ftw$sF;?5u z(lENFrh0bOoOxoEweROzRkX2sSZixbboRKWIaQPtvD#W}&D10mis5awwMg6=YhawA zWq4JrM%-jAiW*ucS2fP95w}=F*BF{(Qs~>Pp`FHNIrtscuoEkEd>@A+Rij&~=8mjt ztx{8dr?q76F*ICQcU#MsCrcY@X3IIf*BaWBV6JGWn#)y0tha`bq_D@t{np5YEPZm7 z>RK6XuBneU)`$nKy{}7<$dy1z!^76_^9lATRSnJcxDk(9gI^e%V&XAtL1&9TW^N0c ztUCDDxtJrJ}4K+5$#1?D8>_l5q-Fnj6XHkOateTeAnvP*DXgT6(Yv_JMvr@gD zwT53yVULMz)`%4gC-FMa+ECRjp0oBkM@#F`l14PuH?@cttbzLyEu$`MldJiQ*1}KC zj8kfwt6Hk?donLu`*gy4JZg;On?0~7DqgYnJJ<#h`|J_Cgb}Zhs zMz*CAM8#Xy;!gI2^pWqVc*hzTtFuH~(O%RF{+=~dmtdX%E43+Av&&lYvQ{HC4Qg=W z18ZP_LldoJnbO*X23aHaSPL&qHnz={LVj#5+^8{*sH(3Y7mc-wz1I9640ud@V)Y;A zj7K%1u4c|WO(LhXR<*Xp#AnvNLlaer`B9`_Sj#WfO6$?4LHhFvXs;Btf4|<^Ax2ley|qT8!Kv~;zw)YHWOpJIA|^W%h(ug z7r$5whu~WQTxUnb)71v+Z`Ptq60LIf4_gCU5-lTZnp^9{AJ)LThL&1!#2QTVBt$0l zvEryT&^OT{-4ab1rP)fxrOZY{TpbgdwtF54Wc0yF>jHO43u-gg;8yJyk+3vK3FVWef7u;tB2#_giOmcKHI zM@5k>@0n!WF2c6_14%q4ifws4FzQr`L5eiiE=p|q6O(w`Y|+=2f4Ko~7yWGh$CC|F z(chN8&w#g!0XDz)_{5meTMe@14>REH;zXOjJ<(7;TbyjmTc3>E#SlcC#H+<=w!A-* zal061%P;Sdkeu>bF~XKNF&VduQMUYO5|4`0ZFyHF<91PD%YQbB$HZ7$-tJ`FF2>vP zomiUG-Ia2b{zO}TZv);gCfWS8$%d$yV#~k6fVYb?ZT@GH4KXpzmcQG8w~MoFewQyH zN#m6-aL~S*&8CA zZ!4W|CZo9_OA+w`Tlr`Ij}(z#Y%4!4-z0LaS0vz4Tlu{@Y4Za4;fI)|F~a4xh}W<6 z)x1FJ``Nz87M_t{*E~X5wb<78{RCBIw4jYA!(eTyKj!m@Lp1B5ut}Tc554NzrIUh-#Is&-BzHM7P@3 zXOmXcQiCDBd_!VljjhmKsEI~0YQ`5aag(ihe3F9KAa1c0wwM`t#upQ}+4|m^q@wA4 zv?eC*uob?TWYo?GW8zL*@1sc)Wl|UuciV~ziW0M+EJ@sJD;RBJQ?k%5*4s)JBx#hP z24=Ljq8E~_iF3f1c+l4G^CX>S8Wql43sS%Ij`J~|^F&Upb9z7B! z6*NzfmM{cc-j`cBFV&c5_eJ@GHb>ul);a^EceI0qh*1KmUG5u;C zdC^uhGTACEr-_$s1vSYw8cDul3tX9GQESF)wxY+9t;sdxbz8r;lXSY8@usc#h)#jo zhcs1w%jWkNYcmCd^k{y^=07#jATJobXA4|lXpt5p+Qlwg_*O$ZFA;rUi+o@xs1vZBXTfYsa zI%z3SUT*oq*6*EUT~vH!%l}Kyo2y#q)QxCrXl_F?zP5$BmuT`9jcLs&oM=nUoL2FT zt@LEAtfgwc6m3j=XA86$TGX&V*oq%AQN&uS8s}g!^G93nFH=is)e!Aj(u;$(!Nq+v ziAHMVj$Qm>3oJ6U#Kdp5;Oz+}Wpy_u4%-UeH?dK~@?8;s*!p_<>Z4^3YG#kvN~%mX zoZX|gK6f2Uq|0!c{iN^zp8!fiJKG13Ej3H1l8AV|bTOsdN8XnZR2f}#wFg}N^iHLw z$3-AA?U5;|1o0R}mc4vkf;4&U+G_9f=dnawC8~wpJ}6kGPhOJCDXnNa}Vd$lJ~ zZLi_8N3Ks2BzGFU?4_H`WSTxB-(LE0k}N6$_Pnm;nnX8Nivs%z`FfPRnNegf8Kl=p zYkgsR-uZeg?{E~`^E(VU_s1pn&?>z->2`{~_L9w7O?y@Sh^D5N>VDOtpFQ}Iv8i43 zw-@|wXsZG+9?Y*0zg5_JTo1wz6t*qCI$)v8i30Y%gdvwAG3s_TVaGQ@c3L zUhr6g4WpyFeqxy2ztg}_CPvu(83Xlcm#SeuG0GkoZDc7Er`rQ_G#1`BQhL)0d(mp0 z6`i%T)-=}ce@|8H$;K+p z3`mwvv6o+_l{U?l?m4%(Gwq?549wMHn%&=NuqJg%xN58f*aJNcEVbfXyZ>Y(L%Wz^ z4@}crYQ;>uuQh?Siz<81YxOWH=Gc8(6Ii>bvG@F33*#&EmDrqUz^Jq(D(2ezI8W5% zAuiI63PsdjI>lI~jN-&Rd-1I)6|@>)FWHw;gPB;9y`=ag!vrZYVIp>+y<~Dq&A6%s zSiOkZOYhRjFu<243T<}(0iB^O){3p-`Sv`^$?>R9uW97T-2!`HqTZq#&|hp1)$7gj zX#P@r{&GD}*u#s7%k90N)k}D&zQ`WRWYI~oVdXeUV5EIwhLre7L8rtj{A8n@Xv}N|9`wgs03KY@x_CBxbM9RYS zu-2xA=$sKvZM6I(mp+!LR@w*sWUQu*XR*p2I(>+?Bot>@N@!_nYsFqEHF>exUV2|@ z8Fn#guUk^Du@5@@f2onao9qK3ry3+c@h5Jvhc8WGA70-yXPy-4ZT7Nt#}XpGJM5(g zQphA%ciKyiKg~Q%F}S(g-g{VrL^_2~Q!P*WW8z+W@wG_`?Oy+Sd*n^MV0cp#HjEmh zGuy@e_Cm{0T@n;yyLiwZ9Gzg2_5kBO)4=j}@vyz`g4C*Z@uW_!Vs1RG{K`qfFX#olLo3K6X|$s00H+RHi(*QJE! zOsY5Sl9YJbK483Ft6k0**ECl=YcGB>LDAHPnIe_^HhY10gf6C$lC51lXAex!TSm3C z&{nrSf1aL?u5ZFdH=Mm_53VpUwTqYS{v8PhWPcj?7dGIsY|G) zW5s+GXJY8IOuSmOi`VU^3^xs;6~1XNTca1A-cr?E7o9@~bZVqYGxk#6viE&Kuc|=b zGqf1SkP z=PP@Dm(z7|kH<5B_ALmn^T92=dE2F zwh#K*K&>4DXyt#{2NzW6Qa*9^1z2VoS2eq)UL3I(O*67qwzkNEqxQ(HdVw@WN6oXD|NfUH=JSSI7sf!CZ`qdvxhh2O} z-zSctYLna*Im-4PQ;2PTM`_jsUCO1@Da!;%ez7Amz(Al$c!{I9!(7oW`Z~h5ncC&V z_H*>!o3RQ8x7~efkr9(vbRcN9i5MlC_IPj=uZ#Dy8vB^K7}PE_ReS zr|BY8G%!c!U^D$HM`V(rKyATG9L0Y(RK%AZ=+<2AD1FjUhNgL~qu_|44R>pqqhR24 zqZGpD^^SrjLmNf7(owiUZ`3T_C=WTzZQ8{uN7<*x5<<4xQCf1gE+HC!u&;51ry1I% zZ2@Y+H#v$gN}-@c-{Rp@r&jPbyRtWqqNI8MyZuj13z~r9LfB|k(WLzAuDaO zvE<;$@2lg{R+^v0#1{_#89D=60~QtAYpRta0$({IwK@TI)uPqvX)Nh%+}DnhYf@-< zI{%HM^f5!3WJrtQh94a#)fonWK;v8-bo6`G zP^Z@UUmV4O*+x-A0cUc<_|4I0hE^0)Hs=mI^0(^vC}|J5TKwVge`REdiX)Cd&KymA zF>P{>Its_@jMDCHnzL7fj`H!Q&QAZ|j0`*x$2YGccj*N3wr^Kw-b*^HoehahXVE^L zRha>aET=!MTAOs`q?^^5@6&TS!DMmyxzP#OUWr_+z)Ch9rlidgcdvfJ5vkxrs{ zfC{g(aJ|MTE#QrBs;;T86*&fu+vrdrY8 z8GI_iB(0JRaOUq$;L@#aZi>~g+dRLGqG8m?93ac!FYD# zjKL6R&vO%CtvJou^Hx2?`G8^0o*ySboWytbEUSx01)oaG9_92eF)~b+-mE;`S@ewF zdU{KgjyzO2{UWOKCmCwRSf_trvH{5&@ATIj7;42tr~fg%LFx>Z^i6UW{c38J6FJ4% zyYvEWT9n0Rai-J1z{r4^uQRaPz!DW_JN^GKGGN;447{PYp!!gA6f>NGZ?u-0hNhMU z!>d|w^tMIJbQX4-r%9aFIDElmyuXY0Vym2eLRwL@QSOSU-=W#k9A~&vYsaEE*RvXD z5U&xaEpfbRsugpc!IcT7q-q*xWGB+ zjYKs%em)X(u`?8EOo%mZ#iE1zuFldVP;25zt$PL*xZcyt24aC)LtvDcZNPRH)9s-3}-i+q^>L~ zRyji_nwv3cb%xJ1wd1h9Gjy4`88cRA_$f1c|7vlIGxV{!8FN)&d|N)X3S5W;V(_?F|pnm%4{)99Pa!5&hQy#_VQ}+pfl89ZpNOy zGrY;vUMn7ThTb(1i8nJAQ_7jHU?UrkhKCJ^-a zQ3eQaIs4n%6B1*njEQ%gr_l1eVUM%4c)oe$icCJp_OWw7Yob;=$>9>;>+JXP|DmJdgRED%Xs1@Hi z^A8$u?DaeSwgsA$%1OeD?#}#(0mn=3PXDN6LrnbQ%*V$h;zYJoSI>DG zSXmW|O|8QTx4Cur8fAv$aIDNr8Bq1YLe%%S+2fcYE|@( zpnOEY>I&E|jwhGb2x&pg?h1}JGNHVkuHa>fCaTIcwZiQRK4EBz3a=~pZlXy}EB5q7 zj;rV=Giy|IcNMuWNl528O-&7=hs$5CHPHQwm!I&tLY3xbY=*nSEvELU$ajTSo15E3 zz!lz-XrB_js74gH{2%HJ()y@0A1QJLe@!+`tgXe-CJ}ZOdM?%EQ(jk)I7L zVUbxH%4)@#uJF(lcFg5nkt@svn9{q#_oc97X77sZHy5B3X1F4jD@>C}UD-@m@kCPv zrUg~5aBB)X_Oe}(r_BYmqQ({8o5GHbY*(aku~{1XM@7^XJ|l&_UCeVuR+om?|(qxX=~$Uul-ca%{cCT#-g|L9J+Wg>Oh<#~!sS@*i_SR4j0XJ6&a( z0^G=pU6Bdq0+hm~u1HHN0k)!D#oJ63a=%uFye@K;ets+&9?y$irDcCJOR?guqd)vz z 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 DL0RI$ literal 285779 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 diff --git a/build/src/CMakeFiles/Exponent.dir/main.cc.obj.d b/build/src/CMakeFiles/Exponent.dir/main.cc.obj.d index 656d1be..1a7da3d 100644 --- a/build/src/CMakeFiles/Exponent.dir/main.cc.obj.d +++ b/build/src/CMakeFiles/Exponent.dir/main.cc.obj.d @@ -32,132 +32,4 @@ src/CMakeFiles/Exponent.dir/main.cc.obj: \ C:/msys64/ucrt64/include/c++/13.2.0/bits/std_abs.h \ C:/msys64/ucrt64/include/string.h \ C:/msys64/ucrt64/include/sec_api/string_s.h \ - E:/OneDrive/Documents/Projects/Exponent/glfw/include/GLFW/glfw3.h \ - E:/OneDrive/Documents/Projects/Exponent/include/linmath.h \ - C:/msys64/ucrt64/include/c++/13.2.0/math.h \ - C:/msys64/ucrt64/include/c++/13.2.0/cmath \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/requires_hosted.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/cpp_type_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/type_traits.h \ - C:/msys64/ucrt64/include/math.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/specfun.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_algobase.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/functexcept.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_defines.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/numeric_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_pair.h \ - C:/msys64/ucrt64/include/c++/13.2.0/type_traits \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/move.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/utility.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_types.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator_base_funcs.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/concept_check.h \ - C:/msys64/ucrt64/include/c++/13.2.0/debug/assertions.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_iterator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ptr_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/debug/debug.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/predefined_ops.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bit \ - C:/msys64/ucrt64/include/c++/13.2.0/limits \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/gamma.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/special_function_util.h \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/bessel_function.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/beta_function.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/ell_integral.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/exp_integral.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/hypergeometric.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/legendre_function.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/modified_bessel_func.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_hermite.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/poly_laguerre.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/tr1/riemann_zeta.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/iostream \ - C:/msys64/ucrt64/include/c++/13.2.0/ostream \ - C:/msys64/ucrt64/include/c++/13.2.0/ios \ - C:/msys64/ucrt64/include/c++/13.2.0/iosfwd \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stringfwd.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/memoryfwd.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/postypes.h \ - C:/msys64/ucrt64/include/c++/13.2.0/cwchar \ - C:/msys64/ucrt64/include/wchar.h \ - C:/msys64/ucrt64/include/_mingw_stat64.h \ - C:/msys64/ucrt64/include/sec_api/wchar_s.h \ - C:/msys64/ucrt64/include/c++/13.2.0/exception \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/exception_ptr.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_init_exception.h \ - C:/msys64/ucrt64/include/c++/13.2.0/typeinfo \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/hash_bytes.h \ - C:/msys64/ucrt64/include/c++/13.2.0/new \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/nested_exception.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/char_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/localefwd.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++locale.h \ - C:/msys64/ucrt64/include/c++/13.2.0/clocale \ - C:/msys64/ucrt64/include/locale.h \ - C:/msys64/ucrt64/include/c++/13.2.0/cctype \ - C:/msys64/ucrt64/include/ctype.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ios_base.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/atomicity.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/gthr-default.h \ - C:/msys64/ucrt64/include/pthread.h C:/msys64/ucrt64/include/sys/types.h \ - C:/msys64/ucrt64/include/process.h \ - C:/msys64/ucrt64/include/corecrt_startup.h \ - C:/msys64/ucrt64/include/signal.h \ - C:/msys64/ucrt64/include/pthread_signal.h \ - C:/msys64/ucrt64/include/time.h C:/msys64/ucrt64/include/sys/timeb.h \ - C:/msys64/ucrt64/include/sec_api/sys/timeb_s.h \ - C:/msys64/ucrt64/include/_timeval.h \ - C:/msys64/ucrt64/include/pthread_time.h \ - C:/msys64/ucrt64/include/pthread_compat.h \ - C:/msys64/ucrt64/include/pthread_unistd.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/atomic_word.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.h \ - C:/msys64/ucrt64/include/c++/13.2.0/string \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/allocator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/c++allocator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/new_allocator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream_insert.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/cxxabi_forced.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_function.h \ - C:/msys64/ucrt64/include/c++/13.2.0/backward/binders.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/refwrap.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/invoke.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/range_access.h \ - C:/msys64/ucrt64/include/c++/13.2.0/initializer_list \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.h \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/alloc_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/alloc_traits.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/stl_construct.h \ - C:/msys64/ucrt64/include/c++/13.2.0/string_view \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/functional_hash.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/string_view.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/ext/string_conversions.h \ - C:/msys64/ucrt64/include/c++/13.2.0/cstdio \ - C:/msys64/ucrt64/include/c++/13.2.0/cerrno \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/charconv.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_string.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/memory_resource.h \ - C:/msys64/ucrt64/include/c++/13.2.0/cstddef \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/uses_allocator_args.h \ - C:/msys64/ucrt64/include/c++/13.2.0/tuple \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_classes.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/system_error \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/error_constants.h \ - C:/msys64/ucrt64/include/c++/13.2.0/stdexcept \ - C:/msys64/ucrt64/include/c++/13.2.0/streambuf \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.h \ - C:/msys64/ucrt64/include/c++/13.2.0/cwctype \ - C:/msys64/ucrt64/include/wctype.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_base.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/streambuf_iterator.h \ - C:/msys64/ucrt64/include/c++/13.2.0/x86_64-w64-mingw32/bits/ctype_inline.h \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/locale_facets.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/basic_ios.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/ostream.tcc \ - C:/msys64/ucrt64/include/c++/13.2.0/istream \ - C:/msys64/ucrt64/include/c++/13.2.0/bits/istream.tcc + E:/OneDrive/Documents/Projects/Exponent/glfw/include/GLFW/glfw3.h diff --git a/build/src/CMakeFiles/Exponent.dir/objects.a b/build/src/CMakeFiles/Exponent.dir/objects.a index 37964b2c5d7520b59be45f1caacea86a772714fb..058cebb29e712c1299aed3850e66975f5191163f 100644 GIT binary patch literal 288338 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

0Uw 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

M`|L^z{idOz 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

X6Z{qg46eS|{iRS2P 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 sA<*%#COa& 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 b{qF0sbwY8hnVr+O_L`Sck^KJvhH@KZ delta 350275 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" + "$" +) + +if (GLM_BUILD_LIBRARY) + add_library(glm + ${ROOT_TEXT} ${ROOT_MD} ${ROOT_NAT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${EXT_SOURCE} ${EXT_INLINE} ${EXT_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER} + ${SIMD_SOURCE} ${SIMD_INLINE} ${SIMD_HEADER} + ) + add_library(glm::glm ALIAS glm) + target_link_libraries(glm PUBLIC glm-header-only) +else() + add_library(glm INTERFACE) + add_library(glm::glm ALIAS glm) + target_link_libraries(glm INTERFACE glm-header-only) +endif() diff --git a/glm/common.hpp b/glm/common.hpp new file mode 100644 index 0000000..b59657d --- /dev/null +++ b/glm/common.hpp @@ -0,0 +1,539 @@ +/// @ref core +/// @file glm/common.hpp +/// +/// @see GLSL 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR genTypeT mix(genTypeT x, genTypeT y, genTypeU a); + + template + GLM_FUNC_DECL GLM_CONSTEXPR vec mix(vec const& x, vec const& y, vec const& a); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 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 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 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 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/glm/copying.txt b/glm/copying.txt new file mode 100644 index 0000000..779c32f --- /dev/null +++ b/glm/copying.txt @@ -0,0 +1,54 @@ +================================================================================ +OpenGL Mathematics (GLM) +-------------------------------------------------------------------------------- +GLM is licensed under The Happy Bunny License or MIT License + +================================================================================ +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. + +================================================================================ +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. diff --git a/glm/detail/_features.hpp b/glm/detail/_features.hpp new file mode 100644 index 0000000..b0cbe9f --- /dev/null +++ b/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/glm/detail/_fixes.hpp b/glm/detail/_fixes.hpp new file mode 100644 index 0000000..a503c7c --- /dev/null +++ b/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/glm/detail/_noise.hpp b/glm/detail/_noise.hpp new file mode 100644 index 0000000..5a874a0 --- /dev/null +++ b/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/glm/detail/_swizzle.hpp b/glm/detail/_swizzle.hpp new file mode 100644 index 0000000..e1f57cc --- /dev/null +++ b/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(int i){ return (reinterpret_cast(_buffer))[i]; } + GLM_FUNC_QUALIFIER T const& elem(int 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[](int i) + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + GLM_FUNC_QUALIFIER T operator[](int 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[] (int 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/glm/detail/_swizzle_func.hpp b/glm/detail/_swizzle_func.hpp new file mode 100644 index 0000000..a264ae9 --- /dev/null +++ b/glm/detail/_swizzle_func.hpp @@ -0,0 +1,682 @@ +#pragma once + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY(T, P, CONST, A, B) \ + GLM_FUNC_QUALIFIER 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) \ + GLM_FUNC_QUALIFIER 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) \ + GLM_FUNC_QUALIFIER 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 \ + GLM_FUNC_QUALIFIER 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 \ + GLM_FUNC_QUALIFIER 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 \ + GLM_FUNC_QUALIFIER 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/glm/detail/_vectorize.hpp b/glm/detail/_vectorize.hpp new file mode 100644 index 0000000..1fcaec3 --- /dev/null +++ b/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/glm/detail/compute_common.hpp b/glm/detail/compute_common.hpp new file mode 100644 index 0000000..83362bc --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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) || (GLM_COMPILER & GLM_COMPILER_HIP) + template<> + struct compute_abs + { + GLM_FUNC_QUALIFIER 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/glm/detail/compute_vector_decl.hpp b/glm/detail/compute_vector_decl.hpp new file mode 100644 index 0000000..00d7de5 --- /dev/null +++ b/glm/detail/compute_vector_decl.hpp @@ -0,0 +1,190 @@ + +#pragma once +#include +#include "_vectorize.hpp" + +namespace glm { + namespace detail + { + template + struct compute_vec_add {}; + + template + struct compute_vec_sub {}; + + template + struct compute_vec_mul {}; + + template + struct compute_vec_div {}; + + template + struct compute_vec_mod {}; + + template + struct compute_splat {}; + + template + struct compute_vec_and {}; + + template + struct compute_vec_or {}; + + template + struct compute_vec_xor {}; + + template + struct compute_vec_shift_left {}; + + template + struct compute_vec_shift_right {}; + + template + struct compute_vec_equal {}; + + template + struct compute_vec_nequal {}; + + template + struct compute_vec_bitwise_not {}; + + template + struct compute_vec_add + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::plus(), a, b); + } + }; + + template + struct compute_vec_sub + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::minus(), a, b); + } + }; + + template + struct compute_vec_mul + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::multiplies(), a, b); + } + }; + + template + struct compute_vec_div + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::divides(), a, b); + } + }; + + template + struct compute_vec_mod + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + return detail::functor2::call(std::modulus(), a, b); + } + }; + + template + struct compute_vec_and + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] &= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_or + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] |= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_xor + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] ^= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_shift_left + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] <<= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_shift_right + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a, vec const& b) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] >>= static_cast(b[i]); + return v; + } + }; + + template + struct compute_vec_equal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec const& v1, vec const& v2) + { + bool b = true; + for (length_t i = 0; i < L; ++i) + b = b && detail::compute_equal::is_iec559>::call(v1.x, v2.x); + return b; + } + }; + + template + struct compute_vec_nequal + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static bool call(vec<4, T, Q> const& v1, vec<4, T, Q> const& v2) + { + return !compute_vec_equal::value, sizeof(T) * 8, detail::is_aligned::value>::call(v1, v2); + } + }; + + template + struct compute_vec_bitwise_not + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec call(vec const& a) + { + vec v(a); + for (length_t i = 0; i < L; ++i) + v[i] = ~v[i]; + return v; + } + }; + + } +} diff --git a/glm/detail/compute_vector_relational.hpp b/glm/detail/compute_vector_relational.hpp new file mode 100644 index 0000000..167b634 --- /dev/null +++ b/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/glm/detail/func_common.inl b/glm/detail/func_common.inl new file mode 100644 index 0000000..f8584c9 --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 GLM_CONSTEXPR static vec call(vec const& x, vec const& y, vec const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 GLM_CONSTEXPR static vec call(vec const& x, vec const& y, vec const& a) + { + vec Result(0); + 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 GLM_CONSTEXPR static vec call(vec const& x, vec const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 GLM_CONSTEXPR static vec call(vec const& x, vec const& y, bool const& a) + { + return a ? y : x; + } + }; + + template + struct compute_mix + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(T const& x, T const& y, U const& a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 GLM_CONSTEXPR static T call(T const& x, T const& y, bool const& a) + { + return a ? y : x; + } + }; + + template + struct compute_sign + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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_FLOAT || 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 GLM_CONSTEXPR genFIType sign(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || (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 GLM_CONSTEXPR vec sign(vec const& x) + { + GLM_STATIC_ASSERT( + std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || (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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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) || (GLM_COMPILER & GLM_COMPILER_HIP) + // 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 || GLM_CONFIG_UNRESTRICTED_FLOAT || 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 GLM_CONSTEXPR genTypeT mix(genTypeT x, genTypeT y, genTypeU a) + { + return detail::compute_mix::call(x, y, a); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec mix(vec const& x, vec const& y, U a) + { + return detail::compute_mix_scalar::value>::call(x, y, a); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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_FLOAT || 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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) || (GLM_COMPILER & GLM_COMPILER_HIP) + 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isnan' only accept floating-point inputs"); + + vec Result(0); + 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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) || (GLM_COMPILER & GLM_COMPILER_HIP) + // 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isinf' only accept floating-point inputs"); + + vec Result(0); + for (length_t l = 0; l < v.length(); ++l) + Result[l] = glm::isinf(v[l]); + return Result; + } + + GLM_FUNC_QUALIFIER int floatBitsToInt(float v) + { + union + { + float in; + int out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec floatBitsToInt(vec const& v) + { + return detail::functor1::call(floatBitsToInt, v); + } + + GLM_FUNC_QUALIFIER uint floatBitsToUint(float v) + { + union + { + float in; + uint out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec floatBitsToUint(vec const& v) + { + return detail::functor1::call(floatBitsToUint, v); + } + + GLM_FUNC_QUALIFIER float intBitsToFloat(int v) + { + union + { + int in; + float out; + } u; + + u.in = v; + + return u.out; + } + + template + GLM_FUNC_QUALIFIER vec intBitsToFloat(vec const& v) + { + return detail::functor1::call(intBitsToFloat, v); + } + + GLM_FUNC_QUALIFIER float uintBitsToFloat(uint 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'frexp' only accept floating-point inputs"); + + vec Result(0); + 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ldexp' only accept floating-point inputs"); + + vec Result(0); + 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/glm/detail/func_common_simd.inl b/glm/detail/func_common_simd.inl new file mode 100644 index 0000000..ce0032d --- /dev/null +++ b/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/glm/detail/func_exponential.inl b/glm/detail/func_exponential.inl new file mode 100644 index 0000000..2efcdc6 --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/detail/func_exponential_simd.inl b/glm/detail/func_exponential_simd.inl new file mode 100644 index 0000000..fb78951 --- /dev/null +++ b/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/glm/detail/func_geometric.inl b/glm/detail/func_geometric.inl new file mode 100644 index 0000000..404c990 --- /dev/null +++ b/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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/func_geometric_simd.inl b/glm/detail/func_geometric_simd.inl new file mode 100644 index 0000000..2076dae --- /dev/null +++ b/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/glm/detail/func_integer.inl b/glm/detail/func_integer.inl new file mode 100644 index 0000000..67177a0 --- /dev/null +++ b/glm/detail/func_integer.inl @@ -0,0 +1,392 @@ +/// @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 push +# pragma GCC diagnostic ignored "-Wlong-long" +# endif +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic push +# 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 = detail::mask(static_cast(Bits)) << Offset; + return (Base & ~Mask) | ((Insert << static_cast(Offset)) & Mask); + } + +#if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(push) +# pragma warning(disable : 4309) +#endif + + // 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; + } + +# if GLM_COMPILER & GLM_COMPILER_VC +# pragma warning(pop) +# endif + + // 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(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(sizeof(T) * 8)>::call(v); + } +}//namespace glm + +#if !GLM_HAS_EXTENDED_INTEGER_TYPE +# if GLM_COMPILER & GLM_COMPILER_GCC +# pragma GCC diagnostic pop +# endif +# if (GLM_COMPILER & GLM_COMPILER_CLANG) +# pragma clang diagnostic pop +# endif +#endif + +#if GLM_CONFIG_SIMD == GLM_ENABLE +# include "func_integer_simd.inl" +#endif + diff --git a/glm/detail/func_integer_simd.inl b/glm/detail/func_integer_simd.inl new file mode 100644 index 0000000..5600c84 --- /dev/null +++ b/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, static_cast(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, static_cast(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, static_cast(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/glm/detail/func_matrix.inl b/glm/detail/func_matrix.inl new file mode 100644 index 0000000..081761f --- /dev/null +++ b/glm/detail/func_matrix.inl @@ -0,0 +1,443 @@ +#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(1); + for(length_t i = 0; i < Result.length(); ++i) + Result[i] = x[i] * y[i]; + return Result; + } + }; + + template + struct compute_matrixCompMult_type { + GLM_FUNC_QUALIFIER static mat call(mat const& x, mat const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'matrixCompMult' only accept floating-point inputs, include to discard this restriction."); + return detail::compute_matrixCompMult::value>::call(x, y); + } + }; + + template + struct compute_outerProduct { + GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait::type call(vec const& c, vec const& r) + { + typename detail::outerProduct_trait::type m(0); + for(length_t i = 0; i < m.length(); ++i) + m[i] = c * r[i]; + return m; + } + }; + + template + struct compute_outerProduct_type { + GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait::type call(vec const& c, vec const& r) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'outerProduct' only accept floating-point inputs, include to discard this restriction."); + + return detail::compute_outerProduct::call(c, r); + } + }; + + 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(1); + 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(1); + 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(1); + 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(1); + 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(1); + 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(1); + 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(1); + 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(1); + 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(1); + 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_transpose_type { + GLM_FUNC_QUALIFIER static mat call(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'transpose' only accept floating-point inputs, include to discard this restriction."); + return detail::compute_transpose::value>::call(m); + } + }; + + 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_determinant_type{ + + GLM_FUNC_QUALIFIER static T call(mat const& m) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_GENTYPE, + "'determinant' only accept floating-point inputs, include to discard this restriction."); + return detail::compute_determinant::value>::call(m); + } + }; + + 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) + { + return detail::compute_matrixCompMult_type::is_iec559, detail::is_aligned::value>::call(x, y); + } + + template + GLM_FUNC_QUALIFIER typename detail::outerProduct_trait::type outerProduct(vec const& c, vec const& r) + { + return detail::compute_outerProduct_type::is_iec559>::call(c, r); + } + + template + GLM_FUNC_QUALIFIER typename mat::transpose_type transpose(mat const& m) + { + return detail::compute_transpose_type::is_iec559, detail::is_aligned::value>::call(m); + } + + template + GLM_FUNC_QUALIFIER T determinant(mat const& m) + { + return detail::compute_determinant_type::is_iec559, detail::is_aligned::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/glm/detail/func_matrix_simd.inl b/glm/detail/func_matrix_simd.inl new file mode 100644 index 0000000..b9bb461 --- /dev/null +++ b/glm/detail/func_matrix_simd.inl @@ -0,0 +1,252 @@ +#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( + &x[0].data, + &y[0].data, + &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 + +namespace detail +{ + 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) + { + 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 detail +}//namespace glm +#endif diff --git a/glm/detail/func_packing.inl b/glm/detail/func_packing.inl new file mode 100644 index 0000000..234b093 --- /dev/null +++ b/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/glm/detail/func_packing_simd.inl b/glm/detail/func_packing_simd.inl new file mode 100644 index 0000000..fd0fe8b --- /dev/null +++ b/glm/detail/func_packing_simd.inl @@ -0,0 +1,6 @@ +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm diff --git a/glm/detail/func_trigonometric.inl b/glm/detail/func_trigonometric.inl new file mode 100644 index 0000000..9e6d9cf --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'atan' only accept floating-point input"); + + return ::std::atan2(y, x); + } + + template + GLM_FUNC_QUALIFIER vec atan(vec const& y, vec const& x) + { + return detail::functor2::call(::std::atan2, y, x); + } + + 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/detail/func_trigonometric_simd.inl b/glm/detail/func_trigonometric_simd.inl new file mode 100644 index 0000000..e69de29 diff --git a/glm/detail/func_vector_relational.inl b/glm/detail/func_vector_relational.inl new file mode 100644 index 0000000..80c9e87 --- /dev/null +++ b/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/glm/detail/func_vector_relational_simd.inl b/glm/detail/func_vector_relational_simd.inl new file mode 100644 index 0000000..fd0fe8b --- /dev/null +++ b/glm/detail/func_vector_relational_simd.inl @@ -0,0 +1,6 @@ +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm diff --git a/glm/detail/glm.cpp b/glm/detail/glm.cpp new file mode 100644 index 0000000..e0755bd --- /dev/null +++ b/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/glm/detail/qualifier.hpp b/glm/detail/qualifier.hpp new file mode 100644 index 0000000..a6c96cc --- /dev/null +++ b/glm/detail/qualifier.hpp @@ -0,0 +1,229 @@ +#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/glm/detail/setup.hpp b/glm/detail/setup.hpp new file mode 100644 index 0000000..1664c89 --- /dev/null +++ b/glm/detail/setup.hpp @@ -0,0 +1,1188 @@ +#ifndef GLM_SETUP_INCLUDED + +#include +#include + +#define GLM_VERSION_MAJOR 1 +#define GLM_VERSION_MINOR 0 +#define GLM_VERSION_PATCH 0 +#define GLM_VERSION_REVISION 0 // Deprecated +#define GLM_VERSION 1000 // Deprecated +#define GLM_VERSION_MESSAGE "GLM: version 1.0.0" + +#define GLM_MAKE_API_VERSION(variant, major, minor, patch) \ + ((((uint32_t)(variant)) << 29U) | (((uint32_t)(major)) << 22U) | (((uint32_t)(minor)) << 12U) | ((uint32_t)(patch))) + +#define GLM_VERSION_COMPLETE GLM_MAKE_API_VERSION(0, GLM_VERSION_MAJOR, GLM_VERSION_MINOR, GLM_VERSION_PATCH) + +#define GLM_SETUP_INCLUDED GLM_VERSION + +#define GLM_GET_VERSION_VARIANT(version) ((uint32_t)(version) >> 29U) +#define GLM_GET_VERSION_MAJOR(version) (((uint32_t)(version) >> 22U) & 0x7FU) +#define GLM_GET_VERSION_MINOR(version) (((uint32_t)(version) >> 12U) & 0x3FFU) +#define GLM_GET_VERSION_PATCH(version) ((uint32_t)(version) & 0xFFFU) + +/////////////////////////////////////////////////////////////////////////////////// +// 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_CXX20_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_CXX20 (GLM_LANG_CXX17 | GLM_LANG_CXX20_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_CXX20) +# define GLM_LANG (GLM_LANG_CXX20 | 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_CXX20 | GLM_LANG_EXT) +# elif __cplusplus == 201703L || GLM_LANG_PLATFORM == 201703L +# define GLM_LANG (GLM_LANG_CXX17 | GLM_LANG_EXT) +# elif __cplusplus == 201402L || __cplusplus == 201406L || __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_CUDA_RTC) == GLM_COMPILER_CUDA_RTC +# define GLM_HAS_CXX11_STL 0 +#elif (GLM_COMPILER & GLM_COMPILER_HIP) +# 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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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 + +// [nodiscard] +#if GLM_LANG & GLM_LANG_CXX17_FLAG +# define GLM_NODISCARD [[nodiscard]] +#else +# define GLM_NODISCARD +#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)) || \ + ((GLM_COMPILER & GLM_COMPILER_HIP)))) +#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 + +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_NOEXCEPT 1 +#else +# define GLM_HAS_NOEXCEPT 0 +#endif + +#if GLM_HAS_NOEXCEPT +# define GLM_NOEXCEPT noexcept +#else +# define GLM_NOEXCEPT +#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 + +// User defines: GLM_CUDA_FORCE_DEVICE_FUNC, GLM_CUDA_FORCE_HOST_FUNC + +#if (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP) +# if defined(GLM_CUDA_FORCE_DEVICE_FUNC) && defined(GLM_CUDA_FORCE_HOST_FUNC) +# error "GLM error: GLM_CUDA_FORCE_DEVICE_FUNC and GLM_CUDA_FORCE_HOST_FUNC should not be defined at the same time, GLM by default generates both device and host code for CUDA compiler." +# endif//defined(GLM_CUDA_FORCE_DEVICE_FUNC) && defined(GLM_CUDA_FORCE_HOST_FUNC) + +# if defined(GLM_CUDA_FORCE_DEVICE_FUNC) +# define GLM_CUDA_FUNC_DEF __device__ +# define GLM_CUDA_FUNC_DECL __device__ +# elif defined(GLM_CUDA_FORCE_HOST_FUNC) +# define GLM_CUDA_FUNC_DEF __host__ +# define GLM_CUDA_FUNC_DECL __host__ +# else +# define GLM_CUDA_FUNC_DEF __device__ __host__ +# define GLM_CUDA_FUNC_DECL __device__ __host__ +# endif//defined(GLM_CUDA_FORCE_XXXX_FUNC) +#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) || (GLM_COMPILER & GLM_COMPILER_HIP) +# 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_CTOR_DECL GLM_CUDA_FUNC_DECL GLM_CONSTEXPR +#define GLM_FUNC_DISCARD_DECL GLM_CUDA_FUNC_DECL +#define GLM_FUNC_DECL GLM_NODISCARD GLM_CUDA_FUNC_DECL +#define GLM_FUNC_QUALIFIER GLM_CUDA_FUNC_DEF GLM_INLINE + +// Do not use CUDA function qualifiers on CUDA compiler when functions are made default +#if GLM_HAS_DEFAULTED_FUNCTIONS +# define GLM_DEFAULTED_FUNC_DECL +# define GLM_DEFAULTED_FUNC_QUALIFIER GLM_INLINE +#else +# define GLM_DEFAULTED_FUNC_DECL GLM_FUNC_DISCARD_DECL +# define GLM_DEFAULTED_FUNC_QUALIFIER GLM_FUNC_QUALIFIER +#endif//GLM_HAS_DEFAULTED_FUNCTIONS +#if !defined(GLM_FORCE_CTOR_INIT) +# define GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CUDA_FUNC_DECL +# define GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_DEFAULTED_FUNC_QUALIFIER +#else +# define GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_FUNC_DISCARD_DECL +# define GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_FUNC_QUALIFIER +#endif//GLM_FORCE_CTOR_INIT + +/////////////////////////////////////////////////////////////////////////////////// +// 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_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) && !defined(GLM_FORCE_XYZW_ONLY) +# 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 + +/////////////////////////////////////////////////////////////////////////////////// +// Allows using any scaler as float + +// #define GLM_FORCE_UNRESTRICTED_FLOAT + +#ifdef GLM_FORCE_UNRESTRICTED_FLOAT +# define GLM_CONFIG_UNRESTRICTED_FLOAT GLM_ENABLE +#else +# define GLM_CONFIG_UNRESTRICTED_FLOAT 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) || (GLM_COMPILER & GLM_COMPILER_HIP) +# 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 + +/////////////////////////////////////////////////////////////////////////////////// +// 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 +# define GLM_ASSERT_LENGTH(l, max) (assert ((l) < (max))) +#else +# define GLM_CONFIG_LENGTH_TYPE GLM_LENGTH_INT +# define GLM_ASSERT_LENGTH(l, max) (assert ((l) >= 0 && (l) < (max))) +#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 +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_ENABLE +# define GLM_DEFAULT = default +#else +# define GLM_CONFIG_DEFAULTED_FUNCTIONS GLM_DISABLE +# define GLM_DEFAULT +#endif + +#if GLM_CONFIG_CTOR_INIT == GLM_CTOR_INIT_DISABLE && GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_ENABLE +# define GLM_CONFIG_DEFAULTED_DEFAULT_CTOR GLM_ENABLE +# define GLM_DEFAULT_CTOR GLM_DEFAULT +#else +# define GLM_CONFIG_DEFAULTED_DEFAULT_CTOR GLM_DISABLE +# define GLM_DEFAULT_CTOR +#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_WARNINGS +# define GLM_SILENT_WARNINGS GLM_DISABLE +#else +# define GLM_SILENT_WARNINGS GLM_ENABLE +#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_CXX20_FLAG) && (GLM_LANG & GLM_LANG_EXT) +# pragma message("GLM: C++ 20 with extensions") +# elif (GLM_LANG & GLM_LANG_CXX20_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_HIP +# pragma message("GLM: HIP 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/glm/detail/type_float.hpp b/glm/detail/type_float.hpp new file mode 100644 index 0000000..c8037eb --- /dev/null +++ b/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/glm/detail/type_half.hpp b/glm/detail/type_half.hpp new file mode 100644 index 0000000..40b8bec --- /dev/null +++ b/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/glm/detail/type_half.inl b/glm/detail/type_half.inl new file mode 100644 index 0000000..5d239cf --- /dev/null +++ b/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 * 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/glm/detail/type_mat2x2.hpp b/glm/detail/type_mat2x2.hpp new file mode 100644 index 0000000..82e9f66 --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<2, 2, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T const& x1, T const& y1, + T const& x2, T const& y2); + GLM_CTOR_DECL mat( + col_type const& v1, + col_type const& v2); + + // -- Conversions -- + + template + GLM_CTOR_DECL mat( + U const& x1, V const& y1, + M const& x2, N const& y2); + + template + GLM_CTOR_DECL mat( + vec<2, U, Q> const& v1, + vec<2, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator+=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator-=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator*=(mat<2, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator/=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator/=(mat<2, 2, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 2, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator-(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator*(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<2, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator/(mat<2, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 2, T, Q> operator/(T scalar, mat<2, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR bool operator==(mat<2, 2, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat2x2.inl b/glm/detail/type_mat2x2.inl new file mode 100644 index 0000000..afb2b31 --- /dev/null +++ b/glm/detail/type_mat2x2.inl @@ -0,0 +1,536 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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{col_type(m[0]), col_type(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 GLM_CONSTEXPR typename mat<2, 2, T, Q>::col_type& mat<2, 2, T, Q>::operator[](typename mat<2, 2, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 2, T, Q>& mat<2, 2, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 2, T, Q> operator+(mat<2, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat2x3.hpp b/glm/detail/type_mat2x3.hpp new file mode 100644 index 0000000..b65d1c5 --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<2, 3, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, T z0, + T x1, T y1, T z1); + GLM_CTOR_DECL mat( + col_type const& v0, + col_type const& v1); + + // -- Conversions -- + + template + GLM_CTOR_DECL mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2); + + template + GLM_CTOR_DECL mat( + vec<3, U, Q> const& v1, + vec<3, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator+=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator-=(mat<2, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 3, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator-(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(T scalar, mat<2, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<2, 3, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator/(mat<2, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator/(T scalar, mat<2, 3, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<2, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat2x3.inl b/glm/detail/type_mat2x3.inl new file mode 100644 index 0000000..345ac8a --- /dev/null +++ b/glm/detail/type_mat2x3.inl @@ -0,0 +1,510 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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{col_type(m[0]), col_type(m[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 GLM_CONSTEXPR typename mat<2, 3, T, Q>::col_type & mat<2, 3, T, Q>::operator[](typename mat<2, 3, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 3, T, Q> & mat<2, 3, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 3, T, Q> operator+(mat<2, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat2x4.hpp b/glm/detail/type_mat2x4.hpp new file mode 100644 index 0000000..7ca43e5 --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<2, 4, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, T z0, T w0, + T x1, T y1, T z1, T w1); + GLM_CTOR_DECL 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_CTOR_DECL mat( + X1 x1, Y1 y1, Z1 z1, W1 w1, + X2 x2, Y2 y2, Z2 z2, W2 w2); + + template + GLM_CTOR_DECL mat( + vec<4, U, Q> const& v1, + vec<4, V, Q> const& v2); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator+=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator-=(mat<2, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<2, 4, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator-(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(T scalar, mat<2, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<2, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<2, 4, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator/(mat<2, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator/(T scalar, mat<2, 4, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<2, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat2x4.inl b/glm/detail/type_mat2x4.inl new file mode 100644 index 0000000..1c182c9 --- /dev/null +++ b/glm/detail/type_mat2x4.inl @@ -0,0 +1,520 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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{col_type(m[0]), col_type(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 GLM_CONSTEXPR typename mat<2, 4, T, Q>::col_type & mat<2, 4, T, Q>::operator[](typename mat<2, 4, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<2, 4, T, Q>& mat<2, 4, T, Q>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 4, T, Q> operator+(mat<2, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat3x2.hpp b/glm/detail/type_mat3x2.hpp new file mode 100644 index 0000000..0249bef --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<3, 2, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, + T x1, T y1, + T x2, T y2); + GLM_CTOR_DECL 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_CTOR_DECL mat( + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template + GLM_CTOR_DECL mat( + vec<2, V1, Q> const& v1, + vec<2, V2, Q> const& v2, + vec<2, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator+=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator-=(mat<3, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 2, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator-(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(T scalar, mat<3, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<3, 2, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator/(mat<3, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator/(T scalar, mat<3, 2, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<3, 2, T, Q> const& m1, mat<3, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat3x2.inl b/glm/detail/type_mat3x2.inl new file mode 100644 index 0000000..cd9f46c --- /dev/null +++ b/glm/detail/type_mat3x2.inl @@ -0,0 +1,532 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 GLM_CONSTEXPR typename mat<3, 2, T, Q>::col_type & mat<3, 2, T, Q>::operator[](typename mat<3, 2, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<3, 2, T, Q> operator+(mat<3, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat3x3.hpp b/glm/detail/type_mat3x3.hpp new file mode 100644 index 0000000..e4cbbdc --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<3, 3, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, T z0, + T x1, T y1, T z1, + T x2, T y2, T z2); + GLM_CTOR_DECL 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_CTOR_DECL mat( + X1 x1, Y1 y1, Z1 z1, + X2 x2, Y2 y2, Z2 z2, + X3 x3, Y3 y3, Z3 z3); + + template + GLM_CTOR_DECL mat( + vec<3, V1, Q> const& v1, + vec<3, V2, Q> const& v2, + vec<3, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator+=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator-=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator*=(mat<3, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator/=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator/=(mat<3, 3, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 3, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator-(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<3, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator/(mat<3, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator/(T scalar, mat<3, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat3x3.inl b/glm/detail/type_mat3x3.inl new file mode 100644 index 0000000..a9b633a --- /dev/null +++ b/glm/detail/type_mat3x3.inl @@ -0,0 +1,601 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 GLM_CONSTEXPR typename mat<3, 3, T, Q>::col_type & mat<3, 3, T, Q>::operator[](typename mat<3, 3, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<3, 3, T, Q> operator+(mat<3, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 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]); + } +} //namespace glm diff --git a/glm/detail/type_mat3x4.hpp b/glm/detail/type_mat3x4.hpp new file mode 100644 index 0000000..f9913d2 --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<3, 4, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T scalar); + GLM_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL mat( + vec<4, V1, Q> const& v1, + vec<4, V2, Q> const& v2, + vec<4, V3, Q> const& v3); + + // -- Matrix conversions -- + + template + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator+=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator-=(mat<3, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<3, 4, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator-(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(T scalar, mat<3, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<2, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<3, 4, T, Q> const& m1, mat<3, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator/(mat<3, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator/(T scalar, mat<3, 4, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<3, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat3x4.inl b/glm/detail/type_mat3x4.inl new file mode 100644 index 0000000..209e9d9 --- /dev/null +++ b/glm/detail/type_mat3x4.inl @@ -0,0 +1,578 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 GLM_CONSTEXPR typename mat<3, 4, T, Q>::col_type & mat<3, 4, T, Q>::operator[](typename mat<3, 4, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<3, 4, T, Q> operator+(mat<3, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat4x2.hpp b/glm/detail/type_mat4x2.hpp new file mode 100644 index 0000000..7057d4c --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<4, 2, T, P> const& m); + + GLM_CTOR_DECL mat(T scalar); + GLM_CTOR_DECL mat( + T x0, T y0, + T x1, T y1, + T x2, T y2, + T x3, T y3); + GLM_CTOR_DECL 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_CTOR_DECL mat( + X0 x0, Y0 y0, + X1 x1, Y1 y1, + X2 x2, Y2 y2, + X3 x3, Y3 y3); + + template + GLM_CTOR_DECL 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_CTOR_DECL mat(mat<4, 2, U, P> const& m); + + GLM_CTOR_DECL mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator+=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator-=(mat<4, 2, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator++ (); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 2, T, Q> & operator-- (); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator-(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(T scalar, mat<4, 2, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator*(mat<4, 2, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator/(mat<4, 2, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 2, T, Q> operator/(T scalar, mat<4, 2, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<4, 2, T, Q> const& m1, mat<4, 2, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat4x2.inl b/glm/detail/type_mat4x2.inl new file mode 100644 index 0000000..2b9b617 --- /dev/null +++ b/glm/detail/type_mat4x2.inl @@ -0,0 +1,574 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 GLM_CONSTEXPR typename mat<4, 2, T, Q>::col_type & mat<4, 2, T, Q>::operator[](typename mat<4, 2, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 2, T, Q> operator+(mat<4, 2, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat4x3.hpp b/glm/detail/type_mat4x3.hpp new file mode 100644 index 0000000..52a38d8 --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<4, 3, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T s); + GLM_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL mat(mat<4, 3, U, P> const& m); + + GLM_CTOR_DECL mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL mat(mat<3, 4, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator+=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator-=(mat<4, 3, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q> & operator/=(U s); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q>& operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 3, T, Q>& operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(T scalar, mat<4, 3, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 3, T, Q> operator/(T scalar, mat<4, 3, T, Q> const& m); + + // -- Boolean operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR bool operator==(mat<4, 3, T, Q> const& m1, mat<4, 3, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat4x3.inl b/glm/detail/type_mat4x3.inl new file mode 100644 index 0000000..8430bc0 --- /dev/null +++ b/glm/detail/type_mat4x3.inl @@ -0,0 +1,598 @@ +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 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 GLM_CONSTEXPR typename mat<4, 3, T, Q>::col_type & mat<4, 3, T, Q>::operator[](typename mat<4, 3, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary updatable operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 3, T, Q> operator+(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 3, T, Q> operator-(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar, + m[3] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 3, T, Q> operator*(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator*(T scalar, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 3, T, Q> operator/(mat<4, 3, T, Q> const& m, T scalar) + { + return mat<4, 3, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar, + m[3] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 3, T, Q> operator/(T scalar, mat<4, 3, T, Q> const& m) + { + return mat<4, 3, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2], + scalar / m[3]); + } + + // -- Boolean operators -- + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat4x4.hpp b/glm/detail/type_mat4x4.hpp new file mode 100644 index 0000000..ad7597b --- /dev/null +++ b/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 GLM_CONSTEXPR col_type & operator[](length_type i) GLM_NOEXCEPT; + GLM_FUNC_DECL GLM_CONSTEXPR col_type const& operator[](length_type i) const GLM_NOEXCEPT; + + // -- Constructors -- + + GLM_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR mat() GLM_DEFAULT_CTOR; + template + GLM_CTOR_DECL mat(mat<4, 4, T, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(T s); + GLM_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL GLM_EXPLICIT mat(mat<4, 4, U, P> const& m); + + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 3, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<2, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 2, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<3, 4, T, Q> const& x); + GLM_CTOR_DECL GLM_EXPLICIT mat(mat<4, 3, T, Q> const& x); + + // -- Unary arithmetic operators -- + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator+=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator+=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator-=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator-=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator*=(mat<4, 4, U, Q> const& m); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator/=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator/=(mat<4, 4, U, Q> const& m); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator++(); + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR mat<4, 4, T, Q> & operator--(); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator++(int); + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator--(int); + }; + + // -- Unary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m); + + // -- Binary operators -- + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<2, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<2, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<3, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<3, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T scalar); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat<4, 4, T, Q> operator/(T scalar, mat<4, 4, T, Q> const& m); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR bool operator==(mat<4, 4, T, Q> const& m1, mat<4, 4, T, Q> const& m2); + + template + GLM_FUNC_DECL GLM_CONSTEXPR 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/glm/detail/type_mat4x4.inl b/glm/detail/type_mat4x4.inl new file mode 100644 index 0000000..116731d --- /dev/null +++ b/glm/detail/type_mat4x4.inl @@ -0,0 +1,706 @@ +#include "../matrix.hpp" + +namespace glm +{ + // -- Constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 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 GLM_CONSTEXPR typename mat<4, 4, T, Q>::col_type & mat<4, 4, T, Q>::operator[](typename mat<4, 4, T, Q>::length_type i) GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(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 GLM_NOEXCEPT + { + GLM_ASSERT_LENGTH(i, this->length()); + return this->value[i]; + } + + // -- Unary arithmetic operators -- + + template + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m) + { + return m; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 4, T, Q> operator+(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator+(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] + scalar, + m[1] + scalar, + m[2] + scalar, + m[3] + scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 4, T, Q> operator-(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] - scalar, + m[1] - scalar, + m[2] - scalar, + m[3] - scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator-(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + scalar - m[0], + scalar - m[1], + scalar - m[2], + scalar - m[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 4, T, Q> operator*(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator*(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + m[0] * scalar, + m[1] * scalar, + m[2] * scalar, + m[3] * scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR mat<4, 4, T, Q> operator/(mat<4, 4, T, Q> const& m, T scalar) + { + return mat<4, 4, T, Q>( + m[0] / scalar, + m[1] / scalar, + m[2] / scalar, + m[3] / scalar); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR mat<4, 4, T, Q> operator/(T scalar, mat<4, 4, T, Q> const& m) + { + return mat<4, 4, T, Q>( + scalar / m[0], + scalar / m[1], + scalar / m[2], + scalar / m[3]); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/detail/type_mat4x4_simd.inl b/glm/detail/type_mat4x4_simd.inl new file mode 100644 index 0000000..fb3a16f --- /dev/null +++ b/glm/detail/type_mat4x4_simd.inl @@ -0,0 +1,6 @@ +/// @ref core + +namespace glm +{ + +}//namespace glm diff --git a/glm/detail/type_quat.hpp b/glm/detail/type_quat.hpp new file mode 100644 index 0000000..1b41e15 --- /dev/null +++ b/glm/detail/type_quat.hpp @@ -0,0 +1,193 @@ +/// @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 +{ +# 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 + + template + struct qua + { + // -- Implementation detail -- + + typedef qua type; + typedef T value_type; + + // -- Data -- + +# 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 + + // -- 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_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR qua() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR qua(qua const& q) GLM_DEFAULT; + template + GLM_CTOR_DECL qua(qua const& q); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL qua(T s, vec<3, T, Q> const& v); + +# ifdef GLM_FORCE_QUAT_DATA_XYZW + GLM_CTOR_DECL qua(T x, T y, T z, T w); +# else + GLM_CTOR_DECL qua(T w, T x, T y, T z); +# endif + + GLM_FUNC_DECL static GLM_CONSTEXPR qua wxyz(T w, T x, T y, T z); + + // -- Conversion constructors -- + + template + GLM_CTOR_DECL 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_DISCARD_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_CTOR_DECL GLM_EXPLICIT qua(vec<3, T, Q> const& eulerAngles); + GLM_CTOR_DECL GLM_EXPLICIT qua(mat<3, 3, T, Q> const& q); + GLM_CTOR_DECL GLM_EXPLICIT qua(mat<4, 4, T, Q> const& q); + + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR qua& operator=(qua const& q) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator+=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator-=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator*=(qua const& q); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator*=(U s); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR qua& operator/=(U s); + }; + +# 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 + + // -- 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/glm/detail/type_quat.inl b/glm/detail/type_quat.inl new file mode 100644 index 0000000..6a8f987 --- /dev/null +++ b/glm/detail/type_quat.inl @@ -0,0 +1,424 @@ +#include "../trigonometric.hpp" +#include "../exponential.hpp" +#include "../ext/quaternion_common.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::wxyz(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::wxyz(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::wxyz(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::wxyz(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) + { + GLM_ASSERT_LENGTH(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 + { + GLM_ASSERT_LENGTH(i, this->length()); +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + return (&w)[i]; +# else + return (&x)[i]; +# endif + } + + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_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 +# ifdef GLM_FORCE_QUAT_DATA_XYZW + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(T _x, T _y, T _z, T _w) +# else + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua::qua(T _w, T _x, T _y, T _z) +# endif +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + : w(_w), x(_x), y(_y), z(_z) +# else + : x(_x), y(_y), z(_z), w(_w) +# endif + {} + + template + GLM_CONSTEXPR qua qua::wxyz(T w, T x, T y, T z) { +# ifdef GLM_FORCE_QUAT_DATA_XYZW + return qua(x, y, z, w); +# else + return qua(w, x, y, z); +# 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::wxyz(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 GLM_CONSTEXPR qua::qua(mat<3, 3, T, Q> const& m) + { + *this = quat_cast(m); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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_DEFAULTED_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::wxyz(-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::wxyz( + 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::wxyz( + 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/glm/detail/type_quat_simd.inl b/glm/detail/type_quat_simd.inl new file mode 100644 index 0000000..fa6da19 --- /dev/null +++ b/glm/detail/type_quat_simd.inl @@ -0,0 +1,208 @@ +/// @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) + { + qua 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) + { +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + __m128 const q_wwww = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 const q_swp0 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 1, 3, 2)); + __m128 const q_swp1 = _mm_shuffle_ps(q.data, q.data, _MM_SHUFFLE(0, 2, 1, 3)); + __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; +# else + __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; +# endif + } + }; +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH & GLM_ARCH_SSE2_BIT diff --git a/glm/detail/type_vec1.hpp b/glm/detail/type_vec1.hpp new file mode 100644 index 0000000..0cc7b5d --- /dev/null +++ b/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_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<1, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL GLM_EXPLICIT vec(vec<1, U, P> const& v); + + // -- Swizzle constructors -- +/* +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_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_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator/=(vec<1, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator++(); + GLM_FUNC_DISCARD_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_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<1, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DISCARD_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/glm/detail/type_vec1.inl b/glm/detail/type_vec1.inl new file mode 100644 index 0000000..18411e7 --- /dev/null +++ b/glm/detail/type_vec1.inl @@ -0,0 +1,553 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR vec<1, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0) +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_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_DEFAULTED_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 |= 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; + } + + // -- 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/glm/detail/type_vec2.hpp b/glm/detail/type_vec2.hpp new file mode 100644 index 0000000..2ddfb43 --- /dev/null +++ b/glm/detail/type_vec2.hpp @@ -0,0 +1,402 @@ +/// @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; +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(T, Q, x, y) +# endif//GLM_CONFIG_SWIZZLE +# 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_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<2, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL explicit vec(T scalar); + GLM_CTOR_DECL vec(T x, T y); + + // -- Conversion constructors -- + + template + GLM_CTOR_DECL 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_CTOR_DECL vec(A x, B y); + template + GLM_CTOR_DECL vec(vec<1, A, Q> const& x, B y); + template + GLM_CTOR_DECL vec(A x, vec<1, B, Q> const& y); + template + GLM_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL GLM_EXPLICIT vec(vec<2, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_DECL 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_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator+=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator-=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator*=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator/=(vec<2, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator++(); + GLM_FUNC_DISCARD_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_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator%=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator&=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator|=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator^=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator<<=(vec<2, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<2, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_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/glm/detail/type_vec2.inl b/glm/detail/type_vec2.inl new file mode 100644 index 0000000..e840899 --- /dev/null +++ b/glm/detail/type_vec2.inl @@ -0,0 +1,915 @@ +/// @ref core + +#include "./compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR vec<2, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0) +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_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) + { + GLM_ASSERT_LENGTH(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 + { + GLM_ASSERT_LENGTH(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_DEFAULTED_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/glm/detail/type_vec3.hpp b/glm/detail/type_vec3.hpp new file mode 100644 index 0000000..4bf8395 --- /dev/null +++ b/glm/detail/type_vec3.hpp @@ -0,0 +1,436 @@ +/// @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" +# pragma clang diagnostic ignored "-Wpadded" +# 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; +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(T, Q, x, y, z) +# endif//GLM_CONFIG_SWIZZLE +# 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_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<3, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL explicit vec(T scalar); + GLM_CTOR_DECL vec(T a, T b, T c); + + // -- Conversion scalar constructors -- + + template + GLM_CTOR_DECL 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_CTOR_DECL vec(X x, Y y, Z z); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, Z _z); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, Z _z); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z); + template + GLM_CTOR_DECL vec(X _x, Y _y, vec<1, Z, Q> const& _z); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z); + template + GLM_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL GLM_EXPLICIT vec(vec<3, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec(detail::_swizzle<3, T, Q, E0, E1, E2, -1> const& that) + { + *this = that(); + } + + template + GLM_FUNC_DISCARD_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_DISCARD_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_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<3, T, Q>& operator=(vec<3, T, Q> const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator+=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator-=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator*=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator/=(vec<3, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator++(); + GLM_FUNC_DISCARD_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_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator%=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator&=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator|=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator^=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator<<=(vec<3, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<3, T, Q> & operator>>=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_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/glm/detail/type_vec3.inl b/glm/detail/type_vec3.inl new file mode 100644 index 0000000..4e44047 --- /dev/null +++ b/glm/detail/type_vec3.inl @@ -0,0 +1,1070 @@ +/// @ref core + +#include "compute_vector_relational.hpp" + +namespace glm +{ + // -- Implicit basic constructors -- + +# if GLM_CONFIG_DEFAULTED_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_QUALIFIER GLM_CONSTEXPR vec<3, T, Q>::vec() +# if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE + : x(0), y(0), z(0) +# endif + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_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) + { + GLM_ASSERT_LENGTH(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 + { + GLM_ASSERT_LENGTH(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_DEFAULTED_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/glm/detail/type_vec4.hpp b/glm/detail/type_vec4.hpp new file mode 100644 index 0000000..15f122f --- /dev/null +++ b/glm/detail/type_vec4.hpp @@ -0,0 +1,508 @@ +/// @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; +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_FUNCTION + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(T, Q, x, y, z, w) +# endif//GLM_CONFIG_SWIZZLE +# 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_DEFAULTED_DEFAULT_CTOR_DECL GLM_CONSTEXPR vec() GLM_DEFAULT_CTOR; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec(vec<4, T, Q> const& v) GLM_DEFAULT; + template + GLM_CTOR_DECL vec(vec<4, T, P> const& v); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL explicit vec(T scalar); + GLM_CTOR_DECL vec(T x, T y, T z, T w); + + // -- Conversion scalar constructors -- + + template + GLM_CTOR_DECL 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_CTOR_DECL vec(X _x, Y _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, W _w); + template + GLM_CTOR_DECL vec(X _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, W _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, vec<1, Y, Q> const& _y, Z _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(X _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(vec<1, X, Q> const& _x, Y _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL vec(X _x, vec<1, Y, Q> const& _y, vec<1, Z, Q> const& _z, vec<1, W, Q> const& _w); + template + GLM_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL 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_CTOR_DECL GLM_EXPLICIT vec(vec<4, U, P> const& v); + + // -- Swizzle constructors -- +# if GLM_CONFIG_SWIZZLE == GLM_SWIZZLE_OPERATOR + template + GLM_FUNC_DISCARD_DECL vec(detail::_swizzle<4, T, Q, E0, E1, E2, E3> const& that) + { + *this = that(); + } + + template + GLM_FUNC_DISCARD_DECL 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_DISCARD_DECL 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_DISCARD_DECL 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_DISCARD_DECL 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_DISCARD_DECL 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_DISCARD_DECL 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_DEFAULTED_FUNC_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, T, Q> const& v) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator+=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator-=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator*=(vec<4, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(U scalar); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<1, U, Q> const& v); + template + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q>& operator/=(vec<4, U, Q> const& v); + + // -- Increment and decrement operators -- + + GLM_FUNC_DISCARD_DECL GLM_CONSTEXPR vec<4, T, Q> & operator++(); + GLM_FUNC_DISCARD_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 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& 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& 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& 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/glm/detail/type_vec4.inl b/glm/detail/type_vec4.inl new file mode 100644 index 0000000..d48fae7 --- /dev/null +++ b/glm/detail/type_vec4.inl @@ -0,0 +1,1142 @@ +/// @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_DEFAULT_CTOR == GLM_DISABLE + template + GLM_DEFAULTED_DEFAULT_CTOR_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 + {} +# endif + +# if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE + template + GLM_DEFAULTED_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) + { + GLM_ASSERT_LENGTH(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 + { + GLM_ASSERT_LENGTH(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_DEFAULTED_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 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 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 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 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/glm/detail/type_vec4_simd.inl b/glm/detail/type_vec4_simd.inl new file mode 100644 index 0000000..816ef45 --- /dev/null +++ b/glm/detail/type_vec4_simd.inl @@ -0,0 +1,788 @@ +#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_cmpneq_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, int, 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; +#if GLM_ARCH & GLM_ARCH_ARMV8_BIT + Result.data = vdivq_f32(a.data, b.data); +#else + /* Arm assembler reference: + * + * The Newton-Raphson iteration: x[n+1] = x[n] * (2 - d * x[n]) + * converges to (1/d) if x0 is the result of VRECPE applied to d. + * + * Note: The precision usually improves with two interactions, but more than two iterations are not helpful. */ + float32x4_t x = vrecpeq_f32(b.data); + x = vmulq_f32(vrecpsq_f32(b.data, x), x); + x = vmulq_f32(vrecpsq_f32(b.data, x), x); + Result.data = vmulq_f32(a.data, x); +#endif + 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_u32(cmp), vget_high_u32(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_u32(cmp), vget_high_u32(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_u32(cmp), vget_high_u32(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/glm/exponential.hpp b/glm/exponential.hpp new file mode 100644 index 0000000..1614f76 --- /dev/null +++ b/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 v, i.e., e^v. + /// + /// @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/glm/ext.hpp b/glm/ext.hpp new file mode 100644 index 0000000..f9ac369 --- /dev/null +++ b/glm/ext.hpp @@ -0,0 +1,267 @@ +/// @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_reciprocal.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_reciprocal.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/common.hpp" +#include "./gtx/compatibility.hpp" +#include "./gtx/component_wise.hpp" +#include "./gtx/dual_quaternion.hpp" +#include "./gtx/easing.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" + +#if __cplusplus >= 201103L +#include "./gtx/hash.hpp" +#endif + +#include "./gtx/integer.hpp" +#include "./gtx/intersect.hpp" +#include "./gtx/io.hpp" +#include "./gtx/log_base.hpp" +#include "./gtx/matrix_cross_product.hpp" +#include "./gtx/matrix_decompose.hpp" +#include "./gtx/matrix_factorisation.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/pca.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_normalized_axis.hpp" +#include "./gtx/rotate_vector.hpp" +#include "./gtx/spline.hpp" +#include "./gtx/std_based_type.hpp" +#if !((GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP)) +# 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/glm/ext/_matrix_vectorize.hpp b/glm/ext/_matrix_vectorize.hpp new file mode 100644 index 0000000..0d08117 --- /dev/null +++ b/glm/ext/_matrix_vectorize.hpp @@ -0,0 +1,128 @@ +#pragma once + +namespace glm { + + namespace detail { + + template class mat, length_t C, length_t R, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<2, 2, T, Q> call(Ret (*Func)(T x), mat<2, 2, T, Q> const &x) { + return mat<2, 2, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), + Func(x[1][0]), Func(x[1][1]) + ); + } + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<2, 3, T, Q> call(Ret (*Func)(T x), mat<2, 3, T, Q> const &x) { + return mat<2, 3, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<2, 4, T, Q> call(Ret (*Func)(T x), mat<2, 4, T, Q> const &x) { + return mat<2, 4, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), Func(x[0][3]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), Func(x[1][3]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<3, 2, T, Q> call(Ret (*Func)(T x), mat<3, 2, T, Q> const &x) { + return mat<3, 2, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), + Func(x[1][0]), Func(x[1][1]), + Func(x[2][0]), Func(x[2][1]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<3, 3, T, Q> call(Ret (*Func)(T x), mat<3, 3, T, Q> const &x) { + return mat<3, 3, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<3, 4, T, Q> call(Ret (*Func)(T x), mat<3, 4, T, Q> const &x) { + return mat<3, 4, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), Func(x[0][3]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), Func(x[1][3]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]), Func(x[2][3]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<4, 2, T, Q> call(Ret (*Func)(T x), mat<4, 2, T, Q> const &x) { + return mat<4, 2, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), + Func(x[1][0]), Func(x[1][1]), + Func(x[2][0]), Func(x[2][1]), + Func(x[3][0]), Func(x[3][1]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<4, 3, T, Q> call(Ret (*Func)(T x), mat<4, 3, T, Q> const &x) { + return mat<4, 3, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]), + Func(x[3][0]), Func(x[3][1]), Func(x[3][2]) + ); + } + + }; + + template class mat, typename Ret, typename T, qualifier Q> + struct matrix_functor_1 { + + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat<4, 4, T, Q> call(Ret (*Func)(T x), mat<4, 4, T, Q> const &x) { + return mat<4, 4, Ret, Q>( + Func(x[0][0]), Func(x[0][1]), Func(x[0][2]), Func(x[0][3]), + Func(x[1][0]), Func(x[1][1]), Func(x[1][2]), Func(x[1][3]), + Func(x[2][0]), Func(x[2][1]), Func(x[2][2]), Func(x[2][3]), + Func(x[3][0]), Func(x[3][1]), Func(x[3][2]), Func(x[3][3]) + ); + } + + }; + + } + +}// namespace glm diff --git a/glm/ext/matrix_clip_space.hpp b/glm/ext/matrix_clip_space.hpp new file mode 100644 index 0000000..43579b8 --- /dev/null +++ b/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 left-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 right-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, symmetric 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, symmetric 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, symmetric 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, symmetric 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 symmetric 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 symmetric 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, symmetric 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, symmetric 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 symmetric 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/glm/ext/matrix_clip_space.inl b/glm/ext/matrix_clip_space.inl new file mode 100644 index 0000000..27fb6a1 --- /dev/null +++ b/glm/ext/matrix_clip_space.inl @@ -0,0 +1,595 @@ +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_NO(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> infinitePerspectiveRH_ZO(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] = - zNear; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, defaultp> infinitePerspectiveLH_NO(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> infinitePerspectiveLH_ZO(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] = - 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_ZO + return infinitePerspectiveLH_ZO(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_LH_NO + return infinitePerspectiveLH_NO(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_ZO + return infinitePerspectiveRH_ZO(fovy, aspect, zNear); +# elif GLM_CONFIG_CLIP_CONTROL == GLM_CLIP_CONTROL_RH_NO + return infinitePerspectiveRH_NO(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/glm/ext/matrix_common.hpp b/glm/ext/matrix_common.hpp new file mode 100644 index 0000000..6bb3d06 --- /dev/null +++ b/glm/ext/matrix_common.hpp @@ -0,0 +1,39 @@ +/// @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_common 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); + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat abs(mat const& x); + + /// @} +}//namespace glm + +#include "matrix_common.inl" diff --git a/glm/ext/matrix_common.inl b/glm/ext/matrix_common.inl new file mode 100644 index 0000000..1be4222 --- /dev/null +++ b/glm/ext/matrix_common.inl @@ -0,0 +1,34 @@ +#include "../matrix.hpp" + +#include "_matrix_vectorize.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); + } + + template + struct compute_abs_matrix + { + GLM_FUNC_QUALIFIER GLM_CONSTEXPR static mat call(mat const& x) + { + return detail::matrix_functor_1::call(abs, x); + } + }; + + template + GLM_FUNC_DECL GLM_CONSTEXPR mat abs(mat const& x) + { + return compute_abs_matrix::value>::call(x); + } + +}//namespace glm diff --git a/glm/ext/matrix_double2x2.hpp b/glm/ext/matrix_double2x2.hpp new file mode 100644 index 0000000..94dca54 --- /dev/null +++ b/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/glm/ext/matrix_double2x2_precision.hpp b/glm/ext/matrix_double2x2_precision.hpp new file mode 100644 index 0000000..9e2c174 --- /dev/null +++ b/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/glm/ext/matrix_double2x3.hpp b/glm/ext/matrix_double2x3.hpp new file mode 100644 index 0000000..bfef87a --- /dev/null +++ b/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/glm/ext/matrix_double2x3_precision.hpp b/glm/ext/matrix_double2x3_precision.hpp new file mode 100644 index 0000000..098fb60 --- /dev/null +++ b/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/glm/ext/matrix_double2x4.hpp b/glm/ext/matrix_double2x4.hpp new file mode 100644 index 0000000..499284b --- /dev/null +++ b/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/glm/ext/matrix_double2x4_precision.hpp b/glm/ext/matrix_double2x4_precision.hpp new file mode 100644 index 0000000..9b61ebc --- /dev/null +++ b/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/glm/ext/matrix_double3x2.hpp b/glm/ext/matrix_double3x2.hpp new file mode 100644 index 0000000..dd23f36 --- /dev/null +++ b/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/glm/ext/matrix_double3x2_precision.hpp b/glm/ext/matrix_double3x2_precision.hpp new file mode 100644 index 0000000..068d9e9 --- /dev/null +++ b/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/glm/ext/matrix_double3x3.hpp b/glm/ext/matrix_double3x3.hpp new file mode 100644 index 0000000..53572b7 --- /dev/null +++ b/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/glm/ext/matrix_double3x3_precision.hpp b/glm/ext/matrix_double3x3_precision.hpp new file mode 100644 index 0000000..8691e78 --- /dev/null +++ b/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/glm/ext/matrix_double3x4.hpp b/glm/ext/matrix_double3x4.hpp new file mode 100644 index 0000000..c572d63 --- /dev/null +++ b/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/glm/ext/matrix_double3x4_precision.hpp b/glm/ext/matrix_double3x4_precision.hpp new file mode 100644 index 0000000..f040217 --- /dev/null +++ b/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/glm/ext/matrix_double4x2.hpp b/glm/ext/matrix_double4x2.hpp new file mode 100644 index 0000000..9b229f4 --- /dev/null +++ b/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/glm/ext/matrix_double4x2_precision.hpp b/glm/ext/matrix_double4x2_precision.hpp new file mode 100644 index 0000000..6ad18ba --- /dev/null +++ b/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/glm/ext/matrix_double4x3.hpp b/glm/ext/matrix_double4x3.hpp new file mode 100644 index 0000000..dca4cf9 --- /dev/null +++ b/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/glm/ext/matrix_double4x3_precision.hpp b/glm/ext/matrix_double4x3_precision.hpp new file mode 100644 index 0000000..f7371de --- /dev/null +++ b/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/glm/ext/matrix_double4x4.hpp b/glm/ext/matrix_double4x4.hpp new file mode 100644 index 0000000..81e1bf6 --- /dev/null +++ b/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/glm/ext/matrix_double4x4_precision.hpp b/glm/ext/matrix_double4x4_precision.hpp new file mode 100644 index 0000000..4c36a84 --- /dev/null +++ b/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/glm/ext/matrix_float2x2.hpp b/glm/ext/matrix_float2x2.hpp new file mode 100644 index 0000000..53df921 --- /dev/null +++ b/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/glm/ext/matrix_float2x2_precision.hpp b/glm/ext/matrix_float2x2_precision.hpp new file mode 100644 index 0000000..898b6db --- /dev/null +++ b/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/glm/ext/matrix_float2x3.hpp b/glm/ext/matrix_float2x3.hpp new file mode 100644 index 0000000..6f68822 --- /dev/null +++ b/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/glm/ext/matrix_float2x3_precision.hpp b/glm/ext/matrix_float2x3_precision.hpp new file mode 100644 index 0000000..50c1032 --- /dev/null +++ b/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/glm/ext/matrix_float2x4.hpp b/glm/ext/matrix_float2x4.hpp new file mode 100644 index 0000000..30f30de --- /dev/null +++ b/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/glm/ext/matrix_float2x4_precision.hpp b/glm/ext/matrix_float2x4_precision.hpp new file mode 100644 index 0000000..079d638 --- /dev/null +++ b/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/glm/ext/matrix_float3x2.hpp b/glm/ext/matrix_float3x2.hpp new file mode 100644 index 0000000..280d0a3 --- /dev/null +++ b/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_matrix + /// @{ + + /// 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/glm/ext/matrix_float3x2_precision.hpp b/glm/ext/matrix_float3x2_precision.hpp new file mode 100644 index 0000000..8572c2a --- /dev/null +++ b/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/glm/ext/matrix_float3x3.hpp b/glm/ext/matrix_float3x3.hpp new file mode 100644 index 0000000..177d809 --- /dev/null +++ b/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/glm/ext/matrix_float3x3_precision.hpp b/glm/ext/matrix_float3x3_precision.hpp new file mode 100644 index 0000000..8a900c1 --- /dev/null +++ b/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/glm/ext/matrix_float3x4.hpp b/glm/ext/matrix_float3x4.hpp new file mode 100644 index 0000000..64b8459 --- /dev/null +++ b/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/glm/ext/matrix_float3x4_precision.hpp b/glm/ext/matrix_float3x4_precision.hpp new file mode 100644 index 0000000..bc36bf1 --- /dev/null +++ b/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/glm/ext/matrix_float4x2.hpp b/glm/ext/matrix_float4x2.hpp new file mode 100644 index 0000000..1ed5227 --- /dev/null +++ b/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/glm/ext/matrix_float4x2_precision.hpp b/glm/ext/matrix_float4x2_precision.hpp new file mode 100644 index 0000000..88fd069 --- /dev/null +++ b/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/glm/ext/matrix_float4x3.hpp b/glm/ext/matrix_float4x3.hpp new file mode 100644 index 0000000..5dbe765 --- /dev/null +++ b/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/glm/ext/matrix_float4x3_precision.hpp b/glm/ext/matrix_float4x3_precision.hpp new file mode 100644 index 0000000..846ed4f --- /dev/null +++ b/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/glm/ext/matrix_float4x4.hpp b/glm/ext/matrix_float4x4.hpp new file mode 100644 index 0000000..5ba111d --- /dev/null +++ b/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/glm/ext/matrix_float4x4_precision.hpp b/glm/ext/matrix_float4x4_precision.hpp new file mode 100644 index 0000000..597149b --- /dev/null +++ b/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/glm/ext/matrix_int2x2.hpp b/glm/ext/matrix_int2x2.hpp new file mode 100644 index 0000000..c6aa068 --- /dev/null +++ b/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/glm/ext/matrix_int2x2_sized.hpp b/glm/ext/matrix_int2x2_sized.hpp new file mode 100644 index 0000000..70c0c21 --- /dev/null +++ b/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/glm/ext/matrix_int2x3.hpp b/glm/ext/matrix_int2x3.hpp new file mode 100644 index 0000000..aee415c --- /dev/null +++ b/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/glm/ext/matrix_int2x3_sized.hpp b/glm/ext/matrix_int2x3_sized.hpp new file mode 100644 index 0000000..b5526fe --- /dev/null +++ b/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/glm/ext/matrix_int2x4.hpp b/glm/ext/matrix_int2x4.hpp new file mode 100644 index 0000000..4f36331 --- /dev/null +++ b/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/glm/ext/matrix_int2x4_sized.hpp b/glm/ext/matrix_int2x4_sized.hpp new file mode 100644 index 0000000..a66a5e7 --- /dev/null +++ b/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/glm/ext/matrix_int3x2.hpp b/glm/ext/matrix_int3x2.hpp new file mode 100644 index 0000000..3bd563b --- /dev/null +++ b/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/glm/ext/matrix_int3x2_sized.hpp b/glm/ext/matrix_int3x2_sized.hpp new file mode 100644 index 0000000..7e34c52 --- /dev/null +++ b/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/glm/ext/matrix_int3x3.hpp b/glm/ext/matrix_int3x3.hpp new file mode 100644 index 0000000..287488d --- /dev/null +++ b/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/glm/ext/matrix_int3x3_sized.hpp b/glm/ext/matrix_int3x3_sized.hpp new file mode 100644 index 0000000..577e305 --- /dev/null +++ b/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/glm/ext/matrix_int3x4.hpp b/glm/ext/matrix_int3x4.hpp new file mode 100644 index 0000000..08e534d --- /dev/null +++ b/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/glm/ext/matrix_int3x4_sized.hpp b/glm/ext/matrix_int3x4_sized.hpp new file mode 100644 index 0000000..692c48c --- /dev/null +++ b/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/glm/ext/matrix_int4x2.hpp b/glm/ext/matrix_int4x2.hpp new file mode 100644 index 0000000..f756ef2 --- /dev/null +++ b/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/glm/ext/matrix_int4x2_sized.hpp b/glm/ext/matrix_int4x2_sized.hpp new file mode 100644 index 0000000..63a99d6 --- /dev/null +++ b/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/glm/ext/matrix_int4x3.hpp b/glm/ext/matrix_int4x3.hpp new file mode 100644 index 0000000..d5d97a7 --- /dev/null +++ b/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/glm/ext/matrix_int4x3_sized.hpp b/glm/ext/matrix_int4x3_sized.hpp new file mode 100644 index 0000000..55078fa --- /dev/null +++ b/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/glm/ext/matrix_int4x4.hpp b/glm/ext/matrix_int4x4.hpp new file mode 100644 index 0000000..e17cff1 --- /dev/null +++ b/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/glm/ext/matrix_int4x4_sized.hpp b/glm/ext/matrix_int4x4_sized.hpp new file mode 100644 index 0000000..4a11203 --- /dev/null +++ b/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/glm/ext/matrix_integer.hpp b/glm/ext/matrix_integer.hpp new file mode 100644 index 0000000..7d7dfc5 --- /dev/null +++ b/glm/ext/matrix_integer.hpp @@ -0,0 +1,91 @@ +/// @ref ext_matrix_integer +/// @file glm/ext/matrix_integer.hpp +/// +/// @defgroup ext_matrix_integer GLM_EXT_matrix_integer +/// @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_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_matrix_integer + /// @{ + + /// 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); + + /// @} +}//namespace glm + +#include "matrix_integer.inl" diff --git a/glm/ext/matrix_integer.inl b/glm/ext/matrix_integer.inl new file mode 100644 index 0000000..8b377ce --- /dev/null +++ b/glm/ext/matrix_integer.inl @@ -0,0 +1,38 @@ +namespace glm{ +namespace detail +{ + template + struct compute_matrixCompMult_type { + GLM_FUNC_QUALIFIER static mat call(mat const& x, mat const& y) + { + return detail::compute_matrixCompMult::value>::call(x, y); + } + }; + + template + struct compute_outerProduct_type { + GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait::type call(vec const& c, vec const& r) + { + return detail::compute_outerProduct::call(c, r); + } + }; + + template + struct compute_transpose_type + { + GLM_FUNC_QUALIFIER static mat call(mat const& m) + { + return detail::compute_transpose::value>::call(m); + } + }; + + template + struct compute_determinant_type{ + + GLM_FUNC_QUALIFIER static T call(mat const& m) + { + return detail::compute_determinant::value>::call(m); + } + }; +}//namespace detail +}//namespace glm diff --git a/glm/ext/matrix_projection.hpp b/glm/ext/matrix_projection.hpp new file mode 100644 index 0000000..51fd01b --- /dev/null +++ b/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/glm/ext/matrix_projection.inl b/glm/ext/matrix_projection.inl new file mode 100644 index 0000000..2f2c196 --- /dev/null +++ b/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/glm/ext/matrix_relational.hpp b/glm/ext/matrix_relational.hpp new file mode 100644 index 0000000..20023ad --- /dev/null +++ b/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/glm/ext/matrix_relational.inl b/glm/ext/matrix_relational.inl new file mode 100644 index 0000000..9cd42b7 --- /dev/null +++ b/glm/ext/matrix_relational.inl @@ -0,0 +1,88 @@ +/// @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) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = all(equal(a[i], b[i])); + return Result; + } + + 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& a, mat const& b) + { + vec Result(true); + for(length_t i = 0; i < C; ++i) + Result[i] = any(notEqual(a[i], b[i])); + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec notEqual(mat const& a, mat const& b, T Epsilon) + { + return notEqual(a, b, 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& a, mat const& b, int MaxULPs) + { + return notEqual(a, b, 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/glm/ext/matrix_transform.hpp b/glm/ext/matrix_transform.hpp new file mode 100644 index 0000000..52695b8 --- /dev/null +++ b/glm/ext/matrix_transform.hpp @@ -0,0 +1,171 @@ +/// @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 GLM_CONSTEXPR 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); + + /// Builds a scale 4 * 4 matrix created from point referent 3 shearers. + /// + /// @param m Input matrix multiplied by this shear matrix. + /// @param p Point of shearing as reference. + /// @param l_x Ratio of matrix.x projection in YZ plane relative to the y-axis/z-axis. + /// @param l_y Ratio of matrix.y projection in XZ plane relative to the x-axis/z-axis. + /// @param l_z Ratio of matrix.z projection in XY plane relative to the x-axis/y-axis. + /// + /// as example: + /// [1 , l_xy, l_xz, -(l_xy+l_xz) * p_x] [x] T + /// [x`, y`, z`, w`] = [x`, y`, z`, w`] * [l_yx, 1 , l_yz, -(l_yx+l_yz) * p_y] [y] + /// [l_zx, l_zy, 1 , -(l_zx+l_zy) * p_z] [z] + /// [0 , 0 , 0 , 1 ] [w] + /// + /// @tparam T A floating-point shear type + /// @tparam Q A value from qualifier enum + /// + /// @see - shear(mat<4, 4, T, Q> const& m, T x, T y, T z) + /// @see - shear(vec<3, T, Q> const& p) + /// @see - shear(vec<2, T, Q> const& l_x) + /// @see - shear(vec<2, T, Q> const& l_y) + /// @see - shear(vec<2, T, Q> const& l_z) + /// @see no resource... + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shear( + mat<4, 4, T, Q> const &m, vec<3, T, Q> const& p, vec<2, T, Q> const &l_x, vec<2, T, Q> const &l_y, vec<2, T, Q> const &l_z); + + /// 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/glm/ext/matrix_transform.inl b/glm/ext/matrix_transform.inl new file mode 100644 index 0000000..029ef0f --- /dev/null +++ b/glm/ext/matrix_transform.inl @@ -0,0 +1,207 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType identity() + { + return detail::init_gentype::GENTYPE>::identity(); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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> shear(mat<4, 4, T, Q> const &m, vec<3, T, Q> const& p, vec<2, T, Q> const &l_x, vec<2, T, Q> const &l_y, vec<2, T, Q> const &l_z) + { + T const lambda_xy = l_x[0]; + T const lambda_xz = l_x[1]; + T const lambda_yx = l_y[0]; + T const lambda_yz = l_y[1]; + T const lambda_zx = l_z[0]; + T const lambda_zy = l_z[1]; + + vec<3, T, Q> point_lambda = vec<3, T, Q>( + (lambda_xy + lambda_xz), (lambda_yx + lambda_yz), (lambda_zx + lambda_zy) + ); + + mat<4, 4, T, Q> Shear = mat<4, 4, T, Q>( + 1 , lambda_yx , lambda_zx , 0, + lambda_xy , 1 , lambda_zy , 0, + lambda_xz , lambda_yz , 1 , 0, + -point_lambda[0] * p[0], -point_lambda[1] * p[1], -point_lambda[2] * p[2], 1 + ); + + mat<4, 4, T, Q> Result; + Result[0] = m[0] * Shear[0][0] + m[1] * Shear[0][1] + m[2] * Shear[0][2] + m[3] * Shear[0][3]; + Result[1] = m[0] * Shear[1][0] + m[1] * Shear[1][1] + m[2] * Shear[1][2] + m[3] * Shear[1][3]; + Result[2] = m[0] * Shear[2][0] + m[1] * Shear[2][1] + m[2] * Shear[2][2] + m[3] * Shear[2][3]; + Result[3] = m[0] * Shear[3][0] + m[1] * Shear[3][1] + m[2] * Shear[3][2] + m[3] * Shear[3][3]; + return Result; + } + + template + GLM_FUNC_QUALIFIER mat<4, 4, T, Q> shear_slow(mat<4, 4, T, Q> const &m, vec<3, T, Q> const& p, vec<2, T, Q> const &l_x, vec<2, T, Q> const &l_y, vec<2, T, Q> const &l_z) + { + T const lambda_xy = static_cast(l_x[0]); + T const lambda_xz = static_cast(l_x[1]); + T const lambda_yx = static_cast(l_y[0]); + T const lambda_yz = static_cast(l_y[1]); + T const lambda_zx = static_cast(l_z[0]); + T const lambda_zy = static_cast(l_z[1]); + + vec<3, T, Q> point_lambda = vec<3, T, Q>( + static_cast(lambda_xy + lambda_xz), + static_cast(lambda_yx + lambda_yz), + static_cast(lambda_zx + lambda_zy) + ); + + mat<4, 4, T, Q> Shear = mat<4, 4, T, Q>( + 1 , lambda_yx , lambda_zx , 0, + lambda_xy , 1 , lambda_zy , 0, + lambda_xz , lambda_yz , 1 , 0, + -point_lambda[0] * p[0], -point_lambda[1] * p[1], -point_lambda[2] * p[2], 1 + ); + return m * Shear; + } + + 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) + { +# if (GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT) + return lookAtLH(eye, center, up); +# else + return lookAtRH(eye, center, up); +# endif + } +}//namespace glm diff --git a/glm/ext/matrix_uint2x2.hpp b/glm/ext/matrix_uint2x2.hpp new file mode 100644 index 0000000..034771a --- /dev/null +++ b/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/glm/ext/matrix_uint2x2_sized.hpp b/glm/ext/matrix_uint2x2_sized.hpp new file mode 100644 index 0000000..4555324 --- /dev/null +++ b/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/glm/ext/matrix_uint2x3.hpp b/glm/ext/matrix_uint2x3.hpp new file mode 100644 index 0000000..f496c53 --- /dev/null +++ b/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_uint2x3 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/glm/ext/matrix_uint2x3_sized.hpp b/glm/ext/matrix_uint2x3_sized.hpp new file mode 100644 index 0000000..db7939c --- /dev/null +++ b/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/glm/ext/matrix_uint2x4.hpp b/glm/ext/matrix_uint2x4.hpp new file mode 100644 index 0000000..0f99350 --- /dev/null +++ b/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/glm/ext/matrix_uint2x4_sized.hpp b/glm/ext/matrix_uint2x4_sized.hpp new file mode 100644 index 0000000..5c55547 --- /dev/null +++ b/glm/ext/matrix_uint2x4_sized.hpp @@ -0,0 +1,49 @@ +/// @ref ext_matrix_uint2x4_sized +/// @file glm/ext/matrix_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/glm/ext/matrix_uint3x2.hpp b/glm/ext/matrix_uint3x2.hpp new file mode 100644 index 0000000..55a9bed --- /dev/null +++ b/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_uint3x2 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/glm/ext/matrix_uint3x2_sized.hpp b/glm/ext/matrix_uint3x2_sized.hpp new file mode 100644 index 0000000..c81af8f --- /dev/null +++ b/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/glm/ext/matrix_uint3x3.hpp b/glm/ext/matrix_uint3x3.hpp new file mode 100644 index 0000000..1004c0d --- /dev/null +++ b/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/glm/ext/matrix_uint3x3_sized.hpp b/glm/ext/matrix_uint3x3_sized.hpp new file mode 100644 index 0000000..41a8be7 --- /dev/null +++ b/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/glm/ext/matrix_uint3x4.hpp b/glm/ext/matrix_uint3x4.hpp new file mode 100644 index 0000000..c6dd78c --- /dev/null +++ b/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/glm/ext/matrix_uint3x4_sized.hpp b/glm/ext/matrix_uint3x4_sized.hpp new file mode 100644 index 0000000..2ce28ad --- /dev/null +++ b/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/glm/ext/matrix_uint4x2.hpp b/glm/ext/matrix_uint4x2.hpp new file mode 100644 index 0000000..0446f57 --- /dev/null +++ b/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/glm/ext/matrix_uint4x2_sized.hpp b/glm/ext/matrix_uint4x2_sized.hpp new file mode 100644 index 0000000..57a66bf --- /dev/null +++ b/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/glm/ext/matrix_uint4x3.hpp b/glm/ext/matrix_uint4x3.hpp new file mode 100644 index 0000000..54c24e4 --- /dev/null +++ b/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/glm/ext/matrix_uint4x3_sized.hpp b/glm/ext/matrix_uint4x3_sized.hpp new file mode 100644 index 0000000..2e61124 --- /dev/null +++ b/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/glm/ext/matrix_uint4x4.hpp b/glm/ext/matrix_uint4x4.hpp new file mode 100644 index 0000000..5cc8455 --- /dev/null +++ b/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/glm/ext/matrix_uint4x4_sized.hpp b/glm/ext/matrix_uint4x4_sized.hpp new file mode 100644 index 0000000..bb10bd2 --- /dev/null +++ b/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/glm/ext/quaternion_common.hpp b/glm/ext/quaternion_common.hpp new file mode 100644 index 0000000..f738692 --- /dev/null +++ b/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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/ext/quaternion_common.inl b/glm/ext/quaternion_common.inl new file mode 100644 index 0000000..ad171f9 --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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::wxyz( + 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 GLM_CONSTEXPR qua lerp(qua const& x, qua const& y, T a) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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::wxyz( + 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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::wxyz( + 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 + static_cast(k) * glm::pi(); + return (sin(angle - a * phi)* x + sin(a * phi) * z) / sin(angle); + } + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua conjugate(qua const& q) + { + return qua::wxyz(q.w, -q.x, -q.y, -q.z); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/ext/quaternion_common_simd.inl b/glm/ext/quaternion_common_simd.inl new file mode 100644 index 0000000..ddfc8a4 --- /dev/null +++ b/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/glm/ext/quaternion_double.hpp b/glm/ext/quaternion_double.hpp new file mode 100644 index 0000000..63b24de --- /dev/null +++ b/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/glm/ext/quaternion_double_precision.hpp b/glm/ext/quaternion_double_precision.hpp new file mode 100644 index 0000000..8aa24a1 --- /dev/null +++ b/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/glm/ext/quaternion_exponential.hpp b/glm/ext/quaternion_exponential.hpp new file mode 100644 index 0000000..affe297 --- /dev/null +++ b/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/glm/ext/quaternion_exponential.inl b/glm/ext/quaternion_exponential.inl new file mode 100644 index 0000000..8a9d774 --- /dev/null +++ b/glm/ext/quaternion_exponential.inl @@ -0,0 +1,89 @@ +#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::wxyz(log(q.w), static_cast(0), static_cast(0), static_cast(0)); + else if(q.w < static_cast(0)) + return qua::wxyz(log(-q.w), pi(), static_cast(0), static_cast(0)); + else + return qua::wxyz(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::wxyz(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::wxyz(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; + //Despite the compiler might say, we actually want to compare + //VectorMagnitude to 0. here; we could use denorm_int() compiling a + //project with unsafe maths optimizations might make the comparison + //always false, even when VectorMagnitude is 0. + if (VectorMagnitude < std::numeric_limits::min()) { + //Equivalent to raising a real number to a power + return qua::wxyz(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::wxyz(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/glm/ext/quaternion_float.hpp b/glm/ext/quaternion_float.hpp new file mode 100644 index 0000000..ca42a60 --- /dev/null +++ b/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/glm/ext/quaternion_float_precision.hpp b/glm/ext/quaternion_float_precision.hpp new file mode 100644 index 0000000..f9e4f5c --- /dev/null +++ b/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/glm/ext/quaternion_geometric.hpp b/glm/ext/quaternion_geometric.hpp new file mode 100644 index 0000000..6a2403f --- /dev/null +++ b/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_func_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 GLM_CONSTEXPR 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 GLM_CONSTEXPR qua cross(qua const& q1, qua const& q2); + + /// @} +} //namespace glm + +#include "quaternion_geometric.inl" diff --git a/glm/ext/quaternion_geometric.inl b/glm/ext/quaternion_geometric.inl new file mode 100644 index 0000000..88dc4d6 --- /dev/null +++ b/glm/ext/quaternion_geometric.inl @@ -0,0 +1,36 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR T dot(qua const& x, qua const& y) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + T oneOverLen = static_cast(1) / len; + return qua::wxyz(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua cross(qua const& q1, qua const& q2) + { + return qua::wxyz( + 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/glm/ext/quaternion_relational.hpp b/glm/ext/quaternion_relational.hpp new file mode 100644 index 0000000..7aa121d --- /dev/null +++ b/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/glm/ext/quaternion_relational.inl b/glm/ext/quaternion_relational.inl new file mode 100644 index 0000000..b1713e9 --- /dev/null +++ b/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/glm/ext/quaternion_transform.hpp b/glm/ext/quaternion_transform.hpp new file mode 100644 index 0000000..a9cc5c2 --- /dev/null +++ b/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/glm/ext/quaternion_transform.inl b/glm/ext/quaternion_transform.inl new file mode 100644 index 0000000..7e773fb --- /dev/null +++ b/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::wxyz(cos(AngleRad * static_cast(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + } +}//namespace glm + diff --git a/glm/ext/quaternion_trigonometric.hpp b/glm/ext/quaternion_trigonometric.hpp new file mode 100644 index 0000000..574a704 --- /dev/null +++ b/glm/ext/quaternion_trigonometric.hpp @@ -0,0 +1,65 @@ +/// @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. + /// + /// @param x A normalized quaternion. + /// + /// @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/glm/ext/quaternion_trigonometric.inl b/glm/ext/quaternion_trigonometric.inl new file mode 100644 index 0000000..896449a --- /dev/null +++ b/glm/ext/quaternion_trigonometric.inl @@ -0,0 +1,37 @@ +#include "scalar_constants.hpp" + +namespace glm +{ + template + GLM_FUNC_QUALIFIER T angle(qua const& x) + { + if (abs(x.w) > cos_one_over_two()) + { + T const a = asin(sqrt(x.x * x.x + x.y * x.y + x.z * x.z)) * static_cast(2); + if(x.w < static_cast(0)) + return pi() * static_cast(2) - a; + return a; + } + + 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/glm/ext/scalar_common.hpp b/glm/ext/scalar_common.hpp new file mode 100644 index 0000000..df04b6b --- /dev/null +++ b/glm/ext/scalar_common.hpp @@ -0,0 +1,181 @@ +/// @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); + + /// 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 genType floating point scalar types. + /// + /// @see GLSL round man page + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL int iround(genType 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 genType floating point scalar types. + /// + /// @see GLSL round man page + /// @see ext_scalar_common extension. + template + GLM_FUNC_DECL uint uround(genType const& x); + + /// @} +}//namespace glm + +#include "scalar_common.inl" diff --git a/glm/ext/scalar_common.inl b/glm/ext/scalar_common.inl new file mode 100644 index 0000000..3d09fef --- /dev/null +++ b/glm/ext/scalar_common.inl @@ -0,0 +1,170 @@ +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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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)); + } + + template + GLM_FUNC_QUALIFIER int iround(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'iround' only accept floating-point inputs"); + assert(static_cast(0.0) <= x); + + return static_cast(x + static_cast(0.5)); + } + + template + GLM_FUNC_QUALIFIER uint uround(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'uround' only accept floating-point inputs"); + assert(static_cast(0.0) <= x); + + return static_cast(x + static_cast(0.5)); + } +}//namespace glm diff --git a/glm/ext/scalar_constants.hpp b/glm/ext/scalar_constants.hpp new file mode 100644 index 0000000..74e210d --- /dev/null +++ b/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/glm/ext/scalar_constants.inl b/glm/ext/scalar_constants.inl new file mode 100644 index 0000000..b928e51 --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/ext/scalar_int_sized.hpp b/glm/ext/scalar_int_sized.hpp new file mode 100644 index 0000000..8e9c511 --- /dev/null +++ b/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/glm/ext/scalar_integer.hpp b/glm/ext/scalar_integer.hpp new file mode 100644 index 0000000..a2ca8a2 --- /dev/null +++ b/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/glm/ext/scalar_integer.inl b/glm/ext/scalar_integer.inl new file mode 100644 index 0000000..d416197 --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/ext/scalar_packing.hpp b/glm/ext/scalar_packing.hpp new file mode 100644 index 0000000..18b85b7 --- /dev/null +++ b/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/glm/ext/scalar_packing.inl b/glm/ext/scalar_packing.inl new file mode 100644 index 0000000..e69de29 diff --git a/glm/ext/scalar_reciprocal.hpp b/glm/ext/scalar_reciprocal.hpp new file mode 100644 index 0000000..1c7b81d --- /dev/null +++ b/glm/ext/scalar_reciprocal.hpp @@ -0,0 +1,135 @@ +/// @ref ext_scalar_reciprocal +/// @file glm/ext/scalar_reciprocal.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_scalar_reciprocal GLM_EXT_scalar_reciprocal +/// @ingroup ext +/// +/// 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_EXT_scalar_reciprocal extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_scalar_reciprocal + /// @{ + + /// Secant function. + /// hypotenuse / adjacent or 1 / cos(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_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 ext_scalar_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 ext_scalar_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 ext_scalar_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 ext_scalar_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 ext_scalar_reciprocal + template + GLM_FUNC_DECL genType acot(genType x); + + /// Secant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType sech(genType angle); + + /// Cosecant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_reciprocal + template + GLM_FUNC_DECL genType csch(genType angle); + + /// Cotangent hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_scalar_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 ext_scalar_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 ext_scalar_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 ext_scalar_reciprocal + template + GLM_FUNC_DECL genType acoth(genType x); + + /// @} +}//namespace glm + +#include "scalar_reciprocal.inl" diff --git a/glm/ext/scalar_reciprocal.inl b/glm/ext/scalar_reciprocal.inl new file mode 100644 index 0000000..0cd5f87 --- /dev/null +++ b/glm/ext/scalar_reciprocal.inl @@ -0,0 +1,107 @@ +/// @ref ext_scalar_reciprocal + +#include "../trigonometric.hpp" +#include + +namespace glm +{ + // sec + template + GLM_FUNC_QUALIFIER genType sec(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sec' only accept floating-point values"); + return genType(1) / glm::cos(angle); + } + + // csc + template + GLM_FUNC_QUALIFIER genType csc(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csc' only accept floating-point values"); + return genType(1) / glm::sin(angle); + } + + // cot + template + GLM_FUNC_QUALIFIER genType cot(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'cot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return glm::tan(pi_over_2 - angle); + } + + // asec + template + GLM_FUNC_QUALIFIER genType asec(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asec' only accept floating-point values"); + return acos(genType(1) / x); + } + + // acsc + template + GLM_FUNC_QUALIFIER genType acsc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsc' only accept floating-point values"); + return asin(genType(1) / x); + } + + // acot + template + GLM_FUNC_QUALIFIER genType acot(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return pi_over_2 - atan(x); + } + + // sech + template + GLM_FUNC_QUALIFIER genType sech(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sech' only accept floating-point values"); + return genType(1) / glm::cosh(angle); + } + + // csch + template + GLM_FUNC_QUALIFIER genType csch(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csch' only accept floating-point values"); + return genType(1) / glm::sinh(angle); + } + + // coth + template + GLM_FUNC_QUALIFIER genType coth(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'coth' only accept floating-point values"); + return glm::cosh(angle) / glm::sinh(angle); + } + + // asech + template + GLM_FUNC_QUALIFIER genType asech(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asech' only accept floating-point values"); + return acosh(genType(1) / x); + } + + // acsch + template + GLM_FUNC_QUALIFIER genType acsch(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsch' only accept floating-point values"); + return asinh(genType(1) / x); + } + + // acoth + template + GLM_FUNC_QUALIFIER genType acoth(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acoth' only accept floating-point values"); + return atanh(genType(1) / x); + } +}//namespace glm diff --git a/glm/ext/scalar_relational.hpp b/glm/ext/scalar_relational.hpp new file mode 100644 index 0000000..e84df17 --- /dev/null +++ b/glm/ext/scalar_relational.hpp @@ -0,0 +1,68 @@ +/// @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 +{ + /// @addtogroup ext_scalar_relational + /// @{ + + /// 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/glm/ext/scalar_relational.inl b/glm/ext/scalar_relational.inl new file mode 100644 index 0000000..c85583e --- /dev/null +++ b/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/glm/ext/scalar_uint_sized.hpp b/glm/ext/scalar_uint_sized.hpp new file mode 100644 index 0000000..fd5267f --- /dev/null +++ b/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/glm/ext/scalar_ulp.hpp b/glm/ext/scalar_ulp.hpp new file mode 100644 index 0000000..6344d95 --- /dev/null +++ b/glm/ext/scalar_ulp.hpp @@ -0,0 +1,77 @@ +/// @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 +{ + /// @addtogroup ext_scalar_ulp + /// @{ + + /// 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/glm/ext/scalar_ulp.inl b/glm/ext/scalar_ulp.inl new file mode 100644 index 0000000..716528d --- /dev/null +++ b/glm/ext/scalar_ulp.inl @@ -0,0 +1,291 @@ +/// 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) +# pragma warning(disable : 4365) // '=': signed/unsigned mismatch +#elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wsign-conversion" +# pragma clang diagnostic ignored "-Wpadded" +#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) = static_cast(gf_u.word); \ + } while (0) + +#define GLM_SET_FLOAT_WORD(d,i) \ + do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = static_cast(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) +#elif GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/ext/vector_bool1.hpp b/glm/ext/vector_bool1.hpp new file mode 100644 index 0000000..002c320 --- /dev/null +++ b/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/glm/ext/vector_bool1_precision.hpp b/glm/ext/vector_bool1_precision.hpp new file mode 100644 index 0000000..e62d3cf --- /dev/null +++ b/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/glm/ext/vector_bool2.hpp b/glm/ext/vector_bool2.hpp new file mode 100644 index 0000000..52288b7 --- /dev/null +++ b/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/glm/ext/vector_bool2_precision.hpp b/glm/ext/vector_bool2_precision.hpp new file mode 100644 index 0000000..4370933 --- /dev/null +++ b/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/glm/ext/vector_bool3.hpp b/glm/ext/vector_bool3.hpp new file mode 100644 index 0000000..90a0b7e --- /dev/null +++ b/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/glm/ext/vector_bool3_precision.hpp b/glm/ext/vector_bool3_precision.hpp new file mode 100644 index 0000000..89cd2d3 --- /dev/null +++ b/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/glm/ext/vector_bool4.hpp b/glm/ext/vector_bool4.hpp new file mode 100644 index 0000000..18aa71b --- /dev/null +++ b/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/glm/ext/vector_bool4_precision.hpp b/glm/ext/vector_bool4_precision.hpp new file mode 100644 index 0000000..79786e5 --- /dev/null +++ b/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/glm/ext/vector_common.hpp b/glm/ext/vector_common.hpp new file mode 100644 index 0000000..c0a2858 --- /dev/null +++ b/glm/ext/vector_common.hpp @@ -0,0 +1,228 @@ +/// @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); + + /// 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 ext_vector_common extension. + 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 ext_vector_common extension. + template + GLM_FUNC_DECL vec uround(vec const& x); + + /// @} +}//namespace glm + +#include "vector_common.inl" diff --git a/glm/ext/vector_common.inl b/glm/ext/vector_common.inl new file mode 100644 index 0000000..67817fc --- /dev/null +++ b/glm/ext/vector_common.inl @@ -0,0 +1,147 @@ +#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 || std::numeric_limits::is_integer, "'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 || std::numeric_limits::is_integer, "'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 || std::numeric_limits::is_integer, "'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 || std::numeric_limits::is_integer, "'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))); + } + + 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 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/glm/ext/vector_double1.hpp b/glm/ext/vector_double1.hpp new file mode 100644 index 0000000..3882667 --- /dev/null +++ b/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/glm/ext/vector_double1_precision.hpp b/glm/ext/vector_double1_precision.hpp new file mode 100644 index 0000000..1d47195 --- /dev/null +++ b/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/glm/ext/vector_double2.hpp b/glm/ext/vector_double2.hpp new file mode 100644 index 0000000..60e3577 --- /dev/null +++ b/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/glm/ext/vector_double2_precision.hpp b/glm/ext/vector_double2_precision.hpp new file mode 100644 index 0000000..fa53940 --- /dev/null +++ b/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/glm/ext/vector_double3.hpp b/glm/ext/vector_double3.hpp new file mode 100644 index 0000000..6dfe4c6 --- /dev/null +++ b/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/glm/ext/vector_double3_precision.hpp b/glm/ext/vector_double3_precision.hpp new file mode 100644 index 0000000..a8cfa37 --- /dev/null +++ b/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/glm/ext/vector_double4.hpp b/glm/ext/vector_double4.hpp new file mode 100644 index 0000000..87f225f --- /dev/null +++ b/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/glm/ext/vector_double4_precision.hpp b/glm/ext/vector_double4_precision.hpp new file mode 100644 index 0000000..09cafa1 --- /dev/null +++ b/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/glm/ext/vector_float1.hpp b/glm/ext/vector_float1.hpp new file mode 100644 index 0000000..28acc2c --- /dev/null +++ b/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/glm/ext/vector_float1_precision.hpp b/glm/ext/vector_float1_precision.hpp new file mode 100644 index 0000000..6e8dad8 --- /dev/null +++ b/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/glm/ext/vector_float2.hpp b/glm/ext/vector_float2.hpp new file mode 100644 index 0000000..d31545d --- /dev/null +++ b/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/glm/ext/vector_float2_precision.hpp b/glm/ext/vector_float2_precision.hpp new file mode 100644 index 0000000..23c0820 --- /dev/null +++ b/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/glm/ext/vector_float3.hpp b/glm/ext/vector_float3.hpp new file mode 100644 index 0000000..cd79a62 --- /dev/null +++ b/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/glm/ext/vector_float3_precision.hpp b/glm/ext/vector_float3_precision.hpp new file mode 100644 index 0000000..be640b5 --- /dev/null +++ b/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/glm/ext/vector_float4.hpp b/glm/ext/vector_float4.hpp new file mode 100644 index 0000000..d84adcc --- /dev/null +++ b/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/glm/ext/vector_float4_precision.hpp b/glm/ext/vector_float4_precision.hpp new file mode 100644 index 0000000..aede838 --- /dev/null +++ b/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/glm/ext/vector_int1.hpp b/glm/ext/vector_int1.hpp new file mode 100644 index 0000000..dc86038 --- /dev/null +++ b/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/glm/ext/vector_int1_sized.hpp b/glm/ext/vector_int1_sized.hpp new file mode 100644 index 0000000..de0d4cf --- /dev/null +++ b/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/glm/ext/vector_int2.hpp b/glm/ext/vector_int2.hpp new file mode 100644 index 0000000..aef803e --- /dev/null +++ b/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/glm/ext/vector_int2_sized.hpp b/glm/ext/vector_int2_sized.hpp new file mode 100644 index 0000000..1fd57ee --- /dev/null +++ b/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/glm/ext/vector_int3.hpp b/glm/ext/vector_int3.hpp new file mode 100644 index 0000000..4767e61 --- /dev/null +++ b/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/glm/ext/vector_int3_sized.hpp b/glm/ext/vector_int3_sized.hpp new file mode 100644 index 0000000..085a3fe --- /dev/null +++ b/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/glm/ext/vector_int4.hpp b/glm/ext/vector_int4.hpp new file mode 100644 index 0000000..bb23adf --- /dev/null +++ b/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/glm/ext/vector_int4_sized.hpp b/glm/ext/vector_int4_sized.hpp new file mode 100644 index 0000000..c63d465 --- /dev/null +++ b/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/glm/ext/vector_integer.hpp b/glm/ext/vector_integer.hpp new file mode 100644 index 0000000..1304dd8 --- /dev/null +++ b/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/glm/ext/vector_integer.inl b/glm/ext/vector_integer.inl new file mode 100644 index 0000000..cefb132 --- /dev/null +++ b/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 equal(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 equal(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/glm/ext/vector_packing.hpp b/glm/ext/vector_packing.hpp new file mode 100644 index 0000000..76e5d0c --- /dev/null +++ b/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/glm/ext/vector_packing.inl b/glm/ext/vector_packing.inl new file mode 100644 index 0000000..e69de29 diff --git a/glm/ext/vector_reciprocal.hpp b/glm/ext/vector_reciprocal.hpp new file mode 100644 index 0000000..84d6766 --- /dev/null +++ b/glm/ext/vector_reciprocal.hpp @@ -0,0 +1,135 @@ +/// @ref ext_vector_reciprocal +/// @file glm/ext/vector_reciprocal.hpp +/// +/// @see core (dependence) +/// +/// @defgroup ext_vector_reciprocal GLM_EXT_vector_reciprocal +/// @ingroup ext +/// +/// 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_EXT_vector_reciprocal extension included") +#endif + +namespace glm +{ + /// @addtogroup ext_vector_reciprocal + /// @{ + + /// Secant function. + /// hypotenuse / adjacent or 1 / cos(x) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_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 ext_vector_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 ext_vector_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 ext_vector_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 ext_vector_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 ext_vector_reciprocal + template + GLM_FUNC_DECL genType acot(genType x); + + /// Secant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType sech(genType angle); + + /// Cosecant hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_reciprocal + template + GLM_FUNC_DECL genType csch(genType angle); + + /// Cotangent hyperbolic function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see ext_vector_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 ext_vector_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 ext_vector_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 ext_vector_reciprocal + template + GLM_FUNC_DECL genType acoth(genType x); + + /// @} +}//namespace glm + +#include "vector_reciprocal.inl" diff --git a/glm/ext/vector_reciprocal.inl b/glm/ext/vector_reciprocal.inl new file mode 100644 index 0000000..b85102a --- /dev/null +++ b/glm/ext/vector_reciprocal.inl @@ -0,0 +1,105 @@ +/// @ref ext_vector_reciprocal + +#include "../trigonometric.hpp" +#include + +namespace glm +{ + // sec + template + GLM_FUNC_QUALIFIER vec sec(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sec' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(cos, x); + } + + // csc + template + GLM_FUNC_QUALIFIER vec csc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csc' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(sin, x); + } + + // cot + template + GLM_FUNC_QUALIFIER vec cot(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'cot' only accept floating-point inputs"); + T const pi_over_2 = static_cast(3.1415926535897932384626433832795 / 2.0); + return detail::functor1::call(tan, pi_over_2 - x); + } + + // asec + template + GLM_FUNC_QUALIFIER vec asec(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asec' only accept floating-point inputs"); + return detail::functor1::call(acos, static_cast(1) / x); + } + + // acsc + template + GLM_FUNC_QUALIFIER vec acsc(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsc' only accept floating-point inputs"); + return detail::functor1::call(asin, static_cast(1) / x); + } + + // acot + template + GLM_FUNC_QUALIFIER vec acot(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acot' only accept floating-point inputs"); + T const pi_over_2 = static_cast(3.1415926535897932384626433832795 / 2.0); + return pi_over_2 - detail::functor1::call(atan, x); + } + + // sech + template + GLM_FUNC_QUALIFIER vec sech(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'sech' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(cosh, x); + } + + // csch + template + GLM_FUNC_QUALIFIER vec csch(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'csch' only accept floating-point inputs"); + return static_cast(1) / detail::functor1::call(sinh, x); + } + + // coth + template + GLM_FUNC_QUALIFIER vec coth(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'coth' only accept floating-point inputs"); + return glm::cosh(x) / glm::sinh(x); + } + + // asech + template + GLM_FUNC_QUALIFIER vec asech(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'asech' only accept floating-point inputs"); + return detail::functor1::call(acosh, static_cast(1) / x); + } + + // acsch + template + GLM_FUNC_QUALIFIER vec acsch(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acsch' only accept floating-point inputs"); + return detail::functor1::call(asinh, static_cast(1) / x); + } + + // acoth + template + GLM_FUNC_QUALIFIER vec acoth(vec const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'acoth' only accept floating-point inputs"); + return detail::functor1::call(atanh, static_cast(1) / x); + } +}//namespace glm diff --git a/glm/ext/vector_relational.hpp b/glm/ext/vector_relational.hpp new file mode 100644 index 0000000..1c2367d --- /dev/null +++ b/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/glm/ext/vector_relational.inl b/glm/ext/vector_relational.inl new file mode 100644 index 0000000..7a39ab5 --- /dev/null +++ b/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/glm/ext/vector_uint1.hpp b/glm/ext/vector_uint1.hpp new file mode 100644 index 0000000..eb8a704 --- /dev/null +++ b/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/glm/ext/vector_uint1_sized.hpp b/glm/ext/vector_uint1_sized.hpp new file mode 100644 index 0000000..2a938bb --- /dev/null +++ b/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/glm/ext/vector_uint2.hpp b/glm/ext/vector_uint2.hpp new file mode 100644 index 0000000..03c00f5 --- /dev/null +++ b/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/glm/ext/vector_uint2_sized.hpp b/glm/ext/vector_uint2_sized.hpp new file mode 100644 index 0000000..620fdc6 --- /dev/null +++ b/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/glm/ext/vector_uint3.hpp b/glm/ext/vector_uint3.hpp new file mode 100644 index 0000000..f5b41c4 --- /dev/null +++ b/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/glm/ext/vector_uint3_sized.hpp b/glm/ext/vector_uint3_sized.hpp new file mode 100644 index 0000000..6f96b98 --- /dev/null +++ b/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/glm/ext/vector_uint4.hpp b/glm/ext/vector_uint4.hpp new file mode 100644 index 0000000..32ced58 --- /dev/null +++ b/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/glm/ext/vector_uint4_sized.hpp b/glm/ext/vector_uint4_sized.hpp new file mode 100644 index 0000000..da992ea --- /dev/null +++ b/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/glm/ext/vector_ulp.hpp b/glm/ext/vector_ulp.hpp new file mode 100644 index 0000000..7c539bb --- /dev/null +++ b/glm/ext/vector_ulp.hpp @@ -0,0 +1,112 @@ +/// @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 +{ + /// @addtogroup ext_vector_ulp + /// @{ + + /// 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/glm/ext/vector_ulp.inl b/glm/ext/vector_ulp.inl new file mode 100644 index 0000000..d3c7648 --- /dev/null +++ b/glm/ext/vector_ulp.inl @@ -0,0 +1,74 @@ +namespace glm +{ + template + GLM_FUNC_QUALIFIER vec nextFloat(vec const& x) + { + vec Result(0); + 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(0); + 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(0); + 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(0); + 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(0); + 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(0); + 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(0); + 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(0); + 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/glm/fwd.hpp b/glm/fwd.hpp new file mode 100644 index 0000000..9c2e5ea --- /dev/null +++ b/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<2, 3, f32, defaultp> mat2x3; + typedef mat<2, 4, f32, defaultp> mat2x4; + typedef mat<3, 2, f32, defaultp> mat3x2; + typedef mat<3, 3, f32, defaultp> mat3x3; + typedef mat<3, 4, f32, defaultp> mat3x4; + typedef mat<4, 2, f32, defaultp> mat4x2; + typedef mat<4, 3, f32, defaultp> mat4x3; + 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<2, 3, f32, defaultp> fmat2x3; + typedef mat<2, 4, f32, defaultp> fmat2x4; + typedef mat<3, 2, f32, defaultp> fmat3x2; + typedef mat<3, 3, f32, defaultp> fmat3x3; + typedef mat<3, 4, f32, defaultp> fmat3x4; + typedef mat<4, 2, f32, defaultp> fmat4x2; + typedef mat<4, 3, f32, defaultp> fmat4x3; + 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<2, 3, f32, defaultp> f32mat2x3; + typedef mat<2, 4, f32, defaultp> f32mat2x4; + typedef mat<3, 2, f32, defaultp> f32mat3x2; + typedef mat<3, 3, f32, defaultp> f32mat3x3; + typedef mat<3, 4, f32, defaultp> f32mat3x4; + typedef mat<4, 2, f32, defaultp> f32mat4x2; + typedef mat<4, 3, f32, defaultp> f32mat4x3; + 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<2, 3, double, defaultp> dmat2x3; + typedef mat<2, 4, double, defaultp> dmat2x4; + typedef mat<3, 2, double, defaultp> dmat3x2; + typedef mat<3, 3, double, defaultp> dmat3x3; + typedef mat<3, 4, double, defaultp> dmat3x4; + typedef mat<4, 2, double, defaultp> dmat4x2; + typedef mat<4, 3, double, defaultp> dmat4x3; + 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<2, 3, f64, defaultp> f64mat2x3; + typedef mat<2, 4, f64, defaultp> f64mat2x4; + typedef mat<3, 2, f64, defaultp> f64mat3x2; + typedef mat<3, 3, f64, defaultp> f64mat3x3; + typedef mat<3, 4, f64, defaultp> f64mat3x4; + typedef mat<4, 2, f64, defaultp> f64mat4x2; + typedef mat<4, 3, f64, defaultp> f64mat4x3; + 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<2, 3, int, defaultp> imat2x3; + typedef mat<2, 4, int, defaultp> imat2x4; + typedef mat<3, 2, int, defaultp> imat3x2; + typedef mat<3, 3, int, defaultp> imat3x3; + typedef mat<3, 4, int, defaultp> imat3x4; + typedef mat<4, 2, int, defaultp> imat4x2; + typedef mat<4, 3, int, defaultp> imat4x3; + 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<2, 3, int8, defaultp> i8mat2x3; + typedef mat<2, 4, int8, defaultp> i8mat2x4; + typedef mat<3, 2, int8, defaultp> i8mat3x2; + typedef mat<3, 3, int8, defaultp> i8mat3x3; + typedef mat<3, 4, int8, defaultp> i8mat3x4; + typedef mat<4, 2, int8, defaultp> i8mat4x2; + typedef mat<4, 3, int8, defaultp> i8mat4x3; + 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<2, 3, int16, defaultp> i16mat2x3; + typedef mat<2, 4, int16, defaultp> i16mat2x4; + typedef mat<3, 2, int16, defaultp> i16mat3x2; + typedef mat<3, 3, int16, defaultp> i16mat3x3; + typedef mat<3, 4, int16, defaultp> i16mat3x4; + typedef mat<4, 2, int16, defaultp> i16mat4x2; + typedef mat<4, 3, int16, defaultp> i16mat4x3; + 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<2, 3, int32, defaultp> i32mat2x3; + typedef mat<2, 4, int32, defaultp> i32mat2x4; + typedef mat<3, 2, int32, defaultp> i32mat3x2; + typedef mat<3, 3, int32, defaultp> i32mat3x3; + typedef mat<3, 4, int32, defaultp> i32mat3x4; + typedef mat<4, 2, int32, defaultp> i32mat4x2; + typedef mat<4, 3, int32, defaultp> i32mat4x3; + 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<2, 3, int64, defaultp> i64mat2x3; + typedef mat<2, 4, int64, defaultp> i64mat2x4; + typedef mat<3, 2, int64, defaultp> i64mat3x2; + typedef mat<3, 3, int64, defaultp> i64mat3x3; + typedef mat<3, 4, int64, defaultp> i64mat3x4; + typedef mat<4, 2, int64, defaultp> i64mat4x2; + typedef mat<4, 3, int64, defaultp> i64mat4x3; + 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<2, 3, uint, defaultp> umat2x3; + typedef mat<2, 4, uint, defaultp> umat2x4; + typedef mat<3, 2, uint, defaultp> umat3x2; + typedef mat<3, 3, uint, defaultp> umat3x3; + typedef mat<3, 4, uint, defaultp> umat3x4; + typedef mat<4, 2, uint, defaultp> umat4x2; + typedef mat<4, 3, uint, defaultp> umat4x3; + 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<2, 3, uint8, defaultp> u8mat2x3; + typedef mat<2, 4, uint8, defaultp> u8mat2x4; + typedef mat<3, 2, uint8, defaultp> u8mat3x2; + typedef mat<3, 3, uint8, defaultp> u8mat3x3; + typedef mat<3, 4, uint8, defaultp> u8mat3x4; + typedef mat<4, 2, uint8, defaultp> u8mat4x2; + typedef mat<4, 3, uint8, defaultp> u8mat4x3; + 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<2, 3, uint16, defaultp> u16mat2x3; + typedef mat<2, 4, uint16, defaultp> u16mat2x4; + typedef mat<3, 2, uint16, defaultp> u16mat3x2; + typedef mat<3, 3, uint16, defaultp> u16mat3x3; + typedef mat<3, 4, uint16, defaultp> u16mat3x4; + typedef mat<4, 2, uint16, defaultp> u16mat4x2; + typedef mat<4, 3, uint16, defaultp> u16mat4x3; + 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<2, 3, uint32, defaultp> u32mat2x3; + typedef mat<2, 4, uint32, defaultp> u32mat2x4; + typedef mat<3, 2, uint32, defaultp> u32mat3x2; + typedef mat<3, 3, uint32, defaultp> u32mat3x3; + typedef mat<3, 4, uint32, defaultp> u32mat3x4; + typedef mat<4, 2, uint32, defaultp> u32mat4x2; + typedef mat<4, 3, uint32, defaultp> u32mat4x3; + 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<2, 3, uint64, defaultp> u64mat2x3; + typedef mat<2, 4, uint64, defaultp> u64mat2x4; + typedef mat<3, 2, uint64, defaultp> u64mat3x2; + typedef mat<3, 3, uint64, defaultp> u64mat3x3; + typedef mat<3, 4, uint64, defaultp> u64mat3x4; + typedef mat<4, 2, uint64, defaultp> u64mat4x2; + typedef mat<4, 3, uint64, defaultp> u64mat4x3; + 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/glm/geometric.hpp b/glm/geometric.hpp new file mode 100644 index 0000000..ac857e6 --- /dev/null +++ b/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 between 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/glm.cppm b/glm/glm.cppm new file mode 100644 index 0000000..85e946e --- /dev/null +++ b/glm/glm.cppm @@ -0,0 +1,2675 @@ +module; + +// #define GLM_GTC_INLINE_NAMESPACE to inline glm::gtc into glm +// #define GLM_EXT_INLINE_NAMESPACE to inline glm::ext into glm +// #define GLM_GTX_INLINE_NAMESPACE to inline glm::gtx into glm + +#include +#include + +export module glm; + +export namespace glm { + // Base types + using glm::qualifier; + using glm::precision; + using glm::vec; + using glm::mat; + using glm::qua; +# if GLM_HAS_TEMPLATE_ALIASES + using glm::tvec1; + using glm::tvec2; + using glm::tvec3; + using glm::tvec4; + using glm::tmat2x2; + using glm::tmat2x3; + using glm::tmat2x4; + using glm::tmat3x2; + using glm::tmat3x3; + using glm::tmat3x4; + using glm::tmat4x2; + using glm::tmat4x3; + using glm::tmat4x4; + using glm::tquat; +# endif + + using glm::int8; + using glm::int16; + using glm::int32; + using glm::int64; + using glm::uint8; + using glm::uint16; + using glm::uint32; + using glm::uint64; + using glm::lowp_i8; + using glm::mediump_i8; + using glm::highp_i8; + using glm::i8; + using glm::lowp_int8; + using glm::mediump_int8; + using glm::highp_int8; + using glm::lowp_int8_t; + using glm::mediump_int8_t; + using glm::highp_int8_t; + using glm::int8_t; + using glm::lowp_i16; + using glm::mediump_i16; + using glm::highp_i16; + using glm::i16; + using glm::lowp_int16; + using glm::mediump_int16; + using glm::highp_int16; + using glm::lowp_int16_t; + using glm::mediump_int16_t; + using glm::highp_int16_t; + using glm::int16_t; + using glm::lowp_i32; + using glm::mediump_i32; + using glm::highp_i32; + using glm::i32; + using glm::lowp_int32; + using glm::mediump_int32; + using glm::highp_int32; + using glm::lowp_int32_t; + using glm::mediump_int32_t; + using glm::highp_int32_t; + using glm::int32_t; + using glm::lowp_i64; + using glm::mediump_i64; + using glm::highp_i64; + using glm::i64; + using glm::lowp_int64; + using glm::mediump_int64; + using glm::highp_int64; + using glm::lowp_int64_t; + using glm::mediump_int64_t; + using glm::highp_int64_t; + using glm::int64_t; + using glm::uint; + using glm::lowp_u8; + using glm::mediump_u8; + using glm::highp_u8; + using glm::u8; + using glm::lowp_uint8; + using glm::mediump_uint8; + using glm::highp_uint8; + using glm::lowp_uint8_t; + using glm::mediump_uint8_t; + using glm::highp_uint8_t; + using glm::uint8_t; + using glm::lowp_u16; + using glm::mediump_u16; + using glm::highp_u16; + using glm::u16; + using glm::lowp_uint16; + using glm::mediump_uint16; + using glm::highp_uint16; + using glm::lowp_uint16_t; + using glm::mediump_uint16_t; + using glm::highp_uint16_t; + using glm::uint16_t; + using glm::lowp_u32; + using glm::mediump_u32; + using glm::highp_u32; + using glm::u32; + using glm::lowp_uint32; + using glm::mediump_uint32; + using glm::highp_uint32; + using glm::lowp_uint32_t; + using glm::mediump_uint32_t; + using glm::highp_uint32_t; + using glm::uint32_t; + using glm::lowp_u64; + using glm::mediump_u64; + using glm::highp_u64; + using glm::u64; + using glm::lowp_uint64; + using glm::mediump_uint64; + using glm::highp_uint64; + using glm::lowp_uint64_t; + using glm::mediump_uint64_t; + using glm::highp_uint64_t; + using glm::uint64_t; + using glm::lowp_f32; + using glm::mediump_f32; + using glm::highp_f32; + using glm::f32; + using glm::lowp_float32; + using glm::mediump_float32; + using glm::highp_float32; + using glm::float32; + using glm::lowp_float32_t; + using glm::mediump_float32_t; + using glm::highp_float32_t; + using glm::float32_t; + using glm::lowp_f64; + using glm::mediump_f64; + using glm::highp_f64; + using glm::f64; + using glm::lowp_float64; + using glm::mediump_float64; + using glm::highp_float64; + using glm::float64; + using glm::lowp_float64_t; + using glm::mediump_float64_t; + using glm::highp_float64_t; + using glm::float64_t; + using glm::lowp_bvec1; + using glm::lowp_bvec2; + using glm::lowp_bvec3; + using glm::lowp_bvec4; + using glm::mediump_bvec1; + using glm::mediump_bvec2; + using glm::mediump_bvec3; + using glm::mediump_bvec4; + using glm::highp_bvec1; + using glm::highp_bvec2; + using glm::highp_bvec3; + using glm::highp_bvec4; + using glm::bvec1; + using glm::bvec2; + using glm::bvec3; + using glm::bvec4; + using glm::lowp_ivec1; + using glm::lowp_ivec2; + using glm::lowp_ivec3; + using glm::lowp_ivec4; + using glm::mediump_ivec1; + using glm::mediump_ivec2; + using glm::mediump_ivec3; + using glm::mediump_ivec4; + using glm::highp_ivec1; + using glm::highp_ivec2; + using glm::highp_ivec3; + using glm::highp_ivec4; + using glm::ivec1; + using glm::ivec2; + using glm::ivec3; + using glm::ivec4; + using glm::lowp_i8vec1; + using glm::lowp_i8vec2; + using glm::lowp_i8vec3; + using glm::lowp_i8vec4; + using glm::mediump_i8vec1; + using glm::mediump_i8vec2; + using glm::mediump_i8vec3; + using glm::mediump_i8vec4; + using glm::highp_i8vec1; + using glm::highp_i8vec2; + using glm::highp_i8vec3; + using glm::highp_i8vec4; + using glm::i8vec1; + using glm::i8vec2; + using glm::i8vec3; + using glm::i8vec4; + using glm::lowp_i16vec1; + using glm::lowp_i16vec2; + using glm::lowp_i16vec3; + using glm::lowp_i16vec4; + using glm::mediump_i16vec1; + using glm::mediump_i16vec2; + using glm::mediump_i16vec3; + using glm::mediump_i16vec4; + using glm::highp_i16vec1; + using glm::highp_i16vec2; + using glm::highp_i16vec3; + using glm::highp_i16vec4; + using glm::i16vec1; + using glm::i16vec2; + using glm::i16vec3; + using glm::i16vec4; + using glm::lowp_i32vec1; + using glm::lowp_i32vec2; + using glm::lowp_i32vec3; + using glm::lowp_i32vec4; + using glm::mediump_i32vec1; + using glm::mediump_i32vec2; + using glm::mediump_i32vec3; + using glm::mediump_i32vec4; + using glm::highp_i32vec1; + using glm::highp_i32vec2; + using glm::highp_i32vec3; + using glm::highp_i32vec4; + using glm::i32vec1; + using glm::i32vec2; + using glm::i32vec3; + using glm::i32vec4; + using glm::lowp_i64vec1; + using glm::lowp_i64vec2; + using glm::lowp_i64vec3; + using glm::lowp_i64vec4; + using glm::mediump_i64vec1; + using glm::mediump_i64vec2; + using glm::mediump_i64vec3; + using glm::mediump_i64vec4; + using glm::highp_i64vec1; + using glm::highp_i64vec2; + using glm::highp_i64vec3; + using glm::highp_i64vec4; + using glm::i64vec1; + using glm::i64vec2; + using glm::i64vec3; + using glm::i64vec4; + using glm::lowp_uvec1; + using glm::lowp_uvec2; + using glm::lowp_uvec3; + using glm::lowp_uvec4; + using glm::mediump_uvec1; + using glm::mediump_uvec2; + using glm::mediump_uvec3; + using glm::mediump_uvec4; + using glm::highp_uvec1; + using glm::highp_uvec2; + using glm::highp_uvec3; + using glm::highp_uvec4; + using glm::uvec1; + using glm::uvec2; + using glm::uvec3; + using glm::uvec4; + using glm::lowp_u8vec1; + using glm::lowp_u8vec2; + using glm::lowp_u8vec3; + using glm::lowp_u8vec4; + using glm::mediump_u8vec1; + using glm::mediump_u8vec2; + using glm::mediump_u8vec3; + using glm::mediump_u8vec4; + using glm::highp_u8vec1; + using glm::highp_u8vec2; + using glm::highp_u8vec3; + using glm::highp_u8vec4; + using glm::u8vec1; + using glm::u8vec2; + using glm::u8vec3; + using glm::u8vec4; + using glm::lowp_u16vec1; + using glm::lowp_u16vec2; + using glm::lowp_u16vec3; + using glm::lowp_u16vec4; + using glm::mediump_u16vec1; + using glm::mediump_u16vec2; + using glm::mediump_u16vec3; + using glm::mediump_u16vec4; + using glm::highp_u16vec1; + using glm::highp_u16vec2; + using glm::highp_u16vec3; + using glm::highp_u16vec4; + using glm::u16vec1; + using glm::u16vec2; + using glm::u16vec3; + using glm::u16vec4; + using glm::lowp_u32vec1; + using glm::lowp_u32vec2; + using glm::lowp_u32vec3; + using glm::lowp_u32vec4; + using glm::mediump_u32vec1; + using glm::mediump_u32vec2; + using glm::mediump_u32vec3; + using glm::mediump_u32vec4; + using glm::highp_u32vec1; + using glm::highp_u32vec2; + using glm::highp_u32vec3; + using glm::highp_u32vec4; + using glm::u32vec1; + using glm::u32vec2; + using glm::u32vec3; + using glm::u32vec4; + using glm::lowp_u64vec1; + using glm::lowp_u64vec2; + using glm::lowp_u64vec3; + using glm::lowp_u64vec4; + using glm::mediump_u64vec1; + using glm::mediump_u64vec2; + using glm::mediump_u64vec3; + using glm::mediump_u64vec4; + using glm::highp_u64vec1; + using glm::highp_u64vec2; + using glm::highp_u64vec3; + using glm::highp_u64vec4; + using glm::u64vec1; + using glm::u64vec2; + using glm::u64vec3; + using glm::u64vec4; + using glm::lowp_vec1; + using glm::lowp_vec2; + using glm::lowp_vec3; + using glm::lowp_vec4; + using glm::mediump_vec1; + using glm::mediump_vec2; + using glm::mediump_vec3; + using glm::mediump_vec4; + using glm::highp_vec1; + using glm::highp_vec2; + using glm::highp_vec3; + using glm::highp_vec4; + using glm::vec1; + using glm::vec2; + using glm::vec3; + using glm::vec4; + using glm::lowp_fvec1; + using glm::lowp_fvec2; + using glm::lowp_fvec3; + using glm::lowp_fvec4; + using glm::mediump_fvec1; + using glm::mediump_fvec2; + using glm::mediump_fvec3; + using glm::mediump_fvec4; + using glm::highp_fvec1; + using glm::highp_fvec2; + using glm::highp_fvec3; + using glm::highp_fvec4; + using glm::fvec1; + using glm::fvec2; + using glm::fvec3; + using glm::fvec4; + using glm::lowp_f32vec1; + using glm::lowp_f32vec2; + using glm::lowp_f32vec3; + using glm::lowp_f32vec4; + using glm::mediump_f32vec1; + using glm::mediump_f32vec2; + using glm::mediump_f32vec3; + using glm::mediump_f32vec4; + using glm::highp_f32vec1; + using glm::highp_f32vec2; + using glm::highp_f32vec3; + using glm::highp_f32vec4; + using glm::f32vec1; + using glm::f32vec2; + using glm::f32vec3; + using glm::f32vec4; + using glm::lowp_dvec1; + using glm::lowp_dvec2; + using glm::lowp_dvec3; + using glm::lowp_dvec4; + using glm::mediump_dvec1; + using glm::mediump_dvec2; + using glm::mediump_dvec3; + using glm::mediump_dvec4; + using glm::highp_dvec1; + using glm::highp_dvec2; + using glm::highp_dvec3; + using glm::highp_dvec4; + using glm::dvec1; + using glm::dvec2; + using glm::dvec3; + using glm::dvec4; + using glm::lowp_f64vec1; + using glm::lowp_f64vec2; + using glm::lowp_f64vec3; + using glm::lowp_f64vec4; + using glm::mediump_f64vec1; + using glm::mediump_f64vec2; + using glm::mediump_f64vec3; + using glm::mediump_f64vec4; + using glm::highp_f64vec1; + using glm::highp_f64vec2; + using glm::highp_f64vec3; + using glm::highp_f64vec4; + using glm::f64vec1; + using glm::f64vec2; + using glm::f64vec3; + using glm::f64vec4; + using glm::lowp_mat2; + using glm::lowp_mat3; + using glm::lowp_mat4; + using glm::mediump_mat2; + using glm::mediump_mat3; + using glm::mediump_mat4; + using glm::highp_mat2; + using glm::highp_mat3; + using glm::highp_mat4; + using glm::mat2; + using glm::mat3; + using glm::mat4; + using glm::lowp_fmat2; + using glm::lowp_fmat3; + using glm::lowp_fmat4; + using glm::mediump_fmat2; + using glm::mediump_fmat3; + using glm::mediump_fmat4; + using glm::highp_fmat2; + using glm::highp_fmat3; + using glm::highp_fmat4; + using glm::fmat2; + using glm::fmat3; + using glm::fmat4; + using glm::lowp_f32mat2; + using glm::lowp_f32mat3; + using glm::lowp_f32mat4; + using glm::mediump_f32mat2; + using glm::mediump_f32mat3; + using glm::mediump_f32mat4; + using glm::highp_f32mat2; + using glm::highp_f32mat3; + using glm::highp_f32mat4; + using glm::f32mat2; + using glm::f32mat3; + using glm::f32mat4; + using glm::lowp_dmat2; + using glm::lowp_dmat3; + using glm::lowp_dmat4; + using glm::mediump_dmat2; + using glm::mediump_dmat3; + using glm::mediump_dmat4; + using glm::highp_dmat2; + using glm::highp_dmat3; + using glm::highp_dmat4; + using glm::dmat2; + using glm::dmat3; + using glm::dmat4; + using glm::lowp_f64mat2; + using glm::lowp_f64mat3; + using glm::lowp_f64mat4; + using glm::mediump_f64mat2; + using glm::mediump_f64mat3; + using glm::mediump_f64mat4; + using glm::highp_f64mat2; + using glm::highp_f64mat3; + using glm::highp_f64mat4; + using glm::f64mat2; + using glm::f64mat3; + using glm::f64mat4; + using glm::lowp_mat2x2; + using glm::lowp_mat2x3; + using glm::lowp_mat2x4; + using glm::lowp_mat3x2; + using glm::lowp_mat3x3; + using glm::lowp_mat3x4; + using glm::lowp_mat4x2; + using glm::lowp_mat4x3; + using glm::lowp_mat4x4; + using glm::mediump_mat2x2; + using glm::mediump_mat2x3; + using glm::mediump_mat2x4; + using glm::mediump_mat3x2; + using glm::mediump_mat3x3; + using glm::mediump_mat3x4; + using glm::mediump_mat4x2; + using glm::mediump_mat4x3; + using glm::mediump_mat4x4; + using glm::highp_mat2x2; + using glm::highp_mat2x3; + using glm::highp_mat2x4; + using glm::highp_mat3x2; + using glm::highp_mat3x3; + using glm::highp_mat3x4; + using glm::highp_mat4x2; + using glm::highp_mat4x3; + using glm::highp_mat4x4; + using glm::mat2x2; + using glm::mat2x3; + using glm::mat2x4; + using glm::mat3x2; + using glm::mat3x3; + using glm::mat3x4; + using glm::mat4x2; + using glm::mat4x3; + using glm::mat4x4; + using glm::lowp_fmat2x2; + using glm::lowp_fmat2x3; + using glm::lowp_fmat2x4; + using glm::lowp_fmat3x2; + using glm::lowp_fmat3x3; + using glm::lowp_fmat3x4; + using glm::lowp_fmat4x2; + using glm::lowp_fmat4x3; + using glm::lowp_fmat4x4; + using glm::mediump_fmat2x2; + using glm::mediump_fmat2x3; + using glm::mediump_fmat2x4; + using glm::mediump_fmat3x2; + using glm::mediump_fmat3x3; + using glm::mediump_fmat3x4; + using glm::mediump_fmat4x2; + using glm::mediump_fmat4x3; + using glm::mediump_fmat4x4; + using glm::highp_fmat2x2; + using glm::highp_fmat2x3; + using glm::highp_fmat2x4; + using glm::highp_fmat3x2; + using glm::highp_fmat3x3; + using glm::highp_fmat3x4; + using glm::highp_fmat4x2; + using glm::highp_fmat4x3; + using glm::highp_fmat4x4; + using glm::fmat2x2; + using glm::fmat2x3; + using glm::fmat2x4; + using glm::fmat3x2; + using glm::fmat3x3; + using glm::fmat3x4; + using glm::fmat4x2; + using glm::fmat4x3; + using glm::fmat4x4; + using glm::lowp_f32mat2x2; + using glm::lowp_f32mat2x3; + using glm::lowp_f32mat2x4; + using glm::lowp_f32mat3x2; + using glm::lowp_f32mat3x3; + using glm::lowp_f32mat3x4; + using glm::lowp_f32mat4x2; + using glm::lowp_f32mat4x3; + using glm::lowp_f32mat4x4; + + using glm::mediump_f32mat2x2; + using glm::mediump_f32mat2x3; + using glm::mediump_f32mat2x4; + using glm::mediump_f32mat3x2; + using glm::mediump_f32mat3x3; + using glm::mediump_f32mat3x4; + using glm::mediump_f32mat4x2; + using glm::mediump_f32mat4x3; + using glm::mediump_f32mat4x4; + using glm::highp_f32mat2x2; + using glm::highp_f32mat2x3; + using glm::highp_f32mat2x4; + using glm::highp_f32mat3x2; + using glm::highp_f32mat3x3; + using glm::highp_f32mat3x4; + using glm::highp_f32mat4x2; + using glm::highp_f32mat4x3; + using glm::highp_f32mat4x4; + using glm::f32mat2x2; + using glm::f32mat2x3; + using glm::f32mat2x4; + using glm::f32mat3x2; + using glm::f32mat3x3; + using glm::f32mat3x4; + using glm::f32mat4x2; + using glm::f32mat4x3; + using glm::f32mat4x4; + using glm::lowp_dmat2x2; + using glm::lowp_dmat2x3; + using glm::lowp_dmat2x4; + using glm::lowp_dmat3x2; + using glm::lowp_dmat3x3; + using glm::lowp_dmat3x4; + using glm::lowp_dmat4x2; + using glm::lowp_dmat4x3; + using glm::lowp_dmat4x4; + using glm::mediump_dmat2x2; + using glm::mediump_dmat2x3; + using glm::mediump_dmat2x4; + using glm::mediump_dmat3x2; + using glm::mediump_dmat3x3; + using glm::mediump_dmat3x4; + using glm::mediump_dmat4x2; + using glm::mediump_dmat4x3; + using glm::mediump_dmat4x4; + using glm::highp_dmat2x2; + using glm::highp_dmat2x3; + using glm::highp_dmat2x4; + using glm::highp_dmat3x2; + using glm::highp_dmat3x3; + using glm::highp_dmat3x4; + using glm::highp_dmat4x2; + using glm::highp_dmat4x3; + using glm::highp_dmat4x4; + using glm::dmat2x2; + using glm::dmat2x3; + using glm::dmat2x4; + using glm::dmat3x2; + using glm::dmat3x3; + using glm::dmat3x4; + using glm::dmat4x2; + using glm::dmat4x3; + using glm::dmat4x4; + using glm::lowp_f64mat2x2; + using glm::lowp_f64mat2x3; + using glm::lowp_f64mat2x4; + using glm::lowp_f64mat3x2; + using glm::lowp_f64mat3x3; + using glm::lowp_f64mat3x4; + using glm::lowp_f64mat4x2; + using glm::lowp_f64mat4x3; + using glm::lowp_f64mat4x4; + using glm::mediump_f64mat2x2; + using glm::mediump_f64mat2x3; + using glm::mediump_f64mat2x4; + using glm::mediump_f64mat3x2; + using glm::mediump_f64mat3x3; + using glm::mediump_f64mat3x4; + using glm::mediump_f64mat4x2; + using glm::mediump_f64mat4x3; + using glm::mediump_f64mat4x4; + using glm::highp_f64mat2x2; + using glm::highp_f64mat2x3; + using glm::highp_f64mat2x4; + using glm::highp_f64mat3x2; + using glm::highp_f64mat3x3; + using glm::highp_f64mat3x4; + using glm::highp_f64mat4x2; + using glm::highp_f64mat4x3; + using glm::highp_f64mat4x4; + using glm::f64mat2x2; + using glm::f64mat2x3; + using glm::f64mat2x4; + using glm::f64mat3x2; + using glm::f64mat3x3; + using glm::f64mat3x4; + using glm::f64mat4x2; + using glm::f64mat4x3; + using glm::f64mat4x4; + using glm::lowp_imat2x2; + using glm::lowp_imat2x3; + using glm::lowp_imat2x4; + using glm::lowp_imat3x2; + using glm::lowp_imat3x3; + using glm::lowp_imat3x4; + using glm::lowp_imat4x2; + using glm::lowp_imat4x3; + using glm::lowp_imat4x4; + using glm::mediump_imat2x2; + using glm::mediump_imat2x3; + using glm::mediump_imat2x4; + using glm::mediump_imat3x2; + using glm::mediump_imat3x3; + using glm::mediump_imat3x4; + using glm::mediump_imat4x2; + using glm::mediump_imat4x3; + using glm::mediump_imat4x4; + using glm::highp_imat2x2; + using glm::highp_imat2x3; + using glm::highp_imat2x4; + using glm::highp_imat3x2; + using glm::highp_imat3x3; + using glm::highp_imat3x4; + using glm::highp_imat4x2; + using glm::highp_imat4x3; + using glm::highp_imat4x4; + using glm::imat2x2; + using glm::imat2x3; + using glm::imat2x4; + using glm::imat3x2; + using glm::imat3x3; + using glm::imat3x4; + using glm::imat4x2; + using glm::imat4x3; + using glm::imat4x4; + using glm::lowp_i8mat2x2; + using glm::lowp_i8mat2x3; + using glm::lowp_i8mat2x4; + using glm::lowp_i8mat3x2; + using glm::lowp_i8mat3x3; + using glm::lowp_i8mat3x4; + using glm::lowp_i8mat4x2; + using glm::lowp_i8mat4x3; + using glm::lowp_i8mat4x4; + using glm::mediump_i8mat2x2; + using glm::mediump_i8mat2x3; + using glm::mediump_i8mat2x4; + using glm::mediump_i8mat3x2; + using glm::mediump_i8mat3x3; + using glm::mediump_i8mat3x4; + using glm::mediump_i8mat4x2; + using glm::mediump_i8mat4x3; + using glm::mediump_i8mat4x4; + using glm::highp_i8mat2x2; + using glm::highp_i8mat2x3; + using glm::highp_i8mat2x4; + using glm::highp_i8mat3x2; + using glm::highp_i8mat3x3; + using glm::highp_i8mat3x4; + using glm::highp_i8mat4x2; + using glm::highp_i8mat4x3; + using glm::highp_i8mat4x4; + using glm::i8mat2x2; + using glm::i8mat2x3; + using glm::i8mat2x4; + using glm::i8mat3x2; + using glm::i8mat3x3; + using glm::i8mat3x4; + using glm::i8mat4x2; + using glm::i8mat4x3; + using glm::i8mat4x4; + using glm::lowp_i16mat2x2; + using glm::lowp_i16mat2x3; + using glm::lowp_i16mat2x4; + using glm::lowp_i16mat3x2; + using glm::lowp_i16mat3x3; + using glm::lowp_i16mat3x4; + using glm::lowp_i16mat4x2; + using glm::lowp_i16mat4x3; + using glm::lowp_i16mat4x4; + using glm::mediump_i16mat2x2; + using glm::mediump_i16mat2x3; + using glm::mediump_i16mat2x4; + using glm::mediump_i16mat3x2; + using glm::mediump_i16mat3x3; + using glm::mediump_i16mat3x4; + using glm::mediump_i16mat4x2; + using glm::mediump_i16mat4x3; + using glm::mediump_i16mat4x4; + using glm::highp_i16mat2x2; + using glm::highp_i16mat2x3; + using glm::highp_i16mat2x4; + using glm::highp_i16mat3x2; + using glm::highp_i16mat3x3; + using glm::highp_i16mat3x4; + using glm::highp_i16mat4x2; + using glm::highp_i16mat4x3; + using glm::highp_i16mat4x4; + using glm::i16mat2x2; + using glm::i16mat2x3; + using glm::i16mat2x4; + using glm::i16mat3x2; + using glm::i16mat3x3; + using glm::i16mat3x4; + using glm::i16mat4x2; + using glm::i16mat4x3; + using glm::i16mat4x4; + using glm::lowp_i32mat2x2; + using glm::lowp_i32mat2x3; + using glm::lowp_i32mat2x4; + using glm::lowp_i32mat3x2; + using glm::lowp_i32mat3x3; + using glm::lowp_i32mat3x4; + using glm::lowp_i32mat4x2; + using glm::lowp_i32mat4x3; + using glm::lowp_i32mat4x4; + using glm::mediump_i32mat2x2; + using glm::mediump_i32mat2x3; + using glm::mediump_i32mat2x4; + using glm::mediump_i32mat3x2; + using glm::mediump_i32mat3x3; + using glm::mediump_i32mat3x4; + using glm::mediump_i32mat4x2; + using glm::mediump_i32mat4x3; + using glm::mediump_i32mat4x4; + using glm::highp_i32mat2x2; + using glm::highp_i32mat2x3; + using glm::highp_i32mat2x4; + using glm::highp_i32mat3x2; + using glm::highp_i32mat3x3; + using glm::highp_i32mat3x4; + using glm::highp_i32mat4x2; + using glm::highp_i32mat4x3; + using glm::highp_i32mat4x4; + using glm::i32mat2x2; + using glm::i32mat2x3; + using glm::i32mat2x4; + using glm::i32mat3x2; + using glm::i32mat3x3; + using glm::i32mat3x4; + using glm::i32mat4x2; + using glm::i32mat4x3; + using glm::i32mat4x4; + using glm::lowp_i64mat2x2; + using glm::lowp_i64mat2x3; + using glm::lowp_i64mat2x4; + using glm::lowp_i64mat3x2; + using glm::lowp_i64mat3x3; + using glm::lowp_i64mat3x4; + using glm::lowp_i64mat4x2; + using glm::lowp_i64mat4x3; + using glm::lowp_i64mat4x4; + using glm::mediump_i64mat2x2; + using glm::mediump_i64mat2x3; + using glm::mediump_i64mat2x4; + using glm::mediump_i64mat3x2; + using glm::mediump_i64mat3x3; + using glm::mediump_i64mat3x4; + using glm::mediump_i64mat4x2; + using glm::mediump_i64mat4x3; + using glm::mediump_i64mat4x4; + using glm::highp_i64mat2x2; + using glm::highp_i64mat2x3; + using glm::highp_i64mat2x4; + using glm::highp_i64mat3x2; + using glm::highp_i64mat3x3; + using glm::highp_i64mat3x4; + using glm::highp_i64mat4x2; + using glm::highp_i64mat4x3; + using glm::highp_i64mat4x4; + using glm::i64mat2x2; + using glm::i64mat2x3; + using glm::i64mat2x4; + using glm::i64mat3x2; + using glm::i64mat3x3; + using glm::i64mat3x4; + using glm::i64mat4x2; + using glm::i64mat4x3; + using glm::i64mat4x4; + using glm::lowp_umat2x2; + using glm::lowp_umat2x3; + using glm::lowp_umat2x4; + using glm::lowp_umat3x2; + using glm::lowp_umat3x3; + using glm::lowp_umat3x4; + using glm::lowp_umat4x2; + using glm::lowp_umat4x3; + using glm::lowp_umat4x4; + using glm::mediump_umat2x2; + using glm::mediump_umat2x3; + using glm::mediump_umat2x4; + using glm::mediump_umat3x2; + using glm::mediump_umat3x3; + using glm::mediump_umat3x4; + using glm::mediump_umat4x2; + using glm::mediump_umat4x3; + using glm::mediump_umat4x4; + using glm::highp_umat2x2; + using glm::highp_umat2x3; + using glm::highp_umat2x4; + using glm::highp_umat3x2; + using glm::highp_umat3x3; + using glm::highp_umat3x4; + using glm::highp_umat4x2; + using glm::highp_umat4x3; + using glm::highp_umat4x4; + using glm::umat2x2; + using glm::umat2x3; + using glm::umat2x4; + using glm::umat3x2; + using glm::umat3x3; + using glm::umat3x4; + using glm::umat4x2; + using glm::umat4x3; + using glm::umat4x4; + using glm::lowp_u8mat2x2; + using glm::lowp_u8mat2x3; + using glm::lowp_u8mat2x4; + using glm::lowp_u8mat3x2; + using glm::lowp_u8mat3x3; + using glm::lowp_u8mat3x4; + using glm::lowp_u8mat4x2; + using glm::lowp_u8mat4x3; + using glm::lowp_u8mat4x4; + using glm::mediump_u8mat2x2; + using glm::mediump_u8mat2x3; + using glm::mediump_u8mat2x4; + using glm::mediump_u8mat3x2; + using glm::mediump_u8mat3x3; + using glm::mediump_u8mat3x4; + using glm::mediump_u8mat4x2; + using glm::mediump_u8mat4x3; + using glm::mediump_u8mat4x4; + using glm::highp_u8mat2x2; + using glm::highp_u8mat2x3; + using glm::highp_u8mat2x4; + using glm::highp_u8mat3x2; + using glm::highp_u8mat3x3; + using glm::highp_u8mat3x4; + using glm::highp_u8mat4x2; + using glm::highp_u8mat4x3; + using glm::highp_u8mat4x4; + using glm::u8mat2x2; + using glm::u8mat2x3; + using glm::u8mat2x4; + using glm::u8mat3x2; + using glm::u8mat3x3; + using glm::u8mat3x4; + using glm::u8mat4x2; + using glm::u8mat4x3; + using glm::u8mat4x4; + using glm::lowp_u16mat2x2; + using glm::lowp_u16mat2x3; + using glm::lowp_u16mat2x4; + using glm::lowp_u16mat3x2; + using glm::lowp_u16mat3x3; + using glm::lowp_u16mat3x4; + using glm::lowp_u16mat4x2; + using glm::lowp_u16mat4x3; + using glm::lowp_u16mat4x4; + using glm::mediump_u16mat2x2; + using glm::mediump_u16mat2x3; + using glm::mediump_u16mat2x4; + using glm::mediump_u16mat3x2; + using glm::mediump_u16mat3x3; + using glm::mediump_u16mat3x4; + using glm::mediump_u16mat4x2; + using glm::mediump_u16mat4x3; + using glm::mediump_u16mat4x4; + using glm::highp_u16mat2x2; + using glm::highp_u16mat2x3; + using glm::highp_u16mat2x4; + using glm::highp_u16mat3x2; + using glm::highp_u16mat3x3; + using glm::highp_u16mat3x4; + using glm::highp_u16mat4x2; + using glm::highp_u16mat4x3; + using glm::highp_u16mat4x4; + using glm::u16mat2x2; + using glm::u16mat2x3; + using glm::u16mat2x4; + using glm::u16mat3x2; + using glm::u16mat3x3; + using glm::u16mat3x4; + using glm::u16mat4x2; + using glm::u16mat4x3; + using glm::u16mat4x4; + using glm::lowp_u32mat2x2; + using glm::lowp_u32mat2x3; + using glm::lowp_u32mat2x4; + using glm::lowp_u32mat3x2; + using glm::lowp_u32mat3x3; + using glm::lowp_u32mat3x4; + using glm::lowp_u32mat4x2; + using glm::lowp_u32mat4x3; + using glm::lowp_u32mat4x4; + using glm::mediump_u32mat2x2; + using glm::mediump_u32mat2x3; + using glm::mediump_u32mat2x4; + using glm::mediump_u32mat3x2; + using glm::mediump_u32mat3x3; + using glm::mediump_u32mat3x4; + using glm::mediump_u32mat4x2; + using glm::mediump_u32mat4x3; + using glm::mediump_u32mat4x4; + using glm::highp_u32mat2x2; + using glm::highp_u32mat2x3; + using glm::highp_u32mat2x4; + using glm::highp_u32mat3x2; + using glm::highp_u32mat3x3; + using glm::highp_u32mat3x4; + using glm::highp_u32mat4x2; + using glm::highp_u32mat4x3; + using glm::highp_u32mat4x4; + using glm::u32mat2x2; + using glm::u32mat2x3; + using glm::u32mat2x4; + using glm::u32mat3x2; + using glm::u32mat3x3; + using glm::u32mat3x4; + using glm::u32mat4x2; + using glm::u32mat4x3; + using glm::u32mat4x4; + using glm::lowp_u64mat2x2; + using glm::lowp_u64mat2x3; + using glm::lowp_u64mat2x4; + using glm::lowp_u64mat3x2; + using glm::lowp_u64mat3x3; + using glm::lowp_u64mat3x4; + using glm::lowp_u64mat4x2; + using glm::lowp_u64mat4x3; + using glm::lowp_u64mat4x4; + using glm::mediump_u64mat2x2; + using glm::mediump_u64mat2x3; + using glm::mediump_u64mat2x4; + using glm::mediump_u64mat3x2; + using glm::mediump_u64mat3x3; + using glm::mediump_u64mat3x4; + using glm::mediump_u64mat4x2; + using glm::mediump_u64mat4x3; + using glm::mediump_u64mat4x4; + using glm::highp_u64mat2x2; + using glm::highp_u64mat2x3; + using glm::highp_u64mat2x4; + using glm::highp_u64mat3x2; + using glm::highp_u64mat3x3; + using glm::highp_u64mat3x4; + using glm::highp_u64mat4x2; + using glm::highp_u64mat4x3; + using glm::highp_u64mat4x4; + using glm::u64mat2x2; + using glm::u64mat2x3; + using glm::u64mat2x4; + using glm::u64mat3x2; + using glm::u64mat3x3; + using glm::u64mat3x4; + using glm::u64mat4x2; + using glm::u64mat4x3; + using glm::u64mat4x4; + using glm::lowp_quat; + using glm::mediump_quat; + using glm::highp_quat; + using glm::quat; + using glm::lowp_fquat; + using glm::mediump_fquat; + using glm::highp_fquat; + using glm::fquat; + using glm::lowp_f32quat; + using glm::mediump_f32quat; + using glm::highp_f32quat; + using glm::f32quat; + using glm::lowp_dquat; + using glm::mediump_dquat; + using glm::highp_dquat; + using glm::dquat; + using glm::lowp_f64quat; + using glm::mediump_f64quat; + using glm::highp_f64quat; + using glm::f64quat; + + // Operators + using glm::operator+; + using glm::operator-; + using glm::operator*; + using glm::operator/; + using glm::operator%; + using glm::operator^; + using glm::operator&; + using glm::operator|; + using glm::operator~; + using glm::operator<<; + using glm::operator>>; + using glm::operator==; + using glm::operator!=; + using glm::operator&&; + using glm::operator||; + + // Core functions + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::all; + using glm::any; + using glm::asin; + using glm::asinh; + using glm::atan; + using glm::atanh; + using glm::bitCount; + using glm::bitfieldExtract; + using glm::bitfieldInsert; + using glm::bitfieldReverse; + using glm::ceil; + using glm::clamp; + using glm::cos; + using glm::cosh; + using glm::cross; + using glm::degrees; + using glm::determinant; + using glm::distance; + using glm::dot; + using glm::equal; + using glm::exp; + using glm::exp2; + using glm::faceforward; + using glm::findLSB; + using glm::findMSB; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::floor; + using glm::fma; + using glm::fract; + using glm::frexp; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::imulExtended; + using glm::intBitsToFloat; + using glm::inverse; + using glm::inversesqrt; + using glm::isinf; + using glm::isnan; + using glm::ldexp; + using glm::length; + using glm::lessThan; + using glm::lessThanEqual; + using glm::log; + using glm::log2; + using glm::matrixCompMult; + using glm::max; + using glm::min; + using glm::mix; + using glm::mod; + using glm::modf; + using glm::normalize; + using glm::notEqual; + using glm::not_; + using glm::outerProduct; + using glm::packDouble2x32; + using glm::packHalf2x16; + using glm::packSnorm2x16; + using glm::packSnorm4x8; + using glm::packUnorm2x16; + using glm::packUnorm4x8; + using glm::pow; + using glm::radians; + using glm::reflect; + using glm::refract; + using glm::round; + using glm::roundEven; + using glm::sign; + using glm::sin; + using glm::sinh; + using glm::smoothstep; + using glm::sqrt; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::transpose; + using glm::trunc; + using glm::uaddCarry; + using glm::uintBitsToFloat; + using glm::umulExtended; + using glm::unpackDouble2x32; + using glm::unpackHalf2x16; + using glm::unpackSnorm2x16; + using glm::unpackSnorm4x8; + using glm::unpackUnorm2x16; + using glm::unpackUnorm4x8; + using glm::usubBorrow; + +# ifdef GLM_GTC_INLINE_NAMESPACE + inline +# endif + namespace gtc { +# if GLM_CONFIG_ALIGNED_GENTYPES == GLM_ENABLE + using glm::aligned_highp_vec1; + using glm::aligned_mediump_vec1; + using glm::aligned_lowp_vec1; + using glm::aligned_highp_dvec1; + using glm::aligned_mediump_dvec1; + using glm::aligned_lowp_dvec1; + using glm::aligned_highp_ivec1; + using glm::aligned_mediump_ivec1; + using glm::aligned_lowp_ivec1; + using glm::aligned_highp_uvec1; + using glm::aligned_mediump_uvec1; + using glm::aligned_lowp_uvec1; + using glm::aligned_highp_bvec1; + using glm::aligned_mediump_bvec1; + using glm::aligned_lowp_bvec1; + using glm::packed_highp_vec1; + using glm::packed_mediump_vec1; + using glm::packed_lowp_vec1; + using glm::packed_highp_dvec1; + using glm::packed_mediump_dvec1; + using glm::packed_lowp_dvec1; + using glm::packed_highp_ivec1; + using glm::packed_mediump_ivec1; + using glm::packed_lowp_ivec1; + using glm::packed_highp_uvec1; + using glm::packed_mediump_uvec1; + using glm::packed_lowp_uvec1; + using glm::packed_highp_bvec1; + using glm::packed_mediump_bvec1; + using glm::packed_lowp_bvec1; + using glm::aligned_highp_vec2; + using glm::aligned_mediump_vec2; + using glm::aligned_lowp_vec2; + using glm::aligned_highp_dvec2; + using glm::aligned_mediump_dvec2; + using glm::aligned_lowp_dvec2; + using glm::aligned_highp_ivec2; + using glm::aligned_mediump_ivec2; + using glm::aligned_lowp_ivec2; + using glm::aligned_highp_uvec2; + using glm::aligned_mediump_uvec2; + using glm::aligned_lowp_uvec2; + using glm::aligned_highp_bvec2; + using glm::aligned_mediump_bvec2; + using glm::aligned_lowp_bvec2; + using glm::packed_highp_vec2; + using glm::packed_mediump_vec2; + using glm::packed_lowp_vec2; + using glm::packed_highp_dvec2; + using glm::packed_mediump_dvec2; + using glm::packed_lowp_dvec2; + using glm::packed_highp_ivec2; + using glm::packed_mediump_ivec2; + using glm::packed_lowp_ivec2; + using glm::packed_highp_uvec2; + using glm::packed_mediump_uvec2; + using glm::packed_lowp_uvec2; + using glm::packed_highp_bvec2; + using glm::packed_mediump_bvec2; + using glm::packed_lowp_bvec2; + using glm::aligned_highp_vec3; + using glm::aligned_mediump_vec3; + using glm::aligned_lowp_vec3; + using glm::aligned_highp_dvec3; + using glm::aligned_mediump_dvec3; + using glm::aligned_lowp_dvec3; + using glm::aligned_highp_ivec3; + using glm::aligned_mediump_ivec3; + using glm::aligned_lowp_ivec3; + using glm::aligned_highp_uvec3; + using glm::aligned_mediump_uvec3; + using glm::aligned_lowp_uvec3; + using glm::aligned_highp_bvec3; + using glm::aligned_mediump_bvec3; + using glm::aligned_lowp_bvec3; + using glm::packed_highp_vec3; + using glm::packed_mediump_vec3; + using glm::packed_lowp_vec3; + using glm::packed_highp_dvec3; + using glm::packed_mediump_dvec3; + using glm::packed_lowp_dvec3; + using glm::packed_highp_ivec3; + using glm::packed_mediump_ivec3; + using glm::packed_lowp_ivec3; + using glm::packed_highp_uvec3; + using glm::packed_mediump_uvec3; + using glm::packed_lowp_uvec3; + using glm::packed_highp_bvec3; + using glm::packed_mediump_bvec3; + using glm::packed_lowp_bvec3; + using glm::aligned_highp_vec4; + using glm::aligned_mediump_vec4; + using glm::aligned_lowp_vec4; + using glm::aligned_highp_dvec4; + using glm::aligned_mediump_dvec4; + using glm::aligned_lowp_dvec4; + using glm::aligned_highp_ivec4; + using glm::aligned_mediump_ivec4; + using glm::aligned_lowp_ivec4; + using glm::aligned_highp_uvec4; + using glm::aligned_mediump_uvec4; + using glm::aligned_lowp_uvec4; + using glm::aligned_highp_bvec4; + using glm::aligned_mediump_bvec4; + using glm::aligned_lowp_bvec4; + using glm::packed_highp_vec4; + using glm::packed_mediump_vec4; + using glm::packed_lowp_vec4; + using glm::packed_highp_dvec4; + using glm::packed_mediump_dvec4; + using glm::packed_lowp_dvec4; + using glm::packed_highp_ivec4; + using glm::packed_mediump_ivec4; + using glm::packed_lowp_ivec4; + using glm::packed_highp_uvec4; + using glm::packed_mediump_uvec4; + using glm::packed_lowp_uvec4; + using glm::packed_highp_bvec4; + using glm::packed_mediump_bvec4; + using glm::packed_lowp_bvec4; + using glm::aligned_highp_mat2; + using glm::aligned_mediump_mat2; + using glm::aligned_lowp_mat2; + using glm::aligned_highp_dmat2; + using glm::aligned_mediump_dmat2; + using glm::aligned_lowp_dmat2; + using glm::packed_highp_mat2; + using glm::packed_mediump_mat2; + using glm::packed_lowp_mat2; + using glm::packed_highp_dmat2; + using glm::packed_mediump_dmat2; + using glm::packed_lowp_dmat2; + using glm::aligned_highp_mat3; + using glm::aligned_mediump_mat3; + using glm::aligned_lowp_mat3; + using glm::aligned_highp_dmat3; + using glm::aligned_mediump_dmat3; + using glm::aligned_lowp_dmat3; + using glm::packed_highp_mat3; + using glm::packed_mediump_mat3; + using glm::packed_lowp_mat3; + using glm::packed_highp_dmat3; + using glm::packed_mediump_dmat3; + using glm::packed_lowp_dmat3; + using glm::aligned_highp_mat4; + using glm::aligned_mediump_mat4; + using glm::aligned_lowp_mat4; + using glm::aligned_highp_dmat4; + using glm::aligned_mediump_dmat4; + using glm::aligned_lowp_dmat4; + using glm::packed_highp_mat4; + using glm::packed_mediump_mat4; + using glm::packed_lowp_mat4; + using glm::packed_highp_dmat4; + using glm::packed_mediump_dmat4; + using glm::packed_lowp_dmat4; + using glm::aligned_highp_mat2x2; + using glm::aligned_mediump_mat2x2; + using glm::aligned_lowp_mat2x2; + using glm::aligned_highp_dmat2x2; + using glm::aligned_mediump_dmat2x2; + using glm::aligned_lowp_dmat2x2; + using glm::packed_highp_mat2x2; + using glm::packed_mediump_mat2x2; + using glm::packed_lowp_mat2x2; + using glm::packed_highp_dmat2x2; + using glm::packed_mediump_dmat2x2; + using glm::packed_lowp_dmat2x2; + using glm::aligned_highp_mat2x3; + using glm::aligned_mediump_mat2x3; + using glm::aligned_lowp_mat2x3; + using glm::aligned_highp_dmat2x3; + using glm::aligned_mediump_dmat2x3; + using glm::aligned_lowp_dmat2x3; + using glm::packed_highp_mat2x3; + using glm::packed_mediump_mat2x3; + using glm::packed_lowp_mat2x3; + using glm::packed_highp_dmat2x3; + using glm::packed_mediump_dmat2x3; + using glm::packed_lowp_dmat2x3; + using glm::aligned_highp_mat2x4; + using glm::aligned_mediump_mat2x4; + using glm::aligned_lowp_mat2x4; + using glm::aligned_highp_dmat2x4; + using glm::aligned_mediump_dmat2x4; + using glm::aligned_lowp_dmat2x4; + using glm::packed_highp_mat2x4; + using glm::packed_mediump_mat2x4; + using glm::packed_lowp_mat2x4; + using glm::packed_highp_dmat2x4; + using glm::packed_mediump_dmat2x4; + using glm::packed_lowp_dmat2x4; + using glm::aligned_highp_mat3x2; + using glm::aligned_mediump_mat3x2; + using glm::aligned_lowp_mat3x2; + using glm::aligned_highp_dmat3x2; + using glm::aligned_mediump_dmat3x2; + using glm::aligned_lowp_dmat3x2; + using glm::packed_highp_mat3x2; + using glm::packed_mediump_mat3x2; + using glm::packed_lowp_mat3x2; + using glm::packed_highp_dmat3x2; + using glm::packed_mediump_dmat3x2; + using glm::packed_lowp_dmat3x2; + using glm::aligned_highp_mat3x3; + using glm::aligned_mediump_mat3x3; + using glm::aligned_lowp_mat3x3; + using glm::aligned_highp_dmat3x3; + using glm::aligned_mediump_dmat3x3; + using glm::aligned_lowp_dmat3x3; + using glm::packed_highp_mat3x3; + using glm::packed_mediump_mat3x3; + using glm::packed_lowp_mat3x3; + using glm::packed_highp_dmat3x3; + using glm::packed_mediump_dmat3x3; + using glm::packed_lowp_dmat3x3; + using glm::aligned_highp_mat3x4; + using glm::aligned_mediump_mat3x4; + using glm::aligned_lowp_mat3x4; + using glm::aligned_highp_dmat3x4; + using glm::aligned_mediump_dmat3x4; + using glm::aligned_lowp_dmat3x4; + using glm::packed_highp_mat3x4; + using glm::packed_mediump_mat3x4; + using glm::packed_lowp_mat3x4; + using glm::packed_highp_dmat3x4; + using glm::packed_mediump_dmat3x4; + using glm::packed_lowp_dmat3x4; + using glm::aligned_highp_mat4x2; + using glm::aligned_mediump_mat4x2; + using glm::aligned_lowp_mat4x2; + using glm::aligned_highp_dmat4x2; + using glm::aligned_mediump_dmat4x2; + using glm::aligned_lowp_dmat4x2; + using glm::packed_highp_mat4x2; + using glm::packed_mediump_mat4x2; + using glm::packed_lowp_mat4x2; + using glm::packed_highp_dmat4x2; + using glm::packed_mediump_dmat4x2; + using glm::packed_lowp_dmat4x2; + using glm::aligned_highp_mat4x3; + using glm::aligned_mediump_mat4x3; + using glm::aligned_lowp_mat4x3; + using glm::aligned_highp_dmat4x3; + using glm::aligned_mediump_dmat4x3; + using glm::aligned_lowp_dmat4x3; + using glm::packed_highp_mat4x3; + using glm::packed_mediump_mat4x3; + using glm::packed_lowp_mat4x3; + using glm::packed_highp_dmat4x3; + using glm::packed_mediump_dmat4x3; + using glm::packed_lowp_dmat4x3; + using glm::aligned_highp_mat4x4; + using glm::aligned_mediump_mat4x4; + using glm::aligned_lowp_mat4x4; + using glm::aligned_highp_dmat4x4; + using glm::aligned_mediump_dmat4x4; + using glm::aligned_lowp_dmat4x4; + using glm::packed_highp_mat4x4; + using glm::packed_mediump_mat4x4; + using glm::packed_lowp_mat4x4; + using glm::packed_highp_dmat4x4; + using glm::packed_mediump_dmat4x4; + using glm::packed_lowp_dmat4x4; +# if(defined(GLM_PRECISION_LOWP_FLOAT)) + using glm::aligned_vec1; + using glm::aligned_vec2; + using glm::aligned_vec3; + using glm::aligned_vec4; + using glm::packed_vec1; + using glm::packed_vec2; + using glm::packed_vec3; + using glm::packed_vec4; + using glm::aligned_mat2; + using glm::aligned_mat3; + using glm::aligned_mat4; + using glm::packed_mat2; + using glm::packed_mat3; + using glm::packed_mat4; + using glm::aligned_mat2x2; + using glm::aligned_mat2x3; + using glm::aligned_mat2x4; + using glm::aligned_mat3x2; + using glm::aligned_mat3x3; + using glm::aligned_mat3x4; + using glm::aligned_mat4x2; + using glm::aligned_mat4x3; + using glm::aligned_mat4x4; + using glm::packed_mat2x2; + using glm::packed_mat2x3; + using glm::packed_mat2x4; + using glm::packed_mat3x2; + using glm::packed_mat3x3; + using glm::packed_mat3x4; + using glm::packed_mat4x2; + using glm::packed_mat4x3; + using glm::packed_mat4x4; +# elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + using glm::aligned_vec1; + using glm::aligned_vec2; + using glm::aligned_vec3; + using glm::aligned_vec4; + using glm::packed_vec1; + using glm::packed_vec2; + using glm::packed_vec3; + using glm::packed_vec4; + using glm::aligned_mat2; + using glm::aligned_mat3; + using glm::aligned_mat4; + using glm::packed_mat2; + using glm::packed_mat3; + using glm::packed_mat4; + using glm::aligned_mat2x2; + using glm::aligned_mat2x3; + using glm::aligned_mat2x4; + using glm::aligned_mat3x2; + using glm::aligned_mat3x3; + using glm::aligned_mat3x4; + using glm::aligned_mat4x2; + using glm::aligned_mat4x3; + using glm::aligned_mat4x4; + using glm::packed_mat2x2; + using glm::packed_mat2x3; + using glm::packed_mat2x4; + using glm::packed_mat3x2; + using glm::packed_mat3x3; + using glm::packed_mat3x4; + using glm::packed_mat4x2; + using glm::packed_mat4x3; + using glm::packed_mat4x4; +# else //defined(GLM_PRECISION_HIGHP_FLOAT) + using glm::aligned_vec1; + using glm::aligned_vec2; + using glm::aligned_vec3; + using glm::aligned_vec4; + using glm::packed_vec1; + using glm::packed_vec2; + using glm::packed_vec3; + using glm::packed_vec4; + using glm::aligned_mat2; + using glm::aligned_mat3; + using glm::aligned_mat4; + using glm::packed_mat2; + using glm::packed_mat3; + using glm::packed_mat4; + using glm::aligned_mat2x2; + using glm::aligned_mat2x3; + using glm::aligned_mat2x4; + using glm::aligned_mat3x2; + using glm::aligned_mat3x3; + using glm::aligned_mat3x4; + using glm::aligned_mat4x2; + using glm::aligned_mat4x3; + using glm::aligned_mat4x4; + using glm::packed_mat2x2; + using glm::packed_mat2x3; + using glm::packed_mat2x4; + using glm::packed_mat3x2; + using glm::packed_mat3x3; + using glm::packed_mat3x4; + using glm::packed_mat4x2; + using glm::packed_mat4x3; + using glm::packed_mat4x4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_DOUBLE)) + using glm::aligned_dvec1; + using glm::aligned_dvec2; + using glm::aligned_dvec3; + using glm::aligned_dvec4; + using glm::packed_dvec1; + using glm::packed_dvec2; + using glm::packed_dvec3; + using glm::packed_dvec4; + using glm::aligned_dmat2; + using glm::aligned_dmat3; + using glm::aligned_dmat4; + using glm::packed_dmat2; + using glm::packed_dmat3; + using glm::packed_dmat4; + using glm::aligned_dmat2x2; + using glm::aligned_dmat2x3; + using glm::aligned_dmat2x4; + using glm::aligned_dmat3x2; + using glm::aligned_dmat3x3; + using glm::aligned_dmat3x4; + using glm::aligned_dmat4x2; + using glm::aligned_dmat4x3; + using glm::aligned_dmat4x4; + using glm::packed_dmat2x2; + using glm::packed_dmat2x3; + using glm::packed_dmat2x4; + using glm::packed_dmat3x2; + using glm::packed_dmat3x3; + using glm::packed_dmat3x4; + using glm::packed_dmat4x2; + using glm::packed_dmat4x3; + using glm::packed_dmat4x4; +# elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + using glm::aligned_dvec1; + using glm::aligned_dvec2; + using glm::aligned_dvec3; + using glm::aligned_dvec4; + using glm::packed_dvec1; + using glm::packed_dvec2; + using glm::packed_dvec3; + using glm::packed_dvec4; + using glm::aligned_dmat2; + using glm::aligned_dmat3; + using glm::aligned_dmat4; + using glm::packed_dmat2; + using glm::packed_dmat3; + using glm::packed_dmat4; + using glm::aligned_dmat2x2; + using glm::aligned_dmat2x3; + using glm::aligned_dmat2x4; + using glm::aligned_dmat3x2; + using glm::aligned_dmat3x3; + using glm::aligned_dmat3x4; + using glm::aligned_dmat4x2; + using glm::aligned_dmat4x3; + using glm::aligned_dmat4x4; + using glm::packed_dmat2x2; + using glm::packed_dmat2x3; + using glm::packed_dmat2x4; + using glm::packed_dmat3x2; + using glm::packed_dmat3x3; + using glm::packed_dmat3x4; + using glm::packed_dmat4x2; + using glm::packed_dmat4x3; + using glm::packed_dmat4x4; +# else //defined(GLM_PRECISION_HIGHP_DOUBLE) + using glm::aligned_dvec1; + using glm::aligned_dvec2; + using glm::aligned_dvec3; + using glm::aligned_dvec4; + using glm::packed_dvec1; + using glm::packed_dvec2; + using glm::packed_dvec3; + using glm::packed_dvec4; + using glm::aligned_dmat2; + using glm::aligned_dmat3; + using glm::aligned_dmat4; + using glm::packed_dmat2; + using glm::packed_dmat3; + using glm::packed_dmat4; + using glm::aligned_dmat2x2; + using glm::aligned_dmat2x3; + using glm::aligned_dmat2x4; + using glm::aligned_dmat3x2; + using glm::aligned_dmat3x3; + using glm::aligned_dmat3x4; + using glm::aligned_dmat4x2; + using glm::aligned_dmat4x3; + using glm::aligned_dmat4x4; + using glm::packed_dmat2x2; + using glm::packed_dmat2x3; + using glm::packed_dmat2x4; + using glm::packed_dmat3x2; + using glm::packed_dmat3x3; + using glm::packed_dmat3x4; + using glm::packed_dmat4x2; + using glm::packed_dmat4x3; + using glm::packed_dmat4x4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_INT)) + using glm::aligned_ivec1; + using glm::aligned_ivec2; + using glm::aligned_ivec3; + using glm::aligned_ivec4; +# elif(defined(GLM_PRECISION_MEDIUMP_INT)) + using glm::aligned_ivec1; + using glm::aligned_ivec2; + using glm::aligned_ivec3; + using glm::aligned_ivec4; +# else //defined(GLM_PRECISION_HIGHP_INT) + using glm::aligned_ivec1; + using glm::aligned_ivec2; + using glm::aligned_ivec3; + using glm::aligned_ivec4; + using glm::packed_ivec1; + using glm::packed_ivec2; + using glm::packed_ivec3; + using glm::packed_ivec4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_UINT)) + using glm::aligned_uvec1; + using glm::aligned_uvec2; + using glm::aligned_uvec3; + using glm::aligned_uvec4; +# elif(defined(GLM_PRECISION_MEDIUMP_UINT)) + using glm::aligned_uvec1; + using glm::aligned_uvec2; + using glm::aligned_uvec3; + using glm::aligned_uvec4; +# else //defined(GLM_PRECISION_HIGHP_UINT) + using glm::aligned_uvec1; + using glm::aligned_uvec2; + using glm::aligned_uvec3; + using glm::aligned_uvec4; + using glm::packed_uvec1; + using glm::packed_uvec2; + using glm::packed_uvec3; + using glm::packed_uvec4; +# endif//GLM_PRECISION +# if(defined(GLM_PRECISION_LOWP_BOOL)) + using glm::aligned_bvec1; + using glm::aligned_bvec2; + using glm::aligned_bvec3; + using glm::aligned_bvec4; +# elif(defined(GLM_PRECISION_MEDIUMP_BOOL)) + using glm::aligned_bvec1; + using glm::aligned_bvec2; + using glm::aligned_bvec3; + using glm::aligned_bvec4; +# else //defined(GLM_PRECISION_HIGHP_BOOL) + using glm::aligned_bvec1; + using glm::aligned_bvec2; + using glm::aligned_bvec3; + using glm::aligned_bvec4; + using glm::packed_bvec1; + using glm::packed_bvec2; + using glm::packed_bvec3; + using glm::packed_bvec4; +# endif//GLM_PRECISION +# endif + + + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::acot; + using glm::acoth; + using glm::acsc; + using glm::acsch; + using glm::affineInverse; + using glm::all; + using glm::angle; + using glm::angleAxis; + using glm::any; + using glm::asec; + using glm::asech; + using glm::asin; + using glm::asinh; + using glm::atan; + using glm::atanh; + using glm::axis; + using glm::ballRand; + using glm::bitCount; + using glm::bitfieldDeinterleave; + using glm::bitfieldExtract; + using glm::bitfieldFillOne; + using glm::bitfieldFillZero; + using glm::bitfieldInsert; + using glm::bitfieldInterleave; + using glm::bitfieldReverse; + using glm::bitfieldRotateLeft; + using glm::bitfieldRotateRight; + using glm::ceil; + using glm::ceilMultiple; + using glm::ceilPowerOfTwo; + using glm::circularRand; + using glm::clamp; + using glm::column; + using glm::conjugate; + using glm::convertLinearToSRGB; + using glm::convertSRGBToLinear; + using glm::cos; + using glm::cos_one_over_two; + using glm::cosh; + using glm::cot; + using glm::coth; + using glm::cross; + using glm::csc; + using glm::csch; + using glm::degrees; + using glm::determinant; + using glm::diskRand; + using glm::distance; + using glm::dot; + using glm::e; + using glm::epsilon; + using glm::epsilonEqual; + using glm::epsilonNotEqual; + using glm::equal; + using glm::euler; + using glm::eulerAngles; + using glm::exp; + using glm::exp2; + using glm::faceforward; + using glm::fclamp; + using glm::findLSB; + using glm::findMSB; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::float_distance; + using glm::floor; + using glm::floorMultiple; + using glm::floorPowerOfTwo; + using glm::fma; + using glm::fmax; + using glm::fmin; + using glm::four_over_pi; + using glm::fract; + using glm::frexp; + using glm::frustum; + using glm::frustumLH; + using glm::frustumLH_NO; + using glm::frustumLH_ZO; + using glm::frustumNO; + using glm::frustumRH; + using glm::frustumRH_NO; + using glm::frustumRH_ZO; + using glm::frustumZO; + using glm::gaussRand; + using glm::golden_ratio; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::half_pi; + using glm::identity; + using glm::imulExtended; + using glm::infinitePerspective; + using glm::infinitePerspectiveLH; + using glm::infinitePerspectiveRH; + using glm::intBitsToFloat; + using glm::inverse; + using glm::inverseTranspose; + using glm::inversesqrt; + using glm::iround; + using glm::isinf; + using glm::isnan; + using glm::ldexp; + using glm::length; + using glm::lerp; + using glm::lessThan; + using glm::lessThanEqual; + using glm::linearRand; + using glm::ln_ln_two; + using glm::ln_ten; + using glm::ln_two; + using glm::log; + using glm::log2; + using glm::lookAt; + using glm::lookAtLH; + using glm::lookAtRH; + using glm::make_mat2; + using glm::make_mat2x2; + using glm::make_mat2x3; + using glm::make_mat2x4; + using glm::make_mat3; + using glm::make_mat3x2; + using glm::make_mat3x3; + using glm::make_mat3x4; + using glm::make_mat4; + using glm::make_mat4x2; + using glm::make_mat4x3; + using glm::make_mat4x4; + using glm::make_quat; + using glm::make_vec1; + using glm::make_vec2; + using glm::make_vec3; + using glm::make_vec4; + using glm::mask; + using glm::mat3_cast; + using glm::mat4_cast; + using glm::matrixCompMult; + using glm::max; + using glm::min; + using glm::mirrorClamp; + using glm::mirrorRepeat; + using glm::mix; + using glm::mod; + using glm::modf; + using glm::next_float; + using glm::normalize; + using glm::notEqual; + using glm::not_; + using glm::one; + using glm::one_over_pi; + using glm::one_over_root_two; + using glm::one_over_two_pi; + using glm::ortho; + using glm::orthoLH; + using glm::orthoLH_NO; + using glm::orthoLH_ZO; + using glm::orthoNO; + using glm::orthoRH; + using glm::orthoRH_NO; + using glm::orthoRH_ZO; + using glm::orthoZO; + using glm::outerProduct; + using glm::packF2x11_1x10; + using glm::packF3x9_E1x5; + using glm::packHalf; + using glm::packHalf1x16; + using glm::packHalf4x16; + using glm::packI3x10_1x2; + using glm::packInt2x16; + using glm::packInt2x32; + using glm::packInt2x8; + using glm::packInt4x16; + using glm::packInt4x8; + using glm::packRGBM; + using glm::packSnorm; + using glm::packSnorm1x16; + using glm::packSnorm1x8; + using glm::packSnorm2x8; + using glm::packSnorm3x10_1x2; + using glm::packSnorm4x16; + using glm::packU3x10_1x2; + using glm::packUint2x16; + using glm::packUint2x32; + using glm::packUint2x8; + using glm::packUint4x16; + using glm::packUint4x8; + using glm::packUnorm; + using glm::packUnorm1x16; + using glm::packUnorm1x5_1x6_1x5; + using glm::packUnorm1x8; + using glm::packUnorm2x3_1x2; + using glm::packUnorm2x4; + using glm::packUnorm2x8; + using glm::packUnorm3x10_1x2; + using glm::packUnorm3x5_1x1; + using glm::packUnorm4x16; + using glm::packUnorm4x4; + using glm::perlin; + using glm::perspective; + using glm::perspectiveFov; + using glm::perspectiveFovLH; + using glm::perspectiveFovLH_NO; + using glm::perspectiveFovLH_ZO; + using glm::perspectiveFovNO; + using glm::perspectiveFovRH; + using glm::perspectiveFovRH_NO; + using glm::perspectiveFovRH_ZO; + using glm::perspectiveFovZO; + using glm::perspectiveLH; + using glm::perspectiveLH_NO; + using glm::perspectiveLH_ZO; + using glm::perspectiveNO; + using glm::perspectiveRH; + using glm::perspectiveRH_NO; + using glm::perspectiveRH_ZO; + using glm::perspectiveZO; + using glm::pi; + using glm::pickMatrix; + using glm::pitch; + using glm::pow; + using glm::prev_float; + using glm::project; + using glm::projectNO; + using glm::projectZO; + using glm::quarter_pi; + using glm::quatLookAt; + using glm::quatLookAtLH; + using glm::quatLookAtRH; + using glm::quat_cast; + using glm::radians; + using glm::reflect; + using glm::refract; + using glm::repeat; + using glm::roll; + using glm::root_five; + using glm::root_half_pi; + using glm::root_ln_four; + using glm::root_pi; + using glm::root_three; + using glm::root_two; + using glm::root_two_pi; + using glm::rotate; + using glm::round; + using glm::roundEven; + using glm::roundMultiple; + using glm::roundPowerOfTwo; + using glm::row; + using glm::scale; + using glm::sec; + using glm::sech; + using glm::sign; + using glm::simplex; + using glm::sin; + using glm::sinh; + using glm::slerp; + using glm::smoothstep; + using glm::sphericalRand; + using glm::sqrt; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::third; + using glm::three_over_two_pi; + using glm::translate; + using glm::transpose; + using glm::trunc; + using glm::tweakedInfinitePerspective; + using glm::two_over_pi; + using glm::two_over_root_pi; + using glm::two_pi; + using glm::two_thirds; + using glm::uaddCarry; + using glm::uintBitsToFloat; + using glm::umulExtended; + using glm::unProject; + using glm::unProjectNO; + using glm::unProjectZO; + using glm::unpackF2x11_1x10; + using glm::unpackF3x9_E1x5; + using glm::unpackHalf; + using glm::unpackHalf1x16; + using glm::unpackHalf4x16; + using glm::unpackI3x10_1x2; + using glm::unpackInt2x16; + using glm::unpackInt2x32; + using glm::unpackInt2x8; + using glm::unpackInt4x16; + using glm::unpackInt4x8; + using glm::unpackRGBM; + using glm::unpackSnorm; + using glm::unpackSnorm1x16; + using glm::unpackSnorm1x8; + using glm::unpackSnorm2x8; + using glm::unpackSnorm3x10_1x2; + using glm::unpackSnorm4x16; + using glm::unpackU3x10_1x2; + using glm::unpackUint2x16; + using glm::unpackUint2x32; + using glm::unpackUint2x8; + using glm::unpackUint4x16; + using glm::unpackUint4x8; + using glm::unpackUnorm; + using glm::unpackUnorm1x16; + using glm::unpackUnorm1x5_1x6_1x5; + using glm::unpackUnorm1x8; + using glm::unpackUnorm2x3_1x2; + using glm::unpackUnorm2x4; + using glm::unpackUnorm2x8; + using glm::unpackUnorm3x10_1x2; + using glm::unpackUnorm3x5_1x1; + using glm::unpackUnorm4x16; + using glm::unpackUnorm4x4; + using glm::uround; + using glm::usubBorrow; + using glm::value_ptr; + using glm::yaw; + using glm::zero; + } + +# ifdef GLM_EXT_INLINE_NAMESPACE + inline +# endif + namespace ext { + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::acot; + using glm::acoth; + using glm::acsc; + using glm::acsch; + using glm::all; + using glm::angle; + using glm::angleAxis; + using glm::any; + using glm::asec; + using glm::asech; + using glm::asin; + using glm::asinh; + using glm::atan; + using glm::atanh; + using glm::axis; + using glm::ceil; + using glm::clamp; + using glm::conjugate; + using glm::cos; + using glm::cos_one_over_two; + using glm::cosh; + using glm::cot; + using glm::coth; + using glm::cross; + using glm::csc; + using glm::csch; + using glm::degrees; + using glm::determinant; + using glm::distance; + using glm::dot; + using glm::e; + using glm::epsilon; + using glm::equal; + using glm::euler; + using glm::exp; + using glm::exp2; + using glm::faceforward; + using glm::fclamp; + using glm::findNSB; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::floatDistance; + using glm::floor; + using glm::fma; + using glm::fmax; + using glm::fmin; + using glm::four_over_pi; + using glm::fract; + using glm::frexp; + using glm::frustum; + using glm::frustumLH; + using glm::frustumLH_NO; + using glm::frustumLH_ZO; + using glm::frustumNO; + using glm::frustumRH; + using glm::frustumRH_NO; + using glm::frustumRH_ZO; + using glm::frustumZO; + using glm::golden_ratio; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::half_pi; + using glm::identity; + using glm::infinitePerspective; + using glm::infinitePerspectiveLH; + using glm::infinitePerspectiveRH; + using glm::intBitsToFloat; + using glm::inverse; + using glm::inversesqrt; + using glm::iround; + using glm::isMultiple; + using glm::isPowerOfTwo; + using glm::isinf; + using glm::isnan; + using glm::ldexp; + using glm::length; + using glm::lerp; + using glm::lessThan; + using glm::lessThanEqual; + using glm::ln_ln_two; + using glm::ln_ten; + using glm::ln_two; + using glm::log; + using glm::log2; + using glm::lookAt; + using glm::lookAtLH; + using glm::lookAtRH; + using glm::matrixCompMult; + using glm::max; + using glm::min; + using glm::mirrorClamp; + using glm::mirrorRepeat; + using glm::mix; + using glm::mod; + using glm::modf; + using glm::nextFloat; + using glm::nextMultiple; + using glm::nextPowerOfTwo; + using glm::normalize; + using glm::notEqual; + using glm::not_; + using glm::one; + using glm::one_over_pi; + using glm::one_over_root_two; + using glm::one_over_two_pi; + using glm::ortho; + using glm::orthoLH; + using glm::orthoLH_NO; + using glm::orthoLH_ZO; + using glm::orthoNO; + using glm::orthoRH; + using glm::orthoRH_NO; + using glm::orthoRH_ZO; + using glm::orthoZO; + using glm::outerProduct; + using glm::perspective; + using glm::perspectiveFov; + using glm::perspectiveFovLH; + using glm::perspectiveFovLH_NO; + using glm::perspectiveFovLH_ZO; + using glm::perspectiveFovNO; + using glm::perspectiveFovRH; + using glm::perspectiveFovRH_NO; + using glm::perspectiveFovRH_ZO; + using glm::perspectiveFovZO; + using glm::perspectiveLH; + using glm::perspectiveLH_NO; + using glm::perspectiveLH_ZO; + using glm::perspectiveNO; + using glm::perspectiveRH; + using glm::perspectiveRH_NO; + using glm::perspectiveRH_ZO; + using glm::perspectiveZO; + using glm::pi; + using glm::pickMatrix; + using glm::pow; + using glm::prevFloat; + using glm::prevMultiple; + using glm::prevPowerOfTwo; + using glm::project; + using glm::projectNO; + using glm::projectZO; + using glm::quarter_pi; + using glm::radians; + using glm::reflect; + using glm::refract; + using glm::repeat; + using glm::root_five; + using glm::root_half_pi; + using glm::root_ln_four; + using glm::root_pi; + using glm::root_three; + using glm::root_two; + using glm::root_two_pi; + using glm::rotate; + using glm::round; + using glm::roundEven; + using glm::scale; + using glm::sec; + using glm::sech; + using glm::sign; + using glm::sin; + using glm::sinh; + using glm::slerp; + using glm::smoothstep; + using glm::sqrt; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::third; + using glm::three_over_two_pi; + using glm::translate; + using glm::transpose; + using glm::trunc; + using glm::tweakedInfinitePerspective; + using glm::two_over_pi; + using glm::two_over_root_pi; + using glm::two_pi; + using glm::two_thirds; + using glm::uintBitsToFloat; + using glm::unProject; + using glm::unProjectNO; + using glm::unProjectZO; + using glm::uround; + using glm::zero; + } + +# ifdef GLM_ENABLE_EXPERIMENTAL +# ifdef GLM_GTX_INLINE_NAMESPACE + inline +# endif + namespace gtx { + using glm::io::order_type; + using glm::io::format_punct; + using glm::io::basic_state_saver; + using glm::io::basic_format_saver; + using glm::io::precision; + using glm::io::width; + using glm::io::delimeter; + using glm::io::order; + using glm::io::get_facet; + using glm::io::formatted; + using glm::io::unformatted; + using glm::io::operator<<; + using glm::operator<<; + using glm::tdualquat; + +# if !((GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP)) + using glm::to_string; +# endif +# if GLM_HAS_TEMPLATE_ALIASES + using glm::operator*; + using glm::operator/; +# endif +# if GLM_HAS_RANGE_FOR + using glm::components; + using glm::begin; + using glm::end; +# endif + + using glm::abs; + using glm::acos; + using glm::acosh; + using glm::adjugate; + using glm::all; + using glm::angle; + using glm::angleAxis; + using glm::any; + using glm::areCollinear; + using glm::areOrthogonal; + using glm::areOrthonormal; + using glm::asin; + using glm::asinh; + using glm::associatedMax; + using glm::associatedMin; + using glm::atan; + using glm::atanh; + using glm::axis; + using glm::axisAngle; + using glm::axisAngleMatrix; + using glm::backEaseIn; + using glm::backEaseInOut; + using glm::backEaseOut; + using glm::bitCount; + using glm::bitfieldDeinterleave; + using glm::bitfieldExtract; + using glm::bitfieldFillOne; + using glm::bitfieldFillZero; + using glm::bitfieldInsert; + using glm::bitfieldInterleave; + using glm::bitfieldReverse; + using glm::bitfieldRotateLeft; + using glm::bitfieldRotateRight; + using glm::bounceEaseIn; + using glm::bounceEaseInOut; + using glm::bounceEaseOut; + using glm::catmullRom; + using glm::ceil; + using glm::circularEaseIn; + using glm::circularEaseInOut; + using glm::circularEaseOut; + using glm::clamp; + using glm::closeBounded; + using glm::closestPointOnLine; + using glm::colMajor2; + using glm::colMajor3; + using glm::colMajor4; + using glm::compAdd; + using glm::compMax; + using glm::compMin; + using glm::compMul; + using glm::compNormalize; + using glm::compScale; + using glm::computeCovarianceMatrix; + using glm::conjugate; + using glm::convertD65XYZToD50XYZ; + using glm::convertD65XYZToLinearSRGB; + using glm::convertLinearSRGBToD50XYZ; + using glm::convertLinearSRGBToD65XYZ; + using glm::cos; + using glm::cos_one_over_two; + using glm::cosh; + using glm::cross; + using glm::cubic; + using glm::cubicEaseIn; + using glm::cubicEaseInOut; + using glm::cubicEaseOut; + using glm::decompose; + using glm::degrees; + using glm::derivedEulerAngleX; + using glm::derivedEulerAngleY; + using glm::derivedEulerAngleZ; + using glm::determinant; + using glm::diagonal2x2; + using glm::diagonal2x3; + using glm::diagonal2x4; + using glm::diagonal3x2; + using glm::diagonal3x3; + using glm::diagonal3x4; + using glm::diagonal4x2; + using glm::diagonal4x3; + using glm::diagonal4x4; + using glm::distance; + using glm::distance2; + using glm::dot; + using glm::dual_quat_identity; + using glm::dualquat_cast; + using glm::e; + using glm::elasticEaseIn; + using glm::elasticEaseInOut; + using glm::elasticEaseOut; + using glm::epsilon; + using glm::epsilonEqual; + using glm::epsilonNotEqual; + using glm::equal; + using glm::euclidean; + using glm::euler; + using glm::eulerAngleX; + using glm::eulerAngleXY; + using glm::eulerAngleXYX; + using glm::eulerAngleXYZ; + using glm::eulerAngleXZ; + using glm::eulerAngleXZX; + using glm::eulerAngleXZY; + using glm::eulerAngleY; + using glm::eulerAngleYX; + using glm::eulerAngleYXY; + using glm::eulerAngleYXZ; + using glm::eulerAngleYZ; + using glm::eulerAngleYZX; + using glm::eulerAngleYZY; + using glm::eulerAngleZ; + using glm::eulerAngleZX; + using glm::eulerAngleZXY; + using glm::eulerAngleZXZ; + using glm::eulerAngleZY; + using glm::eulerAngleZYX; + using glm::eulerAngleZYZ; + using glm::eulerAngles; + using glm::exp; + using glm::exp2; + using glm::exponentialEaseIn; + using glm::exponentialEaseInOut; + using glm::exponentialEaseOut; + using glm::extend; + using glm::extractEulerAngleXYX; + using glm::extractEulerAngleXYZ; + using glm::extractEulerAngleXZX; + using glm::extractEulerAngleXZY; + using glm::extractEulerAngleYXY; + using glm::extractEulerAngleYXZ; + using glm::extractEulerAngleYZX; + using glm::extractEulerAngleYZY; + using glm::extractEulerAngleZXY; + using glm::extractEulerAngleZXZ; + using glm::extractEulerAngleZYX; + using glm::extractEulerAngleZYZ; + using glm::extractMatrixRotation; + using glm::extractRealComponent; + using glm::faceforward; + using glm::factorial; + using glm::fastAcos; + using glm::fastAsin; + using glm::fastAtan; + using glm::fastCos; + using glm::fastDistance; + using glm::fastExp; + using glm::fastExp2; + using glm::fastInverseSqrt; + using glm::fastLength; + using glm::fastLog; + using glm::fastLog2; + using glm::fastMix; + using glm::fastNormalize; + using glm::fastNormalizeDot; + using glm::fastPow; + using glm::fastSin; + using glm::fastSqrt; + using glm::fastTan; + using glm::fclamp; + using glm::findLSB; + using glm::findMSB; + using glm::fliplr; + using glm::flipud; + using glm::floatBitsToInt; + using glm::floatBitsToUint; + using glm::floor; + using glm::floor_log2; + using glm::fma; + using glm::fmax; + using glm::fmin; + using glm::fmod; + using glm::four_over_pi; + using glm::fract; + using glm::frexp; + using glm::frustum; + using glm::frustumLH; + using glm::frustumLH_NO; + using glm::frustumLH_ZO; + using glm::frustumNO; + using glm::frustumRH; + using glm::frustumRH_NO; + using glm::frustumRH_ZO; + using glm::frustumZO; + using glm::gauss; + using glm::golden_ratio; + using glm::greaterThan; + using glm::greaterThanEqual; + using glm::half_pi; + using glm::hermite; + using glm::highestBitValue; + using glm::hsvColor; + using glm::identity; + using glm::imulExtended; + using glm::infinitePerspective; + using glm::infinitePerspectiveLH; + using glm::infinitePerspectiveRH; + using glm::intBitsToFloat; + using glm::intermediate; + using glm::interpolate; + using glm::intersectLineSphere; + using glm::intersectLineTriangle; + using glm::intersectRayPlane; + using glm::intersectRaySphere; + using glm::intersectRayTriangle; + using glm::inverse; + using glm::inversesqrt; + using glm::iround; + using glm::isCompNull; + using glm::isIdentity; + using glm::isNormalized; + using glm::isNull; + using glm::isOrthogonal; + using glm::isdenormal; + using glm::isfinite; + using glm::isinf; + using glm::isnan; + using glm::l1Norm; + using glm::l2Norm; + using glm::lMaxNorm; + using glm::ldexp; + using glm::leftHanded; + using glm::length; + using glm::length2; + using glm::lerp; + using glm::lessThan; + using glm::lessThanEqual; + using glm::linearGradient; + using glm::linearInterpolation; + using glm::ln_ln_two; + using glm::ln_ten; + using glm::ln_two; + using glm::log; + using glm::log2; + using glm::lookAt; + using glm::lookAtLH; + using glm::lookAtRH; + using glm::lowestBitValue; + using glm::luminosity; + using glm::lxNorm; + using glm::make_mat2; + using glm::make_mat2x2; + using glm::make_mat2x3; + using glm::make_mat2x4; + using glm::make_mat3; + using glm::make_mat3x2; + using glm::make_mat3x3; + using glm::make_mat3x4; + using glm::make_mat4; + using glm::make_mat4x2; + using glm::make_mat4x3; + using glm::make_mat4x4; + using glm::make_quat; + using glm::make_vec1; + using glm::make_vec2; + using glm::make_vec3; + using glm::make_vec4; + using glm::mask; + using glm::mat2x4_cast; + using glm::mat3_cast; + using glm::mat3x4_cast; + using glm::mat4_cast; + using glm::matrixCompMult; + using glm::matrixCross3; + using glm::matrixCross4; + using glm::max; + using glm::min; + using glm::mirrorClamp; + using glm::mirrorRepeat; + using glm::mix; + using glm::mixedProduct; + using glm::mod; + using glm::modf; + using glm::nlz; + using glm::normalize; + using glm::normalizeDot; + using glm::notEqual; + using glm::not_; + using glm::YCoCg2rgb; + using glm::YCoCgR2rgb; + using glm::one; + using glm::one_over_pi; + using glm::one_over_root_two; + using glm::one_over_two_pi; + using glm::openBounded; + using glm::orientate2; + using glm::orientate3; + using glm::orientate4; + using glm::orientation; + using glm::orientedAngle; + using glm::ortho; + using glm::orthoLH; + using glm::orthoLH_NO; + using glm::orthoLH_ZO; + using glm::orthoNO; + using glm::orthoRH; + using glm::orthoRH_NO; + using glm::orthoRH_ZO; + using glm::orthoZO; + using glm::orthonormalize; + using glm::outerProduct; + using glm::packDouble2x32; + using glm::packHalf2x16; + using glm::packSnorm2x16; + using glm::packSnorm4x8; + using glm::packUnorm2x16; + using glm::packUnorm4x8; + using glm::perp; + using glm::perspective; + using glm::perspectiveFov; + using glm::perspectiveFovLH; + using glm::perspectiveFovLH_NO; + using glm::perspectiveFovLH_ZO; + using glm::perspectiveFovNO; + using glm::perspectiveFovRH; + using glm::perspectiveFovRH_NO; + using glm::perspectiveFovRH_ZO; + using glm::perspectiveFovZO; + using glm::perspectiveLH; + using glm::perspectiveLH_NO; + using glm::perspectiveLH_ZO; + using glm::perspectiveNO; + using glm::perspectiveRH; + using glm::perspectiveRH_NO; + using glm::perspectiveRH_ZO; + using glm::perspectiveZO; + using glm::pi; + using glm::pickMatrix; + using glm::pitch; + using glm::polar; + using glm::pow; + using glm::pow2; + using glm::pow3; + using glm::pow4; + using glm::powerOfTwoAbove; + using glm::powerOfTwoBelow; + using glm::powerOfTwoNearest; + using glm::proj; + using glm::proj2D; + using glm::proj3D; + using glm::project; + using glm::projectNO; + using glm::projectZO; + using glm::qr_decompose; + using glm::quadraticEaseIn; + using glm::quadraticEaseInOut; + using glm::quadraticEaseOut; + using glm::quarter_pi; + using glm::quarticEaseIn; + using glm::quarticEaseInOut; + using glm::quarticEaseOut; + using glm::quatLookAt; + using glm::quatLookAtLH; + using glm::quatLookAtRH; + using glm::quat_cast; + using glm::quat_identity; + using glm::quinticEaseIn; + using glm::quinticEaseInOut; + using glm::quinticEaseOut; + using glm::radialGradient; + using glm::radians; + using glm::recompose; + using glm::reflect; + using glm::refract; + using glm::repeat; + using glm::rgb2YCoCg; + using glm::rgb2YCoCgR; + using glm::rgbColor; + using glm::rightHanded; + using glm::roll; + using glm::root_five; + using glm::root_half_pi; + using glm::root_ln_four; + using glm::root_pi; + using glm::root_three; + using glm::root_two; + using glm::root_two_pi; + using glm::rotate; + using glm::rotateNormalizedAxis; + using glm::rotateX; + using glm::rotateY; + using glm::rotateZ; + using glm::rotation; + using glm::round; + using glm::roundEven; + using glm::rowMajor2; + using glm::rowMajor3; + using glm::rowMajor4; + using glm::rq_decompose; + using glm::saturation; + using glm::scale; + using glm::scaleBias; + using glm::shearX2D; + using glm::shearX3D; + using glm::shearY2D; + using glm::shearY3D; + using glm::shearZ3D; + using glm::shortMix; + using glm::sign; + using glm::sin; + using glm::sineEaseIn; + using glm::sineEaseInOut; + using glm::sineEaseOut; + using glm::sinh; + using glm::slerp; + using glm::smoothstep; + using glm::sortEigenvalues; + using glm::sqrt; + using glm::squad; + using glm::step; + using glm::tan; + using glm::tanh; + using glm::third; + using glm::three_over_two_pi; + using glm::translate; + using glm::transpose; + using glm::triangleNormal; + using glm::trunc; + using glm::tweakedInfinitePerspective; + using glm::two_over_pi; + using glm::two_over_root_pi; + using glm::two_pi; + using glm::two_thirds; + using glm::uaddCarry; + using glm::uintBitsToFloat; + using glm::umulExtended; + using glm::unProject; + using glm::unProjectNO; + using glm::unProjectZO; + using glm::unpackDouble2x32; + using glm::unpackHalf2x16; + using glm::unpackSnorm2x16; + using glm::unpackSnorm4x8; + using glm::unpackUnorm2x16; + using glm::unpackUnorm4x8; + using glm::uround; + using glm::usubBorrow; + using glm::value_ptr; + using glm::wrapAngle; + using glm::wxyz; + using glm::yaw; + using glm::yawPitchRoll; + using glm::zero; + } +# endif +} + +#if defined(_MSC_VER) // Workaround +// Partial template specialization doesn't need to be exported explicitly, but this may not work otherwise on MSVC. +export namespace std { + using std::hash; // See GLM_GTX_hash +} +#endif diff --git a/glm/glm.hpp b/glm/glm.hpp new file mode 100644 index 0000000..8b37545 --- /dev/null +++ b/glm/glm.hpp @@ -0,0 +1,137 @@ +/// @ref core +/// @file glm/glm.hpp +/// +/// @mainpage OpenGL Mathematics (GLM) +/// - Website: glm.g-truc.net +/// - GLM API documentation +/// - GLM Manual +/// +/// @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. +/// + +#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/glm/gtc/bitfield.hpp b/glm/gtc/bitfield.hpp new file mode 100644 index 0000000..084fbe7 --- /dev/null +++ b/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/glm/gtc/bitfield.inl b/glm/gtc/bitfield.inl new file mode 100644 index 0000000..e7a0b4f --- /dev/null +++ b/glm/gtc/bitfield.inl @@ -0,0 +1,635 @@ +/// @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 + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wsign-compare" +#endif + + 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); + } + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + + 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/glm/gtc/color_space.hpp b/glm/gtc/color_space.hpp new file mode 100644 index 0000000..cffd9f0 --- /dev/null +++ b/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/glm/gtc/color_space.inl b/glm/gtc/color_space.inl new file mode 100644 index 0000000..2a90004 --- /dev/null +++ b/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/glm/gtc/constants.hpp b/glm/gtc/constants.hpp new file mode 100644 index 0000000..6a1f37d --- /dev/null +++ b/glm/gtc/constants.hpp @@ -0,0 +1,170 @@ +/// @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 unit-circle circumference, or pi * 2. + /// @see gtc_constants + template + GLM_FUNC_DECL GLM_CONSTEXPR genType tau(); + + /// 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/glm/gtc/constants.inl b/glm/gtc/constants.inl new file mode 100644 index 0000000..e9d3776 --- /dev/null +++ b/glm/gtc/constants.inl @@ -0,0 +1,173 @@ +/// @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 tau() + { + return two_pi(); + } + + 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/glm/gtc/epsilon.hpp b/glm/gtc/epsilon.hpp new file mode 100644 index 0000000..640439b --- /dev/null +++ b/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/glm/gtc/epsilon.inl b/glm/gtc/epsilon.inl new file mode 100644 index 0000000..508b9f8 --- /dev/null +++ b/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/glm/gtc/integer.hpp b/glm/gtc/integer.hpp new file mode 100644 index 0000000..cff08dc --- /dev/null +++ b/glm/gtc/integer.hpp @@ -0,0 +1,43 @@ +/// @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 "../ext/scalar_common.hpp" +#include "../ext/vector_common.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. Useful to compute mipmap count from the texture size. + /// @see gtc_integer + template + GLM_FUNC_DECL vec log2(vec const& v); + + /// @} +} //namespace glm + +#include "integer.inl" diff --git a/glm/gtc/integer.inl b/glm/gtc/integer.inl new file mode 100644 index 0000000..5f66dfe --- /dev/null +++ b/glm/gtc/integer.inl @@ -0,0 +1,33 @@ +/// @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 +}//namespace glm diff --git a/glm/gtc/matrix_access.hpp b/glm/gtc/matrix_access.hpp new file mode 100644 index 0000000..4935ba7 --- /dev/null +++ b/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/glm/gtc/matrix_access.inl b/glm/gtc/matrix_access.inl new file mode 100644 index 0000000..09fcc10 --- /dev/null +++ b/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/glm/gtc/matrix_integer.hpp b/glm/gtc/matrix_integer.hpp new file mode 100644 index 0000000..d7ebdc7 --- /dev/null +++ b/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/glm/gtc/matrix_inverse.hpp b/glm/gtc/matrix_inverse.hpp new file mode 100644 index 0000000..75d53f2 --- /dev/null +++ b/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 inaccurate. + /// @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 inaccurate. + /// @see gtc_matrix_inverse + template + GLM_FUNC_DECL genType inverseTranspose(genType const& m); + + /// @} +}//namespace glm + +#include "matrix_inverse.inl" diff --git a/glm/gtc/matrix_inverse.inl b/glm/gtc/matrix_inverse.inl new file mode 100644 index 0000000..c004b9e --- /dev/null +++ b/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/glm/gtc/matrix_transform.hpp b/glm/gtc/matrix_transform.hpp new file mode 100644 index 0000000..612418f --- /dev/null +++ b/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/glm/gtc/matrix_transform.inl b/glm/gtc/matrix_transform.inl new file mode 100644 index 0000000..15b46bc --- /dev/null +++ b/glm/gtc/matrix_transform.inl @@ -0,0 +1,3 @@ +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" diff --git a/glm/gtc/noise.hpp b/glm/gtc/noise.hpp new file mode 100644 index 0000000..ab1772e --- /dev/null +++ b/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/glm/gtc/noise.inl b/glm/gtc/noise.inl new file mode 100644 index 0000000..a1cf399 --- /dev/null +++ b/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 detail +{ + 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 detail + + // 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 = detail::grad4(j0, ip); + vec<4, T, Q> p1 = detail::grad4(j1.x, ip); + vec<4, T, Q> p2 = detail::grad4(j1.y, ip); + vec<4, T, Q> p3 = detail::grad4(j1.z, ip); + vec<4, T, Q> p4 = detail::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/glm/gtc/packing.hpp b/glm/gtc/packing.hpp new file mode 100644 index 0000000..8e416b3 --- /dev/null +++ b/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/glm/gtc/packing.inl b/glm/gtc/packing.inl new file mode 100644 index 0000000..1792760 --- /dev/null +++ b/glm/gtc/packing.inl @@ -0,0 +1,951 @@ +/// @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); +// } + +#if GLM_SILENT_WARNINGS == GLM_ENABLE +# if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# endif +#endif + + union u3u3u2 + { + struct Data + { + uint x : 3; + uint y : 3; + uint z : 2; + } data; + uint8 pack; + }; + + union u4u4 + { + struct Data + { + uint x : 4; + uint y : 4; + } data; + uint8 pack; + }; + + union u4u4u4u4 + { + struct Data + { + uint x : 4; + uint y : 4; + uint z : 4; + uint w : 4; + } data; + uint16 pack; + }; + + union u5u6u5 + { + struct Data + { + uint x : 5; + uint y : 6; + uint z : 5; + } data; + uint16 pack; + }; + + union u5u5u5u1 + { + struct Data + { + uint x : 5; + uint y : 5; + uint z : 5; + uint w : 1; + } data; + uint16 pack; + }; + +#if GLM_SILENT_WARNINGS == GLM_ENABLE +# if defined(__clang__) +# pragma clang diagnostic pop +# endif +#endif + + union u10u10u10u2 + { + struct Data + { + uint x : 10; + uint y : 10; + uint z : 10; + uint w : 2; + } data; + uint32 pack; + }; + + union i10i10i10i2 + { + struct Data + { + int x : 10; + int y : 10; + int z : 10; + int w : 2; + } data; + uint32 pack; + }; + + union u9u9u9e5 + { + struct Data + { + 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(Unpack.x), detail::toFloat32(Unpack.y), detail::toFloat32(Unpack.z), detail::toFloat32(Unpack.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, static_cast(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/glm/gtc/quaternion.hpp b/glm/gtc/quaternion.hpp new file mode 100644 index 0000000..314449e --- /dev/null +++ b/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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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/glm/gtc/quaternion.inl b/glm/gtc/quaternion.inl new file mode 100644 index 0000000..ea159f2 --- /dev/null +++ b/glm/gtc/quaternion.inl @@ -0,0 +1,208 @@ +#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) + { + T const y = static_cast(2) * (q.x * q.y + q.w * q.z); + 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(0); + + return static_cast(atan(y, x)); + } + + 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::wxyz(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::wxyz((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::wxyz((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::wxyz((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::wxyz(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 GLM_CONSTEXPR vec<4, bool, Q> lessThan(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] < y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> lessThanEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> greaterThan(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + for(length_t i = 0; i < x.length(); ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, bool, Q> greaterThanEqual(qua const& x, qua const& y) + { + vec<4, bool, Q> Result(false, false, false, false); + 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/glm/gtc/quaternion_simd.inl b/glm/gtc/quaternion_simd.inl new file mode 100644 index 0000000..e69de29 diff --git a/glm/gtc/random.hpp b/glm/gtc/random.hpp new file mode 100644 index 0000000..c6485bf --- /dev/null +++ b/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 regularly 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 regularly 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 regularly 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 regularly 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/glm/gtc/random.inl b/glm/gtc/random.inl new file mode 100644 index 0000000..249ec9f --- /dev/null +++ b/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>( + static_cast(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/glm/gtc/reciprocal.hpp b/glm/gtc/reciprocal.hpp new file mode 100644 index 0000000..4d0fc91 --- /dev/null +++ b/glm/gtc/reciprocal.hpp @@ -0,0 +1,24 @@ +/// @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 + +#include "../ext/scalar_reciprocal.hpp" +#include "../ext/vector_reciprocal.hpp" + diff --git a/glm/gtc/round.hpp b/glm/gtc/round.hpp new file mode 100644 index 0000000..56edbbc --- /dev/null +++ b/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/glm/gtc/round.inl b/glm/gtc/round.inl new file mode 100644 index 0000000..48411e4 --- /dev/null +++ b/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/glm/gtc/type_aligned.hpp b/glm/gtc/type_aligned.hpp new file mode 100644 index 0000000..5403abf --- /dev/null +++ b/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/glm/gtc/type_precision.hpp b/glm/gtc/type_precision.hpp new file mode 100644 index 0000000..775e2f4 --- /dev/null +++ b/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/glm/gtc/type_precision.inl b/glm/gtc/type_precision.inl new file mode 100644 index 0000000..ae80912 --- /dev/null +++ b/glm/gtc/type_precision.inl @@ -0,0 +1,6 @@ +/// @ref gtc_precision + +namespace glm +{ + +} diff --git a/glm/gtc/type_ptr.hpp b/glm/gtc/type_ptr.hpp new file mode 100644 index 0000000..d7e625a --- /dev/null +++ b/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/glm/gtc/type_ptr.inl b/glm/gtc/type_ptr.inl new file mode 100644 index 0000000..26b20b5 --- /dev/null +++ b/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 + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<1, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<2, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<3, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<1, T, Q> make_vec1(vec<4, T, Q> const& v) + { + return vec<1, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<1, T, Q> const& v) + { + return vec<2, T, Q>(v.x, static_cast(0)); + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<2, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<3, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template + GLM_FUNC_DECL vec<2, T, Q> make_vec2(vec<4, T, Q> const& v) + { + return vec<2, T, Q>(v); + } + + template + GLM_FUNC_DECL 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 + GLM_FUNC_DECL 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 + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<3, T, Q> const& v) + { + return v; + } + + template + GLM_FUNC_DECL vec<3, T, Q> make_vec3(vec<4, T, Q> const& v) + { + return vec<3, T, Q>(v); + } + + template + GLM_FUNC_DECL 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 + GLM_FUNC_DECL 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 + GLM_FUNC_DECL 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 + GLM_FUNC_DECL 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/glm/gtc/ulp.hpp b/glm/gtc/ulp.hpp new file mode 100644 index 0000000..7b918f0 --- /dev/null +++ b/glm/gtc/ulp.hpp @@ -0,0 +1,155 @@ +/// @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 +{ + /// @addtogroup gtc_ulp + /// @{ + + /// 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/glm/gtc/ulp.inl b/glm/gtc/ulp.inl new file mode 100644 index 0000000..836c84b --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/gtc/vec1.hpp b/glm/gtc/vec1.hpp new file mode 100644 index 0000000..63697a2 --- /dev/null +++ b/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/glm/gtx/associated_min_max.hpp b/glm/gtx/associated_min_max.hpp new file mode 100644 index 0000000..435230d --- /dev/null +++ b/glm/gtx/associated_min_max.hpp @@ -0,0 +1,205 @@ +/// @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 ones. + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_associated_min_max extension included") +#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 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 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/glm/gtx/associated_min_max.inl b/glm/gtx/associated_min_max.inl new file mode 100644 index 0000000..f09f5bb --- /dev/null +++ b/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 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 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/glm/gtx/bit.hpp b/glm/gtx/bit.hpp new file mode 100644 index 0000000..2f6b3f6 --- /dev/null +++ b/glm/gtx/bit.hpp @@ -0,0 +1,96 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_bit extension included") +#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/glm/gtx/bit.inl b/glm/gtx/bit.inl new file mode 100644 index 0000000..621b626 --- /dev/null +++ b/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/glm/gtx/closest_point.hpp b/glm/gtx/closest_point.hpp new file mode 100644 index 0000000..a248e4b --- /dev/null +++ b/glm/gtx/closest_point.hpp @@ -0,0 +1,47 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_closest_point extension included") +#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/glm/gtx/closest_point.inl b/glm/gtx/closest_point.inl new file mode 100644 index 0000000..0a39b04 --- /dev/null +++ b/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/glm/gtx/color_encoding.hpp b/glm/gtx/color_encoding.hpp new file mode 100644 index 0000000..4769e0a --- /dev/null +++ b/glm/gtx/color_encoding.hpp @@ -0,0 +1,52 @@ +/// @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 + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTC_color_encoding extension included") +#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/glm/gtx/color_encoding.inl b/glm/gtx/color_encoding.inl new file mode 100644 index 0000000..e50fa3e --- /dev/null +++ b/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/glm/gtx/color_space.hpp b/glm/gtx/color_space.hpp new file mode 100644 index 0000000..c39a1f4 --- /dev/null +++ b/glm/gtx/color_space.hpp @@ -0,0 +1,70 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_color_space extension included") +#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/glm/gtx/color_space.inl b/glm/gtx/color_space.inl new file mode 100644 index 0000000..b3183b9 --- /dev/null +++ b/glm/gtx/color_space.inl @@ -0,0 +1,144 @@ +/// @ref gtx_color_space + +#include +#include + +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(equal(hsv.y, static_cast(0), epsilon())) + // 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; + T Min = min(min(rgbColor.r, rgbColor.g), rgbColor.b); + T Max = max(max(rgbColor.r, rgbColor.g), rgbColor.b); + T Delta = Max - Min; + + hsv.z = Max; + + if(!equal(Max, static_cast(0), epsilon())) + { + hsv.y = Delta / hsv.z; + T h = static_cast(0); + + if(equal(rgbColor.r, Max, epsilon())) + // between yellow & magenta + h = static_cast(0) + T(60) * (rgbColor.g - rgbColor.b) / Delta; + else if(equal(rgbColor.g, Max, epsilon())) + // 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/glm/gtx/color_space_YCoCg.hpp b/glm/gtx/color_space_YCoCg.hpp new file mode 100644 index 0000000..a418037 --- /dev/null +++ b/glm/gtx/color_space_YCoCg.hpp @@ -0,0 +1,58 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_color_space_YCoCg extension included") +#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/glm/gtx/color_space_YCoCg.inl b/glm/gtx/color_space_YCoCg.inl new file mode 100644 index 0000000..83ba857 --- /dev/null +++ b/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/glm/gtx/common.hpp b/glm/gtx/common.hpp new file mode 100644 index 0000000..283f947 --- /dev/null +++ b/glm/gtx/common.hpp @@ -0,0 +1,74 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_common extension included") +#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/glm/gtx/common.inl b/glm/gtx/common.inl new file mode 100644 index 0000000..4575b20 --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/gtx/compatibility.hpp b/glm/gtx/compatibility.hpp new file mode 100644 index 0000000..463f86f --- /dev/null +++ b/glm/gtx/compatibility.hpp @@ -0,0 +1,131 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_compatibility extension included") +#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 y, T x){return atan(y, x);} //!< \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>& y, const vec<2, T, Q>& x){return atan(y, x);} //!< \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>& y, const vec<3, T, Q>& x){return atan(y, x);} //!< \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>& y, const vec<4, T, Q>& x){return atan(y, x);} //!< \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/glm/gtx/compatibility.inl b/glm/gtx/compatibility.inl new file mode 100644 index 0000000..1d49496 --- /dev/null +++ b/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/glm/gtx/component_wise.hpp b/glm/gtx/component_wise.hpp new file mode 100644 index 0000000..b1caaa2 --- /dev/null +++ b/glm/gtx/component_wise.hpp @@ -0,0 +1,77 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_component_wise extension included") +#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); + + /// Find the minimum float between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type fcompMin(genType const& v); + + /// Find the maximum float between single vector components. + /// @see gtx_component_wise + template + GLM_FUNC_DECL typename genType::value_type fcompMax(genType const& v); + + /// @} +}//namespace glm + +#include "component_wise.inl" diff --git a/glm/gtx/component_wise.inl b/glm/gtx/component_wise.inl new file mode 100644 index 0000000..f8217b2 --- /dev/null +++ b/glm/gtx/component_wise.inl @@ -0,0 +1,147 @@ +/// @ref gtx_component_wise + +#include "../ext/scalar_common.hpp" +#include +#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; + } + + template + GLM_FUNC_QUALIFIER T fcompMin(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = fmin(Result, v[i]); + return Result; + } + + template + GLM_FUNC_QUALIFIER T fcompMax(vec const& v) + { + T Result(v[0]); + for(length_t i = 1, n = v.length(); i < n; ++i) + Result = fmax(Result, v[i]); + return Result; + } +}//namespace glm diff --git a/glm/gtx/dual_quaternion.hpp b/glm/gtx/dual_quaternion.hpp new file mode 100644 index 0000000..04a6070 --- /dev/null +++ b/glm/gtx/dual_quaternion.hpp @@ -0,0 +1,272 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_dual_quaternion extension included") +#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_DEFAULTED_FUNC_DECL GLM_CONSTEXPR tdualquat() GLM_DEFAULT; + GLM_DEFAULTED_FUNC_DECL GLM_CONSTEXPR tdualquat(tdualquat const& d) GLM_DEFAULT; + template + GLM_CTOR_DECL tdualquat(tdualquat const& d); + + // -- Explicit basic constructors -- + + GLM_CTOR_DECL tdualquat(qua const& real); + GLM_CTOR_DECL tdualquat(qua const& orientation, vec<3, T, Q> const& translation); + GLM_CTOR_DECL tdualquat(qua const& real, qua const& dual); + + // -- Conversion constructors -- + + template + GLM_CTOR_DECL GLM_EXPLICIT tdualquat(tdualquat const& q); + + GLM_CTOR_DECL GLM_EXPLICIT tdualquat(mat<2, 4, T, Q> const& holder_mat); + GLM_CTOR_DECL GLM_EXPLICIT tdualquat(mat<3, 4, T, Q> const& aug_mat); + + // -- Unary arithmetic operators -- + + GLM_DEFAULTED_FUNC_DECL tdualquat & operator=(tdualquat const& m) GLM_DEFAULT; + + template + GLM_FUNC_DISCARD_DECL tdualquat & operator=(tdualquat const& m); + template + GLM_FUNC_DISCARD_DECL tdualquat & operator*=(U s); + template + GLM_FUNC_DISCARD_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/glm/gtx/dual_quaternion.inl b/glm/gtx/dual_quaternion.inl new file mode 100644 index 0000000..3a04160 --- /dev/null +++ b/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_DEFAULTED_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat() +# if GLM_CONFIG_DEFAULTED_FUNCTIONS != GLM_DISABLE + : real(qua()) + , dual(qua::wxyz(0, 0, 0, 0)) +# endif + {} + + template + GLM_DEFAULTED_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::wxyz(0, 0, 0, 0)) + {} + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR tdualquat::tdualquat(qua const& q, vec<3, T, Q> const& p) + : real(q), dual(qua::wxyz( + 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_DEFAULTED_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::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)), + qua::wxyz(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::wxyz( x[0].w, x[0].x, x[0].y, x[0].z ), + qua::wxyz( 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/glm/gtx/easing.hpp b/glm/gtx/easing.hpp new file mode 100644 index 0000000..50ed903 --- /dev/null +++ b/glm/gtx/easing.hpp @@ -0,0 +1,217 @@ +/// @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 transitions +/// 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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_easing extension included") +#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/glm/gtx/easing.inl b/glm/gtx/easing.inl new file mode 100644 index 0000000..b599c30 --- /dev/null +++ b/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(one() - 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/glm/gtx/euler_angles.hpp b/glm/gtx/euler_angles.hpp new file mode 100644 index 0000000..5d67d8e --- /dev/null +++ b/glm/gtx/euler_angles.hpp @@ -0,0 +1,333 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_euler_angles extension included") +#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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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_DISCARD_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/glm/gtx/euler_angles.inl b/glm/gtx/euler_angles.inl new file mode 100644 index 0000000..85f22b9 --- /dev/null +++ b/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] = T(0.0); + Result[1][0] = -s; + Result[1][1] = c; + Result[1][2] = T(0.0); + Result[2][0] = T(0.0); + Result[2][1] = T(0.0); + Result[2][2] = T(1.0); + 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_QUALIFIER 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/glm/gtx/extend.hpp b/glm/gtx/extend.hpp new file mode 100644 index 0000000..46bf5e7 --- /dev/null +++ b/glm/gtx/extend.hpp @@ -0,0 +1,40 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_extend extension included") +#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/glm/gtx/extend.inl b/glm/gtx/extend.inl new file mode 100644 index 0000000..32128eb --- /dev/null +++ b/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/glm/gtx/extended_min_max.hpp b/glm/gtx/extended_min_max.hpp new file mode 100644 index 0000000..e1b722f --- /dev/null +++ b/glm/gtx/extended_min_max.hpp @@ -0,0 +1,135 @@ +/// @ref gtx_extended_min_max +/// @file glm/gtx/extended_min_max.hpp +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extended_min_max GLM_GTX_extended_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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_extended_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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_extended_min_max extension included") +#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/glm/gtx/extended_min_max.inl b/glm/gtx/extended_min_max.inl new file mode 100644 index 0000000..de5998f --- /dev/null +++ b/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/glm/gtx/exterior_product.hpp b/glm/gtx/exterior_product.hpp new file mode 100644 index 0000000..1979acc --- /dev/null +++ b/glm/gtx/exterior_product.hpp @@ -0,0 +1,43 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_exterior_product extension included") +#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 GLM_CONSTEXPR T cross(vec<2, T, Q> const& v, vec<2, T, Q> const& u); + + /// @} +} //namespace glm + +#include "exterior_product.inl" diff --git a/glm/gtx/exterior_product.inl b/glm/gtx/exterior_product.inl new file mode 100644 index 0000000..690085d --- /dev/null +++ b/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 GLM_CONSTEXPR static T call(vec<2, T, Q> const& v, vec<2, T, Q> const& u) + { + GLM_STATIC_ASSERT(std::numeric_limits::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'cross' accepts only floating-point inputs"); + + return v.x * u.y - u.x * v.y; + } + }; +}//namespace detail + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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/glm/gtx/fast_exponential.hpp b/glm/gtx/fast_exponential.hpp new file mode 100644 index 0000000..9fae325 --- /dev/null +++ b/glm/gtx/fast_exponential.hpp @@ -0,0 +1,93 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_fast_exponential extension included") +#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/glm/gtx/fast_exponential.inl b/glm/gtx/fast_exponential.inl new file mode 100644 index 0000000..5b11742 --- /dev/null +++ b/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(static_cast(0.69314718055994530941723212145818) * 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) / static_cast(0.69314718055994530941723212145818); + } + + template + GLM_FUNC_QUALIFIER vec fastLog2(vec const& x) + { + return detail::functor1::call(fastLog2, x); + } +}//namespace glm diff --git a/glm/gtx/fast_square_root.hpp b/glm/gtx/fast_square_root.hpp new file mode 100644 index 0000000..80729db --- /dev/null +++ b/glm/gtx/fast_square_root.hpp @@ -0,0 +1,96 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_fast_square_root extension included") +#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 x); + + /// Faster than the common normalize function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template + GLM_FUNC_DECL vec fastNormalize(vec const& x); + + /// @} +}// namespace glm + +#include "fast_square_root.inl" diff --git a/glm/gtx/fast_square_root.inl b/glm/gtx/fast_square_root.inl new file mode 100644 index 0000000..60fdb7a --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/gtx/fast_trigonometry.hpp b/glm/gtx/fast_trigonometry.hpp new file mode 100644 index 0000000..93acab5 --- /dev/null +++ b/glm/gtx/fast_trigonometry.hpp @@ -0,0 +1,77 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_fast_trigonometry extension included") +#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/glm/gtx/fast_trigonometry.inl b/glm/gtx/fast_trigonometry.inl new file mode 100644 index 0000000..1a710cb --- /dev/null +++ b/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/glm/gtx/float_notmalize.inl b/glm/gtx/float_notmalize.inl new file mode 100644 index 0000000..8cdbc5a --- /dev/null +++ b/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/glm/gtx/functions.hpp b/glm/gtx/functions.hpp new file mode 100644 index 0000000..df68a0d --- /dev/null +++ b/glm/gtx/functions.hpp @@ -0,0 +1,54 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_functions extension included") +#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/glm/gtx/functions.inl b/glm/gtx/functions.inl new file mode 100644 index 0000000..29cbb20 --- /dev/null +++ b/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/glm/gtx/gradient_paint.hpp b/glm/gtx/gradient_paint.hpp new file mode 100644 index 0000000..5656445 --- /dev/null +++ b/glm/gtx/gradient_paint.hpp @@ -0,0 +1,51 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_gradient_paint extension included") +#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/glm/gtx/gradient_paint.inl b/glm/gtx/gradient_paint.inl new file mode 100644 index 0000000..4c495e6 --- /dev/null +++ b/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/glm/gtx/handed_coordinate_space.hpp b/glm/gtx/handed_coordinate_space.hpp new file mode 100644 index 0000000..7c2aada --- /dev/null +++ b/glm/gtx/handed_coordinate_space.hpp @@ -0,0 +1,48 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_handed_coordinate_space extension included") +#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/glm/gtx/handed_coordinate_space.inl b/glm/gtx/handed_coordinate_space.inl new file mode 100644 index 0000000..e43c17b --- /dev/null +++ b/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/glm/gtx/hash.hpp b/glm/gtx/hash.hpp new file mode 100644 index 0000000..ef89290 --- /dev/null +++ b/glm/gtx/hash.hpp @@ -0,0 +1,146 @@ +/// @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 defined(GLM_FORCE_MESSAGES) && !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 "../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 __cplusplus < 201103L +#pragma message("GLM_GTX_hash requires C++11 standard library support") +#endif + +#if GLM_LANG & GLM_LANG_CXX11 +#define GLM_GTX_hash 1 +#include + +namespace std +{ + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<1, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<2, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<3, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::vec<4, T, Q> const& v) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::qua const& q) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::tdualquat const& q) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 2, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 3, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<2, 4, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 2, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 3, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<3, 4, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 2, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 3, T,Q> const& m) const GLM_NOEXCEPT; + }; + + template + struct hash > + { + GLM_FUNC_DECL size_t operator()(glm::mat<4, 4, T,Q> const& m) const GLM_NOEXCEPT; + }; +} // namespace std + +#include "hash.inl" + +#endif //GLM_LANG & GLM_LANG_CXX11 diff --git a/glm/gtx/hash.inl b/glm/gtx/hash.inl new file mode 100644 index 0000000..bcadfe5 --- /dev/null +++ b/glm/gtx/hash.inl @@ -0,0 +1,175 @@ +/// @ref gtx_hash + +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 GLM_NOEXCEPT + { + hash hasher; + return hasher(v.x); + } + + template + GLM_FUNC_QUALIFIER size_t hash >::operator()(glm::vec<2, T, Q> const& v) const GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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 GLM_NOEXCEPT + { + 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/glm/gtx/integer.hpp b/glm/gtx/integer.hpp new file mode 100644 index 0000000..2b16830 --- /dev/null +++ b/glm/gtx/integer.hpp @@ -0,0 +1,74 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_integer extension included") +#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/glm/gtx/integer.inl b/glm/gtx/integer.inl new file mode 100644 index 0000000..eb5df30 --- /dev/null +++ b/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 - static_cast(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/glm/gtx/intersect.hpp b/glm/gtx/intersect.hpp new file mode 100644 index 0000000..c7aec6f --- /dev/null +++ b/glm/gtx/intersect.hpp @@ -0,0 +1,90 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_closest_point extension included") +#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 sphereRadiusSquared, + 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/glm/gtx/intersect.inl b/glm/gtx/intersect.inl new file mode 100644 index 0000000..925a903 --- /dev/null +++ b/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 > static_cast(0)) + { + // 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 < static_cast(0)) + { + // 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); + + typename genType::value_type det = dot(edge1, Perpendicular); + + if (det > -Epsilon && det < Epsilon) + return false; + typename genType::value_type inv_det = typename genType::value_type(1) / det; + + genType Tangent = orig - vert0; + + position.y = dot(Tangent, Perpendicular) * inv_det; + if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1)) + return false; + + genType Cotangent = cross(Tangent, edge1); + + position.z = dot(dir, Cotangent) * 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, Cotangent) * inv_det; + + return true; + } + + template + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const& rayStarting, genType const& rayNormalizedDirection, + genType const& sphereCenter, const typename genType::value_type sphereRadiusSquared, + 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 > sphereRadiusSquared ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadiusSquared - 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/glm/gtx/io.hpp b/glm/gtx/io.hpp new file mode 100644 index 0000000..5afc8cc --- /dev/null +++ b/glm/gtx/io.hpp @@ -0,0 +1,210 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_io extension included") +#endif + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wshorten-64-to-32" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#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_DISCARD_DECL explicit format_punct(size_t a = 0); + GLM_FUNC_DISCARD_DECL explicit format_punct(format_punct const&); + }; + + template > + class basic_state_saver { + + public: + + GLM_FUNC_DISCARD_DECL explicit basic_state_saver(std::basic_ios&); + GLM_FUNC_DISCARD_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_DISCARD_DECL explicit basic_format_saver(std::basic_ios&); + GLM_FUNC_DISCARD_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_DISCARD_DECL explicit precision(unsigned); + }; + + struct width + { + unsigned value; + + GLM_FUNC_DISCARD_DECL explicit width(unsigned); + }; + + template + struct delimeter + { + CTy value[3]; + + GLM_FUNC_DISCARD_DECL explicit delimeter(CTy /* left */, CTy /* right */, CTy /* separator */ = ','); + }; + + struct order + { + order_type value; + + GLM_FUNC_DISCARD_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& unformatted(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_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, qua const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<1, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, vec<4, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<2, 4, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<3, 4, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 2, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 3, T, Q> const&); + template + GLM_FUNC_DISCARD_DECL std::basic_ostream& operator<<(std::basic_ostream&, mat<4, 4, T, Q> const&); + + template + GLM_FUNC_DISCARD_DECL std::basic_ostream & operator<<(std::basic_ostream &, + std::pair const, mat<4, 4, T, Q> const> const&); + + /// @} +}//namespace glm + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + +#include "io.inl" diff --git a/glm/gtx/io.inl b/glm/gtx/io.inl new file mode 100644 index 0000000..d4ef825 --- /dev/null +++ b/glm/gtx/io.inl @@ -0,0 +1,452 @@ +/// @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<> + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wshorten-64-to-32" +# pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + +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(static_cast(fmt.precision)) << std::setfill(fmt.space) << fmt.delim_left; + + for(length_t i(0); i < components; ++i) + { + os << std::setw(static_cast(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 + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + diff --git a/glm/gtx/log_base.hpp b/glm/gtx/log_base.hpp new file mode 100644 index 0000000..915c7a4 --- /dev/null +++ b/glm/gtx/log_base.hpp @@ -0,0 +1,46 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_log_base extension included") +#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/glm/gtx/log_base.inl b/glm/gtx/log_base.inl new file mode 100644 index 0000000..4bbb8e8 --- /dev/null +++ b/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/glm/gtx/matrix_cross_product.hpp b/glm/gtx/matrix_cross_product.hpp new file mode 100644 index 0000000..882a1d7 --- /dev/null +++ b/glm/gtx/matrix_cross_product.hpp @@ -0,0 +1,45 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_cross_product extension included") +#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/glm/gtx/matrix_cross_product.inl b/glm/gtx/matrix_cross_product.inl new file mode 100644 index 0000000..3a15397 --- /dev/null +++ b/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/glm/gtx/matrix_decompose.hpp b/glm/gtx/matrix_decompose.hpp new file mode 100644 index 0000000..19ac8a8 --- /dev/null +++ b/glm/gtx/matrix_decompose.hpp @@ -0,0 +1,50 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_decompose extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_decompose + /// @{ + + /// Decomposes a model matrix to translations, rotation and scale components + /// @see gtx_matrix_decompose + template + GLM_FUNC_DISCARD_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); + + // Recomposes a model matrix from a previously-decomposed matrix + template + GLM_FUNC_DISCARD_DECL mat<4, 4, T, Q> recompose( + vec<3, T, Q> const& scale, qua const& orientation, vec<3, T, Q> const& translation, + vec<3, T, Q> const& skew, vec<4, T, Q> const& perspective); + + /// @} +}//namespace glm + +#include "matrix_decompose.inl" diff --git a/glm/gtx/matrix_decompose.inl b/glm/gtx/matrix_decompose.inl new file mode 100644 index 0000000..1b587e2 --- /dev/null +++ b/glm/gtx/matrix_decompose.inl @@ -0,0 +1,234 @@ +/// @ref gtx_matrix_decompose + +#include "../gtc/constants.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtx/transform.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]; + +# ifdef GLM_FORCE_QUAT_DATA_WXYZ + int off = 1; +# else + int off = 0; +# endif + + root = sqrt(Row[i][i] - Row[j][j] - Row[k][k] + static_cast(1.0)); + + Orientation[i + off] = static_cast(0.5) * root; + root = static_cast(0.5) / root; + Orientation[j + off] = root * (Row[i][j] + Row[j][i]); + Orientation[k + off] = root * (Row[i][k] + Row[k][i]); + Orientation.w = root * (Row[j][k] - Row[k][j]); + } // End if <= 0 + + return true; + } + + // Recomposes a model matrix from a previously-decomposed matrix + // http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp + // https://stackoverflow.com/a/75573092/1047040 + template + GLM_FUNC_DECL mat<4, 4, T, Q> recompose( + vec<3, T, Q> const& scale, qua const& orientation, vec<3, T, Q> const& translation, + vec<3, T, Q> const& skew, vec<4, T, Q> const& perspective) + { + glm::mat4 m = glm::mat4(1.f); + + m[0][3] = perspective.x; + m[1][3] = perspective.y; + m[2][3] = perspective.z; + m[3][3] = perspective.w; + + m *= glm::translate(translation); + m *= glm::mat4_cast(orientation); + + if (abs(skew.x) > static_cast(0)) { + glm::mat4 tmp(1.f); + tmp[2][1] = skew.x; + m *= tmp; + } + + if (abs(skew.y) > static_cast(0)) { + glm::mat4 tmp(1.f); + tmp[2][0] = skew.y; + m *= tmp; + } + + if (abs(skew.z) > static_cast(0)) { + glm::mat4 tmp(1.f); + tmp[1][0] = skew.z; + m *= tmp; + } + + m *= glm::scale(scale); + + return m; + } +}//namespace glm diff --git a/glm/gtx/matrix_factorisation.hpp b/glm/gtx/matrix_factorisation.hpp new file mode 100644 index 0000000..dc32847 --- /dev/null +++ b/glm/gtx/matrix_factorisation.hpp @@ -0,0 +1,67 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_factorisation extension included") +#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_DISCARD_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_DISCARD_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/glm/gtx/matrix_factorisation.inl b/glm/gtx/matrix_factorisation.inl new file mode 100644 index 0000000..6f1683c --- /dev/null +++ b/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%E2%80%93Schmidt_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/glm/gtx/matrix_interpolation.hpp b/glm/gtx/matrix_interpolation.hpp new file mode 100644 index 0000000..e2767c8 --- /dev/null +++ b/glm/gtx/matrix_interpolation.hpp @@ -0,0 +1,58 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_interpolation extension included") +#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_DISCARD_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/glm/gtx/matrix_interpolation.inl b/glm/gtx/matrix_interpolation.inl new file mode 100644 index 0000000..f4ba3a6 --- /dev/null +++ b/glm/gtx/matrix_interpolation.inl @@ -0,0 +1,146 @@ +/// @ref gtx_matrix_interpolation + +#include "../ext/scalar_constants.hpp" + +#include + +namespace glm +{ + template + GLM_FUNC_QUALIFIER void axisAngle(mat<4, 4, T, Q> const& m, vec<3, T, Q>& axis, T& angle) + { + T const epsilon = + std::numeric_limits::epsilon() * static_cast(1e2); + + bool const nearSymmetrical = + 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(nearSymmetrical) + { + bool const nearIdentity = + abs(m[1][0] + m[0][1]) < epsilon && + abs(m[2][0] + m[0][2]) < epsilon && + abs(m[2][1] + m[1][2]) < epsilon && + abs(m[0][0] + m[1][1] + m[2][2] - T(3.0)) < epsilon; + if (nearIdentity) + { + angle = static_cast(0.0); + axis = vec<3, T, Q>( + static_cast(1.0), static_cast(0.0), static_cast(0.0)); + return; + } + angle = pi(); + 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 const angleCos = (m[0][0] + m[1][1] + m[2][2] - static_cast(1)) * static_cast(0.5); + if(angleCos >= static_cast(1.0)) + { + angle = static_cast(0.0); + } + else if (angleCos <= static_cast(-1.0)) + { + angle = pi(); + } + else + { + angle = acos(angleCos); + } + + axis = glm::normalize(glm::vec<3, T, Q>( + m[1][2] - m[2][1], m[2][0] - m[0][2], m[0][1] - m[1][0])); + } + + 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/glm/gtx/matrix_major_storage.hpp b/glm/gtx/matrix_major_storage.hpp new file mode 100644 index 0000000..f518578 --- /dev/null +++ b/glm/gtx/matrix_major_storage.hpp @@ -0,0 +1,117 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_major_storage extension included") +#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/glm/gtx/matrix_major_storage.inl b/glm/gtx/matrix_major_storage.inl new file mode 100644 index 0000000..279dd34 --- /dev/null +++ b/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/glm/gtx/matrix_operation.hpp b/glm/gtx/matrix_operation.hpp new file mode 100644 index 0000000..07ed8e8 --- /dev/null +++ b/glm/gtx/matrix_operation.hpp @@ -0,0 +1,101 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_operation extension included") +#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/glm/gtx/matrix_operation.inl b/glm/gtx/matrix_operation.inl new file mode 100644 index 0000000..a4f4a85 --- /dev/null +++ b/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[0][1], + -m[1][0], +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][1], 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, -m10, +m20, -m30, + -m01, +m11, -m21, +m31, + +m02, -m12, +m22, -m32, + -m03, +m13, -m23, +m33); + } +}//namespace glm diff --git a/glm/gtx/matrix_query.hpp b/glm/gtx/matrix_query.hpp new file mode 100644 index 0000000..de8c655 --- /dev/null +++ b/glm/gtx/matrix_query.hpp @@ -0,0 +1,75 @@ +/// @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 + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_query extension included") +#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/glm/gtx/matrix_query.inl b/glm/gtx/matrix_query.inl new file mode 100644 index 0000000..dc3ec84 --- /dev/null +++ b/glm/gtx/matrix_query.inl @@ -0,0 +1,119 @@ +/// @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.length(); ++i) + { + for(length_t j = 0; result && j < glm::min(i, m[0].length()); ++j) + result = abs(m[i][j]) <= epsilon; + if(result && i < m[0].length()) + result = abs(m[i][i] - 1) <= epsilon; + for(length_t j = i + 1; result && j < m[0].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(); ++i) + { + result = isNormalized(m[i], epsilon); + for(length_t j(i + 1); result && j < m.length(); ++j) + result = abs(dot(m[i], m[j])) <= epsilon; + } + + if(result) + { + mat tmp = transpose(m); + for(length_t i(0); result && i < m.length(); ++i) + { + result = isNormalized(tmp[i], epsilon); + for(length_t j(i + 1); result && j < m.length(); ++j) + result = abs(dot(tmp[i], tmp[j])) <= epsilon; + } + } + return result; + } +}//namespace glm diff --git a/glm/gtx/matrix_transform_2d.hpp b/glm/gtx/matrix_transform_2d.hpp new file mode 100644 index 0000000..deb8da2 --- /dev/null +++ b/glm/gtx/matrix_transform_2d.hpp @@ -0,0 +1,79 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_matrix_transform_2d extension included") +#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/glm/gtx/matrix_transform_2d.inl b/glm/gtx/matrix_transform_2d.inl new file mode 100644 index 0000000..a68d24d --- /dev/null +++ b/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/glm/gtx/mixed_product.hpp b/glm/gtx/mixed_product.hpp new file mode 100644 index 0000000..a091274 --- /dev/null +++ b/glm/gtx/mixed_product.hpp @@ -0,0 +1,39 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_mixed_product extension included") +#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/glm/gtx/mixed_product.inl b/glm/gtx/mixed_product.inl new file mode 100644 index 0000000..e5cdbdb --- /dev/null +++ b/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/glm/gtx/norm.hpp b/glm/gtx/norm.hpp new file mode 100644 index 0000000..d6724a8 --- /dev/null +++ b/glm/gtx/norm.hpp @@ -0,0 +1,86 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_norm extension included") +#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/glm/gtx/norm.inl b/glm/gtx/norm.inl new file mode 100644 index 0000000..4a9f796 --- /dev/null +++ b/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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/gtx/normal.hpp b/glm/gtx/normal.hpp new file mode 100644 index 0000000..8b3a4b5 --- /dev/null +++ b/glm/gtx/normal.hpp @@ -0,0 +1,39 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_normal extension included") +#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/glm/gtx/normal.inl b/glm/gtx/normal.inl new file mode 100644 index 0000000..74f9fc9 --- /dev/null +++ b/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/glm/gtx/normalize_dot.hpp b/glm/gtx/normalize_dot.hpp new file mode 100644 index 0000000..04a6b08 --- /dev/null +++ b/glm/gtx/normalize_dot.hpp @@ -0,0 +1,47 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_normalize_dot extension included") +#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/glm/gtx/normalize_dot.inl b/glm/gtx/normalize_dot.inl new file mode 100644 index 0000000..7bcd9a5 --- /dev/null +++ b/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/glm/gtx/number_precision.hpp b/glm/gtx/number_precision.hpp new file mode 100644 index 0000000..5b9663e --- /dev/null +++ b/glm/gtx/number_precision.hpp @@ -0,0 +1,44 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_number_precision extension included") +#endif + +namespace glm{ + ///////////////////////////// + // Unsigned int vector types + + /// @addtogroup gtx_number_precision + /// @{ + + ////////////////////// + // 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 glm + diff --git a/glm/gtx/optimum_pow.hpp b/glm/gtx/optimum_pow.hpp new file mode 100644 index 0000000..ac34e7e --- /dev/null +++ b/glm/gtx/optimum_pow.hpp @@ -0,0 +1,50 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_optimum_pow extension included") +#endif + +namespace glm +{ + /// @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 glm + +#include "optimum_pow.inl" diff --git a/glm/gtx/optimum_pow.inl b/glm/gtx/optimum_pow.inl new file mode 100644 index 0000000..a26c19c --- /dev/null +++ b/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/glm/gtx/orthonormalize.hpp b/glm/gtx/orthonormalize.hpp new file mode 100644 index 0000000..801b755 --- /dev/null +++ b/glm/gtx/orthonormalize.hpp @@ -0,0 +1,47 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_orthonormalize extension included") +#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/glm/gtx/orthonormalize.inl b/glm/gtx/orthonormalize.inl new file mode 100644 index 0000000..cb553ba --- /dev/null +++ b/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/glm/gtx/pca.hpp b/glm/gtx/pca.hpp new file mode 100644 index 0000000..26f9aec --- /dev/null +++ b/glm/gtx/pca.hpp @@ -0,0 +1,112 @@ +/// @ref gtx_pca +/// @file glm/gtx/pca.hpp +/// +/// @see core (dependence) +/// @see ext_scalar_relational (dependence) +/// +/// @defgroup gtx_pca GLM_GTX_pca +/// @ingroup gtx +/// +/// Include to use the features of this extension. +/// +/// Implements functions required for fundamental 'princple component analysis' in 2D, 3D, and 4D: +/// 1) Computing a covariance matrics from a list of _relative_ position vectors +/// 2) Compute the eigenvalues and eigenvectors of the covariance matrics +/// This is useful, e.g., to compute an object-aligned bounding box from vertices of an object. +/// https://en.wikipedia.org/wiki/Principal_component_analysis +/// +/// Example: +/// ``` +/// std::vector ptData; +/// // ... fill ptData with some point data, e.g. vertices +/// +/// glm::dvec3 center = computeCenter(ptData); +/// +/// glm::dmat3 covarMat = glm::computeCovarianceMatrix(ptData.data(), ptData.size(), center); +/// +/// glm::dvec3 evals; +/// glm::dmat3 evecs; +/// int evcnt = glm::findEigenvaluesSymReal(covarMat, evals, evecs); +/// +/// if(evcnt != 3) +/// // ... error handling +/// +/// glm::sortEigenvalues(evals, evecs); +/// +/// // ... now evecs[0] points in the direction (symmetric) of the largest spatial distribution within ptData +/// ``` + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../ext/scalar_relational.hpp" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_pca 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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_pca extension included") +#endif + +namespace glm { + /// @addtogroup gtx_pca + /// @{ + + /// Compute a covariance matrix form an array of relative coordinates `v` (e.g., relative to the center of gravity of the object) + /// @param v Points to a memory holding `n` times vectors + /// @param n Number of points in v + template + GLM_INLINE mat computeCovarianceMatrix(vec const* v, size_t n); + + /// Compute a covariance matrix form an array of absolute coordinates `v` and a precomputed center of gravity `c` + /// @param v Points to a memory holding `n` times vectors + /// @param n Number of points in v + /// @param c Precomputed center of gravity + template + GLM_INLINE mat computeCovarianceMatrix(vec const* v, size_t n, vec const& c); + + /// Compute a covariance matrix form a pair of iterators `b` (begin) and `e` (end) of a container with relative coordinates (e.g., relative to the center of gravity of the object) + /// Dereferencing an iterator of type I must yield a `vec<D, T, Q%gt;` + template + GLM_FUNC_DECL mat computeCovarianceMatrix(I const& b, I const& e); + + /// Compute a covariance matrix form a pair of iterators `b` (begin) and `e` (end) of a container with absolute coordinates and a precomputed center of gravity `c` + /// Dereferencing an iterator of type I must yield a `vec<D, T, Q%gt;` + template + GLM_FUNC_DECL mat computeCovarianceMatrix(I const& b, I const& e, vec const& c); + + /// Assuming the provided covariance matrix `covarMat` is symmetric and real-valued, this function find the `D` Eigenvalues of the matrix, and also provides the corresponding Eigenvectors. + /// Note: the data in `outEigenvalues` and `outEigenvectors` are in matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + /// This is a numeric implementation to find the Eigenvalues, using 'QL decomposition` (variant of QR decomposition: https://en.wikipedia.org/wiki/QR_decomposition). + /// + /// @param[in] covarMat A symmetric, real-valued covariance matrix, e.g. computed from computeCovarianceMatrix + /// @param[out] outEigenvalues Vector to receive the found eigenvalues + /// @param[out] outEigenvectors Matrix to receive the found eigenvectors corresponding to the found eigenvalues, as column vectors + /// @return The number of eigenvalues found, usually D if the precondition of the covariance matrix is met. + template + GLM_FUNC_DECL unsigned int findEigenvaluesSymReal + ( + mat const& covarMat, + vec& outEigenvalues, + mat& outEigenvectors + ); + + /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. + /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + template + GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<2, T, Q>& eigenvalues, mat<2, 2, T, Q>& eigenvectors); + + /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. + /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + template + GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<3, T, Q>& eigenvalues, mat<3, 3, T, Q>& eigenvectors); + + /// Sorts a group of Eigenvalues&Eigenvectors, for largest Eigenvalue to smallest Eigenvalue. + /// The data in `outEigenvalues` and `outEigenvectors` are assumed to be matching order, i.e. `outEigenvector[i]` is the Eigenvector of the Eigenvalue `outEigenvalue[i]`. + template + GLM_FUNC_DISCARD_DECL void sortEigenvalues(vec<4, T, Q>& eigenvalues, mat<4, 4, T, Q>& eigenvectors); + + /// @} +}//namespace glm + +#include "pca.inl" diff --git a/glm/gtx/pca.inl b/glm/gtx/pca.inl new file mode 100644 index 0000000..94cae94 --- /dev/null +++ b/glm/gtx/pca.inl @@ -0,0 +1,343 @@ +/// @ref gtx_pca + +#ifndef GLM_HAS_CXX11_STL +#include +#else +#include +#endif + +namespace glm { + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(vec const* v, size_t n) + { + return computeCovarianceMatrix const*>(v, v + n); + } + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(vec const* v, size_t n, vec const& c) + { + return computeCovarianceMatrix const*>(v, v + n, c); + } + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(I const& b, I const& e) + { + glm::mat m(0); + + size_t cnt = 0; + for(I i = b; i != e; i++) + { + vec const& v = *i; + for(length_t x = 0; x < D; ++x) + for(length_t y = 0; y < D; ++y) + m[x][y] += static_cast(v[x] * v[y]); + cnt++; + } + if(cnt > 0) + m /= static_cast(cnt); + + return m; + } + + + template + GLM_FUNC_QUALIFIER mat computeCovarianceMatrix(I const& b, I const& e, vec const& c) + { + glm::mat m(0); + glm::vec v; + + size_t cnt = 0; + for(I i = b; i != e; i++) + { + v = *i - c; + for(length_t x = 0; x < D; ++x) + for(length_t y = 0; y < D; ++y) + m[x][y] += static_cast(v[x] * v[y]); + cnt++; + } + if(cnt > 0) + m /= static_cast(cnt); + + return m; + } + + namespace _internal_ + { + + template + GLM_FUNC_QUALIFIER static T transferSign(T const& v, T const& s) + { + return ((s) >= 0 ? glm::abs(v) : -glm::abs(v)); + } + + template + GLM_FUNC_QUALIFIER static T pythag(T const& a, T const& b) { + static const T epsilon = static_cast(0.0000001); + T absa = glm::abs(a); + T absb = glm::abs(b); + if(absa > absb) { + absb /= absa; + absb *= absb; + return absa * glm::sqrt(static_cast(1) + absb); + } + if(glm::equal(absb, 0, epsilon)) return static_cast(0); + absa /= absb; + absa *= absa; + return absb * glm::sqrt(static_cast(1) + absa); + } + + } + + template + GLM_FUNC_QUALIFIER unsigned int findEigenvaluesSymReal + ( + mat const& covarMat, + vec& outEigenvalues, + mat& outEigenvectors + ) + { + using _internal_::transferSign; + using _internal_::pythag; + + T a[D * D]; // matrix -- input and workspace for algorithm (will be changed inplace) + T d[D]; // diagonal elements + T e[D]; // off-diagonal elements + + for(length_t r = 0; r < D; r++) + for(length_t c = 0; c < D; c++) + a[(r) * D + (c)] = covarMat[c][r]; + + // 1. Householder reduction. + length_t l, k, j, i; + T scale, hh, h, g, f; + static const T epsilon = static_cast(0.0000001); + + for(i = D; i >= 2; i--) + { + l = i - 1; + h = scale = 0; + if(l > 1) + { + for(k = 1; k <= l; k++) + { + scale += glm::abs(a[(i - 1) * D + (k - 1)]); + } + if(glm::equal(scale, 0, epsilon)) + { + e[i - 1] = a[(i - 1) * D + (l - 1)]; + } + else + { + for(k = 1; k <= l; k++) + { + a[(i - 1) * D + (k - 1)] /= scale; + h += a[(i - 1) * D + (k - 1)] * a[(i - 1) * D + (k - 1)]; + } + f = a[(i - 1) * D + (l - 1)]; + g = ((f >= 0) ? -glm::sqrt(h) : glm::sqrt(h)); + e[i - 1] = scale * g; + h -= f * g; + a[(i - 1) * D + (l - 1)] = f - g; + f = 0; + for(j = 1; j <= l; j++) + { + a[(j - 1) * D + (i - 1)] = a[(i - 1) * D + (j - 1)] / h; + g = 0; + for(k = 1; k <= j; k++) + { + g += a[(j - 1) * D + (k - 1)] * a[(i - 1) * D + (k - 1)]; + } + for(k = j + 1; k <= l; k++) + { + g += a[(k - 1) * D + (j - 1)] * a[(i - 1) * D + (k - 1)]; + } + e[j - 1] = g / h; + f += e[j - 1] * a[(i - 1) * D + (j - 1)]; + } + hh = f / (h + h); + for(j = 1; j <= l; j++) + { + f = a[(i - 1) * D + (j - 1)]; + e[j - 1] = g = e[j - 1] - hh * f; + for(k = 1; k <= j; k++) + { + a[(j - 1) * D + (k - 1)] -= (f * e[k - 1] + g * a[(i - 1) * D + (k - 1)]); + } + } + } + } + else + { + e[i - 1] = a[(i - 1) * D + (l - 1)]; + } + d[i - 1] = h; + } + d[0] = 0; + e[0] = 0; + for(i = 1; i <= D; i++) + { + l = i - 1; + if(!glm::equal(d[i - 1], 0, epsilon)) + { + for(j = 1; j <= l; j++) + { + g = 0; + for(k = 1; k <= l; k++) + { + g += a[(i - 1) * D + (k - 1)] * a[(k - 1) * D + (j - 1)]; + } + for(k = 1; k <= l; k++) + { + a[(k - 1) * D + (j - 1)] -= g * a[(k - 1) * D + (i - 1)]; + } + } + } + d[i - 1] = a[(i - 1) * D + (i - 1)]; + a[(i - 1) * D + (i - 1)] = 1; + for(j = 1; j <= l; j++) + { + a[(j - 1) * D + (i - 1)] = a[(i - 1) * D + (j - 1)] = 0; + } + } + + // 2. Calculation of eigenvalues and eigenvectors (QL algorithm) + length_t m, iter; + T s, r, p, dd, c, b; + const length_t MAX_ITER = 30; + + for(i = 2; i <= D; i++) + { + e[i - 2] = e[i - 1]; + } + e[D - 1] = 0; + + for(l = 1; l <= D; l++) + { + iter = 0; + do + { + for(m = l; m <= D - 1; m++) + { + dd = glm::abs(d[m - 1]) + glm::abs(d[m - 1 + 1]); + if(glm::equal(glm::abs(e[m - 1]) + dd, dd, epsilon)) + break; + } + if(m != l) + { + if(iter++ == MAX_ITER) + { + return 0; // Too many iterations in FindEigenvalues + } + g = (d[l - 1 + 1] - d[l - 1]) / (2 * e[l - 1]); + r = pythag(g, 1); + g = d[m - 1] - d[l - 1] + e[l - 1] / (g + transferSign(r, g)); + s = c = 1; + p = 0; + for(i = m - 1; i >= l; i--) + { + f = s * e[i - 1]; + b = c * e[i - 1]; + e[i - 1 + 1] = r = pythag(f, g); + if(glm::equal(r, 0, epsilon)) + { + d[i - 1 + 1] -= p; + e[m - 1] = 0; + break; + } + s = f / r; + c = g / r; + g = d[i - 1 + 1] - p; + r = (d[i - 1] - g) * s + 2 * c * b; + d[i - 1 + 1] = g + (p = s * r); + g = c * r - b; + for(k = 1; k <= D; k++) + { + f = a[(k - 1) * D + (i - 1 + 1)]; + a[(k - 1) * D + (i - 1 + 1)] = s * a[(k - 1) * D + (i - 1)] + c * f; + a[(k - 1) * D + (i - 1)] = c * a[(k - 1) * D + (i - 1)] - s * f; + } + } + if(glm::equal(r, 0, epsilon) && (i >= l)) + continue; + d[l - 1] -= p; + e[l - 1] = g; + e[m - 1] = 0; + } + } while(m != l); + } + + // 3. output + for(i = 0; i < D; i++) + outEigenvalues[i] = d[i]; + for(i = 0; i < D; i++) + for(j = 0; j < D; j++) + outEigenvectors[i][j] = a[(j) * D + (i)]; + + return D; + } + + template + GLM_FUNC_QUALIFIER void sortEigenvalues(vec<2, T, Q>& eigenvalues, mat<2, 2, T, Q>& eigenvectors) + { + if (eigenvalues[0] < eigenvalues[1]) + { + std::swap(eigenvalues[0], eigenvalues[1]); + std::swap(eigenvectors[0], eigenvectors[1]); + } + } + + template + GLM_FUNC_QUALIFIER void sortEigenvalues(vec<3, T, Q>& eigenvalues, mat<3, 3, T, Q>& eigenvectors) + { + if (eigenvalues[0] < eigenvalues[1]) + { + std::swap(eigenvalues[0], eigenvalues[1]); + std::swap(eigenvectors[0], eigenvectors[1]); + } + if (eigenvalues[0] < eigenvalues[2]) + { + std::swap(eigenvalues[0], eigenvalues[2]); + std::swap(eigenvectors[0], eigenvectors[2]); + } + if (eigenvalues[1] < eigenvalues[2]) + { + std::swap(eigenvalues[1], eigenvalues[2]); + std::swap(eigenvectors[1], eigenvectors[2]); + } + } + + template + GLM_FUNC_QUALIFIER void sortEigenvalues(vec<4, T, Q>& eigenvalues, mat<4, 4, T, Q>& eigenvectors) + { + if (eigenvalues[0] < eigenvalues[2]) + { + std::swap(eigenvalues[0], eigenvalues[2]); + std::swap(eigenvectors[0], eigenvectors[2]); + } + if (eigenvalues[1] < eigenvalues[3]) + { + std::swap(eigenvalues[1], eigenvalues[3]); + std::swap(eigenvectors[1], eigenvectors[3]); + } + if (eigenvalues[0] < eigenvalues[1]) + { + std::swap(eigenvalues[0], eigenvalues[1]); + std::swap(eigenvectors[0], eigenvectors[1]); + } + if (eigenvalues[2] < eigenvalues[3]) + { + std::swap(eigenvalues[2], eigenvalues[3]); + std::swap(eigenvectors[2], eigenvectors[3]); + } + if (eigenvalues[1] < eigenvalues[2]) + { + std::swap(eigenvalues[1], eigenvalues[2]); + std::swap(eigenvectors[1], eigenvectors[2]); + } + } + +}//namespace glm diff --git a/glm/gtx/perpendicular.hpp b/glm/gtx/perpendicular.hpp new file mode 100644 index 0000000..4087ab0 --- /dev/null +++ b/glm/gtx/perpendicular.hpp @@ -0,0 +1,39 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_perpendicular extension included") +#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/glm/gtx/perpendicular.inl b/glm/gtx/perpendicular.inl new file mode 100644 index 0000000..1e72f33 --- /dev/null +++ b/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/glm/gtx/polar_coordinates.hpp b/glm/gtx/polar_coordinates.hpp new file mode 100644 index 0000000..c27aacf --- /dev/null +++ b/glm/gtx/polar_coordinates.hpp @@ -0,0 +1,46 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_polar_coordinates extension included") +#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/glm/gtx/polar_coordinates.inl b/glm/gtx/polar_coordinates.inl new file mode 100644 index 0000000..371c8dd --- /dev/null +++ b/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/glm/gtx/projection.hpp b/glm/gtx/projection.hpp new file mode 100644 index 0000000..a438f39 --- /dev/null +++ b/glm/gtx/projection.hpp @@ -0,0 +1,41 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_projection extension included") +#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/glm/gtx/projection.inl b/glm/gtx/projection.inl new file mode 100644 index 0000000..f23f884 --- /dev/null +++ b/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/glm/gtx/quaternion.hpp b/glm/gtx/quaternion.hpp new file mode 100644 index 0000000..f51c521 --- /dev/null +++ b/glm/gtx/quaternion.hpp @@ -0,0 +1,172 @@ +/// @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. +/// +/// Extended 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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_quaternion extension included") +#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 GLM_CONSTEXPR 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 GLM_CONSTEXPR 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_QUALIFIER 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_QUALIFIER 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_QUALIFIER 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_QUALIFIER 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/glm/gtx/quaternion.inl b/glm/gtx/quaternion.inl new file mode 100644 index 0000000..5e18899 --- /dev/null +++ b/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::wxyz(static_cast(1), static_cast(0), static_cast(0), static_cast(0)); + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> cross(vec<3, T, Q> const& v, qua const& q) + { + return inverse(q) * v; + } + + template + GLM_FUNC_QUALIFIER GLM_CONSTEXPR 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::wxyz( + 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::wxyz( + s * static_cast(0.5f), + rotationAxis.x * invs, + rotationAxis.y * invs, + rotationAxis.z * invs); + } +}//namespace glm diff --git a/glm/gtx/range.hpp b/glm/gtx/range.hpp new file mode 100644 index 0000000..50c5e57 --- /dev/null +++ b/glm/gtx/range.hpp @@ -0,0 +1,96 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_range extension included") +#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/glm/gtx/raw_data.hpp b/glm/gtx/raw_data.hpp new file mode 100644 index 0000000..3bc27b9 --- /dev/null +++ b/glm/gtx/raw_data.hpp @@ -0,0 +1,49 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_raw_data extension included") +#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/glm/gtx/raw_data.inl b/glm/gtx/raw_data.inl new file mode 100644 index 0000000..c740317 --- /dev/null +++ b/glm/gtx/raw_data.inl @@ -0,0 +1,2 @@ +/// @ref gtx_raw_data + diff --git a/glm/gtx/rotate_normalized_axis.hpp b/glm/gtx/rotate_normalized_axis.hpp new file mode 100644 index 0000000..02c3f5c --- /dev/null +++ b/glm/gtx/rotate_normalized_axis.hpp @@ -0,0 +1,66 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_rotate_normalized_axis extension included") +#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/glm/gtx/rotate_normalized_axis.inl b/glm/gtx/rotate_normalized_axis.inl new file mode 100644 index 0000000..352a56c --- /dev/null +++ b/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::wxyz(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/glm/gtx/rotate_vector.hpp b/glm/gtx/rotate_vector.hpp new file mode 100644 index 0000000..b7345bf --- /dev/null +++ b/glm/gtx/rotate_vector.hpp @@ -0,0 +1,121 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_rotate_vector extension included") +#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/glm/gtx/rotate_vector.inl b/glm/gtx/rotate_vector.inl new file mode 100644 index 0000000..f8136e7 --- /dev/null +++ b/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/glm/gtx/scalar_multiplication.hpp b/glm/gtx/scalar_multiplication.hpp new file mode 100644 index 0000000..97df000 --- /dev/null +++ b/glm/gtx/scalar_multiplication.hpp @@ -0,0 +1,80 @@ +/// @ref gtx_scalar_multiplication +/// @file glm/gtx/scalar_multiplication.hpp +/// @author Joshua Moerman +/// +/// @defgroup gtx_scalar_multiplication GLM_GTX_scalar_multiplication +/// @ingroup gtx +/// +/// 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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_scalar_multiplication extension included") +#endif + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include + +namespace glm +{ + /// @addtogroup gtx_scalar_multiplication + /// @{ + + 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/glm/gtx/scalar_relational.hpp b/glm/gtx/scalar_relational.hpp new file mode 100644 index 0000000..e840932 --- /dev/null +++ b/glm/gtx/scalar_relational.hpp @@ -0,0 +1,34 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "GLM: GLM_GTX_scalar_relational 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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_scalar_relational extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_scalar_relational + /// @{ + + + + /// @} +}//namespace glm + +#include "scalar_relational.inl" diff --git a/glm/gtx/scalar_relational.inl b/glm/gtx/scalar_relational.inl new file mode 100644 index 0000000..c2a121c --- /dev/null +++ b/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/glm/gtx/spline.hpp b/glm/gtx/spline.hpp new file mode 100644 index 0000000..8df5584 --- /dev/null +++ b/glm/gtx/spline.hpp @@ -0,0 +1,63 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_spline extension included") +#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/glm/gtx/spline.inl b/glm/gtx/spline.inl new file mode 100644 index 0000000..c3fd056 --- /dev/null +++ b/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/glm/gtx/std_based_type.hpp b/glm/gtx/std_based_type.hpp new file mode 100644 index 0000000..864885d --- /dev/null +++ b/glm/gtx/std_based_type.hpp @@ -0,0 +1,66 @@ +/// @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 + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_std_based_type extension included") +#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/glm/gtx/std_based_type.inl b/glm/gtx/std_based_type.inl new file mode 100644 index 0000000..9c34bdb --- /dev/null +++ b/glm/gtx/std_based_type.inl @@ -0,0 +1,6 @@ +/// @ref gtx_std_based_type + +namespace glm +{ + +} diff --git a/glm/gtx/string_cast.hpp b/glm/gtx/string_cast.hpp new file mode 100644 index 0000000..2958edc --- /dev/null +++ b/glm/gtx/string_cast.hpp @@ -0,0 +1,45 @@ +/// @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 + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/dual_quaternion.hpp" +#include +#include +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_string_cast extension included") +#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/glm/gtx/string_cast.inl b/glm/gtx/string_cast.inl new file mode 100644 index 0000000..875f2be --- /dev/null +++ b/glm/gtx/string_cast.inl @@ -0,0 +1,497 @@ +/// @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* message, ...) { + std::size_t const STRING_BUFFER(4096); + + assert(message != NULL); + assert(strlen(message) < STRING_BUFFER); + + char buffer[STRING_BUFFER]; + va_list list; + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif + + va_start(list, message); + vsnprintf(buffer, STRING_BUFFER, message, list); + va_end(list); + +#if GLM_COMPILER & GLM_COMPILER_CLANG +# pragma clang diagnostic pop +#endif + + return buffer; + } + + 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/glm/gtx/texture.hpp b/glm/gtx/texture.hpp new file mode 100644 index 0000000..608c6ad --- /dev/null +++ b/glm/gtx/texture.hpp @@ -0,0 +1,44 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_texture extension included") +#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/glm/gtx/texture.inl b/glm/gtx/texture.inl new file mode 100644 index 0000000..593c826 --- /dev/null +++ b/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/glm/gtx/transform.hpp b/glm/gtx/transform.hpp new file mode 100644 index 0000000..9707b50 --- /dev/null +++ b/glm/gtx/transform.hpp @@ -0,0 +1,58 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_transform extension included") +#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/glm/gtx/transform.inl b/glm/gtx/transform.inl new file mode 100644 index 0000000..48ee680 --- /dev/null +++ b/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/glm/gtx/transform2.hpp b/glm/gtx/transform2.hpp new file mode 100644 index 0000000..9604a92 --- /dev/null +++ b/glm/gtx/transform2.hpp @@ -0,0 +1,87 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_transform2 extension included") +#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/glm/gtx/transform2.inl b/glm/gtx/transform2.inl new file mode 100644 index 0000000..0118ab0 --- /dev/null +++ b/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/glm/gtx/type_aligned.hpp b/glm/gtx/type_aligned.hpp new file mode 100644 index 0000000..ec40935 --- /dev/null +++ b/glm/gtx/type_aligned.hpp @@ -0,0 +1,980 @@ +/// @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" + +#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.") +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_type_aligned extension included") +#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/glm/gtx/type_aligned.inl b/glm/gtx/type_aligned.inl new file mode 100644 index 0000000..54c1b81 --- /dev/null +++ b/glm/gtx/type_aligned.inl @@ -0,0 +1,6 @@ +/// @ref gtc_type_aligned + +namespace glm +{ + +} diff --git a/glm/gtx/type_trait.hpp b/glm/gtx/type_trait.hpp new file mode 100644 index 0000000..17ddbad --- /dev/null +++ b/glm/gtx/type_trait.hpp @@ -0,0 +1,83 @@ +/// @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 + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_type_trait extension included") +#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/glm/gtx/type_trait.inl b/glm/gtx/type_trait.inl new file mode 100644 index 0000000..045de95 --- /dev/null +++ b/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/glm/gtx/vec_swizzle.hpp b/glm/gtx/vec_swizzle.hpp new file mode 100644 index 0000000..2dafa64 --- /dev/null +++ b/glm/gtx/vec_swizzle.hpp @@ -0,0 +1,2784 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_vec_swizzle extension included") +#endif + +namespace glm { + /// @addtogroup gtx_vec_swizzle + /// @{ + + // xx + template + GLM_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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_FUNC_QUALIFIER 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); + } + + /// @} +}//namespace glm diff --git a/glm/gtx/vector_angle.hpp b/glm/gtx/vector_angle.hpp new file mode 100644 index 0000000..9ff4127 --- /dev/null +++ b/glm/gtx/vector_angle.hpp @@ -0,0 +1,55 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_vector_angle extension included") +#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/glm/gtx/vector_angle.inl b/glm/gtx/vector_angle.inl new file mode 100644 index 0000000..11e1a21 --- /dev/null +++ b/glm/gtx/vector_angle.inl @@ -0,0 +1,45 @@ +/// @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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), T(-1), T(1))); + } + + 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'orientedAngle' only accept floating-point inputs"); + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + + T const partialCross = x.x * y.y - y.x * x.y; + + if (partialCross > T(0)) + 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 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'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/glm/gtx/vector_query.hpp b/glm/gtx/vector_query.hpp new file mode 100644 index 0000000..ab52df0 --- /dev/null +++ b/glm/gtx/vector_query.hpp @@ -0,0 +1,64 @@ +/// @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 information of vector types + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include +#include + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_vector_query extension included") +#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/glm/gtx/vector_query.inl b/glm/gtx/vector_query.inl new file mode 100644 index 0000000..d1a5c9b --- /dev/null +++ b/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/glm/gtx/wrap.hpp b/glm/gtx/wrap.hpp new file mode 100644 index 0000000..b7ac5af --- /dev/null +++ b/glm/gtx/wrap.hpp @@ -0,0 +1,35 @@ +/// @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" + +#ifndef GLM_ENABLE_EXPERIMENTAL +# error "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." +#elif GLM_MESSAGES == GLM_ENABLE && !defined(GLM_EXT_INCLUDED) +# pragma message("GLM: GLM_GTX_wrap extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_wrap + /// @{ + + /// @} +}// namespace glm + +#include "wrap.inl" diff --git a/glm/gtx/wrap.inl b/glm/gtx/wrap.inl new file mode 100644 index 0000000..4be3b4c --- /dev/null +++ b/glm/gtx/wrap.inl @@ -0,0 +1,6 @@ +/// @ref gtx_wrap + +namespace glm +{ + +}//namespace glm diff --git a/glm/integer.hpp b/glm/integer.hpp new file mode 100644 index 0000000..36c67be --- /dev/null +++ b/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_DISCARD_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_DISCARD_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/glm/mat2x2.hpp b/glm/mat2x2.hpp new file mode 100644 index 0000000..96bec96 --- /dev/null +++ b/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/glm/mat2x3.hpp b/glm/mat2x3.hpp new file mode 100644 index 0000000..d68dc25 --- /dev/null +++ b/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/glm/mat2x4.hpp b/glm/mat2x4.hpp new file mode 100644 index 0000000..b04b738 --- /dev/null +++ b/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/glm/mat3x2.hpp b/glm/mat3x2.hpp new file mode 100644 index 0000000..c853153 --- /dev/null +++ b/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/glm/mat3x3.hpp b/glm/mat3x3.hpp new file mode 100644 index 0000000..fd4fa31 --- /dev/null +++ b/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/glm/mat3x4.hpp b/glm/mat3x4.hpp new file mode 100644 index 0000000..6342bf5 --- /dev/null +++ b/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/glm/mat4x2.hpp b/glm/mat4x2.hpp new file mode 100644 index 0000000..e013e46 --- /dev/null +++ b/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/glm/mat4x3.hpp b/glm/mat4x3.hpp new file mode 100644 index 0000000..205725a --- /dev/null +++ b/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/glm/mat4x4.hpp b/glm/mat4x4.hpp new file mode 100644 index 0000000..3515f7f --- /dev/null +++ b/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/glm/matrix.hpp b/glm/matrix.hpp new file mode 100644 index 0000000..4584c92 --- /dev/null +++ b/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 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 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 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 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 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/glm/packing.hpp b/glm/packing.hpp new file mode 100644 index 0000000..ca83ac1 --- /dev/null +++ b/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/glm/simd/common.h b/glm/simd/common.h new file mode 100644 index 0000000..a580a1f --- /dev/null +++ b/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_div(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/glm/simd/exponential.h b/glm/simd/exponential.h new file mode 100644 index 0000000..bc351d0 --- /dev/null +++ b/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/glm/simd/geometric.h b/glm/simd/geometric.h new file mode 100644 index 0000000..afbe590 --- /dev/null +++ b/glm/simd/geometric.h @@ -0,0 +1,130 @@ +/// @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) +{ + // k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)); + // if (k < 0.0) + // R = genType(0.0); // or genDType(0.0) + // else + // R = eta * I - (eta * dot(N, I) + sqrt(k)) * N; + + glm_vec4 const dot0 = glm_vec4_dot(N, I); // dot(N, I) + glm_vec4 const mul0 = _mm_mul_ps(eta, eta); // eta * eta + glm_vec4 const mul1 = _mm_mul_ps(dot0, dot0); // dot(N, I) * dot(N, I) + glm_vec4 const sub1 = _mm_sub_ps(_mm_set1_ps(1.0f), mul1); // (1.0 - dot(N, I) * dot(N, I)) + glm_vec4 const mul2 = _mm_mul_ps(mul0, sub1); // eta * eta * (1.0 - dot(N, I) * dot(N, I)) + glm_vec4 const sub0 = _mm_sub_ps(_mm_set1_ps(1.0f), mul2); // 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) + + if(_mm_movemask_ps(_mm_cmplt_ss(sub0, _mm_set1_ps(0.0f))) == 0) + return _mm_set1_ps(0.0f); + + glm_vec4 const sqt0 = _mm_sqrt_ps(sub0); + 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/glm/simd/integer.h b/glm/simd/integer.h new file mode 100644 index 0000000..9381418 --- /dev/null +++ b/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/glm/simd/matrix.h b/glm/simd/matrix.h new file mode 100644 index 0000000..b6c42ea --- /dev/null +++ b/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/glm/simd/neon.h b/glm/simd/neon.h new file mode 100644 index 0000000..f85947f --- /dev/null +++ b/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 inline 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 inline 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 inline 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 inline 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 inline 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/glm/simd/packing.h b/glm/simd/packing.h new file mode 100644 index 0000000..609163e --- /dev/null +++ b/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/glm/simd/platform.h b/glm/simd/platform.h new file mode 100644 index 0000000..a318b09 --- /dev/null +++ b/glm/simd/platform.h @@ -0,0 +1,469 @@ +#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 +#define GLM_COMPILER_INTEL18 0x00100080 +#define GLM_COMPILER_INTEL19 0x00100090 +#define GLM_COMPILER_INTEL21 0x001000A0 + +// Visual C++ defines +#define GLM_COMPILER_VC 0x01000000 +#define GLM_COMPILER_VC12 0x01000001 // Visual Studio 2013 +#define GLM_COMPILER_VC14 0x01000002 // Visual Studio 2015 +#define GLM_COMPILER_VC15 0x01000003 // Visual Studio 2017 +#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 // Visual Studio 2019 +#define GLM_COMPILER_VC17 0x0100000B // Visual Studio 2022 + +// 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_GCC61 0x02000800 +#define GLM_COMPILER_GCC7 0x02000400 +#define GLM_COMPILER_GCC8 0x02000500 +#define GLM_COMPILER_GCC9 0x02000600 +#define GLM_COMPILER_GCC10 0x02000700 +#define GLM_COMPILER_GCC11 0x02000800 +#define GLM_COMPILER_GCC12 0x02000900 +#define GLM_COMPILER_GCC13 0x02000A00 +#define GLM_COMPILER_GCC14 0x02000B00 + +// CUDA +#define GLM_COMPILER_CUDA 0x10000000 +#define GLM_COMPILER_CUDA75 0x10000001 +#define GLM_COMPILER_CUDA80 0x10000002 +#define GLM_COMPILER_CUDA90 0x10000004 +#define GLM_COMPILER_CUDA_RTC 0x10000100 + +// 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_CLANG4 0x200000B0 +#define GLM_COMPILER_CLANG5 0x200000C0 +#define GLM_COMPILER_CLANG6 0x200000D0 +#define GLM_COMPILER_CLANG7 0x200000E0 +#define GLM_COMPILER_CLANG8 0x200000F0 +#define GLM_COMPILER_CLANG9 0x20000100 +#define GLM_COMPILER_CLANG10 0x20000200 +#define GLM_COMPILER_CLANG11 0x20000300 +#define GLM_COMPILER_CLANG12 0x20000400 +#define GLM_COMPILER_CLANG13 0x20000500 +#define GLM_COMPILER_CLANG14 0x20000600 +#define GLM_COMPILER_CLANG15 0x20000700 +#define GLM_COMPILER_CLANG16 0x20000800 +#define GLM_COMPILER_CLANG17 0x20000900 +#define GLM_COMPILER_CLANG18 0x20000A00 +#define GLM_COMPILER_CLANG19 0x20000B00 + +// HIP +#define GLM_COMPILER_HIP 0x40000000 + +// 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 >= 2021 +# define GLM_COMPILER GLM_COMPILER_INTEL21 +# elif __INTEL_COMPILER >= 1900 +# define GLM_COMPILER GLM_COMPILER_INTEL19 +# elif __INTEL_COMPILER >= 1800 +# define GLM_COMPILER GLM_COMPILER_INTEL18 +# elif __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 defined(__CUDACC_RTC__) +# define GLM_COMPILER GLM_COMPILER_CUDA_RTC +# elif 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 + +// HIP +#elif defined(__HIP__) +# define GLM_COMPILER GLM_COMPILER_HIP + +// 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_CLANG4 +# elif __clang_major__ == 5 +# define GLM_COMPILER GLM_COMPILER_CLANG5 +# elif __clang_major__ == 6 +# define GLM_COMPILER GLM_COMPILER_CLANG6 +# elif __clang_major__ == 7 +# define GLM_COMPILER GLM_COMPILER_CLANG7 +# elif __clang_major__ == 8 +# define GLM_COMPILER GLM_COMPILER_CLANG8 +# elif __clang_major__ == 9 +# define GLM_COMPILER GLM_COMPILER_CLANG9 +# elif __clang_major__ == 10 +# define GLM_COMPILER GLM_COMPILER_CLANG10 +# elif __clang_major__ == 11 +# define GLM_COMPILER GLM_COMPILER_CLANG11 +# elif __clang_major__ == 12 +# define GLM_COMPILER GLM_COMPILER_CLANG12 +# elif __clang_major__ == 13 +# define GLM_COMPILER GLM_COMPILER_CLANG13 +# elif __clang_major__ == 14 +# define GLM_COMPILER GLM_COMPILER_CLANG14 +# elif __clang_major__ == 15 +# define GLM_COMPILER GLM_COMPILER_CLANG15 +# elif __clang_major__ == 16 +# define GLM_COMPILER GLM_COMPILER_CLANG16 +# elif __clang_major__ == 17 +# define GLM_COMPILER GLM_COMPILER_CLANG17 +# elif __clang_major__ == 18 +# define GLM_COMPILER GLM_COMPILER_CLANG18 +# elif __clang_major__ >= 19 +# define GLM_COMPILER GLM_COMPILER_CLANG19 +# endif +# endif + +// Visual C++ +#elif defined(_MSC_VER) +# if _MSC_VER >= 1930 +# define GLM_COMPILER GLM_COMPILER_VC17 +# elif _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__ >= 14 +# define GLM_COMPILER GLM_COMPILER_GCC14 +# elif __GNUC__ >= 13 +# define GLM_COMPILER GLM_COMPILER_GCC13 +# elif __GNUC__ >= 12 +# define GLM_COMPILER GLM_COMPILER_GCC12 +# elif __GNUC__ >= 11 +# define GLM_COMPILER GLM_COMPILER_GCC11 +# elif __GNUC__ >= 10 +# define GLM_COMPILER GLM_COMPILER_GCC10 +# elif __GNUC__ >= 9 +# define GLM_COMPILER GLM_COMPILER_GCC9 +# elif __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/glm/simd/trigonometric.h b/glm/simd/trigonometric.h new file mode 100644 index 0000000..739b796 --- /dev/null +++ b/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/glm/simd/vector_relational.h b/glm/simd/vector_relational.h new file mode 100644 index 0000000..f7385e9 --- /dev/null +++ b/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/glm/trigonometric.hpp b/glm/trigonometric.hpp new file mode 100644 index 0000000..51d49c1 --- /dev/null +++ b/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 cosine 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/glm/vec2.hpp b/glm/vec2.hpp new file mode 100644 index 0000000..cd4e070 --- /dev/null +++ b/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/glm/vec3.hpp b/glm/vec3.hpp new file mode 100644 index 0000000..f5a927d --- /dev/null +++ b/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/glm/vec4.hpp b/glm/vec4.hpp new file mode 100644 index 0000000..c6ea9f1 --- /dev/null +++ b/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/glm/vector_relational.hpp b/glm/vector_relational.hpp new file mode 100644 index 0000000..a0fe17e --- /dev/null +++ b/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/include/linmath.h b/include/linmath.h deleted file mode 100644 index 45a9e18..0000000 --- a/include/linmath.h +++ /dev/null @@ -1,605 +0,0 @@ -#ifndef LINMATH_H -#define LINMATH_H - -#include -#include -#include - -#ifdef LINMATH_NO_INLINE -#define LINMATH_H_FUNC static -#else -#define LINMATH_H_FUNC static inline -#endif - -#define LINMATH_H_DEFINE_VEC(n) \ -typedef float vec##n[n]; \ -LINMATH_H_FUNC void vec##n##_add(vec##n r, vec##n const a, vec##n const b) \ -{ \ - int i; \ - for(i=0; ib[i] ? a[i] : b[i]; \ -} \ -LINMATH_H_FUNC void vec##n##_dup(vec##n r, vec##n const src) \ -{ \ - int i; \ - for(i=0; i 1e-4) { - vec3_norm(u, u); - mat4x4 T; - mat4x4_from_vec3_mul_outer(T, u, u); - - mat4x4 S = { - { 0, u[2], -u[1], 0}, - {-u[2], 0, u[0], 0}, - { u[1], -u[0], 0, 0}, - { 0, 0, 0, 0} - }; - mat4x4_scale(S, S, s); - - mat4x4 C; - mat4x4_identity(C); - mat4x4_sub(C, C, T); - - mat4x4_scale(C, C, c); - - mat4x4_add(T, T, C); - mat4x4_add(T, T, S); - - T[3][3] = 1.f; - mat4x4_mul(R, M, T); - } else { - mat4x4_dup(R, M); - } -} -LINMATH_H_FUNC void mat4x4_rotate_X(mat4x4 Q, mat4x4 const M, float angle) -{ - float s = sinf(angle); - float c = cosf(angle); - mat4x4 R = { - {1.f, 0.f, 0.f, 0.f}, - {0.f, c, s, 0.f}, - {0.f, -s, c, 0.f}, - {0.f, 0.f, 0.f, 1.f} - }; - mat4x4_mul(Q, M, R); -} -LINMATH_H_FUNC void mat4x4_rotate_Y(mat4x4 Q, mat4x4 const M, float angle) -{ - float s = sinf(angle); - float c = cosf(angle); - mat4x4 R = { - { c, 0.f, -s, 0.f}, - { 0.f, 1.f, 0.f, 0.f}, - { s, 0.f, c, 0.f}, - { 0.f, 0.f, 0.f, 1.f} - }; - mat4x4_mul(Q, M, R); -} -LINMATH_H_FUNC void mat4x4_rotate_Z(mat4x4 Q, mat4x4 const M, float angle) -{ - float s = sinf(angle); - float c = cosf(angle); - mat4x4 R = { - { c, s, 0.f, 0.f}, - { -s, c, 0.f, 0.f}, - { 0.f, 0.f, 1.f, 0.f}, - { 0.f, 0.f, 0.f, 1.f} - }; - mat4x4_mul(Q, M, R); -} -LINMATH_H_FUNC void mat4x4_invert(mat4x4 T, mat4x4 const M) -{ - float s[6]; - float c[6]; - s[0] = M[0][0]*M[1][1] - M[1][0]*M[0][1]; - s[1] = M[0][0]*M[1][2] - M[1][0]*M[0][2]; - s[2] = M[0][0]*M[1][3] - M[1][0]*M[0][3]; - s[3] = M[0][1]*M[1][2] - M[1][1]*M[0][2]; - s[4] = M[0][1]*M[1][3] - M[1][1]*M[0][3]; - s[5] = M[0][2]*M[1][3] - M[1][2]*M[0][3]; - - c[0] = M[2][0]*M[3][1] - M[3][0]*M[2][1]; - c[1] = M[2][0]*M[3][2] - M[3][0]*M[2][2]; - c[2] = M[2][0]*M[3][3] - M[3][0]*M[2][3]; - c[3] = M[2][1]*M[3][2] - M[3][1]*M[2][2]; - c[4] = M[2][1]*M[3][3] - M[3][1]*M[2][3]; - c[5] = M[2][2]*M[3][3] - M[3][2]*M[2][3]; - - /* Assumes it is invertible */ - float idet = 1.0f/( s[0]*c[5]-s[1]*c[4]+s[2]*c[3]+s[3]*c[2]-s[4]*c[1]+s[5]*c[0] ); - - T[0][0] = ( M[1][1] * c[5] - M[1][2] * c[4] + M[1][3] * c[3]) * idet; - T[0][1] = (-M[0][1] * c[5] + M[0][2] * c[4] - M[0][3] * c[3]) * idet; - T[0][2] = ( M[3][1] * s[5] - M[3][2] * s[4] + M[3][3] * s[3]) * idet; - T[0][3] = (-M[2][1] * s[5] + M[2][2] * s[4] - M[2][3] * s[3]) * idet; - - T[1][0] = (-M[1][0] * c[5] + M[1][2] * c[2] - M[1][3] * c[1]) * idet; - T[1][1] = ( M[0][0] * c[5] - M[0][2] * c[2] + M[0][3] * c[1]) * idet; - T[1][2] = (-M[3][0] * s[5] + M[3][2] * s[2] - M[3][3] * s[1]) * idet; - T[1][3] = ( M[2][0] * s[5] - M[2][2] * s[2] + M[2][3] * s[1]) * idet; - - T[2][0] = ( M[1][0] * c[4] - M[1][1] * c[2] + M[1][3] * c[0]) * idet; - T[2][1] = (-M[0][0] * c[4] + M[0][1] * c[2] - M[0][3] * c[0]) * idet; - T[2][2] = ( M[3][0] * s[4] - M[3][1] * s[2] + M[3][3] * s[0]) * idet; - T[2][3] = (-M[2][0] * s[4] + M[2][1] * s[2] - M[2][3] * s[0]) * idet; - - T[3][0] = (-M[1][0] * c[3] + M[1][1] * c[1] - M[1][2] * c[0]) * idet; - T[3][1] = ( M[0][0] * c[3] - M[0][1] * c[1] + M[0][2] * c[0]) * idet; - T[3][2] = (-M[3][0] * s[3] + M[3][1] * s[1] - M[3][2] * s[0]) * idet; - T[3][3] = ( M[2][0] * s[3] - M[2][1] * s[1] + M[2][2] * s[0]) * idet; -} -LINMATH_H_FUNC void mat4x4_orthonormalize(mat4x4 R, mat4x4 const M) -{ - mat4x4_dup(R, M); - float s = 1.f; - vec3 h; - - vec3_norm(R[2], R[2]); - - s = vec3_mul_inner(R[1], R[2]); - vec3_scale(h, R[2], s); - vec3_sub(R[1], R[1], h); - vec3_norm(R[1], R[1]); - - s = vec3_mul_inner(R[0], R[2]); - vec3_scale(h, R[2], s); - vec3_sub(R[0], R[0], h); - - s = vec3_mul_inner(R[0], R[1]); - vec3_scale(h, R[1], s); - vec3_sub(R[0], R[0], h); - vec3_norm(R[0], R[0]); -} - -LINMATH_H_FUNC void mat4x4_frustum(mat4x4 M, float l, float r, float b, float t, float n, float f) -{ - M[0][0] = 2.f*n/(r-l); - M[0][1] = M[0][2] = M[0][3] = 0.f; - - M[1][1] = 2.f*n/(t-b); - M[1][0] = M[1][2] = M[1][3] = 0.f; - - M[2][0] = (r+l)/(r-l); - M[2][1] = (t+b)/(t-b); - M[2][2] = -(f+n)/(f-n); - M[2][3] = -1.f; - - M[3][2] = -2.f*(f*n)/(f-n); - M[3][0] = M[3][1] = M[3][3] = 0.f; -} -LINMATH_H_FUNC void mat4x4_ortho(mat4x4 M, float l, float r, float b, float t, float n, float f) -{ - M[0][0] = 2.f/(r-l); - M[0][1] = M[0][2] = M[0][3] = 0.f; - - M[1][1] = 2.f/(t-b); - M[1][0] = M[1][2] = M[1][3] = 0.f; - - M[2][2] = -2.f/(f-n); - M[2][0] = M[2][1] = M[2][3] = 0.f; - - M[3][0] = -(r+l)/(r-l); - M[3][1] = -(t+b)/(t-b); - M[3][2] = -(f+n)/(f-n); - M[3][3] = 1.f; -} -LINMATH_H_FUNC void mat4x4_perspective(mat4x4 m, float y_fov, float aspect, float n, float f) -{ - /* NOTE: Degrees are an unhandy unit to work with. - * linmath.h uses radians for everything! */ - float const a = 1.f / tanf(y_fov / 2.f); - - m[0][0] = a / aspect; - m[0][1] = 0.f; - m[0][2] = 0.f; - m[0][3] = 0.f; - - m[1][0] = 0.f; - m[1][1] = a; - m[1][2] = 0.f; - m[1][3] = 0.f; - - m[2][0] = 0.f; - m[2][1] = 0.f; - m[2][2] = -((f + n) / (f - n)); - m[2][3] = -1.f; - - m[3][0] = 0.f; - m[3][1] = 0.f; - m[3][2] = -((2.f * f * n) / (f - n)); - m[3][3] = 0.f; -} -LINMATH_H_FUNC void mat4x4_look_at(mat4x4 m, vec3 const eye, vec3 const center, vec3 const up) -{ - /* Adapted from Android's OpenGL Matrix.java. */ - /* See the OpenGL GLUT documentation for gluLookAt for a description */ - /* of the algorithm. We implement it in a straightforward way: */ - - /* TODO: The negation of of can be spared by swapping the order of - * operands in the following cross products in the right way. */ - vec3 f; - vec3_sub(f, center, eye); - vec3_norm(f, f); - - vec3 s; - vec3_mul_cross(s, f, up); - vec3_norm(s, s); - - vec3 t; - vec3_mul_cross(t, s, f); - - m[0][0] = s[0]; - m[0][1] = t[0]; - m[0][2] = -f[0]; - m[0][3] = 0.f; - - m[1][0] = s[1]; - m[1][1] = t[1]; - m[1][2] = -f[1]; - m[1][3] = 0.f; - - m[2][0] = s[2]; - m[2][1] = t[2]; - m[2][2] = -f[2]; - m[2][3] = 0.f; - - m[3][0] = 0.f; - m[3][1] = 0.f; - m[3][2] = 0.f; - m[3][3] = 1.f; - - mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]); -} - -typedef float quat[4]; -#define quat_add vec4_add -#define quat_sub vec4_sub -#define quat_norm vec4_norm -#define quat_scale vec4_scale -#define quat_mul_inner vec4_mul_inner - -LINMATH_H_FUNC void quat_identity(quat q) -{ - q[0] = q[1] = q[2] = 0.f; - q[3] = 1.f; -} -LINMATH_H_FUNC void quat_mul(quat r, quat const p, quat const q) -{ - vec3 w, tmp; - - vec3_mul_cross(tmp, p, q); - vec3_scale(w, p, q[3]); - vec3_add(tmp, tmp, w); - vec3_scale(w, q, p[3]); - vec3_add(tmp, tmp, w); - - vec3_dup(r, tmp); - r[3] = p[3]*q[3] - vec3_mul_inner(p, q); -} -LINMATH_H_FUNC void quat_conj(quat r, quat const q) -{ - int i; - for(i=0; i<3; ++i) - r[i] = -q[i]; - r[3] = q[3]; -} -LINMATH_H_FUNC void quat_rotate(quat r, float angle, vec3 const axis) { - vec3 axis_norm; - vec3_norm(axis_norm, axis); - float s = sinf(angle / 2); - float c = cosf(angle / 2); - vec3_scale(r, axis_norm, s); - r[3] = c; -} -LINMATH_H_FUNC void quat_mul_vec3(vec3 r, quat const q, vec3 const v) -{ -/* - * Method by Fabian 'ryg' Giessen (of Farbrausch) -t = 2 * cross(q.xyz, v) -v' = v + q.w * t + cross(q.xyz, t) - */ - vec3 t; - vec3 q_xyz = {q[0], q[1], q[2]}; - vec3 u = {q[0], q[1], q[2]}; - - vec3_mul_cross(t, q_xyz, v); - vec3_scale(t, t, 2); - - vec3_mul_cross(u, q_xyz, t); - vec3_scale(t, t, q[3]); - - vec3_add(r, v, t); - vec3_add(r, r, u); -} -LINMATH_H_FUNC void mat4x4_from_quat(mat4x4 M, quat const q) -{ - float a = q[3]; - float b = q[0]; - float c = q[1]; - float d = q[2]; - float a2 = a*a; - float b2 = b*b; - float c2 = c*c; - float d2 = d*d; - - M[0][0] = a2 + b2 - c2 - d2; - M[0][1] = 2.f*(b*c + a*d); - M[0][2] = 2.f*(b*d - a*c); - M[0][3] = 0.f; - - M[1][0] = 2*(b*c - a*d); - M[1][1] = a2 - b2 + c2 - d2; - M[1][2] = 2.f*(c*d + a*b); - M[1][3] = 0.f; - - M[2][0] = 2.f*(b*d + a*c); - M[2][1] = 2.f*(c*d - a*b); - M[2][2] = a2 - b2 - c2 + d2; - M[2][3] = 0.f; - - M[3][0] = M[3][1] = M[3][2] = 0.f; - M[3][3] = 1.f; -} - -LINMATH_H_FUNC void mat4x4o_mul_quat(mat4x4 R, mat4x4 const M, quat const q) -{ -/* XXX: The way this is written only works for orthogonal matrices. */ -/* TODO: Take care of non-orthogonal case. */ - quat_mul_vec3(R[0], q, M[0]); - quat_mul_vec3(R[1], q, M[1]); - quat_mul_vec3(R[2], q, M[2]); - - R[3][0] = R[3][1] = R[3][2] = 0.f; - R[0][3] = M[0][3]; - R[1][3] = M[1][3]; - R[2][3] = M[2][3]; - R[3][3] = M[3][3]; // typically 1.0, but here we make it general -} -LINMATH_H_FUNC void quat_from_mat4x4(quat q, mat4x4 const M) -{ - float r=0.f; - int i; - - int perm[] = { 0, 1, 2, 0, 1 }; - int *p = perm; - - for(i = 0; i<3; i++) { - float m = M[i][i]; - if( m < r ) - continue; - m = r; - p = &perm[i]; - } - - r = sqrtf(1.f + M[p[0]][p[0]] - M[p[1]][p[1]] - M[p[2]][p[2]] ); - - if(r < 1e-6) { - q[0] = 1.f; - q[1] = q[2] = q[3] = 0.f; - return; - } - - q[0] = r/2.f; - q[1] = (M[p[0]][p[1]] - M[p[1]][p[0]])/(2.f*r); - q[2] = (M[p[2]][p[0]] - M[p[0]][p[2]])/(2.f*r); - q[3] = (M[p[2]][p[1]] - M[p[1]][p[2]])/(2.f*r); -} - -LINMATH_H_FUNC void mat4x4_arcball(mat4x4 R, mat4x4 const M, vec2 const _a, vec2 const _b, float s) -{ - vec2 a; memcpy(a, _a, sizeof(a)); - vec2 b; memcpy(b, _b, sizeof(b)); - - float z_a = 0.; - float z_b = 0.; - - if(vec2_len(a) < 1.) { - z_a = sqrtf(1. - vec2_mul_inner(a, a)); - } else { - vec2_norm(a, a); - } - - if(vec2_len(b) < 1.) { - z_b = sqrtf(1. - vec2_mul_inner(b, b)); - } else { - vec2_norm(b, b); - } - - vec3 a_ = {a[0], a[1], z_a}; - vec3 b_ = {b[0], b[1], z_b}; - - vec3 c_; - vec3_mul_cross(c_, a_, b_); - - float const angle = acos(vec3_mul_inner(a_, b_)) * s; - mat4x4_rotate(R, M, c_[0], c_[1], c_[2], angle); -} -#endif \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ccb5389..05c37b8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,5 +2,5 @@ add_executable(Exponent main.cc ) -target_link_libraries(Exponent PUBLIC glfw) +target_link_libraries(Exponent PUBLIC glfw glm::glm) target_include_directories(Exponent PUBLIC ${CMAKE_SOURCE_DIR}/include) \ No newline at end of file diff --git a/src/main.cc b/src/main.cc index 6542fd4..d5e780b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -3,136 +3,58 @@ #define GLFW_INCLUDE_NONE #include "GLFW/glfw3.h" -#include "linmath.h" - -#include - -struct Vertex { - vec2 pos; - vec3 col; -}; - -static const struct Vertex verts[3] = { - { { -0.6f, -0.4f }, { 1.f, 0.f, 0.f } }, - { { 0.6f, -0.4f }, { 0.f, 1.f, 0.f } }, - { { 0.f, 0.6f }, { 0.f, 0.f, 1.f } } -}; - -static const char* vertex_shader_text = -"#version 330\n" -"uniform mat4 MVP;\n" -"in vec3 vCol;\n" -"in vec2 vPos;\n" -"out vec3 color;\n" -"void main()\n" -"{\n" -" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n" -" color = vCol;\n" -"}\n"; - -static const char* fragment_shader_text = -"#version 330\n" -"in vec3 color;\n" -"out vec4 fragment;\n" -"void main()\n" -"{\n" -" fragment = vec4(color, 1.0);\n" -"}\n"; - -void error_cb(int error, const char *desc) { - std::cerr << desc << std::endl; -} - -static void key_cb(GLFWwindow *w, int key, int scancode, int action, int mods) { +static void key_callback(GLFWwindow *w, int key, int scancode, int action, int mods) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { - glfwSetWindowShouldClose(w, GLFW_TRUE); + glfwSetWindowShouldClose(w, GL_TRUE); } } -int main(void) { - glfwSetErrorCallback(error_cb); +int main() { + // Initialise GLFW if (!glfwInit()) { - return 1; + exit(EXIT_FAILURE); } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - GLFWwindow *w = glfwCreateWindow(640, 480, "Window!", NULL, NULL); - + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); + // Create our context + GLFWwindow *w = glfwCreateWindow(640, 480, "Test", NULL, NULL); if (!w) { glfwTerminate(); - return 2; + exit(EXIT_FAILURE); } - glfwMakeContextCurrent(w); - gladLoadGL(glfwGetProcAddress); + glfwSwapInterval(1); // Essentially vsync + gladLoadGL(glfwGetProcAddress); // Load openGL using glfw + + // Set up the key handler + glfwSetKeyCallback(w, key_callback); + + // Configure the context's capabilities + glClearColor(1.0, 0.0, 0.0, 1.0); + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); // Maybe this allows transparency? + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // TODO: Actually make some opengl shit happen - glfwSetKeyCallback(w, key_cb); - - int width, height; - glfwGetFramebufferSize(w, &width, &height); - glViewport(0, 0, width, height); - - glfwSwapInterval(1); - - GLuint vertex_buffer; - glGenBuffers(1, &vertex_buffer); - glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); - glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); - - const GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL); - glCompileShader(vertex_shader); - - const GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL); - glCompileShader(fragment_shader); - - const GLuint program = glCreateProgram(); - glAttachShader(program, vertex_shader); - glAttachShader(program, fragment_shader); - glLinkProgram(program); - - const GLint mvp_location = glGetUniformLocation(program, "MVP"); - const GLint vpos_location = glGetAttribLocation(program, "vPos"); - const GLint vcol_location = glGetAttribLocation(program, "vCol"); - - GLuint vertex_array; - glGenVertexArrays(1, &vertex_array); - glBindVertexArray(vertex_array); - glEnableVertexAttribArray(vpos_location); - glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE, - sizeof(Vertex), (void*) offsetof(Vertex, pos)); - glEnableVertexAttribArray(vcol_location); - glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE, - sizeof(Vertex), (void*) offsetof(Vertex, col)); - - double time = glfwGetTime(); + // Main Loop while(!glfwWindowShouldClose(w)) { - int width, height; + /* + int width, height; glfwGetFramebufferSize(w, &width, &height); - const float ratio = width / (float) height; - + glViewport(0, 0, width, height); glClear(GL_COLOR_BUFFER_BIT); - - mat4x4 m, p, mvp; - mat4x4_identity(m); - mat4x4_rotate_Z(m, m, (float) glfwGetTime()); - mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f); - mat4x4_mul(mvp, p, m); - - glUseProgram(program); - glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) &mvp); - glBindVertexArray(vertex_array); - glDrawArrays(GL_TRIANGLES, 0, 3); - + */ + + // TODO Draw primitives + glfwSwapBuffers(w); glfwPollEvents(); } glfwDestroyWindow(w); glfwTerminate(); - return 0; + exit(EXIT_SUCCESS); } \ No newline at end of file

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 Cy4D^5 diff --git a/build/src/Exponent.exe b/build/src/Exponent.exe index 15976cb3fc4b3e005f998b364faa0f4e607c562c..a36137b25779cb80be633f5ee39cf387c795b869 100644 GIT binary patch delta 326251 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