mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:23:52 +00:00
Add support for NiUVController on meshes
This commit is contained in:
parent
e0da265972
commit
59f1d4b047
2 changed files with 123 additions and 2 deletions
|
@ -133,7 +133,10 @@ void Animation::createEntityList(Ogre::SceneNode *node, const std::string &model
|
|||
|
||||
Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this));
|
||||
for(size_t i = 0;i < mEntityList.mControllers.size();i++)
|
||||
{
|
||||
if(mEntityList.mControllers[i].getSource().isNull())
|
||||
mEntityList.mControllers[i].setSource(ctrlval);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <OgreParticleSystem.h>
|
||||
#include <OgreParticleEmitter.h>
|
||||
#include <OgreParticleAffector.h>
|
||||
#include <OgreControllerManager.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
@ -139,6 +140,105 @@ public:
|
|||
};
|
||||
};
|
||||
|
||||
class UVController
|
||||
{
|
||||
public:
|
||||
class Value : public Ogre::ControllerValue<Ogre::Real>
|
||||
{
|
||||
private:
|
||||
Ogre::MaterialPtr mMaterial;
|
||||
Nif::FloatKeyList mUTrans;
|
||||
Nif::FloatKeyList mVTrans;
|
||||
Nif::FloatKeyList mUScale;
|
||||
Nif::FloatKeyList mVScale;
|
||||
|
||||
static float lookupValue(float time, const Nif::FloatKeyList &keys)
|
||||
{
|
||||
Nif::FloatKeyList::VecType::const_iterator iter(keys.mKeys.begin());
|
||||
for(;iter != keys.mKeys.end();iter++)
|
||||
{
|
||||
if(iter->mTime > time)
|
||||
continue;
|
||||
Nif::FloatKeyList::VecType::const_iterator next(iter+1);
|
||||
if(next == keys.mKeys.end())
|
||||
return iter->mValue;
|
||||
float a = (time-iter->mTime) / (next->mTime-iter->mTime);
|
||||
return iter->mValue + ((next->mValue - iter->mValue)*a);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
public:
|
||||
Value(const Ogre::MaterialPtr &material, Nif::NiUVData *data)
|
||||
: mMaterial(material)
|
||||
, mUTrans(data->mKeyList[0])
|
||||
, mVTrans(data->mKeyList[1])
|
||||
, mUScale(data->mKeyList[2])
|
||||
, mVScale(data->mKeyList[3])
|
||||
{ }
|
||||
|
||||
virtual Ogre::Real getValue() const
|
||||
{
|
||||
// Should not be called
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
virtual void setValue(Ogre::Real value)
|
||||
{
|
||||
float uTrans = lookupValue(value, mUTrans);
|
||||
float vTrans = lookupValue(value, mVTrans);
|
||||
float uScale = lookupValue(value, mUScale);
|
||||
float vScale = lookupValue(value, mVScale);
|
||||
if(uScale == 0.0f) uScale = 1.0f;
|
||||
if(vScale == 0.0f) vScale = 1.0f;
|
||||
|
||||
Ogre::Material::TechniqueIterator techs = mMaterial->getTechniqueIterator();
|
||||
while(techs.hasMoreElements())
|
||||
{
|
||||
Ogre::Technique *tech = techs.getNext();
|
||||
Ogre::Technique::PassIterator passes = tech->getPassIterator();
|
||||
while(passes.hasMoreElements())
|
||||
{
|
||||
Ogre::Pass *pass = passes.getNext();
|
||||
Ogre::TextureUnitState *tex = pass->getTextureUnitState(0);
|
||||
tex->setTextureScroll(uTrans, vTrans);
|
||||
tex->setTextureScale(uScale, vScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class Function : public Ogre::ControllerFunction<Ogre::Real>
|
||||
{
|
||||
private:
|
||||
float mFrequency;
|
||||
float mPhase;
|
||||
float mStartTime;
|
||||
float mStopTime;
|
||||
|
||||
public:
|
||||
Function(const Nif::NiUVController *ctrl)
|
||||
: Ogre::ControllerFunction<Ogre::Real>(false)
|
||||
, mFrequency(ctrl->frequency)
|
||||
, mPhase(ctrl->phase)
|
||||
, mStartTime(ctrl->timeStart)
|
||||
, mStopTime(ctrl->timeStop)
|
||||
{
|
||||
mDeltaCount = mPhase;
|
||||
while(mDeltaCount < mStartTime)
|
||||
mDeltaCount += (mStopTime-mStartTime);
|
||||
}
|
||||
|
||||
virtual Ogre::Real calculate(Ogre::Real value)
|
||||
{
|
||||
mDeltaCount += value;
|
||||
mDeltaCount = std::fmod(mDeltaCount+(value*mFrequency) - mStartTime,
|
||||
mStopTime - mStartTime) + mStartTime;
|
||||
return mDeltaCount;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// Helper class that computes the bounding box and of a mesh
|
||||
class BoundsFinder
|
||||
|
@ -409,7 +509,8 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro
|
|||
if(ctrl->recType == Nif::RC_NiKeyframeController)
|
||||
ctrls.push_back(static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr()));
|
||||
else if(!(ctrl->recType == Nif::RC_NiParticleSystemController ||
|
||||
ctrl->recType == Nif::RC_NiVisController
|
||||
ctrl->recType == Nif::RC_NiVisController ||
|
||||
ctrl->recType == Nif::RC_NiUVController
|
||||
))
|
||||
warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName());
|
||||
ctrl = ctrl->next;
|
||||
|
@ -1429,6 +1530,23 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
|
|||
entities.mSkelBase->attachObjectToBone(trgtbone->getName(), entity);
|
||||
}
|
||||
}
|
||||
|
||||
Nif::ControllerPtr ctrl = node->controller;
|
||||
while(!ctrl.empty())
|
||||
{
|
||||
if(ctrl->recType == Nif::RC_NiUVController)
|
||||
{
|
||||
const Nif::NiUVController *uv = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
||||
|
||||
const Ogre::MaterialPtr &material = entity->getSubEntity(0)->getMaterial();
|
||||
Ogre::ControllerValueRealPtr srcval(Ogre::ControllerManager::getSingleton().getFrameTimeSource());
|
||||
Ogre::ControllerValueRealPtr dstval(OGRE_NEW UVController::Value(material, uv->data.getPtr()));
|
||||
Ogre::ControllerFunctionRealPtr func(OGRE_NEW UVController::Function(uv));
|
||||
|
||||
entities.mControllers.push_back(Ogre::Controller<Ogre::Real>(srcval, dstval, func));
|
||||
}
|
||||
ctrl = ctrl->next;
|
||||
}
|
||||
}
|
||||
|
||||
if(node->recType == Nif::RC_NiAutoNormalParticles ||
|
||||
|
|
Loading…
Reference in a new issue