• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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