• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/// @ref gtc_matrix_transform
2/// @file glm/gtc/matrix_transform.inl
3
4#include "../geometric.hpp"
5#include "../trigonometric.hpp"
6#include "../matrix.hpp"
7
8namespace glm
9{
10	template <typename T, precision P>
11	GLM_FUNC_QUALIFIER tmat4x4<T, P> translate(tmat4x4<T, P> const & m, tvec3<T, P> const & v)
12	{
13		tmat4x4<T, P> Result(m);
14		Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3];
15		return Result;
16	}
17
18	template <typename T, precision P>
19	GLM_FUNC_QUALIFIER tmat4x4<T, P> rotate(tmat4x4<T, P> const & m, T angle, tvec3<T, P> const & v)
20	{
21		T const a = angle;
22		T const c = cos(a);
23		T const s = sin(a);
24
25		tvec3<T, P> axis(normalize(v));
26		tvec3<T, P> temp((T(1) - c) * axis);
27
28		tmat4x4<T, P> Rotate(uninitialize);
29		Rotate[0][0] = c + temp[0] * axis[0];
30		Rotate[0][1] = temp[0] * axis[1] + s * axis[2];
31		Rotate[0][2] = temp[0] * axis[2] - s * axis[1];
32
33		Rotate[1][0] = temp[1] * axis[0] - s * axis[2];
34		Rotate[1][1] = c + temp[1] * axis[1];
35		Rotate[1][2] = temp[1] * axis[2] + s * axis[0];
36
37		Rotate[2][0] = temp[2] * axis[0] + s * axis[1];
38		Rotate[2][1] = temp[2] * axis[1] - s * axis[0];
39		Rotate[2][2] = c + temp[2] * axis[2];
40
41		tmat4x4<T, P> Result(uninitialize);
42		Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2];
43		Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2];
44		Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2];
45		Result[3] = m[3];
46		return Result;
47	}
48
49	template <typename T, precision P>
50	GLM_FUNC_QUALIFIER tmat4x4<T, P> rotate_slow(tmat4x4<T, P> const & m, T angle, tvec3<T, P> const & v)
51	{
52		T const a = angle;
53		T const c = cos(a);
54		T const s = sin(a);
55		tmat4x4<T, P> Result;
56
57		tvec3<T, P> axis = normalize(v);
58
59		Result[0][0] = c + (static_cast<T>(1) - c)      * axis.x     * axis.x;
60		Result[0][1] = (static_cast<T>(1) - c) * axis.x * axis.y + s * axis.z;
61		Result[0][2] = (static_cast<T>(1) - c) * axis.x * axis.z - s * axis.y;
62		Result[0][3] = static_cast<T>(0);
63
64		Result[1][0] = (static_cast<T>(1) - c) * axis.y * axis.x - s * axis.z;
65		Result[1][1] = c + (static_cast<T>(1) - c) * axis.y * axis.y;
66		Result[1][2] = (static_cast<T>(1) - c) * axis.y * axis.z + s * axis.x;
67		Result[1][3] = static_cast<T>(0);
68
69		Result[2][0] = (static_cast<T>(1) - c) * axis.z * axis.x + s * axis.y;
70		Result[2][1] = (static_cast<T>(1) - c) * axis.z * axis.y - s * axis.x;
71		Result[2][2] = c + (static_cast<T>(1) - c) * axis.z * axis.z;
72		Result[2][3] = static_cast<T>(0);
73
74		Result[3] = tvec4<T, P>(0, 0, 0, 1);
75		return m * Result;
76	}
77
78	template <typename T, precision P>
79	GLM_FUNC_QUALIFIER tmat4x4<T, P> scale(tmat4x4<T, P> const & m, tvec3<T, P> const & v)
80	{
81		tmat4x4<T, P> Result(uninitialize);
82		Result[0] = m[0] * v[0];
83		Result[1] = m[1] * v[1];
84		Result[2] = m[2] * v[2];
85		Result[3] = m[3];
86		return Result;
87	}
88
89	template <typename T, precision P>
90	GLM_FUNC_QUALIFIER tmat4x4<T, P> scale_slow(tmat4x4<T, P> const & m, tvec3<T, P> const & v)
91	{
92		tmat4x4<T, P> Result(T(1));
93		Result[0][0] = v.x;
94		Result[1][1] = v.y;
95		Result[2][2] = v.z;
96		return m * Result;
97	}
98
99	template <typename T>
100	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> ortho
101	(
102		T left, T right,
103		T bottom, T top,
104		T zNear, T zFar
105	)
106	{
107#		if GLM_COORDINATE_SYSTEM == GLM_LEFT_HANDED
108			return orthoLH(left, right, bottom, top, zNear, zFar);
109#		else
110			return orthoRH(left, right, bottom, top, zNear, zFar);
111#		endif
112	}
113
114	template <typename T>
115	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> orthoLH
116	(
117		T left, T right,
118		T bottom, T top,
119		T zNear, T zFar
120	)
121	{
122		tmat4x4<T, defaultp> Result(1);
123		Result[0][0] = static_cast<T>(2) / (right - left);
124		Result[1][1] = static_cast<T>(2) / (top - bottom);
125		Result[3][0] = - (right + left) / (right - left);
126		Result[3][1] = - (top + bottom) / (top - bottom);
127
128#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
129			Result[2][2] = static_cast<T>(1) / (zFar - zNear);
130			Result[3][2] = - zNear / (zFar - zNear);
131#		else
132			Result[2][2] = static_cast<T>(2) / (zFar - zNear);
133			Result[3][2] = - (zFar + zNear) / (zFar - zNear);
134#		endif
135
136		return Result;
137	}
138
139	template <typename T>
140	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> orthoRH
141	(
142		T left, T right,
143		T bottom, T top,
144		T zNear, T zFar
145	)
146	{
147		tmat4x4<T, defaultp> Result(1);
148		Result[0][0] = static_cast<T>(2) / (right - left);
149		Result[1][1] = static_cast<T>(2) / (top - bottom);
150		Result[3][0] = - (right + left) / (right - left);
151		Result[3][1] = - (top + bottom) / (top - bottom);
152
153#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
154			Result[2][2] = - static_cast<T>(1) / (zFar - zNear);
155			Result[3][2] = - zNear / (zFar - zNear);
156#		else
157			Result[2][2] = - static_cast<T>(2) / (zFar - zNear);
158			Result[3][2] = - (zFar + zNear) / (zFar - zNear);
159#		endif
160
161		return Result;
162	}
163
164	template <typename T>
165	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> ortho
166	(
167		T left, T right,
168		T bottom, T top
169	)
170	{
171		tmat4x4<T, defaultp> Result(static_cast<T>(1));
172		Result[0][0] = static_cast<T>(2) / (right - left);
173		Result[1][1] = static_cast<T>(2) / (top - bottom);
174		Result[2][2] = - static_cast<T>(1);
175		Result[3][0] = - (right + left) / (right - left);
176		Result[3][1] = - (top + bottom) / (top - bottom);
177		return Result;
178	}
179
180	template <typename T>
181	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> frustum
182	(
183		T left, T right,
184		T bottom, T top,
185		T nearVal, T farVal
186	)
187	{
188#		if GLM_COORDINATE_SYSTEM == GLM_LEFT_HANDED
189			return frustumLH(left, right, bottom, top, nearVal, farVal);
190#		else
191			return frustumRH(left, right, bottom, top, nearVal, farVal);
192#		endif
193	}
194
195	template <typename T>
196	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> frustumLH
197	(
198		T left, T right,
199		T bottom, T top,
200		T nearVal, T farVal
201	)
202	{
203		tmat4x4<T, defaultp> Result(0);
204		Result[0][0] = (static_cast<T>(2) * nearVal) / (right - left);
205		Result[1][1] = (static_cast<T>(2) * nearVal) / (top - bottom);
206		Result[2][0] = (right + left) / (right - left);
207		Result[2][1] = (top + bottom) / (top - bottom);
208		Result[2][3] = static_cast<T>(1);
209
210#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
211			Result[2][2] = farVal / (farVal - nearVal);
212			Result[3][2] = -(farVal * nearVal) / (farVal - nearVal);
213#		else
214			Result[2][2] = (farVal + nearVal) / (farVal - nearVal);
215			Result[3][2] = - (static_cast<T>(2) * farVal * nearVal) / (farVal - nearVal);
216#		endif
217
218		return Result;
219	}
220
221	template <typename T>
222	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> frustumRH
223	(
224		T left, T right,
225		T bottom, T top,
226		T nearVal, T farVal
227	)
228	{
229		tmat4x4<T, defaultp> Result(0);
230		Result[0][0] = (static_cast<T>(2) * nearVal) / (right - left);
231		Result[1][1] = (static_cast<T>(2) * nearVal) / (top - bottom);
232		Result[2][0] = (right + left) / (right - left);
233		Result[2][1] = (top + bottom) / (top - bottom);
234		Result[2][3] = static_cast<T>(-1);
235
236#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
237			Result[2][2] = farVal / (nearVal - farVal);
238			Result[3][2] = -(farVal * nearVal) / (farVal - nearVal);
239#		else
240			Result[2][2] = - (farVal + nearVal) / (farVal - nearVal);
241			Result[3][2] = - (static_cast<T>(2) * farVal * nearVal) / (farVal - nearVal);
242#		endif
243
244		return Result;
245	}
246
247	template <typename T>
248	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspective(T fovy, T aspect, T zNear, T zFar)
249	{
250#		if GLM_COORDINATE_SYSTEM == GLM_LEFT_HANDED
251			return perspectiveLH(fovy, aspect, zNear, zFar);
252#		else
253			return perspectiveRH(fovy, aspect, zNear, zFar);
254#		endif
255	}
256
257	template <typename T>
258	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspectiveRH(T fovy, T aspect, T zNear, T zFar)
259	{
260		assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0));
261
262		T const tanHalfFovy = tan(fovy / static_cast<T>(2));
263
264		tmat4x4<T, defaultp> Result(static_cast<T>(0));
265		Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy);
266		Result[1][1] = static_cast<T>(1) / (tanHalfFovy);
267		Result[2][3] = - static_cast<T>(1);
268
269#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
270			Result[2][2] = zFar / (zNear - zFar);
271			Result[3][2] = -(zFar * zNear) / (zFar - zNear);
272#		else
273			Result[2][2] = - (zFar + zNear) / (zFar - zNear);
274			Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear);
275#		endif
276
277		return Result;
278	}
279
280	template <typename T>
281	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspectiveLH(T fovy, T aspect, T zNear, T zFar)
282	{
283		assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0));
284
285		T const tanHalfFovy = tan(fovy / static_cast<T>(2));
286
287		tmat4x4<T, defaultp> Result(static_cast<T>(0));
288		Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy);
289		Result[1][1] = static_cast<T>(1) / (tanHalfFovy);
290		Result[2][3] = static_cast<T>(1);
291
292#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
293			Result[2][2] = zFar / (zFar - zNear);
294			Result[3][2] = -(zFar * zNear) / (zFar - zNear);
295#		else
296			Result[2][2] = (zFar + zNear) / (zFar - zNear);
297			Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear);
298#		endif
299
300		return Result;
301	}
302
303	template <typename T>
304	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspectiveFov(T fov, T width, T height, T zNear, T zFar)
305	{
306#		if GLM_COORDINATE_SYSTEM == GLM_LEFT_HANDED
307			return perspectiveFovLH(fov, width, height, zNear, zFar);
308#		else
309			return perspectiveFovRH(fov, width, height, zNear, zFar);
310#		endif
311	}
312
313	template <typename T>
314	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspectiveFovRH(T fov, T width, T height, T zNear, T zFar)
315	{
316		assert(width > static_cast<T>(0));
317		assert(height > static_cast<T>(0));
318		assert(fov > static_cast<T>(0));
319
320		T const rad = fov;
321		T const h = glm::cos(static_cast<T>(0.5) * rad) / glm::sin(static_cast<T>(0.5) * rad);
322		T const w = h * height / width; ///todo max(width , Height) / min(width , Height)?
323
324		tmat4x4<T, defaultp> Result(static_cast<T>(0));
325		Result[0][0] = w;
326		Result[1][1] = h;
327		Result[2][3] = - static_cast<T>(1);
328
329#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
330			Result[2][2] = zFar / (zNear - zFar);
331			Result[3][2] = -(zFar * zNear) / (zFar - zNear);
332#		else
333			Result[2][2] = - (zFar + zNear) / (zFar - zNear);
334			Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear);
335#		endif
336
337		return Result;
338	}
339
340	template <typename T>
341	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspectiveFovLH(T fov, T width, T height, T zNear, T zFar)
342	{
343		assert(width > static_cast<T>(0));
344		assert(height > static_cast<T>(0));
345		assert(fov > static_cast<T>(0));
346
347		T const rad = fov;
348		T const h = glm::cos(static_cast<T>(0.5) * rad) / glm::sin(static_cast<T>(0.5) * rad);
349		T const w = h * height / width; ///todo max(width , Height) / min(width , Height)?
350
351		tmat4x4<T, defaultp> Result(static_cast<T>(0));
352		Result[0][0] = w;
353		Result[1][1] = h;
354		Result[2][3] = static_cast<T>(1);
355
356#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
357			Result[2][2] = zFar / (zFar - zNear);
358			Result[3][2] = -(zFar * zNear) / (zFar - zNear);
359#		else
360			Result[2][2] = (zFar + zNear) / (zFar - zNear);
361			Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear);
362#		endif
363
364		return Result;
365	}
366
367	template <typename T>
368	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> infinitePerspective(T fovy, T aspect, T zNear)
369	{
370#		if GLM_COORDINATE_SYSTEM == GLM_LEFT_HANDED
371			return infinitePerspectiveLH(fovy, aspect, zNear);
372#		else
373			return infinitePerspectiveRH(fovy, aspect, zNear);
374#		endif
375	}
376
377	template <typename T>
378	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> infinitePerspectiveRH(T fovy, T aspect, T zNear)
379	{
380		T const range = tan(fovy / static_cast<T>(2)) * zNear;
381		T const left = -range * aspect;
382		T const right = range * aspect;
383		T const bottom = -range;
384		T const top = range;
385
386		tmat4x4<T, defaultp> Result(static_cast<T>(0));
387		Result[0][0] = (static_cast<T>(2) * zNear) / (right - left);
388		Result[1][1] = (static_cast<T>(2) * zNear) / (top - bottom);
389		Result[2][2] = - static_cast<T>(1);
390		Result[2][3] = - static_cast<T>(1);
391		Result[3][2] = - static_cast<T>(2) * zNear;
392		return Result;
393	}
394
395	template <typename T>
396	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> infinitePerspectiveLH(T fovy, T aspect, T zNear)
397	{
398		T const range = tan(fovy / static_cast<T>(2)) * zNear;
399		T const left = -range * aspect;
400		T const right = range * aspect;
401		T const bottom = -range;
402		T const top = range;
403
404		tmat4x4<T, defaultp> Result(T(0));
405		Result[0][0] = (static_cast<T>(2) * zNear) / (right - left);
406		Result[1][1] = (static_cast<T>(2) * zNear) / (top - bottom);
407		Result[2][2] = static_cast<T>(1);
408		Result[2][3] = static_cast<T>(1);
409		Result[3][2] = - static_cast<T>(2) * zNear;
410		return Result;
411	}
412
413	// Infinite projection matrix: http://www.terathon.com/gdc07_lengyel.pdf
414	template <typename T>
415	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear, T ep)
416	{
417		T const range = tan(fovy / static_cast<T>(2)) * zNear;
418		T const left = -range * aspect;
419		T const right = range * aspect;
420		T const bottom = -range;
421		T const top = range;
422
423		tmat4x4<T, defaultp> Result(static_cast<T>(0));
424		Result[0][0] = (static_cast<T>(2) * zNear) / (right - left);
425		Result[1][1] = (static_cast<T>(2) * zNear) / (top - bottom);
426		Result[2][2] = ep - static_cast<T>(1);
427		Result[2][3] = static_cast<T>(-1);
428		Result[3][2] = (ep - static_cast<T>(2)) * zNear;
429		return Result;
430	}
431
432	template <typename T>
433	GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> tweakedInfinitePerspective(T fovy, T aspect, T zNear)
434	{
435		return tweakedInfinitePerspective(fovy, aspect, zNear, epsilon<T>());
436	}
437
438	template <typename T, typename U, precision P>
439	GLM_FUNC_QUALIFIER tvec3<T, P> project
440	(
441		tvec3<T, P> const & obj,
442		tmat4x4<T, P> const & model,
443		tmat4x4<T, P> const & proj,
444		tvec4<U, P> const & viewport
445	)
446	{
447		tvec4<T, P> tmp = tvec4<T, P>(obj, static_cast<T>(1));
448		tmp = model * tmp;
449		tmp = proj * tmp;
450
451		tmp /= tmp.w;
452#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
453			tmp.x = tmp.x * static_cast<T>(0.5) + static_cast<T>(0.5);
454			tmp.y = tmp.y * static_cast<T>(0.5) + static_cast<T>(0.5);
455#		else
456			tmp = tmp * static_cast<T>(0.5) + static_cast<T>(0.5);
457#		endif
458		tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]);
459		tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]);
460
461		return tvec3<T, P>(tmp);
462	}
463
464	template <typename T, typename U, precision P>
465	GLM_FUNC_QUALIFIER tvec3<T, P> unProject
466	(
467		tvec3<T, P> const & win,
468		tmat4x4<T, P> const & model,
469		tmat4x4<T, P> const & proj,
470		tvec4<U, P> const & viewport
471	)
472	{
473		tmat4x4<T, P> Inverse = inverse(proj * model);
474
475		tvec4<T, P> tmp = tvec4<T, P>(win, T(1));
476		tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]);
477		tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]);
478#		if GLM_DEPTH_CLIP_SPACE == GLM_DEPTH_ZERO_TO_ONE
479			tmp.x = tmp.x * static_cast<T>(2) - static_cast<T>(1);
480			tmp.y = tmp.y * static_cast<T>(2) - static_cast<T>(1);
481#		else
482			tmp = tmp * static_cast<T>(2) - static_cast<T>(1);
483#		endif
484
485		tvec4<T, P> obj = Inverse * tmp;
486		obj /= obj.w;
487
488		return tvec3<T, P>(obj);
489	}
490
491	template <typename T, precision P, typename U>
492	GLM_FUNC_QUALIFIER tmat4x4<T, P> pickMatrix(tvec2<T, P> const & center, tvec2<T, P> const & delta, tvec4<U, P> const & viewport)
493	{
494		assert(delta.x > static_cast<T>(0) && delta.y > static_cast<T>(0));
495		tmat4x4<T, P> Result(static_cast<T>(1));
496
497		if(!(delta.x > static_cast<T>(0) && delta.y > static_cast<T>(0)))
498			return Result; // Error
499
500		tvec3<T, P> Temp(
501			(static_cast<T>(viewport[2]) - static_cast<T>(2) * (center.x - static_cast<T>(viewport[0]))) / delta.x,
502			(static_cast<T>(viewport[3]) - static_cast<T>(2) * (center.y - static_cast<T>(viewport[1]))) / delta.y,
503			static_cast<T>(0));
504
505		// Translate and scale the picked region to the entire window
506		Result = translate(Result, Temp);
507		return scale(Result, tvec3<T, P>(static_cast<T>(viewport[2]) / delta.x, static_cast<T>(viewport[3]) / delta.y, static_cast<T>(1)));
508	}
509
510	template <typename T, precision P>
511	GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAt(tvec3<T, P> const & eye, tvec3<T, P> const & center, tvec3<T, P> const & up)
512	{
513#		if GLM_COORDINATE_SYSTEM == GLM_LEFT_HANDED
514			return lookAtLH(eye, center, up);
515#		else
516			return lookAtRH(eye, center, up);
517#		endif
518	}
519
520	template <typename T, precision P>
521	GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAtRH
522	(
523		tvec3<T, P> const & eye,
524		tvec3<T, P> const & center,
525		tvec3<T, P> const & up
526	)
527	{
528		tvec3<T, P> const f(normalize(center - eye));
529		tvec3<T, P> const s(normalize(cross(f, up)));
530		tvec3<T, P> const u(cross(s, f));
531
532		tmat4x4<T, P> Result(1);
533		Result[0][0] = s.x;
534		Result[1][0] = s.y;
535		Result[2][0] = s.z;
536		Result[0][1] = u.x;
537		Result[1][1] = u.y;
538		Result[2][1] = u.z;
539		Result[0][2] =-f.x;
540		Result[1][2] =-f.y;
541		Result[2][2] =-f.z;
542		Result[3][0] =-dot(s, eye);
543		Result[3][1] =-dot(u, eye);
544		Result[3][2] = dot(f, eye);
545		return Result;
546	}
547
548	template <typename T, precision P>
549	GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAtLH
550	(
551		tvec3<T, P> const & eye,
552		tvec3<T, P> const & center,
553		tvec3<T, P> const & up
554	)
555	{
556		tvec3<T, P> const f(normalize(center - eye));
557		tvec3<T, P> const s(normalize(cross(up, f)));
558		tvec3<T, P> const u(cross(f, s));
559
560		tmat4x4<T, P> Result(1);
561		Result[0][0] = s.x;
562		Result[1][0] = s.y;
563		Result[2][0] = s.z;
564		Result[0][1] = u.x;
565		Result[1][1] = u.y;
566		Result[2][1] = u.z;
567		Result[0][2] = f.x;
568		Result[1][2] = f.y;
569		Result[2][2] = f.z;
570		Result[3][0] = -dot(s, eye);
571		Result[3][1] = -dot(u, eye);
572		Result[3][2] = -dot(f, eye);
573		return Result;
574	}
575}//namespace glm
576