]>
Dogcows Code - chaz/yoink/blob - src/cml/mathlib/matrix_projection.h
1 /* -*- C++ -*- ------------------------------------------------------------
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
8 *-----------------------------------------------------------------------*/
13 #ifndef matrix_projection_h
14 #define matrix_projection_h
16 #include <cml/mathlib/checking.h>
17 #include <cml/mathlib/helper.h>
19 /* Functions for building matrix transforms other than rotations
20 * (matrix_rotation.h) and viewing projections (matrix_projection.h).
22 * @todo: Clean up comments and documentation throughout.
25 // NOTE: Changed 'near' and 'far' to 'n' and 'f' throughout to work around
26 // windows.h 'near' and 'far' macros.
30 //////////////////////////////////////////////////////////////////////////////
31 // 3D perspective projection from frustum
32 //////////////////////////////////////////////////////////////////////////////
34 /** Build a matrix representing a perspective projection, specified by frustum
35 * bounds in l,r,b,t,n,f form, and with the given handedness and z clipping
38 template < typename E
, class A
, class B
, class L
> void
39 matrix_perspective(matrix
<E
,A
,B
,L
>& m
, E left
, E right
, E bottom
, E top
,
40 E n
, E f
, Handedness handedness
,
43 typedef matrix
<E
,A
,B
,L
> matrix_type
;
44 typedef typename
matrix_type::value_type value_type
;
47 detail::CheckMatHomogeneous3D(m
);
49 identity_transform(m
);
51 value_type inv_width
= value_type(1) / (right
- left
);
52 value_type inv_height
= value_type(1) / (top
- bottom
);
53 value_type inv_depth
= value_type(1) / (f
- n
);
54 value_type near2
= value_type(2) * n
;
55 value_type s
= handedness
== left_handed
? 1 : -1;
57 if (z_clip
== z_clip_neg_one
) {
58 m
.set_basis_element(2,2,s
* (f
+ n
) * inv_depth
);
59 m
.set_basis_element(3,2,value_type(-2) * f
* n
* inv_depth
);
60 } else { // z_clip == z_clip_zero
61 m
.set_basis_element(2,2,s
* f
* inv_depth
);
62 m
.set_basis_element(3,2,-s
* n
* m
.basis_element(2,2));
65 m
.set_basis_element(0,0,near2
* inv_width
);
66 m
.set_basis_element(1,1,near2
* inv_height
);
67 m
.set_basis_element(2,0,-s
* (right
+ left
) * inv_width
);
68 m
.set_basis_element(2,1,-s
* (top
+ bottom
) * inv_height
);
69 m
.set_basis_element(2,3,s
);
70 m
.set_basis_element(3,3,value_type(0) );
73 /** Build a matrix representing a perspective projection, specified by frustum
74 * bounds in w,h,n,f form, and with the given handedness and z clipping
77 template < typename E
, class A
, class B
, class L
> void
78 matrix_perspective(matrix
<E
,A
,B
,L
>& m
, E width
, E height
, E n
, E f
,
79 Handedness handedness
, ZClip z_clip
)
81 typedef matrix
<E
,A
,B
,L
> matrix_type
;
82 typedef typename
matrix_type::value_type value_type
;
84 value_type half_width
= width
* value_type(.5);
85 value_type half_height
= height
* value_type(.5);
86 matrix_perspective(m
, -half_width
, half_width
,
87 -half_height
, half_height
, n
, f
, handedness
, z_clip
);
90 /** Build a left-handedness frustum perspective matrix */
91 template < typename E
, class A
, class B
, class L
> void
92 matrix_perspective_LH(matrix
<E
,A
,B
,L
>& m
, E left
, E right
, E bottom
,
93 E top
, E n
, E f
, ZClip z_clip
)
95 matrix_perspective(m
, left
, right
, bottom
, top
, n
, f
,
99 /** Build a right-handedness frustum perspective matrix */
100 template < typename E
, class A
, class B
, class L
> void
101 matrix_perspective_RH(matrix
<E
,A
,B
,L
>& m
, E left
, E right
, E bottom
,
102 E top
, E n
, E f
, ZClip z_clip
)
104 matrix_perspective(m
, left
, right
, bottom
, top
, n
, f
,
105 right_handed
, z_clip
);
108 /** Build a left-handedness frustum perspective matrix */
109 template < typename E
, class A
, class B
, class L
> void
110 matrix_perspective_LH(matrix
<E
,A
,B
,L
>& m
, E width
, E height
, E n
,
113 matrix_perspective(m
, width
, height
, n
, f
, left_handed
, z_clip
);
116 /** Build a right-handedness frustum perspective matrix */
117 template < typename E
, class A
, class B
, class L
> void
118 matrix_perspective_RH(matrix
<E
,A
,B
,L
>& m
, E width
, E height
, E n
,
121 matrix_perspective(m
, width
, height
, n
, f
, right_handed
, z_clip
);
124 //////////////////////////////////////////////////////////////////////////////
125 // 3D perspective projection from horizontal field of view
126 //////////////////////////////////////////////////////////////////////////////
128 /** Build a perspective matrix */
129 template < typename E
, class A
, class B
, class L
> void
130 matrix_perspective_xfov(matrix
<E
,A
,B
,L
>& m
, E xfov
, E aspect
, E n
,
131 E f
, Handedness handedness
, ZClip z_clip
)
133 typedef matrix
<E
,A
,B
,L
> matrix_type
;
134 typedef typename
matrix_type::value_type value_type
;
136 value_type width
= value_type(2) * std::tan(xfov
* value_type(.5)) * n
;
137 matrix_perspective(m
, width
, width
/ aspect
, n
, f
,
141 /** Build a left-handedness perspective matrix */
142 template < typename E
, class A
, class B
, class L
> void
143 matrix_perspective_xfov_LH(matrix
<E
,A
,B
,L
>& m
, E xfov
, E aspect
, E n
,
146 matrix_perspective_xfov(m
,xfov
,aspect
,n
,f
,left_handed
,z_clip
);
149 /** Build a right-handedness perspective matrix */
150 template < typename E
, class A
, class B
, class L
> void
151 matrix_perspective_xfov_RH(matrix
<E
,A
,B
,L
>& m
, E xfov
, E aspect
, E n
,
154 matrix_perspective_xfov(m
,xfov
,aspect
,n
,f
,right_handed
,z_clip
);
157 //////////////////////////////////////////////////////////////////////////////
158 // 3D perspective projection from vertical field of view
159 //////////////////////////////////////////////////////////////////////////////
161 /** Build a perspective matrix */
162 template < typename E
, class A
, class B
, class L
> void
163 matrix_perspective_yfov(matrix
<E
,A
,B
,L
>& m
, E yfov
, E aspect
, E n
,
164 E f
, Handedness handedness
, ZClip z_clip
)
166 typedef matrix
<E
,A
,B
,L
> matrix_type
;
167 typedef typename
matrix_type::value_type value_type
;
169 value_type height
= value_type(2) * std::tan(yfov
* value_type(.5)) * n
;
170 matrix_perspective(m
, height
* aspect
, height
, n
, f
,
174 /** Build a left-handedness perspective matrix */
175 template < typename E
, class A
, class B
, class L
> void
176 matrix_perspective_yfov_LH(matrix
<E
,A
,B
,L
>& m
, E yfov
, E aspect
, E n
,
179 matrix_perspective_yfov(m
,yfov
,aspect
,n
,f
,left_handed
,z_clip
);
182 /** Build a right-handedness perspective matrix */
183 template < typename E
, class A
, class B
, class L
> void
184 matrix_perspective_yfov_RH(matrix
<E
,A
,B
,L
>& m
, E yfov
, E aspect
, E n
,
187 matrix_perspective_yfov(m
,yfov
,aspect
,n
,f
,right_handed
,z_clip
);
190 //////////////////////////////////////////////////////////////////////////////
191 // 3D orthographic projection from frustum
192 //////////////////////////////////////////////////////////////////////////////
194 /** Build a matrix representing an orthographic projection, specified by
195 * frustum bounds in l,r,b,t,n,f form, and with the given handedness and z
199 template < typename E
, class A
, class B
, class L
> void
200 matrix_orthographic(matrix
<E
,A
,B
,L
>& m
, E left
, E right
, E bottom
, E top
,
201 E n
, E f
, Handedness handedness
,
204 typedef matrix
<E
,A
,B
,L
> matrix_type
;
205 typedef typename
matrix_type::value_type value_type
;
208 detail::CheckMatHomogeneous3D(m
);
210 identity_transform(m
);
212 value_type inv_width
= value_type(1) / (right
- left
);
213 value_type inv_height
= value_type(1) / (top
- bottom
);
214 value_type inv_depth
= value_type(1) / (f
- n
);
215 value_type s
= handedness
== left_handed
? 1 : -1;
217 if (z_clip
== z_clip_neg_one
) {
218 m
.set_basis_element(2,2,s
* value_type(2) * inv_depth
);
219 m
.set_basis_element(3,2,-(f
+ n
) * inv_depth
);
220 } else { // z_clip.z_clip() == 0
221 m
.set_basis_element(2,2,s
* inv_depth
);
222 m
.set_basis_element(3,2,-n
* inv_depth
);
225 m
.set_basis_element(0,0,value_type(2) * inv_width
);
226 m
.set_basis_element(1,1,value_type(2) * inv_height
);
227 m
.set_basis_element(3,0,-(right
+ left
) * inv_width
);
228 m
.set_basis_element(3,1,-(top
+ bottom
) * inv_height
);
231 /** Build an orthographic projection matrix */
232 template < typename E
, class A
, class B
, class L
> void
233 matrix_orthographic(matrix
<E
,A
,B
,L
>& m
, E width
, E height
, E n
, E f
,
234 Handedness handedness
, ZClip z_clip
)
236 typedef matrix
<E
,A
,B
,L
> matrix_type
;
237 typedef typename
matrix_type::value_type value_type
;
239 value_type half_width
= width
* value_type(.5);
240 value_type half_height
= height
* value_type(.5);
241 matrix_orthographic(m
, -half_width
, half_width
,
242 -half_height
, half_height
, n
, f
, handedness
, z_clip
);
245 /** Build a left-handedness orthographic projection matrix */
246 template < typename E
, class A
, class B
, class L
> void
247 matrix_orthographic_LH(matrix
<E
,A
,B
,L
>& m
, E left
, E right
, E bottom
,
248 E top
, E n
, E f
, ZClip z_clip
)
250 matrix_orthographic(m
, left
, right
, bottom
, top
, n
, f
,
251 left_handed
, z_clip
);
254 /** Build a right-handedness orthographic projection matrix */
255 template < typename E
, class A
, class B
, class L
> void
256 matrix_orthographic_RH(matrix
<E
,A
,B
,L
>& m
, E left
, E right
, E bottom
,
257 E top
, E n
, E f
, ZClip z_clip
)
259 matrix_orthographic(m
, left
, right
, bottom
, top
, n
, f
,
260 right_handed
, z_clip
);
263 /** Build a left-handedness orthographic projection matrix */
264 template < typename E
, class A
, class B
, class L
> void
265 matrix_orthographic_LH(matrix
<E
,A
,B
,L
>& m
, E width
, E height
, E n
,
268 matrix_orthographic(m
, width
, height
, n
, f
, left_handed
,
272 /** Build a right-handedness orthographic projection matrix */
273 template < typename E
, class A
, class B
, class L
> void
274 matrix_orthographic_RH(matrix
<E
,A
,B
,L
>& m
, E width
, E height
, E n
,
277 matrix_orthographic(m
, width
, height
, n
, f
, right_handed
,
281 //////////////////////////////////////////////////////////////////////////////
283 //////////////////////////////////////////////////////////////////////////////
285 /* Build a viewport matrix
287 * Note: A viewport matrix is in a sense the opposite of an orthographics
288 * projection matrix, and can be build by constructing and inverting the
291 * @todo: Need to look into D3D viewport conventions and see if this needs to
292 * be adapted accordingly.
295 template < typename E
, class A
, class B
, class L
> void
296 matrix_viewport(matrix
<E
,A
,B
,L
>& m
, E left
, E right
, E bottom
,
297 E top
, ZClip z_clip
, E n
= E(0), E f
= E(1))
299 matrix_orthographic_LH(m
, left
, right
, bottom
, top
, n
, f
, z_clip
);
300 /* @todo: invert(m), when available */
304 //////////////////////////////////////////////////////////////////////////////
306 //////////////////////////////////////////////////////////////////////////////
308 /* Build a pick volume matrix
310 * When post-concatenated with a projection matrix, the pick matrix modifies
311 * the view volume to create a 'picking volume'. This volume corresponds to
312 * a screen rectangle centered at (pick_x, pick_y) and with dimensions
313 * pick_widthXpick_height.
315 * @todo: Representation of viewport between this function and
316 * matrix_viewport() is inconsistent (position and dimensions vs. bounds).
317 * Should this be addressed?
320 template < typename E
, class A
, class B
, class L
> void
322 matrix
<E
,A
,B
,L
>& m
, E pick_x
, E pick_y
, E pick_width
, E pick_height
,
323 E viewport_x
, E viewport_y
, E viewport_width
, E viewport_height
)
325 typedef matrix
<E
,A
,B
,L
> matrix_type
;
326 typedef typename
matrix_type::value_type value_type
;
329 detail::CheckMatHomogeneous3D(m
);
331 identity_transform(m
);
333 value_type inv_width
= value_type(1) / pick_width
;
334 value_type inv_height
= value_type(1) / pick_height
;
336 m
.set_basis_element(0,0,viewport_width
*inv_width
);
337 m
.set_basis_element(1,1,viewport_height
*inv_height
);
338 m
.set_basis_element(3,0,
339 (viewport_width
+value_type(2)*(viewport_x
-pick_x
))*inv_width
);
340 m
.set_basis_element(3,1,
341 (viewport_height
+value_type(2)*(viewport_y
-pick_y
))*inv_height
);
This page took 0.065151 seconds and 5 git commands to generate.