]>
Dogcows Code - chaz/yoink/blob - src/cml/mathlib/frustum.h
6a707afb78dc2019ba8fa44b7bccb02c226841b7
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 *-----------------------------------------------------------------------*/
16 #include <cml/mathlib/matrix_concat.h>
17 #include <cml/mathlib/checking.h>
21 /* @todo: plane class, and perhaps named arguments instead of an array. */
23 /* Extract the planes of a frustum given a modelview matrix and a projection
24 * matrix with the given near z-clipping range. The planes are normalized by
25 * default, but this can be turned off with the 'normalize' argument.
27 * The planes are in ax+by+cz+d = 0 form, and are in the order:
36 template < class MatT
, typename Real
> void
37 extract_frustum_planes(
38 const MatT
& modelview
,
39 const MatT
& projection
,
42 bool normalize
= true)
44 extract_frustum_planes(
45 detail::matrix_concat_transforms_4x4(modelview
,projection
),
52 /* Extract the planes of a frustum from a single matrix assumed to contain any
53 * model and view transforms followed by a projection transform with the given
54 * near z-cliping range. The planes are normalized by default, but this can be
55 * turned off with the 'normalize' argument.
57 * The planes are in ax+by+cz+d = 0 form, and are in the order:
66 template < class MatT
, typename Real
> void
67 extract_frustum_planes(
71 bool normalize
= true)
73 detail::CheckMatHomogeneous3D(m
);
75 /* Left: [03+00, 13+10, 23+20, 33+30] */
77 planes
[0][0] = m
.basis_element(0,3) + m
.basis_element(0,0);
78 planes
[0][1] = m
.basis_element(1,3) + m
.basis_element(1,0);
79 planes
[0][2] = m
.basis_element(2,3) + m
.basis_element(2,0);
80 planes
[0][3] = m
.basis_element(3,3) + m
.basis_element(3,0);
82 /* Right: [03-00, 13-10, 23-20, 33-30] */
84 planes
[1][0] = m
.basis_element(0,3) - m
.basis_element(0,0);
85 planes
[1][1] = m
.basis_element(1,3) - m
.basis_element(1,0);
86 planes
[1][2] = m
.basis_element(2,3) - m
.basis_element(2,0);
87 planes
[1][3] = m
.basis_element(3,3) - m
.basis_element(3,0);
89 /* Bottom: [03+01, 13+11, 23+21, 33+31] */
91 planes
[2][0] = m
.basis_element(0,3) + m
.basis_element(0,1);
92 planes
[2][1] = m
.basis_element(1,3) + m
.basis_element(1,1);
93 planes
[2][2] = m
.basis_element(2,3) + m
.basis_element(2,1);
94 planes
[2][3] = m
.basis_element(3,3) + m
.basis_element(3,1);
96 /* Top: [03-01, 13-11, 23-21, 33-31] */
98 planes
[3][0] = m
.basis_element(0,3) - m
.basis_element(0,1);
99 planes
[3][1] = m
.basis_element(1,3) - m
.basis_element(1,1);
100 planes
[3][2] = m
.basis_element(2,3) - m
.basis_element(2,1);
101 planes
[3][3] = m
.basis_element(3,3) - m
.basis_element(3,1);
103 /* Far: [03-02, 13-12, 23-22, 33-32] */
105 planes
[5][0] = m
.basis_element(0,3) - m
.basis_element(0,2);
106 planes
[5][1] = m
.basis_element(1,3) - m
.basis_element(1,2);
107 planes
[5][2] = m
.basis_element(2,3) - m
.basis_element(2,2);
108 planes
[5][3] = m
.basis_element(3,3) - m
.basis_element(3,2);
110 /* Near: [03+02, 13+12, 23+22, 33+32] : [02, 12, 22, 32] */
112 if (z_clip
== z_clip_neg_one
) {
113 planes
[4][0] = m
.basis_element(0,3) + m
.basis_element(0,2);
114 planes
[4][1] = m
.basis_element(1,3) + m
.basis_element(1,2);
115 planes
[4][2] = m
.basis_element(2,3) + m
.basis_element(2,2);
116 planes
[4][3] = m
.basis_element(3,3) + m
.basis_element(3,2);
117 } else { // z_clip == z_clip_zero
118 planes
[4][0] = m
.basis_element(0,2);
119 planes
[4][1] = m
.basis_element(1,2);
120 planes
[4][2] = m
.basis_element(2,2);
121 planes
[4][3] = m
.basis_element(3,2);
124 /* @todo: This will be handled by the plane class */
126 for (size_t i
= 0; i
< 6; ++i
) {
127 Real invl
= inv_sqrt(planes
[i
][0] * planes
[i
][0] +
128 planes
[i
][1] * planes
[i
][1] +
129 planes
[i
][2] * planes
[i
][2]);
131 planes
[i
][0] *= invl
;
132 planes
[i
][1] *= invl
;
133 planes
[i
][2] *= invl
;
134 planes
[i
][3] *= invl
;
141 /* This is currently only in support of finding the corners of a frustum.
142 * The input planes are assumed to have a single unique intersection, so
143 * no tolerance is used.
146 template < typename Real
> vector
< Real
, fixed
<3> >
147 intersect_planes(Real p1
[4], Real p2
[4], Real p3
[4])
149 typedef vector
< Real
, fixed
<3> > vector_type
;
150 typedef typename
vector_type::value_type value_type
;
152 vector_type
n1(p1
[0],p1
[1],p1
[2]);
153 vector_type
n2(p2
[0],p2
[1],p2
[2]);
154 vector_type
n3(p3
[0],p3
[1],p3
[2]);
156 value_type d1
= -p1
[3];
157 value_type d2
= -p2
[3];
158 value_type d3
= -p3
[3];
161 d1
*cross(n2
,n3
) + d2
*cross(n3
,n1
) + d3
*cross(n1
,n2
);
162 value_type denom
= triple_product(n1
,n2
,n3
);
166 } // namespace detail
168 /* Get the corners of a frustum defined by 6 planes. The planes are in
169 * ax+by+cz+d = 0 form, and are in the order:
177 * The corners are in CCW order starting in the lower-left, first at the near
178 * plane, then at the far plane.
181 template < typename Real
, typename E
, class A
> void
182 get_frustum_corners(Real planes
[6][4], vector
<E
,A
> corners
[8])
184 // NOTE: Prefixed with 'PLANE_' due to symbol conflict with Windows
185 // macros PLANE_LEFT and PLANE_RIGHT.
195 corners
[0] = detail::intersect_planes(
197 planes
[PLANE_BOTTOM
],
200 corners
[1] = detail::intersect_planes(
202 planes
[PLANE_BOTTOM
],
205 corners
[2] = detail::intersect_planes(
210 corners
[3] = detail::intersect_planes(
215 corners
[4] = detail::intersect_planes(
217 planes
[PLANE_BOTTOM
],
220 corners
[5] = detail::intersect_planes(
222 planes
[PLANE_BOTTOM
],
225 corners
[6] = detail::intersect_planes(
230 corners
[7] = detail::intersect_planes(
This page took 0.046155 seconds and 4 git commands to generate.