1/// @ref core 2/// @file glm/detail/func_geometric.inl 3 4#include "func_exponential.hpp" 5#include "func_common.hpp" 6#include "type_vec2.hpp" 7#include "type_vec4.hpp" 8#include "type_float.hpp" 9 10namespace glm{ 11namespace detail 12{ 13 template <template <typename, precision> class vecType, typename T, precision P, bool Aligned> 14 struct compute_length 15 { 16 GLM_FUNC_QUALIFIER static T call(vecType<T, P> const & v) 17 { 18 return sqrt(dot(v, v)); 19 } 20 }; 21 22 template <template <typename, precision> class vecType, typename T, precision P, bool Aligned> 23 struct compute_distance 24 { 25 GLM_FUNC_QUALIFIER static T call(vecType<T, P> const & p0, vecType<T, P> const & p1) 26 { 27 return length(p1 - p0); 28 } 29 }; 30 31 template <template <class, precision> class vecType, typename T, precision P, bool Aligned> 32 struct compute_dot{}; 33 34 template <typename T, precision P, bool Aligned> 35 struct compute_dot<tvec1, T, P, Aligned> 36 { 37 GLM_FUNC_QUALIFIER static T call(tvec1<T, P> const & a, tvec1<T, P> const & b) 38 { 39 return a.x * b.x; 40 } 41 }; 42 43 template <typename T, precision P, bool Aligned> 44 struct compute_dot<tvec2, T, P, Aligned> 45 { 46 GLM_FUNC_QUALIFIER static T call(tvec2<T, P> const & x, tvec2<T, P> const & y) 47 { 48 tvec2<T, P> tmp(x * y); 49 return tmp.x + tmp.y; 50 } 51 }; 52 53 template <typename T, precision P, bool Aligned> 54 struct compute_dot<tvec3, T, P, Aligned> 55 { 56 GLM_FUNC_QUALIFIER static T call(tvec3<T, P> const & x, tvec3<T, P> const & y) 57 { 58 tvec3<T, P> tmp(x * y); 59 return tmp.x + tmp.y + tmp.z; 60 } 61 }; 62 63 template <typename T, precision P, bool Aligned> 64 struct compute_dot<tvec4, T, P, Aligned> 65 { 66 GLM_FUNC_QUALIFIER static T call(tvec4<T, P> const & x, tvec4<T, P> const & y) 67 { 68 tvec4<T, P> tmp(x * y); 69 return (tmp.x + tmp.y) + (tmp.z + tmp.w); 70 } 71 }; 72 73 template <typename T, precision P, bool Aligned> 74 struct compute_cross 75 { 76 GLM_FUNC_QUALIFIER static tvec3<T, P> call(tvec3<T, P> const & x, tvec3<T, P> const & y) 77 { 78 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' accepts only floating-point inputs"); 79 80 return tvec3<T, P>( 81 x.y * y.z - y.y * x.z, 82 x.z * y.x - y.z * x.x, 83 x.x * y.y - y.x * x.y); 84 } 85 }; 86 87 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 88 struct compute_normalize 89 { 90 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v) 91 { 92 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs"); 93 94 return v * inversesqrt(dot(v, v)); 95 } 96 }; 97 98 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 99 struct compute_faceforward 100 { 101 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & N, vecType<T, P> const & I, vecType<T, P> const & Nref) 102 { 103 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs"); 104 105 return dot(Nref, I) < static_cast<T>(0) ? N : -N; 106 } 107 }; 108 109 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 110 struct compute_reflect 111 { 112 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & I, vecType<T, P> const & N) 113 { 114 return I - N * dot(N, I) * static_cast<T>(2); 115 } 116 }; 117 118 template <typename T, precision P, template <typename, precision> class vecType, bool Aligned> 119 struct compute_refract 120 { 121 GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & I, vecType<T, P> const & N, T eta) 122 { 123 T const dotValue(dot(N, I)); 124 T const k(static_cast<T>(1) - eta * eta * (static_cast<T>(1) - dotValue * dotValue)); 125 return (eta * I - (eta * dotValue + std::sqrt(k)) * N) * static_cast<T>(k >= static_cast<T>(0)); 126 } 127 }; 128}//namespace detail 129 130 // length 131 template <typename genType> 132 GLM_FUNC_QUALIFIER genType length(genType x) 133 { 134 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' accepts only floating-point inputs"); 135 136 return abs(x); 137 } 138 139 template <typename T, precision P, template <typename, precision> class vecType> 140 GLM_FUNC_QUALIFIER T length(vecType<T, P> const & v) 141 { 142 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' accepts only floating-point inputs"); 143 144 return detail::compute_length<vecType, T, P, detail::is_aligned<P>::value>::call(v); 145 } 146 147 // distance 148 template <typename genType> 149 GLM_FUNC_QUALIFIER genType distance(genType const & p0, genType const & p1) 150 { 151 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' accepts only floating-point inputs"); 152 153 return length(p1 - p0); 154 } 155 156 template <typename T, precision P, template <typename, precision> class vecType> 157 GLM_FUNC_QUALIFIER T distance(vecType<T, P> const & p0, vecType<T, P> const & p1) 158 { 159 return detail::compute_distance<vecType, T, P, detail::is_aligned<P>::value>::call(p0, p1); 160 } 161 162 // dot 163 template <typename T> 164 GLM_FUNC_QUALIFIER T dot(T x, T y) 165 { 166 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs"); 167 return x * y; 168 } 169 170 template <typename T, precision P, template <typename, precision> class vecType> 171 GLM_FUNC_QUALIFIER T dot(vecType<T, P> const & x, vecType<T, P> const & y) 172 { 173 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' accepts only floating-point inputs"); 174 return detail::compute_dot<vecType, T, P, detail::is_aligned<P>::value>::call(x, y); 175 } 176 177 // cross 178 template <typename T, precision P> 179 GLM_FUNC_QUALIFIER tvec3<T, P> cross(tvec3<T, P> const & x, tvec3<T, P> const & y) 180 { 181 return detail::compute_cross<T, P, detail::is_aligned<P>::value>::call(x, y); 182 } 183 184 // normalize 185 template <typename genType> 186 GLM_FUNC_QUALIFIER genType normalize(genType const & x) 187 { 188 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' accepts only floating-point inputs"); 189 190 return x < genType(0) ? genType(-1) : genType(1); 191 } 192 193 template <typename T, precision P, template <typename, precision> class vecType> 194 GLM_FUNC_QUALIFIER vecType<T, P> normalize(vecType<T, P> const & x) 195 { 196 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' accepts only floating-point inputs"); 197 198 return detail::compute_normalize<T, P, vecType, detail::is_aligned<P>::value>::call(x); 199 } 200 201 // faceforward 202 template <typename genType> 203 GLM_FUNC_QUALIFIER genType faceforward(genType const & N, genType const & I, genType const & Nref) 204 { 205 return dot(Nref, I) < static_cast<genType>(0) ? N : -N; 206 } 207 208 template <typename T, precision P, template <typename, precision> class vecType> 209 GLM_FUNC_QUALIFIER vecType<T, P> faceforward(vecType<T, P> const & N, vecType<T, P> const & I, vecType<T, P> const & Nref) 210 { 211 return detail::compute_faceforward<T, P, vecType, detail::is_aligned<P>::value>::call(N, I, Nref); 212 } 213 214 // reflect 215 template <typename genType> 216 GLM_FUNC_QUALIFIER genType reflect(genType const & I, genType const & N) 217 { 218 return I - N * dot(N, I) * genType(2); 219 } 220 221 template <typename T, precision P, template <typename, precision> class vecType> 222 GLM_FUNC_QUALIFIER vecType<T, P> reflect(vecType<T, P> const & I, vecType<T, P> const & N) 223 { 224 return detail::compute_reflect<T, P, vecType, detail::is_aligned<P>::value>::call(I, N); 225 } 226 227 // refract 228 template <typename genType> 229 GLM_FUNC_QUALIFIER genType refract(genType const & I, genType const & N, genType eta) 230 { 231 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' accepts only floating-point inputs"); 232 genType const dotValue(dot(N, I)); 233 genType const k(static_cast<genType>(1) - eta * eta * (static_cast<genType>(1) - dotValue * dotValue)); 234 return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast<genType>(k >= static_cast<genType>(0)); 235 } 236 237 template <typename T, precision P, template <typename, precision> class vecType> 238 GLM_FUNC_QUALIFIER vecType<T, P> refract(vecType<T, P> const & I, vecType<T, P> const & N, T eta) 239 { 240 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' accepts only floating-point inputs"); 241 return detail::compute_refract<T, P, vecType, detail::is_aligned<P>::value>::call(I, N, eta); 242 } 243}//namespace glm 244 245#if GLM_ARCH != GLM_ARCH_PURE && GLM_HAS_UNRESTRICTED_UNIONS 246# include "func_geometric_simd.inl" 247#endif 248