1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-16 02:19:55 +00:00
openmw-tes3mp/apps/openmw/mwrender/sky.cpp
dteviot 3f28634d1f consolidate random number logic
Note, I suspect Rng::rollClosedProbability() is not needed.  The only difference between it and rollProbability() is that one time in 37k (on Windows), it will give an output of 1.0.
On some versions of Linux, the value of 1.0 will occur about 1 time in 4 billion.
2015-03-15 14:07:47 +13:00

874 lines
29 KiB
C++

#include "sky.hpp"
#include <OgreCamera.h>
#include <OgreRenderWindow.h>
#include <OgreSceneNode.h>
#include <OgreMesh.h>
#include <OgreSubMesh.h>
#include <OgreSceneManager.h>
#include <OgreHardwareVertexBuffer.h>
#include <OgreHighLevelGpuProgramManager.h>
#include <OgreParticle.h>
#include <OgreParticleSystem.h>
#include <OgreEntity.h>
#include <OgreSubEntity.h>
#include <OgreTechnique.h>
#include <OgreControllerManager.h>
#include <OgreMeshManager.h>
#include <boost/lexical_cast.hpp>
#include <openengine/misc/rng.hpp>
#include <components/nifogre/ogrenifloader.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <extern/shiny/Platforms/Ogre/OgreMaterial.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwworld/fallback.hpp"
#include "renderconst.hpp"
#include "renderingmanager.hpp"
using namespace MWRender;
using namespace Ogre;
namespace
{
void setAlpha (NifOgre::ObjectScenePtr scene, Ogre::MovableObject* movable, float alpha)
{
Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(movable);
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
Ogre::Technique::PassIterator passes = tech->getPassIterator();
while(passes.hasMoreElements())
{
Ogre::Pass *pass = passes.getNext();
Ogre::ColourValue diffuse = pass->getDiffuse();
diffuse.a = alpha;
pass->setDiffuse(diffuse);
}
}
}
void setAlpha (NifOgre::ObjectScenePtr scene, float alpha)
{
for(size_t i = 0; i < scene->mParticles.size(); ++i)
setAlpha(scene, scene->mParticles[i], alpha);
for(size_t i = 0; i < scene->mEntities.size(); ++i)
{
if (scene->mEntities[i] != scene->mSkelBase)
setAlpha(scene, scene->mEntities[i], alpha);
}
}
}
BillboardObject::BillboardObject( const String& textureName,
const float initialSize,
const Vector3& position,
SceneNode* rootNode,
const std::string& material)
: mVisibility(1.0f)
{
SceneManager* sceneMgr = rootNode->getCreator();
Vector3 finalPosition = position.normalisedCopy() * 1000.f;
static unsigned int bodyCount=0;
mMaterial = sh::Factory::getInstance().createMaterialInstance ("BillboardMaterial"+StringConverter::toString(bodyCount), material);
mMaterial->setProperty("texture", sh::makeProperty(new sh::StringValue(textureName)));
static Ogre::Mesh* plane = MeshManager::getSingleton().createPlane("billboard",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::Plane(Ogre::Vector3(0,0,1), 0), 1, 1, 1, 1, true, 1, 1, 1, Vector3::UNIT_Y).get();
plane->_setBounds(Ogre::AxisAlignedBox::BOX_INFINITE);
mEntity = sceneMgr->createEntity("billboard");
mEntity->setMaterialName("BillboardMaterial"+StringConverter::toString(bodyCount));
mEntity->setVisibilityFlags(RV_Sky);
mEntity->setCastShadows(false);
mNode = rootNode->createChildSceneNode();
mNode->setPosition(finalPosition);
mNode->attachObject(mEntity);
mNode->setScale(Ogre::Vector3(450.f*initialSize));
mNode->setOrientation(Ogre::Vector3::UNIT_Z.getRotationTo(-position.normalisedCopy()));
sh::Factory::getInstance().getMaterialInstance ("BillboardMaterial"+StringConverter::toString(bodyCount))->setListener(this);
bodyCount++;
}
void BillboardObject::requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration)
{
}
void BillboardObject::createdConfiguration (sh::MaterialInstance* m, const std::string& configuration)
{
setVisibility(mVisibility);
setColour(mColour);
}
void BillboardObject::setVisible(const bool visible)
{
mEntity->setVisible(visible);
}
void BillboardObject::setSize(const float size)
{
mNode->setScale(450.f*size, 450.f*size, 450.f*size);
}
void BillboardObject::setVisibility(const float visibility)
{
mVisibility = visibility;
Ogre::MaterialPtr m = static_cast<sh::OgreMaterial*>(mMaterial->getMaterial ())->getOgreMaterial ();
for (int i=0; i<m->getNumTechniques(); ++i)
{
Ogre::Technique* t = m->getTechnique(i);
if (t->getNumPasses ())
t->getPass(0)->setDiffuse (0,0,0, visibility);
}
}
void BillboardObject::setPosition(const Vector3& pPosition)
{
Vector3 normalised = pPosition.normalisedCopy();
Vector3 finalPosition = normalised * 1000.f;
mNode->setOrientation(Ogre::Vector3::UNIT_Z.getRotationTo(-normalised));
mNode->setPosition(finalPosition);
}
Vector3 BillboardObject::getPosition() const
{
return mNode->getPosition();
}
void BillboardObject::setVisibilityFlags(int flags)
{
mEntity->setVisibilityFlags(flags);
}
void BillboardObject::setColour(const ColourValue& pColour)
{
mColour = pColour;
Ogre::MaterialPtr m = static_cast<sh::OgreMaterial*>(mMaterial->getMaterial ())->getOgreMaterial ();
for (int i=0; i<m->getNumTechniques(); ++i)
{
Ogre::Technique* t = m->getTechnique(i);
if (t->getNumPasses ())
t->getPass(0)->setSelfIllumination (pColour);
}
}
void BillboardObject::setRenderQueue(unsigned int id)
{
mEntity->setRenderQueueGroup(id);
}
SceneNode* BillboardObject::getNode()
{
return mNode;
}
Moon::Moon( const String& textureName,
const float initialSize,
const Vector3& position,
SceneNode* rootNode,
const std::string& material)
: BillboardObject(textureName, initialSize, position, rootNode, material)
, mType(Type_Masser)
{
setVisibility(1.0);
mMaterial->setProperty("alphatexture", sh::makeProperty(new sh::StringValue(textureName + "_alpha")));
mPhase = Moon::Phase_Full;
}
void Moon::setType(const Moon::Type& type)
{
mType = type;
}
void Moon::setPhase(const Moon::Phase& phase)
{
// Colour texture
Ogre::String textureName = "textures\\tx_";
if (mType == Moon::Type_Secunda) textureName += "secunda_";
else textureName += "masser_";
if (phase == Moon::Phase_New) textureName += "new";
else if (phase == Moon::Phase_WaxingCrescent) textureName += "one_wax";
else if (phase == Moon::Phase_WaxingHalf) textureName += "half_wax";
else if (phase == Moon::Phase_WaxingGibbous) textureName += "three_wax";
else if (phase == Moon::Phase_WaningCrescent) textureName += "one_wan";
else if (phase == Moon::Phase_WaningHalf) textureName += "half_wan";
else if (phase == Moon::Phase_WaningGibbous) textureName += "three_wan";
else if (phase == Moon::Phase_Full) textureName += "full";
textureName += ".dds";
if (mType == Moon::Type_Secunda)
{
sh::Factory::getInstance ().setTextureAlias ("secunda_texture", textureName);
sh::Factory::getInstance ().setTextureAlias ("secunda_texture_alpha", "textures\\tx_mooncircle_full_s.dds");
}
else
{
sh::Factory::getInstance ().setTextureAlias ("masser_texture", textureName);
sh::Factory::getInstance ().setTextureAlias ("masser_texture_alpha", "textures\\tx_mooncircle_full_m.dds");
}
mPhase = phase;
}
unsigned int Moon::getPhaseInt() const
{
if (mPhase == Moon::Phase_New) return 0;
else if (mPhase == Moon::Phase_WaxingCrescent) return 1;
else if (mPhase == Moon::Phase_WaningCrescent) return 1;
else if (mPhase == Moon::Phase_WaxingHalf) return 2;
else if (mPhase == Moon::Phase_WaningHalf) return 2;
else if (mPhase == Moon::Phase_WaxingGibbous) return 3;
else if (mPhase == Moon::Phase_WaningGibbous) return 3;
else if (mPhase == Moon::Phase_Full) return 4;
return 0;
}
SkyManager::SkyManager(Ogre::SceneNode *root, Ogre::Camera *pCamera)
: mHour(0.0f)
, mDay(0)
, mMonth(0)
, mSun(NULL)
, mSunGlare(NULL)
, mMasser(NULL)
, mSecunda(NULL)
, mCamera(pCamera)
, mRootNode(NULL)
, mSceneMgr(NULL)
, mAtmosphereDay(NULL)
, mAtmosphereNight(NULL)
, mCloudNode(NULL)
, mClouds()
, mNextClouds()
, mCloudBlendFactor(0.0f)
, mCloudOpacity(0.0f)
, mCloudSpeed(0.0f)
, mStarsOpacity(0.0f)
, mLightning(NULL)
, mRemainingTransitionTime(0.0f)
, mGlareFade(0.0f)
, mGlare(0.0f)
, mEnabled(true)
, mSunEnabled(true)
, mMasserEnabled(true)
, mSecundaEnabled(true)
, mCreated(false)
, mCloudAnimationTimer(0.f)
, mMoonRed(false)
, mParticleNode(NULL)
, mRainEnabled(false)
, mRainTimer(0)
, mRainSpeed(0)
, mRainFrequency(1)
, mStormDirection(0,-1,0)
, mIsStorm(false)
{
mSceneMgr = root->getCreator();
mRootNode = mSceneMgr->getRootSceneNode()->createChildSceneNode();
}
void SkyManager::create()
{
assert(!mCreated);
sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance().setSharedParameter ("cloudOpacity",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(1)));
sh::Factory::getInstance().setSharedParameter ("cloudColour",
sh::makeProperty<sh::Vector3>(new sh::Vector3(1,1,1)));
sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance().setSharedParameter ("nightFade",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(0)));
sh::Factory::getInstance().setSharedParameter ("atmosphereColour", sh::makeProperty<sh::Vector4>(new sh::Vector4(0,0,0,1)));
sh::Factory::getInstance().setSharedParameter ("horizonColour", sh::makeProperty<sh::Vector4>(new sh::Vector4(0,0,0,1)));
sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", "");
sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", "");
// Create light used for thunderstorm
mLightning = mSceneMgr->createLight();
mLightning->setType (Ogre::Light::LT_DIRECTIONAL);
mLightning->setDirection (Ogre::Vector3(0.3f, -0.7f, 0.3f));
mLightning->setVisible (false);
mLightning->setDiffuseColour (ColourValue(3,3,3));
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
mSecunda = new Moon("secunda_texture", fallback->getFallbackFloat("Moons_Secunda_Size")/100, Vector3(-0.4f, 0.4f, 0.5f), mRootNode, "openmw_moon");
mSecunda->setType(Moon::Type_Secunda);
mSecunda->setRenderQueue(RQG_SkiesEarly+4);
mMasser = new Moon("masser_texture", fallback->getFallbackFloat("Moons_Masser_Size")/100, Vector3(-0.4f, 0.4f, 0.5f), mRootNode, "openmw_moon");
mMasser->setRenderQueue(RQG_SkiesEarly+3);
mMasser->setType(Moon::Type_Masser);
mSun = new BillboardObject("textures\\tx_sun_05.dds", 1, Vector3(0.4f, 0.4f, 0.4f), mRootNode, "openmw_sun");
mSun->setRenderQueue(RQG_SkiesEarly+4);
mSunGlare = new BillboardObject("textures\\tx_sun_flash_grey_05.dds", 3, Vector3(0.4f, 0.4f, 0.4f), mRootNode, "openmw_sun");
mSunGlare->setRenderQueue(RQG_SkiesLate);
mSunGlare->setVisibilityFlags(RV_NoReflection);
Ogre::AxisAlignedBox aabInf = Ogre::AxisAlignedBox::BOX_INFINITE;
// Stars
mAtmosphereNight = mRootNode->createChildSceneNode();
NifOgre::ObjectScenePtr objects;
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("meshes\\sky_night_02.nif"))
objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_02.nif");
else
objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_01.nif");
for(size_t i = 0, matidx = 0;i < objects->mEntities.size();i++)
{
Entity* night1_ent = objects->mEntities[i];
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
night1_ent->setVisibilityFlags(RV_Sky);
night1_ent->setCastShadows(false);
night1_ent->getMesh()->_setBounds (aabInf);
for (unsigned int j=0; j<night1_ent->getNumSubEntities(); ++j)
{
std::string matName = "openmw_stars_" + boost::lexical_cast<std::string>(matidx++);
sh::MaterialInstance* m = sh::Factory::getInstance().createMaterialInstance(matName, "openmw_stars");
std::string textureName = sh::retrieveValue<sh::StringValue>(
sh::Factory::getInstance().getMaterialInstance(night1_ent->getSubEntity(j)->getMaterialName())->getProperty("diffuseMap"), NULL).get();
m->setProperty("texture", sh::makeProperty<sh::StringValue>(new sh::StringValue(textureName)));
night1_ent->getSubEntity(j)->setMaterialName(matName);
}
}
mObjects.push_back(objects);
// Atmosphere (day)
mAtmosphereDay = mRootNode->createChildSceneNode();
objects = NifOgre::Loader::createObjects(mAtmosphereDay, "meshes\\sky_atmosphere.nif");
for(size_t i = 0;i < objects->mEntities.size();i++)
{
Entity* atmosphere_ent = objects->mEntities[i];
atmosphere_ent->setCastShadows(false);
atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly);
atmosphere_ent->setVisibilityFlags(RV_Sky);
for(unsigned int j = 0;j < atmosphere_ent->getNumSubEntities();j++)
atmosphere_ent->getSubEntity (j)->setMaterialName("openmw_atmosphere");
// Using infinite AAB here to prevent being clipped by the custom near clip plane used for reflections/refractions
atmosphere_ent->getMesh()->_setBounds (aabInf);
}
mObjects.push_back(objects);
// Clouds
mCloudNode = mRootNode->createChildSceneNode();
objects = NifOgre::Loader::createObjects(mCloudNode, "meshes\\sky_clouds_01.nif");
for(size_t i = 0;i < objects->mEntities.size();i++)
{
Entity* clouds_ent = objects->mEntities[i];
clouds_ent->setVisibilityFlags(RV_Sky);
clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5);
for(unsigned int j = 0;j < clouds_ent->getNumSubEntities();j++)
clouds_ent->getSubEntity(j)->setMaterialName("openmw_clouds");
clouds_ent->setCastShadows(false);
// Using infinite AAB here to prevent being clipped by the custom near clip plane used for reflections/refractions
clouds_ent->getMesh()->_setBounds (aabInf);
}
mObjects.push_back(objects);
mCreated = true;
}
SkyManager::~SkyManager()
{
clearRain();
delete mSun;
delete mSunGlare;
delete mMasser;
delete mSecunda;
}
int SkyManager::getMasserPhase() const
{
if (!mCreated) return 0;
return mMasser->getPhaseInt();
}
int SkyManager::getSecundaPhase() const
{
if (!mCreated) return 0;
return mSecunda->getPhaseInt();
}
void SkyManager::clearRain()
{
for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end();)
{
it->second.setNull();
mSceneMgr->destroySceneNode(it->first);
mRainModels.erase(it++);
}
}
void SkyManager::updateRain(float dt)
{
// Move existing rain
// Note: if rain gets disabled, we let the existing rain drops finish falling down.
float minHeight = 200;
for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end();)
{
Ogre::Vector3 pos = it->first->getPosition();
pos.z -= mRainSpeed * dt;
it->first->setPosition(pos);
if (pos.z < -minHeight
// Here we might want to add a "splash" effect later
|| MWBase::Environment::get().getWorld()->isUnderwater(
MWBase::Environment::get().getWorld()->getPlayerPtr().getCell(), it->first->_getDerivedPosition()))
{
it->second.setNull();
mSceneMgr->destroySceneNode(it->first);
mRainModels.erase(it++);
}
else
++it;
}
// Spawn new rain
float rainFrequency = mRainFrequency;
if (mRainEnabled)
{
mRainTimer += dt;
if (mRainTimer >= 1.f/rainFrequency)
{
mRainTimer = 0;
// TODO: handle rain settings from Morrowind.ini
const float rangeRandom = 100;
float xOffs = OEngine::Misc::Rng::rollProbability() * rangeRandom - (rangeRandom / 2);
float yOffs = OEngine::Misc::Rng::rollProbability() * rangeRandom - (rangeRandom / 2);
// Create a separate node to control the offset, since a node with setInheritOrientation(false) will still
// consider the orientation of the parent node for its position, just not for its orientation
float startHeight = 700;
Ogre::Vector3 worldPos = mParticleNode->_getDerivedPosition();
worldPos += Ogre::Vector3(xOffs, yOffs, startHeight);
if (MWBase::Environment::get().getWorld()->isUnderwater(
MWBase::Environment::get().getWorld()->getPlayerPtr().getCell(), worldPos))
return;
Ogre::SceneNode* offsetNode = mParticleNode->createChildSceneNode(Ogre::Vector3(xOffs,yOffs,startHeight));
// Spawn a new rain object for each instance.
// TODO: this is inefficient. We could try to use an Ogre::ParticleSystem instead, but then we would need to make assumptions
// about the rain meshes being Quads and their dimensions.
// Or we could clone meshes into one vertex buffer manually.
NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(offsetNode, mRainEffect);
for (unsigned int i=0; i<objects->mEntities.size(); ++i)
{
objects->mEntities[i]->setRenderQueueGroup(RQG_Alpha);
objects->mEntities[i]->setVisibilityFlags(RV_Sky);
}
for (unsigned int i=0; i<objects->mParticles.size(); ++i)
{
objects->mParticles[i]->setRenderQueueGroup(RQG_Alpha);
objects->mParticles[i]->setVisibilityFlags(RV_Sky);
}
mRainModels[offsetNode] = objects;
}
}
}
void SkyManager::update(float duration)
{
if (!mEnabled) return;
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
if (!mParticle.isNull())
{
for (unsigned int i=0; i<mParticle->mControllers.size(); ++i)
mParticle->mControllers[i].update();
for (unsigned int i=0; i<mParticle->mParticles.size(); ++i)
{
Ogre::ParticleSystem* psys = mParticle->mParticles[i];
Ogre::ParticleIterator pi = psys->_getIterator();
while (!pi.end())
{
Ogre::Particle *p = pi.getNext();
#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0)
Ogre::Vector3 pos = p->mPosition;
Ogre::Real& timeToLive = p->mTimeToLive;
#else
Ogre::Vector3 pos = p->position;
Ogre::Real& timeToLive = p->timeToLive;
#endif
if (psys->getKeepParticlesInLocalSpace() && psys->getParentNode())
pos = psys->getParentNode()->convertLocalToWorldPosition(pos);
if (MWBase::Environment::get().getWorld()->isUnderwater(
MWBase::Environment::get().getWorld()->getPlayerPtr().getCell(), pos))
timeToLive = 0;
}
}
if (mIsStorm)
mParticleNode->setOrientation(Ogre::Vector3::UNIT_Y.getRotationTo(mStormDirection));
}
if (mIsStorm)
mCloudNode->setOrientation(Ogre::Vector3::UNIT_Y.getRotationTo(mStormDirection));
else
mCloudNode->setOrientation(Ogre::Quaternion::IDENTITY);
updateRain(duration);
// UV Scroll the clouds
mCloudAnimationTimer += duration * mCloudSpeed;
sh::Factory::getInstance().setSharedParameter ("cloudAnimationTimer",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(mCloudAnimationTimer)));
/// \todo improve this
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
mSecunda->setColour ( mMoonRed ? fallback->getFallbackColour("Moons_Script_Color") : ColourValue(1,1,1,1));
mMasser->setColour (ColourValue(1,1,1,1));
if (mSunEnabled)
{
// take 1/10 sec for fading the glare effect from invisible to full
if (mGlareFade > mGlare)
{
mGlareFade -= duration*10;
if (mGlareFade < mGlare) mGlareFade = mGlare;
}
else if (mGlareFade < mGlare)
{
mGlareFade += duration*10;
if (mGlareFade > mGlare) mGlareFade = mGlare;
}
// increase the strength of the sun glare effect depending
// on how directly the player is looking at the sun
Vector3 sun = mSunGlare->getPosition();
Vector3 cam = mCamera->getRealDirection();
const Degree angle = sun.angleBetween( cam );
float val = 1- (angle.valueDegrees() / 180.f);
val = (val*val*val*val)*6;
mSunGlare->setSize(val * mGlareFade);
}
mSunGlare->setVisible(mSunEnabled);
mSun->setVisible(mSunEnabled);
mMasser->setVisible(mMasserEnabled);
mSecunda->setVisible(mSecundaEnabled);
// rotate the stars by 360 degrees every 4 days
mAtmosphereNight->roll(Degree(MWBase::Environment::get().getWorld()->getTimeScaleFactor()*duration*360 / (3600*96.f)));
}
void SkyManager::enable()
{
if (!mCreated)
create();
if (mParticleNode)
mParticleNode->setVisible(true);
mRootNode->setVisible(true);
mEnabled = true;
}
void SkyManager::disable()
{
if (mParticleNode)
mParticleNode->setVisible(false);
clearRain();
mRootNode->setVisible(false);
mEnabled = false;
}
void SkyManager::setMoonColour (bool red)
{
mMoonRed = red;
}
void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
{
if (!mCreated) return;
mRainEffect = weather.mRainEffect;
mRainEnabled = !mRainEffect.empty();
mRainFrequency = weather.mRainFrequency;
mRainSpeed = weather.mRainSpeed;
mIsStorm = weather.mIsStorm;
if (mCurrentParticleEffect != weather.mParticleEffect)
{
mCurrentParticleEffect = weather.mParticleEffect;
if (mCurrentParticleEffect.empty())
{
mParticle.setNull();
}
else
{
mParticle = NifOgre::Loader::createObjects(mParticleNode, mCurrentParticleEffect);
for(size_t i = 0; i < mParticle->mParticles.size(); ++i)
{
ParticleSystem* particle = mParticle->mParticles[i];
particle->setRenderQueueGroup(RQG_Alpha);
particle->setVisibilityFlags(RV_Sky);
}
for (size_t i = 0; i < mParticle->mControllers.size(); ++i)
{
if (mParticle->mControllers[i].getSource().isNull())
mParticle->mControllers[i].setSource(Ogre::ControllerManager::getSingleton().getFrameTimeSource());
}
}
}
if (mClouds != weather.mCloudTexture)
{
sh::Factory::getInstance().setTextureAlias ("cloud_texture_1", Misc::ResourceHelpers::correctTexturePath(weather.mCloudTexture));
mClouds = weather.mCloudTexture;
}
if (mNextClouds != weather.mNextCloudTexture)
{
sh::Factory::getInstance().setTextureAlias ("cloud_texture_2", Misc::ResourceHelpers::correctTexturePath(weather.mNextCloudTexture));
mNextClouds = weather.mNextCloudTexture;
}
if (mCloudBlendFactor != weather.mCloudBlendFactor)
{
mCloudBlendFactor = weather.mCloudBlendFactor;
sh::Factory::getInstance().setSharedParameter ("cloudBlendFactor",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mCloudBlendFactor)));
}
if (mCloudOpacity != weather.mCloudOpacity)
{
mCloudOpacity = weather.mCloudOpacity;
sh::Factory::getInstance().setSharedParameter ("cloudOpacity",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mCloudOpacity)));
}
if (mCloudColour != weather.mSunColor)
{
ColourValue clr( weather.mSunColor.r*0.7f + weather.mAmbientColor.r*0.7f,
weather.mSunColor.g*0.7f + weather.mAmbientColor.g*0.7f,
weather.mSunColor.b*0.7f + weather.mAmbientColor.b*0.7f);
sh::Factory::getInstance().setSharedParameter ("cloudColour",
sh::makeProperty<sh::Vector3>(new sh::Vector3(clr.r, clr.g, clr.b)));
mCloudColour = weather.mSunColor;
}
if (mSkyColour != weather.mSkyColor)
{
mSkyColour = weather.mSkyColor;
sh::Factory::getInstance().setSharedParameter ("atmosphereColour", sh::makeProperty<sh::Vector4>(new sh::Vector4(
weather.mSkyColor.r, weather.mSkyColor.g, weather.mSkyColor.b, weather.mSkyColor.a)));
}
if (mFogColour != weather.mFogColor)
{
mFogColour = weather.mFogColor;
sh::Factory::getInstance().setSharedParameter ("horizonColour", sh::makeProperty<sh::Vector4>(new sh::Vector4(
weather.mFogColor.r, weather.mFogColor.g, weather.mFogColor.b, weather.mFogColor.a)));
}
mCloudSpeed = weather.mCloudSpeed;
if (weather.mNight && mStarsOpacity != weather.mNightFade)
{
if (weather.mNightFade == 0)
mAtmosphereNight->setVisible(false);
else
{
mAtmosphereNight->setVisible(true);
sh::Factory::getInstance().setSharedParameter ("nightFade",
sh::makeProperty<sh::FloatValue>(new sh::FloatValue(weather.mNightFade)));
mStarsOpacity = weather.mNightFade;
}
}
float strength;
float timeofday_angle = std::abs(mSunGlare->getPosition().z/mSunGlare->getPosition().length());
if (timeofday_angle <= 0.44)
strength = timeofday_angle/0.44f;
else
strength = 1.f;
mSunGlare->setVisibility(weather.mGlareView * mGlareFade * strength);
mSun->setVisibility(weather.mGlareView * strength);
mAtmosphereNight->setVisible(weather.mNight && mEnabled);
if (mParticle.get())
setAlpha(mParticle, weather.mEffectFade);
for (std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr>::iterator it = mRainModels.begin(); it != mRainModels.end(); ++it)
setAlpha(it->second, weather.mEffectFade);
}
void SkyManager::setGlare(const float glare)
{
mGlare = glare;
}
Vector3 SkyManager::getRealSunPos()
{
if (!mCreated) return Vector3(0,0,0);
return mSun->getNode()->getPosition() + mCamera->getRealPosition();
}
void SkyManager::sunEnable()
{
mSunEnabled = true;
}
void SkyManager::sunDisable()
{
mSunEnabled = false;
}
void SkyManager::setStormDirection(const Vector3 &direction)
{
mStormDirection = direction;
}
void SkyManager::setSunDirection(const Vector3& direction, bool is_night)
{
if (!mCreated) return;
mSun->setPosition(direction);
mSunGlare->setPosition(direction);
float height = direction.z;
float fade = is_night ? 0.0f : (( height > 0.5) ? 1.0f : height * 2);
sh::Factory::getInstance ().setSharedParameter ("waterSunFade_sunHeight", sh::makeProperty<sh::Vector2>(new sh::Vector2(fade, height)));
}
void SkyManager::setMasserDirection(const Vector3& direction)
{
if (!mCreated) return;
mMasser->setPosition(direction);
}
void SkyManager::setSecundaDirection(const Vector3& direction)
{
if (!mCreated) return;
mSecunda->setPosition(direction);
}
void SkyManager::masserEnable()
{
mMasserEnabled = true;
}
void SkyManager::secundaEnable()
{
mSecundaEnabled = true;
}
void SkyManager::masserDisable()
{
mMasserEnabled = false;
}
void SkyManager::secundaDisable()
{
mSecundaEnabled = false;
}
void SkyManager::setLightningStrength(const float factor)
{
if (!mCreated) return;
if (factor > 0.f)
{
mLightning->setDiffuseColour (ColourValue(2*factor, 2*factor, 2*factor));
mLightning->setVisible(true);
}
else
mLightning->setVisible(false);
}
void SkyManager::setMasserFade(const float fade)
{
if (!mCreated) return;
mMasser->setVisibility(fade);
}
void SkyManager::setSecundaFade(const float fade)
{
if (!mCreated) return;
mSecunda->setVisibility(fade);
}
void SkyManager::setHour(double hour)
{
mHour = static_cast<float>(hour);
}
void SkyManager::setDate(int day, int month)
{
mDay = day;
mMonth = month;
}
Ogre::SceneNode* SkyManager::getSunNode()
{
if (!mCreated) return 0;
return mSun->getNode();
}
void SkyManager::setGlareEnabled (bool enabled)
{
if (!mCreated || !mEnabled)
return;
mSunGlare->setVisible (mSunEnabled && enabled);
}
void SkyManager::attachToNode(SceneNode *sceneNode)
{
if (!mParticleNode)
{
mParticleNode = sceneNode->createChildSceneNode();
mParticleNode->setInheritOrientation(false);
}
else
{
sceneNode->addChild(mParticleNode);
}
}