3 * Copyright (C) 2006 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 // To be able to traverse correctly only the active children, we need to
137 // track the model view matrices during update.
138 virtual void apply(osg::Transform& transform)
140 osg::Matrix matrix = _matrix;
141 transform.computeLocalToWorldMatrix(_matrix, this);
142 osgUtil::UpdateVisitor::apply(transform);
145 virtual void apply(osg::Camera& camera)
147 if (camera.getReferenceFrame() == osg::Camera::ABSOLUTE_RF) {
148 osg::Vec3d currentEyePos = _currentEyePos;
149 _currentEyePos = osg::Vec3d(0, 0, 0);
150 apply(static_cast<osg::Transform&>(camera));
151 _currentEyePos = currentEyePos;
153 apply(static_cast<osg::Transform&>(camera));
156 virtual float getDistanceToViewPoint(const osg::Vec3& pos, bool) const
157 { return (_currentEyePos - _matrix.preMult(osg::Vec3d(pos))).length(); }
161 osg::Vec3d _currentEyePos;
163 SGGeod mGlobalGeodEyePos;
164 SGVec3d mGlobalEyePos;
165 SGQuatd mGlobalViewOr;
166 SGQuatd mGlobalHorizLocalOr;
167 SGVec3d mHorizLocalNorth;
168 SGVec3d mHorizLocalEast;
169 SGVec3d mHorizLocalDown;
172 double mSqrVisibility;
173 double mFogExpDensity;
174 double mFogExp2Density;
175 double mRunwayFogExp2Density;
176 double mTaxiFogExp2Density;
177 double mGroundLightsFogExp2Density;
179 SGVec3f mLightDirection;
180 SGVec4f mAmbientLight;
181 SGVec4f mDiffuseLight;
182 SGVec4f mSpecularLight;