mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-10 21:40:15 +00:00
Environment map for enchanted objects
This commit is contained in:
parent
8f6d4fb3e0
commit
083c41c950
@ -491,7 +491,6 @@ void OMW::Engine::go()
|
|||||||
mViewer.setCameraManipulator(new osgGA::TrackballManipulator);
|
mViewer.setCameraManipulator(new osgGA::TrackballManipulator);
|
||||||
mViewer.addEventHandler(new osgViewer::StatsHandler);
|
mViewer.addEventHandler(new osgViewer::StatsHandler);
|
||||||
|
|
||||||
osg::Timer timer;
|
|
||||||
mViewer.realize();
|
mViewer.realize();
|
||||||
osg::Timer frameTimer;
|
osg::Timer frameTimer;
|
||||||
while (!mViewer.done())
|
while (!mViewer.done())
|
||||||
|
@ -1,11 +1,68 @@
|
|||||||
#include "animation.hpp"
|
#include "animation.hpp"
|
||||||
|
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
#include <osg/TexGen>
|
||||||
|
#include <osg/TexEnvCombine>
|
||||||
|
|
||||||
#include <components/nifosg/nifloader.hpp>
|
#include <components/nifosg/nifloader.hpp>
|
||||||
|
|
||||||
#include <components/resource/resourcesystem.hpp>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <components/resource/scenemanager.hpp>
|
#include <components/resource/scenemanager.hpp>
|
||||||
|
#include <components/resource/texturemanager.hpp>
|
||||||
|
|
||||||
#include <osg/PositionAttitudeTransform>
|
#include <components/sceneutil/statesetupdater.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
class GlowUpdater : public SceneUtil::StateSetUpdater
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GlowUpdater(osg::Vec4f color, const std::vector<osg::ref_ptr<osg::Texture2D> >& textures)
|
||||||
|
: mTexUnit(1) // FIXME: might not always be 1
|
||||||
|
, mColor(color)
|
||||||
|
, mTextures(textures)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setDefaults(osg::StateSet *stateset)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor *nv)
|
||||||
|
{
|
||||||
|
float time = nv->getFrameStamp()->getSimulationTime();
|
||||||
|
int index = (int)(time*16) % mTextures.size();
|
||||||
|
stateset->setTextureAttribute(mTexUnit, mTextures[index], osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mTexUnit;
|
||||||
|
osg::Vec4f mColor;
|
||||||
|
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
@ -54,6 +111,42 @@ namespace MWRender
|
|||||||
return static_cast<osg::Group*>(mObjectRoot.get());
|
return static_cast<osg::Group*>(mObjectRoot.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Animation::addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor)
|
||||||
|
{
|
||||||
|
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";
|
||||||
|
|
||||||
|
textures.push_back(mResourceSystem->getTextureManager()->getTexture2D(stream.str(), osg::Texture2D::REPEAT, osg::Texture2D::REPEAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<GlowUpdater> glowupdater (new GlowUpdater(glowColor, textures));
|
||||||
|
node->addUpdateCallback(glowupdater);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Should not be here
|
||||||
|
osg::Vec4f Animation::getEnchantmentColor(MWWorld::Ptr item)
|
||||||
|
{
|
||||||
|
osg::Vec4f result(1,1,1,1);
|
||||||
|
std::string enchantmentName = item.getClass().getEnchantment(item);
|
||||||
|
if (enchantmentName.empty())
|
||||||
|
return result;
|
||||||
|
const ESM::Enchantment* enchantment = MWBase::Environment::get().getWorld()->getStore().get<ESM::Enchantment>().find(enchantmentName);
|
||||||
|
assert (enchantment->mEffects.mList.size());
|
||||||
|
const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get<ESM::MagicEffect>().find(
|
||||||
|
enchantment->mEffects.mList.front().mEffectID);
|
||||||
|
result.x() = magicEffect->mData.mRed / 255.f;
|
||||||
|
result.y() = magicEffect->mData.mGreen / 255.f;
|
||||||
|
result.z() = magicEffect->mData.mBlue / 255.f;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------
|
||||||
|
|
||||||
ObjectAnimation::ObjectAnimation(const MWWorld::Ptr &ptr, const std::string &model, Resource::ResourceSystem* resourceSystem)
|
ObjectAnimation::ObjectAnimation(const MWWorld::Ptr &ptr, const std::string &model, Resource::ResourceSystem* resourceSystem)
|
||||||
@ -62,6 +155,9 @@ namespace MWRender
|
|||||||
if (!model.empty())
|
if (!model.empty())
|
||||||
{
|
{
|
||||||
setObjectRoot(model);
|
setObjectRoot(model);
|
||||||
|
|
||||||
|
if (!ptr.getClass().getEnchantment(ptr).empty())
|
||||||
|
addGlow(mObjectRoot, getEnchantmentColor(ptr));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -172,6 +172,10 @@ protected:
|
|||||||
|
|
||||||
//void clearAnimSources();
|
//void clearAnimSources();
|
||||||
|
|
||||||
|
osg::Vec4f getEnchantmentColor(MWWorld::Ptr item);
|
||||||
|
|
||||||
|
void addGlow(osg::ref_ptr<osg::Node> node, osg::Vec4f glowColor);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Animation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem);
|
Animation(const MWWorld::Ptr &ptr, osg::ref_ptr<osg::Group> parentNode, Resource::ResourceSystem* resourceSystem);
|
||||||
|
@ -328,8 +328,8 @@ void NpcAnimation::updateNpcBase()
|
|||||||
|
|
||||||
void NpcAnimation::updateParts()
|
void NpcAnimation::updateParts()
|
||||||
{
|
{
|
||||||
//if (!mSkelBase)
|
if (!mObjectRoot.get())
|
||||||
// return;
|
return;
|
||||||
|
|
||||||
mAlpha = 1.f;
|
mAlpha = 1.f;
|
||||||
const MWWorld::Class &cls = mPtr.getClass();
|
const MWWorld::Class &cls = mPtr.getClass();
|
||||||
@ -386,8 +386,7 @@ void NpcAnimation::updateParts()
|
|||||||
|
|
||||||
int prio = 1;
|
int prio = 1;
|
||||||
bool enchantedGlow = !store->getClass().getEnchantment(*store).empty();
|
bool enchantedGlow = !store->getClass().getEnchantment(*store).empty();
|
||||||
//Ogre::Vector3 glowColor = getEnchantmentColor(*store);
|
osg::Vec4f glowColor = getEnchantmentColor(*store);
|
||||||
Ogre::Vector3 glowColor (1,1,1);
|
|
||||||
if(store->getTypeName() == typeid(ESM::Clothing).name())
|
if(store->getTypeName() == typeid(ESM::Clothing).name())
|
||||||
{
|
{
|
||||||
prio = ((slotlist[i].mBasePriority+1)<<1) + 0;
|
prio = ((slotlist[i].mBasePriority+1)<<1) + 0;
|
||||||
@ -588,44 +587,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PartHolderPtr NpcAnimation::insertBoundedPart(const std::string& model, int group, const std::string& bonename, const std::string& bonefilter, bool enchantedGlow, Ogre::Vector3* glowColor)
|
PartHolderPtr NpcAnimation::insertBoundedPart(const std::string& model, int group, const std::string& bonename, const std::string& bonefilter, bool enchantedGlow, osg::Vec4f* glowColor)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Node> instance = mResourceSystem->getSceneManager()->createInstance(model);
|
osg::ref_ptr<osg::Node> instance = mResourceSystem->getSceneManager()->createInstance(model);
|
||||||
std::cout << "inserting " << model << std::endl;
|
|
||||||
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, bonename);
|
osg::ref_ptr<osg::Node> attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, bonename);
|
||||||
|
if (enchantedGlow)
|
||||||
|
addGlow(attached, *glowColor);
|
||||||
return PartHolderPtr(new PartHolder(attached));
|
return PartHolderPtr(new PartHolder(attached));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
NifOgre::ObjectScenePtr NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename, const std::string &bonefilter, bool enchantedGlow, Ogre::Vector3* glowColor)
|
|
||||||
{
|
|
||||||
NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(mSkelBase, bonename, bonefilter, mInsert, model);
|
|
||||||
setRenderProperties(objects, (mViewMode == VM_FirstPerson) ? RV_FirstPerson : mVisibilityFlags, RQG_Main, RQG_Alpha, 0,
|
|
||||||
enchantedGlow, glowColor);
|
|
||||||
|
|
||||||
std::for_each(objects->mEntities.begin(), objects->mEntities.end(), SetObjectGroup(group));
|
|
||||||
std::for_each(objects->mParticles.begin(), objects->mParticles.end(), SetObjectGroup(group));
|
|
||||||
|
|
||||||
if(objects->mSkelBase)
|
|
||||||
{
|
|
||||||
Ogre::AnimationStateSet *aset = objects->mSkelBase->getAllAnimationStates();
|
|
||||||
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
|
|
||||||
while(asiter.hasMoreElements())
|
|
||||||
{
|
|
||||||
Ogre::AnimationState *state = asiter.getNext();
|
|
||||||
state->setEnabled(false);
|
|
||||||
state->setLoop(false);
|
|
||||||
}
|
|
||||||
Ogre::SkeletonInstance *skelinst = objects->mSkelBase->getSkeleton();
|
|
||||||
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
|
|
||||||
while(boneiter.hasMoreElements())
|
|
||||||
boneiter.getNext()->setManuallyControlled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return objects;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
|
Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
|
||||||
{
|
{
|
||||||
@ -684,7 +654,7 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type)
|
|||||||
mPartPriorities[type] = 0;
|
mPartPriorities[type] = 0;
|
||||||
mPartslots[type] = -1;
|
mPartslots[type] = -1;
|
||||||
|
|
||||||
//mObjectParts[type].setNull();
|
mObjectParts[type].reset();
|
||||||
if (!mSoundIds[type].empty() && !mSoundsDisabled)
|
if (!mSoundIds[type].empty() && !mSoundsDisabled)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mSoundIds[type]);
|
MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mSoundIds[type]);
|
||||||
@ -711,7 +681,7 @@ void NpcAnimation::removePartGroup(int group)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh, bool enchantedGlow, Ogre::Vector3* glowColor)
|
bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh, bool enchantedGlow, osg::Vec4f* glowColor)
|
||||||
{
|
{
|
||||||
if(priority <= mPartPriorities[type])
|
if(priority <= mPartPriorities[type])
|
||||||
return false;
|
return false;
|
||||||
@ -804,7 +774,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts, bool enchantedGlow, Ogre::Vector3* glowColor)
|
void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts, bool enchantedGlow, osg::Vec4f* glowColor)
|
||||||
{
|
{
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
const MWWorld::Store<ESM::BodyPart> &partStore = store.get<ESM::BodyPart>();
|
||||||
@ -861,7 +831,7 @@ void NpcAnimation::showWeapons(bool showWeapon)
|
|||||||
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
if(weapon != inv.end())
|
if(weapon != inv.end())
|
||||||
{
|
{
|
||||||
Ogre::Vector3 glowColor (1,1,1); //= getEnchantmentColor(*weapon);
|
osg::Vec4f glowColor = getEnchantmentColor(*weapon);
|
||||||
std::string mesh = weapon->getClass().getModel(*weapon);
|
std::string mesh = weapon->getClass().getModel(*weapon);
|
||||||
addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1,
|
addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1,
|
||||||
mesh, !weapon->getClass().getEnchantment(*weapon).empty(), &glowColor);
|
mesh, !weapon->getClass().getEnchantment(*weapon).empty(), &glowColor);
|
||||||
@ -894,7 +864,7 @@ void NpcAnimation::showCarriedLeft(bool show)
|
|||||||
MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft);
|
||||||
if(show && iter != inv.end())
|
if(show && iter != inv.end())
|
||||||
{
|
{
|
||||||
Ogre::Vector3 glowColor(1,1,1);// = getEnchantmentColor(*iter);
|
osg::Vec4f glowColor = getEnchantmentColor(*iter);
|
||||||
std::string mesh = iter->getClass().getModel(*iter);
|
std::string mesh = iter->getClass().getModel(*iter);
|
||||||
if (addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
if (addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1,
|
||||||
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor))
|
mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor))
|
||||||
|
@ -128,16 +128,16 @@ private:
|
|||||||
void updateNpcBase();
|
void updateNpcBase();
|
||||||
|
|
||||||
PartHolderPtr insertBoundedPart(const std::string &model, int group, const std::string &bonename,
|
PartHolderPtr insertBoundedPart(const std::string &model, int group, const std::string &bonename,
|
||||||
const std::string &bonefilter, bool enchantedGlow, Ogre::Vector3* glowColor=NULL);
|
const std::string &bonefilter, bool enchantedGlow, osg::Vec4f* glowColor=NULL);
|
||||||
|
|
||||||
void removeIndividualPart(ESM::PartReferenceType type);
|
void removeIndividualPart(ESM::PartReferenceType type);
|
||||||
void reserveIndividualPart(ESM::PartReferenceType type, int group, int priority);
|
void reserveIndividualPart(ESM::PartReferenceType type, int group, int priority);
|
||||||
|
|
||||||
bool addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh,
|
bool addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh,
|
||||||
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
|
bool enchantedGlow=false, osg::Vec4f* glowColor=NULL);
|
||||||
void removePartGroup(int group);
|
void removePartGroup(int group);
|
||||||
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
|
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
|
||||||
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
|
bool enchantedGlow=false, osg::Vec4f* glowColor=NULL);
|
||||||
|
|
||||||
//void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene);
|
//void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene);
|
||||||
|
|
||||||
|
@ -166,10 +166,10 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool
|
|||||||
osg::Light* light = new osg::Light;
|
osg::Light* light = new osg::Light;
|
||||||
lightSource->setLight(light);
|
lightSource->setLight(light);
|
||||||
|
|
||||||
float realRadius = esmLight->mData.mRadius * 2;
|
float realRadius = esmLight->mData.mRadius;
|
||||||
|
|
||||||
lightSource->setRadius(realRadius);
|
lightSource->setRadius(realRadius);
|
||||||
light->setLinearAttenuation(10.f/realRadius);
|
light->setLinearAttenuation(10.f/(esmLight->mData.mRadius*2.f));
|
||||||
//light->setLinearAttenuation(0.05);
|
//light->setLinearAttenuation(0.05);
|
||||||
light->setConstantAttenuation(0.f);
|
light->setConstantAttenuation(0.f);
|
||||||
|
|
||||||
|
@ -18,6 +18,11 @@ namespace Resource
|
|||||||
return mSceneManager.get();
|
return mSceneManager.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextureManager* ResourceSystem::getTextureManager()
|
||||||
|
{
|
||||||
|
return mTextureManager.get();
|
||||||
|
}
|
||||||
|
|
||||||
const VFS::Manager* ResourceSystem::getVFS() const
|
const VFS::Manager* ResourceSystem::getVFS() const
|
||||||
{
|
{
|
||||||
return mVFS;
|
return mVFS;
|
||||||
|
@ -23,6 +23,7 @@ namespace Resource
|
|||||||
ResourceSystem(const VFS::Manager* vfs);
|
ResourceSystem(const VFS::Manager* vfs);
|
||||||
|
|
||||||
SceneManager* getSceneManager();
|
SceneManager* getSceneManager();
|
||||||
|
TextureManager* getTextureManager();
|
||||||
|
|
||||||
const VFS::Manager* getVFS() const;
|
const VFS::Manager* getVFS() const;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user