From 083c41c9503ecf4d75e0a3fd2b02c483c29a4bae Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 17 Apr 2015 01:23:37 +0200 Subject: [PATCH] Environment map for enchanted objects --- apps/openmw/engine.cpp | 1 - apps/openmw/mwrender/animation.cpp | 98 +++++++++++++++++++++++++- apps/openmw/mwrender/animation.hpp | 4 ++ apps/openmw/mwrender/npcanimation.cpp | 52 +++----------- apps/openmw/mwrender/npcanimation.hpp | 6 +- apps/openmw/mwrender/objects.cpp | 4 +- components/resource/resourcesystem.cpp | 5 ++ components/resource/resourcesystem.hpp | 1 + 8 files changed, 123 insertions(+), 48 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index f6f2ba9bb7..9a7f023e67 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -491,7 +491,6 @@ void OMW::Engine::go() mViewer.setCameraManipulator(new osgGA::TrackballManipulator); mViewer.addEventHandler(new osgViewer::StatsHandler); - osg::Timer timer; mViewer.realize(); osg::Timer frameTimer; while (!mViewer.done()) diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index 4352520db6..3aeaa2ed1d 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1,11 +1,68 @@ #include "animation.hpp" +#include +#include +#include + #include #include #include +#include -#include +#include + +#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 >& 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 > mTextures; + }; + +} namespace MWRender { @@ -54,6 +111,42 @@ namespace MWRender return static_cast(mObjectRoot.get()); } + void Animation::addGlow(osg::ref_ptr node, osg::Vec4f glowColor) + { + std::vector > 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 (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().find(enchantmentName); + assert (enchantment->mEffects.mList.size()); + const ESM::MagicEffect* magicEffect = MWBase::Environment::get().getWorld()->getStore().get().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) @@ -62,6 +155,9 @@ namespace MWRender if (!model.empty()) { setObjectRoot(model); + + if (!ptr.getClass().getEnchantment(ptr).empty()) + addGlow(mObjectRoot, getEnchantmentColor(ptr)); } else { diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 34173c29cd..1feab7bf3a 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -172,6 +172,10 @@ protected: //void clearAnimSources(); + osg::Vec4f getEnchantmentColor(MWWorld::Ptr item); + + void addGlow(osg::ref_ptr node, osg::Vec4f glowColor); + public: Animation(const MWWorld::Ptr &ptr, osg::ref_ptr parentNode, Resource::ResourceSystem* resourceSystem); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index fe16fa06e0..e30c701fcf 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -328,8 +328,8 @@ void NpcAnimation::updateNpcBase() void NpcAnimation::updateParts() { - //if (!mSkelBase) - // return; + if (!mObjectRoot.get()) + return; mAlpha = 1.f; const MWWorld::Class &cls = mPtr.getClass(); @@ -386,8 +386,7 @@ void NpcAnimation::updateParts() int prio = 1; bool enchantedGlow = !store->getClass().getEnchantment(*store).empty(); - //Ogre::Vector3 glowColor = getEnchantmentColor(*store); - Ogre::Vector3 glowColor (1,1,1); + osg::Vec4f glowColor = getEnchantmentColor(*store); if(store->getTypeName() == typeid(ESM::Clothing).name()) { 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 instance = mResourceSystem->getSceneManager()->createInstance(model); -std::cout << "inserting " << model << std::endl; osg::ref_ptr attached = SceneUtil::attach(instance, mObjectRoot, bonefilter, bonename); + if (enchantedGlow) + addGlow(attached, *glowColor); 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) { @@ -684,7 +654,7 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) mPartPriorities[type] = 0; mPartslots[type] = -1; - //mObjectParts[type].setNull(); + mObjectParts[type].reset(); if (!mSoundIds[type].empty() && !mSoundsDisabled) { 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]) return false; @@ -804,7 +774,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g return true; } -void NpcAnimation::addPartGroup(int group, int priority, const std::vector &parts, bool enchantedGlow, Ogre::Vector3* glowColor) +void NpcAnimation::addPartGroup(int group, int priority, const std::vector &parts, bool enchantedGlow, osg::Vec4f* glowColor) { const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const MWWorld::Store &partStore = store.get(); @@ -861,7 +831,7 @@ void NpcAnimation::showWeapons(bool showWeapon) MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); if(weapon != inv.end()) { - Ogre::Vector3 glowColor (1,1,1); //= getEnchantmentColor(*weapon); + osg::Vec4f glowColor = getEnchantmentColor(*weapon); std::string mesh = weapon->getClass().getModel(*weapon); addOrReplaceIndividualPart(ESM::PRT_Weapon, MWWorld::InventoryStore::Slot_CarriedRight, 1, 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); 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); if (addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor)) diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 28ac6509b8..2605d58e3b 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -128,16 +128,16 @@ private: void updateNpcBase(); 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 reserveIndividualPart(ESM::PartReferenceType type, int group, int priority); 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 addPartGroup(int group, int priority, const std::vector &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); diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 322d02e94c..21d7c1ab59 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -166,10 +166,10 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh, bool osg::Light* light = new osg::Light; lightSource->setLight(light); - float realRadius = esmLight->mData.mRadius * 2; + float realRadius = esmLight->mData.mRadius; lightSource->setRadius(realRadius); - light->setLinearAttenuation(10.f/realRadius); + light->setLinearAttenuation(10.f/(esmLight->mData.mRadius*2.f)); //light->setLinearAttenuation(0.05); light->setConstantAttenuation(0.f); diff --git a/components/resource/resourcesystem.cpp b/components/resource/resourcesystem.cpp index 215b1a67c8..acde8f5d2d 100644 --- a/components/resource/resourcesystem.cpp +++ b/components/resource/resourcesystem.cpp @@ -18,6 +18,11 @@ namespace Resource return mSceneManager.get(); } + TextureManager* ResourceSystem::getTextureManager() + { + return mTextureManager.get(); + } + const VFS::Manager* ResourceSystem::getVFS() const { return mVFS; diff --git a/components/resource/resourcesystem.hpp b/components/resource/resourcesystem.hpp index a91f3cab3d..3bb4547854 100644 --- a/components/resource/resourcesystem.hpp +++ b/components/resource/resourcesystem.hpp @@ -23,6 +23,7 @@ namespace Resource ResourceSystem(const VFS::Manager* vfs); SceneManager* getSceneManager(); + TextureManager* getTextureManager(); const VFS::Manager* getVFS() const;