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 gtc_matrix_transform 24/// @file glm/gtc/matrix_transform.inl 25/// @date 2009-04-29 / 2011-06-15 26/// @author Christophe Riccio 27/////////////////////////////////////////////////////////////////////////////////// 28 29#include "../geometric.hpp" 30#include "../trigonometric.hpp" 31#include "../matrix.hpp" 32 33namespace glm 34{ 35 template <typename T, precision P> 36 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> translate 37 ( 38 detail::tmat4x4<T, P> const & m, 39 detail::tvec3<T, P> const & v 40 ) 41 { 42 detail::tmat4x4<T, P> Result(m); 43 Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3]; 44 return Result; 45 } 46 47 template <typename T, precision P> 48 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> rotate 49 ( 50 detail::tmat4x4<T, P> const & m, 51 T const & angle, 52 detail::tvec3<T, P> const & v 53 ) 54 { 55#ifdef GLM_FORCE_RADIANS 56 T a = angle; 57#else 58# pragma message("GLM: rotate function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 59 T a = radians(angle); 60#endif 61 T c = cos(a); 62 T s = sin(a); 63 64 detail::tvec3<T, P> axis(normalize(v)); 65 detail::tvec3<T, P> temp((T(1) - c) * axis); 66 67 detail::tmat4x4<T, P> Rotate(detail::tmat4x4<T, P>::_null); 68 Rotate[0][0] = c + temp[0] * axis[0]; 69 Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; 70 Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; 71 72 Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; 73 Rotate[1][1] = c + temp[1] * axis[1]; 74 Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; 75 76 Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; 77 Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; 78 Rotate[2][2] = c + temp[2] * axis[2]; 79 80 detail::tmat4x4<T, P> Result(detail::tmat4x4<T, P>::_null); 81 Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; 82 Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; 83 Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; 84 Result[3] = m[3]; 85 return Result; 86 } 87 88 template <typename T, precision P> 89 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> rotate_slow 90 ( 91 detail::tmat4x4<T, P> const & m, 92 T const & angle, 93 detail::tvec3<T, P> const & v 94 ) 95 { 96#ifdef GLM_FORCE_RADIANS 97 T const a = angle; 98#else 99# pragma message("GLM: rotate_slow function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 100 T const a = radians(angle); 101#endif 102 T c = cos(a); 103 T s = sin(a); 104 detail::tmat4x4<T, P> Result; 105 106 detail::tvec3<T, P> axis = normalize(v); 107 108 Result[0][0] = c + (1 - c) * axis.x * axis.x; 109 Result[0][1] = (1 - c) * axis.x * axis.y + s * axis.z; 110 Result[0][2] = (1 - c) * axis.x * axis.z - s * axis.y; 111 Result[0][3] = 0; 112 113 Result[1][0] = (1 - c) * axis.y * axis.x - s * axis.z; 114 Result[1][1] = c + (1 - c) * axis.y * axis.y; 115 Result[1][2] = (1 - c) * axis.y * axis.z + s * axis.x; 116 Result[1][3] = 0; 117 118 Result[2][0] = (1 - c) * axis.z * axis.x + s * axis.y; 119 Result[2][1] = (1 - c) * axis.z * axis.y - s * axis.x; 120 Result[2][2] = c + (1 - c) * axis.z * axis.z; 121 Result[2][3] = 0; 122 123 Result[3] = detail::tvec4<T, P>(0, 0, 0, 1); 124 return m * Result; 125 } 126 127 template <typename T, precision P> 128 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> scale 129 ( 130 detail::tmat4x4<T, P> const & m, 131 detail::tvec3<T, P> const & v 132 ) 133 { 134 detail::tmat4x4<T, P> Result(detail::tmat4x4<T, P>::_null); 135 Result[0] = m[0] * v[0]; 136 Result[1] = m[1] * v[1]; 137 Result[2] = m[2] * v[2]; 138 Result[3] = m[3]; 139 return Result; 140 } 141 142 template <typename T, precision P> 143 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> scale_slow 144 ( 145 detail::tmat4x4<T, P> const & m, 146 detail::tvec3<T, P> const & v 147 ) 148 { 149 detail::tmat4x4<T, P> Result(T(1)); 150 Result[0][0] = v.x; 151 Result[1][1] = v.y; 152 Result[2][2] = v.z; 153 return m * Result; 154 } 155 156 template <typename T> 157 GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> ortho 158 ( 159 T const & left, 160 T const & right, 161 T const & bottom, 162 T const & top, 163 T const & zNear, 164 T const & zFar 165 ) 166 { 167 detail::tmat4x4<T, defaultp> Result(1); 168 Result[0][0] = static_cast<T>(2) / (right - left); 169 Result[1][1] = static_cast<T>(2) / (top - bottom); 170 Result[2][2] = - T(2) / (zFar - zNear); 171 Result[3][0] = - (right + left) / (right - left); 172 Result[3][1] = - (top + bottom) / (top - bottom); 173 Result[3][2] = - (zFar + zNear) / (zFar - zNear); 174 return Result; 175 } 176 177 template <typename T> 178 GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> ortho 179 ( 180 T const & left, 181 T const & right, 182 T const & bottom, 183 T const & top 184 ) 185 { 186 detail::tmat4x4<T, defaultp> Result(1); 187 Result[0][0] = static_cast<T>(2) / (right - left); 188 Result[1][1] = static_cast<T>(2) / (top - bottom); 189 Result[2][2] = - T(1); 190 Result[3][0] = - (right + left) / (right - left); 191 Result[3][1] = - (top + bottom) / (top - bottom); 192 return Result; 193 } 194 195 template <typename valType> 196 GLM_FUNC_QUALIFIER detail::tmat4x4<valType, defaultp> frustum 197 ( 198 valType const & left, 199 valType const & right, 200 valType const & bottom, 201 valType const & top, 202 valType const & nearVal, 203 valType const & farVal 204 ) 205 { 206 detail::tmat4x4<valType, defaultp> Result(0); 207 Result[0][0] = (valType(2) * nearVal) / (right - left); 208 Result[1][1] = (valType(2) * nearVal) / (top - bottom); 209 Result[2][0] = (right + left) / (right - left); 210 Result[2][1] = (top + bottom) / (top - bottom); 211 Result[2][2] = -(farVal + nearVal) / (farVal - nearVal); 212 Result[2][3] = valType(-1); 213 Result[3][2] = -(valType(2) * farVal * nearVal) / (farVal - nearVal); 214 return Result; 215 } 216 217 template <typename valType> 218 GLM_FUNC_QUALIFIER detail::tmat4x4<valType, defaultp> perspective 219 ( 220 valType const & fovy, 221 valType const & aspect, 222 valType const & zNear, 223 valType const & zFar 224 ) 225 { 226 assert(aspect != valType(0)); 227 assert(zFar != zNear); 228 229#ifdef GLM_FORCE_RADIANS 230 valType const rad = fovy; 231#else 232# pragma message("GLM: perspective function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 233 valType const rad = glm::radians(fovy); 234#endif 235 236 valType tanHalfFovy = tan(rad / valType(2)); 237 238 detail::tmat4x4<valType, defaultp> Result(valType(0)); 239 Result[0][0] = valType(1) / (aspect * tanHalfFovy); 240 Result[1][1] = valType(1) / (tanHalfFovy); 241 Result[2][2] = - (zFar + zNear) / (zFar - zNear); 242 Result[2][3] = - valType(1); 243 Result[3][2] = - (valType(2) * zFar * zNear) / (zFar - zNear); 244 return Result; 245 } 246 247 template <typename valType> 248 GLM_FUNC_QUALIFIER detail::tmat4x4<valType, defaultp> perspectiveFov 249 ( 250 valType const & fov, 251 valType const & width, 252 valType const & height, 253 valType const & zNear, 254 valType const & zFar 255 ) 256 { 257 assert(width > valType(0)); 258 assert(height > valType(0)); 259 assert(fov > valType(0)); 260 261#ifdef GLM_FORCE_RADIANS 262 valType rad = fov; 263#else 264# pragma message("GLM: perspectiveFov function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 265 valType rad = glm::radians(fov); 266#endif 267 valType h = glm::cos(valType(0.5) * rad) / glm::sin(valType(0.5) * rad); 268 valType w = h * height / width; ///todo max(width , Height) / min(width , Height)? 269 270 detail::tmat4x4<valType, defaultp> Result(valType(0)); 271 Result[0][0] = w; 272 Result[1][1] = h; 273 Result[2][2] = - (zFar + zNear) / (zFar - zNear); 274 Result[2][3] = - valType(1); 275 Result[3][2] = - (valType(2) * zFar * zNear) / (zFar - zNear); 276 return Result; 277 } 278 279 template <typename T> 280 GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> infinitePerspective 281 ( 282 T fovy, 283 T aspect, 284 T zNear 285 ) 286 { 287#ifdef GLM_FORCE_RADIANS 288 T const range = tan(fovy / T(2)) * zNear; 289#else 290# pragma message("GLM: infinitePerspective function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 291 T const range = tan(radians(fovy / T(2))) * zNear; 292#endif 293 T left = -range * aspect; 294 T right = range * aspect; 295 T bottom = -range; 296 T top = range; 297 298 detail::tmat4x4<T, defaultp> Result(T(0)); 299 Result[0][0] = (T(2) * zNear) / (right - left); 300 Result[1][1] = (T(2) * zNear) / (top - bottom); 301 Result[2][2] = - T(1); 302 Result[2][3] = - T(1); 303 Result[3][2] = - T(2) * zNear; 304 return Result; 305 } 306 307 template <typename T> 308 GLM_FUNC_QUALIFIER detail::tmat4x4<T, defaultp> tweakedInfinitePerspective 309 ( 310 T fovy, 311 T aspect, 312 T zNear 313 ) 314 { 315#ifdef GLM_FORCE_RADIANS 316 T range = tan(fovy / T(2)) * zNear; 317#else 318# pragma message("GLM: tweakedInfinitePerspective function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 319 T range = tan(radians(fovy / T(2))) * zNear; 320#endif 321 T left = -range * aspect; 322 T right = range * aspect; 323 T bottom = -range; 324 T top = range; 325 326 detail::tmat4x4<T, defaultp> Result(T(0)); 327 Result[0][0] = (T(2) * zNear) / (right - left); 328 Result[1][1] = (T(2) * zNear) / (top - bottom); 329 Result[2][2] = static_cast<T>(0.0001) - T(1); 330 Result[2][3] = static_cast<T>(-1); 331 Result[3][2] = - (T(0.0001) - T(2)) * zNear; 332 return Result; 333 } 334 335 template <typename T, typename U, precision P> 336 GLM_FUNC_QUALIFIER detail::tvec3<T, P> project 337 ( 338 detail::tvec3<T, P> const & obj, 339 detail::tmat4x4<T, P> const & model, 340 detail::tmat4x4<T, P> const & proj, 341 detail::tvec4<U, P> const & viewport 342 ) 343 { 344 detail::tvec4<T, P> tmp = detail::tvec4<T, P>(obj, T(1)); 345 tmp = model * tmp; 346 tmp = proj * tmp; 347 348 tmp /= tmp.w; 349 tmp = tmp * T(0.5) + T(0.5); 350 tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]); 351 tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]); 352 353 return detail::tvec3<T, P>(tmp); 354 } 355 356 template <typename T, typename U, precision P> 357 GLM_FUNC_QUALIFIER detail::tvec3<T, P> unProject 358 ( 359 detail::tvec3<T, P> const & win, 360 detail::tmat4x4<T, P> const & model, 361 detail::tmat4x4<T, P> const & proj, 362 detail::tvec4<U, P> const & viewport 363 ) 364 { 365 detail::tmat4x4<T, P> Inverse = inverse(proj * model); 366 367 detail::tvec4<T, P> tmp = detail::tvec4<T, P>(win, T(1)); 368 tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]); 369 tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]); 370 tmp = tmp * T(2) - T(1); 371 372 detail::tvec4<T, P> obj = Inverse * tmp; 373 obj /= obj.w; 374 375 return detail::tvec3<T, P>(obj); 376 } 377 378 template <typename T, precision P, typename U> 379 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> pickMatrix 380 ( 381 detail::tvec2<T, P> const & center, 382 detail::tvec2<T, P> const & delta, 383 detail::tvec4<U, P> const & viewport 384 ) 385 { 386 assert(delta.x > T(0) && delta.y > T(0)); 387 detail::tmat4x4<T, P> Result(1.0f); 388 389 if(!(delta.x > T(0) && delta.y > T(0))) 390 return Result; // Error 391 392 detail::tvec3<T, P> Temp( 393 (T(viewport[2]) - T(2) * (center.x - T(viewport[0]))) / delta.x, 394 (T(viewport[3]) - T(2) * (center.y - T(viewport[1]))) / delta.y, 395 T(0)); 396 397 // Translate and scale the picked region to the entire window 398 Result = translate(Result, Temp); 399 return scale(Result, detail::tvec3<T, P>(T(viewport[2]) / delta.x, T(viewport[3]) / delta.y, T(1))); 400 } 401 402 template <typename T, precision P> 403 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> lookAt 404 ( 405 detail::tvec3<T, P> const & eye, 406 detail::tvec3<T, P> const & center, 407 detail::tvec3<T, P> const & up 408 ) 409 { 410 detail::tvec3<T, P> f(normalize(center - eye)); 411 detail::tvec3<T, P> s(normalize(cross(f, up))); 412 detail::tvec3<T, P> u(cross(s, f)); 413 414 detail::tmat4x4<T, P> Result(1); 415 Result[0][0] = s.x; 416 Result[1][0] = s.y; 417 Result[2][0] = s.z; 418 Result[0][1] = u.x; 419 Result[1][1] = u.y; 420 Result[2][1] = u.z; 421 Result[0][2] =-f.x; 422 Result[1][2] =-f.y; 423 Result[2][2] =-f.z; 424 Result[3][0] =-dot(s, eye); 425 Result[3][1] =-dot(u, eye); 426 Result[3][2] = dot(f, eye); 427 return Result; 428 } 429}//namespace glm 430