1 // Copyright (C) 2009 - 2012 Mathias Froehlich
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.
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.
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.
24 #include <simgear/math/SGMath.hxx>
29 Frustum(const double& aspectRatio = 1) :
36 Frustum(const double& left, const double& right, const double& bottom, const double& top, const double& zNear) :
43 Frustum(const Frustum& frustum) :
45 _right(frustum._right),
46 _bottom(frustum._bottom),
51 bool setMatrix(const osg::Matrix& matrix)
54 return matrix.getFrustum(_left, _right, _bottom, _top, _near, zFar);
56 osg::Matrix getMatrix() const
58 return getMatrix(osg::Vec2(_near, 2*_near));
60 /// Finite projection matrix
61 osg::Matrix getMatrix(const osg::Vec2& depthRange) const
63 double zNear = depthRange[0];
64 double zFar = depthRange[1];
65 /// left, right, bottom and top are rescaled by zNear/_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 = (zNear + zFar)/(zNear - zFar);
73 double a32 = 2*zNear*zFar/(zNear - zFar);
75 return osg::Matrix(a00, 0, 0, 0,
80 /// Infinite projection matrix with a given zNear plane
81 osg::Matrix getMatrix(const double& zNear, const double& eps = 0) const
83 /// left, right, bottom and top are rescaled by zNear/_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);
91 double a32 = zNear*(eps - 2);
93 return osg::Matrix(a00, 0, 0, 0,
99 /// Return the aspect ratio of the frustum
100 double getAspectRatio() const
101 { return (_right - _left)/(_top - _bottom); }
102 void setAspectRatio(double aspectRatio)
104 double aspectScale = aspectRatio/getAspectRatio();
105 _left *= aspectScale;
106 _right *= aspectScale;
109 void setFieldOfViewRad(double fieldOfViewRad)
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;
118 void setFieldOfViewDeg(double fieldOfViewDeg)
119 { setFieldOfViewRad(SGMiscd::deg2rad(fieldOfViewDeg)); }
122 /// Translate this frustum by the given eye point offset
123 Frustum translate(const osg::Vec3& eyeOffset) const
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 zNear = _near + eyeOffset[2];
130 return Frustum(left, right, bottom, top, zNear);
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
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];
145 // Parameters for the reference view frustum.
150 // Is not the real zNear plane. Just used to reference the other frustum parameters.
154 } // namespace fgviewer