1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-24 19:39:44 +00:00
openmw/extern/caelum/src/CaelumSystem.cpp

760 lines
29 KiB
C++

/*
This file is part of Caelum.
See http://www.ogre3d.org/wiki/index.php/Caelum
Copyright (c) 2006-2008 Caelum team. See Contributors.txt for details.
Caelum is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Caelum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with Caelum. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CaelumPrecompiled.h"
#include "CaelumSystem.h"
#include "CaelumExceptions.h"
#include "InternalUtilities.h"
#include "Astronomy.h"
#include "CaelumPlugin.h"
#include "FlatCloudLayer.h"
using namespace Ogre;
namespace Caelum
{
const String CaelumSystem::DEFAULT_SKY_GRADIENTS_IMAGE = "EarthClearSky2.png";
const String CaelumSystem::DEFAULT_SUN_COLOURS_IMAGE = "SunGradient.png";
CaelumSystem::CaelumSystem
(
Ogre::Root *root,
Ogre::SceneManager *sceneMgr,
CaelumComponent componentsToCreate/* = CAELUM_COMPONENTS_DEFAULT*/
):
mOgreRoot (root),
mSceneMgr (sceneMgr),
mCleanup (false)
{
LogManager::getSingleton().logMessage ("Caelum: Initialising Caelum system...");
//LogManager::getSingleton().logMessage ("Caelum: CaelumSystem* at d" +
// StringConverter::toString (reinterpret_cast<uint>(this)));
Ogre::String uniqueId = Ogre::StringConverter::toString ((size_t)this);
if (!CaelumPlugin::getSingletonPtr ()) {
LogManager::getSingleton().logMessage ("Caelum: Plugin not installed; installing now.");
new CaelumPlugin ();
CaelumPlugin::getSingletonPtr ()->install ();
CaelumPlugin::getSingletonPtr ()->initialise ();
}
mCaelumCameraNode.reset(mSceneMgr->getRootSceneNode ()->createChildSceneNode ("Caelum/CameraNode/" + uniqueId));
mCaelumGroundNode.reset(mSceneMgr->getRootSceneNode ()->createChildSceneNode ("Caelum/GroundNode/" + uniqueId));
mUniversalClock.reset(new UniversalClock ());
// If the "Caelum" resource group does not exist; create it.
// This resource group is never released; which may be bad.
// What does ogre do for it's own runtime resources?
Ogre::StringVector groups = ResourceGroupManager::getSingleton ().getResourceGroups ();
if (std::find (groups.begin(), groups.end(), Caelum::RESOURCE_GROUP_NAME) == groups.end()) {
LogManager::getSingleton ().logMessage (
"Caelum: Creating required internal resource group \'" + RESOURCE_GROUP_NAME + "\'");
ResourceGroupManager::getSingleton ().createResourceGroup (Caelum::RESOURCE_GROUP_NAME);
}
// Autoconfigure. Calls clear first to set defaults.
autoConfigure (componentsToCreate);
}
void CaelumSystem::destroySubcomponents (bool destroyEverything)
{
// Destroy sub-components
setSkyDome (0);
setSun (0);
setImageStarfield (0);
setPointStarfield (0);
setCloudSystem (0);
setPrecipitationController (0);
setDepthComposer (0);
setGroundFog (0);
setMoon (0);
mSkyGradientsImage.reset ();
mSunColoursImage.reset ();
// These things can't be rebuilt.
if (destroyEverything) {
LogManager::getSingleton ().logMessage("Caelum: Delete UniversalClock");
mUniversalClock.reset ();
mCaelumCameraNode.reset ();
mCaelumGroundNode.reset ();
}
}
CaelumSystem::~CaelumSystem () {
destroySubcomponents (true);
LogManager::getSingleton ().logMessage ("Caelum: CaelumSystem destroyed.");
}
void CaelumSystem::clear()
{
// Destroy all subcomponents first.
destroySubcomponents (false);
// Some "magical" behaviour.
mAutoMoveCameraNode = true;
mAutoNotifyCameraChanged = true;
mAutoAttachViewportsToComponents = true;
mAutoViewportBackground = true;
// Default lookups.
setSkyGradientsImage(DEFAULT_SKY_GRADIENTS_IMAGE);
setSunColoursImage(DEFAULT_SUN_COLOURS_IMAGE);
// Fog defaults.
setManageSceneFog (true);
mGlobalFogDensityMultiplier = 1;
mGlobalFogColourMultiplier = Ogre::ColourValue(1.0, 1.0, 1.0, 1.0);
mSceneFogDensityMultiplier = 1;
mSceneFogColourMultiplier = Ogre::ColourValue(0.7, 0.7, 0.7, 0.7);
mGroundFogDensityMultiplier = 1;
mGroundFogColourMultiplier = Ogre::ColourValue(1.0, 1.0, 1.0, 1.0);
// Ambient lighting.
setManageAmbientLight (true);
setMinimumAmbientLight (Ogre::ColourValue (0.1, 0.1, 0.3));
mEnsureSingleLightSource = false;
mEnsureSingleShadowSource = false;
// Observer time & position. J2000 is midday.
mObserverLatitude = Ogre::Degree(45);
mObserverLongitude = Ogre::Degree(0);
mUniversalClock->setJulianDay (Astronomy::J2000);
}
void CaelumSystem::autoConfigure
(
CaelumComponent componentsToCreate/* = CAELUM_COMPONENTS_DEFAULT*/
)
{
// Clear everything; revert to default.
clear();
if (componentsToCreate == 0) {
// Nothing to do. Don't print junk if not creating anything.
return;
}
LogManager::getSingleton ().logMessage ("Caelum: Creating caelum sub-components.");
// Init skydome
if (componentsToCreate & CAELUM_COMPONENT_SKY_DOME) {
try {
this->setSkyDome (new SkyDome (mSceneMgr, getCaelumCameraNode ()));
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize skydome: " + ex.getFullDescription());
}
}
// Init sun
if (componentsToCreate & CAELUM_COMPONENT_SUN) {
try {
this->setSun (new SpriteSun (mSceneMgr, getCaelumCameraNode ()));
this->getSun ()->setAmbientMultiplier (Ogre::ColourValue (0.5, 0.5, 0.5));
this->getSun ()->setDiffuseMultiplier (Ogre::ColourValue (3, 3, 2.7));
this->getSun ()->setSpecularMultiplier (Ogre::ColourValue (5, 5, 5));
this->getSun ()->setAutoDisable (true);
this->getSun ()->setAutoDisableThreshold (0.05);
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize sun: " + ex.getFullDescription());
}
}
// Init moon
if (componentsToCreate & CAELUM_COMPONENT_MOON) {
try {
this->setMoon (new Moon (mSceneMgr, getCaelumCameraNode ()));
this->getMoon ()->setAutoDisable (true);
this->getMoon ()->setAutoDisableThreshold (0.05);
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize moon: " + ex.getFullDescription());
}
}
if (componentsToCreate & CAELUM_COMPONENT_IMAGE_STARFIELD) {
try {
this->setImageStarfield (new ImageStarfield (mSceneMgr, getCaelumCameraNode ()));
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize the old image starfield: " + ex.getFullDescription());
}
}
if (componentsToCreate & CAELUM_COMPONENT_POINT_STARFIELD) {
try {
this->setPointStarfield (new PointStarfield (mSceneMgr, getCaelumCameraNode ()));
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize starfield: " + ex.getFullDescription());
}
}
if (componentsToCreate & CAELUM_COMPONENT_GROUND_FOG) {
try {
this->setGroundFog (new GroundFog (mSceneMgr, getCaelumCameraNode ()));
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize ground fog: " + ex.getFullDescription());
}
}
if (componentsToCreate & CAELUM_COMPONENT_CLOUDS) {
try {
this->setCloudSystem (new CloudSystem (mSceneMgr, getCaelumGroundNode ()));
getCloudSystem ()->createLayerAtHeight (3000);
getCloudSystem ()->getLayer (0)->setCloudCover (0.3);
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize clouds: " + ex.getFullDescription());
}
}
if (componentsToCreate & CAELUM_COMPONENT_PRECIPITATION) {
try {
this->setPrecipitationController (new PrecipitationController (mSceneMgr));
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize precipitation: " + ex.getFullDescription());
}
}
if (componentsToCreate & CAELUM_COMPONENT_SCREEN_SPACE_FOG) {
try {
this->setDepthComposer (new DepthComposer (mSceneMgr));
} catch (Caelum::UnsupportedException& ex) {
LogManager::getSingleton ().logMessage (
"Caelum: Failed to initialize precipitation: " + ex.getFullDescription());
}
}
LogManager::getSingleton ().logMessage ("Caelum: DONE initializing");
}
void CaelumSystem::shutdown (const bool cleanup) {
LogManager::getSingleton ().logMessage ("Caelum: Shutting down Caelum system...");
destroySubcomponents (true);
if (cleanup) {
mOgreRoot->removeFrameListener (this);
delete this;
} else {
// We'll delete later. Make sure we're registered as a frame listener, or we'd leak.
mOgreRoot->addFrameListener(this);
mCleanup = true;
}
}
void CaelumSystem::attachViewportImpl (Ogre::Viewport* vp)
{
LogManager::getSingleton().getDefaultLog ()->logMessage (
"CaelumSystem: Attached to"
" viewport " + StringConverter::toString ((long)vp) +
" render target " + vp->getTarget ()->getName ());
if (getAutoAttachViewportsToComponents ()) {
if (getPrecipitationController ()) {
getPrecipitationController ()->createViewportInstance (vp);
}
if (getDepthComposer ()) {
getDepthComposer ()->createViewportInstance (vp);
}
}
}
void CaelumSystem::detachViewportImpl (Ogre::Viewport* vp)
{
LogManager::getSingleton().getDefaultLog ()->logMessage (
"CaelumSystem: Detached from "
" viewport " + StringConverter::toString ((long)vp) +
" render target " + vp->getTarget ()->getName ());
if (getAutoAttachViewportsToComponents ()) {
if (getPrecipitationController ()) {
getPrecipitationController ()->destroyViewportInstance (vp);
}
if (getDepthComposer ()) {
getDepthComposer ()->destroyViewportInstance (vp);
}
}
}
void CaelumSystem::attachViewport (Ogre::Viewport* vp)
{
bool found = !mAttachedViewports.insert (vp).second;
if (!found) {
attachViewportImpl (vp);
}
}
void CaelumSystem::detachViewport (Ogre::Viewport* vp)
{
std::set<Viewport*>::size_type erase_result = mAttachedViewports.erase(vp);
assert(erase_result == 0 || erase_result == 1);
bool found = erase_result == 1;
if (found) {
detachViewportImpl (vp);
}
}
void CaelumSystem::detachAllViewports ()
{
std::set<Viewport*>::const_iterator it = mAttachedViewports.begin(), end = mAttachedViewports.end();
for (; it != end; ++it) {
detachViewportImpl (*it);
}
mAttachedViewports.clear();
}
bool CaelumSystem::isViewportAttached (Ogre::Viewport* vp) const {
return mAttachedViewports.find (vp) != mAttachedViewports.end();
}
void CaelumSystem::setSkyDome (SkyDome *obj) {
mSkyDome.reset (obj);
}
void CaelumSystem::setSun (BaseSkyLight* obj) {
mSun.reset (obj);
}
void CaelumSystem::setMoon (Moon* obj) {
mMoon.reset (obj);
}
void CaelumSystem::setImageStarfield (ImageStarfield* obj) {
mImageStarfield.reset (obj);
}
void CaelumSystem::setPointStarfield (PointStarfield* obj) {
mPointStarfield.reset (obj);
}
void CaelumSystem::setGroundFog (GroundFog* obj) {
mGroundFog.reset (obj);
}
void CaelumSystem::setCloudSystem (CloudSystem* obj) {
mCloudSystem.reset (obj);
}
void CaelumSystem::setPrecipitationController (PrecipitationController* newptr) {
PrecipitationController* oldptr = getPrecipitationController ();
if (oldptr == newptr) {
return;
}
// Detach old
if (getAutoAttachViewportsToComponents() && oldptr) {
std::for_each (mAttachedViewports.begin(), mAttachedViewports.end(),
std::bind1st (std::mem_fun (&PrecipitationController::destroyViewportInstance), oldptr));
}
// Attach new.
if (getAutoAttachViewportsToComponents() && newptr) {
std::for_each (mAttachedViewports.begin(), mAttachedViewports.end(),
std::bind1st (std::mem_fun (&PrecipitationController::createViewportInstance), newptr));
}
mPrecipitationController.reset(newptr);
}
void CaelumSystem::setDepthComposer (DepthComposer* ptr) {
mDepthComposer.reset(ptr);
if (getAutoAttachViewportsToComponents() && getDepthComposer ()) {
std::for_each (
mAttachedViewports.begin(), mAttachedViewports.end(),
std::bind1st (
std::mem_fun (&DepthComposer::createViewportInstance),
getDepthComposer ()));
}
}
void CaelumSystem::preViewportUpdate (const Ogre::RenderTargetViewportEvent &e) {
Ogre::Viewport *viewport = e.source;
Ogre::Camera *camera = viewport->getCamera ();
if (getAutoViewportBackground ()) {
viewport->setBackgroundColour (Ogre::ColourValue::Black);
}
if (getAutoNotifyCameraChanged ()) {
this->notifyCameraChanged (camera);
}
}
void CaelumSystem::notifyCameraChanged(Ogre::Camera* cam)
{
// Move camera node.
if (getAutoMoveCameraNode ()) {
mCaelumCameraNode->setPosition (cam->getDerivedPosition());
mCaelumCameraNode->_update (true, true);
}
if (getSkyDome ()) {
getSkyDome ()->notifyCameraChanged (cam);
}
if (getSun ()) {
getSun ()->notifyCameraChanged (cam);
}
if (getMoon ()) {
getMoon ()->notifyCameraChanged (cam);
}
if (getImageStarfield ()) {
getImageStarfield ()->notifyCameraChanged (cam);
}
if (getPointStarfield ()) {
getPointStarfield ()->notifyCameraChanged (cam);
}
if (getGroundFog ()) {
getGroundFog ()->notifyCameraChanged (cam);
}
}
bool CaelumSystem::frameStarted (const Ogre::FrameEvent &e) {
if (mCleanup) {
// Delayed destruction.
mOgreRoot->removeFrameListener (this);
delete this;
return true;
}
updateSubcomponents(e.timeSinceLastFrame);
return true;
}
void CaelumSystem::updateSubcomponents (Real timeSinceLastFrame)
{
/*
LogManager::getSingleton().getDefaultLog()->logMessage(
"CaelumSystem::updateSubcomponents: " +
StringConverter::toString (timeSinceLastFrame, 10));
*/
mUniversalClock->update (timeSinceLastFrame);
// Timing variables
LongReal julDay = mUniversalClock->getJulianDay ();
LongReal relDayTime = fmod(julDay, 1);
Real secondDiff = timeSinceLastFrame * mUniversalClock->getTimeScale ();
// Get astronomical parameters.
Ogre::Vector3 sunDir = getSunDirection(julDay);
Ogre::Vector3 moonDir = getMoonDirection(julDay);
Real moonPhase = getMoonPhase(julDay);
// Get parameters from sky colour model.
Real fogDensity = getFogDensity (relDayTime, sunDir);
Ogre::ColourValue fogColour = getFogColour (relDayTime, sunDir);
Ogre::ColourValue sunLightColour = getSunLightColour (relDayTime, sunDir);
Ogre::ColourValue sunSphereColour = getSunSphereColour (relDayTime, sunDir);
Ogre::ColourValue moonLightColour = getMoonLightColour (moonDir);
Ogre::ColourValue moonBodyColour = getMoonBodyColour (moonDir);
fogDensity *= mGlobalFogDensityMultiplier;
fogColour = fogColour * mGlobalFogColourMultiplier;
// Update image starfield
if (getImageStarfield ()) {
getImageStarfield ()->update (relDayTime);
getImageStarfield ()->setInclination (-getObserverLatitude ());
}
// Update point starfield
if (getPointStarfield ()) {
getPointStarfield ()->setObserverLatitude (getObserverLatitude ());
getPointStarfield ()->setObserverLongitude (getObserverLongitude ());
getPointStarfield ()->_update (relDayTime);
}
// Update skydome.
if (getSkyDome ()) {
getSkyDome ()->setSunDirection (sunDir);
getSkyDome ()->setHazeColour (fogColour * mSceneFogColourMultiplier);
}
// Update scene fog.
if (getManageSceneFog ()) {
mSceneMgr->setFog (Ogre::FOG_EXP2,
fogColour * mSceneFogColourMultiplier,
fogDensity * mSceneFogDensityMultiplier);
}
// Update ground fog.
if (getGroundFog ()) {
getGroundFog ()->setColour (fogColour * mGroundFogColourMultiplier);
getGroundFog ()->setDensity (fogDensity * mGroundFogDensityMultiplier);
}
// Update sun
if (getSun ()) {
mSun->update (sunDir, sunLightColour, sunSphereColour);
}
// Update moon.
if (getMoon ()) {
mMoon->update (
moonDir,
moonLightColour,
moonBodyColour);
mMoon->setPhase (moonPhase);
}
// Update clouds
if (getCloudSystem ()) {
getCloudSystem ()->update (
secondDiff, sunDir, sunLightColour, fogColour, sunSphereColour);
}
// Update precipitation
if (getPrecipitationController ()) {
getPrecipitationController ()->update (secondDiff, fogColour);
}
// Update screen space fog
if (getDepthComposer ()) {
getDepthComposer ()->update ();
getDepthComposer ()->setSunDirection (sunDir);
getDepthComposer ()->setHazeColour (fogColour);
getDepthComposer ()->setGroundFogColour (fogColour * mGroundFogColourMultiplier);
getDepthComposer ()->setGroundFogDensity (fogDensity * mGroundFogDensityMultiplier);
}
// Update ambient lighting.
if (getManageAmbientLight ()) {
Ogre::ColourValue ambient = Ogre::ColourValue::Black;
if (getMoon ()) {
ambient += getMoon ()->getLightColour () * getMoon ()->getAmbientMultiplier ();
}
if (getSun ()) {
ambient += getSun ()->getLightColour () * getSun ()->getAmbientMultiplier ();
}
ambient.r = std::max(ambient.r, mMinimumAmbientLight.r);
ambient.g = std::max(ambient.g, mMinimumAmbientLight.g);
ambient.b = std::max(ambient.b, mMinimumAmbientLight.b);
ambient.a = std::max(ambient.a, mMinimumAmbientLight.a);
// Debug ambient factos (ick).
/*
LogManager::getSingleton().logMessage (
"Sun is " + StringConverter::toString(sunLightColour) + "\n"
"Moon is " + StringConverter::toString(moonLightColour) + "\n"
"Ambient is " + StringConverter::toString(ambient) + "\n"
);
*/
mSceneMgr->setAmbientLight (ambient);
}
if (getSun() && getMoon ()) {
Ogre::Real moonBrightness = moonLightColour.r + moonLightColour.g + moonLightColour.b + moonLightColour.a;
Ogre::Real sunBrightness = sunLightColour.r + sunLightColour.g + sunLightColour.b + sunLightColour.a;
bool sunBrighterThanMoon = (sunBrightness > moonBrightness);
if (getEnsureSingleLightSource ()) {
getMoon ()->setForceDisable (sunBrighterThanMoon);
getSun ()->setForceDisable (!sunBrighterThanMoon);
}
if (getEnsureSingleShadowSource ()) {
getMoon ()->getMainLight ()->setCastShadows (!sunBrighterThanMoon);
getSun ()->getMainLight ()->setCastShadows (sunBrighterThanMoon);
}
}
}
void CaelumSystem::setManageSceneFog (bool value) {
mManageSceneFog = value;
// Prevent having some stale values around.
if (!value) {
mSceneMgr->setFog (Ogre::FOG_NONE);
}
}
bool CaelumSystem::getManageSceneFog () const {
return mManageSceneFog;
}
void CaelumSystem::setSceneFogDensityMultiplier (Real value) {
mSceneFogDensityMultiplier = value;
}
Real CaelumSystem::getSceneFogDensityMultiplier () const {
return mSceneFogDensityMultiplier;
}
void CaelumSystem::setGroundFogDensityMultiplier (Real value) {
mGroundFogDensityMultiplier = value;
}
Real CaelumSystem::getGroundFogDensityMultiplier () const {
return mGroundFogDensityMultiplier;
}
void CaelumSystem::setGlobalFogDensityMultiplier (Real value) {
mGlobalFogDensityMultiplier = value;
}
Real CaelumSystem::getGlobalFogDensityMultiplier () const {
return mGlobalFogDensityMultiplier;
}
void CaelumSystem::setSkyGradientsImage (const Ogre::String &filename) {
mSkyGradientsImage.reset(new Ogre::Image ());
mSkyGradientsImage->load (filename, RESOURCE_GROUP_NAME);
}
void CaelumSystem::setSunColoursImage (const Ogre::String &filename) {
mSunColoursImage.reset(new Ogre::Image ());
mSunColoursImage->load (filename, RESOURCE_GROUP_NAME);
}
Ogre::ColourValue CaelumSystem::getFogColour (Real time, const Ogre::Vector3 &sunDir) {
if (!mSkyGradientsImage.get()) {
return Ogre::ColourValue::Black;
}
Real elevation = sunDir.dotProduct (Ogre::Vector3::UNIT_Y) * 0.5 + 0.5;
Ogre::ColourValue col = InternalUtilities::getInterpolatedColour (elevation, 1, mSkyGradientsImage.get(), false);
return col;
}
Real CaelumSystem::getFogDensity (Real time, const Ogre::Vector3 &sunDir)
{
if (!mSkyGradientsImage.get()) {
return 0;
}
Real elevation = sunDir.dotProduct (Ogre::Vector3::UNIT_Y) * 0.5 + 0.5;
Ogre::ColourValue col = InternalUtilities::getInterpolatedColour (elevation, 1, mSkyGradientsImage.get(), false);
return col.a;
}
Ogre::ColourValue CaelumSystem::getSunSphereColour (Real time, const Ogre::Vector3 &sunDir)
{
if (!mSunColoursImage.get()) {
return Ogre::ColourValue::White;
}
Real elevation = sunDir.dotProduct (Ogre::Vector3::UNIT_Y);
elevation = elevation * 2 + 0.4;
return InternalUtilities::getInterpolatedColour (elevation, 1, mSunColoursImage.get(), false);
}
Ogre::ColourValue CaelumSystem::getSunLightColour (Real time, const Ogre::Vector3 &sunDir)
{
if (!mSkyGradientsImage.get()) {
exit(-1);
return Ogre::ColourValue::White;
}
Real elevation = sunDir.dotProduct (Ogre::Vector3::UNIT_Y) * 0.5 + 0.5;
// Hack: return averaged sky colours.
// Don't use an alpha value for lights, this can cause nasty problems.
Ogre::ColourValue col = InternalUtilities::getInterpolatedColour (elevation, elevation, mSkyGradientsImage.get(), false);
Real val = (col.r + col.g + col.b) / 3;
col = Ogre::ColourValue(val, val, val, 1.0);
assert(Ogre::Math::RealEqual(col.a, 1));
return col;
}
Ogre::ColourValue CaelumSystem::getMoonBodyColour (const Ogre::Vector3 &moonDir) {
return Ogre::ColourValue::White;
}
Ogre::ColourValue CaelumSystem::getMoonLightColour (const Ogre::Vector3 &moonDir)
{
if (!mSkyGradientsImage.get()) {
return Ogre::ColourValue::Blue;
}
// Scaled version of getSunLightColor
Real elevation = moonDir.dotProduct (Ogre::Vector3::UNIT_Y) * 0.5 + 0.5;
Ogre::ColourValue col = InternalUtilities::getInterpolatedColour (elevation, elevation, mSkyGradientsImage.get(), false);
Real val = (col.r + col.g + col.b) / 3;
col = Ogre::ColourValue(val / 2.5f, val / 2.5f, val / 2.5f, 1.0);
assert(Ogre::Math::RealEqual(col.a, 1));
return col;
}
const Ogre::Vector3 CaelumSystem::makeDirection (
Ogre::Degree azimuth, Ogre::Degree altitude)
{
Ogre::Vector3 res;
res.z = -Ogre::Math::Cos (azimuth) * Ogre::Math::Cos (altitude); // North
res.x = Ogre::Math::Sin (azimuth) * Ogre::Math::Cos (altitude); // East
res.y = -Ogre::Math::Sin (altitude); // Zenith
return res;
}
const Ogre::Vector3 CaelumSystem::getSunDirection (LongReal jday)
{
Ogre::Degree azimuth, altitude;
{
ScopedHighPrecissionFloatSwitch precissionSwitch;
Astronomy::getHorizontalSunPosition(jday,
getObserverLongitude(), getObserverLatitude(),
azimuth, altitude);
}
Ogre::Vector3 res = makeDirection(azimuth, altitude);
return res;
}
const Ogre::Vector3 CaelumSystem::getMoonDirection (LongReal jday)
{
Ogre::Degree azimuth, altitude;
{
ScopedHighPrecissionFloatSwitch precissionSwitch;
Astronomy::getHorizontalMoonPosition(jday,
getObserverLongitude (), getObserverLatitude (),
azimuth, altitude);
}
Ogre::Vector3 res = makeDirection(azimuth, altitude);
return res;
}
const Ogre::Real CaelumSystem::getMoonPhase (LongReal jday)
{
// Calculates julian days since January 22, 2008 13:36 (full moon)
// and divides by the time between lunations (synodic month)
LongReal T = (jday - 2454488.0665L) / 29.531026L;
T = fabs(fmod(T, 1));
return -fabs(-4 * T + 2) + 2;
}
void CaelumSystem::forceSubcomponentQueryFlags (uint flags)
{
if (getSkyDome ()) getSkyDome ()->setQueryFlags (flags);
if (getSun ()) getSun ()->setQueryFlags (flags);
if (getMoon ()) getMoon ()->setQueryFlags (flags);
if (getImageStarfield ()) getImageStarfield ()->setQueryFlags (flags);
if (getPointStarfield ()) getPointStarfield ()->setQueryFlags (flags);
if (getGroundFog ()) getGroundFog ()->setQueryFlags (flags);
if (getCloudSystem ()) getCloudSystem ()->forceLayerQueryFlags (flags);
}
void CaelumSystem::forceSubcomponentVisibilityFlags (uint flags)
{
if (getSkyDome ()) getSkyDome ()->setVisibilityFlags (flags);
if (getSun ()) getSun ()->setVisibilityFlags (flags);
if (getMoon ()) getMoon ()->setVisibilityFlags (flags);
if (getImageStarfield ()) getImageStarfield ()->setVisibilityFlags (flags);
if (getPointStarfield ()) getPointStarfield ()->setVisibilityFlags (flags);
if (getGroundFog ()) getGroundFog ()->setVisibilityFlags (flags);
if (getCloudSystem ()) getCloudSystem ()->forceLayerVisibilityFlags (flags);
}
}