diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index e0ddeb254..48de580bc 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -50,10 +50,6 @@ add_component_dir (nifosg # nifcache # ) -#add_component_dir (nifogre -# ogrenifloader skeleton material mesh particles controller -# ) - #add_component_dir (nifbullet # bulletnifloader # ) diff --git a/components/nifogre/controller.hpp b/components/nifogre/controller.hpp deleted file mode 100644 index cc750ea65..000000000 --- a/components/nifogre/controller.hpp +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef COMPONENTS_NIFOGRE_CONTROLLER_H -#define COMPONENTS_NIFOGRE_CONTROLLER_H - -#include -#include -#include - -namespace NifOgre -{ - - class ValueInterpolator - { - protected: - float interpKey(const Nif::FloatKeyMap::MapType &keys, float time, float def=0.f) const - { - if (keys.size() == 0) - return def; - - if(time <= keys.begin()->first) - return keys.begin()->second.mValue; - - Nif::FloatKeyMap::MapType::const_iterator it = keys.lower_bound(time); - if (it != keys.end()) - { - float aTime = it->first; - const Nif::FloatKey* aKey = &it->second; - - assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function - - Nif::FloatKeyMap::MapType::const_iterator last = --it; - float aLastTime = last->first; - const Nif::FloatKey* aLastKey = &last->second; - - float a = (time - aLastTime) / (aTime - aLastTime); - return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a); - } - else - return keys.rbegin()->second.mValue; - } - - Ogre::Vector3 interpKey(const Nif::Vector3KeyMap::MapType &keys, float time) const - { - if(time <= keys.begin()->first) - return keys.begin()->second.mValue; - - Nif::Vector3KeyMap::MapType::const_iterator it = keys.lower_bound(time); - if (it != keys.end()) - { - float aTime = it->first; - const Nif::Vector3Key* aKey = &it->second; - - assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function - - Nif::Vector3KeyMap::MapType::const_iterator last = --it; - float aLastTime = last->first; - const Nif::Vector3Key* aLastKey = &last->second; - - float a = (time - aLastTime) / (aTime - aLastTime); - return aLastKey->mValue + ((aKey->mValue - aLastKey->mValue) * a); - } - else - return keys.rbegin()->second.mValue; - } - }; - - // FIXME: Should not be here. - class DefaultFunction : public Ogre::ControllerFunction - { - private: - float mFrequency; - float mPhase; - float mStartTime; - public: - float mStopTime; - - public: - DefaultFunction(const Nif::Controller *ctrl, bool deltaInput) - : Ogre::ControllerFunction(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) - { - if (mStopTime - mStartTime == 0.f) - return 0.f; - - 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 diff --git a/components/nifogre/material.cpp b/components/nifogre/material.cpp deleted file mode 100644 index 90930bca8..000000000 --- a/components/nifogre/material.cpp +++ /dev/null @@ -1,442 +0,0 @@ -#include "material.hpp" - -#include -#include -#include -#include - -#include - -#include -#include - -#include - - -namespace NifOgre -{ - -// Conversion of blend / test mode from NIF -static const char *getBlendFactor(int mode) -{ - switch(mode) - { - case 0: return "one"; - case 1: return "zero"; - case 2: return "src_colour"; - case 3: return "one_minus_src_colour"; - case 4: return "dest_colour"; - case 5: return "one_minus_dest_colour"; - case 6: return "src_alpha"; - case 7: return "one_minus_src_alpha"; - case 8: return "dest_alpha"; - case 9: return "one_minus_dest_alpha"; - case 10: return "src_alpha_saturate"; - } - std::cerr<< "Unexpected blend mode: "<setProperty(textureSlotName + "UVSet", sh::makeProperty(new sh::IntValue(tex.uvSet))); - const std::string clampMode = textureSlotName + "ClampMode"; - switch (tex.clamp) - { - case 0: - material->setProperty(clampMode, sh::makeProperty(new sh::StringValue("clamp clamp"))); - break; - case 1: - material->setProperty(clampMode, sh::makeProperty(new sh::StringValue("clamp wrap"))); - break; - case 2: - material->setProperty(clampMode, sh::makeProperty(new sh::StringValue("wrap clamp"))); - break; - case 3: - default: - material->setProperty(clampMode, sh::makeProperty(new sh::StringValue("wrap wrap"))); - break; - } -} - -Ogre::String NIFMaterialLoader::getMaterial(const Nif::ShapeData *shapedata, - const Ogre::String &name, const Ogre::String &group, - const Nif::NiTexturingProperty *texprop, - const Nif::NiMaterialProperty *matprop, - const Nif::NiAlphaProperty *alphaprop, - const Nif::NiVertexColorProperty *vertprop, - const Nif::NiZBufferProperty *zprop, - const Nif::NiSpecularProperty *specprop, - const Nif::NiWireframeProperty *wireprop, - const Nif::NiStencilProperty *stencilprop, - bool &needTangents, bool particleMaterial) -{ - Ogre::MaterialManager &matMgr = Ogre::MaterialManager::getSingleton(); - Ogre::MaterialPtr material = matMgr.getByName(name); - if(!material.isNull()) - return name; - - Ogre::Vector3 ambient(1.0f); - Ogre::Vector3 diffuse(1.0f); - Ogre::Vector3 specular(0.0f); - Ogre::Vector3 emissive(0.0f); - float glossiness = 0.0f; - float alpha = 1.0f; - int alphaFlags = 0; - int alphaTest = 0; - int vertMode = 2; - //int lightMode = 1; - int depthFlags = 3; - // Default should be 1, but Bloodmoon's models are broken - int specFlags = 0; - int wireFlags = 0; - int drawMode = 1; - Ogre::String texName[7]; - - bool vertexColour = (shapedata->colors.size() != 0); - - // Texture - if(texprop) - { - for(int i = 0;i < 7;i++) - { - if(!texprop->textures[i].inUse) - continue; - if(texprop->textures[i].texture.empty()) - { - warn("Texture layer "+Ogre::StringConverter::toString(i)+" is in use but empty in "+name); - continue; - } - - const Nif::NiSourceTexture *st = texprop->textures[i].texture.getPtr(); - if(st->external) - texName[i] = Misc::ResourceHelpers::correctTexturePath(st->filename); - else - warn("Found internal texture, ignoring."); - } - - Nif::ControllerPtr ctrls = texprop->controller; - while(!ctrls.empty()) - { - if (ctrls->recType != Nif::RC_NiFlipController) // Handled in ogrenifloader - warn("Unhandled texture controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - // Alpha modifiers - if(alphaprop) - { - alphaFlags = alphaprop->flags; - alphaTest = alphaprop->data.threshold; - - Nif::ControllerPtr ctrls = alphaprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled alpha controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - // Vertex color handling - if(vertprop) - { - vertMode = vertprop->data.vertmode; - // FIXME: Handle lightmode? - //lightMode = vertprop->data.lightmode; - - Nif::ControllerPtr ctrls = vertprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled vertex color controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if(zprop) - { - depthFlags = zprop->flags; - // Depth function??? - - Nif::ControllerPtr ctrls = zprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled depth controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if(specprop) - { - specFlags = specprop->flags; - - Nif::ControllerPtr ctrls = specprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled specular controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if(wireprop) - { - wireFlags = wireprop->flags; - - Nif::ControllerPtr ctrls = wireprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled wireframe controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if(stencilprop) - { - drawMode = stencilprop->data.drawMode; - if (stencilprop->data.enabled) - warn("Unhandled stencil test in "+name); - - Nif::ControllerPtr ctrls = stencilprop->controller; - while(!ctrls.empty()) - { - warn("Unhandled stencil controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - // Material - if(matprop) - { - ambient = matprop->data.ambient; - diffuse = matprop->data.diffuse; - specular = matprop->data.specular; - emissive = matprop->data.emissive; - glossiness = matprop->data.glossiness; - alpha = matprop->data.alpha; - - Nif::ControllerPtr ctrls = matprop->controller; - while(!ctrls.empty()) - { - if (ctrls->recType != Nif::RC_NiAlphaController && ctrls->recType != Nif::RC_NiMaterialColorController) - warn("Unhandled material controller "+ctrls->recName+" in "+name); - ctrls = ctrls->next; - } - } - - if (particleMaterial) - { - alpha = 1.f; // Apparently ignored, might be overridden by particle vertex colors? - } - - { - // Generate a hash out of all properties that can affect the material. - size_t h = 0; - boost::hash_combine(h, ambient.x); - boost::hash_combine(h, ambient.y); - boost::hash_combine(h, ambient.z); - boost::hash_combine(h, diffuse.x); - boost::hash_combine(h, diffuse.y); - boost::hash_combine(h, diffuse.z); - boost::hash_combine(h, alpha); - boost::hash_combine(h, specular.x); - boost::hash_combine(h, specular.y); - boost::hash_combine(h, specular.z); - boost::hash_combine(h, glossiness); - boost::hash_combine(h, emissive.x); - boost::hash_combine(h, emissive.y); - boost::hash_combine(h, emissive.z); - for(int i = 0;i < 7;i++) - { - if(!texName[i].empty()) - { - boost::hash_combine(h, texName[i]); - boost::hash_combine(h, texprop->textures[i].clamp); - boost::hash_combine(h, texprop->textures[i].uvSet); - } - } - boost::hash_combine(h, drawMode); - boost::hash_combine(h, vertexColour); - boost::hash_combine(h, alphaFlags); - boost::hash_combine(h, alphaTest); - boost::hash_combine(h, vertMode); - boost::hash_combine(h, depthFlags); - boost::hash_combine(h, specFlags); - boost::hash_combine(h, wireFlags); - - std::map::iterator itr = sMaterialMap.find(h); - if (itr != sMaterialMap.end()) - { - // a suitable material exists already - use it - sh::MaterialInstance* instance = sh::Factory::getInstance().getMaterialInstance(itr->second); - needTangents = !sh::retrieveValue(instance->getProperty("normalMap"), instance).get().empty(); - return itr->second; - } - // not found, create a new one - sMaterialMap.insert(std::make_pair(h, name)); - } - - // No existing material like this. Create a new one. - sh::MaterialInstance *instance = sh::Factory::getInstance().createMaterialInstance(name, "openmw_objects_base"); - if(vertMode == 0 || !vertexColour) - { - instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); - instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); - instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); - instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("0"))); - } - else if(vertMode == 1) - { - instance->setProperty("ambient", sh::makeProperty(new sh::Vector4(ambient.x, ambient.y, ambient.z, 1))); - instance->setProperty("diffuse", sh::makeProperty(new sh::Vector4(diffuse.x, diffuse.y, diffuse.z, alpha))); - instance->setProperty("emissive", sh::makeProperty(new sh::StringValue("vertexcolour"))); - instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("1"))); - } - else if(vertMode == 2) - { - instance->setProperty("ambient", sh::makeProperty(new sh::StringValue("vertexcolour"))); - instance->setProperty("diffuse", sh::makeProperty(new sh::StringValue("vertexcolour"))); - instance->setProperty("emissive", sh::makeProperty(new sh::Vector4(emissive.x, emissive.y, emissive.z, 1))); - instance->setProperty("vertmode", sh::makeProperty(new sh::StringValue("2"))); - } - else - std::cerr<< "Unhandled vertex mode: "<setProperty("specular", sh::makeProperty( - new sh::Vector4(specular.x, specular.y, specular.z, glossiness))); - } - - if(wireFlags) - { - instance->setProperty("polygon_mode", sh::makeProperty(new sh::StringValue("wireframe"))); - } - - if (drawMode == 1) - instance->setProperty("cullmode", sh::makeProperty(new sh::StringValue("clockwise"))); - else if (drawMode == 2) - instance->setProperty("cullmode", sh::makeProperty(new sh::StringValue("anticlockwise"))); - else if (drawMode == 3) - instance->setProperty("cullmode", sh::makeProperty(new sh::StringValue("none"))); - - instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture])); - instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture])); - instance->setProperty("detailMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DetailTexture])); - instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture])); - instance->setProperty("darkMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DarkTexture])); - if (!texName[Nif::NiTexturingProperty::BaseTexture].empty()) - { - instance->setProperty("use_diffuse_map", sh::makeProperty(new sh::BooleanValue(true))); - setTextureProperties(instance, "diffuseMap", texprop->textures[Nif::NiTexturingProperty::BaseTexture]); - } - if (!texName[Nif::NiTexturingProperty::GlowTexture].empty()) - { - instance->setProperty("use_emissive_map", sh::makeProperty(new sh::BooleanValue(true))); - setTextureProperties(instance, "emissiveMap", texprop->textures[Nif::NiTexturingProperty::GlowTexture]); - } - if (!texName[Nif::NiTexturingProperty::DetailTexture].empty()) - { - instance->setProperty("use_detail_map", sh::makeProperty(new sh::BooleanValue(true))); - setTextureProperties(instance, "detailMap", texprop->textures[Nif::NiTexturingProperty::DetailTexture]); - } - if (!texName[Nif::NiTexturingProperty::DarkTexture].empty()) - { - instance->setProperty("use_dark_map", sh::makeProperty(new sh::BooleanValue(true))); - setTextureProperties(instance, "darkMap", texprop->textures[Nif::NiTexturingProperty::DarkTexture]); - } - - bool useParallax = !texName[Nif::NiTexturingProperty::BumpTexture].empty() - && texName[Nif::NiTexturingProperty::BumpTexture].find("_nh.") != std::string::npos; - instance->setProperty("use_parallax", sh::makeProperty(new sh::BooleanValue(useParallax))); - - for(int i = 0;i < 7;i++) - { - if(i == Nif::NiTexturingProperty::BaseTexture || - i == Nif::NiTexturingProperty::DetailTexture || - i == Nif::NiTexturingProperty::DarkTexture || - i == Nif::NiTexturingProperty::BumpTexture || - i == Nif::NiTexturingProperty::GlowTexture) - continue; - if(!texName[i].empty()) - warn("Ignored texture "+texName[i]+" on layer "+Ogre::StringConverter::toString(i) + " in " + name); - } - - if (vertexColour) - instance->setProperty("has_vertex_colour", sh::makeProperty(new sh::BooleanValue(true))); - - // Override alpha flags based on our override list (transparency-overrides.cfg) - if ((alphaFlags&1) && !texName[0].empty()) - { - NifOverrides::TransparencyResult result = NifOverrides::Overrides::getTransparencyOverride(texName[0]); - if (result.first) - { - alphaFlags = (1<<9) | (6<<10); /* alpha_rejection enabled, greater_equal */ - alphaTest = result.second; - depthFlags = (1<<0) | (1<<1); // depth_write on, depth_check on - } - } - - // Add transparency if NiAlphaProperty was present - if((alphaFlags&1)) - { - std::string blend_mode; - blend_mode += getBlendFactor((alphaFlags>>1)&0xf); - blend_mode += " "; - blend_mode += getBlendFactor((alphaFlags>>5)&0xf); - instance->setProperty("scene_blend", sh::makeProperty(new sh::StringValue(blend_mode))); - } - - if((alphaFlags>>9)&1) - { -#ifndef ANDROID - std::string reject; - reject += getTestMode((alphaFlags>>10)&0x7); - reject += " "; - reject += Ogre::StringConverter::toString(alphaTest); - instance->setProperty("alpha_rejection", sh::makeProperty(new sh::StringValue(reject))); -#else - // alpha test not supported in OpenGL ES 2, use manual implementation in shader - instance->setProperty("alphaTestMode", sh::makeProperty(new sh::IntValue((alphaFlags>>10)&0x7))); - instance->setProperty("alphaTestValue", sh::makeProperty(new sh::FloatValue(alphaTest/255.f))); -#endif - } - else - instance->getMaterial()->setShadowCasterMaterial("openmw_shadowcaster_noalpha"); - - // Ogre usually only sorts if depth write is disabled, so we want "force" instead of "on" - instance->setProperty("transparent_sorting", sh::makeProperty(new sh::StringValue( - ((alphaFlags&1) && !((alphaFlags>>13)&1)) ? "force" : "off"))); - - instance->setProperty("depth_check", sh::makeProperty(new sh::StringValue((depthFlags&1) ? "on" : "off"))); - instance->setProperty("depth_write", sh::makeProperty(new sh::StringValue(((depthFlags>>1)&1) ? "on" : "off"))); - // depth_func??? - - if (!texName[0].empty()) - NifOverrides::Overrides::getMaterialOverrides(texName[0], instance); - - // Don't use texName, as it may be overridden - needTangents = !sh::retrieveValue(instance->getProperty("normalMap"), instance).get().empty(); - - return name; -} - -std::map NIFMaterialLoader::sMaterialMap; - -} diff --git a/components/nifogre/material.hpp b/components/nifogre/material.hpp deleted file mode 100644 index 6be52d1a5..000000000 --- a/components/nifogre/material.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef COMPONENTS_NIFOGRE_MATERIAL_HPP -#define COMPONENTS_NIFOGRE_MATERIAL_HPP - -#include -#include -#include -#include - -#include - -namespace Nif -{ - class ShapeData; - class NiTexturingProperty; - class NiMaterialProperty; - class NiAlphaProperty; - class NiVertexColorProperty; - class NiZBufferProperty; - class NiSpecularProperty; - class NiWireframeProperty; - class NiStencilProperty; -} - -namespace NifOgre -{ - -class NIFMaterialLoader { - static void warn(const std::string &msg) - { - std::cerr << "NIFMaterialLoader: Warn: " << msg << std::endl; - } - - static std::map sMaterialMap; - -public: - static Ogre::String getMaterial(const Nif::ShapeData *shapedata, - const Ogre::String &name, const Ogre::String &group, - const Nif::NiTexturingProperty *texprop, - const Nif::NiMaterialProperty *matprop, - const Nif::NiAlphaProperty *alphaprop, - const Nif::NiVertexColorProperty *vertprop, - const Nif::NiZBufferProperty *zprop, - const Nif::NiSpecularProperty *specprop, - const Nif::NiWireframeProperty *wireprop, - const Nif::NiStencilProperty *stencilprop, - bool &needTangents, bool particleMaterial=false); -}; - -} - -#endif diff --git a/components/nifogre/mesh.cpp b/components/nifogre/mesh.cpp deleted file mode 100644 index 85c3a7b65..000000000 --- a/components/nifogre/mesh.cpp +++ /dev/null @@ -1,412 +0,0 @@ -#include "mesh.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "material.hpp" - -namespace NifOgre -{ - -// Helper class that computes the bounding box and of a mesh -class BoundsFinder -{ - struct MaxMinFinder - { - float max, min; - - MaxMinFinder() - { - min = std::numeric_limits::infinity(); - max = -min; - } - - void add(float f) - { - if (f > max) max = f; - if (f < min) min = f; - } - - // Return Max(max**2, min**2) - float getMaxSquared() - { - float m1 = max*max; - float m2 = min*min; - if (m1 >= m2) return m1; - return m2; - } - }; - - MaxMinFinder X, Y, Z; - -public: - // Add 'verts' vertices to the calculation. The 'data' pointer is - // expected to point to 3*verts floats representing x,y,z for each - // point. - void add(float *data, int verts) - { - for (int i=0;idata.getPtr(); - const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); - std::vector srcVerts = data->vertices; - std::vector srcNorms = data->normals; - Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC; - bool vertShadowBuffer = false; - - if(skin != NULL) - { - vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY; - vertShadowBuffer = true; - - // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be - // explicitly attached later. - mesh->setSkeletonName(mName); - - // Convert vertices and normals to bone space from bind position. It would be - // better to transform the bones into bind position, but there doesn't seem to - // be a reliable way to do that. - std::vector newVerts(srcVerts.size(), Ogre::Vector3(0.0f)); - std::vector newNorms(srcNorms.size(), Ogre::Vector3(0.0f)); - - const Nif::NiSkinData *data = skin->data.getPtr(); - const Nif::NodeList &bones = skin->bones; - for(size_t b = 0;b < bones.length();b++) - { - Ogre::Matrix4 mat; - mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), - Ogre::Quaternion(data->bones[b].trafo.rotation)); - mat = bones[b]->getWorldTransform() * mat; - - const std::vector &weights = data->bones[b].weights; - for(size_t i = 0;i < weights.size();i++) - { - size_t index = weights[i].vertex; - float weight = weights[i].weight; - - newVerts.at(index) += (mat*srcVerts[index]) * weight; - if(newNorms.size() > index) - { - Ogre::Vector4 vec4(srcNorms[index][0], srcNorms[index][1], srcNorms[index][2], 0.0f); - vec4 = mat*vec4 * weight; - newNorms[index] += Ogre::Vector3(&vec4[0]); - } - } - } - - srcVerts = newVerts; - srcNorms = newNorms; - } - else - { - Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); - if(skelMgr->getByName(mName).isNull()) - { - // No skinning and no skeleton, so just transform the vertices and - // normals into position. - Ogre::Matrix4 mat4 = shape->getWorldTransform(); - for(size_t i = 0;i < srcVerts.size();i++) - { - Ogre::Vector4 vec4(srcVerts[i].x, srcVerts[i].y, srcVerts[i].z, 1.0f); - vec4 = mat4*vec4; - srcVerts[i] = Ogre::Vector3(&vec4[0]); - } - for(size_t i = 0;i < srcNorms.size();i++) - { - Ogre::Vector4 vec4(srcNorms[i].x, srcNorms[i].y, srcNorms[i].z, 0.0f); - vec4 = mat4*vec4; - srcNorms[i] = Ogre::Vector3(&vec4[0]); - } - } - } - - // Set the bounding box first - BoundsFinder bounds; - bounds.add(&srcVerts[0][0], srcVerts.size()); - if(!bounds.isValid()) - { - float v[3] = { 0.0f, 0.0f, 0.0f }; - bounds.add(&v[0], 1); - } - - mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX()-0.5f, bounds.minY()-0.5f, bounds.minZ()-0.5f, - bounds.maxX()+0.5f, bounds.maxY()+0.5f, bounds.maxZ()+0.5f)); - mesh->_setBoundingSphereRadius(bounds.getRadius()); - - // This function is just one long stream of Ogre-barf, but it works - // great. - Ogre::HardwareBufferManager *hwBufMgr = Ogre::HardwareBufferManager::getSingletonPtr(); - Ogre::HardwareVertexBufferSharedPtr vbuf; - Ogre::HardwareIndexBufferSharedPtr ibuf; - Ogre::VertexBufferBinding *bind; - Ogre::VertexDeclaration *decl; - int nextBuf = 0; - - Ogre::SubMesh *sub = mesh->createSubMesh(); - - // Add vertices - sub->useSharedVertices = false; - sub->vertexData = new Ogre::VertexData(); - sub->vertexData->vertexStart = 0; - sub->vertexData->vertexCount = srcVerts.size(); - - decl = sub->vertexData->vertexDeclaration; - bind = sub->vertexData->vertexBufferBinding; - if(srcVerts.size()) - { - vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - srcVerts.size(), vertUsage, vertShadowBuffer); - vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true); - - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); - bind->setBinding(nextBuf++, vbuf); - } - - // Vertex normals - if(srcNorms.size()) - { - vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), - srcNorms.size(), vertUsage, vertShadowBuffer); - vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true); - - decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); - bind->setBinding(nextBuf++, vbuf); - } - - // Vertex colors - const std::vector &colors = data->colors; - if(colors.size()) - { - Ogre::RenderSystem *rs = Ogre::Root::getSingleton().getRenderSystem(); - std::vector colorsRGB(colors.size()); - for(size_t i = 0;i < colorsRGB.size();i++) - { - Ogre::ColourValue clr(colors[i][0], colors[i][1], colors[i][2], colors[i][3]); - rs->convertColourValue(clr, &colorsRGB[i]); - } - vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), - colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC); - vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true); - decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); - bind->setBinding(nextBuf++, vbuf); - } - - // Texture UV coordinates - size_t numUVs = data->uvlist.size(); - if (numUVs) - { - size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); - - for(size_t i = 0; i < numUVs; i++) - decl->addElement(nextBuf, elemSize*i, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i); - - vbuf = hwBufMgr->createVertexBuffer(decl->getVertexSize(nextBuf), srcVerts.size(), - Ogre::HardwareBuffer::HBU_STATIC); - - std::vector allUVs; - allUVs.reserve(srcVerts.size()*numUVs); - for (size_t vert = 0; vertuvlist[i][vert]); - - vbuf->writeData(0, elemSize*srcVerts.size()*numUVs, &allUVs[0], true); - - bind->setBinding(nextBuf++, vbuf); - } - - // Triangle faces - const std::vector &srcIdx = data->triangles; - if(srcIdx.size()) - { - ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(), - Ogre::HardwareBuffer::HBU_STATIC); - ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true); - sub->indexData->indexBuffer = ibuf; - sub->indexData->indexCount = srcIdx.size(); - sub->indexData->indexStart = 0; - } - - // Assign bone weights for this TriShape - if(skin != NULL) - { - Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(mName); - - const Nif::NiSkinData *data = skin->data.getPtr(); - const Nif::NodeList &bones = skin->bones; - for(size_t i = 0;i < bones.length();i++) - { - Ogre::VertexBoneAssignment boneInf; - boneInf.boneIndex = skel->getBone(bones[i]->name)->getHandle(); - - const std::vector &weights = data->bones[i].weights; - for(size_t j = 0;j < weights.size();j++) - { - boneInf.vertexIndex = weights[j].vertex; - boneInf.weight = weights[j].weight; - sub->addBoneAssignment(boneInf); - } - } - } - - 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; - const Nif::NiStencilProperty *stencilprop = NULL; - bool needTangents = false; - - shape->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop, stencilprop); - std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, - texprop, matprop, alphaprop, - vertprop, zprop, specprop, - wireprop, stencilprop, needTangents); - if(matname.length() > 0) - sub->setMaterialName(matname); - - // build tangents if the material needs them - if (needTangents) - { - unsigned short src,dest; - if (!mesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src,dest)) - mesh->buildTangentVectors(Ogre::VES_TANGENT, src,dest); - } - - - if(!shape->controller.empty()) - { - Nif::ControllerPtr ctrl = shape->controller; - do { - // Load GeomMorpherController into an Ogre::Pose and Animation - if(ctrl->recType == Nif::RC_NiGeomMorpherController && ctrl->flags & Nif::NiNode::ControllerFlag_Active) - { - const Nif::NiGeomMorpherController *geom = - static_cast(ctrl.getPtr()); - - const std::vector& morphs = geom->data.getPtr()->mMorphs; - // Note we are not interested in morph 0, which just contains the original vertices - for (unsigned int i = 1; i < morphs.size(); ++i) - { - Ogre::Pose* pose = mesh->createPose(i); - const Nif::NiMorphData::MorphData& data = morphs[i]; - for (unsigned int v = 0; v < data.mVertices.size(); ++v) - pose->addVertex(v, data.mVertices[v]); - - Ogre::String animationID = Ogre::StringConverter::toString(ctrl->recIndex) - + "_" + Ogre::StringConverter::toString(i); - Ogre::VertexAnimationTrack* track = - mesh->createAnimation(animationID, 0) - ->createVertexTrack(1, Ogre::VAT_POSE); - Ogre::VertexPoseKeyFrame* keyframe = track->createVertexPoseKeyFrame(0); - keyframe->addPoseReference(i-1, 1); - } - - break; - } - } while(!(ctrl=ctrl->next).empty()); - } -} - - -NIFMeshLoader::NIFMeshLoader(const std::string &name, const std::string &group, size_t idx) - : mName(name), mGroup(group), mShapeIndex(idx) -{ -} - -void NIFMeshLoader::loadResource(Ogre::Resource *resource) -{ - Ogre::Mesh *mesh = static_cast(resource); - OgreAssert(mesh, "Attempting to load a mesh into a non-mesh resource!"); - - Nif::NIFFilePtr nif = Nif::Cache::getInstance().load(mName); - if(mShapeIndex >= nif->numRecords()) - { - Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); - if(!skelMgr->getByName(mName).isNull()) - mesh->setSkeletonName(mName); - return; - } - - const Nif::Record *record = nif->getRecord(mShapeIndex); - createSubMesh(mesh, static_cast(record)); -} - - -void NIFMeshLoader::createMesh(const std::string &name, const std::string &fullname, const std::string &group, size_t idx) -{ - NIFMeshLoader::LoaderMap::iterator loader; - loader = sLoaders.insert(std::make_pair(fullname, NIFMeshLoader(name, group, idx))).first; - - Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - Ogre::MeshPtr mesh = meshMgr.createManual(fullname, group, &loader->second); - mesh->setAutoBuildEdgeLists(false); -} - -} diff --git a/components/nifogre/mesh.hpp b/components/nifogre/mesh.hpp deleted file mode 100644 index 731e49c90..000000000 --- a/components/nifogre/mesh.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef COMPONENTS_NIFOGRE_MESH_HPP -#define COMPONENTS_NIFOGRE_MESH_HPP - -#include -#include -#include -#include - -#include - -namespace Nif -{ - class NiTriShape; -} - -namespace NifOgre -{ - -/** Manual resource loader for NiTriShapes. This is the main class responsible - * for translating the internal NIF meshes into something Ogre can use. - */ -class NIFMeshLoader : Ogre::ManualResourceLoader -{ - static void warn(const std::string &msg) - { - std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl; - } - - static void fail(const std::string &msg) - { - std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl; - abort(); - } - - std::string mName; - std::string mGroup; - size_t mShapeIndex; - - // Convert NiTriShape to Ogre::SubMesh - void createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape); - - typedef std::map LoaderMap; - static LoaderMap sLoaders; - - NIFMeshLoader(const std::string &name, const std::string &group, size_t idx); - - virtual void loadResource(Ogre::Resource *resource); - -public: - static void createMesh(const std::string &name, const std::string &fullname, const std::string &group, size_t idx); -}; - -} - -#endif diff --git a/components/nifogre/ogrenifloader.cpp b/components/nifogre/ogrenifloader.cpp deleted file mode 100644 index 17df7a3cd..000000000 --- a/components/nifogre/ogrenifloader.cpp +++ /dev/null @@ -1,1492 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2010 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ - - This file (ogre_nif_loader.cpp) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -#include "ogrenifloader.hpp" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include "skeleton.hpp" -#include "material.hpp" -#include "mesh.hpp" -#include "controller.hpp" -#include "particles.hpp" - -namespace -{ - - void getAllNiNodes(const Nif::Node* node, std::vector& out) - { - const Nif::NiNode* ninode = dynamic_cast(node); - if (ninode) - { - out.push_back(ninode); - for (unsigned int i=0; ichildren.length(); ++i) - if (!ninode->children[i].empty()) - getAllNiNodes(ninode->children[i].getPtr(), out); - } - } - -} - -namespace NifOgre -{ - -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(movable)) - mat = ent->getSubEntity(0)->getMaterial(); - else if (Ogre::ParticleSystem* partSys = dynamic_cast(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(movable)) - ent->getSubEntity(0)->setMaterial(mat); - else if (Ogre::ParticleSystem* partSys = dynamic_cast(movable)) - partSys->setMaterialName(mat->getName()); - - return mat; - } -} - -MaterialControllerManager::~MaterialControllerManager() -{ - for (std::map::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; -} - -void ObjectScene::setVisibilityFlags (unsigned int flags) -{ - for (std::vector::iterator iter (mEntities.begin()); iter!=mEntities.end(); - ++iter) - (*iter)->setVisibilityFlags (flags); - - for (std::vector::iterator iter (mParticles.begin()); - iter!=mParticles.end(); ++iter) - (*iter)->setVisibilityFlags (flags); - - for (std::vector::iterator iter (mLights.begin()); iter!=mLights.end(); - ++iter) - (*iter)->setVisibilityFlags (flags); -} - -void ObjectScene::rotateBillboardNodes(Ogre::Camera *camera) -{ - for (std::vector::iterator it = mBillboardNodes.begin(); it != mBillboardNodes.end(); ++it) - { - assert(mSkelBase); - Ogre::Node* node = *it; - node->_setDerivedOrientation(mSkelBase->getParentNode()->_getDerivedOrientation().Inverse() * - camera->getRealOrientation()); - } -} - -void ObjectScene::_notifyAttached() -{ - // convert initial particle positions to world space for world-space particle systems - // this can't be done on creation because the particle system is not in its correct world space position yet - for (std::vector::iterator it = mParticles.begin(); it != mParticles.end(); ++it) - { - Ogre::ParticleSystem* psys = *it; - if (psys->getKeepParticlesInLocalSpace()) - continue; - Ogre::ParticleIterator pi = psys->_getIterator(); - while (!pi.end()) - { - Ogre::Particle *p = pi.getNext(); - -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - Ogre::Vector3& position = p->mPosition; - Ogre::Vector3& direction = p->mDirection; -#else - Ogre::Vector3& position = p->position; - Ogre::Vector3& direction = p->direction; -#endif - - position = - (psys->getParentNode()->_getDerivedOrientation() * - (psys->getParentNode()->_getDerivedScale() * position)) - + psys->getParentNode()->_getDerivedPosition(); - direction = - (psys->getParentNode()->_getDerivedOrientation() * direction); - } - } -} - -// Animates a texture -class FlipController -{ -public: - class Value : public Ogre::ControllerValue - { - private: - Ogre::MovableObject* mMovable; - int mTexSlot; - float mDelta; - std::vector 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; imSources.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(Misc::ResourceHelpers::correctTexturePath(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() == "darkMap" && mTexSlot == Nif::NiTexturingProperty::DarkTexture) - || (texture->getName() == "emissiveMap" && mTexSlot == Nif::NiTexturingProperty::GlowTexture)) - texture->setTextureName(mTextures[curTexture]); - } - } - } - } - }; - - typedef DefaultFunction Function; -}; - -class AlphaController -{ -public: - class Value : public Ogre::ControllerValue, public ValueInterpolator - { - private: - Ogre::MovableObject* mMovable; - Nif::FloatKeyMap 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; -}; - -class MaterialColorController -{ -public: - class Value : public Ogre::ControllerValue, public ValueInterpolator - { - private: - Ogre::MovableObject* mMovable; - Nif::Vector3KeyMap mData; - MaterialControllerManager* mMaterialControllerMgr; - - public: - Value(Ogre::MovableObject *movable, const Nif::NiPosData *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) - { - 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 -{ -public: - class Value : public NodeTargetValue - { - private: - std::vector mData; - - bool calculate(Ogre::Real time) const - { - if(mData.size() == 0) - return true; - - for(size_t i = 1;i < mData.size();i++) - { - if(mData[i].time > time) - return mData[i-1].isSet; - } - return mData.back().isSet; - } - - static void setVisible(Ogre::Node *node, int vis) - { - // Skinned meshes are attached to the scene node, not the bone. - // We use the Node's user data to connect it with the mesh. - Ogre::Any customData = node->getUserObjectBindings().getUserAny(); - - if (!customData.isEmpty()) - Ogre::any_cast(customData)->setVisible(vis); - - Ogre::TagPoint *tag = dynamic_cast(node); - if(tag != NULL) - { - Ogre::MovableObject *obj = tag->getChildObject(); - if(obj != NULL) - obj->setVisible(vis); - } - - Ogre::Node::ChildNodeIterator iter = node->getChildIterator(); - while(iter.hasMoreElements()) - { - node = iter.getNext(); - setVisible(node, vis); - } - } - - public: - Value(Ogre::Node *target, const Nif::NiVisData *data) - : NodeTargetValue(target) - , mData(data->mVis) - { } - - virtual Ogre::Quaternion getRotation(float time) const - { return Ogre::Quaternion(); } - - virtual Ogre::Vector3 getTranslation(float time) const - { return Ogre::Vector3(0.0f); } - - virtual Ogre::Vector3 getScale(float time) const - { return Ogre::Vector3(1.0f); } - - virtual Ogre::Real getValue() const - { - // Should not be called - return 0.0f; - } - - virtual void setValue(Ogre::Real time) - { - bool vis = calculate(time); - setVisible(mNode, vis); - } - }; - - typedef DefaultFunction Function; -}; - -class KeyframeController -{ -public: - class Value : public NodeTargetValue, public ValueInterpolator - { - private: - const Nif::QuaternionKeyMap* mRotations; - const Nif::FloatKeyMap* mXRotations; - const Nif::FloatKeyMap* mYRotations; - const Nif::FloatKeyMap* mZRotations; - const Nif::Vector3KeyMap* mTranslations; - const Nif::FloatKeyMap* mScales; - Nif::NIFFilePtr mNif; // Hold a SharedPtr to make sure key lists stay valid - - using ValueInterpolator::interpKey; - - static Ogre::Quaternion interpKey(const Nif::QuaternionKeyMap::MapType &keys, float time) - { - if(time <= keys.begin()->first) - return keys.begin()->second.mValue; - - Nif::QuaternionKeyMap::MapType::const_iterator it = keys.lower_bound(time); - if (it != keys.end()) - { - float aTime = it->first; - const Nif::QuaternionKey* aKey = &it->second; - - assert (it != keys.begin()); // Shouldn't happen, was checked at beginning of this function - - Nif::QuaternionKeyMap::MapType::const_iterator last = --it; - float aLastTime = last->first; - const Nif::QuaternionKey* aLastKey = &last->second; - - float a = (time - aLastTime) / (aTime - aLastTime); - return Ogre::Quaternion::nlerp(a, aLastKey->mValue, aKey->mValue); - } - else - return keys.rbegin()->second.mValue; - } - - Ogre::Quaternion getXYZRotation(float time) const - { - float xrot = interpKey(mXRotations->mKeys, time); - float yrot = interpKey(mYRotations->mKeys, time); - float zrot = interpKey(mZRotations->mKeys, time); - Ogre::Quaternion xr(Ogre::Radian(xrot), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yr(Ogre::Radian(yrot), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zr(Ogre::Radian(zrot), Ogre::Vector3::UNIT_Z); - return (zr*yr*xr); - } - - public: - /// @note The NiKeyFrameData must be valid as long as this KeyframeController exists. - Value(Ogre::Node *target, const Nif::NIFFilePtr& nif, const Nif::NiKeyframeData *data) - : NodeTargetValue(target) - , mRotations(&data->mRotations) - , mXRotations(&data->mXRotations) - , mYRotations(&data->mYRotations) - , mZRotations(&data->mZRotations) - , mTranslations(&data->mTranslations) - , mScales(&data->mScales) - , mNif(nif) - { } - - virtual Ogre::Quaternion getRotation(float time) const - { - if(mRotations->mKeys.size() > 0) - return interpKey(mRotations->mKeys, time); - else if (!mXRotations->mKeys.empty() || !mYRotations->mKeys.empty() || !mZRotations->mKeys.empty()) - return getXYZRotation(time); - return mNode->getOrientation(); - } - - virtual Ogre::Vector3 getTranslation(float time) const - { - if(mTranslations->mKeys.size() > 0) - return interpKey(mTranslations->mKeys, time); - return mNode->getPosition(); - } - - virtual Ogre::Vector3 getScale(float time) const - { - if(mScales->mKeys.size() > 0) - return Ogre::Vector3(interpKey(mScales->mKeys, time)); - return mNode->getScale(); - } - - virtual Ogre::Real getValue() const - { - // Should not be called - return 0.0f; - } - - virtual void setValue(Ogre::Real time) - { - if(mRotations->mKeys.size() > 0) - mNode->setOrientation(interpKey(mRotations->mKeys, time)); - else if (!mXRotations->mKeys.empty() || !mYRotations->mKeys.empty() || !mZRotations->mKeys.empty()) - mNode->setOrientation(getXYZRotation(time)); - if(mTranslations->mKeys.size() > 0) - mNode->setPosition(interpKey(mTranslations->mKeys, time)); - if(mScales->mKeys.size() > 0) - mNode->setScale(Ogre::Vector3(interpKey(mScales->mKeys, time))); - } - }; - - typedef DefaultFunction Function; -}; - -class UVController -{ -public: - class Value : public Ogre::ControllerValue, public ValueInterpolator - { - private: - Ogre::MovableObject* mMovable; - Nif::FloatKeyMap mUTrans; - Nif::FloatKeyMap mVTrans; - Nif::FloatKeyMap mUScale; - Nif::FloatKeyMap mVScale; - MaterialControllerManager* mMaterialControllerMgr; - - public: - 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 - { - // Should not be called - return 1.0f; - } - - virtual void setValue(Ogre::Real value) - { - 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 = material->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); - } - } - } - }; - - typedef DefaultFunction Function; -}; - -class ParticleSystemController -{ -public: - class Value : public Ogre::ControllerValue - { - private: - Ogre::ParticleSystem *mParticleSys; - float mEmitStart; - float mEmitStop; - - public: - Value(Ogre::ParticleSystem *psys, const Nif::NiParticleSystemController *pctrl) - : mParticleSys(psys) - , mEmitStart(pctrl->startTime) - , mEmitStop(pctrl->stopTime) - { - } - - Ogre::Real getValue() const - { return 0.0f; } - - void setValue(Ogre::Real value) - { - mParticleSys->setEmitting(value >= mEmitStart && value < mEmitStop); - } - }; - - typedef DefaultFunction Function; -}; - -class GeomMorpherController -{ -public: - class Value : public Ogre::ControllerValue, public ValueInterpolator - { - private: - Ogre::Entity *mEntity; - std::vector mMorphs; - size_t mControllerIndex; - - std::vector mVertices; - - public: - Value(Ogre::Entity *ent, const Nif::NiMorphData *data, size_t controllerIndex) - : mEntity(ent) - , mMorphs(data->mMorphs) - , mControllerIndex(controllerIndex) - { - } - - virtual Ogre::Real getValue() const - { - // Should not be called - return 0.0f; - } - - virtual void setValue(Ogre::Real time) - { - if (mMorphs.size() <= 1) - return; - int i = 1; - for (std::vector::iterator it = mMorphs.begin()+1; it != mMorphs.end(); ++it,++i) - { - float val = 0; - if (!it->mData.mKeys.empty()) - val = interpKey(it->mData.mKeys, time); - val = std::max(0.f, std::min(1.f, val)); - - Ogre::String animationID = Ogre::StringConverter::toString(mControllerIndex) - + "_" + Ogre::StringConverter::toString(i); - - Ogre::AnimationState* state = mEntity->getAnimationState(animationID); - state->setEnabled(val > 0); - state->setWeight(val); - } - } - }; - - typedef DefaultFunction Function; -}; - - -/** Object creator for NIFs. This is the main class responsible for creating - * "live" Ogre objects (entities, particle systems, controllers, etc) from - * their NIF equivalents. - */ -class NIFObjectLoader -{ - static bool sShowMarkers; -public: - static void setShowMarkers(bool show) - { - sShowMarkers = show; - } -private: - - static void warn(const std::string &msg) - { - std::cerr << "NIFObjectLoader: Warn: " << msg << std::endl; - } - - static void createEntity(const std::string &name, const std::string &group, - Ogre::SceneManager *sceneMgr, ObjectScenePtr scene, - const Nif::Node *node, int flags, int animflags) - { - const Nif::NiTriShape *shape = static_cast(node); - - std::string fullname = name+"@index="+Ogre::StringConverter::toString(shape->recIndex); - if(shape->name.length() > 0) - fullname += "@shape="+shape->name; - Misc::StringUtils::toLower(fullname); - - Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - if(meshMgr.getByName(fullname).isNull()) - NIFMeshLoader::createMesh(name, fullname, group, shape->recIndex); - - Ogre::Entity *entity = sceneMgr->createEntity(fullname); - -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - // Enable skeleton-based bounding boxes. With the static bounding box, - // the animation may cause parts to go outside the box and cause culling problems. - if (entity->hasSkeleton()) - entity->setUpdateBoundingBoxFromSkeleton(true); -#endif - - entity->setVisible(!(flags&Nif::NiNode::Flag_Hidden)); - - scene->mEntities.push_back(entity); - if(scene->mSkelBase) - { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, shape->recIndex); - Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid); - trgtbone->getUserObjectBindings().setUserAny(Ogre::Any(static_cast(entity))); - - if(entity->hasSkeleton()) - entity->shareSkeletonInstanceWith(scene->mSkelBase); - else - scene->mSkelBase->attachObjectToBone(trgtbone->getName(), entity); - } - - Nif::ControllerPtr ctrl = node->controller; - while(!ctrl.empty()) - { - if (ctrl->flags & Nif::NiNode::ControllerFlag_Active) - { - if(ctrl->recType == Nif::RC_NiUVController) - { - const Nif::NiUVController *uv = static_cast(ctrl.getPtr()); - - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? - Ogre::ControllerManager::getSingleton().getFrameTimeSource() : - Ogre::ControllerValueRealPtr()); - 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)); - scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); - Ogre::ControllerFunctionRealPtr func(function); - - scene->mControllers.push_back(Ogre::Controller(srcval, dstval, func)); - } - else if(ctrl->recType == Nif::RC_NiGeomMorpherController) - { - const Nif::NiGeomMorpherController *geom = static_cast(ctrl.getPtr()); - - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? - Ogre::ControllerManager::getSingleton().getFrameTimeSource() : - Ogre::ControllerValueRealPtr()); - Ogre::ControllerValueRealPtr dstval(OGRE_NEW GeomMorpherController::Value( - entity, geom->data.getPtr(), geom->recIndex)); - - GeomMorpherController::Function* function = OGRE_NEW GeomMorpherController::Function(geom, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); - scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); - Ogre::ControllerFunctionRealPtr func(function); - - scene->mControllers.push_back(Ogre::Controller(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; - const Nif::NiStencilProperty *stencilprop = NULL; - node->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop, stencilprop); - - 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 = static_cast(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(srcval, dstval, func)); - } - else if (ctrls->recType == Nif::RC_NiMaterialColorController) - { - const Nif::NiMaterialColorController *matCtrl = static_cast(ctrls.getPtr()); - Ogre::ControllerValueRealPtr dstval(OGRE_NEW MaterialColorController::Value(movable, matCtrl->data.getPtr(), &scene->mMaterialControllerMgr)); - MaterialColorController::Function* function = OGRE_NEW MaterialColorController::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(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 = static_cast(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(srcval, dstval, func)); - } - - ctrls = ctrls->next; - } - } - } - - static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, - const Nif::NiParticleSystemController *partctrl, Ogre::Bone* bone, - const std::string& skelBaseName) - { - Ogre::ParticleEmitter *emitter = partsys->addEmitter("Nif"); - emitter->setParticleVelocity(partctrl->velocity - partctrl->velocityRandom*0.5f, - partctrl->velocity + partctrl->velocityRandom*0.5f); - - if (partctrl->emitFlags & Nif::NiParticleSystemController::NoAutoAdjust) - emitter->setEmissionRate(partctrl->emitRate); - else - emitter->setEmissionRate(partctrl->numParticles / (partctrl->lifetime + partctrl->lifetimeRandom/2)); - - emitter->setTimeToLive(std::max(0.f, partctrl->lifetime), - std::max(0.f, partctrl->lifetime + partctrl->lifetimeRandom)); - emitter->setParameter("width", Ogre::StringConverter::toString(partctrl->offsetRandom.x)); - emitter->setParameter("height", Ogre::StringConverter::toString(partctrl->offsetRandom.y)); - emitter->setParameter("depth", Ogre::StringConverter::toString(partctrl->offsetRandom.z)); - emitter->setParameter("vertical_direction", Ogre::StringConverter::toString(Ogre::Radian(partctrl->verticalDir).valueDegrees())); - emitter->setParameter("vertical_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->verticalAngle).valueDegrees())); - emitter->setParameter("horizontal_direction", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalDir).valueDegrees())); - emitter->setParameter("horizontal_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalAngle).valueDegrees())); - - Nif::ExtraPtr e = partctrl->extra; - while(!e.empty()) - { - if(e->recType == Nif::RC_NiParticleGrowFade) - { - const Nif::NiParticleGrowFade *gf = static_cast(e.getPtr()); - - Ogre::ParticleAffector *affector = partsys->addAffector("GrowFade"); - affector->setParameter("grow_time", Ogre::StringConverter::toString(gf->growTime)); - affector->setParameter("fade_time", Ogre::StringConverter::toString(gf->fadeTime)); - } - else if(e->recType == Nif::RC_NiGravity) - { - const Nif::NiGravity *gr = static_cast(e.getPtr()); - - Ogre::ParticleAffector *affector = partsys->addAffector("Gravity"); - affector->setParameter("force", Ogre::StringConverter::toString(gr->mForce)); - affector->setParameter("force_type", (gr->mType==0) ? "wind" : "point"); - affector->setParameter("direction", Ogre::StringConverter::toString(gr->mDirection)); - affector->setParameter("position", Ogre::StringConverter::toString(gr->mPosition)); - affector->setParameter("skelbase", skelBaseName); - affector->setParameter("bone", bone->getName()); - } - else if(e->recType == Nif::RC_NiParticleColorModifier) - { - const Nif::NiParticleColorModifier *cl = static_cast(e.getPtr()); - const Nif::NiColorData *clrdata = cl->data.getPtr(); - - Ogre::ParticleAffector *affector = partsys->addAffector("ColourInterpolator"); - size_t num_colors = std::min(6, clrdata->mKeyMap.mKeys.size()); - unsigned int i=0; - for (Nif::Vector4KeyMap::MapType::const_iterator it = clrdata->mKeyMap.mKeys.begin(); it != clrdata->mKeyMap.mKeys.end() && i < num_colors; ++it,++i) - { - Ogre::ColourValue color; - color.r = it->second.mValue[0]; - color.g = it->second.mValue[1]; - color.b = it->second.mValue[2]; - color.a = it->second.mValue[3]; - affector->setParameter("colour"+Ogre::StringConverter::toString(i), - Ogre::StringConverter::toString(color)); - affector->setParameter("time"+Ogre::StringConverter::toString(i), - Ogre::StringConverter::toString(it->first)); - } - } - else if(e->recType == Nif::RC_NiParticleRotation) - { - // TODO: Implement (Ogre::RotationAffector?) - } - else - warn("Unhandled particle modifier "+e->recName); - e = e->extra; - } - } - - static void createParticleSystem(const std::string &name, const std::string &group, - 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) - particledata = static_cast(partnode)->data.getPtr(); - else if(partnode->recType == Nif::RC_NiRotatingParticles) - particledata = static_cast(partnode)->data.getPtr(); - else - throw std::runtime_error("Unexpected particle node type"); - - std::string fullname = name+"@index="+Ogre::StringConverter::toString(partnode->recIndex); - if(partnode->name.length() > 0) - fullname += "@type="+partnode->name; - Misc::StringUtils::toLower(fullname); - - Ogre::ParticleSystem *partsys = sceneNode->getCreator()->createParticleSystem(); - - 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; - const Nif::NiStencilProperty *stencilprop = NULL; - bool needTangents = false; - - partnode->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop, stencilprop); - partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, group, - texprop, matprop, alphaprop, - vertprop, zprop, specprop, - wireprop, stencilprop, needTangents, - // MW doesn't light particles, but the MaterialProperty - // used still has lighting, so that must be ignored. - true)); - - partsys->setCullIndividually(false); - partsys->setParticleQuota(particledata->numParticles); - partsys->setKeepParticlesInLocalSpace(partflags & (Nif::NiNode::ParticleFlag_LocalSpace)); - - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partnode->recIndex); - Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid); - scene->mSkelBase->attachObjectToBone(trgtbone->getName(), partsys); - - Nif::ControllerPtr ctrl = partnode->controller; - while(!ctrl.empty()) - { - if((ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController) - && ctrl->flags & Nif::NiNode::ControllerFlag_Active) - { - const Nif::NiParticleSystemController *partctrl = static_cast(ctrl.getPtr()); - - float size = partctrl->size*2; - // HACK: don't allow zero-sized particles which can rarely cause an AABB assertion in Ogre to fail - size = std::max(size, 0.00001f); - partsys->setDefaultDimensions(size, size); - - if(!partctrl->emitter.empty()) - { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partctrl->emitter->recIndex); - Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid); - // Set the emitter bone(s) as user data on the particle system - // so the emitters/affectors can access it easily. - std::vector bones; - if (partctrl->recType == Nif::RC_NiBSPArrayController) - { - std::vector nodes; - getAllNiNodes(partctrl->emitter.getPtr(), nodes); - if (nodes.empty()) - throw std::runtime_error("Emitter for NiBSPArrayController must be a NiNode"); - for (unsigned int i=0; imSkelBase->getSkeleton()->getBone( - NIFSkeletonLoader::lookupOgreBoneHandle(name, nodes[i]->recIndex))); - } - } - else - { - bones.push_back(trgtbone); - } - NiNodeHolder holder; - holder.mBones = bones; - partsys->getUserObjectBindings().setUserAny(Ogre::Any(holder)); - createParticleEmitterAffectors(partsys, partctrl, trgtbone, scene->mSkelBase->getName()); - } - - createParticleInitialState(partsys, particledata, partctrl); - - Ogre::ControllerValueRealPtr srcval((partflags&Nif::NiNode::ParticleFlag_AutoPlay) ? - Ogre::ControllerManager::getSingleton().getFrameTimeSource() : - Ogre::ControllerValueRealPtr()); - Ogre::ControllerValueRealPtr dstval(OGRE_NEW ParticleSystemController::Value(partsys, partctrl)); - - ParticleSystemController::Function* function = - OGRE_NEW ParticleSystemController::Function(partctrl, (partflags&Nif::NiNode::ParticleFlag_AutoPlay)); - scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); - Ogre::ControllerFunctionRealPtr func(function); - - scene->mControllers.push_back(Ogre::Controller(srcval, dstval, func)); - - // Emitting state will be overwritten on frame update by the ParticleSystemController, - // but set up an initial value anyway so the user can fast-forward particle systems - // immediately after creation if desired. - partsys->setEmitting(partflags&Nif::NiNode::ParticleFlag_AutoPlay); - } - ctrl = ctrl->next; - } - - partsys->setVisible(!(flags&Nif::NiNode::Flag_Hidden)); - scene->mParticles.push_back(partsys); - - createMaterialControllers(partnode, partsys, animflags, scene); - } - - static void createParticleInitialState(Ogre::ParticleSystem* partsys, const Nif::NiAutoNormalParticlesData* particledata, - const Nif::NiParticleSystemController* partctrl) - { - partsys->_update(0.f); // seems to be required to allocate mFreeParticles. TODO: patch Ogre to handle this better - int i=0; - for (std::vector::const_iterator it = partctrl->particles.begin(); - iactiveCount && it != partctrl->particles.end(); ++it, ++i) - { - const Nif::NiParticleSystemController::Particle& particle = *it; - - Ogre::Particle* created = partsys->createParticle(); - if (!created) - break; - -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - Ogre::Vector3& position = created->mPosition; - Ogre::Vector3& direction = created->mDirection; - Ogre::ColourValue& colour = created->mColour; - float& totalTimeToLive = created->mTotalTimeToLive; - float& timeToLive = created->mTimeToLive; -#else - Ogre::Vector3& position = created->position; - Ogre::Vector3& direction = created->direction; - Ogre::ColourValue& colour = created->colour; - float& totalTimeToLive = created->totalTimeToLive; - float& timeToLive = created->timeToLive; -#endif - - direction = particle.velocity; - position = particledata->vertices.at(particle.vertex); - - if (particle.vertex < int(particledata->colors.size())) - { - Ogre::Vector4 partcolour = particledata->colors.at(particle.vertex); - colour = Ogre::ColourValue(partcolour.x, partcolour.y, partcolour.z, partcolour.w); - } - else - colour = Ogre::ColourValue(1.f, 1.f, 1.f, 1.f); - float size = particledata->sizes.at(particle.vertex); - created->setDimensions(size, size); - totalTimeToLive = std::max(0.f, particle.lifespan); - timeToLive = std::max(0.f, particle.lifespan - particle.lifetime); - } - partsys->_update(0.f); // now apparently needs another update, otherwise it won't render in the first frame. TODO: patch Ogre to handle this better - } - - static void createNodeControllers(const Nif::NIFFilePtr& nif, const std::string &name, Nif::ControllerPtr ctrl, ObjectScenePtr scene, int animflags) - { - do { - if (ctrl->flags & Nif::NiNode::ControllerFlag_Active) - { - if(ctrl->recType == Nif::RC_NiVisController) - { - const Nif::NiVisController *vis = static_cast(ctrl.getPtr()); - - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex); - 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)); - scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); - Ogre::ControllerFunctionRealPtr func(function); - - scene->mControllers.push_back(Ogre::Controller(srcval, dstval, func)); - } - else if(ctrl->recType == Nif::RC_NiKeyframeController) - { - const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); - if(!key->data.empty()) - { - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, ctrl->target->recIndex); - Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid); - // The keyframe controller will control this bone manually - trgtbone->setManuallyControlled(true); - Ogre::ControllerValueRealPtr srcval((animflags&Nif::NiNode::AnimFlag_AutoPlay) ? - Ogre::ControllerManager::getSingleton().getFrameTimeSource() : - Ogre::ControllerValueRealPtr()); - Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, nif, key->data.getPtr())); - KeyframeController::Function* function = OGRE_NEW KeyframeController::Function(key, (animflags&Nif::NiNode::AnimFlag_AutoPlay)); - scene->mMaxControllerLength = std::max(function->mStopTime, scene->mMaxControllerLength); - Ogre::ControllerFunctionRealPtr func(function); - - scene->mControllers.push_back(Ogre::Controller(srcval, dstval, func)); - } - } - } - ctrl = ctrl->next; - } while(!ctrl.empty()); - } - - - static void extractTextKeys(const Nif::NiTextKeyExtraData *tk, TextKeyMap &textkeys) - { - for(size_t i = 0;i < tk->list.size();i++) - { - const std::string &str = tk->list[i].text; - std::string::size_type pos = 0; - while(pos < str.length()) - { - if(::isspace(str[pos])) - { - pos++; - continue; - } - - std::string::size_type nextpos = std::min(str.find('\r', pos), str.find('\n', pos)); - if(nextpos != std::string::npos) - { - do { - nextpos--; - } while(nextpos > pos && ::isspace(str[nextpos])); - nextpos++; - } - else if(::isspace(*str.rbegin())) - { - std::string::const_iterator last = str.end(); - do { - --last; - } while(last != str.begin() && ::isspace(*last)); - nextpos = std::distance(str.begin(), ++last); - } - std::string result = str.substr(pos, nextpos-pos); - textkeys.insert(std::make_pair(tk->list[i].time, Misc::StringUtils::toLower(result))); - - pos = nextpos; - } - } - } - - - static void createObjects(const Nif::NIFFilePtr& nif, const std::string &name, const std::string &group, - Ogre::SceneNode *sceneNode, const Nif::Node *node, - ObjectScenePtr scene, int flags, int animflags, int partflags, bool isRootCollisionNode=false) - { - // Do not create objects for the collision shape (includes all children) - if(node->recType == Nif::RC_RootCollisionNode) - isRootCollisionNode = true; - - if(node->recType == Nif::RC_NiBSAnimationNode) - animflags |= node->flags; - else if(node->recType == Nif::RC_NiBSParticleNode) - partflags |= node->flags; - else - flags |= node->flags; - - if (node->recType == Nif::RC_NiBillboardNode) - { - // TODO: figure out what the flags mean. - // NifSkope has names for them, but doesn't implement them. - // Change mBillboardNodes to map - int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, node->recIndex); - Ogre::Bone* bone = scene->mSkelBase->getSkeleton()->getBone(trgtid); - bone->setManuallyControlled(true); - scene->mBillboardNodes.push_back(bone); - } - - Nif::ExtraPtr e = node->extra; - while(!e.empty()) - { - if(e->recType == Nif::RC_NiTextKeyExtraData) - { - const Nif::NiTextKeyExtraData *tk = static_cast(e.getPtr()); - - extractTextKeys(tk, scene->mTextKeys); - } - else if(e->recType == Nif::RC_NiStringExtraData) - { - const Nif::NiStringExtraData *sd = static_cast(e.getPtr()); - // String markers may contain important information - // affecting the entire subtree of this obj - if(sd->string == "MRK" && !sShowMarkers) - { - // Marker objects. These meshes are only visible in the - // editor. - flags |= 0x80000000; - } - } - - e = e->extra; - } - - if(!node->controller.empty()) - createNodeControllers(nif, name, node->controller, scene, animflags); - - if (!isRootCollisionNode) - { - if(node->recType == Nif::RC_NiCamera) - { - /* Ignored */ - } - - if(node->recType == Nif::RC_NiTriShape && !(flags&0x80000000)) - { - 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, scene, node, flags, partflags, animflags); - } - } - - const Nif::NiNode *ninode = dynamic_cast(node); - if(ninode) - { - const Nif::NodeList &children = ninode->children; - for(size_t i = 0;i < children.length();i++) - { - if(!children[i].empty()) - createObjects(nif, name, group, sceneNode, children[i].getPtr(), scene, flags, animflags, partflags, isRootCollisionNode); - } - } - } - - static void createSkelBase(const std::string &name, const std::string &group, - Ogre::SceneManager *sceneMgr, const Nif::Node *node, - 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 - * other entities are attached to bones and not skinned. */ - Ogre::MeshManager &meshMgr = Ogre::MeshManager::getSingleton(); - if(meshMgr.getByName(name).isNull()) - NIFMeshLoader::createMesh(name, name, group, ~(size_t)0); - - scene->mSkelBase = sceneMgr->createEntity(name); - scene->mEntities.push_back(scene->mSkelBase); - } - -public: - static void load(Ogre::SceneNode *sceneNode, ObjectScenePtr scene, const std::string &name, const std::string &group, int flags=0) - { - Nif::NIFFilePtr nif = Nif::Cache::getInstance().load(name); - if(nif->numRoots() < 1) - { - nif->warn("Found no root nodes in "+name+"."); - return; - } - - const Nif::Record *r = nif->getRoot(0); - assert(r != NULL); - - const Nif::Node *node = dynamic_cast(r); - if(node == NULL) - { - nif->warn("First root in "+name+" was not a node, but a "+ - r->recName+"."); - return; - } - - if(Ogre::SkeletonManager::getSingleton().resourceExists(name) || - !NIFSkeletonLoader::createSkeleton(name, group, node).isNull()) - { - // Create a base skeleton entity if this NIF needs one - createSkelBase(name, group, sceneNode->getCreator(), node, scene); - } - createObjects(nif, name, group, sceneNode, node, scene, flags, 0, 0); - } - - static void loadKf(Ogre::Skeleton *skel, const std::string &name, - TextKeyMap &textKeys, std::vector > &ctrls) - { - Nif::NIFFilePtr nif = Nif::Cache::getInstance().load(name); - if(nif->numRoots() < 1) - { - nif->warn("Found no root nodes in "+name+"."); - return; - } - - const Nif::Record *r = nif->getRoot(0); - assert(r != NULL); - - if(r->recType != Nif::RC_NiSequenceStreamHelper) - { - nif->warn("First root was not a NiSequenceStreamHelper, but a "+ - r->recName+"."); - return; - } - const Nif::NiSequenceStreamHelper *seq = static_cast(r); - - Nif::ExtraPtr extra = seq->extra; - if(extra.empty() || extra->recType != Nif::RC_NiTextKeyExtraData) - { - nif->warn("First extra data was not a NiTextKeyExtraData, but a "+ - (extra.empty() ? std::string("nil") : extra->recName)+"."); - return; - } - - extractTextKeys(static_cast(extra.getPtr()), textKeys); - - extra = extra->extra; - Nif::ControllerPtr ctrl = seq->controller; - for(;!extra.empty() && !ctrl.empty();(extra=extra->extra),(ctrl=ctrl->next)) - { - if(extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController) - { - nif->warn("Unexpected extra data "+extra->recName+" with controller "+ctrl->recName); - continue; - } - - if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active)) - continue; - - const Nif::NiStringExtraData *strdata = static_cast(extra.getPtr()); - const Nif::NiKeyframeController *key = static_cast(ctrl.getPtr()); - - if(key->data.empty()) - continue; - if(!skel->hasBone(strdata->string)) - continue; - - Ogre::Bone *trgtbone = skel->getBone(strdata->string); - Ogre::ControllerValueRealPtr srcval; - Ogre::ControllerValueRealPtr dstval(OGRE_NEW KeyframeController::Value(trgtbone, nif, key->data.getPtr())); - Ogre::ControllerFunctionRealPtr func(OGRE_NEW KeyframeController::Function(key, false)); - - ctrls.push_back(Ogre::Controller(srcval, dstval, func)); - } - } -}; - - -ObjectScenePtr Loader::createObjects(Ogre::SceneNode *parentNode, std::string name, const std::string &group) -{ - ObjectScenePtr scene = ObjectScenePtr (new ObjectScene(parentNode->getCreator())); - - Misc::StringUtils::toLower(name); - NIFObjectLoader::load(parentNode, scene, name, group); - - for(size_t i = 0;i < scene->mEntities.size();i++) - { - Ogre::Entity *entity = scene->mEntities[i]; - if(!entity->isAttached()) - parentNode->attachObject(entity); - } - - scene->_notifyAttached(); - - return scene; -} - -ObjectScenePtr Loader::createObjects(Ogre::Entity *parent, const std::string &bonename, - const std::string& bonefilter, - Ogre::SceneNode *parentNode, - std::string name, const std::string &group) -{ - ObjectScenePtr scene = ObjectScenePtr (new ObjectScene(parentNode->getCreator())); - - Misc::StringUtils::toLower(name); - NIFObjectLoader::load(parentNode, scene, name, group); - - bool isskinned = false; - for(size_t i = 0;i < scene->mEntities.size();i++) - { - Ogre::Entity *ent = scene->mEntities[i]; - if(scene->mSkelBase != ent && ent->hasSkeleton()) - { - isskinned = true; - break; - } - } - - Ogre::Vector3 scale(1.0f); - if(bonename.find("Left") != std::string::npos) - scale.x *= -1.0f; - - if(isskinned) - { - // accepts anything named "filter*" or "tri filter*" - std::string filter = "@shape=tri "+bonefilter; - std::string filter2 = "@shape="+bonefilter; - Misc::StringUtils::toLower(filter); - Misc::StringUtils::toLower(filter2); - for(size_t i = 0;i < scene->mEntities.size();i++) - { - Ogre::Entity *entity = scene->mEntities[i]; - if(entity->hasSkeleton()) - { - if(entity == scene->mSkelBase || - entity->getMesh()->getName().find(filter) != std::string::npos - || entity->getMesh()->getName().find(filter2) != std::string::npos) - parentNode->attachObject(entity); - } - else - { - if(entity->getMesh()->getName().find(filter) == std::string::npos - || entity->getMesh()->getName().find(filter2) == std::string::npos) - entity->detachFromParent(); - } - } - } - else - { - for(size_t i = 0;i < scene->mEntities.size();i++) - { - Ogre::Entity *entity = scene->mEntities[i]; - if(!entity->isAttached()) - { - Ogre::TagPoint *tag = parent->attachObjectToBone(bonename, entity); - tag->setScale(scale); - } - } - } - - scene->_notifyAttached(); - - return scene; -} - - -ObjectScenePtr Loader::createObjectBase(Ogre::SceneNode *parentNode, std::string name, const std::string &group) -{ - ObjectScenePtr scene = ObjectScenePtr (new ObjectScene(parentNode->getCreator())); - - Misc::StringUtils::toLower(name); - NIFObjectLoader::load(parentNode, scene, name, group, 0xC0000000); - - if(scene->mSkelBase) - parentNode->attachObject(scene->mSkelBase); - - return scene; -} - - -void Loader::createKfControllers(Ogre::Entity *skelBase, - const std::string &name, - TextKeyMap &textKeys, - std::vector > &ctrls) -{ - NIFObjectLoader::loadKf(skelBase->getSkeleton(), name, textKeys, ctrls); -} - -bool Loader::sShowMarkers = false; -bool NIFObjectLoader::sShowMarkers = false; - -void Loader::setShowMarkers(bool show) -{ - sShowMarkers = show; - NIFObjectLoader::setShowMarkers(show); -} - - -} // namespace NifOgre diff --git a/components/nifogre/ogrenifloader.hpp b/components/nifogre/ogrenifloader.hpp deleted file mode 100644 index c13532644..000000000 --- a/components/nifogre/ogrenifloader.hpp +++ /dev/null @@ -1,151 +0,0 @@ -/* - OpenMW - The completely unofficial reimplementation of Morrowind - Copyright (C) 2008-2010 Nicolay Korslund - Email: < korslund@gmail.com > - WWW: http://openmw.sourceforge.net/ - - This file (ogre_nif_loader.h) is part of the OpenMW package. - - OpenMW is distributed as free software: you can redistribute it - and/or modify it under the terms of the GNU General Public License - version 3, as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - version 3 along with this program. If not, see - http://www.gnu.org/licenses/ . - - */ - -#ifndef OPENMW_COMPONENTS_NIFOGRE_OGRENIFLOADER_HPP -#define OPENMW_COMPONENTS_NIFOGRE_OGRENIFLOADER_HPP - -#include -#include -#include - -#include -#include -#include - - -// FIXME: This namespace really doesn't do anything Nif-specific. Any supportable -// model format should go through this. -namespace NifOgre -{ - -/** - * @brief Clones materials as necessary to not make controllers affect other objects (that share the original material). - */ -class MaterialControllerManager -{ -public: - ~MaterialControllerManager(); - - /// @attention if \a movable is an Entity, it needs to have *one* SubEntity - Ogre::MaterialPtr getWritableMaterial (Ogre::MovableObject* movable); - -private: - std::map mClonedMaterials; -}; - -typedef std::multimap TextKeyMap; -static const char sTextKeyExtraDataID[] = "TextKeyExtraData"; -struct ObjectScene { - Ogre::Entity *mSkelBase; - std::vector mEntities; - std::vector mParticles; - std::vector mLights; - - // Nodes that should always face the camera when rendering - std::vector mBillboardNodes; - - 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; - - TextKeyMap mTextKeys; - - MaterialControllerManager mMaterialControllerMgr; - - std::vector > mControllers; - - ObjectScene(Ogre::SceneManager* sceneMgr) : mSkelBase(0), mMaxControllerLength(0), mSceneMgr(sceneMgr) - { } - - ~ObjectScene(); - - // Rotate nodes in mBillboardNodes so they face the given camera - void rotateBillboardNodes(Ogre::Camera* camera); - - void setVisibilityFlags (unsigned int flags); - - // This is called internally by the OgreNifLoader once all elements of the - // scene have been attached to their respective nodes. - void _notifyAttached(); -}; - -typedef Ogre::SharedPtr ObjectScenePtr; - - -class Loader -{ -public: - static ObjectScenePtr createObjects(Ogre::Entity *parent, const std::string &bonename, - const std::string& filter, - Ogre::SceneNode *parentNode, - std::string name, - const std::string &group="General"); - - static ObjectScenePtr createObjects(Ogre::SceneNode *parentNode, - std::string name, - const std::string &group="General"); - - static ObjectScenePtr createObjectBase(Ogre::SceneNode *parentNode, - std::string name, - const std::string &group="General"); - - /// Set whether or not nodes marked as "MRK" should be shown. - /// These should be hidden ingame, but visible in the editior. - /// Default: false. - static void setShowMarkers(bool show); - - static void createKfControllers(Ogre::Entity *skelBase, - const std::string &name, - TextKeyMap &textKeys, - std::vector > &ctrls); - -private: - static bool sShowMarkers; -}; - -// FIXME: Should be with other general Ogre extensions. -template -class NodeTargetValue : public Ogre::ControllerValue -{ -protected: - Ogre::Node *mNode; - -public: - NodeTargetValue(Ogre::Node *target) : mNode(target) - { } - - virtual Ogre::Quaternion getRotation(T value) const = 0; - virtual Ogre::Vector3 getTranslation(T value) const = 0; - virtual Ogre::Vector3 getScale(T value) const = 0; - - void setNode(Ogre::Node *target) - { mNode = target; } - Ogre::Node *getNode() const - { return mNode; } -}; -typedef Ogre::SharedPtr > NodeTargetValueRealPtr; - -} - -#endif diff --git a/components/nifogre/particles.cpp b/components/nifogre/particles.cpp deleted file mode 100644 index 4fec2d29e..000000000 --- a/components/nifogre/particles.cpp +++ /dev/null @@ -1,773 +0,0 @@ -#include "particles.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* FIXME: "Nif" isn't really an appropriate emitter name. */ -class NifEmitter : public Ogre::ParticleEmitter -{ -public: - std::vector mEmitterBones; - Ogre::Bone* mParticleBone; - - Ogre::ParticleSystem* getPartSys() { return mParent; } - - /** Command object for the emitter width (see Ogre::ParamCommand).*/ - class CmdWidth : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - return Ogre::StringConverter::toString(static_cast(target)->getWidth()); - } - void doSet(void *target, const Ogre::String &val) - { - static_cast(target)->setWidth(Ogre::StringConverter::parseReal(val)); - } - }; - - /** Command object for the emitter height (see Ogre::ParamCommand).*/ - class CmdHeight : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - return Ogre::StringConverter::toString(static_cast(target)->getHeight()); - } - void doSet(void *target, const Ogre::String &val) - { - static_cast(target)->setHeight(Ogre::StringConverter::parseReal(val)); - } - }; - - /** Command object for the emitter depth (see Ogre::ParamCommand).*/ - class CmdDepth : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - return Ogre::StringConverter::toString(static_cast(target)->getDepth()); - } - void doSet(void *target, const Ogre::String &val) - { - static_cast(target)->setDepth(Ogre::StringConverter::parseReal(val)); - } - }; - - /** Command object for the emitter vertical_direction (see Ogre::ParamCommand).*/ - class CmdVerticalDir : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const NifEmitter *self = static_cast(target); - return Ogre::StringConverter::toString(self->getVerticalDirection().valueDegrees()); - } - void doSet(void *target, const Ogre::String &val) - { - NifEmitter *self = static_cast(target); - self->setVerticalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val))); - } - }; - - /** Command object for the emitter vertical_angle (see Ogre::ParamCommand).*/ - class CmdVerticalAngle : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const NifEmitter *self = static_cast(target); - return Ogre::StringConverter::toString(self->getVerticalAngle().valueDegrees()); - } - void doSet(void *target, const Ogre::String &val) - { - NifEmitter *self = static_cast(target); - self->setVerticalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val))); - } - }; - - /** Command object for the emitter horizontal_direction (see Ogre::ParamCommand).*/ - class CmdHorizontalDir : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const NifEmitter *self = static_cast(target); - return Ogre::StringConverter::toString(self->getHorizontalDirection().valueDegrees()); - } - void doSet(void *target, const Ogre::String &val) - { - NifEmitter *self = static_cast(target); - self->setHorizontalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val))); - } - }; - - /** Command object for the emitter horizontal_angle (see Ogre::ParamCommand).*/ - class CmdHorizontalAngle : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const NifEmitter *self = static_cast(target); - return Ogre::StringConverter::toString(self->getHorizontalAngle().valueDegrees()); - } - void doSet(void *target, const Ogre::String &val) - { - NifEmitter *self = static_cast(target); - self->setHorizontalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val))); - } - }; - - - NifEmitter(Ogre::ParticleSystem *psys) - : Ogre::ParticleEmitter(psys) - , mEmitterBones(Ogre::any_cast(psys->getUserObjectBindings().getUserAny()).mBones) - { - assert (!mEmitterBones.empty()); - Ogre::TagPoint* tag = static_cast(mParent->getParentNode()); - mParticleBone = static_cast(tag->getParent()); - initDefaults("Nif"); - } - - /** See Ogre::ParticleEmitter. */ - unsigned short _getEmissionCount(Ogre::Real timeElapsed) - { - // Use basic constant emission - return genConstantEmissionCount(timeElapsed); - } - - /** See Ogre::ParticleEmitter. */ - void _initParticle(Ogre::Particle *particle) - { - Ogre::Vector3 xOff, yOff, zOff; - - // Call superclass - ParticleEmitter::_initParticle(particle); - - xOff = Ogre::Math::SymmetricRandom() * mXRange; - yOff = Ogre::Math::SymmetricRandom() * mYRange; - zOff = Ogre::Math::SymmetricRandom() * mZRange; - -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - Ogre::Vector3& position = particle->mPosition; - Ogre::Vector3& direction = particle->mDirection; - Ogre::ColourValue& colour = particle->mColour; - Ogre::Real& totalTimeToLive = particle->mTotalTimeToLive; - Ogre::Real& timeToLive = particle->mTimeToLive; -#else - Ogre::Vector3& position = particle->position; - Ogre::Vector3& direction = particle->direction; - Ogre::ColourValue& colour = particle->colour; - Ogre::Real& totalTimeToLive = particle->totalTimeToLive; - Ogre::Real& timeToLive = particle->timeToLive; -#endif - - Ogre::Node* emitterBone = mEmitterBones.at((int)(::rand()/(RAND_MAX+1.0)*mEmitterBones.size())); - - position = xOff + yOff + zOff + - mParticleBone->_getDerivedOrientation().Inverse() * (emitterBone->_getDerivedPosition() - - mParticleBone->_getDerivedPosition()); - - // Generate complex data by reference - genEmissionColour(colour); - - // NOTE: We do not use mDirection/mAngle for the initial direction. - Ogre::Radian hdir = mHorizontalDir + mHorizontalAngle*Ogre::Math::SymmetricRandom(); - Ogre::Radian vdir = mVerticalDir + mVerticalAngle*Ogre::Math::SymmetricRandom(); - direction = (mParticleBone->_getDerivedOrientation().Inverse() - * emitterBone->_getDerivedOrientation() * - Ogre::Quaternion(hdir, Ogre::Vector3::UNIT_Z) * - Ogre::Quaternion(vdir, Ogre::Vector3::UNIT_X)) * - Ogre::Vector3::UNIT_Z; - - genEmissionVelocity(direction); - - // Generate simpler data - timeToLive = totalTimeToLive = genEmissionTTL(); - } - - /** Overloaded to update the trans. matrix */ - void setDirection(const Ogre::Vector3 &dir) - { - ParticleEmitter::setDirection(dir); - genAreaAxes(); - } - - /** Sets the size of the area from which particles are emitted. - @param - size Vector describing the size of the area. The area extends - around the center point by half the x, y and z components of - this vector. The box is aligned such that it's local Z axis points - along it's direction (see setDirection) - */ - void setSize(const Ogre::Vector3 &size) - { - mSize = size; - genAreaAxes(); - } - - /** Sets the size of the area from which particles are emitted. - @param x,y,z - Individual axis lengths describing the size of the area. The area - extends around the center point by half the x, y and z components - of this vector. The box is aligned such that it's local Z axis - points along it's direction (see setDirection) - */ - void setSize(Ogre::Real x, Ogre::Real y, Ogre::Real z) - { - mSize.x = x; - mSize.y = y; - mSize.z = z; - genAreaAxes(); - } - - /** Sets the width (local x size) of the emitter. */ - void setWidth(Ogre::Real width) - { - mSize.x = width; - genAreaAxes(); - } - /** Gets the width (local x size) of the emitter. */ - Ogre::Real getWidth(void) const - { return mSize.x; } - /** Sets the height (local y size) of the emitter. */ - void setHeight(Ogre::Real height) - { - mSize.y = height; - genAreaAxes(); - } - /** Gets the height (local y size) of the emitter. */ - Ogre::Real getHeight(void) const - { return mSize.y; } - /** Sets the depth (local y size) of the emitter. */ - void setDepth(Ogre::Real depth) - { - mSize.z = depth; - genAreaAxes(); - } - /** Gets the depth (local y size) of the emitter. */ - Ogre::Real getDepth(void) const - { return mSize.z; } - - void setVerticalDirection(Ogre::Radian vdir) - { mVerticalDir = vdir; } - Ogre::Radian getVerticalDirection(void) const - { return mVerticalDir; } - - void setVerticalAngle(Ogre::Radian vangle) - { mVerticalAngle = vangle; } - Ogre::Radian getVerticalAngle(void) const - { return mVerticalAngle; } - - void setHorizontalDirection(Ogre::Radian hdir) - { mHorizontalDir = hdir; } - Ogre::Radian getHorizontalDirection(void) const - { return mHorizontalDir; } - - void setHorizontalAngle(Ogre::Radian hangle) - { mHorizontalAngle = hangle; } - Ogre::Radian getHorizontalAngle(void) const - { return mHorizontalAngle; } - - -protected: - /// Size of the area - Ogre::Vector3 mSize; - - Ogre::Radian mVerticalDir; - Ogre::Radian mVerticalAngle; - Ogre::Radian mHorizontalDir; - Ogre::Radian mHorizontalAngle; - - /// Local axes, not normalised, their magnitude reflects area size - Ogre::Vector3 mXRange, mYRange, mZRange; - - /// Internal method for generating the area axes - void genAreaAxes(void) - { - Ogre::Vector3 mLeft = mUp.crossProduct(mDirection); - mXRange = mLeft * (mSize.x * 0.5f); - mYRange = mUp * (mSize.y * 0.5f); - mZRange = mDirection * (mSize.z * 0.5f); - } - - /** Internal for initializing some defaults and parameters - @return True if custom parameters need initialising - */ - bool initDefaults(const Ogre::String &t) - { - // Defaults - mDirection = Ogre::Vector3::UNIT_Z; - mUp = Ogre::Vector3::UNIT_Y; - setSize(100.0f, 100.0f, 100.0f); - mType = t; - - // Set up parameters - if(createParamDictionary(mType + "Emitter")) - { - addBaseParameters(); - Ogre::ParamDictionary *dict = getParamDictionary(); - - // Custom params - dict->addParameter(Ogre::ParameterDef("width", - "Width of the shape in world coordinates.", - Ogre::PT_REAL), - &msWidthCmd); - dict->addParameter(Ogre::ParameterDef("height", - "Height of the shape in world coordinates.", - Ogre::PT_REAL), - &msHeightCmd); - dict->addParameter(Ogre::ParameterDef("depth", - "Depth of the shape in world coordinates.", - Ogre::PT_REAL), - &msDepthCmd); - - dict->addParameter(Ogre::ParameterDef("vertical_direction", - "Vertical direction of emitted particles (in degrees).", - Ogre::PT_REAL), - &msVerticalDirCmd); - dict->addParameter(Ogre::ParameterDef("vertical_angle", - "Vertical direction variance of emitted particles (in degrees).", - Ogre::PT_REAL), - &msVerticalAngleCmd); - dict->addParameter(Ogre::ParameterDef("horizontal_direction", - "Horizontal direction of emitted particles (in degrees).", - Ogre::PT_REAL), - &msHorizontalDirCmd); - dict->addParameter(Ogre::ParameterDef("horizontal_angle", - "Horizontal direction variance of emitted particles (in degrees).", - Ogre::PT_REAL), - &msHorizontalAngleCmd); - - return true; - } - return false; - } - - /// Command objects - static CmdWidth msWidthCmd; - static CmdHeight msHeightCmd; - static CmdDepth msDepthCmd; - static CmdVerticalDir msVerticalDirCmd; - static CmdVerticalAngle msVerticalAngleCmd; - static CmdHorizontalDir msHorizontalDirCmd; - static CmdHorizontalAngle msHorizontalAngleCmd; -}; -NifEmitter::CmdWidth NifEmitter::msWidthCmd; -NifEmitter::CmdHeight NifEmitter::msHeightCmd; -NifEmitter::CmdDepth NifEmitter::msDepthCmd; -NifEmitter::CmdVerticalDir NifEmitter::msVerticalDirCmd; -NifEmitter::CmdVerticalAngle NifEmitter::msVerticalAngleCmd; -NifEmitter::CmdHorizontalDir NifEmitter::msHorizontalDirCmd; -NifEmitter::CmdHorizontalAngle NifEmitter::msHorizontalAngleCmd; - -Ogre::ParticleEmitter* NifEmitterFactory::createEmitter(Ogre::ParticleSystem *psys) -{ - Ogre::ParticleEmitter *emitter = OGRE_NEW NifEmitter(psys); - mEmitters.push_back(emitter); - return emitter; -} - - -class GrowFadeAffector : public Ogre::ParticleAffector -{ -public: - /** Command object for grow_time (see Ogre::ParamCommand).*/ - class CmdGrowTime : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const GrowFadeAffector *self = static_cast(target); - return Ogre::StringConverter::toString(self->getGrowTime()); - } - void doSet(void *target, const Ogre::String &val) - { - GrowFadeAffector *self = static_cast(target); - self->setGrowTime(Ogre::StringConverter::parseReal(val)); - } - }; - - /** Command object for fade_time (see Ogre::ParamCommand).*/ - class CmdFadeTime : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const GrowFadeAffector *self = static_cast(target); - return Ogre::StringConverter::toString(self->getFadeTime()); - } - void doSet(void *target, const Ogre::String &val) - { - GrowFadeAffector *self = static_cast(target); - self->setFadeTime(Ogre::StringConverter::parseReal(val)); - } - }; - - /** Default constructor. */ - GrowFadeAffector(Ogre::ParticleSystem *psys) : ParticleAffector(psys) - { - mGrowTime = 0.0f; - mFadeTime = 0.0f; - - mType = "GrowFade"; - - // Init parameters - if(createParamDictionary("GrowFadeAffector")) - { - Ogre::ParamDictionary *dict = getParamDictionary(); - - Ogre::String grow_title("grow_time"); - Ogre::String fade_title("fade_time"); - Ogre::String grow_descr("Time from begin to reach full size."); - Ogre::String fade_descr("Time from end to shrink."); - - dict->addParameter(Ogre::ParameterDef(grow_title, grow_descr, Ogre::PT_REAL), &msGrowCmd); - dict->addParameter(Ogre::ParameterDef(fade_title, fade_descr, Ogre::PT_REAL), &msFadeCmd); - } - } - - /** See Ogre::ParticleAffector. */ - void _initParticle(Ogre::Particle *particle) - { -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - const Ogre::Real life_time = particle->mTotalTimeToLive; - Ogre::Real particle_time = particle->mTimeToLive; -#else - const Ogre::Real life_time = particle->totalTimeToLive; - Ogre::Real particle_time = particle->timeToLive; -#endif - Ogre::Real width = mParent->getDefaultWidth(); - Ogre::Real height = mParent->getDefaultHeight(); - if(life_time-particle_time < mGrowTime) - { - Ogre::Real scale = (life_time-particle_time) / mGrowTime; - assert (scale >= 0); - // HACK: don't allow zero-sized particles which can rarely cause an AABB assertion in Ogre to fail - scale = std::max(scale, 0.00001f); - width *= scale; - height *= scale; - } - if(particle_time < mFadeTime) - { - Ogre::Real scale = particle_time / mFadeTime; - assert (scale >= 0); - // HACK: don't allow zero-sized particles which can rarely cause an AABB assertion in Ogre to fail - scale = std::max(scale, 0.00001f); - width *= scale; - height *= scale; - } - particle->setDimensions(width, height); - } - - /** See Ogre::ParticleAffector. */ - void _affectParticles(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed) - { - Ogre::ParticleIterator pi = psys->_getIterator(); - while (!pi.end()) - { - Ogre::Particle *p = pi.getNext(); -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - const Ogre::Real life_time = p->mTotalTimeToLive; - Ogre::Real particle_time = p->mTimeToLive; -#else - const Ogre::Real life_time = p->totalTimeToLive; - Ogre::Real particle_time = p->timeToLive; -#endif - Ogre::Real width = mParent->getDefaultWidth(); - Ogre::Real height = mParent->getDefaultHeight(); - if(life_time-particle_time < mGrowTime) - { - Ogre::Real scale = (life_time-particle_time) / mGrowTime; - assert (scale >= 0); - // HACK: don't allow zero-sized particles which can rarely cause an AABB assertion in Ogre to fail - scale = std::max(scale, 0.00001f); - width *= scale; - height *= scale; - } - if(particle_time < mFadeTime) - { - Ogre::Real scale = particle_time / mFadeTime; - assert (scale >= 0); - // HACK: don't allow zero-sized particles which can rarely cause an AABB assertion in Ogre to fail - scale = std::max(scale, 0.00001f); - width *= scale; - height *= scale; - } - p->setDimensions(width, height); - } - } - - void setGrowTime(Ogre::Real time) - { - mGrowTime = time; - } - Ogre::Real getGrowTime() const - { return mGrowTime; } - - void setFadeTime(Ogre::Real time) - { - mFadeTime = time; - } - Ogre::Real getFadeTime() const - { return mFadeTime; } - - static CmdGrowTime msGrowCmd; - static CmdFadeTime msFadeCmd; - -protected: - Ogre::Real mGrowTime; - Ogre::Real mFadeTime; -}; -GrowFadeAffector::CmdGrowTime GrowFadeAffector::msGrowCmd; -GrowFadeAffector::CmdFadeTime GrowFadeAffector::msFadeCmd; - -Ogre::ParticleAffector *GrowFadeAffectorFactory::createAffector(Ogre::ParticleSystem *psys) -{ - Ogre::ParticleAffector *p = new GrowFadeAffector(psys); - mAffectors.push_back(p); - return p; -} - - -class GravityAffector : public Ogre::ParticleAffector -{ - enum ForceType { - Type_Wind, - Type_Point - }; - -public: - Ogre::Bone* mEmitterBone; - Ogre::Bone* mParticleBone; - - Ogre::ParticleSystem* getPartSys() { return mParent; } - - /** Command object for force (see Ogre::ParamCommand).*/ - class CmdForce : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const GravityAffector *self = static_cast(target); - return Ogre::StringConverter::toString(self->getForce()); - } - void doSet(void *target, const Ogre::String &val) - { - GravityAffector *self = static_cast(target); - self->setForce(Ogre::StringConverter::parseReal(val)); - } - }; - - /** Command object for force_type (see Ogre::ParamCommand).*/ - class CmdForceType : public Ogre::ParamCommand - { - static ForceType getTypeFromString(const Ogre::String &type) - { - if(type == "wind") - return Type_Wind; - if(type == "point") - return Type_Point; - OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Invalid force type string: "+type, - "CmdForceType::getTypeFromString"); - } - - static Ogre::String getStringFromType(ForceType type) - { - switch(type) - { - case Type_Wind: return "wind"; - case Type_Point: return "point"; - } - OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Invalid force type enum: "+Ogre::StringConverter::toString(type), - "CmdForceType::getStringFromType"); - } - - public: - Ogre::String doGet(const void *target) const - { - const GravityAffector *self = static_cast(target); - return getStringFromType(self->getForceType()); - } - void doSet(void *target, const Ogre::String &val) - { - GravityAffector *self = static_cast(target); - self->setForceType(getTypeFromString(val)); - } - }; - - /** Command object for direction (see Ogre::ParamCommand).*/ - class CmdDirection : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const GravityAffector *self = static_cast(target); - return Ogre::StringConverter::toString(self->getDirection()); - } - void doSet(void *target, const Ogre::String &val) - { - GravityAffector *self = static_cast(target); - self->setDirection(Ogre::StringConverter::parseVector3(val)); - } - }; - - /** Command object for position (see Ogre::ParamCommand).*/ - class CmdPosition : public Ogre::ParamCommand - { - public: - Ogre::String doGet(const void *target) const - { - const GravityAffector *self = static_cast(target); - return Ogre::StringConverter::toString(self->getPosition()); - } - void doSet(void *target, const Ogre::String &val) - { - GravityAffector *self = static_cast(target); - self->setPosition(Ogre::StringConverter::parseVector3(val)); - } - }; - - - /** Default constructor. */ - GravityAffector(Ogre::ParticleSystem *psys) - : ParticleAffector(psys) - , mForce(0.0f) - , mForceType(Type_Wind) - , mPosition(0.0f) - , mDirection(0.0f) - { - std::vector bones = Ogre::any_cast(psys->getUserObjectBindings().getUserAny()).mBones; - assert (!bones.empty()); - mEmitterBone = bones[0]; - Ogre::TagPoint* tag = static_cast(mParent->getParentNode()); - mParticleBone = static_cast(tag->getParent()); - - mType = "Gravity"; - - // Init parameters - if(createParamDictionary("GravityAffector")) - { - Ogre::ParamDictionary *dict = getParamDictionary(); - - Ogre::String force_title("force"); - Ogre::String force_descr("Amount of force applied to particles."); - Ogre::String force_type_title("force_type"); - Ogre::String force_type_descr("Type of force applied to particles (point or wind)."); - Ogre::String direction_title("direction"); - Ogre::String direction_descr("Direction of wind forces."); - Ogre::String position_title("position"); - Ogre::String position_descr("Position of point forces."); - - dict->addParameter(Ogre::ParameterDef(force_title, force_descr, Ogre::PT_REAL), &msForceCmd); - dict->addParameter(Ogre::ParameterDef(force_type_title, force_type_descr, Ogre::PT_STRING), &msForceTypeCmd); - dict->addParameter(Ogre::ParameterDef(direction_title, direction_descr, Ogre::PT_VECTOR3), &msDirectionCmd); - dict->addParameter(Ogre::ParameterDef(position_title, position_descr, Ogre::PT_VECTOR3), &msPositionCmd); - } - } - - /** See Ogre::ParticleAffector. */ - void _affectParticles(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed) - { - switch(mForceType) - { - case Type_Wind: - applyWindForce(psys, timeElapsed); - break; - case Type_Point: - applyPointForce(psys, timeElapsed); - break; - } - } - - void setForce(Ogre::Real force) - { mForce = force; } - Ogre::Real getForce() const - { return mForce; } - - void setForceType(ForceType type) - { mForceType = type; } - ForceType getForceType() const - { return mForceType; } - - void setDirection(const Ogre::Vector3 &dir) - { mDirection = dir; } - const Ogre::Vector3 &getDirection() const - { return mDirection; } - - void setPosition(const Ogre::Vector3 &pos) - { mPosition = pos; } - const Ogre::Vector3 &getPosition() const - { return mPosition; } - - static CmdForce msForceCmd; - static CmdForceType msForceTypeCmd; - static CmdDirection msDirectionCmd; - static CmdPosition msPositionCmd; - -protected: - void applyWindForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed) - { - const Ogre::Vector3 vec = mDirection * mForce * timeElapsed; - Ogre::ParticleIterator pi = psys->_getIterator(); - while (!pi.end()) - { - Ogre::Particle *p = pi.getNext(); -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - p->mDirection += vec; -#else - p->direction += vec; -#endif - } - } - - void applyPointForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed) - { - const Ogre::Real force = mForce * timeElapsed; - Ogre::ParticleIterator pi = psys->_getIterator(); - while (!pi.end()) - { - Ogre::Particle *p = pi.getNext(); -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - Ogre::Vector3 position = p->mPosition; -#else - Ogre::Vector3 position = p->position; -#endif - - Ogre::Vector3 vec = (mPosition - position).normalisedCopy() * force; -#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0) - p->mDirection += vec; -#else - p->direction += vec; -#endif - } - } - - - float mForce; - - ForceType mForceType; - - Ogre::Vector3 mPosition; - Ogre::Vector3 mDirection; -}; -GravityAffector::CmdForce GravityAffector::msForceCmd; -GravityAffector::CmdForceType GravityAffector::msForceTypeCmd; -GravityAffector::CmdDirection GravityAffector::msDirectionCmd; -GravityAffector::CmdPosition GravityAffector::msPositionCmd; - -Ogre::ParticleAffector *GravityAffectorFactory::createAffector(Ogre::ParticleSystem *psys) -{ - Ogre::ParticleAffector *p = new GravityAffector(psys); - mAffectors.push_back(p); - return p; -} diff --git a/components/nifogre/particles.hpp b/components/nifogre/particles.hpp deleted file mode 100644 index 6efc669fe..000000000 --- a/components/nifogre/particles.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef OENGINE_OGRE_PARTICLES_H -#define OENGINE_OGRE_PARTICLES_H - -#include -#include - -/** Factory class for NifEmitter. */ -class NifEmitterFactory : public Ogre::ParticleEmitterFactory -{ -public: - /** See ParticleEmitterFactory */ - Ogre::String getName() const - { return "Nif"; } - - /** See ParticleEmitterFactory */ - Ogre::ParticleEmitter* createEmitter(Ogre::ParticleSystem *psys); -}; - -/** Factory class for GrowFadeAffector. */ -class GrowFadeAffectorFactory : public Ogre::ParticleAffectorFactory -{ - /** See Ogre::ParticleAffectorFactory */ - Ogre::String getName() const - { return "GrowFade"; } - - /** See Ogre::ParticleAffectorFactory */ - Ogre::ParticleAffector *createAffector(Ogre::ParticleSystem *psys); -}; - -/** Factory class for GravityAffector. */ -class GravityAffectorFactory : public Ogre::ParticleAffectorFactory -{ - /** See Ogre::ParticleAffectorFactory */ - Ogre::String getName() const - { return "Gravity"; } - - /** See Ogre::ParticleAffectorFactory */ - Ogre::ParticleAffector *createAffector(Ogre::ParticleSystem *psys); -}; - -struct NiNodeHolder -{ - std::vector mBones; - - // Ogre::Any needs this for some reason - friend std::ostream& operator<<(std::ostream& o, const NiNodeHolder& r) - { return o; } -}; - -#endif /* OENGINE_OGRE_PARTICLES_H */ diff --git a/components/nifogre/skeleton.cpp b/components/nifogre/skeleton.cpp deleted file mode 100644 index db6a753c5..000000000 --- a/components/nifogre/skeleton.cpp +++ /dev/null @@ -1,179 +0,0 @@ -#include "skeleton.hpp" - -#include -#include -#include -#include - -#include -#include -#include - -namespace NifOgre -{ - -void NIFSkeletonLoader::buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent) -{ - Ogre::Bone *bone; - if (node->name.empty()) - { - // HACK: use " " instead of empty name, otherwise Ogre will replace it with an auto-generated - // name in SkeletonInstance::cloneBoneAndChildren. - static const char* emptyname = " "; - if (!skel->hasBone(emptyname)) - bone = skel->createBone(emptyname); - else - bone = skel->createBone(); - } - else - { - if(!skel->hasBone(node->name)) - bone = skel->createBone(node->name); - else - bone = skel->createBone(); - } - - if(parent) parent->addChild(bone); - mNifToOgreHandleMap[node->recIndex] = bone->getHandle(); - - bone->setOrientation(node->trafo.rotation); - bone->setPosition(node->trafo.pos); - bone->setScale(Ogre::Vector3(node->trafo.scale)); - bone->setBindingPose(); - - if(!(node->recType == Nif::RC_NiNode || /* Nothing special; children traversed below */ - node->recType == Nif::RC_RootCollisionNode || /* handled in nifbullet (hopefully) */ - node->recType == Nif::RC_NiTriShape || /* Handled in the mesh loader */ - node->recType == Nif::RC_NiBSAnimationNode || /* Handled in the object loader */ - node->recType == Nif::RC_NiBillboardNode || /* Handled in the object loader */ - node->recType == Nif::RC_NiBSParticleNode || - node->recType == Nif::RC_NiCamera || - node->recType == Nif::RC_NiAutoNormalParticles || - node->recType == Nif::RC_NiRotatingParticles - )) - warn("Unhandled "+node->recName+" "+node->name+" in "+skel->getName()); - - Nif::ControllerPtr ctrl = node->controller; - while(!ctrl.empty()) - { - if(!(ctrl->recType == Nif::RC_NiParticleSystemController || - ctrl->recType == Nif::RC_NiBSPArrayController || - ctrl->recType == Nif::RC_NiVisController || - ctrl->recType == Nif::RC_NiUVController || - ctrl->recType == Nif::RC_NiKeyframeController || - ctrl->recType == Nif::RC_NiGeomMorpherController - )) - warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName()); - ctrl = ctrl->next; - } - - const Nif::NiNode *ninode = dynamic_cast(node); - if(ninode) - { - const Nif::NodeList &children = ninode->children; - for(size_t i = 0;i < children.length();i++) - { - if(!children[i].empty()) - buildBones(skel, children[i].getPtr(), bone); - } - } -} - -void NIFSkeletonLoader::loadResource(Ogre::Resource *resource) -{ - Ogre::Skeleton *skel = dynamic_cast(resource); - OgreAssert(skel, "Attempting to load a skeleton into a non-skeleton resource!"); - - Nif::NIFFilePtr nif(Nif::Cache::getInstance().load(skel->getName())); - const Nif::Node *node = static_cast(nif->getRoot(0)); - - try { - buildBones(skel, node); - } - catch(std::exception &e) { - std::cerr<< "Exception while loading "<getName() <boneTrafo) - return true; - - if(!node->controller.empty()) - { - Nif::ControllerPtr ctrl = node->controller; - do { - if(ctrl->recType == Nif::RC_NiKeyframeController && ctrl->flags & Nif::NiNode::ControllerFlag_Active) - return true; - } while(!(ctrl=ctrl->next).empty()); - } - - if (node->name == "AttachLight" || node->name == "ArrowBone") - return true; - - if(node->recType == Nif::RC_NiNode || node->recType == Nif::RC_RootCollisionNode) - { - const Nif::NiNode *ninode = static_cast(node); - const Nif::NodeList &children = ninode->children; - for(size_t i = 0;i < children.length();i++) - { - if(!children[i].empty()) - { - if(needSkeleton(children[i].getPtr())) - return true; - } - } - return false; - } - if(node->recType == Nif::RC_NiTriShape) - return false; - - return true; -} - -Ogre::SkeletonPtr NIFSkeletonLoader::createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node) -{ - bool forceskel = false; - std::string::size_type extpos = name.rfind('.'); - if(extpos != std::string::npos && name.compare(extpos, name.size()-extpos, ".nif") == 0) - { - Ogre::ResourceGroupManager &resMgr = Ogre::ResourceGroupManager::getSingleton(); - forceskel = resMgr.resourceExistsInAnyGroup(name.substr(0, extpos)+".kf"); - } - - if(forceskel || needSkeleton(node)) - { - Ogre::SkeletonManager &skelMgr = Ogre::SkeletonManager::getSingleton(); - return skelMgr.create(name, group, true, &sLoaders[name]); - } - - return Ogre::SkeletonPtr(); -} - -// Looks up an Ogre Bone handle ID from a NIF's record index. Should only be -// used when the bone name is insufficient as this is a relatively slow lookup -int NIFSkeletonLoader::lookupOgreBoneHandle(const std::string &nifname, int idx) -{ - LoaderMap::const_iterator loader = sLoaders.find(nifname); - if(loader != sLoaders.end()) - { - std::map::const_iterator entry = loader->second.mNifToOgreHandleMap.find(idx); - if(entry != loader->second.mNifToOgreHandleMap.end()) - return entry->second; - } - throw std::runtime_error("Invalid NIF record lookup ("+nifname+", index "+Ogre::StringConverter::toString(idx)+")"); -} - -NIFSkeletonLoader::LoaderMap NIFSkeletonLoader::sLoaders; - -} diff --git a/components/nifogre/skeleton.hpp b/components/nifogre/skeleton.hpp deleted file mode 100644 index 9ec3a0c82..000000000 --- a/components/nifogre/skeleton.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef COMPONENTS_NIFOGRE_SKELETON_HPP -#define COMPONENTS_NIFOGRE_SKELETON_HPP - -#include -#include -#include - -#include - -#include "ogrenifloader.hpp" - -namespace Nif -{ - class NiTextKeyExtraData; - class Node; - class NiKeyframeController; -} - -namespace NifOgre -{ - -/** Manual resource loader for NIF skeletons. This is the main class - responsible for translating the internal NIF skeleton structure into - something Ogre can use (includes animations and node TextKeyData). - */ -class NIFSkeletonLoader : public Ogre::ManualResourceLoader -{ - static void warn(const std::string &msg) - { - std::cerr << "NIFSkeletonLoader: Warn: " << msg << std::endl; - } - - static void fail(const std::string &msg) - { - std::cerr << "NIFSkeletonLoader: Fail: "<< msg << std::endl; - abort(); - } - - void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *parent=NULL); - - static bool needSkeleton(const Nif::Node *node); - - // Lookup to retrieve an Ogre bone handle for a given Nif record index - std::map mNifToOgreHandleMap; - - typedef std::map LoaderMap; - static LoaderMap sLoaders; - -public: - void loadResource(Ogre::Resource *resource); - - static Ogre::SkeletonPtr createSkeleton(const std::string &name, const std::string &group, const Nif::Node *node); - - // Looks up an Ogre Bone handle ID from a NIF's record index. Should only - // be used when the bone name is insufficient as this is a relatively slow - // lookup - static int lookupOgreBoneHandle(const std::string &nifname, int idx); -}; - -} - -#endif diff --git a/components/ogreinit/ogreinit.cpp b/components/ogreinit/ogreinit.cpp index 574b67f19..e8ca2e8bd 100644 --- a/components/ogreinit/ogreinit.cpp +++ b/components/ogreinit/ogreinit.cpp @@ -15,8 +15,6 @@ #include #endif -#include - #include #include @@ -118,8 +116,6 @@ namespace OgreInit loadPlugins(); #endif - loadParticleFactories(); - return mRoot; } @@ -128,16 +124,6 @@ namespace OgreInit delete mRoot; delete Ogre::LogManager::getSingletonPtr(); - std::vector::iterator ei; - for(ei = mEmitterFactories.begin();ei != mEmitterFactories.end();++ei) - OGRE_DELETE (*ei); - mEmitterFactories.clear(); - - std::vector::iterator ai; - for(ai = mAffectorFactories.begin();ai != mAffectorFactories.end();++ai) - OGRE_DELETE (*ai); - mAffectorFactories.clear(); - #ifdef ENABLE_PLUGIN_GL delete mGLPlugin; mGLPlugin = NULL; @@ -221,22 +207,4 @@ namespace OgreInit if (!Files::loadOgrePlugin(pluginDir, "Plugin_ParticleFX", *mRoot)) throw std::runtime_error("Required Plugin_ParticleFX for Ogre not found!"); } - - void OgreInit::loadParticleFactories() - { - Ogre::ParticleEmitterFactory *emitter; - emitter = OGRE_NEW NifEmitterFactory(); - Ogre::ParticleSystemManager::getSingleton().addEmitterFactory(emitter); - mEmitterFactories.push_back(emitter); - - Ogre::ParticleAffectorFactory *affector; - affector = OGRE_NEW GrowFadeAffectorFactory(); - Ogre::ParticleSystemManager::getSingleton().addAffectorFactory(affector); - mAffectorFactories.push_back(affector); - - affector = OGRE_NEW GravityAffectorFactory(); - Ogre::ParticleSystemManager::getSingleton().addAffectorFactory(affector); - mAffectorFactories.push_back(affector); - } - } diff --git a/components/ogreinit/ogreinit.hpp b/components/ogreinit/ogreinit.hpp index 9613421f7..d1743950f 100644 --- a/components/ogreinit/ogreinit.hpp +++ b/components/ogreinit/ogreinit.hpp @@ -48,13 +48,10 @@ namespace OgreInit ~OgreInit(); private: - std::vector mEmitterFactories; - std::vector mAffectorFactories; Ogre::Root* mRoot; void loadStaticPlugins(); void loadPlugins(); - void loadParticleFactories(); #ifdef ENABLE_PLUGIN_CgProgramManager Ogre::CgPlugin* mCgPlugin;