mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 08:49:40 +00:00
Use glow for enchanted arrows (feature #5122)
This commit is contained in:
parent
1eed511b4e
commit
8557346fbd
9 changed files with 239 additions and 208 deletions
|
@ -157,6 +157,7 @@
|
|||
Feature #5051: Provide a separate textures for scrollbars
|
||||
Feature #5094: Unix like console hotkeys
|
||||
Feature #5098: Allow user controller bindings
|
||||
Feature #5122: Use magic glow for enchanted arrows
|
||||
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
||||
Task #4695: Optimize Distant Terrain memory consumption
|
||||
Task #4789: Optimize cell transitions
|
||||
|
|
|
@ -79,7 +79,7 @@ PartHolderPtr ActorAnimation::getWeaponPart(const std::string& model, const std:
|
|||
return PartHolderPtr();
|
||||
|
||||
if (enchantedGlow)
|
||||
addGlow(instance, *glowColor);
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(instance, mResourceSystem, *glowColor);
|
||||
|
||||
return PartHolderPtr(new PartHolder(instance));
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ void ActorAnimation::updateHolsteredWeapon(bool showHolsteredWeapons)
|
|||
if (isEnchanted)
|
||||
{
|
||||
osg::Vec4f glowColor = weapon->getClass().getEnchantmentColor(*weapon);
|
||||
addGlow(weaponNode, glowColor);
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(weaponNode, mResourceSystem, glowColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ void ActorAnimation::updateQuiver()
|
|||
osg::ref_ptr<osg::Group> arrowNode = ammoNode->getChild(i)->asGroup();
|
||||
osg::ref_ptr<osg::Node> arrow = mResourceSystem->getSceneManager()->getInstance(model, arrowNode);
|
||||
if (!ammo->getClass().getEnchantment(*ammo).empty())
|
||||
addGlow(arrow, glowColor);
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(arrow, mResourceSystem, glowColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
||||
#include <osg/TexGen>
|
||||
#include <osg/TexEnvCombine>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Material>
|
||||
|
@ -16,10 +14,8 @@
|
|||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
#include <components/resource/keyframemanager.hpp>
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
|
||||
#include <components/misc/constants.hpp>
|
||||
|
||||
|
@ -519,135 +515,6 @@ namespace MWRender
|
|||
float mAlpha;
|
||||
};
|
||||
|
||||
class GlowUpdater : public SceneUtil::StateSetUpdater
|
||||
{
|
||||
public:
|
||||
GlowUpdater(int texUnit, const osg::Vec4f& color, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures,
|
||||
osg::Node* node, float duration, Resource::ResourceSystem* resourcesystem)
|
||||
: mTexUnit(texUnit)
|
||||
, mColor(color)
|
||||
, mOriginalColor(color)
|
||||
, mTextures(textures)
|
||||
, mNode(node)
|
||||
, mDuration(duration)
|
||||
, mOriginalDuration(duration)
|
||||
, mStartingTime(0)
|
||||
, mResourceSystem(resourcesystem)
|
||||
, mColorChanged(false)
|
||||
, mDone(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void setDefaults(osg::StateSet *stateset)
|
||||
{
|
||||
if (mDone)
|
||||
removeTexture(stateset);
|
||||
else
|
||||
{
|
||||
stateset->setTextureMode(mTexUnit, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||
osg::TexGen* texGen = new osg::TexGen;
|
||||
texGen->setMode(osg::TexGen::SPHERE_MAP);
|
||||
|
||||
stateset->setTextureAttributeAndModes(mTexUnit, texGen, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
|
||||
osg::TexEnvCombine* texEnv = new osg::TexEnvCombine;
|
||||
texEnv->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
|
||||
texEnv->setConstantColor(mColor);
|
||||
texEnv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
|
||||
texEnv->setSource2_RGB(osg::TexEnvCombine::TEXTURE);
|
||||
texEnv->setOperand2_RGB(osg::TexEnvCombine::SRC_COLOR);
|
||||
|
||||
stateset->setTextureAttributeAndModes(mTexUnit, texEnv, osg::StateAttribute::ON);
|
||||
stateset->addUniform(new osg::Uniform("envMapColor", mColor));
|
||||
}
|
||||
}
|
||||
|
||||
void removeTexture(osg::StateSet* stateset)
|
||||
{
|
||||
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXTURE);
|
||||
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXGEN);
|
||||
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXENV);
|
||||
stateset->removeTextureMode(mTexUnit, GL_TEXTURE_2D);
|
||||
stateset->removeUniform("envMapColor");
|
||||
|
||||
osg::StateSet::TextureAttributeList& list = stateset->getTextureAttributeList();
|
||||
while (list.size() && list.rbegin()->empty())
|
||||
list.pop_back();
|
||||
}
|
||||
|
||||
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||
{
|
||||
if (mColorChanged){
|
||||
this->reset();
|
||||
setDefaults(stateset);
|
||||
mColorChanged = false;
|
||||
}
|
||||
if (mDone)
|
||||
return;
|
||||
|
||||
// Set the starting time to measure glow duration from if this is a temporary glow
|
||||
if ((mDuration >= 0) && mStartingTime == 0)
|
||||
mStartingTime = nv->getFrameStamp()->getSimulationTime();
|
||||
|
||||
float time = nv->getFrameStamp()->getSimulationTime();
|
||||
int index = (int)(time*16) % mTextures.size();
|
||||
stateset->setTextureAttribute(mTexUnit, mTextures[index], osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
|
||||
if ((mDuration >= 0) && (time - mStartingTime > mDuration)) // If this is a temporary glow and it has finished its duration
|
||||
{
|
||||
if (mOriginalDuration >= 0) // if this glowupdater was a temporary glow since its creation
|
||||
{
|
||||
removeTexture(stateset);
|
||||
this->reset();
|
||||
mDone = true;
|
||||
mResourceSystem->getSceneManager()->recreateShaders(mNode);
|
||||
}
|
||||
if (mOriginalDuration < 0) // if this glowupdater was originally a permanent glow
|
||||
{
|
||||
mDuration = mOriginalDuration;
|
||||
mStartingTime = 0;
|
||||
mColor = mOriginalColor;
|
||||
this->reset();
|
||||
setDefaults(stateset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isPermanentGlowUpdater()
|
||||
{
|
||||
return (mDuration < 0);
|
||||
}
|
||||
|
||||
bool isDone()
|
||||
{
|
||||
return mDone;
|
||||
}
|
||||
|
||||
void setColor(const osg::Vec4f& color)
|
||||
{
|
||||
mColor = color;
|
||||
mColorChanged = true;
|
||||
}
|
||||
|
||||
void setDuration(float duration)
|
||||
{
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
private:
|
||||
int mTexUnit;
|
||||
osg::Vec4f mColor;
|
||||
osg::Vec4f mOriginalColor; // for restoring the color of a permanent glow after a temporary glow on the object finishes
|
||||
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
|
||||
osg::Node* mNode;
|
||||
float mDuration;
|
||||
float mOriginalDuration; // for recording that this is originally a permanent glow if it is changed to a temporary one
|
||||
float mStartingTime;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
bool mColorChanged;
|
||||
bool mDone;
|
||||
};
|
||||
|
||||
struct Animation::AnimSource
|
||||
{
|
||||
osg::ref_ptr<const NifOsg::KeyframeHolder> mKeyframes;
|
||||
|
@ -1574,25 +1441,6 @@ namespace MWRender
|
|||
return mObjectRoot.get();
|
||||
}
|
||||
|
||||
class FindLowestUnusedTexUnitVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
FindLowestUnusedTexUnitVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mLowestUnusedTexUnit(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
if (osg::StateSet* stateset = node.getStateSet())
|
||||
mLowestUnusedTexUnit = std::max(mLowestUnusedTexUnit, int(stateset->getTextureAttributeList().size()));
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
int mLowestUnusedTexUnit;
|
||||
};
|
||||
|
||||
void Animation::addSpellCastGlow(const ESM::MagicEffect *effect, float glowDuration)
|
||||
{
|
||||
osg::Vec4f glowColor(1,1,1,1);
|
||||
|
@ -1611,53 +1459,10 @@ namespace MWRender
|
|||
mGlowUpdater->setDuration(glowDuration);
|
||||
}
|
||||
else
|
||||
addGlow(mObjectRoot, glowColor, glowDuration);
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(mObjectRoot, mResourceSystem, glowColor, glowDuration);
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor, float glowDuration)
|
||||
{
|
||||
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
||||
for (int i=0; i<32; ++i)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "textures/magicitem/caust";
|
||||
stream << std::setw(2);
|
||||
stream << std::setfill('0');
|
||||
stream << i;
|
||||
stream << ".dds";
|
||||
|
||||
osg::ref_ptr<osg::Image> image = mResourceSystem->getImageManager()->getImage(stream.str());
|
||||
osg::ref_ptr<osg::Texture2D> tex (new osg::Texture2D(image));
|
||||
tex->setName("envMap");
|
||||
tex->setWrap(osg::Texture::WRAP_S, osg::Texture2D::REPEAT);
|
||||
tex->setWrap(osg::Texture::WRAP_T, osg::Texture2D::REPEAT);
|
||||
mResourceSystem->getSceneManager()->applyFilterSettings(tex);
|
||||
textures.push_back(tex);
|
||||
}
|
||||
|
||||
FindLowestUnusedTexUnitVisitor findLowestUnusedTexUnitVisitor;
|
||||
node->accept(findLowestUnusedTexUnitVisitor);
|
||||
int texUnit = findLowestUnusedTexUnitVisitor.mLowestUnusedTexUnit;
|
||||
|
||||
osg::ref_ptr<GlowUpdater> glowUpdater = new GlowUpdater(texUnit, glowColor, textures, node, glowDuration, mResourceSystem);
|
||||
mGlowUpdater = glowUpdater;
|
||||
node->addUpdateCallback(glowUpdater);
|
||||
|
||||
// set a texture now so that the ShaderVisitor can find it
|
||||
osg::ref_ptr<osg::StateSet> writableStateSet = nullptr;
|
||||
if (!node->getStateSet())
|
||||
writableStateSet = node->getOrCreateStateSet();
|
||||
else
|
||||
{
|
||||
writableStateSet = new osg::StateSet(*node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
||||
node->setStateSet(writableStateSet);
|
||||
}
|
||||
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);
|
||||
writableStateSet->addUniform(new osg::Uniform("envMapColor", glowColor));
|
||||
mResourceSystem->getSceneManager()->recreateShaders(node);
|
||||
}
|
||||
|
||||
void Animation::addExtraLight(osg::ref_ptr<osg::Group> parent, const ESM::Light *esmLight)
|
||||
{
|
||||
bool exterior = mPtr.isInCell() && mPtr.getCell()->getCell()->isExterior();
|
||||
|
@ -1976,7 +1781,7 @@ namespace MWRender
|
|||
addAnimSource(model, model);
|
||||
|
||||
if (!ptr.getClass().getEnchantment(ptr).empty())
|
||||
addGlow(mObjectRoot, ptr.getClass().getEnchantmentColor(ptr));
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(mObjectRoot, mResourceSystem, ptr.getClass().getEnchantmentColor(ptr));
|
||||
}
|
||||
if (ptr.getTypeName() == typeid(ESM::Light).name() && allowLight)
|
||||
addExtraLight(getOrCreateObjectRoot(), ptr.get<ESM::Light>()->mBase);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
#include <components/sceneutil/controller.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -34,7 +35,6 @@ namespace MWRender
|
|||
|
||||
class ResetAccumRootCallback;
|
||||
class RotateController;
|
||||
class GlowUpdater;
|
||||
class TransparencyUpdater;
|
||||
|
||||
class EffectAnimationTime : public SceneUtil::ControllerSource
|
||||
|
@ -266,7 +266,7 @@ protected:
|
|||
bool mHasMagicEffects;
|
||||
|
||||
osg::ref_ptr<SceneUtil::LightSource> mGlowLight;
|
||||
osg::ref_ptr<GlowUpdater> mGlowUpdater;
|
||||
osg::ref_ptr<SceneUtil::GlowUpdater> mGlowUpdater;
|
||||
osg::ref_ptr<TransparencyUpdater> mTransparencyUpdater;
|
||||
|
||||
float mAlpha;
|
||||
|
@ -330,8 +330,6 @@ protected:
|
|||
*/
|
||||
virtual void addControllers();
|
||||
|
||||
void addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor, float glowDuration = -1);
|
||||
|
||||
/// Set the render bin for this animation's object root. May be customized by subclasses.
|
||||
virtual void setRenderBin();
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ void CreatureWeaponAnimation::updatePart(PartHolderPtr& scene, int slot)
|
|||
scene.reset(new PartHolder(attached));
|
||||
|
||||
if (!item.getClass().getEnchantment(item).empty())
|
||||
addGlow(attached, item.getClass().getEnchantmentColor(item));
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(attached, mResourceSystem, item.getClass().getEnchantmentColor(item));
|
||||
|
||||
// Crossbows start out with a bolt attached
|
||||
// FIXME: code duplicated from NpcAnimation
|
||||
|
@ -180,7 +180,7 @@ void CreatureWeaponAnimation::attachArrow()
|
|||
{
|
||||
osg::Group* bone = getArrowBone();
|
||||
if (bone != nullptr && bone->getNumChildren())
|
||||
addGlow(bone->getChild(0), ammo->getClass().getEnchantmentColor(*ammo));
|
||||
SceneUtil::addEnchantedGlow(bone->getChild(0), mResourceSystem, ammo->getClass().getEnchantmentColor(*ammo));
|
||||
}
|
||||
|
||||
updateQuiver();
|
||||
|
|
|
@ -664,7 +664,7 @@ PartHolderPtr NpcAnimation::insertBoundedPart(const std::string& model, const st
|
|||
|
||||
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, found->second);
|
||||
if (enchantedGlow)
|
||||
addGlow(attached, *glowColor);
|
||||
mGlowUpdater = SceneUtil::addEnchantedGlow(attached, mResourceSystem, *glowColor);
|
||||
|
||||
return PartHolderPtr(new PartHolder(attached));
|
||||
}
|
||||
|
@ -954,7 +954,7 @@ void NpcAnimation::attachArrow()
|
|||
{
|
||||
osg::Group* bone = getArrowBone();
|
||||
if (bone != nullptr && bone->getNumChildren())
|
||||
addGlow(bone->getChild(0), ammo->getClass().getEnchantmentColor(*ammo));
|
||||
SceneUtil::addEnchantedGlow(bone->getChild(0), mResourceSystem, ammo->getClass().getEnchantmentColor(*ammo));
|
||||
}
|
||||
|
||||
updateQuiver();
|
||||
|
|
|
@ -323,6 +323,8 @@ namespace MWWorld
|
|||
MWWorld::Ptr ptr = ref.getPtr();
|
||||
|
||||
createModel(state, ptr.getClass().getModel(ptr), pos, orient, false, false, osg::Vec4(0,0,0,0));
|
||||
if (!ptr.getClass().getEnchantment(ptr).empty())
|
||||
SceneUtil::addEnchantedGlow(state.mNode, mResourceSystem, ptr.getClass().getEnchantmentColor(ptr));
|
||||
|
||||
mProjectiles.push_back(state);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,151 @@
|
|||
#include "util.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
#include <osg/Node>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/TexGen>
|
||||
#include <osg/TexEnvCombine>
|
||||
|
||||
#include <components/resource/imagemanager.hpp>
|
||||
#include <components/resource/scenemanager.hpp>
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
|
||||
class FindLowestUnusedTexUnitVisitor : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
FindLowestUnusedTexUnitVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mLowestUnusedTexUnit(0)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void apply(osg::Node& node)
|
||||
{
|
||||
if (osg::StateSet* stateset = node.getStateSet())
|
||||
mLowestUnusedTexUnit = std::max(mLowestUnusedTexUnit, int(stateset->getTextureAttributeList().size()));
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
int mLowestUnusedTexUnit;
|
||||
};
|
||||
|
||||
GlowUpdater::GlowUpdater(int texUnit, const osg::Vec4f& color, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures,
|
||||
osg::Node* node, float duration, Resource::ResourceSystem* resourcesystem)
|
||||
: mTexUnit(texUnit)
|
||||
, mColor(color)
|
||||
, mOriginalColor(color)
|
||||
, mTextures(textures)
|
||||
, mNode(node)
|
||||
, mDuration(duration)
|
||||
, mOriginalDuration(duration)
|
||||
, mStartingTime(0)
|
||||
, mResourceSystem(resourcesystem)
|
||||
, mColorChanged(false)
|
||||
, mDone(false)
|
||||
{
|
||||
}
|
||||
|
||||
void GlowUpdater::setDefaults(osg::StateSet *stateset)
|
||||
{
|
||||
if (mDone)
|
||||
removeTexture(stateset);
|
||||
else
|
||||
{
|
||||
stateset->setTextureMode(mTexUnit, GL_TEXTURE_2D, osg::StateAttribute::ON);
|
||||
osg::TexGen* texGen = new osg::TexGen;
|
||||
texGen->setMode(osg::TexGen::SPHERE_MAP);
|
||||
|
||||
stateset->setTextureAttributeAndModes(mTexUnit, texGen, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
|
||||
osg::TexEnvCombine* texEnv = new osg::TexEnvCombine;
|
||||
texEnv->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
|
||||
texEnv->setConstantColor(mColor);
|
||||
texEnv->setCombine_RGB(osg::TexEnvCombine::INTERPOLATE);
|
||||
texEnv->setSource2_RGB(osg::TexEnvCombine::TEXTURE);
|
||||
texEnv->setOperand2_RGB(osg::TexEnvCombine::SRC_COLOR);
|
||||
|
||||
stateset->setTextureAttributeAndModes(mTexUnit, texEnv, osg::StateAttribute::ON);
|
||||
stateset->addUniform(new osg::Uniform("envMapColor", mColor));
|
||||
}
|
||||
}
|
||||
|
||||
void GlowUpdater::removeTexture(osg::StateSet* stateset)
|
||||
{
|
||||
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXTURE);
|
||||
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXGEN);
|
||||
stateset->removeTextureAttribute(mTexUnit, osg::StateAttribute::TEXENV);
|
||||
stateset->removeTextureMode(mTexUnit, GL_TEXTURE_2D);
|
||||
stateset->removeUniform("envMapColor");
|
||||
|
||||
osg::StateSet::TextureAttributeList& list = stateset->getTextureAttributeList();
|
||||
while (list.size() && list.rbegin()->empty())
|
||||
list.pop_back();
|
||||
}
|
||||
|
||||
void GlowUpdater::apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||
{
|
||||
if (mColorChanged){
|
||||
this->reset();
|
||||
setDefaults(stateset);
|
||||
mColorChanged = false;
|
||||
}
|
||||
if (mDone)
|
||||
return;
|
||||
|
||||
// Set the starting time to measure glow duration from if this is a temporary glow
|
||||
if ((mDuration >= 0) && mStartingTime == 0)
|
||||
mStartingTime = nv->getFrameStamp()->getSimulationTime();
|
||||
|
||||
float time = nv->getFrameStamp()->getSimulationTime();
|
||||
int index = (int)(time*16) % mTextures.size();
|
||||
stateset->setTextureAttribute(mTexUnit, mTextures[index], osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
|
||||
if ((mDuration >= 0) && (time - mStartingTime > mDuration)) // If this is a temporary glow and it has finished its duration
|
||||
{
|
||||
if (mOriginalDuration >= 0) // if this glowupdater was a temporary glow since its creation
|
||||
{
|
||||
removeTexture(stateset);
|
||||
this->reset();
|
||||
mDone = true;
|
||||
mResourceSystem->getSceneManager()->recreateShaders(mNode);
|
||||
}
|
||||
if (mOriginalDuration < 0) // if this glowupdater was originally a permanent glow
|
||||
{
|
||||
mDuration = mOriginalDuration;
|
||||
mStartingTime = 0;
|
||||
mColor = mOriginalColor;
|
||||
this->reset();
|
||||
setDefaults(stateset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GlowUpdater::isPermanentGlowUpdater()
|
||||
{
|
||||
return (mDuration < 0);
|
||||
}
|
||||
|
||||
bool GlowUpdater::isDone()
|
||||
{
|
||||
return mDone;
|
||||
}
|
||||
|
||||
void GlowUpdater::setColor(const osg::Vec4f& color)
|
||||
{
|
||||
mColor = color;
|
||||
mColorChanged = true;
|
||||
}
|
||||
|
||||
void GlowUpdater::setDuration(float duration)
|
||||
{
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
void transformBoundingSphere (const osg::Matrixf& matrix, osg::BoundingSphere& bsphere)
|
||||
{
|
||||
osg::BoundingSphere::vec_type xdash = bsphere._center;
|
||||
|
@ -73,4 +214,48 @@ bool hasUserDescription(const osg::Node* node, const std::string pattern)
|
|||
return false;
|
||||
}
|
||||
|
||||
osg::ref_ptr<GlowUpdater> addEnchantedGlow(osg::ref_ptr<osg::Node> node, Resource::ResourceSystem* resourceSystem, osg::Vec4f glowColor, float glowDuration)
|
||||
{
|
||||
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
||||
for (int i=0; i<32; ++i)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "textures/magicitem/caust";
|
||||
stream << std::setw(2);
|
||||
stream << std::setfill('0');
|
||||
stream << i;
|
||||
stream << ".dds";
|
||||
|
||||
osg::ref_ptr<osg::Image> image = resourceSystem->getImageManager()->getImage(stream.str());
|
||||
osg::ref_ptr<osg::Texture2D> tex (new osg::Texture2D(image));
|
||||
tex->setName("envMap");
|
||||
tex->setWrap(osg::Texture::WRAP_S, osg::Texture2D::REPEAT);
|
||||
tex->setWrap(osg::Texture::WRAP_T, osg::Texture2D::REPEAT);
|
||||
resourceSystem->getSceneManager()->applyFilterSettings(tex);
|
||||
textures.push_back(tex);
|
||||
}
|
||||
|
||||
FindLowestUnusedTexUnitVisitor findLowestUnusedTexUnitVisitor;
|
||||
node->accept(findLowestUnusedTexUnitVisitor);
|
||||
int texUnit = findLowestUnusedTexUnitVisitor.mLowestUnusedTexUnit;
|
||||
|
||||
osg::ref_ptr<GlowUpdater> glowUpdater = new GlowUpdater(texUnit, glowColor, textures, node, glowDuration, resourceSystem);
|
||||
node->addUpdateCallback(glowUpdater);
|
||||
|
||||
// set a texture now so that the ShaderVisitor can find it
|
||||
osg::ref_ptr<osg::StateSet> writableStateSet = nullptr;
|
||||
if (!node->getStateSet())
|
||||
writableStateSet = node->getOrCreateStateSet();
|
||||
else
|
||||
{
|
||||
writableStateSet = new osg::StateSet(*node->getStateSet(), osg::CopyOp::SHALLOW_COPY);
|
||||
node->setStateSet(writableStateSet);
|
||||
}
|
||||
writableStateSet->setTextureAttributeAndModes(texUnit, textures.front(), osg::StateAttribute::ON);
|
||||
writableStateSet->addUniform(new osg::Uniform("envMapColor", glowColor));
|
||||
resourceSystem->getSceneManager()->recreateShaders(node);
|
||||
|
||||
return glowUpdater;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,10 +3,48 @@
|
|||
|
||||
#include <osg/Matrix>
|
||||
#include <osg/BoundingSphere>
|
||||
#include <osg/NodeCallback>
|
||||
#include <osg/Texture2D>
|
||||
#include <osg/Vec4f>
|
||||
|
||||
#include <components/resource/resourcesystem.hpp>
|
||||
|
||||
#include "statesetupdater.hpp"
|
||||
|
||||
namespace SceneUtil
|
||||
{
|
||||
class GlowUpdater : public SceneUtil::StateSetUpdater
|
||||
{
|
||||
public:
|
||||
GlowUpdater(int texUnit, const osg::Vec4f& color, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures,
|
||||
osg::Node* node, float duration, Resource::ResourceSystem* resourcesystem);
|
||||
|
||||
virtual void setDefaults(osg::StateSet *stateset);
|
||||
|
||||
void removeTexture(osg::StateSet* stateset);
|
||||
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv);
|
||||
|
||||
bool isPermanentGlowUpdater();
|
||||
|
||||
bool isDone();
|
||||
|
||||
void setColor(const osg::Vec4f& color);
|
||||
|
||||
void setDuration(float duration);
|
||||
|
||||
private:
|
||||
int mTexUnit;
|
||||
osg::Vec4f mColor;
|
||||
osg::Vec4f mOriginalColor; // for restoring the color of a permanent glow after a temporary glow on the object finishes
|
||||
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
|
||||
osg::Node* mNode;
|
||||
float mDuration;
|
||||
float mOriginalDuration; // for recording that this is originally a permanent glow if it is changed to a temporary one
|
||||
float mStartingTime;
|
||||
Resource::ResourceSystem* mResourceSystem;
|
||||
bool mColorChanged;
|
||||
bool mDone;
|
||||
};
|
||||
|
||||
// Transform a bounding sphere by a matrix
|
||||
// based off private code in osg::Transform
|
||||
|
@ -20,6 +58,8 @@ namespace SceneUtil
|
|||
float makeOsgColorComponent (unsigned int value, unsigned int shift);
|
||||
|
||||
bool hasUserDescription(const osg::Node* node, const std::string pattern);
|
||||
|
||||
osg::ref_ptr<GlowUpdater> addEnchantedGlow(osg::ref_ptr<osg::Node> node, Resource::ResourceSystem* resourceSystem, osg::Vec4f glowColor, float glowDuration=-1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue