mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 22:56:40 +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++) | ||||
|         mEntityList.mControllers[i].setSource(ctrlval); | ||||
|     { | ||||
|         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