mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-24 19:39:44 +00:00
760 lines
29 KiB
C++
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);
|
|
}
|
|
}
|