1/////////////////////////////////////////////////////////////////////////////////// 2/// OpenGL Mathematics (glm.g-truc.net) 3/// 4/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) 5/// Permission is hereby granted, free of charge, to any person obtaining a copy 6/// of this software and associated documentation files (the "Software"), to deal 7/// in the Software without restriction, including without limitation the rights 8/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9/// copies of the Software, and to permit persons to whom the Software is 10/// furnished to do so, subject to the following conditions: 11/// 12/// The above copyright notice and this permission notice shall be included in 13/// all copies or substantial portions of the Software. 14/// 15/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21/// THE SOFTWARE. 22/// 23/// @ref core 24/// @file glm/core/func_geometric.inl 25/// @date 2008-08-03 / 2011-06-15 26/// @author Christophe Riccio 27/////////////////////////////////////////////////////////////////////////////////// 28 29#include "func_exponential.hpp" 30#include "func_common.hpp" 31#include "type_vec2.hpp" 32#include "type_vec4.hpp" 33#include "type_float.hpp" 34 35namespace glm{ 36namespace detail 37{ 38 template <template <class, precision> class vecType, typename T, precision P> 39 struct compute_dot{}; 40 41 template <typename T, precision P> 42 struct compute_dot<detail::tvec1, T, P> 43 { 44 GLM_FUNC_QUALIFIER static T call(detail::tvec1<T, P> const & x, detail::tvec1<T, P> const & y) 45 { 46# ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6 47 detail::tvec1<T, P> tmp(x * y); 48 return tmp.x; 49# else 50 return detail::tvec1<T, P>(x * y).x; 51# endif 52 } 53 }; 54 55 template <typename T, precision P> 56 struct compute_dot<detail::tvec2, T, P> 57 { 58 GLM_FUNC_QUALIFIER static T call(detail::tvec2<T, P> const & x, detail::tvec2<T, P> const & y) 59 { 60 detail::tvec2<T, P> tmp(x * y); 61 return tmp.x + tmp.y; 62 } 63 }; 64 65 template <typename T, precision P> 66 struct compute_dot<detail::tvec3, T, P> 67 { 68 GLM_FUNC_QUALIFIER static T call(detail::tvec3<T, P> const & x, detail::tvec3<T, P> const & y) 69 { 70 detail::tvec3<T, P> tmp(x * y); 71 return tmp.x + tmp.y + tmp.z; 72 } 73 }; 74 75 template <typename T, precision P> 76 struct compute_dot<detail::tvec4, T, P> 77 { 78 GLM_FUNC_QUALIFIER static T call(detail::tvec4<T, P> const & x, detail::tvec4<T, P> const & y) 79 { 80 detail::tvec4<T, P> tmp(x * y); 81 return (tmp.x + tmp.y) + (tmp.z + tmp.w); 82 } 83 }; 84}//namespace detail 85 86 // length 87 template <typename genType> 88 GLM_FUNC_QUALIFIER genType length 89 ( 90 genType const & x 91 ) 92 { 93 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' only accept floating-point inputs"); 94 95 genType sqr = x * x; 96 return sqrt(sqr); 97 } 98 99 template <typename T, precision P> 100 GLM_FUNC_QUALIFIER T length(detail::tvec2<T, P> const & v) 101 { 102 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs"); 103 104 T sqr = v.x * v.x + v.y * v.y; 105 return sqrt(sqr); 106 } 107 108 template <typename T, precision P> 109 GLM_FUNC_QUALIFIER T length(detail::tvec3<T, P> const & v) 110 { 111 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs"); 112 113 T sqr = v.x * v.x + v.y * v.y + v.z * v.z; 114 return sqrt(sqr); 115 } 116 117 template <typename T, precision P> 118 GLM_FUNC_QUALIFIER T length(detail::tvec4<T, P> const & v) 119 { 120 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs"); 121 122 T sqr = v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w; 123 return sqrt(sqr); 124 } 125 126 // distance 127 template <typename genType> 128 GLM_FUNC_QUALIFIER genType distance 129 ( 130 genType const & p0, 131 genType const & p1 132 ) 133 { 134 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' only accept floating-point inputs"); 135 136 return length(p1 - p0); 137 } 138 139 template <typename T, precision P> 140 GLM_FUNC_QUALIFIER T distance 141 ( 142 detail::tvec2<T, P> const & p0, 143 detail::tvec2<T, P> const & p1 144 ) 145 { 146 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs"); 147 148 return length(p1 - p0); 149 } 150 151 template <typename T, precision P> 152 GLM_FUNC_QUALIFIER T distance 153 ( 154 detail::tvec3<T, P> const & p0, 155 detail::tvec3<T, P> const & p1 156 ) 157 { 158 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs"); 159 160 return length(p1 - p0); 161 } 162 163 template <typename T, precision P> 164 GLM_FUNC_QUALIFIER T distance 165 ( 166 detail::tvec4<T, P> const & p0, 167 detail::tvec4<T, P> const & p1 168 ) 169 { 170 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'distance' only accept floating-point inputs"); 171 172 return length(p1 - p0); 173 } 174 175 // dot 176 template <typename T> 177 GLM_FUNC_QUALIFIER T dot 178 ( 179 T const & x, 180 T const & y 181 ) 182 { 183 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs"); 184 return detail::compute_dot<detail::tvec1, T, highp>::call(x, y); 185 } 186 187 template <typename T, precision P, template <typename, precision> class vecType> 188 GLM_FUNC_QUALIFIER T dot 189 ( 190 vecType<T, P> const & x, 191 vecType<T, P> const & y 192 ) 193 { 194 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs"); 195 return detail::compute_dot<vecType, T, P>::call(x, y); 196 } 197 198/* // SSE3 199 GLM_FUNC_QUALIFIER float dot(const tvec4<float>& x, const tvec4<float>& y) 200 { 201 float Result; 202 __asm 203 { 204 mov esi, x 205 mov edi, y 206 movaps xmm0, [esi] 207 mulps xmm0, [edi] 208 haddps( _xmm0, _xmm0 ) 209 haddps( _xmm0, _xmm0 ) 210 movss Result, xmm0 211 } 212 return Result; 213 } 214*/ 215 // cross 216 template <typename T, precision P> 217 GLM_FUNC_QUALIFIER detail::tvec3<T, P> cross 218 ( 219 detail::tvec3<T, P> const & x, 220 detail::tvec3<T, P> const & y 221 ) 222 { 223 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' only accept floating-point inputs"); 224 225 return detail::tvec3<T, P>( 226 x.y * y.z - y.y * x.z, 227 x.z * y.x - y.z * x.x, 228 x.x * y.y - y.x * x.y); 229 } 230 231 // normalize 232 template <typename genType> 233 GLM_FUNC_QUALIFIER genType normalize 234 ( 235 genType const & x 236 ) 237 { 238 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' only accept floating-point inputs"); 239 240 return x < genType(0) ? genType(-1) : genType(1); 241 } 242 243 // According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefine and generate an error 244 template <typename T, precision P> 245 GLM_FUNC_QUALIFIER detail::tvec2<T, P> normalize 246 ( 247 detail::tvec2<T, P> const & x 248 ) 249 { 250 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs"); 251 252 T sqr = x.x * x.x + x.y * x.y; 253 return x * inversesqrt(sqr); 254 } 255 256 template <typename T, precision P> 257 GLM_FUNC_QUALIFIER detail::tvec3<T, P> normalize 258 ( 259 detail::tvec3<T, P> const & x 260 ) 261 { 262 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs"); 263 264 T sqr = x.x * x.x + x.y * x.y + x.z * x.z; 265 return x * inversesqrt(sqr); 266 } 267 268 template <typename T, precision P> 269 GLM_FUNC_QUALIFIER detail::tvec4<T, P> normalize 270 ( 271 detail::tvec4<T, P> const & x 272 ) 273 { 274 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs"); 275 276 T sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w; 277 return x * inversesqrt(sqr); 278 } 279 280 // faceforward 281 template <typename genType> 282 GLM_FUNC_QUALIFIER genType faceforward 283 ( 284 genType const & N, 285 genType const & I, 286 genType const & Nref 287 ) 288 { 289 return dot(Nref, I) < 0 ? N : -N; 290 } 291 292 // reflect 293 template <typename genType> 294 GLM_FUNC_QUALIFIER genType reflect 295 ( 296 genType const & I, 297 genType const & N 298 ) 299 { 300 return I - N * dot(N, I) * genType(2); 301 } 302 303 // refract 304 template <typename genType> 305 GLM_FUNC_QUALIFIER genType refract 306 ( 307 genType const & I, 308 genType const & N, 309 genType const & eta 310 ) 311 { 312 GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' only accept floating-point inputs"); 313 314 genType dotValue = dot(N, I); 315 genType k = genType(1) - eta * eta * (genType(1) - dotValue * dotValue); 316 if(k < genType(0)) 317 return genType(0); 318 else 319 return eta * I - (eta * dotValue + sqrt(k)) * N; 320 } 321 322 template <typename T, precision P, template <typename, precision> class vecType> 323 GLM_FUNC_QUALIFIER vecType<T, P> refract 324 ( 325 vecType<T, P> const & I, 326 vecType<T, P> const & N, 327 T const & eta 328 ) 329 { 330 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' only accept floating-point inputs"); 331 332 T dotValue = dot(N, I); 333 T k = T(1) - eta * eta * (T(1) - dotValue * dotValue); 334 if(k < T(0)) 335 return vecType<T, P>(0); 336 else 337 return eta * I - (eta * dotValue + std::sqrt(k)) * N; 338 } 339 340}//namespace glm 341