@ -35,6 +35,7 @@
# include <components/sceneutil/util.hpp>
# include <components/sceneutil/statesetupdater.hpp>
# include <components/sceneutil/controller.hpp>
# include <components/sceneutil/visitor.hpp>
# include "../mwbase/environment.hpp"
# include "../mwbase/world.hpp"
@ -261,8 +262,18 @@ public:
META_Node ( MWRender , CameraRelativeTransform )
virtual bool computeLocalToWorldMatrix ( osg : : Matrix & matrix , osg : : NodeVisitor * ) const
const osg : : Vec3f & getLastEyePoint ( ) const
{
return mEyePoint ;
}
virtual bool computeLocalToWorldMatrix ( osg : : Matrix & matrix , osg : : NodeVisitor * nv ) const
{
if ( nv - > getVisitorType ( ) = = osg : : NodeVisitor : : CULL_VISITOR )
{
mEyePoint = static_cast < osgUtil : : CullVisitor * > ( nv ) - > getEyePoint ( ) ;
}
if ( _referenceFrame = = RELATIVE_RF )
{
matrix . setTrans ( osg : : Vec3f ( 0.f , 0.f , 0.f ) ) ;
@ -321,6 +332,9 @@ public:
cv - > getCurrentCullingSet ( ) . popCurrentMask ( ) ;
}
} ;
private :
// eyePoint for the current frame
mutable osg : : Vec3f mEyePoint ;
} ;
class ModVertexAlphaVisitor : public osg : : NodeVisitor
@ -370,6 +384,45 @@ private:
int mMeshType ;
} ;
/// @brief Hides the node subgraph if the eye point is below water.
/// @note Must be added as cull callback.
/// @note Meant to be used on a node that is child of a CameraRelativeTransform.
/// The current eye point must be retrieved by the CameraRelativeTransform since we can't get it anymore once we are in camera-relative space.
class UnderwaterSwitchCallback : public osg : : NodeCallback
{
public :
UnderwaterSwitchCallback ( CameraRelativeTransform * cameraRelativeTransform )
: mCameraRelativeTransform ( cameraRelativeTransform )
, mEnabled ( true )
, mWaterLevel ( 0.f )
{
}
virtual void operator ( ) ( osg : : Node * node , osg : : NodeVisitor * nv )
{
osg : : Vec3f eyePoint = mCameraRelativeTransform - > getLastEyePoint ( ) ;
if ( mEnabled & & eyePoint . z ( ) < mWaterLevel )
return ;
traverse ( node , nv ) ;
}
void setEnabled ( bool enabled )
{
mEnabled = enabled ;
}
void setWaterLevel ( float waterLevel )
{
mWaterLevel = waterLevel ;
}
private :
osg : : ref_ptr < CameraRelativeTransform > mCameraRelativeTransform ;
bool mEnabled ;
float mWaterLevel ;
} ;
/// A base class for the sun and moons.
class CelestialBody
{
@ -1065,18 +1118,21 @@ SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneMana
mRootNode = skyroot ;
// By default render before the world is rendered
mRootNode - > getOrCreateStateSet ( ) - > setRenderBinDetails ( RenderBin_Sky , " RenderBin " ) ;
mEarlyRenderBinRoot = new osg : : Group ;
// render before the world is rendered
mEarlyRenderBinRoot - > getOrCreateStateSet ( ) - > setRenderBinDetails ( RenderBin_Sky , " RenderBin " ) ;
// Prevent unwanted clipping by water reflection camera's clipping plane
mRootNode - > getOrCreateStateSet ( ) - > setMode ( GL_CLIP_PLANE0 , osg : : StateAttribute : : OFF ) ;
mEarlyRenderBinRoot - > getOrCreateStateSet ( ) - > setMode ( GL_CLIP_PLANE0 , osg : : StateAttribute : : OFF ) ;
mRootNode - > addChild ( mEarlyRenderBinRoot ) ;
mUnderwaterSwitch = new UnderwaterSwitchCallback ( skyroot ) ;
}
void SkyManager : : create ( )
{
assert ( ! mCreated ) ;
mAtmosphereDay = mSceneManager - > createInstance ( " meshes/sky_atmosphere.nif " , m RootNode ) ;
mAtmosphereDay = mSceneManager - > createInstance ( " meshes/sky_atmosphere.nif " , m EarlyRenderBin Root) ;
ModVertexAlphaVisitor modAtmosphere ( 0 ) ;
mAtmosphereDay - > accept ( modAtmosphere ) ;
@ -1085,7 +1141,7 @@ void SkyManager::create()
mAtmosphereNightNode = new osg : : PositionAttitudeTransform ;
mAtmosphereNightNode - > setNodeMask ( 0 ) ;
m RootNode - > addChild ( mAtmosphereNightNode ) ;
m EarlyRenderBin Root- > addChild ( mAtmosphereNightNode ) ;
osg : : ref_ptr < osg : : Node > atmosphereNight ;
if ( mSceneManager - > getVFS ( ) - > exists ( " meshes/sky_night_02.nif " ) )
@ -1098,14 +1154,14 @@ void SkyManager::create()
mAtmosphereNightUpdater = new AtmosphereNightUpdater ( mSceneManager - > getTextureManager ( ) ) ;
atmosphereNight - > addUpdateCallback ( mAtmosphereNightUpdater ) ;
mSun . reset ( new Sun ( m RootNode , * mSceneManager - > getTextureManager ( ) ) ) ;
mSun . reset ( new Sun ( m EarlyRenderBin Root, * mSceneManager - > getTextureManager ( ) ) ) ;
const MWWorld : : Fallback * fallback = MWBase : : Environment : : get ( ) . getWorld ( ) - > getFallback ( ) ;
mMasser . reset ( new Moon ( m RootNode , * mSceneManager - > getTextureManager ( ) , fallback - > getFallbackFloat ( " Moons_Masser_Size " ) / 125 , Moon : : Type_Masser ) ) ;
mSecunda . reset ( new Moon ( m RootNode , * mSceneManager - > getTextureManager ( ) , fallback - > getFallbackFloat ( " Moons_Secunda_Size " ) / 125 , Moon : : Type_Secunda ) ) ;
mMasser . reset ( new Moon ( m EarlyRenderBin Root, * mSceneManager - > getTextureManager ( ) , fallback - > getFallbackFloat ( " Moons_Masser_Size " ) / 125 , Moon : : Type_Masser ) ) ;
mSecunda . reset ( new Moon ( m EarlyRenderBin Root, * mSceneManager - > getTextureManager ( ) , fallback - > getFallbackFloat ( " Moons_Secunda_Size " ) / 125 , Moon : : Type_Secunda ) ) ;
mCloudNode = new osg : : PositionAttitudeTransform ;
m RootNode - > addChild ( mCloudNode ) ;
m EarlyRenderBin Root- > addChild ( mCloudNode ) ;
mCloudMesh = mSceneManager - > createInstance ( " meshes/sky_clouds_01.nif " , mCloudNode ) ;
ModVertexAlphaVisitor modClouds ( 1 ) ;
mCloudMesh - > accept ( modClouds ) ;
@ -1122,9 +1178,9 @@ void SkyManager::create()
osg : : ref_ptr < osg : : Depth > depth = new osg : : Depth ;
depth - > setWriteMask ( false ) ;
m RootNode - > getOrCreateStateSet ( ) - > setAttributeAndModes ( depth , osg : : StateAttribute : : ON ) ;
m RootNode - > getOrCreateStateSet ( ) - > setMode ( GL_BLEND , osg : : StateAttribute : : ON ) ;
m RootNode - > getOrCreateStateSet ( ) - > setMode ( GL_FOG , osg : : StateAttribute : : OFF ) ;
m EarlyRenderBin Root- > getOrCreateStateSet ( ) - > setAttributeAndModes ( depth , osg : : StateAttribute : : ON ) ;
m EarlyRenderBin Root- > getOrCreateStateSet ( ) - > setMode ( GL_BLEND , osg : : StateAttribute : : ON ) ;
m EarlyRenderBin Root- > getOrCreateStateSet ( ) - > setMode ( GL_FOG , osg : : StateAttribute : : OFF ) ;
mMoonScriptColor = fallback - > getFallbackColour ( " Moons_Script_Color " ) ;
@ -1196,14 +1252,13 @@ public:
mat - > setDiffuse ( osg : : Material : : FRONT_AND_BACK , osg : : Vec4f ( 0 , 0 , 0 , mAlpha ) ) ;
}
// Helper for adding AlphaFader to a subgraph
// Helper for adding AlphaFader s to a subgraph
class SetupVisitor : public osg : : NodeVisitor
{
public :
SetupVisitor ( )
: osg : : NodeVisitor ( TRAVERSE_ALL_CHILDREN )
{
mAlphaFader = new AlphaFader ;
}
virtual void apply ( osg : : Node & node )
@ -1225,22 +1280,26 @@ public:
callback = callback - > getNestedCallback ( ) ;
}
osg : : ref_ptr < AlphaFader > alphaFader ( new AlphaFader ) ;
if ( composite )
composite - > addController ( mAlphaFader ) ;
composite - > addController ( a lphaFader) ;
else
node . addUpdateCallback ( mAlphaFader ) ;
node . addUpdateCallback ( alphaFader ) ;
mAlphaFaders . push_back ( alphaFader ) ;
}
}
traverse ( node ) ;
}
osg: : ref_ptr < AlphaFader > getAlphaFader ( )
std: : vector < osg: : ref_ptr < AlphaFader > > getAlphaFader s ( )
{
return mAlphaFader ;
return mAlphaFader s ;
}
private :
osg: : ref_ptr < AlphaFader > mAlphaFader ;
std: : vector < osg: : ref_ptr < AlphaFader > > mAlphaFader s ;
} ;
private :
@ -1278,6 +1337,7 @@ void SkyManager::createRain()
stateset - > setNestRenderBins ( false ) ;
stateset - > setRenderingHint ( osg : : StateSet : : TRANSPARENT_BIN ) ;
stateset - > setMode ( GL_CULL_FACE , osg : : StateAttribute : : OFF ) ;
stateset - > setMode ( GL_BLEND , osg : : StateAttribute : : ON ) ;
osgParticle : : Particle & particleTemplate = mRainParticleSystem - > getDefaultParticleTemplate ( ) ;
particleTemplate . setSizeRange ( osgParticle : : rangef ( 5.f , 15.f ) ) ;
@ -1313,6 +1373,8 @@ void SkyManager::createRain()
mRainFader = new RainFader ;
mRainNode - > addUpdateCallback ( mRainFader ) ;
mRainNode - > addCullCallback ( mUnderwaterSwitch ) ;
mRainNode - > setNodeMask ( Mask_WeatherParticles ) ;
mRootNode - > addChild ( mRainNode ) ;
}
@ -1432,6 +1494,14 @@ void SkyManager::setWeather(const WeatherResult& weather)
{
mCurrentParticleEffect = weather . mParticleEffect ;
// cleanup old particles
if ( mParticleEffect )
{
mParticleNode - > removeChild ( mParticleEffect ) ;
mParticleEffect = NULL ;
mParticleFaders . clear ( ) ;
}
if ( mCurrentParticleEffect . empty ( ) )
{
if ( mParticleNode )
@ -1439,14 +1509,14 @@ void SkyManager::setWeather(const WeatherResult& weather)
mRootNode - > removeChild ( mParticleNode ) ;
mParticleNode = NULL ;
}
mParticleEffect = NULL ;
mParticleFader = NULL ;
}
else
{
if ( ! mParticleNode )
{
mParticleNode = new osg : : PositionAttitudeTransform ;
mParticleNode - > addCullCallback ( mUnderwaterSwitch ) ;
mParticleNode - > setNodeMask ( Mask_WeatherParticles ) ;
mRootNode - > addChild ( mParticleNode ) ;
}
mParticleEffect = mSceneManager - > createInstance ( mCurrentParticleEffect , mParticleNode ) ;
@ -1456,7 +1526,10 @@ void SkyManager::setWeather(const WeatherResult& weather)
AlphaFader : : SetupVisitor alphaFaderSetupVisitor ;
mParticleEffect - > accept ( alphaFaderSetupVisitor ) ;
mParticleFader = alphaFaderSetupVisitor . getAlphaFader ( ) ;
mParticleFaders = alphaFaderSetupVisitor . getAlphaFaders ( ) ;
SceneUtil : : DisableFreezeOnCullVisitor disableFreezeOnCullVisitor ;
mParticleEffect - > accept ( disableFreezeOnCullVisitor ) ;
}
}
@ -1537,8 +1610,8 @@ void SkyManager::setWeather(const WeatherResult& weather)
if ( mRainFader )
mRainFader - > setAlpha ( weather . mEffectFade * 0.6 ) ; // * Rain_Threshold?
if ( mParticleFader )
mParticleFader - > setAlpha ( weather . mEffectFade ) ;
for ( std : : vector < osg : : ref_ptr < AlphaFader > > : : const_iterator it = mParticleFaders . begin ( ) ; it ! = mParticleFaders . end ( ) ; + + it )
( * it ) - > setAlpha ( weather . mEffectFade ) ;
}
void SkyManager : : sunEnable ( )
@ -1592,4 +1665,14 @@ void SkyManager::setGlareTimeOfDayFade(float val)
mSun - > setGlareTimeOfDayFade ( val ) ;
}
void SkyManager : : setWaterHeight ( float height )
{
mUnderwaterSwitch - > setWaterLevel ( height ) ;
}
void SkyManager : : setWaterEnabled ( bool enabled )
{
mUnderwaterSwitch - > setEnabled ( enabled ) ;
}
}