vmmlib  1.13.0
Templatized C++ vector and matrix math library
frustum.hpp
1 /*
2  * Copyright (c) 2006-2016, Visualization and Multimedia Lab,
3  * University of Zurich <http://vmml.ifi.uzh.ch>,
4  * Eyescale Software GmbH,
5  * Blue Brain Project, EPFL
6  *
7  * This file is part of VMMLib <https://github.com/VMML/vmmlib/>
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * Redistributions of source code must retain the above copyright notice, this
13  * list of conditions and the following disclaimer. Redistributions in binary
14  * form must reproduce the above copyright notice, this list of conditions and
15  * the following disclaimer in the documentation and/or other materials provided
16  * with the distribution. Neither the name of the Visualization and Multimedia
17  * Lab, University of Zurich nor the names of its contributors may be used to
18  * endorse or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef __VMML__FRUSTUM__HPP__
34 #define __VMML__FRUSTUM__HPP__
35 
36 #include <cstring> // memcmp
37 #include <vmmlib/matrix.hpp> // used inline
38 
39 #if defined(_MSC_VER)
40  //can otherwise cause problems with, e.g., M_PI under Windows.
41 #define _USE_MATH_DEFINES
42 #include <cmath>
43 #ifndef M_PI
44 #include <corecrt_math_defines.h>
45 #endif
46 #else
47 #ifndef M_PI
48 #define M_PI 3.1415926535897932
49 #endif
50 #endif
51 
52 namespace vmml
53 {
55 template <typename T>
56 class Frustum
57 {
58 public:
60  Frustum();
61 
63  Frustum(T left, T right, T bottom, T top, T nearPlane, T farPlane);
64 
66  Frustum(T field_of_view_y, T aspect_ratio, T nearPlane_, T farPlane);
67 
69  Frustum(const Matrix<4, 4, T>& projection);
70 
72  ~Frustum() {}
74  bool operator==(const Frustum<T>& other) const;
75 
77  bool operator!=(const Frustum<T>& other) const;
78 
80  bool equals(const Frustum<T>& other,
81  T tolerance = std::numeric_limits<T>::epsilon()) const;
82 
85 
88 
90  void jitter(const vector<2, T>& jitter_);
91 
98  void adjustNearPlane(const T nearPlane);
99 
102  T& left() { return _array[0]; }
103  T left() const { return _array[0]; }
104  T& right() { return _array[1]; }
105  T right() const { return _array[1]; }
106  T& bottom() { return _array[2]; }
107  T bottom() const { return _array[2]; }
108  T& top() { return _array[3]; }
109  T top() const { return _array[3]; }
110  T& nearPlane() { return _array[4]; }
111  T nearPlane() const { return _array[4]; }
112  T& farPlane() { return _array[5]; }
113  T farPlane() const { return _array[5]; }
115 
117  T getWidth() const;
118 
120  T getHeight() const;
121 
122  friend std::ostream& operator<<(std::ostream& os, const Frustum& f)
123  {
124  const std::ios::fmtflags flags = os.flags();
125  const int prec = os.precision();
126 
127  os.setf(std::ios::right, std::ios::adjustfield);
128  os.precision(5);
129  os << "[" << std::setw(10) << f.left() << " " << std::setw(10)
130  << f.right() << " " << std::setw(10) << f.bottom() << " "
131  << std::setw(10) << f.top() << " " << std::setw(10) << f.nearPlane()
132  << " " << std::setw(10) << f.farPlane() << "]";
133  os.precision(prec);
134  os.setf(flags);
135  return os;
136  };
137 
138 private:
139  T _array[6];
140 };
141 } // namespace vmml
142 
143 // - implementation - //
144 
145 namespace vmml
146 {
147 template <typename T>
149 {
150  _array[0] = -1;
151  _array[1] = 1;
152  _array[2] = -1;
153  _array[3] = 1;
154  _array[4] = 0.1f;
155  _array[5] = 100;
156 }
157 
158 template <typename T>
159 Frustum<T>::Frustum(const T _left, const T _right, const T _bottom,
160  const T _top, const T _near, const T _far)
161 {
162  _array[0] = _left;
163  _array[1] = _right;
164  _array[2] = _bottom;
165  _array[3] = _top;
166  _array[4] = _near;
167  _array[5] = _far;
168 }
169 
170 template <typename T>
171 Frustum<T>::Frustum(const T fov_y, const T aspect_ratio, const T nearPlane_,
172  const T farPlane_)
173 {
174  _array[2] = std::tan(0.5 * fov_y * M_PI / 180.0) * nearPlane_;
175  _array[3] = -_array[2];
176  // depend on _array[2,3]:
177  _array[0] = bottom() * aspect_ratio;
178  _array[1] = top() * aspect_ratio;
179  _array[4] = nearPlane_;
180  _array[5] = farPlane_;
181 }
182 
183 template <typename T>
185 {
186  _array[4] = projection(2, 3) / (projection(2, 2) - 1.0);
187  _array[5] = projection(2, 3) / (projection(2, 2) + 1.0);
188  _array[2] = nearPlane() * (projection(1, 2) - 1.0) / projection(1, 1);
189  _array[3] = nearPlane() * (projection(1, 2) + 1.0) / projection(1, 1);
190  _array[0] = nearPlane() * (projection(0, 2) - 1.0) / projection(0, 0);
191  _array[1] = nearPlane() * (projection(0, 2) + 1.0) / projection(0, 0);
192 }
193 
194 template <typename T>
195 bool Frustum<T>::operator==(const Frustum<T>& other) const
196 {
197  return ::memcmp(_array, other._array, sizeof(_array)) == 0;
198 }
199 
200 template <typename T>
201 bool Frustum<T>::operator!=(const Frustum<T>& other) const
202 {
203  return ::memcmp(_array, other._array, sizeof(_array)) != 0;
204 }
205 
206 template <typename T>
207 bool Frustum<T>::equals(const Frustum<T>& other, const T tolerance) const
208 {
209  return std::abs(_array[0] - other._array[0]) <= tolerance &&
210  std::abs(_array[1] - other._array[1]) <= tolerance &&
211  std::abs(_array[2] - other._array[2]) <= tolerance &&
212  std::abs(_array[3] - other._array[3]) <= tolerance &&
213  std::abs(_array[4] - other._array[4]) <= tolerance &&
214  std::abs(_array[5] - other._array[5]) <= tolerance;
215 }
216 
217 template <typename T>
219 {
220  Matrix<4, 4, T> M;
221 
222  M(0, 0) = 2.0 * nearPlane() / (right() - left());
223  M(0, 1) = 0.0;
224  M(0, 2) = (right() + left()) / (right() - left());
225  M(0, 3) = 0.0;
226 
227  M(1, 0) = 0.0;
228  M(1, 1) = 2.0 * nearPlane() / (top() - bottom());
229  M(1, 2) = (top() + bottom()) / (top() - bottom());
230  M(1, 3) = 0.0;
231 
232  M(2, 0) = 0.0;
233  M(2, 1) = 0.0;
234  // NOTE: Some glfrustum man pages say wrongly '(far + near) / (far - near)'
235  M(2, 2) = -(farPlane() + nearPlane()) / (farPlane() - nearPlane());
236  M(2, 3) = -2.0 * farPlane() * nearPlane() / (farPlane() - nearPlane());
237 
238  M(3, 0) = 0.0;
239  M(3, 1) = 0.0;
240  M(3, 2) = -1.0;
241  M(3, 3) = 0.0;
242 
243  return M;
244 }
245 
246 template <typename T>
248 {
249  Matrix<4, 4, T> M;
250 
251  M(0, 0) = 2.0 / (right() - left());
252  M(0, 1) = 0.0;
253  M(0, 2) = 0.0;
254  M(0, 3) = -(right() + left()) / (right() - left());
255 
256  M(1, 0) = 0.0;
257  M(1, 1) = 2.0 / (top() - bottom());
258  M(1, 2) = 0.0f;
259  M(1, 3) = -(top() + bottom()) / (top() - bottom());
260 
261  M(2, 0) = 0.0;
262  M(2, 1) = 0.0;
263  M(2, 2) = -2.0 / (farPlane() - nearPlane());
264  M(2, 3) = -(farPlane() + nearPlane()) / (farPlane() - nearPlane());
265 
266  M(3, 0) = 0.0;
267  M(3, 1) = 0.0;
268  M(3, 2) = 0.0;
269  M(3, 3) = 1.0f;
270 
271  return M;
272 }
273 
274 template <typename T>
275 void Frustum<T>::jitter(const vector<2, T>& jitter_)
276 {
277  left() = left() + jitter_.x();
278  right() = right() + jitter_.x();
279  bottom() = bottom() + jitter_.y();
280  top() = top() + jitter_.y();
281 }
282 
283 template <typename T>
284 void Frustum<T>::adjustNearPlane(const T new_near)
285 {
286  if (new_near == nearPlane())
287  return;
288 
289  const T ratio = new_near / nearPlane();
290  right() *= ratio;
291  left() *= ratio;
292  top() *= ratio;
293  bottom() *= ratio;
294  nearPlane() = new_near;
295 }
296 
297 template <typename T>
298 inline T Frustum<T>::getWidth() const
299 {
300  return std::abs(right() - left());
301 }
302 
303 template <typename T>
304 inline T Frustum<T>::getHeight() const
305 {
306  return std::abs(top() - bottom());
307 }
308 
309 } // namespace vmml
310 
311 #endif
Represents a frustum, following OpenGL conventions.
Definition: frustum.hpp:56
bool operator==(const Frustum< T > &other) const
Definition: frustum.hpp:195
T getWidth() const
Definition: frustum.hpp:298
Frustum()
Construct a default frustum (-1, 1, -1, 1, 0.1, 100).
Definition: frustum.hpp:148
bool operator!=(const Frustum< T > &other) const
Definition: frustum.hpp:201
Matrix< 4, 4, T > computePerspectiveMatrix() const
Definition: frustum.hpp:218
Matrix< 4, 4, T > computeOrthoMatrix() const
Definition: frustum.hpp:247
void adjustNearPlane(const T nearPlane)
Move the frustum near plane.
Definition: frustum.hpp:284
Definition: aabb.hpp:44
~Frustum()
Destruct this frustum.
Definition: frustum.hpp:72
bool equals(const Frustum< T > &other, T tolerance=std::numeric_limits< T >::epsilon()) const
Definition: frustum.hpp:207
void jitter(const vector< 2, T > &jitter_)
Move the frustum near plane by the given offset "sideways".
Definition: frustum.hpp:275
Matrix with R rows and C columns of element type T.
Definition: matrix.hpp:52
T getHeight() const
Definition: frustum.hpp:304