]> Dogcows Code - chaz/yoink/blob - src/Moof/cml/mathlib/matrix_projection.h
beginnings of scene rendering
[chaz/yoink] / src / Moof / cml / mathlib / matrix_projection.h
1 /* -*- C++ -*- ------------------------------------------------------------
2
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
4
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
7
8 *-----------------------------------------------------------------------*/
9 /** @file
10 * @brief
11 */
12
13 #ifndef matrix_projection_h
14 #define matrix_projection_h
15
16 #include <cml/mathlib/checking.h>
17 #include <cml/mathlib/helper.h>
18
19 /* Functions for building matrix transforms other than rotations
20 * (matrix_rotation.h) and viewing projections (matrix_projection.h).
21 *
22 * @todo: Clean up comments and documentation throughout.
23 */
24
25 // NOTE: Changed 'near' and 'far' to 'n' and 'f' throughout to work around
26 // windows.h 'near' and 'far' macros.
27
28 namespace cml {
29
30 //////////////////////////////////////////////////////////////////////////////
31 // 3D perspective projection from frustum
32 //////////////////////////////////////////////////////////////////////////////
33
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
36 * range
37 */
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,
41 ZClip z_clip)
42 {
43 typedef matrix<E,A,B,L> matrix_type;
44 typedef typename matrix_type::value_type value_type;
45
46 /* Checking */
47 detail::CheckMatHomogeneous3D(m);
48
49 identity_transform(m);
50
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;
56
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));
63 }
64
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) );
71 }
72
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
75 * range
76 */
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)
80 {
81 typedef matrix<E,A,B,L> matrix_type;
82 typedef typename matrix_type::value_type value_type;
83
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);
88 }
89
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)
94 {
95 matrix_perspective(m, left, right, bottom, top, n, f,
96 left_handed, z_clip);
97 }
98
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)
103 {
104 matrix_perspective(m, left, right, bottom, top, n, f,
105 right_handed, z_clip);
106 }
107
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,
111 E f, ZClip z_clip)
112 {
113 matrix_perspective(m, width, height, n, f, left_handed, z_clip);
114 }
115
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,
119 E f, ZClip z_clip)
120 {
121 matrix_perspective(m, width, height, n, f, right_handed, z_clip);
122 }
123
124 //////////////////////////////////////////////////////////////////////////////
125 // 3D perspective projection from horizontal field of view
126 //////////////////////////////////////////////////////////////////////////////
127
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)
132 {
133 typedef matrix<E,A,B,L> matrix_type;
134 typedef typename matrix_type::value_type value_type;
135
136 value_type width = value_type(2) * std::tan(xfov * value_type(.5)) * n;
137 matrix_perspective(m, width, width / aspect, n, f,
138 handedness, z_clip);
139 }
140
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,
144 E f, ZClip z_clip)
145 {
146 matrix_perspective_xfov(m,xfov,aspect,n,f,left_handed,z_clip);
147 }
148
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,
152 E f, ZClip z_clip)
153 {
154 matrix_perspective_xfov(m,xfov,aspect,n,f,right_handed,z_clip);
155 }
156
157 //////////////////////////////////////////////////////////////////////////////
158 // 3D perspective projection from vertical field of view
159 //////////////////////////////////////////////////////////////////////////////
160
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)
165 {
166 typedef matrix<E,A,B,L> matrix_type;
167 typedef typename matrix_type::value_type value_type;
168
169 value_type height = value_type(2) * std::tan(yfov * value_type(.5)) * n;
170 matrix_perspective(m, height * aspect, height, n, f,
171 handedness, z_clip);
172 }
173
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,
177 E f, ZClip z_clip)
178 {
179 matrix_perspective_yfov(m,yfov,aspect,n,f,left_handed,z_clip);
180 }
181
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,
185 E f, ZClip z_clip)
186 {
187 matrix_perspective_yfov(m,yfov,aspect,n,f,right_handed,z_clip);
188 }
189
190 //////////////////////////////////////////////////////////////////////////////
191 // 3D orthographic projection from frustum
192 //////////////////////////////////////////////////////////////////////////////
193
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
196 * clipping range
197 */
198
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,
202 ZClip z_clip)
203 {
204 typedef matrix<E,A,B,L> matrix_type;
205 typedef typename matrix_type::value_type value_type;
206
207 /* Checking */
208 detail::CheckMatHomogeneous3D(m);
209
210 identity_transform(m);
211
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;
216
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);
223 }
224
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);
229 }
230
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)
235 {
236 typedef matrix<E,A,B,L> matrix_type;
237 typedef typename matrix_type::value_type value_type;
238
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);
243 }
244
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)
249 {
250 matrix_orthographic(m, left, right, bottom, top, n, f,
251 left_handed, z_clip);
252 }
253
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)
258 {
259 matrix_orthographic(m, left, right, bottom, top, n, f,
260 right_handed, z_clip);
261 }
262
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,
266 E f, ZClip z_clip)
267 {
268 matrix_orthographic(m, width, height, n, f, left_handed,
269 z_clip);
270 }
271
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,
275 E f, ZClip z_clip)
276 {
277 matrix_orthographic(m, width, height, n, f, right_handed,
278 z_clip);
279 }
280
281 //////////////////////////////////////////////////////////////////////////////
282 // 3D viewport
283 //////////////////////////////////////////////////////////////////////////////
284
285 /* Build a viewport matrix
286 *
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
289 * latter.
290 *
291 * @todo: Need to look into D3D viewport conventions and see if this needs to
292 * be adapted accordingly.
293 */
294
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))
298 {
299 matrix_orthographic_LH(m, left, right, bottom, top, n, f, z_clip);
300 /* @todo: invert(m), when available */
301 m = inverse(m);
302 }
303
304 //////////////////////////////////////////////////////////////////////////////
305 // 3D picking volume
306 //////////////////////////////////////////////////////////////////////////////
307
308 /* Build a pick volume matrix
309 *
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.
314 *
315 * @todo: Representation of viewport between this function and
316 * matrix_viewport() is inconsistent (position and dimensions vs. bounds).
317 * Should this be addressed?
318 */
319
320 template < typename E, class A, class B, class L > void
321 matrix_pick(
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)
324 {
325 typedef matrix<E,A,B,L> matrix_type;
326 typedef typename matrix_type::value_type value_type;
327
328 /* Checking */
329 detail::CheckMatHomogeneous3D(m);
330
331 identity_transform(m);
332
333 value_type inv_width = value_type(1) / pick_width;
334 value_type inv_height = value_type(1) / pick_height;
335
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);
342 }
343
344 } // namespace cml
345
346 #endif
This page took 0.050056 seconds and 4 git commands to generate.