Merge remote-tracking branch 'origin/master'

openmw-37
Marc Zinnschlag 9 years ago
commit ab2df963e9

@ -774,7 +774,7 @@ namespace MWClass
return ref->mBase->mAiData.mFight;
}
void Creature::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f &scale) const
void Creature::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f &scale, bool /* rendering */) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
scale *= ref->mBase->mScale;

@ -133,7 +133,8 @@ namespace MWClass
virtual int getBaseFightRating(const MWWorld::Ptr &ptr) const;
virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale) const;
virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale, bool rendering) const;
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
};
}

@ -1012,8 +1012,12 @@ namespace MWClass
+ shield;
}
void Npc::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f&scale) const
void Npc::adjustScale(const MWWorld::Ptr &ptr, osg::Vec3f&scale, bool rendering) const
{
if (!rendering)
return; // collision meshes are not scaled based on race height
// having the same collision extents for all races makes the environments easier to test
MWWorld::LiveCellRef<ESM::NPC> *ref =
ptr.get<ESM::NPC>();

@ -109,7 +109,8 @@ namespace MWClass
/// \param actor Actor that is resposible for the ID being applied to \a ptr.
/// \return Any effect?
virtual void adjustScale (const MWWorld::Ptr &ptr, osg::Vec3f &scale) const;
virtual void adjustScale (const MWWorld::Ptr &ptr, osg::Vec3f &scale, bool rendering) const;
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
virtual void skillUsageSucceeded (const MWWorld::Ptr& ptr, int skill, int usageType, float extraFactor=1.f) const;
///< Inform actor \a ptr that a skill use has succeeded.

@ -110,12 +110,14 @@ void Actor::updateScale()
float scale = mPtr.getCellRef().getScale();
osg::Vec3f scaleVec(scale,scale,scale);
if (!mPtr.getClass().isNpc())
mPtr.getClass().adjustScale(mPtr, scaleVec);
mPtr.getClass().adjustScale(mPtr, scaleVec, false);
mScale = scaleVec;
mShape->setLocalScaling(toBullet(mScale));
scaleVec = osg::Vec3f(scale,scale,scale);
mPtr.getClass().adjustScale(mPtr, scaleVec, true);
mRenderingScale = scaleVec;
updatePosition();
}
@ -124,6 +126,11 @@ osg::Vec3f Actor::getHalfExtents() const
return osg::componentMultiply(mHalfExtents, mScale);
}
osg::Vec3f Actor::getRenderingHalfExtents() const
{
return osg::componentMultiply(mHalfExtents, mRenderingScale);
}
void Actor::setInertialForce(const osg::Vec3f &force)
{
mForce = force;

@ -66,10 +66,17 @@ namespace MWPhysics
void updatePosition();
/**
* Returns the (scaled) half extents
* Returns the half extents of the collision body (scaled according to collision scale)
*/
osg::Vec3f getHalfExtents() const;
/**
* Returns the half extents of the collision body (scaled according to rendering scale)
* @note The reason we need this extra method is because of an inconsistency in MW - NPC race scales aren't applied to the collision shape,
* most likely to make environment collision testing easier. However in some cases (swimming level) we want the actual scale.
*/
osg::Vec3f getRenderingHalfExtents() const;
/**
* Sets the current amount of inertial force (incl. gravity) affecting this physic actor
*/
@ -118,6 +125,7 @@ namespace MWPhysics
osg::Quat mRotation;
osg::Vec3f mScale;
osg::Vec3f mRenderingScale;
osg::Vec3f mPosition;
osg::Vec3f mForce;

@ -261,7 +261,7 @@ namespace MWPhysics
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
.find("fSwimHeightScale")->getFloat();
float swimlevel = waterlevel + halfExtents.z() - (halfExtents.z() * 2 * fSwimHeightScale);
float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
ActorTracer tracer;
osg::Vec3f inertia = physicActor->getInertialForce();
@ -878,6 +878,15 @@ namespace MWPhysics
return osg::Vec3f();
}
osg::Vec3f PhysicsSystem::getRenderingHalfExtents(const MWWorld::Ptr &actor)
{
Actor* physactor = getActor(actor);
if (physactor)
return physactor->getRenderingHalfExtents();
else
return osg::Vec3f();
}
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
{
public:

@ -110,6 +110,9 @@ namespace MWPhysics
/// Get physical half extents (scaled) of the given actor.
osg::Vec3f getHalfExtents(const MWWorld::Ptr& actor);
/// @see MWPhysics::Actor::getRenderingHalfExtents
osg::Vec3f getRenderingHalfExtents(const MWWorld::Ptr& actor);
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
/// be overwritten. Valid until the next call to applyQueuedMovement.
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);

@ -287,7 +287,7 @@ namespace MWRender
void InventoryPreview::onSetup()
{
osg::Vec3f scale (1.f, 1.f, 1.f);
mCharacter.getClass().adjustScale(mCharacter, scale);
mCharacter.getClass().adjustScale(mCharacter, scale, true);
mNode->setScale(scale);

@ -31,6 +31,8 @@
#include <components/esm/loadcell.hpp>
#include "../mwworld/fallback.hpp"
#include "sky.hpp"
#include "effectmanager.hpp"
#include "npcanimation.hpp"
@ -199,6 +201,10 @@ namespace MWRender
updateProjectionMatrix();
mStateUpdater->setFogEnd(mViewDistance);
mUnderwaterColor = fallback->getFallbackColour("Water_UnderwaterColor");
mUnderwaterWeight = fallback->getFallbackFloat("Water_UnderwaterColorWeight");
mUnderwaterIndoorFog = fallback->getFallbackFloat("Water_UnderwaterIndoorFog");
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("near", mNearClip));
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance));
}
@ -349,13 +355,14 @@ namespace MWRender
{
osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog);
configureFog (cell->mAmbi.mFogDensity, color);
configureFog (cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, color);
}
void RenderingManager::configureFog(float fogDepth, const osg::Vec4f &color)
void RenderingManager::configureFog(float fogDepth, float underwaterFog, const osg::Vec4f &color)
{
mFogDepth = fogDepth;
mFogColor = color;
mUnderwaterFog = underwaterFog;
}
SkyManager* RenderingManager::getSkyManager()
@ -378,9 +385,9 @@ namespace MWRender
mCamera->getPosition(focal, cameraPos);
if (mWater->isUnderwater(cameraPos))
{
setFogColor(osg::Vec4f(0.090195f, 0.115685f, 0.12745f, 1.f));
mStateUpdater->setFogStart(0.f);
mStateUpdater->setFogEnd(1000);
setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight));
mStateUpdater->setFogStart(mViewDistance * (1 - mUnderwaterFog));
mStateUpdater->setFogEnd(mViewDistance);
}
else
{

@ -79,7 +79,7 @@ namespace MWRender
void configureAmbient(const ESM::Cell* cell);
void configureFog(const ESM::Cell* cell);
void configureFog(float fogDepth, const osg::Vec4f& colour);
void configureFog(float fogDepth, float underwaterFog, const osg::Vec4f& colour);
void addCell(const MWWorld::CellStore* store);
void removeCell(const MWWorld::CellStore* store);
@ -192,6 +192,10 @@ namespace MWRender
osg::ref_ptr<StateUpdater> mStateUpdater;
float mFogDepth;
osg::Vec4f mUnderwaterColor;
float mUnderwaterWeight;
float mUnderwaterFog;
float mUnderwaterIndoorFog;
osg::Vec4f mFogColor;
osg::Vec4f mAmbientColor;

@ -13,6 +13,7 @@
#include <osg/MatrixTransform>
#include <osg/FrontFace>
#include <osg/Shader>
#include <osg/GLExtensions>
#include <osgDB/ReadFile>
@ -144,14 +145,18 @@ class ClipCullNode : public osg::Group
osg::RefMatrix* modelViewMatrix = new osg::RefMatrix(*cv->getModelViewMatrix());
// move the plane back along its normal a little bit to prevent bleeding at the water shore
const float clipFudge = -5;
// now apply the height of the plane
// we can't apply this height in the addClipPlane() since the "flip the below graph" function would otherwise flip the height as well
float translate = clipFudge + ((*mCullPlane)[3] * -1);
modelViewMatrix->preMultTranslate(mCullPlane->getNormal() * translate);
// flip the below graph if the eye point is above the plane
if (mCullPlane->intersect(osg::BoundingSphere(osg::Vec3d(0,0,eyePoint.z()), 0)) > 0)
{
modelViewMatrix->preMultScale(osg::Vec3(1,1,-1));
}
// move the plane back along its normal a little bit to prevent bleeding at the water shore
const float clipFudge = 5;
modelViewMatrix->preMultTranslate(mCullPlane->getNormal() * (-clipFudge));
cv->pushModelViewMatrix(modelViewMatrix, osg::Transform::RELATIVE_RF);
traverse(node, nv);
@ -167,7 +172,7 @@ public:
{
addCullCallback (new PlaneCullCallback(&mPlane));
mClipNodeTransform = new osg::PositionAttitudeTransform;
mClipNodeTransform = new osg::Group;
mClipNodeTransform->addCullCallback(new FlipCallback(&mPlane));
addChild(mClipNodeTransform);
@ -183,12 +188,12 @@ public:
mPlane = plane;
mClipNode->getClipPlaneList().clear();
mClipNode->addClipPlane(new osg::ClipPlane(0, mPlane));
mClipNode->addClipPlane(new osg::ClipPlane(0, osg::Plane(mPlane.getNormal(), 0))); // mPlane.d() applied in FlipCallback
mClipNode->setStateSetModes(*getOrCreateStateSet(), osg::StateAttribute::ON);
}
private:
osg::ref_ptr<osg::PositionAttitudeTransform> mClipNodeTransform;
osg::ref_ptr<osg::Group> mClipNodeTransform;
osg::ref_ptr<osg::ClipNode> mClipNode;
osg::Plane mPlane;
@ -204,6 +209,36 @@ public:
}
};
/// Moves water mesh away from the camera slightly if the camera gets too close on the Z axis.
/// The offset works around graphics artifacts that occured with the GL_DEPTH_CLAMP when the camera gets extremely close to the mesh (seen on NVIDIA at least).
/// Must be added as a Cull callback.
class FudgeCallback : public osg::NodeCallback
{
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
const float fudge = 0.2;
if (std::abs(cv->getEyeLocal().z()) < fudge)
{
float diff = fudge - cv->getEyeLocal().z();
osg::RefMatrix* modelViewMatrix = new osg::RefMatrix(*cv->getModelViewMatrix());
if (cv->getEyeLocal().z() > 0)
modelViewMatrix->preMultTranslate(osg::Vec3f(0,0,-diff));
else
modelViewMatrix->preMultTranslate(osg::Vec3f(0,0,diff));
cv->pushModelViewMatrix(modelViewMatrix, osg::Transform::RELATIVE_RF);
traverse(node, nv);
cv->popModelViewMatrix();
}
else
traverse(node, nv);
}
};
osg::ref_ptr<osg::Shader> readShader (osg::Shader::Type type, const std::string& file, const std::map<std::string, std::string>& defineMap = std::map<std::string, std::string>())
{
osg::ref_ptr<osg::Shader> shader (new osg::Shader(type));
@ -389,6 +424,28 @@ private:
osg::ref_ptr<osg::Node> mScene;
};
/// DepthClampCallback enables GL_DEPTH_CLAMP for the current draw, if supported.
class DepthClampCallback : public osg::Drawable::DrawCallback
{
public:
virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const
{
static bool supported = osg::isGLExtensionOrVersionSupported(renderInfo.getState()->getContextID(), "GL_ARB_depth_clamp", 3.3);
if (!supported)
{
drawable->drawImplementation(renderInfo);
return;
}
glEnable(GL_DEPTH_CLAMP);
drawable->drawImplementation(renderInfo);
// restore default
glDisable(GL_DEPTH_CLAMP);
}
};
Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem *resourceSystem, osgUtil::IncrementalCompileOperation *ico,
const MWWorld::Fallback* fallback, const std::string& resourcePath)
: mParent(parent)
@ -402,6 +459,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
mSimulation.reset(new RippleSimulation(parent, resourceSystem, fallback));
osg::ref_ptr<osg::Geometry> waterGeom = createWaterGeometry(CELL_SIZE*150, 40, 900);
waterGeom->setDrawCallback(new DepthClampCallback);
mWaterGeode = new osg::Geode;
mWaterGeode->addDrawable(waterGeom);
@ -412,6 +470,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
mWaterNode = new osg::PositionAttitudeTransform;
mWaterNode->addChild(mWaterGeode);
mWaterNode->addCullCallback(new FudgeCallback);
// simple water fallback for the local map
osg::ref_ptr<osg::Geode> geode2 (osg::clone(mWaterGeode.get(), osg::CopyOp::DEEP_COPY_NODES));
@ -558,6 +617,17 @@ void Water::processChangedSettings(const Settings::CategorySettingVector& settin
Water::~Water()
{
mParent->removeChild(mWaterNode);
if (mReflection)
{
mParent->removeChild(mReflection);
mReflection = NULL;
}
if (mRefraction)
{
mParent->removeChild(mRefraction);
mRefraction = NULL;
}
}
void Water::setEnabled(bool enabled)

@ -287,7 +287,7 @@ namespace MWWorld
return "";
}
void Class::adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale) const
void Class::adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale, bool rendering) const
{
}

@ -258,7 +258,8 @@ namespace MWWorld
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
///< @return the number of enchantment points available for possible enchanting
virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale) const;
virtual void adjustScale(const MWWorld::Ptr& ptr, osg::Vec3f& scale, bool rendering) const;
/// @param rendering Indicates if the scale to adjust is for the rendering mesh, or for the collision mesh
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
///< Determine whether or not \a item can be sold to an npc with the given \a npcServices

@ -72,7 +72,7 @@ namespace
{
float scale = ptr.getCellRef().getScale();
osg::Vec3f scaleVec (scale, scale, scale);
ptr.getClass().adjustScale(ptr, scaleVec);
ptr.getClass().adjustScale(ptr, scaleVec, true);
rendering.scaleObject(ptr, scaleVec);
}
}

@ -31,17 +31,74 @@ namespace
{
static const int invalidWeatherID = -1;
// linear interpolate between x and y based on factor.
float lerp (float x, float y, float factor)
{
return x * (1-factor) + y * factor;
}
// linear interpolate between x and y based on factor.
osg::Vec4f lerp (const osg::Vec4f& x, const osg::Vec4f& y, float factor)
{
return x * (1-factor) + y * factor;
}
}
template <typename T>
T TimeOfDayInterpolator<T>::getValue(const float gameHour, const TimeOfDaySettings& timeSettings) const
{
// TODO: use pre/post sunset/sunrise time values in [Weather] section
// night
if (gameHour <= timeSettings.mNightEnd || gameHour >= timeSettings.mNightStart + 1)
return mNightValue;
// sunrise
else if (gameHour >= timeSettings.mNightEnd && gameHour <= timeSettings.mDayStart + 1)
{
if (gameHour <= timeSettings.mSunriseTime)
{
// fade in
float advance = timeSettings.mSunriseTime - gameHour;
float factor = advance / 0.5f;
return lerp(mSunriseValue, mNightValue, factor);
}
else
{
// fade out
float advance = gameHour - timeSettings.mSunriseTime;
float factor = advance / 3.f;
return lerp(mSunriseValue, mDayValue, factor);
}
}
// day
else if (gameHour >= timeSettings.mDayStart + 1 && gameHour <= timeSettings.mDayEnd - 1)
return mDayValue;
// sunset
else if (gameHour >= timeSettings.mDayEnd - 1 && gameHour <= timeSettings.mNightStart + 1)
{
if (gameHour <= timeSettings.mDayEnd + 1)
{
// fade in
float advance = (timeSettings.mDayEnd + 1) - gameHour;
float factor = (advance / 2);
return lerp(mSunsetValue, mDayValue, factor);
}
else
{
// fade out
float advance = gameHour - (timeSettings.mDayEnd + 1);
float factor = advance / 2.f;
return lerp(mSunsetValue, mNightValue, factor);
}
}
// shut up compiler
return T();
}
template class TimeOfDayInterpolator<float>;
template class TimeOfDayInterpolator<osg::Vec4f>;
Weather::Weather(const std::string& name,
const MWWorld::Fallback& fallback,
float stormWindSpeed,
@ -49,24 +106,26 @@ Weather::Weather(const std::string& name,
const std::string& ambientLoopSoundID,
const std::string& particleEffect)
: mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture"))
, mSkySunriseColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"))
, mSkyDayColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Day_Color"))
, mSkySunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Sunset_Color"))
, mSkyNightColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Night_Color"))
, mFogSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunrise_Color"))
, mFogDayColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Day_Color"))
, mFogSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunset_Color"))
, mFogNightColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Night_Color"))
, mAmbientSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunrise_Color"))
, mAmbientDayColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Day_Color"))
, mAmbientSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunset_Color"))
, mAmbientNightColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Night_Color"))
, mSunSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunrise_Color"))
, mSunDayColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Day_Color"))
, mSunSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunset_Color"))
, mSunNightColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Night_Color"))
, mLandFogDayDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Day_Depth"))
, mLandFogNightDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Night_Depth"))
, mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sky_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sky_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sky_Night_Color"))
, mFogColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Fog_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Fog_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Fog_Night_Color"))
, mAmbientColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Ambient_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Ambient_Night_Color"))
, mSunColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunrise_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sun_Day_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sun_Sunset_Color"),
fallback.getFallbackColour("Weather_" + name + "_Sun_Night_Color"))
, mLandFogDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Day_Depth"),
fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Day_Depth"),
fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Day_Depth"),
fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Night_Depth"))
, mSunDiscSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Disc_Sunset_Color"))
, mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed"))
, mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_Speed"))
@ -432,12 +491,13 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const MWWo
, mSunriseDuration(fallback.getFallbackFloat("Weather_Sunrise_Duration"))
, mSunsetDuration(fallback.getFallbackFloat("Weather_Sunset_Duration"))
, mSunPreSunsetTime(fallback.getFallbackFloat("Weather_Sun_Pre-Sunset_Time"))
, mNightStart(mSunsetTime + mSunsetDuration)
, mNightEnd(mSunriseTime - 0.5f)
, mDayStart(mSunriseTime + mSunriseDuration)
, mDayEnd(mSunsetTime)
, mNightFade(0, 0, 0, 1)
, mHoursBetweenWeatherChanges(fallback.getFallbackFloat("Weather_Hours_Between_Weather_Changes"))
, mRainSpeed(fallback.getFallbackFloat("Weather_Precip_Gravity"))
, mUnderwaterFog(fallback.getFallbackFloat("Water_UnderwaterSunriseFog"),
fallback.getFallbackFloat("Water_UnderwaterDayFog"),
fallback.getFallbackFloat("Water_UnderwaterSunsetFog"),
fallback.getFallbackFloat("Water_UnderwaterNightFog"))
, mWeatherSettings()
, mMasser("Masser", fallback)
, mSecunda("Secunda", fallback)
@ -457,6 +517,12 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const MWWo
, mAmbientSound()
, mPlayingSoundID()
{
mTimeSettings.mNightStart = mSunsetTime + mSunsetDuration;
mTimeSettings.mNightEnd = mSunriseTime - 0.5f;
mTimeSettings.mDayStart = mSunriseTime + mSunriseDuration;
mTimeSettings.mDayEnd = mSunsetTime;
mTimeSettings.mSunriseTime = mSunriseTime;
mWeatherSettings.reserve(10);
addWeather("Clear", fallback); // 0
addWeather("Cloudy", fallback); // 1
@ -589,7 +655,7 @@ void WeatherManager::update(float duration, bool paused)
}
// disable sun during night
if (time.getHour() >= mNightStart || time.getHour() <= mSunriseTime)
if (time.getHour() >= mTimeSettings.mNightStart || time.getHour() <= mSunriseTime)
mRendering.getSkyManager()->sunDisable();
else
mRendering.getSkyManager()->sunEnable();
@ -600,10 +666,10 @@ void WeatherManager::update(float duration, bool paused)
{
// Shift times into a 24-hour window beginning at mSunriseTime...
float adjustedHour = time.getHour();
float adjustedNightStart = mNightStart;
float adjustedNightStart = mTimeSettings.mNightStart;
if ( time.getHour() < mSunriseTime )
adjustedHour += 24.f;
if ( mNightStart < mSunriseTime )
if ( mTimeSettings.mNightStart < mSunriseTime )
adjustedNightStart += 24.f;
const bool is_night = adjustedHour >= adjustedNightStart;
@ -624,6 +690,8 @@ void WeatherManager::update(float duration, bool paused)
mRendering.setSunDirection( final * -1 );
}
float underwaterFog = mUnderwaterFog.getValue(time.getHour(), mTimeSettings);
float peakHour = mSunriseTime + (mSunsetTime - mSunriseTime) / 2;
if (time.getHour() < mSunriseTime || time.getHour() > mSunsetTime)
mRendering.getSkyManager()->setGlareTimeOfDayFade(0);
@ -635,7 +703,7 @@ void WeatherManager::update(float duration, bool paused)
mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time));
mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time));
mRendering.configureFog(mResult.mFogDepth, mResult.mFogColor);
mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mFogColor);
mRendering.setAmbientColour(mResult.mAmbientColor);
mRendering.setSunColour(mResult.mSunColor);
@ -697,7 +765,7 @@ bool WeatherManager::isDark() const
TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp();
bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior()
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior());
return exterior && (time.getHour() < mSunriseTime || time.getHour() > mNightStart - 1);
return exterior && (time.getHour() < mSunriseTime || time.getHour() > mTimeSettings.mNightStart - 1);
}
void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
@ -975,81 +1043,14 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam
mResult.mParticleEffect = current.mParticleEffect;
mResult.mRainEffect = current.mRainEffect;
mResult.mNight = (gameHour < mSunriseTime || gameHour > mNightStart - 1);
mResult.mFogDepth = mResult.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth;
mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1);
// TODO: use pre/post sunset/sunrise time values in [Weather] section
// night
if (gameHour <= mNightEnd || gameHour >= mNightStart + 1)
{
mResult.mFogColor = current.mFogNightColor;
mResult.mAmbientColor = current.mAmbientNightColor;
mResult.mSunColor = current.mSunNightColor;
mResult.mSkyColor = current.mSkyNightColor;
mResult.mNightFade = 1.f;
}
// sunrise
else if (gameHour >= mNightEnd && gameHour <= mDayStart + 1)
{
if (gameHour <= mSunriseTime)
{
// fade in
float advance = mSunriseTime - gameHour;
float factor = advance / 0.5f;
mResult.mFogColor = lerp(current.mFogSunriseColor, current.mFogNightColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientNightColor, factor);
mResult.mSunColor = lerp(current.mSunSunriseColor, current.mSunNightColor, factor);
mResult.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyNightColor, factor);
mResult.mNightFade = factor;
}
else //if (gameHour >= 6)
{
// fade out
float advance = gameHour - mSunriseTime;
float factor = advance / 3.f;
mResult.mFogColor = lerp(current.mFogSunriseColor, current.mFogDayColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunriseColor, current.mAmbientDayColor, factor);
mResult.mSunColor = lerp(current.mSunSunriseColor, current.mSunDayColor, factor);
mResult.mSkyColor = lerp(current.mSkySunriseColor, current.mSkyDayColor, factor);
}
}
// day
else if (gameHour >= mDayStart + 1 && gameHour <= mDayEnd - 1)
{
mResult.mFogColor = current.mFogDayColor;
mResult.mAmbientColor = current.mAmbientDayColor;
mResult.mSunColor = current.mSunDayColor;
mResult.mSkyColor = current.mSkyDayColor;
}
// sunset
else if (gameHour >= mDayEnd - 1 && gameHour <= mNightStart + 1)
{
if (gameHour <= mDayEnd + 1)
{
// fade in
float advance = (mDayEnd + 1) - gameHour;
float factor = (advance / 2);
mResult.mFogColor = lerp(current.mFogSunsetColor, current.mFogDayColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientDayColor, factor);
mResult.mSunColor = lerp(current.mSunSunsetColor, current.mSunDayColor, factor);
mResult.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyDayColor, factor);
}
else //if (gameHour >= 19)
{
// fade out
float advance = gameHour - (mDayEnd + 1);
float factor = advance / 2.f;
mResult.mFogColor = lerp(current.mFogSunsetColor, current.mFogNightColor, factor);
mResult.mAmbientColor = lerp(current.mAmbientSunsetColor, current.mAmbientNightColor, factor);
mResult.mSunColor = lerp(current.mSunSunsetColor, current.mSunNightColor, factor);
mResult.mSkyColor = lerp(current.mSkySunsetColor, current.mSkyNightColor, factor);
mResult.mNightFade = factor;
}
}
mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings);
mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings);
mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings);
mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings);
mResult.mSkyColor = current.mSkyColor.getValue(gameHour, mTimeSettings);
mResult.mNightFade = mNightFade.getValue(gameHour, mTimeSettings);
if (gameHour >= mSunsetTime - mSunPreSunsetTime)
{

@ -34,6 +34,33 @@ namespace MWWorld
class Fallback;
class TimeStamp;
struct TimeOfDaySettings
{
float mNightStart;
float mNightEnd;
float mDayStart;
float mDayEnd;
float mSunriseTime;
};
/// Interpolates between 4 data points (sunrise, day, sunset, night) based on the time of day.
/// The template value could be a floating point number, or a color.
template <typename T>
class TimeOfDayInterpolator
{
public:
TimeOfDayInterpolator(const T& sunrise, const T& day, const T& sunset, const T& night)
: mSunriseValue(sunrise), mDayValue(day), mSunsetValue(sunset), mNightValue(night)
{
}
T getValue (const float gameHour, const TimeOfDaySettings& timeSettings) const;
private:
T mSunriseValue, mDayValue, mSunsetValue, mNightValue;
};
/// Defines a single weather setting (according to INI)
class Weather
{
@ -47,33 +74,17 @@ namespace MWWorld
std::string mCloudTexture;
// Sky (atmosphere) colors
osg::Vec4f mSkySunriseColor;
osg::Vec4f mSkyDayColor;
osg::Vec4f mSkySunsetColor;
osg::Vec4f mSkyNightColor;
// Fog colors
osg::Vec4f mFogSunriseColor;
osg::Vec4f mFogDayColor;
osg::Vec4f mFogSunsetColor;
osg::Vec4f mFogNightColor;
// Ambient lighting colors
osg::Vec4f mAmbientSunriseColor;
osg::Vec4f mAmbientDayColor;
osg::Vec4f mAmbientSunsetColor;
osg::Vec4f mAmbientNightColor;
// Sun (directional) lighting colors
osg::Vec4f mSunSunriseColor;
osg::Vec4f mSunDayColor;
osg::Vec4f mSunSunsetColor;
osg::Vec4f mSunNightColor;
// Sky (atmosphere) color
TimeOfDayInterpolator<osg::Vec4f> mSkyColor;
// Fog color
TimeOfDayInterpolator<osg::Vec4f> mFogColor;
// Ambient lighting color
TimeOfDayInterpolator<osg::Vec4f> mAmbientColor;
// Sun (directional) lighting color
TimeOfDayInterpolator<osg::Vec4f> mSunColor;
// Fog depth/density
float mLandFogDayDepth;
float mLandFogNightDepth;
TimeOfDayInterpolator<float> mLandFogDepth;
// Color modulation for the sun itself during sunset
osg::Vec4f mSunDiscSunsetColor;
@ -243,12 +254,18 @@ namespace MWWorld
float mSunriseDuration;
float mSunsetDuration;
float mSunPreSunsetTime;
float mNightStart;
float mNightEnd;
float mDayStart;
float mDayEnd;
TimeOfDaySettings mTimeSettings;
// fading of night skydome
TimeOfDayInterpolator<float> mNightFade;
float mHoursBetweenWeatherChanges;
float mRainSpeed;
// underwater fog not really related to weather, but we handle it here because it's convenient
TimeOfDayInterpolator<float> mUnderwaterFog;
std::vector<Weather> mWeatherSettings;
MoonModel mMasser;
MoonModel mSecunda;

@ -1969,7 +1969,7 @@ namespace MWWorld
{
osg::Vec3f pos (object.getRefData().getPosition().asVec3());
pos.z() += heightRatio*2*mPhysics->getHalfExtents(object).z();
pos.z() += heightRatio*2*mPhysics->getRenderingHalfExtents(object).z();
return isUnderwater(object.getCell(), pos);
}

Loading…
Cancel
Save