mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-21 12:53:51 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
ab2df963e9
18 changed files with 290 additions and 157 deletions
|
@ -774,7 +774,7 @@ namespace MWClass
|
||||||
return ref->mBase->mAiData.mFight;
|
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>();
|
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||||
scale *= ref->mBase->mScale;
|
scale *= ref->mBase->mScale;
|
||||||
|
|
|
@ -133,7 +133,8 @@ namespace MWClass
|
||||||
|
|
||||||
virtual int getBaseFightRating(const MWWorld::Ptr &ptr) const;
|
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;
|
+ 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 =
|
MWWorld::LiveCellRef<ESM::NPC> *ref =
|
||||||
ptr.get<ESM::NPC>();
|
ptr.get<ESM::NPC>();
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,8 @@ namespace MWClass
|
||||||
/// \param actor Actor that is resposible for the ID being applied to \a ptr.
|
/// \param actor Actor that is resposible for the ID being applied to \a ptr.
|
||||||
/// \return Any effect?
|
/// \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;
|
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.
|
///< Inform actor \a ptr that a skill use has succeeded.
|
||||||
|
|
|
@ -110,12 +110,14 @@ void Actor::updateScale()
|
||||||
float scale = mPtr.getCellRef().getScale();
|
float scale = mPtr.getCellRef().getScale();
|
||||||
osg::Vec3f scaleVec(scale,scale,scale);
|
osg::Vec3f scaleVec(scale,scale,scale);
|
||||||
|
|
||||||
if (!mPtr.getClass().isNpc())
|
mPtr.getClass().adjustScale(mPtr, scaleVec, false);
|
||||||
mPtr.getClass().adjustScale(mPtr, scaleVec);
|
|
||||||
|
|
||||||
mScale = scaleVec;
|
mScale = scaleVec;
|
||||||
mShape->setLocalScaling(toBullet(mScale));
|
mShape->setLocalScaling(toBullet(mScale));
|
||||||
|
|
||||||
|
scaleVec = osg::Vec3f(scale,scale,scale);
|
||||||
|
mPtr.getClass().adjustScale(mPtr, scaleVec, true);
|
||||||
|
mRenderingScale = scaleVec;
|
||||||
|
|
||||||
updatePosition();
|
updatePosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,6 +126,11 @@ osg::Vec3f Actor::getHalfExtents() const
|
||||||
return osg::componentMultiply(mHalfExtents, mScale);
|
return osg::componentMultiply(mHalfExtents, mScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Vec3f Actor::getRenderingHalfExtents() const
|
||||||
|
{
|
||||||
|
return osg::componentMultiply(mHalfExtents, mRenderingScale);
|
||||||
|
}
|
||||||
|
|
||||||
void Actor::setInertialForce(const osg::Vec3f &force)
|
void Actor::setInertialForce(const osg::Vec3f &force)
|
||||||
{
|
{
|
||||||
mForce = force;
|
mForce = force;
|
||||||
|
|
|
@ -66,10 +66,17 @@ namespace MWPhysics
|
||||||
void updatePosition();
|
void updatePosition();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the (scaled) half extents
|
* Returns the half extents of the collision body (scaled according to collision scale)
|
||||||
*/
|
*/
|
||||||
osg::Vec3f getHalfExtents() const;
|
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
|
* Sets the current amount of inertial force (incl. gravity) affecting this physic actor
|
||||||
*/
|
*/
|
||||||
|
@ -118,6 +125,7 @@ namespace MWPhysics
|
||||||
osg::Quat mRotation;
|
osg::Quat mRotation;
|
||||||
|
|
||||||
osg::Vec3f mScale;
|
osg::Vec3f mScale;
|
||||||
|
osg::Vec3f mRenderingScale;
|
||||||
osg::Vec3f mPosition;
|
osg::Vec3f mPosition;
|
||||||
|
|
||||||
osg::Vec3f mForce;
|
osg::Vec3f mForce;
|
||||||
|
|
|
@ -261,7 +261,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
static const float fSwimHeightScale = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||||
.find("fSwimHeightScale")->getFloat();
|
.find("fSwimHeightScale")->getFloat();
|
||||||
float swimlevel = waterlevel + halfExtents.z() - (halfExtents.z() * 2 * fSwimHeightScale);
|
float swimlevel = waterlevel + halfExtents.z() - (physicActor->getRenderingHalfExtents().z() * 2 * fSwimHeightScale);
|
||||||
|
|
||||||
ActorTracer tracer;
|
ActorTracer tracer;
|
||||||
osg::Vec3f inertia = physicActor->getInertialForce();
|
osg::Vec3f inertia = physicActor->getInertialForce();
|
||||||
|
@ -878,6 +878,15 @@ namespace MWPhysics
|
||||||
return osg::Vec3f();
|
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
|
class ContactTestResultCallback : public btCollisionWorld::ContactResultCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -110,6 +110,9 @@ namespace MWPhysics
|
||||||
/// Get physical half extents (scaled) of the given actor.
|
/// Get physical half extents (scaled) of the given actor.
|
||||||
osg::Vec3f getHalfExtents(const MWWorld::Ptr& 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
|
/// Queues velocity movement for a Ptr. If a Ptr is already queued, its velocity will
|
||||||
/// be overwritten. Valid until the next call to applyQueuedMovement.
|
/// be overwritten. Valid until the next call to applyQueuedMovement.
|
||||||
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);
|
void queueObjectMovement(const MWWorld::Ptr &ptr, const osg::Vec3f &velocity);
|
||||||
|
|
|
@ -287,7 +287,7 @@ namespace MWRender
|
||||||
void InventoryPreview::onSetup()
|
void InventoryPreview::onSetup()
|
||||||
{
|
{
|
||||||
osg::Vec3f scale (1.f, 1.f, 1.f);
|
osg::Vec3f scale (1.f, 1.f, 1.f);
|
||||||
mCharacter.getClass().adjustScale(mCharacter, scale);
|
mCharacter.getClass().adjustScale(mCharacter, scale, true);
|
||||||
|
|
||||||
mNode->setScale(scale);
|
mNode->setScale(scale);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
|
#include "../mwworld/fallback.hpp"
|
||||||
|
|
||||||
#include "sky.hpp"
|
#include "sky.hpp"
|
||||||
#include "effectmanager.hpp"
|
#include "effectmanager.hpp"
|
||||||
#include "npcanimation.hpp"
|
#include "npcanimation.hpp"
|
||||||
|
@ -199,6 +201,10 @@ namespace MWRender
|
||||||
updateProjectionMatrix();
|
updateProjectionMatrix();
|
||||||
mStateUpdater->setFogEnd(mViewDistance);
|
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("near", mNearClip));
|
||||||
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance));
|
mRootNode->getOrCreateStateSet()->addUniform(new osg::Uniform("far", mViewDistance));
|
||||||
}
|
}
|
||||||
|
@ -349,13 +355,14 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog);
|
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;
|
mFogDepth = fogDepth;
|
||||||
mFogColor = color;
|
mFogColor = color;
|
||||||
|
mUnderwaterFog = underwaterFog;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkyManager* RenderingManager::getSkyManager()
|
SkyManager* RenderingManager::getSkyManager()
|
||||||
|
@ -378,9 +385,9 @@ namespace MWRender
|
||||||
mCamera->getPosition(focal, cameraPos);
|
mCamera->getPosition(focal, cameraPos);
|
||||||
if (mWater->isUnderwater(cameraPos))
|
if (mWater->isUnderwater(cameraPos))
|
||||||
{
|
{
|
||||||
setFogColor(osg::Vec4f(0.090195f, 0.115685f, 0.12745f, 1.f));
|
setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight));
|
||||||
mStateUpdater->setFogStart(0.f);
|
mStateUpdater->setFogStart(mViewDistance * (1 - mUnderwaterFog));
|
||||||
mStateUpdater->setFogEnd(1000);
|
mStateUpdater->setFogEnd(mViewDistance);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace MWRender
|
||||||
|
|
||||||
void configureAmbient(const ESM::Cell* cell);
|
void configureAmbient(const ESM::Cell* cell);
|
||||||
void configureFog(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 addCell(const MWWorld::CellStore* store);
|
||||||
void removeCell(const MWWorld::CellStore* store);
|
void removeCell(const MWWorld::CellStore* store);
|
||||||
|
@ -192,6 +192,10 @@ namespace MWRender
|
||||||
osg::ref_ptr<StateUpdater> mStateUpdater;
|
osg::ref_ptr<StateUpdater> mStateUpdater;
|
||||||
|
|
||||||
float mFogDepth;
|
float mFogDepth;
|
||||||
|
osg::Vec4f mUnderwaterColor;
|
||||||
|
float mUnderwaterWeight;
|
||||||
|
float mUnderwaterFog;
|
||||||
|
float mUnderwaterIndoorFog;
|
||||||
osg::Vec4f mFogColor;
|
osg::Vec4f mFogColor;
|
||||||
|
|
||||||
osg::Vec4f mAmbientColor;
|
osg::Vec4f mAmbientColor;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <osg/MatrixTransform>
|
#include <osg/MatrixTransform>
|
||||||
#include <osg/FrontFace>
|
#include <osg/FrontFace>
|
||||||
#include <osg/Shader>
|
#include <osg/Shader>
|
||||||
|
#include <osg/GLExtensions>
|
||||||
|
|
||||||
#include <osgDB/ReadFile>
|
#include <osgDB/ReadFile>
|
||||||
|
|
||||||
|
@ -144,14 +145,18 @@ class ClipCullNode : public osg::Group
|
||||||
|
|
||||||
osg::RefMatrix* modelViewMatrix = new osg::RefMatrix(*cv->getModelViewMatrix());
|
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
|
// 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)
|
if (mCullPlane->intersect(osg::BoundingSphere(osg::Vec3d(0,0,eyePoint.z()), 0)) > 0)
|
||||||
{
|
{
|
||||||
modelViewMatrix->preMultScale(osg::Vec3(1,1,-1));
|
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);
|
cv->pushModelViewMatrix(modelViewMatrix, osg::Transform::RELATIVE_RF);
|
||||||
traverse(node, nv);
|
traverse(node, nv);
|
||||||
|
@ -167,7 +172,7 @@ public:
|
||||||
{
|
{
|
||||||
addCullCallback (new PlaneCullCallback(&mPlane));
|
addCullCallback (new PlaneCullCallback(&mPlane));
|
||||||
|
|
||||||
mClipNodeTransform = new osg::PositionAttitudeTransform;
|
mClipNodeTransform = new osg::Group;
|
||||||
mClipNodeTransform->addCullCallback(new FlipCallback(&mPlane));
|
mClipNodeTransform->addCullCallback(new FlipCallback(&mPlane));
|
||||||
addChild(mClipNodeTransform);
|
addChild(mClipNodeTransform);
|
||||||
|
|
||||||
|
@ -183,12 +188,12 @@ public:
|
||||||
mPlane = plane;
|
mPlane = plane;
|
||||||
|
|
||||||
mClipNode->getClipPlaneList().clear();
|
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);
|
mClipNode->setStateSetModes(*getOrCreateStateSet(), osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
osg::ref_ptr<osg::PositionAttitudeTransform> mClipNodeTransform;
|
osg::ref_ptr<osg::Group> mClipNodeTransform;
|
||||||
osg::ref_ptr<osg::ClipNode> mClipNode;
|
osg::ref_ptr<osg::ClipNode> mClipNode;
|
||||||
|
|
||||||
osg::Plane mPlane;
|
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> 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));
|
osg::ref_ptr<osg::Shader> shader (new osg::Shader(type));
|
||||||
|
@ -389,6 +424,28 @@ private:
|
||||||
osg::ref_ptr<osg::Node> mScene;
|
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,
|
Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem *resourceSystem, osgUtil::IncrementalCompileOperation *ico,
|
||||||
const MWWorld::Fallback* fallback, const std::string& resourcePath)
|
const MWWorld::Fallback* fallback, const std::string& resourcePath)
|
||||||
: mParent(parent)
|
: mParent(parent)
|
||||||
|
@ -402,6 +459,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
|
||||||
mSimulation.reset(new RippleSimulation(parent, resourceSystem, fallback));
|
mSimulation.reset(new RippleSimulation(parent, resourceSystem, fallback));
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geometry> waterGeom = createWaterGeometry(CELL_SIZE*150, 40, 900);
|
osg::ref_ptr<osg::Geometry> waterGeom = createWaterGeometry(CELL_SIZE*150, 40, 900);
|
||||||
|
waterGeom->setDrawCallback(new DepthClampCallback);
|
||||||
|
|
||||||
mWaterGeode = new osg::Geode;
|
mWaterGeode = new osg::Geode;
|
||||||
mWaterGeode->addDrawable(waterGeom);
|
mWaterGeode->addDrawable(waterGeom);
|
||||||
|
@ -412,6 +470,7 @@ Water::Water(osg::Group *parent, osg::Group* sceneRoot, Resource::ResourceSystem
|
||||||
|
|
||||||
mWaterNode = new osg::PositionAttitudeTransform;
|
mWaterNode = new osg::PositionAttitudeTransform;
|
||||||
mWaterNode->addChild(mWaterGeode);
|
mWaterNode->addChild(mWaterGeode);
|
||||||
|
mWaterNode->addCullCallback(new FudgeCallback);
|
||||||
|
|
||||||
// simple water fallback for the local map
|
// simple water fallback for the local map
|
||||||
osg::ref_ptr<osg::Geode> geode2 (osg::clone(mWaterGeode.get(), osg::CopyOp::DEEP_COPY_NODES));
|
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()
|
Water::~Water()
|
||||||
{
|
{
|
||||||
mParent->removeChild(mWaterNode);
|
mParent->removeChild(mWaterNode);
|
||||||
|
|
||||||
|
if (mReflection)
|
||||||
|
{
|
||||||
|
mParent->removeChild(mReflection);
|
||||||
|
mReflection = NULL;
|
||||||
|
}
|
||||||
|
if (mRefraction)
|
||||||
|
{
|
||||||
|
mParent->removeChild(mRefraction);
|
||||||
|
mRefraction = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Water::setEnabled(bool enabled)
|
void Water::setEnabled(bool enabled)
|
||||||
|
|
|
@ -287,7 +287,7 @@ namespace MWWorld
|
||||||
return "";
|
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;
|
virtual int getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
|
||||||
///< @return the number of enchantment points available for possible enchanting
|
///< @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;
|
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
|
///< 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();
|
float scale = ptr.getCellRef().getScale();
|
||||||
osg::Vec3f scaleVec (scale, scale, scale);
|
osg::Vec3f scaleVec (scale, scale, scale);
|
||||||
ptr.getClass().adjustScale(ptr, scaleVec);
|
ptr.getClass().adjustScale(ptr, scaleVec, true);
|
||||||
rendering.scaleObject(ptr, scaleVec);
|
rendering.scaleObject(ptr, scaleVec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,17 +31,74 @@ namespace
|
||||||
{
|
{
|
||||||
static const int invalidWeatherID = -1;
|
static const int invalidWeatherID = -1;
|
||||||
|
|
||||||
|
// linear interpolate between x and y based on factor.
|
||||||
float lerp (float x, float y, float factor)
|
float lerp (float x, float y, float factor)
|
||||||
{
|
{
|
||||||
return x * (1-factor) + y * 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)
|
osg::Vec4f lerp (const osg::Vec4f& x, const osg::Vec4f& y, float factor)
|
||||||
{
|
{
|
||||||
return x * (1-factor) + y * 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,
|
Weather::Weather(const std::string& name,
|
||||||
const MWWorld::Fallback& fallback,
|
const MWWorld::Fallback& fallback,
|
||||||
float stormWindSpeed,
|
float stormWindSpeed,
|
||||||
|
@ -49,24 +106,26 @@ Weather::Weather(const std::string& name,
|
||||||
const std::string& ambientLoopSoundID,
|
const std::string& ambientLoopSoundID,
|
||||||
const std::string& particleEffect)
|
const std::string& particleEffect)
|
||||||
: mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture"))
|
: mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture"))
|
||||||
, mSkySunriseColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"))
|
, mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"),
|
||||||
, mSkyDayColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Day_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Sky_Day_Color"),
|
||||||
, mSkySunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Sunset_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Sky_Sunset_Color"),
|
||||||
, mSkyNightColor(fallback.getFallbackColour("Weather_" + name + "_Sky_Night_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Sky_Night_Color"))
|
||||||
, mFogSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunrise_Color"))
|
, mFogColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunrise_Color"),
|
||||||
, mFogDayColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Day_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Fog_Day_Color"),
|
||||||
, mFogSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Sunset_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Fog_Sunset_Color"),
|
||||||
, mFogNightColor(fallback.getFallbackColour("Weather_" + name + "_Fog_Night_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Fog_Night_Color"))
|
||||||
, mAmbientSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunrise_Color"))
|
, mAmbientColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunrise_Color"),
|
||||||
, mAmbientDayColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Day_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Ambient_Day_Color"),
|
||||||
, mAmbientSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunset_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Ambient_Sunset_Color"),
|
||||||
, mAmbientNightColor(fallback.getFallbackColour("Weather_" + name + "_Ambient_Night_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Ambient_Night_Color"))
|
||||||
, mSunSunriseColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunrise_Color"))
|
, mSunColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunrise_Color"),
|
||||||
, mSunDayColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Day_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Sun_Day_Color"),
|
||||||
, mSunSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Sunset_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Sun_Sunset_Color"),
|
||||||
, mSunNightColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Night_Color"))
|
fallback.getFallbackColour("Weather_" + name + "_Sun_Night_Color"))
|
||||||
, mLandFogDayDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Day_Depth"))
|
, mLandFogDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Day_Depth"),
|
||||||
, mLandFogNightDepth(fallback.getFallbackFloat("Weather_" + name + "_Land_Fog_Night_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"))
|
, mSunDiscSunsetColor(fallback.getFallbackColour("Weather_" + name + "_Sun_Disc_Sunset_Color"))
|
||||||
, mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed"))
|
, mWindSpeed(fallback.getFallbackFloat("Weather_" + name + "_Wind_Speed"))
|
||||||
, mCloudSpeed(fallback.getFallbackFloat("Weather_" + name + "_Cloud_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"))
|
, mSunriseDuration(fallback.getFallbackFloat("Weather_Sunrise_Duration"))
|
||||||
, mSunsetDuration(fallback.getFallbackFloat("Weather_Sunset_Duration"))
|
, mSunsetDuration(fallback.getFallbackFloat("Weather_Sunset_Duration"))
|
||||||
, mSunPreSunsetTime(fallback.getFallbackFloat("Weather_Sun_Pre-Sunset_Time"))
|
, mSunPreSunsetTime(fallback.getFallbackFloat("Weather_Sun_Pre-Sunset_Time"))
|
||||||
, mNightStart(mSunsetTime + mSunsetDuration)
|
, mNightFade(0, 0, 0, 1)
|
||||||
, mNightEnd(mSunriseTime - 0.5f)
|
|
||||||
, mDayStart(mSunriseTime + mSunriseDuration)
|
|
||||||
, mDayEnd(mSunsetTime)
|
|
||||||
, mHoursBetweenWeatherChanges(fallback.getFallbackFloat("Weather_Hours_Between_Weather_Changes"))
|
, mHoursBetweenWeatherChanges(fallback.getFallbackFloat("Weather_Hours_Between_Weather_Changes"))
|
||||||
, mRainSpeed(fallback.getFallbackFloat("Weather_Precip_Gravity"))
|
, mRainSpeed(fallback.getFallbackFloat("Weather_Precip_Gravity"))
|
||||||
|
, mUnderwaterFog(fallback.getFallbackFloat("Water_UnderwaterSunriseFog"),
|
||||||
|
fallback.getFallbackFloat("Water_UnderwaterDayFog"),
|
||||||
|
fallback.getFallbackFloat("Water_UnderwaterSunsetFog"),
|
||||||
|
fallback.getFallbackFloat("Water_UnderwaterNightFog"))
|
||||||
, mWeatherSettings()
|
, mWeatherSettings()
|
||||||
, mMasser("Masser", fallback)
|
, mMasser("Masser", fallback)
|
||||||
, mSecunda("Secunda", fallback)
|
, mSecunda("Secunda", fallback)
|
||||||
|
@ -457,6 +517,12 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const MWWo
|
||||||
, mAmbientSound()
|
, mAmbientSound()
|
||||||
, mPlayingSoundID()
|
, mPlayingSoundID()
|
||||||
{
|
{
|
||||||
|
mTimeSettings.mNightStart = mSunsetTime + mSunsetDuration;
|
||||||
|
mTimeSettings.mNightEnd = mSunriseTime - 0.5f;
|
||||||
|
mTimeSettings.mDayStart = mSunriseTime + mSunriseDuration;
|
||||||
|
mTimeSettings.mDayEnd = mSunsetTime;
|
||||||
|
mTimeSettings.mSunriseTime = mSunriseTime;
|
||||||
|
|
||||||
mWeatherSettings.reserve(10);
|
mWeatherSettings.reserve(10);
|
||||||
addWeather("Clear", fallback); // 0
|
addWeather("Clear", fallback); // 0
|
||||||
addWeather("Cloudy", fallback); // 1
|
addWeather("Cloudy", fallback); // 1
|
||||||
|
@ -589,7 +655,7 @@ void WeatherManager::update(float duration, bool paused)
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable sun during night
|
// disable sun during night
|
||||||
if (time.getHour() >= mNightStart || time.getHour() <= mSunriseTime)
|
if (time.getHour() >= mTimeSettings.mNightStart || time.getHour() <= mSunriseTime)
|
||||||
mRendering.getSkyManager()->sunDisable();
|
mRendering.getSkyManager()->sunDisable();
|
||||||
else
|
else
|
||||||
mRendering.getSkyManager()->sunEnable();
|
mRendering.getSkyManager()->sunEnable();
|
||||||
|
@ -600,10 +666,10 @@ void WeatherManager::update(float duration, bool paused)
|
||||||
{
|
{
|
||||||
// Shift times into a 24-hour window beginning at mSunriseTime...
|
// Shift times into a 24-hour window beginning at mSunriseTime...
|
||||||
float adjustedHour = time.getHour();
|
float adjustedHour = time.getHour();
|
||||||
float adjustedNightStart = mNightStart;
|
float adjustedNightStart = mTimeSettings.mNightStart;
|
||||||
if ( time.getHour() < mSunriseTime )
|
if ( time.getHour() < mSunriseTime )
|
||||||
adjustedHour += 24.f;
|
adjustedHour += 24.f;
|
||||||
if ( mNightStart < mSunriseTime )
|
if ( mTimeSettings.mNightStart < mSunriseTime )
|
||||||
adjustedNightStart += 24.f;
|
adjustedNightStart += 24.f;
|
||||||
|
|
||||||
const bool is_night = adjustedHour >= adjustedNightStart;
|
const bool is_night = adjustedHour >= adjustedNightStart;
|
||||||
|
@ -624,6 +690,8 @@ void WeatherManager::update(float duration, bool paused)
|
||||||
mRendering.setSunDirection( final * -1 );
|
mRendering.setSunDirection( final * -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float underwaterFog = mUnderwaterFog.getValue(time.getHour(), mTimeSettings);
|
||||||
|
|
||||||
float peakHour = mSunriseTime + (mSunsetTime - mSunriseTime) / 2;
|
float peakHour = mSunriseTime + (mSunsetTime - mSunriseTime) / 2;
|
||||||
if (time.getHour() < mSunriseTime || time.getHour() > mSunsetTime)
|
if (time.getHour() < mSunriseTime || time.getHour() > mSunsetTime)
|
||||||
mRendering.getSkyManager()->setGlareTimeOfDayFade(0);
|
mRendering.getSkyManager()->setGlareTimeOfDayFade(0);
|
||||||
|
@ -635,7 +703,7 @@ void WeatherManager::update(float duration, bool paused)
|
||||||
mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time));
|
mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time));
|
||||||
mRendering.getSkyManager()->setSecundaState(mSecunda.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.setAmbientColour(mResult.mAmbientColor);
|
||||||
mRendering.setSunColour(mResult.mSunColor);
|
mRendering.setSunColour(mResult.mSunColor);
|
||||||
|
|
||||||
|
@ -697,7 +765,7 @@ bool WeatherManager::isDark() const
|
||||||
TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp();
|
TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||||
bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior()
|
bool exterior = (MWBase::Environment::get().getWorld()->isCellExterior()
|
||||||
|| MWBase::Environment::get().getWorld()->isCellQuasiExterior());
|
|| 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)
|
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.mParticleEffect = current.mParticleEffect;
|
||||||
mResult.mRainEffect = current.mRainEffect;
|
mResult.mRainEffect = current.mRainEffect;
|
||||||
|
|
||||||
mResult.mNight = (gameHour < mSunriseTime || gameHour > mNightStart - 1);
|
mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1);
|
||||||
|
|
||||||
mResult.mFogDepth = mResult.mNight ? current.mLandFogNightDepth : current.mLandFogDayDepth;
|
mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings);
|
||||||
|
mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings);
|
||||||
// TODO: use pre/post sunset/sunrise time values in [Weather] section
|
mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings);
|
||||||
// night
|
mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings);
|
||||||
if (gameHour <= mNightEnd || gameHour >= mNightStart + 1)
|
mResult.mSkyColor = current.mSkyColor.getValue(gameHour, mTimeSettings);
|
||||||
{
|
mResult.mNightFade = mNightFade.getValue(gameHour, mTimeSettings);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gameHour >= mSunsetTime - mSunPreSunsetTime)
|
if (gameHour >= mSunsetTime - mSunPreSunsetTime)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,33 @@ namespace MWWorld
|
||||||
class Fallback;
|
class Fallback;
|
||||||
class TimeStamp;
|
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)
|
/// Defines a single weather setting (according to INI)
|
||||||
class Weather
|
class Weather
|
||||||
{
|
{
|
||||||
|
@ -47,33 +74,17 @@ namespace MWWorld
|
||||||
|
|
||||||
std::string mCloudTexture;
|
std::string mCloudTexture;
|
||||||
|
|
||||||
// Sky (atmosphere) colors
|
// Sky (atmosphere) color
|
||||||
osg::Vec4f mSkySunriseColor;
|
TimeOfDayInterpolator<osg::Vec4f> mSkyColor;
|
||||||
osg::Vec4f mSkyDayColor;
|
// Fog color
|
||||||
osg::Vec4f mSkySunsetColor;
|
TimeOfDayInterpolator<osg::Vec4f> mFogColor;
|
||||||
osg::Vec4f mSkyNightColor;
|
// Ambient lighting color
|
||||||
|
TimeOfDayInterpolator<osg::Vec4f> mAmbientColor;
|
||||||
// Fog colors
|
// Sun (directional) lighting color
|
||||||
osg::Vec4f mFogSunriseColor;
|
TimeOfDayInterpolator<osg::Vec4f> mSunColor;
|
||||||
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;
|
|
||||||
|
|
||||||
// Fog depth/density
|
// Fog depth/density
|
||||||
float mLandFogDayDepth;
|
TimeOfDayInterpolator<float> mLandFogDepth;
|
||||||
float mLandFogNightDepth;
|
|
||||||
|
|
||||||
// Color modulation for the sun itself during sunset
|
// Color modulation for the sun itself during sunset
|
||||||
osg::Vec4f mSunDiscSunsetColor;
|
osg::Vec4f mSunDiscSunsetColor;
|
||||||
|
@ -243,12 +254,18 @@ namespace MWWorld
|
||||||
float mSunriseDuration;
|
float mSunriseDuration;
|
||||||
float mSunsetDuration;
|
float mSunsetDuration;
|
||||||
float mSunPreSunsetTime;
|
float mSunPreSunsetTime;
|
||||||
float mNightStart;
|
|
||||||
float mNightEnd;
|
TimeOfDaySettings mTimeSettings;
|
||||||
float mDayStart;
|
|
||||||
float mDayEnd;
|
// fading of night skydome
|
||||||
|
TimeOfDayInterpolator<float> mNightFade;
|
||||||
|
|
||||||
float mHoursBetweenWeatherChanges;
|
float mHoursBetweenWeatherChanges;
|
||||||
float mRainSpeed;
|
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;
|
std::vector<Weather> mWeatherSettings;
|
||||||
MoonModel mMasser;
|
MoonModel mMasser;
|
||||||
MoonModel mSecunda;
|
MoonModel mSecunda;
|
||||||
|
|
|
@ -1969,7 +1969,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
osg::Vec3f pos (object.getRefData().getPosition().asVec3());
|
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);
|
return isUnderwater(object.getCell(), pos);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue