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