]> git.mxchange.org Git - flightgear.git/blob - utils/fgviewer/Frustum.hxx
fgviewer: Import hla based viewer application.
[flightgear.git] / utils / fgviewer / Frustum.hxx
1 // Copyright (C) 2009 - 2012  Mathias Froehlich
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16
17 #ifndef Frustum_hxx
18 #define Frustum_hxx
19
20 #include <cmath>
21 #include <osg/Matrix>
22 #include <osg/Vec2>
23 #include <osg/Vec3>
24 #include <simgear/math/SGMath.hxx>
25
26 namespace fgviewer  {
27
28 struct Frustum {
29     Frustum(const double& aspectRatio = 1) :
30         _left(-aspectRatio),
31         _right(aspectRatio),
32         _bottom(-1),
33         _top(1),
34         _near(2)
35     { }
36     Frustum(const double& left, const double& right, const double& bottom, const double& top, const double& near) :
37         _left(left),
38         _right(right),
39         _bottom(bottom),
40         _top(top),
41         _near(near)
42     { }
43     Frustum(const Frustum& frustum) :
44         _left(frustum._left),
45         _right(frustum._right),
46         _bottom(frustum._bottom),
47         _top(frustum._top),
48         _near(frustum._near)
49     { }
50
51     bool setMatrix(const osg::Matrix& matrix)
52     {
53         double zFar;
54         return matrix.getFrustum(_left, _right, _bottom, _top, _near, zFar);
55     }
56     osg::Matrix getMatrix() const
57     {
58         return getMatrix(osg::Vec2(_near, 2*_near));
59     }
60     /// Finite projection matrix
61     osg::Matrix getMatrix(const osg::Vec2& depthRange) const
62     {
63         double near = depthRange[0];
64         double far = depthRange[1];
65         /// left, right, bottom and top are rescaled by near/_near and the result is
66         /// inserted into the final equations. This rescaling factor just cancels out mostly.
67         double a00 = 2*_near/(_right - _left);
68         double a11 = 2*_near/(_top - _bottom);
69         double a20 = (_right + _left)/(_right - _left);
70         double a21 = (_top + _bottom)/(_top - _bottom);
71         double a22 = (near + far)/(near - far);
72         double a23 = -1;
73         double a32 = 2*near*far/(near - far);
74
75         return osg::Matrix(a00,   0,   0,   0,
76                              0, a11,   0,   0,
77                            a20, a21, a22, a23,
78                              0,   0, a32,   0);
79     }
80     /// Infinite projection matrix with a given near plane
81     osg::Matrix getMatrix(const double& near, const double& eps = 0) const
82     {
83         /// left, right, bottom and top are rescaled by near/_near and the result is
84         /// inserted into the final equations. This rescaling factor just cancels out mostly.
85         double a00 = 2*_near/(_right - _left);
86         double a11 = 2*_near/(_top - _bottom);
87         double a20 = (_right + _left)/(_right - _left);
88         double a21 = (_top + _bottom)/(_top - _bottom);
89         double a22 = eps - 1;
90         double a23 = -1;
91         double a32 = near*(eps - 2);
92
93         return osg::Matrix(a00,   0,   0,   0,
94                              0, a11,   0,   0,
95                            a20, a21, a22, a23,
96                              0,   0, a32,   0);
97     }
98
99     /// Return the aspect ratio of the frustum
100     double getAspectRatio() const
101     { return (_right - _left)/(_top - _bottom); }
102     void setAspectRatio(double aspectRatio)
103     {
104         double aspectScale = aspectRatio/getAspectRatio();
105         _left *= aspectScale;
106         _right *= aspectScale;
107     }
108
109     void setFieldOfViewRad(double fieldOfViewRad)
110     {
111         double fieldOfView = tan(fieldOfViewRad);
112         double aspectRatio = getAspectRatio();
113         _left = -fieldOfView*aspectRatio*0.5*_near;
114         _right = fieldOfView*aspectRatio*0.5*_near;
115         _bottom = -fieldOfView*0.5*_near;
116         _top = fieldOfView*0.5*_near;
117     }
118     void setFieldOfViewDeg(double fieldOfViewDeg)
119     { setFieldOfViewRad(SGMiscd::deg2rad(fieldOfViewDeg)); }
120
121
122     /// Translate this frustum by the given eye point offset
123     Frustum translate(const osg::Vec3& eyeOffset) const
124     {
125         double left = _left - eyeOffset[0];
126         double right = _right - eyeOffset[0];
127         double bottom = _bottom - eyeOffset[1];
128         double top = _top - eyeOffset[1];
129         double near = _near + eyeOffset[2];
130         return Frustum(left, right, bottom, top, near);
131     }
132     /// Scale this frustum around the scale center.
133     /// Gives something similar like zooming into the view.
134     Frustum scale(double scaleFactor, const osg::Vec3& scaleCenter) const
135     {
136         Frustum frustum;
137         frustum._left = scaleFactor*(_left - scaleCenter[0]) + scaleCenter[0];
138         frustum._right = scaleFactor*(_right - scaleCenter[0]) + scaleCenter[0];
139         frustum._bottom = scaleFactor*(_bottom - scaleCenter[1]) + scaleCenter[1];
140         frustum._top = scaleFactor*(_top - scaleCenter[1]) + scaleCenter[1];
141         frustum._near = scaleFactor*(_near + scaleCenter[2]) - scaleCenter[2];
142         return frustum;
143     }
144
145     // Parameters for the reference view frustum.
146     double _left;
147     double _right;
148     double _bottom;
149     double _top;
150     // Is not the real near plane. Just used to reference the other frustum parameters.
151     double _near;
152 };
153
154 } // namespace fgviewer
155
156 #endif