Merge remote-tracking branch 'scrawl/master'

actorid
Marc Zinnschlag 11 years ago
commit 77a2179d1e

@ -517,6 +517,8 @@ void OMW::Engine::activate()
std::string script = MWWorld::Class::get (ptr).getScript (ptr);
MWBase::Environment::get().getWorld()->breakInvisibility(MWBase::Environment::get().getWorld()->getPlayer().getPlayer());
if (!script.empty())
{
MWBase::Environment::get().getWorld()->getLocalScripts().setIgnore (ptr);

@ -419,6 +419,8 @@ namespace MWBase
virtual void launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& actor, const std::string& sourceName) = 0;
virtual void breakInvisibility (const MWWorld::Ptr& actor) = 0;
};
}

@ -149,7 +149,7 @@ namespace MWGui
// health, magicka, fatigue tooltip
MyGUI::Widget* w;
std::string valStr = boost::lexical_cast<std::string>(value.getCurrent()) + "/" + boost::lexical_cast<std::string>(value.getModified());
std::string valStr = boost::lexical_cast<std::string>(int(value.getCurrent())) + "/" + boost::lexical_cast<std::string>(int(value.getModified()));
if (i==0)
{
getWidget(w, "Health");

@ -501,6 +501,7 @@ bool CharacterController::updateNpcState(bool onground, bool inwater, bool isrun
{
if(mUpperBodyState == UpperCharState_WeapEquiped)
{
MWBase::Environment::get().getWorld()->breakInvisibility(mPtr);
mAttackType.clear();
if(mWeaponType == WeapType_Spell)
{
@ -727,6 +728,8 @@ void CharacterController::update(float duration)
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
Ogre::Vector3 movement(0.0f);
updateVisibility();
if(!cls.isActor())
{
if(mAnimQueue.size() > 1)
@ -1130,4 +1133,25 @@ void CharacterController::updateContinuousVfx()
}
}
void CharacterController::updateVisibility()
{
if (!mPtr.getClass().isActor())
return;
float alpha = 1.f;
if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude)
{
if (mPtr.getRefData().getHandle() == "player")
alpha = 0.4f;
else
alpha = 0.f;
}
float chameleon = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude;
if (chameleon)
{
alpha *= std::max(0.2f, (100.f - chameleon)/100.f);
}
mAnimation->setAlpha(alpha);
}
}

@ -173,6 +173,8 @@ class CharacterController
bool updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak);
void updateVisibility();
public:
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
virtual ~CharacterController();

@ -51,28 +51,6 @@ void Animation::EffectAnimationValue::setValue(Ogre::Real)
{
}
void Animation::destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects)
{
for(size_t i = 0;i < objects.mLights.size();i++)
{
Ogre::Light *light = objects.mLights[i];
// If parent is a scene node, it was created specifically for this light. Destroy it now.
if(light->isAttached() && !light->isParentTagPoint())
sceneMgr->destroySceneNode(light->getParentSceneNode());
sceneMgr->destroyLight(light);
}
for(size_t i = 0;i < objects.mParticles.size();i++)
sceneMgr->destroyParticleSystem(objects.mParticles[i]);
for(size_t i = 0;i < objects.mEntities.size();i++)
sceneMgr->destroyEntity(objects.mEntities[i]);
objects.mControllers.clear();
objects.mLights.clear();
objects.mParticles.clear();
objects.mEntities.clear();
objects.mSkelBase = NULL;
}
Animation::Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node)
: mPtr(ptr)
, mCamera(NULL)
@ -90,13 +68,9 @@ Animation::Animation(const MWWorld::Ptr &ptr, Ogre::SceneNode *node)
Animation::~Animation()
{
for (std::vector<EffectParams>::iterator it = mEffects.begin(); it != mEffects.end(); ++it)
destroyObjectList(mInsert->getCreator(), it->mObjects);
mEffects.clear();
mAnimSources.clear();
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
destroyObjectList(sceneMgr, mObjectRoot);
}
@ -105,7 +79,7 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
OgreAssert(mAnimSources.empty(), "Setting object root while animation sources are set!");
mSkelBase = NULL;
destroyObjectList(mInsert->getCreator(), mObjectRoot);
mObjectRoot.setNull();
if(model.empty())
return;
@ -126,11 +100,11 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
mObjectRoot = (!baseonly ? NifOgre::Loader::createObjects(mInsert, mdlname) :
NifOgre::Loader::createObjectBase(mInsert, mdlname));
if(mObjectRoot.mSkelBase)
if(mObjectRoot->mSkelBase)
{
mSkelBase = mObjectRoot.mSkelBase;
mSkelBase = mObjectRoot->mSkelBase;
Ogre::AnimationStateSet *aset = mObjectRoot.mSkelBase->getAllAnimationStates();
Ogre::AnimationStateSet *aset = mObjectRoot->mSkelBase->getAllAnimationStates();
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
while(asiter.hasMoreElements())
{
@ -141,7 +115,7 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
// Set the bones as manually controlled since we're applying the
// transformations manually
Ogre::SkeletonInstance *skelinst = mObjectRoot.mSkelBase->getSkeleton();
Ogre::SkeletonInstance *skelinst = mObjectRoot->mSkelBase->getSkeleton();
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
while(boneiter.hasMoreElements())
boneiter.getNext()->setManuallyControlled(true);
@ -162,10 +136,10 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
else
mAttachedObjects.clear();
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
for(size_t i = 0;i < mObjectRoot->mControllers.size();i++)
{
if(mObjectRoot.mControllers[i].getSource().isNull())
mObjectRoot.mControllers[i].setSource(mAnimationValuePtr[0]);
if(mObjectRoot->mControllers[i].getSource().isNull())
mObjectRoot->mControllers[i].setSource(mAnimationValuePtr[0]);
}
}
@ -233,15 +207,15 @@ public:
}
};
void Animation::setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist, bool enchantedGlow, Ogre::Vector3* glowColor)
void Animation::setRenderProperties(NifOgre::ObjectScenePtr objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue, Ogre::uint8 transqueue, Ogre::Real dist, bool enchantedGlow, Ogre::Vector3* glowColor)
{
std::for_each(objlist.mEntities.begin(), objlist.mEntities.end(),
std::for_each(objlist->mEntities.begin(), objlist->mEntities.end(),
VisQueueSet(visflags, solidqueue, transqueue, dist));
std::for_each(objlist.mParticles.begin(), objlist.mParticles.end(),
std::for_each(objlist->mParticles.begin(), objlist->mParticles.end(),
VisQueueSet(visflags, solidqueue, transqueue, dist));
if (enchantedGlow)
std::for_each(objlist.mEntities.begin(), objlist.mEntities.end(),
std::for_each(objlist->mEntities.begin(), objlist->mEntities.end(),
AddGlow(glowColor));
}
@ -340,7 +314,7 @@ void Animation::clearAnimSources()
}
void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objlist, const ESM::Light *light)
void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScenePtr objlist, const ESM::Light *light)
{
const MWWorld::Fallback *fallback = MWBase::Environment::get().getWorld()->getFallback();
@ -353,8 +327,8 @@ void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList
if((light->mData.mFlags&ESM::Light::Negative))
color *= -1;
objlist.mLights.push_back(sceneMgr->createLight());
Ogre::Light *olight = objlist.mLights.back();
objlist->mLights.push_back(sceneMgr->createLight());
Ogre::Light *olight = objlist->mLights.back();
olight->setDiffuseColour(color);
Ogre::ControllerValueRealPtr src(Ogre::ControllerManager::getSingleton().getFrameTimeSource());
@ -366,7 +340,7 @@ void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList
(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));
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") ?
@ -392,14 +366,14 @@ void Animation::addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList
}
// If there's an AttachLight bone, attach the light to that, otherwise put it in the center,
if(objlist.mSkelBase && objlist.mSkelBase->getSkeleton()->hasBone("AttachLight"))
objlist.mSkelBase->attachObjectToBone("AttachLight", olight);
if(objlist->mSkelBase && objlist->mSkelBase->getSkeleton()->hasBone("AttachLight"))
objlist->mSkelBase->attachObjectToBone("AttachLight", olight);
else
{
Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL;
for(size_t i = 0;i < objlist.mEntities.size();i++)
for(size_t i = 0;i < objlist->mEntities.size();i++)
{
Ogre::Entity *ent = objlist.mEntities[i];
Ogre::Entity *ent = objlist->mEntities[i];
bounds.merge(ent->getBoundingBox());
}
@ -942,8 +916,8 @@ Ogre::Vector3 Animation::runAnimation(float duration)
++stateiter;
}
for(size_t i = 0;i < mObjectRoot.mControllers.size();i++)
mObjectRoot.mControllers[i].update();
for(size_t i = 0;i < mObjectRoot->mControllers.size();i++)
mObjectRoot->mControllers[i].update();
// Apply group controllers
for(size_t grp = 0;grp < sNumGroups;grp++)
@ -986,7 +960,7 @@ public:
void Animation::enableLights(bool enable)
{
std::for_each(mObjectRoot.mLights.begin(), mObjectRoot.mLights.end(), ToggleLight(enable));
std::for_each(mObjectRoot->mLights.begin(), mObjectRoot->mLights.end(), ToggleLight(enable));
}
@ -1005,7 +979,7 @@ public:
Ogre::AxisAlignedBox Animation::getWorldBounds()
{
Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL;
std::for_each(mObjectRoot.mEntities.begin(), mObjectRoot.mEntities.end(), MergeBounds(&bounds));
std::for_each(mObjectRoot->mEntities.begin(), mObjectRoot->mEntities.end(), MergeBounds(&bounds));
return bounds;
}
@ -1055,17 +1029,17 @@ void Animation::addEffect(const std::string &model, int effectId, bool loop, con
params.mEffectId = effectId;
params.mBoneName = bonename;
for(size_t i = 0;i < params.mObjects.mControllers.size();i++)
for(size_t i = 0;i < params.mObjects->mControllers.size();i++)
{
if(params.mObjects.mControllers[i].getSource().isNull())
params.mObjects.mControllers[i].setSource(Ogre::SharedPtr<EffectAnimationValue> (new EffectAnimationValue()));
if(params.mObjects->mControllers[i].getSource().isNull())
params.mObjects->mControllers[i].setSource(Ogre::SharedPtr<EffectAnimationValue> (new EffectAnimationValue()));
}
if (!texture.empty())
{
for(size_t i = 0;i < params.mObjects.mParticles.size(); ++i)
for(size_t i = 0;i < params.mObjects->mParticles.size(); ++i)
{
Ogre::ParticleSystem* partSys = params.mObjects.mParticles[i];
Ogre::ParticleSystem* partSys = params.mObjects->mParticles[i];
sh::Factory::getInstance()._ensureMaterial(partSys->getMaterialName(), "Default");
Ogre::MaterialPtr mat = Ogre::MaterialManager::getSingleton().getByName(partSys->getMaterialName());
static int count = 0;
@ -1099,7 +1073,6 @@ void Animation::removeEffect(int effectId)
{
if (it->mEffectId == effectId)
{
destroyObjectList(mInsert->getCreator(), it->mObjects);
mEffects.erase(it);
return;
}
@ -1119,32 +1092,31 @@ void Animation::updateEffects(float duration)
{
for (std::vector<EffectParams>::iterator it = mEffects.begin(); it != mEffects.end(); )
{
NifOgre::ObjectList& objects = it->mObjects;
for(size_t i = 0; i < objects.mControllers.size() ;i++)
NifOgre::ObjectScenePtr objects = it->mObjects;
for(size_t i = 0; i < objects->mControllers.size() ;i++)
{
EffectAnimationValue* value = dynamic_cast<EffectAnimationValue*>(objects.mControllers[i].getSource().get());
EffectAnimationValue* value = dynamic_cast<EffectAnimationValue*>(objects->mControllers[i].getSource().get());
if (value)
value->addTime(duration);
objects.mControllers[i].update();
objects->mControllers[i].update();
}
if (objects.mControllers[0].getSource()->getValue() >= objects.mMaxControllerLength)
if (objects->mControllers[0].getSource()->getValue() >= objects->mMaxControllerLength)
{
if (it->mLoop)
{
// Start from the beginning again; carry over the remainder
float remainder = objects.mControllers[0].getSource()->getValue() - objects.mMaxControllerLength;
for(size_t i = 0; i < objects.mControllers.size() ;i++)
float remainder = objects->mControllers[0].getSource()->getValue() - objects->mMaxControllerLength;
for(size_t i = 0; i < objects->mControllers.size() ;i++)
{
EffectAnimationValue* value = dynamic_cast<EffectAnimationValue*>(objects.mControllers[i].getSource().get());
EffectAnimationValue* value = dynamic_cast<EffectAnimationValue*>(objects->mControllers[i].getSource().get());
if (value)
value->resetTime(remainder);
}
}
else
{
destroyObjectList(mInsert->getCreator(), it->mObjects);
it = mEffects.erase(it);
continue;
}
@ -1214,16 +1186,16 @@ public:
bool ObjectAnimation::canBatch() const
{
if(!mObjectRoot.mParticles.empty() || !mObjectRoot.mLights.empty() || !mObjectRoot.mControllers.empty())
if(!mObjectRoot->mParticles.empty() || !mObjectRoot->mLights.empty() || !mObjectRoot->mControllers.empty())
return false;
return std::find_if(mObjectRoot.mEntities.begin(), mObjectRoot.mEntities.end(),
FindEntityTransparency()) == mObjectRoot.mEntities.end();
return std::find_if(mObjectRoot->mEntities.begin(), mObjectRoot->mEntities.end(),
FindEntityTransparency()) == mObjectRoot->mEntities.end();
}
void ObjectAnimation::fillBatch(Ogre::StaticGeometry *sg)
{
std::vector<Ogre::Entity*>::reverse_iterator iter = mObjectRoot.mEntities.rbegin();
for(;iter != mObjectRoot.mEntities.rend();++iter)
std::vector<Ogre::Entity*>::reverse_iterator iter = mObjectRoot->mEntities.rbegin();
for(;iter != mObjectRoot->mEntities.rend();++iter)
{
Ogre::Node *node = (*iter)->getParentNode();
sg->addEntity(*iter, node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale());

@ -112,7 +112,7 @@ protected:
struct EffectParams
{
std::string mModelName; // Just here so we don't add the same effect twice
NifOgre::ObjectList mObjects;
NifOgre::ObjectScenePtr mObjects;
int mEffectId;
bool mLoop;
std::string mBoneName;
@ -125,7 +125,7 @@ protected:
Ogre::SceneNode *mInsert;
Ogre::Entity *mSkelBase;
NifOgre::ObjectList mObjectRoot;
NifOgre::ObjectScenePtr mObjectRoot;
AnimSourceList mAnimSources;
Ogre::Node *mAccumRoot;
Ogre::Node *mNonAccumRoot;
@ -187,11 +187,9 @@ protected:
void addAnimSource(const std::string &model);
/** Adds an additional light to the given object list using the specified ESM record. */
void addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objlist, const ESM::Light *light);
void addExtraLight(Ogre::SceneManager *sceneMgr, NifOgre::ObjectScenePtr objlist, const ESM::Light *light);
static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects);
static void setRenderProperties(const NifOgre::ObjectList &objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue,
static void setRenderProperties(NifOgre::ObjectScenePtr objlist, Ogre::uint32 visflags, Ogre::uint8 solidqueue,
Ogre::uint8 transqueue, Ogre::Real dist=0.0f,
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
@ -217,6 +215,8 @@ public:
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", std::string texture = "");
void removeEffect (int effectId);
void getLoopingEffects (std::vector<int>& out);
virtual void setAlpha(float alpha) {}
private:
void updateEffects(float duration);

@ -5,6 +5,8 @@
#include <OgreParticleSystem.h>
#include <OgreSubEntity.h>
#include <extern/shiny/Main/Factory.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
@ -106,10 +108,6 @@ NpcAnimation::~NpcAnimation()
{
if (!mListenerDisabled)
mPtr.getClass().getInventoryStore(mPtr).setListener(NULL, mPtr);
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
for(size_t i = 0;i < ESM::PRT_Count;i++)
destroyObjectList(sceneMgr, mObjectParts[i]);
}
@ -120,7 +118,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v
mViewMode(viewMode),
mShowWeapons(false),
mShowShield(true),
mFirstPersonOffset(0.f, 0.f, 0.f)
mFirstPersonOffset(0.f, 0.f, 0.f),
mAlpha(1.f)
{
mNpc = mPtr.get<ESM::NPC>()->mBase;
@ -223,6 +222,7 @@ void NpcAnimation::updateNpcBase()
void NpcAnimation::updateParts()
{
mAlpha = 1.f;
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr);
@ -447,18 +447,18 @@ public:
}
};
NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename, bool enchantedGlow, Ogre::Vector3* glowColor)
NifOgre::ObjectScenePtr NpcAnimation::insertBoundedPart(const std::string &model, int group, const std::string &bonename, bool enchantedGlow, Ogre::Vector3* glowColor)
{
NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mSkelBase, bonename, mInsert, model);
NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(mSkelBase, bonename, 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));
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)
if(objects->mSkelBase)
{
Ogre::AnimationStateSet *aset = objects.mSkelBase->getAllAnimationStates();
Ogre::AnimationStateSet *aset = objects->mSkelBase->getAllAnimationStates();
Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator();
while(asiter.hasMoreElements())
{
@ -466,7 +466,7 @@ NifOgre::ObjectList NpcAnimation::insertBoundedPart(const std::string &model, in
state->setEnabled(false);
state->setLoop(false);
}
Ogre::SkeletonInstance *skelinst = objects.mSkelBase->getSkeleton();
Ogre::SkeletonInstance *skelinst = objects->mSkelBase->getSkeleton();
Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator();
while(boneiter.hasMoreElements())
boneiter.getNext()->setManuallyControlled(true);
@ -494,11 +494,13 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
for(size_t i = 0;i < ESM::PRT_Count;i++)
{
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[i].mControllers.begin());
for(;ctrl != mObjectParts[i].mControllers.end();ctrl++)
if (mObjectParts[i].isNull())
continue;
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[i]->mControllers.begin());
for(;ctrl != mObjectParts[i]->mControllers.end();ctrl++)
ctrl->update();
Ogre::Entity *ent = mObjectParts[i].mSkelBase;
Ogre::Entity *ent = mObjectParts[i]->mSkelBase;
if(!ent) continue;
updateSkeletonInstance(baseinst, ent->getSkeleton());
ent->getAllAnimationStates()->_notifyDirty();
@ -512,7 +514,7 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type)
mPartPriorities[type] = 0;
mPartslots[type] = -1;
destroyObjectList(mInsert->getCreator(), mObjectParts[type]);
mObjectParts[type].setNull();
}
void NpcAnimation::reserveIndividualPart(ESM::PartReferenceType type, int group, int priority)
@ -544,12 +546,12 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
mPartPriorities[type] = priority;
mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor);
if(mObjectParts[type].mSkelBase)
if(mObjectParts[type]->mSkelBase)
{
Ogre::SkeletonInstance *skel = mObjectParts[type].mSkelBase->getSkeleton();
if(mObjectParts[type].mSkelBase->isParentTagPoint())
Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton();
if(mObjectParts[type]->mSkelBase->isParentTagPoint())
{
Ogre::Node *root = mObjectParts[type].mSkelBase->getParentNode();
Ogre::Node *root = mObjectParts[type]->mSkelBase->getParentNode();
if(skel->hasBone("BoneOffset"))
{
Ogre::Bone *offset = skel->getBone("BoneOffset");
@ -571,8 +573,8 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g
// TODO:
// type == ESM::PRT_Weapon should get an animation source based on the current offset
// of the weapon attack animation (from its beginning, or start marker?)
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[type].mControllers.begin());
for(;ctrl != mObjectParts[type].mControllers.end();ctrl++)
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[type]->mControllers.begin());
for(;ctrl != mObjectParts[type]->mControllers.end();ctrl++)
{
if(ctrl->getSource().isNull())
{
@ -649,6 +651,7 @@ void NpcAnimation::showWeapons(bool showWeapon)
{
removeIndividualPart(ESM::PRT_Weapon);
}
mAlpha = 1.f;
}
void NpcAnimation::showShield(bool show)
@ -707,4 +710,56 @@ void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, boo
}
}
void NpcAnimation::setAlpha(float alpha)
{
if (alpha == mAlpha)
return;
mAlpha = alpha;
for (int i=0; i<ESM::PRT_Count; ++i)
{
if (mObjectParts[i].isNull())
continue;
for (unsigned int j=0; j<mObjectParts[i]->mEntities.size(); ++j)
{
Ogre::Entity* ent = mObjectParts[i]->mEntities[j];
if (ent != mObjectParts[i]->mSkelBase)
applyAlpha(alpha, ent, mObjectParts[i]);
}
}
}
void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectScenePtr scene)
{
ent->getSubEntity(0)->setRenderQueueGroup(alpha != 1.f || ent->getSubEntity(0)->getMaterial()->isTransparent()
? RQG_Alpha : RQG_Main);
Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(ent);
if (mAlpha == 1.f)
{
// Don't bother remembering what the original values were. Just remove the techniques and let the factory restore them.
mat->removeAllTechniques();
sh::Factory::getInstance()._ensureMaterial(mat->getName(), "Default");
return;
}
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
Ogre::Technique::PassIterator passes = tech->getPassIterator();
while(passes.hasMoreElements())
{
Ogre::Pass *pass = passes.getNext();
pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
Ogre::ColourValue diffuse = pass->getDiffuse();
diffuse.a = alpha;
pass->setDiffuse(diffuse);
pass->setVertexColourTracking(pass->getVertexColourTracking() &~Ogre::TVC_DIFFUSE);
}
}
}
}

@ -46,7 +46,7 @@ private:
bool mListenerDisabled;
// Bounded Parts
NifOgre::ObjectList mObjectParts[ESM::PRT_Count];
NifOgre::ObjectScenePtr mObjectParts[ESM::PRT_Count];
const ESM::NPC *mNpc;
std::string mHeadModel;
@ -64,9 +64,11 @@ private:
Ogre::SharedPtr<SayAnimationValue> mSayAnimationValue;
float mAlpha;
void updateNpcBase();
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename,
NifOgre::ObjectScenePtr insertBoundedPart(const std::string &model, int group, const std::string &bonename,
bool enchantedGlow, Ogre::Vector3* glowColor=NULL);
void removeIndividualPart(ESM::PartReferenceType type);
@ -78,6 +80,8 @@ private:
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene);
public:
/**
* @param ptr
@ -109,6 +113,9 @@ public:
/// Rebuilds the NPC, updating their root model, animation sources, and equipment.
void rebuild();
/// Make the NPC only partially visible
virtual void setAlpha(float alpha);
};
}

@ -60,14 +60,14 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
MWWorld::Fallback* fallback)
: mRendering(_rend)
, mFallback(fallback)
, mObjects(mRendering)
, mActors(mRendering, this)
, mPlayerAnimation(NULL)
, mAmbientMode(0)
, mSunEnabled(0)
, mPhysicsEngine(engine)
, mTerrain(NULL)
{
mActors = new MWRender::Actors(mRendering, this);
mObjects = new MWRender::Objects(mRendering);
// select best shader mode
bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos);
bool glES = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL ES") != std::string::npos);
@ -162,8 +162,8 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
mRootNode = mRendering.getScene()->getRootSceneNode();
mRootNode->createChildSceneNode("player");
mObjects.setRootNode(mRootNode);
mActors.setRootNode(mRootNode);
mObjects->setRootNode(mRootNode);
mActors->setRootNode(mRootNode);
mCamera = new MWRender::Camera(mRendering.getCamera());
@ -201,6 +201,8 @@ RenderingManager::~RenderingManager ()
delete mCompositors;
delete mWater;
delete mVideoPlayer;
delete mActors;
delete mObjects;
delete mFactory;
}
@ -210,10 +212,10 @@ MWRender::SkyManager* RenderingManager::getSkyManager()
}
MWRender::Objects& RenderingManager::getObjects(){
return mObjects;
return *mObjects;
}
MWRender::Actors& RenderingManager::getActors(){
return mActors;
return *mActors;
}
OEngine::Render::Fader* RenderingManager::getFader()
@ -223,8 +225,8 @@ OEngine::Render::Fader* RenderingManager::getFader()
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store)
{
mObjects.removeCell(store);
mActors.removeCell(store);
mObjects->removeCell(store);
mActors->removeCell(store);
mDebugging->cellRemoved(store);
}
@ -240,7 +242,7 @@ void RenderingManager::toggleWater()
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
{
mObjects.buildStaticGeometry (*store);
mObjects->buildStaticGeometry (*store);
sh::Factory::getInstance().unloadUnreferencedMaterials();
mDebugging->cellAdded(store);
waterAdded(store);
@ -254,8 +256,8 @@ void RenderingManager::addObject (const MWWorld::Ptr& ptr){
void RenderingManager::removeObject (const MWWorld::Ptr& ptr)
{
if (!mObjects.deleteObject (ptr))
mActors.deleteObject (ptr);
if (!mObjects->deleteObject (ptr))
mActors->deleteObject (ptr);
}
void RenderingManager::moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position)
@ -295,9 +297,9 @@ RenderingManager::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &
parent->removeChild(child);
if (MWWorld::Class::get(old).isActor()) {
mActors.updateObjectCell(old, cur);
mActors->updateObjectCell(old, cur);
} else {
mObjects.updateObjectCell(old, cur);
mObjects->updateObjectCell(old, cur);
}
}
@ -315,7 +317,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
if(ptr.getRefData().getHandle() == "player")
anim = mPlayerAnimation;
else if(MWWorld::Class::get(ptr).isActor())
anim = dynamic_cast<NpcAnimation*>(mActors.getAnimation(ptr));
anim = dynamic_cast<NpcAnimation*>(mActors->getAnimation(ptr));
if(anim)
{
anim->rebuild();
@ -380,8 +382,8 @@ void RenderingManager::update (float duration, bool paused)
if(paused)
return;
mActors.update (duration);
mObjects.update (duration);
mActors->update (duration);
mObjects->update (duration);
mSkyManager->update(duration);
@ -657,7 +659,7 @@ void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell)
{
assert(mTerrain);
Ogre::AxisAlignedBox dims = mObjects.getDimensions(cell);
Ogre::AxisAlignedBox dims = mObjects->getDimensions(cell);
Ogre::Vector2 center(cell->mCell->getGridX() + 0.5, cell->mCell->getGridY() + 0.5);
dims.merge(mTerrain->getWorldBoundingBox(center));
@ -667,7 +669,7 @@ void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell)
mLocalMap->requestMap(cell, dims.getMinimum().z, dims.getMaximum().z);
}
else
mLocalMap->requestMap(cell, mObjects.getDimensions(cell));
mLocalMap->requestMap(cell, mObjects->getDimensions(cell));
}
void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
@ -677,13 +679,13 @@ void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
void RenderingManager::disableLights(bool sun)
{
mObjects.disableLights();
mObjects->disableLights();
sunDisable(sun);
}
void RenderingManager::enableLights(bool sun)
{
mObjects.enableLights();
mObjects->enableLights();
sunEnable(sun);
}
@ -859,7 +861,7 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
if (rebuild)
{
mObjects.rebuildStaticGeometry();
mObjects->rebuildStaticGeometry();
if (mTerrain)
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
Settings::Manager::getBool("split", "Shadows"));
@ -976,13 +978,13 @@ void RenderingManager::setupExternalRendering (MWRender::ExternalRendering& rend
Animation* RenderingManager::getAnimation(const MWWorld::Ptr &ptr)
{
Animation *anim = mActors.getAnimation(ptr);
Animation *anim = mActors->getAnimation(ptr);
if(!anim && ptr.getRefData().getHandle() == "player")
anim = mPlayerAnimation;
if (!anim)
anim = mObjects.getAnimation(ptr);
anim = mObjects->getAnimation(ptr);
return anim;
}

@ -242,8 +242,8 @@ private:
OEngine::Render::OgreRenderer &mRendering;
MWRender::Objects mObjects;
MWRender::Actors mActors;
MWRender::Objects* mObjects;
MWRender::Actors* mActors;
MWRender::NpcAnimation *mPlayerAnimation;

@ -285,10 +285,10 @@ void SkyManager::create()
// Stars
mAtmosphereNight = mRootNode->createChildSceneNode();
NifOgre::ObjectList objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_01.nif");
for(size_t i = 0, matidx = 0;i < objects.mEntities.size();i++)
NifOgre::ObjectScenePtr objects = NifOgre::Loader::createObjects(mAtmosphereNight, "meshes\\sky_night_01.nif");
for(size_t i = 0, matidx = 0;i < objects->mEntities.size();i++)
{
Entity* night1_ent = objects.mEntities[i];
Entity* night1_ent = objects->mEntities[i];
night1_ent->setRenderQueueGroup(RQG_SkiesEarly+1);
night1_ent->setVisibilityFlags(RV_Sky);
night1_ent->setCastShadows(false);
@ -307,14 +307,14 @@ void SkyManager::create()
night1_ent->getSubEntity(j)->setMaterialName(matName);
}
}
mObjects.push_back(objects);
// Atmosphere (day)
mAtmosphereDay = mRootNode->createChildSceneNode();
objects = NifOgre::Loader::createObjects(mAtmosphereDay, "meshes\\sky_atmosphere.nif");
for(size_t i = 0;i < objects.mEntities.size();i++)
for(size_t i = 0;i < objects->mEntities.size();i++)
{
Entity* atmosphere_ent = objects.mEntities[i];
Entity* atmosphere_ent = objects->mEntities[i];
atmosphere_ent->setCastShadows(false);
atmosphere_ent->setRenderQueueGroup(RQG_SkiesEarly);
atmosphere_ent->setVisibilityFlags(RV_Sky);
@ -325,14 +325,14 @@ void SkyManager::create()
// Using infinite AAB here to prevent being clipped by the custom near clip plane used for reflections/refractions
atmosphere_ent->getMesh()->_setBounds (aabInf);
}
mObjects.push_back(objects);
// Clouds
SceneNode* clouds_node = mRootNode->createChildSceneNode();
objects = NifOgre::Loader::createObjects(clouds_node, "meshes\\sky_clouds_01.nif");
for(size_t i = 0;i < objects.mEntities.size();i++)
for(size_t i = 0;i < objects->mEntities.size();i++)
{
Entity* clouds_ent = objects.mEntities[i];
Entity* clouds_ent = objects->mEntities[i];
clouds_ent->setVisibilityFlags(RV_Sky);
clouds_ent->setRenderQueueGroup(RQG_SkiesEarly+5);
for(unsigned int j = 0;j < clouds_ent->getNumSubEntities();j++)
@ -341,6 +341,7 @@ void SkyManager::create()
// Using infinite AAB here to prevent being clipped by the custom near clip plane used for reflections/refractions
clouds_ent->getMesh()->_setBounds (aabInf);
}
mObjects.push_back(objects);
mCreated = true;
}

@ -11,6 +11,8 @@
#include <extern/shiny/Main/Factory.hpp>
#include <components/nifogre/ogrenifloader.hpp>
#include "../mwworld/weather.hpp"
@ -196,6 +198,8 @@ namespace MWRender
Ogre::SceneNode* mAtmosphereDay;
Ogre::SceneNode* mAtmosphereNight;
std::vector<NifOgre::ObjectScenePtr> mObjects;
// remember some settings so we don't have to apply them again if they didnt change
Ogre::String mClouds;
Ogre::String mNextClouds;

@ -615,3 +615,8 @@ void MWWorld::InventoryStore::rechargeItems(float duration)
it->second);
}
}
void MWWorld::InventoryStore::purgeEffect(short effectId)
{
mMagicEffects.add(MWMechanics::EffectKey(effectId), -mMagicEffects.get(MWMechanics::EffectKey(effectId)).mMagnitude);
}

@ -179,7 +179,10 @@ namespace MWWorld
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor);
void rechargeItems (float duration);
/// Restore charge on enchanted items. Note this should only be done for the player.
///< Restore charge on enchanted items. Note this should only be done for the player.
void purgeEffect (short effectId);
///< Remove a magic effect
};
}

@ -1845,6 +1845,13 @@ namespace MWWorld
bool World::getLOS(const MWWorld::Ptr& npc,const MWWorld::Ptr& targetNpc)
{
// This is a placeholder! Needs to go into an NPC awareness check function (see
// https://wiki.openmw.org/index.php?title=Research:NPC_AI_Behaviour#NPC_Awareness_Check )
if (targetNpc.getClass().getCreatureStats(targetNpc).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude)
return false;
if (targetNpc.getClass().getCreatureStats(targetNpc).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude > 100)
return false;
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents();
float* pos1 = npc.getRefData().getPosition().pos;
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents();
@ -2231,4 +2238,10 @@ namespace MWWorld
deleteObject(movedPtr);
}
}
void World::breakInvisibility(const Ptr &actor)
{
actor.getClass().getCreatureStats(actor).getActiveSpells().purgeEffect(ESM::MagicEffect::Invisibility);
actor.getClass().getInventoryStore(actor).purgeEffect(ESM::MagicEffect::Invisibility);
}
}

@ -504,6 +504,8 @@ namespace MWWorld
virtual void launchProjectile (const std::string& id, bool stack, const ESM::EffectList& effects,
const MWWorld::Ptr& actor, const std::string& sourceName);
virtual void breakInvisibility (const MWWorld::Ptr& actor);
};
}

@ -19,7 +19,7 @@ add_component_dir (nif
)
add_component_dir (nifogre
ogrenifloader skeleton material mesh particles
ogrenifloader skeleton material mesh particles controller
)
add_component_dir (nifbullet

@ -306,7 +306,7 @@ public:
class NiFlipController : public Controller
{
public:
int mTexSlot;
int mTexSlot; // NiTexturingProperty::TextureType
float mDelta; // Time between two flips. delta = (start_time - stop_time) / num_sources
NiSourceTextureList mSources;

@ -0,0 +1,95 @@
#ifndef COMPONENTS_NIFOGRE_CONTROLLER_H
#define COMPONENTS_NIFOGRE_CONTROLLER_H
#include <components/nif/niffile.hpp>
#include <OgreController.h>
namespace NifOgre
{
class ValueInterpolator
{
protected:
float interpKey(const Nif::FloatKeyList::VecType &keys, float time, float def=0.f) const
{
if (keys.size() == 0)
return def;
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::FloatKeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::FloatKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.back().mValue;
}
Ogre::Vector3 interpKey(const Nif::Vector3KeyList::VecType &keys, float time) const
{
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::Vector3KeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::Vector3KeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.back().mValue;
}
};
// FIXME: Should not be here.
class DefaultFunction : public Ogre::ControllerFunction<Ogre::Real>
{
private:
float mFrequency;
float mPhase;
float mStartTime;
public:
float mStopTime;
public:
DefaultFunction(const Nif::Controller *ctrl, bool deltaInput)
: Ogre::ControllerFunction<Ogre::Real>(deltaInput)
, mFrequency(ctrl->frequency)
, mPhase(ctrl->phase)
, mStartTime(ctrl->timeStart)
, mStopTime(ctrl->timeStop)
{
if(mDeltaInput)
mDeltaCount = mPhase;
}
virtual Ogre::Real calculate(Ogre::Real value)
{
if(mDeltaInput)
{
mDeltaCount += value*mFrequency;
if(mDeltaCount < mStartTime)
mDeltaCount = mStopTime - std::fmod(mStartTime - mDeltaCount,
mStopTime - mStartTime);
mDeltaCount = std::fmod(mDeltaCount - mStartTime,
mStopTime - mStartTime) + mStartTime;
return mDeltaCount;
}
value = std::min(mStopTime, std::max(mStartTime, value+mPhase));
return value;
}
};
}
#endif

@ -237,7 +237,8 @@ Ogre::String NIFMaterialLoader::getMaterial(const Nif::ShapeData *shapedata,
Nif::ControllerPtr ctrls = matprop->controller;
while(!ctrls.empty())
{
warn("Unhandled material controller "+ctrls->recName+" in "+name);
if (ctrls->recType != Nif::RC_NiAlphaController && ctrls->recType != Nif::RC_NiMaterialColorController)
warn("Unhandled material controller "+ctrls->recName+" in "+name);
ctrls = ctrls->next;
}
}

@ -37,9 +37,9 @@ class NIFMaterialLoader {
static std::map<size_t,std::string> sMaterialMap;
public:
static std::string findTextureName(const std::string &filename);
public:
static Ogre::String getMaterial(const Nif::ShapeData *shapedata,
const Ogre::String &name, const Ogre::String &group,
const Nif::NiTexturingProperty *texprop,

@ -37,54 +37,241 @@
#include <OgreSkeletonManager.h>
#include <OgreControllerManager.h>
#include <extern/shiny/Main/Factory.hpp>
#include <components/nif/node.hpp>
#include <components/misc/stringops.hpp>
#include "skeleton.hpp"
#include "material.hpp"
#include "mesh.hpp"
#include "controller.hpp"
namespace NifOgre
{
// FIXME: Should not be here.
class DefaultFunction : public Ogre::ControllerFunction<Ogre::Real>
Ogre::MaterialPtr MaterialControllerManager::getWritableMaterial(Ogre::MovableObject *movable)
{
if (mClonedMaterials.find(movable) != mClonedMaterials.end())
return mClonedMaterials[movable];
else
{
Ogre::MaterialPtr mat;
if (Ogre::Entity* ent = dynamic_cast<Ogre::Entity*>(movable))
mat = ent->getSubEntity(0)->getMaterial();
else if (Ogre::ParticleSystem* partSys = dynamic_cast<Ogre::ParticleSystem*>(movable))
mat = Ogre::MaterialManager::getSingleton().getByName(partSys->getMaterialName());
static int count=0;
Ogre::String newName = mat->getName() + Ogre::StringConverter::toString(count++);
sh::Factory::getInstance().createMaterialInstance(newName, mat->getName());
// Make sure techniques are created
sh::Factory::getInstance()._ensureMaterial(newName, "Default");
mat = Ogre::MaterialManager::getSingleton().getByName(newName);
mClonedMaterials[movable] = mat;
if (Ogre::Entity* ent = dynamic_cast<Ogre::Entity*>(movable))
ent->getSubEntity(0)->setMaterial(mat);
else if (Ogre::ParticleSystem* partSys = dynamic_cast<Ogre::ParticleSystem*>(movable))
partSys->setMaterialName(mat->getName());
return mat;
}
}
MaterialControllerManager::~MaterialControllerManager()
{
for (std::map<Ogre::MovableObject*, Ogre::MaterialPtr>::iterator it = mClonedMaterials.begin(); it != mClonedMaterials.end(); ++it)
{
sh::Factory::getInstance().destroyMaterialInstance(it->second->getName());
}
}
ObjectScene::~ObjectScene()
{
for(size_t i = 0;i < mLights.size();i++)
{
Ogre::Light *light = mLights[i];
// If parent is a scene node, it was created specifically for this light. Destroy it now.
if(light->isAttached() && !light->isParentTagPoint())
mSceneMgr->destroySceneNode(light->getParentSceneNode());
mSceneMgr->destroyLight(light);
}
for(size_t i = 0;i < mParticles.size();i++)
mSceneMgr->destroyParticleSystem(mParticles[i]);
for(size_t i = 0;i < mEntities.size();i++)
mSceneMgr->destroyEntity(mEntities[i]);
mControllers.clear();
mLights.clear();
mParticles.clear();
mEntities.clear();
mSkelBase = NULL;
}
// Animates a texture
class FlipController
{
private:
float mFrequency;
float mPhase;
float mStartTime;
public:
float mStopTime;
class Value : public Ogre::ControllerValue<Ogre::Real>
{
private:
Ogre::MovableObject* mMovable;
int mTexSlot;
float mDelta;
std::vector<std::string> mTextures;
MaterialControllerManager* mMaterialControllerMgr;
public:
Value(Ogre::MovableObject *movable, const Nif::NiFlipController *ctrl, MaterialControllerManager* materialControllerMgr)
: mMovable(movable)
, mMaterialControllerMgr(materialControllerMgr)
{
mTexSlot = ctrl->mTexSlot;
mDelta = ctrl->mDelta;
for (unsigned int i=0; i<ctrl->mSources.length(); ++i)
{
const Nif::NiSourceTexture* tex = ctrl->mSources[i].getPtr();
if (!tex->external)
std::cerr << "Warning: Found internal texture, ignoring." << std::endl;
mTextures.push_back(NIFMaterialLoader::findTextureName(tex->filename));
}
}
virtual Ogre::Real getValue() const
{
// Should not be called
return 0.0f;
}
virtual void setValue(Ogre::Real time)
{
if (mDelta == 0)
return;
int curTexture = int(time / mDelta) % mTextures.size();
Ogre::MaterialPtr mat = mMaterialControllerMgr->getWritableMaterial(mMovable);
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
Ogre::Technique::PassIterator passes = tech->getPassIterator();
while(passes.hasMoreElements())
{
Ogre::Pass *pass = passes.getNext();
Ogre::Pass::TextureUnitStateIterator textures = pass->getTextureUnitStateIterator();
while (textures.hasMoreElements())
{
Ogre::TextureUnitState *texture = textures.getNext();
if ((texture->getName() == "diffuseMap" && mTexSlot == Nif::NiTexturingProperty::BaseTexture)
|| (texture->getName() == "normalMap" && mTexSlot == Nif::NiTexturingProperty::BumpTexture)
|| (texture->getName() == "detailMap" && mTexSlot == Nif::NiTexturingProperty::DetailTexture)
|| (texture->getName() == "emissiveMap" && mTexSlot == Nif::NiTexturingProperty::GlowTexture))
texture->setTextureName(mTextures[curTexture]);
}
}
}
}
};
typedef DefaultFunction Function;
};
class AlphaController
{
public:
DefaultFunction(const Nif::Controller *ctrl, bool deltaInput)
: Ogre::ControllerFunction<Ogre::Real>(deltaInput)
, mFrequency(ctrl->frequency)
, mPhase(ctrl->phase)
, mStartTime(ctrl->timeStart)
, mStopTime(ctrl->timeStop)
class Value : public Ogre::ControllerValue<Ogre::Real>, public ValueInterpolator
{
if(mDeltaInput)
mDeltaCount = mPhase;
}
private:
Ogre::MovableObject* mMovable;
Nif::FloatKeyList mData;
MaterialControllerManager* mMaterialControllerMgr;
public:
Value(Ogre::MovableObject *movable, const Nif::NiFloatData *data, MaterialControllerManager* materialControllerMgr)
: mMovable(movable)
, mData(data->mKeyList)
, mMaterialControllerMgr(materialControllerMgr)
{
}
virtual Ogre::Real getValue() const
{
// Should not be called
return 0.0f;
}
virtual void setValue(Ogre::Real time)
{
float value = interpKey(mData.mKeys, time);
Ogre::MaterialPtr mat = mMaterialControllerMgr->getWritableMaterial(mMovable);
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
Ogre::Technique::PassIterator passes = tech->getPassIterator();
while(passes.hasMoreElements())
{
Ogre::Pass *pass = passes.getNext();
Ogre::ColourValue diffuse = pass->getDiffuse();
diffuse.a = value;
pass->setDiffuse(diffuse);
}
}
}
};
typedef DefaultFunction Function;
};
virtual Ogre::Real calculate(Ogre::Real value)
class MaterialColorController
{
public:
class Value : public Ogre::ControllerValue<Ogre::Real>, public ValueInterpolator
{
if(mDeltaInput)
private:
Ogre::MovableObject* mMovable;
Nif::Vector3KeyList mData;
MaterialControllerManager* mMaterialControllerMgr;
public:
Value(Ogre::MovableObject *movable, const Nif::NiPosData *data, MaterialControllerManager* materialControllerMgr)
: mMovable(movable)
, mData(data->mKeyList)
, mMaterialControllerMgr(materialControllerMgr)
{
mDeltaCount += value*mFrequency;
if(mDeltaCount < mStartTime)
mDeltaCount = mStopTime - std::fmod(mStartTime - mDeltaCount,
mStopTime - mStartTime);
mDeltaCount = std::fmod(mDeltaCount - mStartTime,
mStopTime - mStartTime) + mStartTime;
return mDeltaCount;
}
value = std::min(mStopTime, std::max(mStartTime, value+mPhase));
return value;
}
virtual Ogre::Real getValue() const
{
// Should not be called
return 0.0f;
}
virtual void setValue(Ogre::Real time)
{
Ogre::Vector3 value = interpKey(mData.mKeys, time);
Ogre::MaterialPtr mat = mMaterialControllerMgr->getWritableMaterial(mMovable);
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
Ogre::Technique::PassIterator passes = tech->getPassIterator();
while(passes.hasMoreElements())
{
Ogre::Pass *pass = passes.getNext();
Ogre::ColourValue diffuse = pass->getDiffuse();
diffuse.r = value.x;
diffuse.g = value.y;
diffuse.b = value.z;
pass->setDiffuse(diffuse);
}
}
}
};
typedef DefaultFunction Function;
};
class VisController
@ -163,48 +350,14 @@ public:
class KeyframeController
{
public:
class Value : public NodeTargetValue<Ogre::Real>
class Value : public NodeTargetValue<Ogre::Real>, public ValueInterpolator
{
private:
Nif::QuaternionKeyList mRotations;
Nif::Vector3KeyList mTranslations;
Nif::FloatKeyList mScales;
static float interpKey(const Nif::FloatKeyList::VecType &keys, float time)
{
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::FloatKeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::FloatKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.back().mValue;
}
static Ogre::Vector3 interpKey(const Nif::Vector3KeyList::VecType &keys, float time)
{
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::Vector3KeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::Vector3KeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.back().mValue;
}
using ValueInterpolator::interpKey;
static Ogre::Quaternion interpKey(const Nif::QuaternionKeyList::VecType &keys, float time)
{
@ -276,43 +429,24 @@ public:
class UVController
{
public:
class Value : public Ogre::ControllerValue<Ogre::Real>
class Value : public Ogre::ControllerValue<Ogre::Real>, public ValueInterpolator
{
private:
Ogre::MaterialPtr mMaterial;
Ogre::MovableObject* mMovable;
Nif::FloatKeyList mUTrans;
Nif::FloatKeyList mVTrans;
Nif::FloatKeyList mUScale;
Nif::FloatKeyList mVScale;
static float lookupValue(const Nif::FloatKeyList &keys, float time, float def)
{
if(keys.mKeys.size() == 0)
return def;
if(time <= keys.mKeys.front().mTime)
return keys.mKeys.front().mValue;
Nif::FloatKeyList::VecType::const_iterator iter(keys.mKeys.begin()+1);
for(;iter != keys.mKeys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::FloatKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.mKeys.back().mValue;
}
MaterialControllerManager* mMaterialControllerMgr;
public:
Value(const Ogre::MaterialPtr &material, const Nif::NiUVData *data)
: mMaterial(material)
Value(Ogre::MovableObject* movable, const Nif::NiUVData *data, MaterialControllerManager* materialControllerMgr)
: mMovable(movable)
, mUTrans(data->mKeyList[0])
, mVTrans(data->mKeyList[1])
, mUScale(data->mKeyList[2])
, mVScale(data->mKeyList[3])
, mMaterialControllerMgr(materialControllerMgr)
{ }
virtual Ogre::Real getValue() const
@ -323,12 +457,14 @@ public:
virtual void setValue(Ogre::Real value)
{
float uTrans = lookupValue(mUTrans, value, 0.0f);
float vTrans = lookupValue(mVTrans, value, 0.0f);
float uScale = lookupValue(mUScale, value, 1.0f);
float vScale = lookupValue(mVScale, value, 1.0f);
float uTrans = interpKey(mUTrans.mKeys, value, 0.0f);
float vTrans = interpKey(mVTrans.mKeys, value, 0.0f);
float uScale = interpKey(mUScale.mKeys, value, 1.0f);
float vScale = interpKey(mVScale.mKeys, value, 1.0f);
Ogre::MaterialPtr material = mMaterialControllerMgr->getWritableMaterial(mMovable);
Ogre::Material::TechniqueIterator techs = mMaterial->getTechniqueIterator();
Ogre::Material::TechniqueIterator techs = material->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
@ -380,7 +516,7 @@ public:
class GeomMorpherController
{
public:
class Value : public Ogre::ControllerValue<Ogre::Real>
class Value : public Ogre::ControllerValue<Ogre::Real>, public ValueInterpolator
{
private:
Ogre::SubEntity *mSubEntity;
@ -389,24 +525,6 @@ public:
std::vector<Ogre::Vector3> mVertices;
static float interpKey(const Nif::FloatKeyList::VecType &keys, float time)
{
if(time <= keys.front().mTime)
return keys.front().mValue;
Nif::FloatKeyList::VecType::const_iterator iter(keys.begin()+1);
for(;iter != keys.end();iter++)
{
if(iter->mTime < time)
continue;
Nif::FloatKeyList::VecType::const_iterator last(iter-1);
float a = (time-last->mTime) / (iter->mTime-last->mTime);
return last->mValue + ((iter->mValue - last->mValue)*a);
}
return keys.back().mValue;
}
public:
Value(Ogre::SubEntity *subent, const Nif::NiMorphData *data)
: mSubEntity(subent)
@ -504,7 +622,7 @@ class NIFObjectLoader
static void createEntity(const std::string &name, const std::string &group,
Ogre::SceneManager *sceneMgr, ObjectList &objectlist,
Ogre::SceneManager *sceneMgr, ObjectScenePtr scene,
const Nif::Node *node, int flags, int animflags)
{
const Nif::NiTriShape *shape = static_cast<const Nif::NiTriShape*>(node);
@ -521,16 +639,16 @@ class NIFObjectLoader
Ogre::Entity *entity = sceneMgr->createEntity(fullname);
entity->setVisible(!(flags&Nif::NiNode::Flag_Hidden));
objectlist.mEntities.push_back(entity);
if(objectlist.mSkelBase)
scene->mEntities.push_back(entity);
if(scene->mSkelBase)
{
if(entity->hasSkeleton())
entity->shareSkeletonInstanceWith(objectlist.mSkelBase);
entity->shareSkeletonInstanceWith(scene->mSkelBase);
else
{
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, shape->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
objectlist.mSkelBase->attachObjectToBone(trgtbone->getName(), entity);
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
scene->mSkelBase->attachObjectToBone(trgtbone->getName(), entity);
}
}
@ -541,17 +659,16 @@ class NIFObjectLoader
{
const Nif::NiUVController *uv = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
const Ogre::MaterialPtr &material = entity->getSubEntity(0)->getMaterial();
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr()));
Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(entity, uv->data.getPtr(), &scene->mMaterialControllerMgr));
UVController::Function* function = OGRE_NEW UVController::Function(uv, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
else if(ctrl->recType == Nif::RC_NiGeomMorpherController)
{
@ -563,15 +680,81 @@ class NIFObjectLoader
Ogre::ControllerValueRealPtr dstval(OGRE_NEW GeomMorpherController::Value(entity->getSubEntity(0), geom->data.getPtr()));
GeomMorpherController::Function* function = OGRE_NEW GeomMorpherController::Function(geom, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
ctrl = ctrl->next;
}
createMaterialControllers(shape, entity, animflags, scene);
}
static void createMaterialControllers (const Nif::Node* node, Ogre::MovableObject* movable, int animflags, ObjectScenePtr scene)
{
const Nif::NiTexturingProperty *texprop = NULL;
const Nif::NiMaterialProperty *matprop = NULL;
const Nif::NiAlphaProperty *alphaprop = NULL;
const Nif::NiVertexColorProperty *vertprop = NULL;
const Nif::NiZBufferProperty *zprop = NULL;
const Nif::NiSpecularProperty *specprop = NULL;
const Nif::NiWireframeProperty *wireprop = NULL;
node->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop);
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
if(matprop)
{
Nif::ControllerPtr ctrls = matprop->controller;
while(!ctrls.empty())
{
if (ctrls->recType == Nif::RC_NiAlphaController)
{
const Nif::NiAlphaController *alphaCtrl = dynamic_cast<const Nif::NiAlphaController*>(ctrls.getPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW AlphaController::Value(movable, alphaCtrl->data.getPtr(), &scene->mMaterialControllerMgr));
AlphaController::Function* function = OGRE_NEW AlphaController::Function(alphaCtrl, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
else if (ctrls->recType == Nif::RC_NiMaterialColorController)
{
const Nif::NiMaterialColorController *matCtrl = dynamic_cast<const Nif::NiMaterialColorController*>(ctrls.getPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW MaterialColorController::Value(movable, matCtrl->data.getPtr(), &scene->mMaterialControllerMgr));
AlphaController::Function* function = OGRE_NEW AlphaController::Function(matCtrl, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
ctrls = ctrls->next;
}
}
if (texprop)
{
Nif::ControllerPtr ctrls = texprop->controller;
while(!ctrls.empty())
{
if (ctrls->recType == Nif::RC_NiFlipController)
{
const Nif::NiFlipController *flipCtrl = dynamic_cast<const Nif::NiFlipController*>(ctrls.getPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW FlipController::Value(
movable, flipCtrl, &scene->mMaterialControllerMgr));
FlipController::Function* function = OGRE_NEW FlipController::Function(flipCtrl, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
ctrls = ctrls->next;
}
}
}
static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys,
const Nif::NiParticleSystemController *partctrl, Ogre::Bone* bone,
@ -647,8 +830,8 @@ class NIFObjectLoader
}
static void createParticleSystem(const std::string &name, const std::string &group,
Ogre::SceneNode *sceneNode, ObjectList &objectlist,
const Nif::Node *partnode, int flags, int partflags)
Ogre::SceneNode *sceneNode, ObjectScenePtr scene,
const Nif::Node *partnode, int flags, int partflags, int animflags)
{
const Nif::NiAutoNormalParticlesData *particledata = NULL;
if(partnode->recType == Nif::RC_NiAutoNormalParticles)
@ -696,8 +879,8 @@ class NIFObjectLoader
if(!partctrl->emitter.empty())
{
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partctrl->emitter->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
createParticleEmitterAffectors(partsys, partctrl, trgtbone, objectlist.mSkelBase->getName());
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
createParticleEmitterAffectors(partsys, partctrl, trgtbone, scene->mSkelBase->getName());
}
Ogre::ControllerValueRealPtr srcval((partflags&Nif::NiNode::ParticleFlag_AutoPlay) ?
@ -707,20 +890,22 @@ class NIFObjectLoader
ParticleSystemController::Function* function =
OGRE_NEW ParticleSystemController::Function(partctrl, (partflags&Nif::NiNode::ParticleFlag_AutoPlay));
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
ctrl = ctrl->next;
}
partsys->setVisible(!(flags&Nif::NiNode::Flag_Hidden));
objectlist.mParticles.push_back(partsys);
scene->mParticles.push_back(partsys);
createMaterialControllers(partnode, partsys, animflags, scene);
}
static void createNodeControllers(const std::string &name, Nif::ControllerPtr ctrl, ObjectList &objectlist, int animflags)
static void createNodeControllers(const std::string &name, Nif::ControllerPtr ctrl, ObjectScenePtr scene, int animflags)
{
do {
if(ctrl->recType == Nif::RC_NiVisController)
@ -728,17 +913,17 @@ class NIFObjectLoader
const Nif::NiVisController *vis = static_cast<const Nif::NiVisController*>(ctrl.getPtr());
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW VisController::Value(trgtbone, vis->data.getPtr()));
VisController::Function* function = OGRE_NEW VisController::Function(vis, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
else if(ctrl->recType == Nif::RC_NiKeyframeController)
{
@ -746,16 +931,16 @@ class NIFObjectLoader
if(!key->data.empty())
{
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex);
Ogre::Bone *trgtbone = objectlist.mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ?
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
Ogre::ControllerValueRealPtr());
Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, key->data.getPtr()));
KeyframeController::Function* function = OGRE_NEW KeyframeController::Function(key, (animflags&Nif::NiNode::AnimFlag_AutoPlay));
objectlist.mMaxControllerLength = std::max(function->mStopTime, objectlist.mMaxControllerLength);
scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength);
Ogre::ControllerFunctionRealPtr func(function);
objectlist.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
scene->mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
}
}
ctrl = ctrl->next;
@ -804,7 +989,7 @@ class NIFObjectLoader
static void createObjects(const std::string &name, const std::string &group,
Ogre::SceneNode *sceneNode, const Nif::Node *node,
ObjectList &objectlist, int flags, int animflags, int partflags)
ObjectScenePtr scene, int flags, int animflags, int partflags)
{
// Do not create objects for the collision shape (includes all children)
if(node->recType == Nif::RC_RootCollisionNode)
@ -830,7 +1015,7 @@ class NIFObjectLoader
const Nif::NiTextKeyExtraData *tk = static_cast<const Nif::NiTextKeyExtraData*>(e.getPtr());
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex);
extractTextKeys(tk, objectlist.mTextKeys[trgtid]);
extractTextKeys(tk, scene->mTextKeys[trgtid]);
}
else if(e->recType == Nif::RC_NiStringExtraData)
{
@ -849,7 +1034,7 @@ class NIFObjectLoader
}
if(!node->controller.empty() && (node->parent || node->recType != Nif::RC_NiNode))
createNodeControllers(name, node->controller, objectlist, animflags);
createNodeControllers(name, node->controller, scene, animflags);
if(node->recType == Nif::RC_NiCamera)
{
@ -858,13 +1043,13 @@ class NIFObjectLoader
if(node->recType == Nif::RC_NiTriShape && !(flags&0x80000000))
{
createEntity(name, group, sceneNode->getCreator(), objectlist, node, flags, animflags);
createEntity(name, group, sceneNode->getCreator(), scene, node, flags, animflags);
}
if((node->recType == Nif::RC_NiAutoNormalParticles ||
node->recType == Nif::RC_NiRotatingParticles) && !(flags&0x40000000))
{
createParticleSystem(name, group, sceneNode, objectlist, node, flags, partflags);
createParticleSystem(name, group, sceneNode, scene, node, flags, partflags, animflags);
}
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
@ -874,14 +1059,14 @@ class NIFObjectLoader
for(size_t i = 0;i < children.length();i++)
{
if(!children[i].empty())
createObjects(name, group, sceneNode, children[i].getPtr(), objectlist, flags, animflags, partflags);
createObjects(name, group, sceneNode, children[i].getPtr(), scene, flags, animflags, partflags);
}
}
}
static void createSkelBase(const std::string &name, const std::string &group,
Ogre::SceneManager *sceneMgr, const Nif::Node *node,
ObjectList &objectlist)
ObjectScenePtr scene)
{
/* This creates an empty mesh to which a skeleton gets attached. This
* is to ensure we have an entity with a skeleton instance, even if all
@ -890,12 +1075,12 @@ class NIFObjectLoader
if(meshMgr.getByName(name).isNull())
NIFMeshLoader::createMesh(name, name, group, ~(size_t)0);
objectlist.mSkelBase = sceneMgr->createEntity(name);
objectlist.mEntities.push_back(objectlist.mSkelBase);
scene->mSkelBase = sceneMgr->createEntity(name);
scene->mEntities.push_back(scene->mSkelBase);
}
public:
static void load(Ogre::SceneNode *sceneNode, ObjectList &objectlist, const std::string &name, const std::string &group, int flags=0)
static void load(Ogre::SceneNode *sceneNode, ObjectScenePtr scene, const std::string &name, const std::string &group, int flags=0)
{
Nif::NIFFile::ptr nif = Nif::NIFFile::create(name);
if(nif->numRoots() < 1)
@ -919,9 +1104,9 @@ public:
!NIFSkeletonLoader::createSkeleton(name, group, node).isNull())
{
// Create a base skeleton entity if this NIF needs one
createSkelBase(name, group, sceneNode->getCreator(), node, objectlist);
createSkelBase(name, group, sceneNode->getCreator(), node, scene);
}
createObjects(name, group, sceneNode, node, objectlist, flags, 0, 0);
createObjects(name, group, sceneNode, node, scene, flags, 0, 0);
}
static void loadKf(Ogre::Skeleton *skel, const std::string &name,
@ -984,37 +1169,37 @@ public:
};
ObjectList Loader::createObjects(Ogre::SceneNode *parentNode, std::string name, const std::string &group)
ObjectScenePtr Loader::createObjects(Ogre::SceneNode *parentNode, std::string name, const std::string &group)
{
ObjectList objectlist;
ObjectScenePtr scene = ObjectScenePtr (new ObjectScene(parentNode->getCreator()));;
Misc::StringUtils::toLower(name);
NIFObjectLoader::load(parentNode, objectlist, name, group);
NIFObjectLoader::load(parentNode, scene, name, group);
for(size_t i = 0;i < objectlist.mEntities.size();i++)
for(size_t i = 0;i < scene->mEntities.size();i++)
{
Ogre::Entity *entity = objectlist.mEntities[i];
Ogre::Entity *entity = scene->mEntities[i];
if(!entity->isAttached())
parentNode->attachObject(entity);
}
return objectlist;
return scene;
}
ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonename,
ObjectScenePtr Loader::createObjects(Ogre::Entity *parent, const std::string &bonename,
Ogre::SceneNode *parentNode,
std::string name, const std::string &group)
{
ObjectList objectlist;
ObjectScenePtr scene = ObjectScenePtr (new ObjectScene(parentNode->getCreator()));
Misc::StringUtils::toLower(name);
NIFObjectLoader::load(parentNode, objectlist, name, group);
NIFObjectLoader::load(parentNode, scene, name, group);
bool isskinned = false;
for(size_t i = 0;i < objectlist.mEntities.size();i++)
for(size_t i = 0;i < scene->mEntities.size();i++)
{
Ogre::Entity *ent = objectlist.mEntities[i];
if(objectlist.mSkelBase != ent && ent->hasSkeleton())
Ogre::Entity *ent = scene->mEntities[i];
if(scene->mSkelBase != ent && ent->hasSkeleton())
{
isskinned = true;
break;
@ -1029,12 +1214,12 @@ ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonena
{
std::string filter = "@shape=tri "+bonename;
Misc::StringUtils::toLower(filter);
for(size_t i = 0;i < objectlist.mEntities.size();i++)
for(size_t i = 0;i < scene->mEntities.size();i++)
{
Ogre::Entity *entity = objectlist.mEntities[i];
Ogre::Entity *entity = scene->mEntities[i];
if(entity->hasSkeleton())
{
if(entity == objectlist.mSkelBase ||
if(entity == scene->mSkelBase ||
entity->getMesh()->getName().find(filter) != std::string::npos)
parentNode->attachObject(entity);
}
@ -1047,9 +1232,9 @@ ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonena
}
else
{
for(size_t i = 0;i < objectlist.mEntities.size();i++)
for(size_t i = 0;i < scene->mEntities.size();i++)
{
Ogre::Entity *entity = objectlist.mEntities[i];
Ogre::Entity *entity = scene->mEntities[i];
if(!entity->isAttached())
{
Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entity);
@ -1058,32 +1243,32 @@ ObjectList Loader::createObjects(Ogre::Entity *parent, const std::string &bonena
}
}
for(size_t i = 0;i < objectlist.mParticles.size();i++)
for(size_t i = 0;i < scene->mParticles.size();i++)
{
Ogre::ParticleSystem *partsys = objectlist.mParticles[i];
Ogre::ParticleSystem *partsys = scene->mParticles[i];
if(partsys->isAttached())
partsys->detachFromParent();
Ogre::TagPoint *tag = objectlist.mSkelBase->attachObjectToBone(
objectlist.mSkelBase->getSkeleton()->getRootBone()->getName(), partsys);
Ogre::TagPoint *tag = scene->mSkelBase->attachObjectToBone(
scene->mSkelBase->getSkeleton()->getRootBone()->getName(), partsys);
tag->setScale(scale);
}
return objectlist;
return scene;
}
ObjectList Loader::createObjectBase(Ogre::SceneNode *parentNode, std::string name, const std::string &group)
ObjectScenePtr Loader::createObjectBase(Ogre::SceneNode *parentNode, std::string name, const std::string &group)
{
ObjectList objectlist;
ObjectScenePtr scene = ObjectScenePtr (new ObjectScene(parentNode->getCreator()));
Misc::StringUtils::toLower(name);
NIFObjectLoader::load(parentNode, objectlist, name, group, 0xC0000000);
NIFObjectLoader::load(parentNode, scene, name, group, 0xC0000000);
if(objectlist.mSkelBase)
parentNode->attachObject(objectlist.mSkelBase);
if(scene->mSkelBase)
parentNode->attachObject(scene->mSkelBase);
return objectlist;
return scene;
}

@ -25,6 +25,7 @@
#define OPENMW_COMPONENTS_NIFOGRE_OGRENIFLOADER_HPP
#include <OgreResource.h>
#include <OgreMaterial.h>
#include <OgreController.h>
#include <vector>
@ -37,39 +38,60 @@
namespace NifOgre
{
/**
* @brief Clones materials as necessary to not make controllers affect other objects (that share the original material).
*/
class MaterialControllerManager
{
public:
~MaterialControllerManager();
Ogre::MaterialPtr getWritableMaterial (Ogre::MovableObject* movable);
private:
std::map<Ogre::MovableObject*, Ogre::MaterialPtr> mClonedMaterials;
};
typedef std::multimap<float,std::string> TextKeyMap;
static const char sTextKeyExtraDataID[] = "TextKeyExtraData";
struct ObjectList {
struct ObjectScene {
Ogre::Entity *mSkelBase;
std::vector<Ogre::Entity*> mEntities;
std::vector<Ogre::ParticleSystem*> mParticles;
std::vector<Ogre::Light*> mLights;
Ogre::SceneManager* mSceneMgr;
// The maximum length on any of the controllers. For animations with controllers, but no text keys, consider this the animation length.
float mMaxControllerLength;
std::map<int,TextKeyMap> mTextKeys;
MaterialControllerManager mMaterialControllerMgr;
std::vector<Ogre::Controller<Ogre::Real> > mControllers;
ObjectList() : mSkelBase(0), mMaxControllerLength(0)
ObjectScene(Ogre::SceneManager* sceneMgr) : mSkelBase(0), mMaxControllerLength(0), mSceneMgr(sceneMgr)
{ }
~ObjectScene();
};
typedef Ogre::SharedPtr<ObjectScene> ObjectScenePtr;
class Loader
{
public:
static ObjectList createObjects(Ogre::Entity *parent, const std::string &bonename,
static ObjectScenePtr createObjects(Ogre::Entity *parent, const std::string &bonename,
Ogre::SceneNode *parentNode,
std::string name,
const std::string &group="General");
static ObjectList createObjects(Ogre::SceneNode *parentNode,
static ObjectScenePtr createObjects(Ogre::SceneNode *parentNode,
std::string name,
const std::string &group="General");
static ObjectList createObjectBase(Ogre::SceneNode *parentNode,
static ObjectScenePtr createObjectBase(Ogre::SceneNode *parentNode,
std::string name,
const std::string &group="General");

@ -98,9 +98,7 @@
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
#endif
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour)
#endif
#if VERTEXCOLOR_MODE != 1
shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour)
#endif
@ -234,9 +232,7 @@
lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz;
#endif
#if VERTEXCOLOR_MODE != 2
lightResult.a *= materialDiffuse.a;
#endif
#endif
}
@ -339,9 +335,7 @@
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
#endif
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour)
#endif
#if VERTEXCOLOR_MODE != 1
shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour)
#endif
@ -434,9 +428,7 @@
lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz;
#endif
#if VERTEXCOLOR_MODE != 2
lightResult.a *= materialDiffuse.a;
#endif
#endif
// shadows only for the first (directional) light

Loading…
Cancel
Save