]> git.mxchange.org Git - simgear.git/blob - simgear/scene/util/SGUpdateVisitor.hxx
simgear/scene/sky/sky.cxx: Include sg_inlines.h with simgear/ prefix as all other...
[simgear.git] / simgear / scene / util / SGUpdateVisitor.hxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2006-2009 Mathias Froehlich 
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21
22 #ifndef SG_SCENE_UPDATEVISITOR_HXX
23 #define SG_SCENE_UPDATEVISITOR_HXX
24
25 #include <osg/NodeVisitor>
26 #include <osg/PagedLOD>
27 #include <osgUtil/UpdateVisitor>
28
29 #include "simgear/math/SGMath.hxx"
30
31 class SGUpdateVisitor : public osgUtil::UpdateVisitor {
32 public:
33   SGUpdateVisitor() :
34     mVisibility(-1)
35   {
36     setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
37     setVisibility(10000);
38   }
39   void setViewData(const SGVec3d& globalEyePos,
40                    const SGQuatd& globalViewOrientation)
41   {
42     mGlobalGeodEyePos = SGGeod::fromCart(globalEyePos);
43     _currentEyePos = toOsg(globalEyePos);
44     mGlobalEyePos = globalEyePos;
45     mGlobalViewOr = globalViewOrientation;
46     mGlobalHorizLocalOr = SGQuatd::fromLonLat(mGlobalGeodEyePos);
47     mHorizLocalNorth = mGlobalHorizLocalOr.backTransform(SGVec3d(1, 0, 0));
48     mHorizLocalEast = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 1, 0));
49     mHorizLocalDown = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 0, 1));
50   }
51
52   void setVisibility(double visibility)
53   {
54     if (mVisibility == visibility)
55       return;
56     mVisibility = visibility;
57     mSqrVisibility = visibility*visibility;
58
59     double m_log01 = -log( 0.01 );
60     double sqrt_m_log01 = sqrt( m_log01 );
61     double fog_exp_density = m_log01 / visibility;
62     double fog_exp2_density = sqrt_m_log01 / visibility;
63     double ground_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
64     double rwy_exp2_punch_through, taxi_exp2_punch_through;
65     if ( visibility < 8000 ) {
66       rwy_exp2_punch_through = sqrt_m_log01 / (visibility * 2.5);
67       taxi_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
68     } else {
69       rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 );
70       taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 );
71     }
72     
73     mFogExpDensity = fog_exp_density;
74     mFogExp2Density = fog_exp2_density;
75     mRunwayFogExp2Density = rwy_exp2_punch_through;
76     mTaxiFogExp2Density = taxi_exp2_punch_through;
77     mGroundLightsFogExp2Density = ground_exp2_punch_through;
78   }
79
80   double getVisibility() const
81   { return mVisibility; }
82   double getSqrVisibility() const
83   { return mSqrVisibility; }
84
85   double getFogExpDensity() const
86   { return mFogExpDensity; }
87   double getFogExp2Density() const
88   { return mFogExp2Density; }
89   double getRunwayFogExp2Density() const
90   { return mRunwayFogExp2Density; }
91   double getTaxiFogExp2Density() const
92   { return mTaxiFogExp2Density; }
93   double getGroundLightsFogExp2Density() const
94   { return mGroundLightsFogExp2Density; }
95
96   const SGVec3d& getGlobalEyePos() const
97   { return mGlobalEyePos; }
98   const SGGeod& getGeodEyePos() const
99   { return mGlobalGeodEyePos; }
100   const SGQuatd& getGlobalViewOr() const
101   { return mGlobalViewOr; }
102   const SGQuatd& getGlobalHorizLocalOr() const
103   { return mGlobalViewOr; }
104   const SGVec3d& getHorizLocalNorth() const
105   { return mHorizLocalNorth; }
106   const SGVec3d& getHorizLocalEast() const
107   { return mHorizLocalEast; }
108   const SGVec3d& getHorizLocalDown() const
109   { return mHorizLocalDown; }
110
111   void setLight(const SGVec3f& direction, const SGVec4f& ambient,
112                 const SGVec4f& diffuse, const SGVec4f& specular,
113                 const SGVec4f& fogColor, double sunAngleDeg)
114   {
115     mLightDirection = direction;
116     mAmbientLight = ambient;
117     mDiffuseLight = diffuse;
118     mSpecularLight = specular;
119     mFogColor = fogColor;
120     mSunAngleDeg = sunAngleDeg;
121   }
122
123   const SGVec3f& getLightDirection() const
124   { return mLightDirection; }
125   const SGVec4f& getAmbientLight() const
126   { return mAmbientLight; }
127   const SGVec4f& getDiffuseLight() const
128   { return mDiffuseLight; }
129   const SGVec4f& getSpecularLight() const
130   { return mSpecularLight; }
131   const SGVec4f& getFogColor() const
132   { return mFogColor; }
133
134   double getSunAngleDeg() const
135   { return mSunAngleDeg; }
136
137   virtual void apply(osg::Node& node)
138   {
139     if (!needToEnterNode(node))
140       return;
141     osgUtil::UpdateVisitor::apply(node);
142   }
143   // To avoid expiry of LOD nodes that are in range and that are updated,
144   // mark them with the last traversal number, even if they are culled away
145   // by the cull frustum.
146   virtual void apply(osg::PagedLOD& pagedLOD)
147   {
148     if (!needToEnterNode(pagedLOD))
149       return;
150     if (getFrameStamp())
151       pagedLOD.setFrameNumberOfLastTraversal(getFrameStamp()->getFrameNumber());
152     osgUtil::UpdateVisitor::apply(pagedLOD);
153   }
154   // To be able to traverse correctly only the active children, we need to
155   // track the model view matrices during update.
156   virtual void apply(osg::Transform& transform)
157   {
158     if (!needToEnterNode(transform))
159       return;
160     osg::Matrix matrix = _matrix;
161     transform.computeLocalToWorldMatrix(_matrix, this);
162     osgUtil::UpdateVisitor::apply(transform);
163     _matrix = matrix;
164   }
165   virtual void apply(osg::Camera& camera)
166   {
167     if (!needToEnterNode(camera))
168       return;
169     if (camera.getReferenceFrame() == osg::Camera::ABSOLUTE_RF) {
170       osg::Vec3d currentEyePos = _currentEyePos;
171       _currentEyePos = osg::Vec3d(0, 0, 0);
172       apply(static_cast<osg::Transform&>(camera));
173       _currentEyePos = currentEyePos;
174     } else {
175       apply(static_cast<osg::Transform&>(camera));
176     }
177   }
178   // Function to make the LOD traversal only enter that children that
179   // are visible on the screen.
180   virtual float getDistanceToViewPoint(const osg::Vec3& pos, bool) const
181   { return (_currentEyePos - _matrix.preMult(osg::Vec3d(pos))).length(); }
182
183 protected:
184   bool needToEnterNode(const osg::Node& node) const
185   {
186     if (!node.isCullingActive())
187       return true;
188     return isSphereInRange(node.getBound());
189   }
190   bool isSphereInRange(const osg::BoundingSphere& sphere) const
191   {
192     if (!sphere.valid())
193       return false;
194     float maxDist = mVisibility + sphere._radius;
195     osg::Vec3d center = _matrix.preMult(osg::Vec3d(sphere._center));
196     return (_currentEyePos - center).length2() <= maxDist*maxDist;
197   }
198     
199 private:
200   osg::Matrix _matrix;
201   osg::Vec3d _currentEyePos;
202
203   SGGeod mGlobalGeodEyePos;
204   SGVec3d mGlobalEyePos;
205   SGQuatd mGlobalViewOr;
206   SGQuatd mGlobalHorizLocalOr;
207   SGVec3d mHorizLocalNorth;
208   SGVec3d mHorizLocalEast;
209   SGVec3d mHorizLocalDown;
210
211   double mVisibility;
212   double mSqrVisibility;
213   double mFogExpDensity;
214   double mFogExp2Density;
215   double mRunwayFogExp2Density;
216   double mTaxiFogExp2Density;
217   double mGroundLightsFogExp2Density;
218
219   SGVec3f mLightDirection;
220   SGVec4f mAmbientLight;
221   SGVec4f mDiffuseLight;
222   SGVec4f mSpecularLight;
223   SGVec4f mFogColor;
224
225   double mSunAngleDeg;
226 };
227
228 #endif