00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef SG_SCENE_UPDATEVISITOR_HXX
00023 #define SG_SCENE_UPDATEVISITOR_HXX
00024
00025 #include <osg/NodeVisitor>
00026 #include <osg/PagedLOD>
00027 #include <osgUtil/UpdateVisitor>
00028
00029 #include "simgear/math/SGMath.hxx"
00030
00031 class SGUpdateVisitor : public osgUtil::UpdateVisitor {
00032 public:
00033 SGUpdateVisitor() :
00034 mVisibility(-1)
00035 {
00036 setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
00037 setVisibility(10000);
00038 }
00039 void setViewData(const SGVec3d& globalEyePos,
00040 const SGQuatd& globalViewOrientation)
00041 {
00042 mGlobalGeodEyePos = SGGeod::fromCart(globalEyePos);
00043 _currentEyePos = toOsg(globalEyePos);
00044 mGlobalEyePos = globalEyePos;
00045 mGlobalViewOr = globalViewOrientation;
00046 mGlobalHorizLocalOr = SGQuatd::fromLonLat(mGlobalGeodEyePos);
00047 mHorizLocalNorth = mGlobalHorizLocalOr.backTransform(SGVec3d(1, 0, 0));
00048 mHorizLocalEast = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 1, 0));
00049 mHorizLocalDown = mGlobalHorizLocalOr.backTransform(SGVec3d(0, 0, 1));
00050 }
00051
00052 void setVisibility(double visibility)
00053 {
00054 if (mVisibility == visibility)
00055 return;
00056 mVisibility = visibility;
00057 mSqrVisibility = visibility*visibility;
00058
00059 double m_log01 = -log( 0.01 );
00060 double sqrt_m_log01 = sqrt( m_log01 );
00061 double fog_exp_density = m_log01 / visibility;
00062 double fog_exp2_density = sqrt_m_log01 / visibility;
00063 double ground_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
00064 double rwy_exp2_punch_through, taxi_exp2_punch_through;
00065 if ( visibility < 8000 ) {
00066 rwy_exp2_punch_through = sqrt_m_log01 / (visibility * 2.5);
00067 taxi_exp2_punch_through = sqrt_m_log01 / (visibility * 1.5);
00068 } else {
00069 rwy_exp2_punch_through = sqrt_m_log01 / ( 8000 * 2.5 );
00070 taxi_exp2_punch_through = sqrt_m_log01 / ( 8000 * 1.5 );
00071 }
00072
00073 mFogExpDensity = fog_exp_density;
00074 mFogExp2Density = fog_exp2_density;
00075 mRunwayFogExp2Density = rwy_exp2_punch_through;
00076 mTaxiFogExp2Density = taxi_exp2_punch_through;
00077 mGroundLightsFogExp2Density = ground_exp2_punch_through;
00078 }
00079
00080 double getVisibility() const
00081 { return mVisibility; }
00082 double getSqrVisibility() const
00083 { return mSqrVisibility; }
00084
00085 double getFogExpDensity() const
00086 { return mFogExpDensity; }
00087 double getFogExp2Density() const
00088 { return mFogExp2Density; }
00089 double getRunwayFogExp2Density() const
00090 { return mRunwayFogExp2Density; }
00091 double getTaxiFogExp2Density() const
00092 { return mTaxiFogExp2Density; }
00093 double getGroundLightsFogExp2Density() const
00094 { return mGroundLightsFogExp2Density; }
00095
00096 const SGVec3d& getGlobalEyePos() const
00097 { return mGlobalEyePos; }
00098 const SGGeod& getGeodEyePos() const
00099 { return mGlobalGeodEyePos; }
00100 const SGQuatd& getGlobalViewOr() const
00101 { return mGlobalViewOr; }
00102 const SGQuatd& getGlobalHorizLocalOr() const
00103 { return mGlobalViewOr; }
00104 const SGVec3d& getHorizLocalNorth() const
00105 { return mHorizLocalNorth; }
00106 const SGVec3d& getHorizLocalEast() const
00107 { return mHorizLocalEast; }
00108 const SGVec3d& getHorizLocalDown() const
00109 { return mHorizLocalDown; }
00110
00111 void setLight(const SGVec3f& direction, const SGVec4f& ambient,
00112 const SGVec4f& diffuse, const SGVec4f& specular,
00113 const SGVec4f& fogColor, double sunAngleDeg)
00114 {
00115 mLightDirection = direction;
00116 mAmbientLight = ambient;
00117 mDiffuseLight = diffuse;
00118 mSpecularLight = specular;
00119 mFogColor = fogColor;
00120 mSunAngleDeg = sunAngleDeg;
00121 }
00122
00123 const SGVec3f& getLightDirection() const
00124 { return mLightDirection; }
00125 const SGVec4f& getAmbientLight() const
00126 { return mAmbientLight; }
00127 const SGVec4f& getDiffuseLight() const
00128 { return mDiffuseLight; }
00129 const SGVec4f& getSpecularLight() const
00130 { return mSpecularLight; }
00131 const SGVec4f& getFogColor() const
00132 { return mFogColor; }
00133
00134 double getSunAngleDeg() const
00135 { return mSunAngleDeg; }
00136
00137 virtual void apply(osg::Node& node)
00138 {
00139 if (!needToEnterNode(node))
00140 return;
00141 osgUtil::UpdateVisitor::apply(node);
00142 }
00143
00144
00145
00146 virtual void apply(osg::PagedLOD& pagedLOD)
00147 {
00148 if (!needToEnterNode(pagedLOD))
00149 return;
00150 if (getFrameStamp())
00151 pagedLOD.setFrameNumberOfLastTraversal(getFrameStamp()->getFrameNumber());
00152 osgUtil::UpdateVisitor::apply(pagedLOD);
00153 }
00154
00155
00156 virtual void apply(osg::Transform& transform)
00157 {
00158 if (!needToEnterNode(transform))
00159 return;
00160 osg::Matrix matrix = _matrix;
00161 transform.computeLocalToWorldMatrix(_matrix, this);
00162 osgUtil::UpdateVisitor::apply(transform);
00163 _matrix = matrix;
00164 }
00165 virtual void apply(osg::Camera& camera)
00166 {
00167 if (!needToEnterNode(camera))
00168 return;
00169 if (camera.getReferenceFrame() == osg::Camera::ABSOLUTE_RF) {
00170 osg::Vec3d currentEyePos = _currentEyePos;
00171 _currentEyePos = osg::Vec3d(0, 0, 0);
00172 apply(static_cast<osg::Transform&>(camera));
00173 _currentEyePos = currentEyePos;
00174 } else {
00175 apply(static_cast<osg::Transform&>(camera));
00176 }
00177 }
00178
00179
00180 virtual float getDistanceToViewPoint(const osg::Vec3& pos, bool) const
00181 { return (_currentEyePos - _matrix.preMult(osg::Vec3d(pos))).length(); }
00182
00183 protected:
00184 bool needToEnterNode(const osg::Node& node) const
00185 {
00186 if (!node.isCullingActive())
00187 return true;
00188 return isSphereInRange(node.getBound());
00189 }
00190 bool isSphereInRange(const osg::BoundingSphere& sphere) const
00191 {
00192 if (!sphere.valid())
00193 return false;
00194 float maxDist = mVisibility + sphere._radius;
00195 osg::Vec3d center = _matrix.preMult(osg::Vec3d(sphere._center));
00196 return (_currentEyePos - center).length2() <= maxDist*maxDist;
00197 }
00198
00199 private:
00200 osg::Matrix _matrix;
00201 osg::Vec3d _currentEyePos;
00202
00203 SGGeod mGlobalGeodEyePos;
00204 SGVec3d mGlobalEyePos;
00205 SGQuatd mGlobalViewOr;
00206 SGQuatd mGlobalHorizLocalOr;
00207 SGVec3d mHorizLocalNorth;
00208 SGVec3d mHorizLocalEast;
00209 SGVec3d mHorizLocalDown;
00210
00211 double mVisibility;
00212 double mSqrVisibility;
00213 double mFogExpDensity;
00214 double mFogExp2Density;
00215 double mRunwayFogExp2Density;
00216 double mTaxiFogExp2Density;
00217 double mGroundLightsFogExp2Density;
00218
00219 SGVec3f mLightDirection;
00220 SGVec4f mAmbientLight;
00221 SGVec4f mDiffuseLight;
00222 SGVec4f mSpecularLight;
00223 SGVec4f mFogColor;
00224
00225 double mSunAngleDeg;
00226 };
00227
00228 #endif