Use controllers to animate lights in ObjectLists

actorid
Chris Robinson 12 years ago
parent 8984d8f8ee
commit de95926e9f

@ -78,6 +78,7 @@ set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
set(OENGINE_OGRE
${LIBDIR}/openengine/ogre/renderer.cpp
${LIBDIR}/openengine/ogre/fader.cpp
${LIBDIR}/openengine/ogre/lights.cpp
${LIBDIR}/openengine/ogre/particles.cpp
${LIBDIR}/openengine/ogre/selectionbuffer.cpp
${LIBDIR}/openengine/ogre/imagerotate.cpp

@ -8,6 +8,9 @@
#include <OgreBone.h>
#include <OgreSubMesh.h>
#include <OgreSceneManager.h>
#include <OgreControllerManager.h>
#include <libs/openengine/ogre/lights.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/soundmanager.hpp"
@ -281,26 +284,18 @@ void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList
Ogre::Light *olight = objlist.mLights.back();
olight->setDiffuseColour(color);
bool interior = !(mPtr.isInCell() && mPtr.getCell()->mCell->isExterior());
// TODO: Create Controllers for these
#if 0
// randomize lights animations
info.time = Ogre::Math::RangeRandom(-500, +500);
info.phase = Ogre::Math::RangeRandom(-500, +500);
if((light->mData.mFlags&ESM::Light::Flicker))
info.type = LT_Flicker;
else if((light->mData.mFlags&ESM::Light::FlickerSlow))
info.type = LT_FlickerSlow;
else if((light->mData.mFlags&ESM::Light::Pulse))
info.type = LT_Pulse;
else if((light->mData.mFlags&ESM::Light::PulseSlow))
info.type = LT_PulseSlow;
else
info.type = LT_Normal;
#endif
Ogre::ControllerValueRealPtr src(Ogre::ControllerManager::getSingleton().getFrameTimeSource());
Ogre::ControllerValueRealPtr dest(OGRE_NEW OEngine::Render::LightValue(olight, color));
Ogre::ControllerFunctionRealPtr func(OGRE_NEW OEngine::Render::LightFunction(
(light->mData.mFlags&ESM::Light::Flicker) ? OEngine::Render::LT_Flicker :
(light->mData.mFlags&ESM::Light::FlickerSlow) ? OEngine::Render::LT_FlickerSlow :
(light->mData.mFlags&ESM::Light::Pulse) ? OEngine::Render::LT_Pulse :
(light->mData.mFlags&ESM::Light::PulseSlow) ? OEngine::Render::LT_PulseSlow :
OEngine::Render::LT_Normal
));
objlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(src, dest, func));
bool interior = !(mPtr.isInCell() && mPtr.getCell()->mCell->isExterior());
bool quadratic = fallback->getFallbackBool("LightAttenuation_OutQuadInLin") ?
!interior : fallback->getFallbackBool("LightAttenuation_UseQuadratic");

@ -52,6 +52,7 @@ protected:
virtual void setValue(Ogre::Real value);
};
class NullAnimationValue : public Ogre::ControllerValue<Ogre::Real>
{
public:
@ -61,6 +62,7 @@ protected:
{ }
};
struct AnimSource : public Ogre::AnimationAlloc {
NifOgre::TextKeyMap mTextKeys;
std::vector<Ogre::Controller<Ogre::Real> > mControllers[sNumGroups];

@ -0,0 +1,118 @@
#include "lights.hpp"
#include <OgreLight.h>
#include <OgreMath.h>
namespace OEngine {
namespace Render {
LightFunction::LightFunction(LightType type)
: ControllerFunction<Ogre::Real>(true)
, mType(type)
, mPhase(Ogre::Math::RangeRandom(-500.0f, +500.0f))
, mDirection(1.0f)
{
}
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.0 + flickerAmplitude(mDeltaCount*slow)/255.0f;
}
else if(mType == LT_Flicker)
brightness = 0.75 + flickerAmplitude(mDeltaCount*fast)*0.25;
else if(mType == LT_FlickerSlow)
brightness = 0.75 + flickerAmplitude(mDeltaCount*slow)*0.25;
else if(mType == LT_Pulse)
brightness = 1.0 + pulseAmplitude(mDeltaCount*fast)*0.25;
else if(mType == LT_PulseSlow)
brightness = 1.0 + pulseAmplitude(mDeltaCount*slow)*0.25;
return brightness;
}
LightValue::LightValue(Ogre::Light *light, const Ogre::ColourValue &color)
: mTarget(light)
, mColor(color)
{
}
Ogre::Real LightValue::getValue() const
{
return 0.0f;
}
void LightValue::setValue(Ogre::Real value)
{
mTarget->setDiffuseColour(mColor * value);
}
}
}

@ -0,0 +1,51 @@
#ifndef OENGINE_OGRE_LIGHTS_H
#define OENGINE_OGRE_LIGHTS_H
#include <OgreController.h>
#include <OgreColourValue.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:
LightFunction(LightType type);
virtual Ogre::Real calculate(Ogre::Real value);
};
class LightValue : public Ogre::ControllerValue<Ogre::Real>
{
Ogre::Light *mTarget;
Ogre::ColourValue mColor;
public:
LightValue(Ogre::Light *light, const Ogre::ColourValue &color);
virtual Ogre::Real getValue() const;
virtual void setValue(Ogre::Real value);
};
}
}
#endif
Loading…
Cancel
Save