Home | History | Annotate | Download | only in gtc
      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 
     33 namespace 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