3 * Copyright (C) 2006-2009 Mathias Froehlich
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.
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.
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,
22 #ifndef SG_SCENE_UPDATEVISITOR_HXX
23 #define SG_SCENE_UPDATEVISITOR_HXX
25 #include <osg/NodeVisitor>
26 #include <osgUtil/UpdateVisitor>
28 #include "simgear/math/SGMath.hxx"
30 class SGUpdateVisitor : public osgUtil::UpdateVisitor {
35 setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
38 void setViewData(const SGVec3d& globalEyePos,
39 const SGQuatd& globalViewOrientation)
41 mGlobalGeodEyePos = SGGeod::fromCart(globalEyePos);
42 _currentEyePos = globalEyePos.osg();
43 mGlobalEyePos = globalEyePos;
44 mGlobalViewOr = globalViewOrientation;
45 mGlobalHorizLocalOr = SGQuatd::fromLonLat(mGlobalGeodEyePos);
46 mHorizLocalNorth = mGlobalHorizLocalOr.backTransform(SGVec3d(1, 0, 0));
47 mHorizLocalEast = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 1, 0));
48 mHorizLocalDown = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 0, 1));
51 void setVisibility(double visibility)
53 if (mVisibility == visibility)
55 mVisibility = visibility;
56 mSqrVisibility = visibility*visibility;
58 double m_log01 = -log( 0.01 );
59 double sqrt_m_log01 = sqrt( m_log01 );
60 double fog_exp_density = m_log01 / visibility;
61 double fog_exp2_density = sqrt_m_log01 / visibility;
62 double ground_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
63 double rwy_exp2_punch_through, taxi_exp2_punch_through;
64 if ( visibility < 8000 ) {
65 rwy_exp2_punch_through = sqrt_m_log01 / (visibility * 2.5);
66 taxi_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
68 rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 );
69 taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 );
72 mFogExpDensity = fog_exp_density;
73 mFogExp2Density = fog_exp2_density;
74 mRunwayFogExp2Density = rwy_exp2_punch_through;
75 mTaxiFogExp2Density = taxi_exp2_punch_through;
76 mGroundLightsFogExp2Density = ground_exp2_punch_through;
79 double getVisibility() const
80 { return mVisibility; }
81 double getSqrVisibility() const
82 { return mSqrVisibility; }
84 double getFogExpDensity() const
85 { return mFogExpDensity; }
86 double getFogExp2Density() const
87 { return mFogExp2Density; }
88 double getRunwayFogExp2Density() const
89 { return mRunwayFogExp2Density; }
90 double getTaxiFogExp2Density() const
91 { return mTaxiFogExp2Density; }
92 double getGroundLightsFogExp2Density() const
93 { return mGroundLightsFogExp2Density; }
95 const SGVec3d& getGlobalEyePos() const
96 { return mGlobalEyePos; }
97 const SGGeod& getGeodEyePos() const
98 { return mGlobalGeodEyePos; }
99 const SGQuatd& getGlobalViewOr() const
100 { return mGlobalViewOr; }
101 const SGQuatd& getGlobalHorizLocalOr() const
102 { return mGlobalViewOr; }
103 const SGVec3d& getHorizLocalNorth() const
104 { return mHorizLocalNorth; }
105 const SGVec3d& getHorizLocalEast() const
106 { return mHorizLocalEast; }
107 const SGVec3d& getHorizLocalDown() const
108 { return mHorizLocalDown; }
110 void setLight(const SGVec3f& direction, const SGVec4f& ambient,
111 const SGVec4f& diffuse, const SGVec4f& specular,
112 const SGVec4f& fogColor, double sunAngleDeg)
114 mLightDirection = direction;
115 mAmbientLight = ambient;
116 mDiffuseLight = diffuse;
117 mSpecularLight = specular;
118 mFogColor = fogColor;
119 mSunAngleDeg = sunAngleDeg;
122 const SGVec3f& getLightDirection() const
123 { return mLightDirection; }
124 const SGVec4f& getAmbientLight() const
125 { return mAmbientLight; }
126 const SGVec4f& getDiffuseLight() const
127 { return mDiffuseLight; }
128 const SGVec4f& getSpecularLight() const
129 { return mSpecularLight; }
130 const SGVec4f& getFogColor() const
131 { return mFogColor; }
133 double getSunAngleDeg() const
134 { return mSunAngleDeg; }
136 virtual void apply(osg::Node& node)
138 if (!needToEnterNode(node))
140 osgUtil::UpdateVisitor::apply(node);
143 // To be able to traverse correctly only the active children, we need to
144 // track the model view matrices during update.
145 virtual void apply(osg::Transform& transform)
147 if (!needToEnterNode(transform))
149 osg::Matrix matrix = _matrix;
150 transform.computeLocalToWorldMatrix(_matrix, this);
151 osgUtil::UpdateVisitor::apply(transform);
154 virtual void apply(osg::Camera& camera)
156 if (!needToEnterNode(camera))
158 if (camera.getReferenceFrame() == osg::Camera::ABSOLUTE_RF) {
159 osg::Vec3d currentEyePos = _currentEyePos;
160 _currentEyePos = osg::Vec3d(0, 0, 0);
161 apply(static_cast<osg::Transform&>(camera));
162 _currentEyePos = currentEyePos;
164 apply(static_cast<osg::Transform&>(camera));
167 virtual float getDistanceToViewPoint(const osg::Vec3& pos, bool) const
168 { return (_currentEyePos - _matrix.preMult(osg::Vec3d(pos))).length(); }
171 bool needToEnterNode(const osg::Node& node) const
173 if (!node.isCullingActive())
175 return isSphereInRange(node.getBound());
177 bool isSphereInRange(const osg::BoundingSphere& sphere) const
179 float maxDist = mVisibility + 2*sphere._radius;
180 return getDistanceToViewPoint(sphere._center, false) < maxDist;
185 osg::Vec3d _currentEyePos;
187 SGGeod mGlobalGeodEyePos;
188 SGVec3d mGlobalEyePos;
189 SGQuatd mGlobalViewOr;
190 SGQuatd mGlobalHorizLocalOr;
191 SGVec3d mHorizLocalNorth;
192 SGVec3d mHorizLocalEast;
193 SGVec3d mHorizLocalDown;
196 double mSqrVisibility;
197 double mFogExpDensity;
198 double mFogExp2Density;
199 double mRunwayFogExp2Density;
200 double mTaxiFogExp2Density;
201 double mGroundLightsFogExp2Density;
203 SGVec3f mLightDirection;
204 SGVec4f mAmbientLight;
205 SGVec4f mDiffuseLight;
206 SGVec4f mSpecularLight;