Add LightController

c++11
scrawl 10 years ago
parent 5fbcf8a859
commit 04accb7652

@ -17,6 +17,7 @@
#include <components/sceneutil/visitor.hpp>
#include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/util.hpp>
#include <components/sceneutil/lightcontroller.hpp>
#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<SceneUtil::LightController> 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);
}

@ -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

@ -0,0 +1,129 @@
#include "lightcontroller.hpp"
#include <cmath>
#include <osg/NodeVisitor>
#include <components/sceneutil/lightmanager.hpp>
#include <libs/openengine/misc/rng.hpp>
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<float>(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<SceneUtil::LightSource*>(node)->getLight()->setDiffuse(mDiffuseColor * brightness);
}
void LightController::setDiffuse(osg::Vec4f color)
{
mDiffuseColor = color;
}
}

@ -0,0 +1,42 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_LIGHTCONTROLLER_H
#define OPENMW_COMPONENTS_SCENEUTIL_LIGHTCONTROLLER_H
#include <osg/NodeCallback>
#include <osg/Vec4f>
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

@ -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<osg::Vec3Array*>(mSourceGeometry->getVertexArray());

@ -16,7 +16,7 @@ namespace SceneUtil
Bone();
~Bone();
osg::Matrix mMatrixInSkeletonSpace;
osg::Matrixf mMatrixInSkeletonSpace;
osg::MatrixTransform* mNode;

@ -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)

@ -1,102 +0,0 @@
#include "lights.hpp"
#include <OgreLight.h>
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);
}
}
}

@ -1,64 +0,0 @@
#ifndef OENGINE_OGRE_LIGHTS_H
#define OENGINE_OGRE_LIGHTS_H
#include <OgreController.h>
#include <OgreColourValue.h>
#include <OgreMath.h>
/*
* 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<Ogre::Real>
{
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<Ogre::Real>(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::Real>
{
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
Loading…
Cancel
Save