From 04accb7652d7deb681a71f9407bd4fca77d4a98a Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 22 Apr 2015 17:34:39 +0200 Subject: [PATCH] Add LightController --- apps/openmw/mwrender/animation.cpp | 14 +++ components/CMakeLists.txt | 2 +- components/sceneutil/lightcontroller.cpp | 129 +++++++++++++++++++++++ components/sceneutil/lightcontroller.hpp | 42 ++++++++ components/sceneutil/riggeometry.cpp | 2 +- components/sceneutil/skeleton.hpp | 2 +- libs/openengine/CMakeLists.txt | 6 +- libs/openengine/ogre/.gitignore | 1 - libs/openengine/ogre/lights.cpp | 102 ------------------ libs/openengine/ogre/lights.hpp | 64 ----------- 10 files changed, 189 insertions(+), 175 deletions(-) create mode 100644 components/sceneutil/lightcontroller.cpp create mode 100644 components/sceneutil/lightcontroller.hpp delete mode 100644 libs/openengine/ogre/.gitignore delete mode 100644 libs/openengine/ogre/lights.cpp delete mode 100644 libs/openengine/ogre/lights.hpp diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index d54e87dc5..8a0a85620 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -197,6 +198,19 @@ namespace MWRender light->setAmbient(osg::Vec4f(0,0,0,1)); light->setSpecular(osg::Vec4f(0,0,0,0)); + osg::ref_ptr ctrl (new SceneUtil::LightController); + ctrl->setDiffuse(light->getDiffuse()); + if (esmLight->mData.mFlags & ESM::Light::Flicker) + ctrl->setType(SceneUtil::LightController::LT_Flicker); + if (esmLight->mData.mFlags & ESM::Light::FlickerSlow) + ctrl->setType(SceneUtil::LightController::LT_FlickerSlow); + if (esmLight->mData.mFlags & ESM::Light::Pulse) + ctrl->setType(SceneUtil::LightController::LT_Pulse); + if (esmLight->mData.mFlags & ESM::Light::PulseSlow) + ctrl->setType(SceneUtil::LightController::LT_PulseSlow); + + lightSource->addUpdateCallback(ctrl); + attachTo->addChild(lightSource); } diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index 75f6756f8..aa801689a 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -39,7 +39,7 @@ add_component_dir (resource ) add_component_dir (sceneutil - clone attach lightmanager visitor util statesetupdater controller skeleton riggeometry + clone attach lightmanager visitor util statesetupdater controller skeleton riggeometry lightcontroller ) add_component_dir (nif diff --git a/components/sceneutil/lightcontroller.cpp b/components/sceneutil/lightcontroller.cpp new file mode 100644 index 000000000..d0056ecc6 --- /dev/null +++ b/components/sceneutil/lightcontroller.cpp @@ -0,0 +1,129 @@ +#include "lightcontroller.hpp" + +#include + +#include + +#include + +#include + +namespace +{ + + float pulseAmplitude(float time) + { + return std::sin(time); + } + + float flickerAmplitude(float time) + { + static const float fb = 1.17024f; + static const float f[3] = { 1.5708f, 4.18774f, 5.19934f }; + static const float o[3] = { 0.804248f, 2.11115f, 3.46832f }; + static const float m[3] = { 1.0f, 0.785f, 0.876f }; + static const float s = 0.394f; + + float v = 0.0f; + for(int i = 0;i < 3;++i) + v += std::sin(fb*time*f[i] + o[1])*m[i]; + return v * s; + } + + float flickerFrequency(float phase) + { + static const float fa = 0.785398f; + static const float tdo = 0.94f; + static const float tdm = 2.48f; + + return tdo + tdm*std::sin(fa * phase); + } + +} + +namespace SceneUtil +{ + + LightController::LightController() + : mType(LT_Normal) + , mPhase((OEngine::Misc::Rng::rollClosedProbability() * 2.f - 1.f) * 500.f) + , mLastTime(0.0) + , mDeltaCount(0.f) + , mDirection(1.f) + { + } + + void LightController::setType(LightController::LightType type) + { + mType = type; + } + + void LightController::operator ()(osg::Node* node, osg::NodeVisitor* nv) + { + double time = nv->getFrameStamp()->getSimulationTime(); + if (time == mLastTime) + return; + + float dt = static_cast(time - mLastTime); + mLastTime = time; + + float brightness = 1.0f; + float cycle_time; + float time_distortion; + + const float pi = 3.14159265359; + + if(mType == LT_Pulse || mType == LT_PulseSlow) + { + cycle_time = 2.0f * pi; + time_distortion = 20.0f; + } + else + { + static const float fa = 0.785398f; + static const float phase_wavelength = 120.0f * pi / fa; + + cycle_time = 500.0f; + mPhase = std::fmod(mPhase + dt, phase_wavelength); + time_distortion = flickerFrequency(mPhase); + } + + mDeltaCount += mDirection*dt*time_distortion; + if(mDirection > 0 && mDeltaCount > +cycle_time) + { + mDirection = -1.0f; + mDeltaCount = 2.0f*cycle_time - mDeltaCount; + } + if(mDirection < 0 && mDeltaCount < -cycle_time) + { + mDirection = +1.0f; + mDeltaCount = -2.0f*cycle_time - mDeltaCount; + } + + static const float fast = 4.0f/1.0f; + static const float slow = 1.0f/1.0f; + + // These formulas are just guesswork, but they work pretty well + if(mType == LT_Normal) + { + // Less than 1/255 light modifier for a constant light: + brightness = 1.0f + flickerAmplitude(mDeltaCount*slow)/255.0f; + } + else if(mType == LT_Flicker) + brightness = 0.75f + flickerAmplitude(mDeltaCount*fast)*0.25f; + else if(mType == LT_FlickerSlow) + brightness = 0.75f + flickerAmplitude(mDeltaCount*slow)*0.25f; + else if(mType == LT_Pulse) + brightness = 1.0f + pulseAmplitude(mDeltaCount*fast)*0.25f; + else if(mType == LT_PulseSlow) + brightness = 1.0f + pulseAmplitude(mDeltaCount*slow)*0.25f; + + static_cast(node)->getLight()->setDiffuse(mDiffuseColor * brightness); + } + + void LightController::setDiffuse(osg::Vec4f color) + { + mDiffuseColor = color; + } + +} diff --git a/components/sceneutil/lightcontroller.hpp b/components/sceneutil/lightcontroller.hpp new file mode 100644 index 000000000..f6e2fa9fa --- /dev/null +++ b/components/sceneutil/lightcontroller.hpp @@ -0,0 +1,42 @@ +#ifndef OPENMW_COMPONENTS_SCENEUTIL_LIGHTCONTROLLER_H +#define OPENMW_COMPONENTS_SCENEUTIL_LIGHTCONTROLLER_H + +#include +#include + +namespace SceneUtil +{ + + /// @brief Controller class to handle a pulsing and/or flickering light + /// @note Must be set on a SceneUtil::LightSource. + class LightController : public osg::NodeCallback + { + public: + enum LightType { + LT_Normal, + LT_Flicker, + LT_FlickerSlow, + LT_Pulse, + LT_PulseSlow + }; + + LightController(); + + void setType(LightType type); + + void setDiffuse(osg::Vec4f color); + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv); + + private: + LightType mType; + osg::Vec4f mDiffuseColor; + float mPhase; + float mDeltaCount; + int mDirection; + double mLastTime; + }; + +} + +#endif diff --git a/components/sceneutil/riggeometry.cpp b/components/sceneutil/riggeometry.cpp index 4d4ea22d2..ab9abcdda 100644 --- a/components/sceneutil/riggeometry.cpp +++ b/components/sceneutil/riggeometry.cpp @@ -149,7 +149,7 @@ void RigGeometry::update(osg::NodeVisitor* nv) else path.push_back(*it); } - osg::Matrix geomToSkel = osg::computeWorldToLocal(path); + osg::Matrixf geomToSkel = osg::computeWorldToLocal(path); // skinning osg::Vec3Array* positionSrc = static_cast(mSourceGeometry->getVertexArray()); diff --git a/components/sceneutil/skeleton.hpp b/components/sceneutil/skeleton.hpp index acb9e6136..d710ac61b 100644 --- a/components/sceneutil/skeleton.hpp +++ b/components/sceneutil/skeleton.hpp @@ -16,7 +16,7 @@ namespace SceneUtil Bone(); ~Bone(); - osg::Matrix mMatrixInSkeletonSpace; + osg::Matrixf mMatrixInSkeletonSpace; osg::MatrixTransform* mNode; diff --git a/libs/openengine/CMakeLists.txt b/libs/openengine/CMakeLists.txt index f3622b2ee..0fb39b9d1 100644 --- a/libs/openengine/CMakeLists.txt +++ b/libs/openengine/CMakeLists.txt @@ -1,7 +1,3 @@ -set(OENGINE_OGRE - #ogre/lights.cpp -) - set(OENGINE_GUI gui/loglistener.cpp #gui/manager.cpp @@ -26,7 +22,7 @@ set(OENGINE_MISC misc/rng.hpp ) -set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET} ${OENGINE_MISC}) +set(OENGINE_ALL ${OENGINE_GUI} ${OENGINE_BULLET} ${OENGINE_MISC}) set(OENGINE_LIBRARY "oengine") set(OENGINE_LIBRARY ${OENGINE_LIBRARY} PARENT_SCOPE) diff --git a/libs/openengine/ogre/.gitignore b/libs/openengine/ogre/.gitignore deleted file mode 100644 index 3367afdbb..000000000 --- a/libs/openengine/ogre/.gitignore +++ /dev/null @@ -1 +0,0 @@ -old diff --git a/libs/openengine/ogre/lights.cpp b/libs/openengine/ogre/lights.cpp deleted file mode 100644 index 97fa938da..000000000 --- a/libs/openengine/ogre/lights.cpp +++ /dev/null @@ -1,102 +0,0 @@ -#include "lights.hpp" - -#include - - -namespace OEngine { -namespace Render { - -Ogre::Real LightFunction::pulseAmplitude(Ogre::Real time) -{ - return std::sin(time); -} - -Ogre::Real LightFunction::flickerAmplitude(Ogre::Real time) -{ - static const float fb = 1.17024f; - static const float f[3] = { 1.5708f, 4.18774f, 5.19934f }; - static const float o[3] = { 0.804248f, 2.11115f, 3.46832f }; - static const float m[3] = { 1.0f, 0.785f, 0.876f }; - static const float s = 0.394f; - - float v = 0.0f; - for(int i = 0;i < 3;++i) - v += std::sin(fb*time*f[i] + o[1])*m[i]; - return v * s; -} - -Ogre::Real LightFunction::flickerFrequency(Ogre::Real phase) -{ - static const float fa = 0.785398f; - static const float tdo = 0.94f; - static const float tdm = 2.48f; - - return tdo + tdm*std::sin(fa * phase); -} - -Ogre::Real LightFunction::calculate(Ogre::Real value) -{ - Ogre::Real brightness = 1.0f; - float cycle_time; - float time_distortion; - - if(mType == LT_Pulse || mType == LT_PulseSlow) - { - cycle_time = 2.0f * Ogre::Math::PI; - time_distortion = 20.0f; - } - else - { - static const float fa = 0.785398f; - static const float phase_wavelength = 120.0f * 3.14159265359f / fa; - - cycle_time = 500.0f; - mPhase = std::fmod(mPhase + value, phase_wavelength); - time_distortion = flickerFrequency(mPhase); - } - - mDeltaCount += mDirection*value*time_distortion; - if(mDirection > 0 && mDeltaCount > +cycle_time) - { - mDirection = -1.0f; - mDeltaCount = 2.0f*cycle_time - mDeltaCount; - } - if(mDirection < 0 && mDeltaCount < -cycle_time) - { - mDirection = +1.0f; - mDeltaCount = -2.0f*cycle_time - mDeltaCount; - } - - static const float fast = 4.0f/1.0f; - static const float slow = 1.0f/1.0f; - - // These formulas are just guesswork, but they work pretty well - if(mType == LT_Normal) - { - // Less than 1/255 light modifier for a constant light: - brightness = 1.0f + flickerAmplitude(mDeltaCount*slow)/255.0f; - } - else if(mType == LT_Flicker) - brightness = 0.75f + flickerAmplitude(mDeltaCount*fast)*0.25f; - else if(mType == LT_FlickerSlow) - brightness = 0.75f + flickerAmplitude(mDeltaCount*slow)*0.25f; - else if(mType == LT_Pulse) - brightness = 1.0f + pulseAmplitude(mDeltaCount*fast)*0.25f; - else if(mType == LT_PulseSlow) - brightness = 1.0f + pulseAmplitude(mDeltaCount*slow)*0.25f; - - return brightness; -} - -Ogre::Real LightValue::getValue() const -{ - return 0.0f; -} - -void LightValue::setValue(Ogre::Real value) -{ - mTarget->setDiffuseColour(mColor * value); -} - -} -} diff --git a/libs/openengine/ogre/lights.hpp b/libs/openengine/ogre/lights.hpp deleted file mode 100644 index 61d09a0e6..000000000 --- a/libs/openengine/ogre/lights.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef OENGINE_OGRE_LIGHTS_H -#define OENGINE_OGRE_LIGHTS_H - -#include -#include -#include - -/* - * Controller classes to handle pulsing and flicker lights - */ - -namespace OEngine { -namespace Render { - enum LightType { - LT_Normal, - LT_Flicker, - LT_FlickerSlow, - LT_Pulse, - LT_PulseSlow - }; - - class LightFunction : public Ogre::ControllerFunction - { - LightType mType; - Ogre::Real mPhase; - Ogre::Real mDirection; - - static Ogre::Real pulseAmplitude(Ogre::Real time); - - static Ogre::Real flickerAmplitude(Ogre::Real time); - static Ogre::Real flickerFrequency(Ogre::Real phase); - - public: - // MSVC needs the constructor for a class inheriting a template to be defined in header - LightFunction(LightType type) - : ControllerFunction(true) - , mType(type) - , mPhase(Ogre::Math::RangeRandom(-500.0f, +500.0f)) - , mDirection(1.0f) - { - } - virtual Ogre::Real calculate(Ogre::Real value); - }; - - class LightValue : public Ogre::ControllerValue - { - Ogre::Light *mTarget; - Ogre::ColourValue mColor; - - public: - // MSVC needs the constructor for a class inheriting a template to be defined in header - LightValue(Ogre::Light *light, const Ogre::ColourValue &color) - : mTarget(light) - , mColor(color) - { - } - - virtual Ogre::Real getValue() const; - virtual void setValue(Ogre::Real value); - }; -} -} - -#endif