You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

434 lines
12 KiB

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