]>
Dogcows Code - chaz/yoink/blob - src/cml/mathlib/frustum.h
43eb41f8aea876df7fb31a8cc52412b73e834d3a
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] */
111 extract_near_frustum_plane(m
, planes
[4], z_clip
);
113 /* @todo: This will be handled by the plane class */
115 for (size_t i
= 0; i
< 6; ++i
) {
116 Real invl
= inv_sqrt(planes
[i
][0] * planes
[i
][0] +
117 planes
[i
][1] * planes
[i
][1] +
118 planes
[i
][2] * planes
[i
][2]);
120 planes
[i
][0] *= invl
;
121 planes
[i
][1] *= invl
;
122 planes
[i
][2] *= invl
;
123 planes
[i
][3] *= invl
;
128 /** Extract the near plane of a frustum given a concatenated modelview and
129 * projection matrix with the given near z-clipping range. The plane is
132 * @note The plane is in ax+by+cz+d = 0 form.
134 * @warning The matrix is assumed to be a homogeneous transformation
137 template < class MatT
, class PlaneT
> void
138 extract_near_frustum_plane(
144 /* Near: [03+02, 13+12, 23+22, 33+32] : [02, 12, 22, 32] */
145 if (z_clip
== z_clip_neg_one
) {
146 plane
[0] = m
.basis_element(0,3) + m
.basis_element(0,2);
147 plane
[1] = m
.basis_element(1,3) + m
.basis_element(1,2);
148 plane
[2] = m
.basis_element(2,3) + m
.basis_element(2,2);
149 plane
[3] = m
.basis_element(3,3) + m
.basis_element(3,2);
150 } else { // z_clip == z_clip_zero
151 plane
[0] = m
.basis_element(0,2);
152 plane
[1] = m
.basis_element(1,2);
153 plane
[2] = m
.basis_element(2,2);
154 plane
[3] = m
.basis_element(3,2);
160 /* This is currently only in support of finding the corners of a frustum.
161 * The input planes are assumed to have a single unique intersection, so
162 * no tolerance is used.
165 template < typename Real
> vector
< Real
, fixed
<3> >
166 intersect_planes(Real p1
[4], Real p2
[4], Real p3
[4])
168 typedef vector
< Real
, fixed
<3> > vector_type
;
169 typedef typename
vector_type::value_type value_type
;
171 vector_type
n1(p1
[0],p1
[1],p1
[2]);
172 vector_type
n2(p2
[0],p2
[1],p2
[2]);
173 vector_type
n3(p3
[0],p3
[1],p3
[2]);
175 value_type d1
= -p1
[3];
176 value_type d2
= -p2
[3];
177 value_type d3
= -p3
[3];
180 d1
*cross(n2
,n3
) + d2
*cross(n3
,n1
) + d3
*cross(n1
,n2
);
181 value_type denom
= triple_product(n1
,n2
,n3
);
185 } // namespace detail
187 /* Get the corners of a frustum defined by 6 planes. The planes are in
188 * ax+by+cz+d = 0 form, and are in the order:
196 * The corners are in CCW order starting in the lower-left, first at the near
197 * plane, then at the far plane.
200 template < typename Real
, typename E
, class A
> void
201 get_frustum_corners(Real planes
[6][4], vector
<E
,A
> corners
[8])
203 // NOTE: Prefixed with 'PLANE_' due to symbol conflict with Windows
204 // macros PLANE_LEFT and PLANE_RIGHT.
214 corners
[0] = detail::intersect_planes(
216 planes
[PLANE_BOTTOM
],
219 corners
[1] = detail::intersect_planes(
221 planes
[PLANE_BOTTOM
],
224 corners
[2] = detail::intersect_planes(
229 corners
[3] = detail::intersect_planes(
234 corners
[4] = detail::intersect_planes(
236 planes
[PLANE_BOTTOM
],
239 corners
[5] = detail::intersect_planes(
241 planes
[PLANE_BOTTOM
],
244 corners
[6] = detail::intersect_planes(
249 corners
[7] = detail::intersect_planes(
This page took 0.049529 seconds and 4 git commands to generate.