Delete the old nifogre loader

pull/638/head
scrawl 10 years ago
parent 376f0f3ac1
commit 1affa497d5

@ -50,10 +50,6 @@ add_component_dir (nifosg
# nifcache
# )
#add_component_dir (nifogre
# ogrenifloader skeleton material mesh particles controller
# )
#add_component_dir (nifbullet
# bulletnifloader
# )

@ -1,111 +0,0 @@
#ifndef COMPONENTS_NIFOGRE_CONTROLLER_H
#define COMPONENTS_NIFOGRE_CONTROLLER_H
#include <components/nif/niffile.hpp>
#include <components/nif/nifkey.hpp>
#include <OgreController.h>
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<Ogre::Real>
{
private:
float mFrequency;
float mPhase;
float mStartTime;
public:
float mStopTime;
public:
DefaultFunction(const Nif::Controller *ctrl, bool deltaInput)
: Ogre::ControllerFunction<Ogre::Real>(deltaInput)
, mFrequency(ctrl->frequency)
, mPhase(ctrl->phase)
, mStartTime(ctrl->timeStart)
, mStopTime(ctrl->timeStop)
{
if(mDeltaInput)
mDeltaCount = mPhase;
}
virtual Ogre::Real calculate(Ogre::Real value)
{
if(mDeltaInput)
{
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

@ -1,442 +0,0 @@
#include "material.hpp"
#include <components/nif/node.hpp>
#include <components/misc/resourcehelpers.hpp>
#include <components/settings/settings.hpp>
#include <components/nifoverrides/nifoverrides.hpp>
#include <extern/shiny/Main/Factory.hpp>
#include <OgreMaterialManager.h>
#include <OgreMaterial.h>
#include <boost/functional/hash.hpp>
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: "<<mode <<std::endl;
return "src_alpha";
}
static const char *getTestMode(int mode)
{
switch(mode)
{
case 0: return "always_pass";
case 1: return "less";
case 2: return "equal";
case 3: return "less_equal";
case 4: return "greater";
case 5: return "not_equal";
case 6: return "greater_equal";
case 7: return "always_fail";
}
std::cerr<< "Unexpected test mode: "<<mode <<std::endl;
return "less_equal";
}
static void setTextureProperties(sh::MaterialInstance* material, const std::string& textureSlotName, const Nif::NiTexturingProperty::Texture& tex)
{
material->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<size_t,std::string>::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<sh::StringValue>(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: "<<vertMode <<std::endl;
if(specFlags)
{
instance->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<sh::StringValue>(instance->getProperty("normalMap"), instance).get().empty();
return name;
}
std::map<size_t,std::string> NIFMaterialLoader::sMaterialMap;
}

@ -1,51 +0,0 @@
#ifndef COMPONENTS_NIFOGRE_MATERIAL_HPP
#define COMPONENTS_NIFOGRE_MATERIAL_HPP
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <OgreString.h>
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<size_t,std::string> 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

@ -1,412 +0,0 @@
#include "mesh.hpp"
#include <limits>
#include <OgreMeshManager.h>
#include <OgreMesh.h>
#include <OgreSubMesh.h>
#include <OgreBone.h>
#include <OgreHardwareBufferManager.h>
#include <OgreMaterialManager.h>
#include <OgreSkeletonManager.h>
#include <OgreRenderSystem.h>
#include <OgreRoot.h>
#include <OgreSkeleton.h>
#include <OgreKeyFrame.h>
#include <components/nif/node.hpp>
#include <components/nifcache/nifcache.hpp>
#include <components/misc/stringops.hpp>
#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<float>::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;i<verts;i++)
{
X.add(*(data++));
Y.add(*(data++));
Z.add(*(data++));
}
}
// True if this structure has valid values
bool isValid()
{
return
minX() <= maxX() &&
minY() <= maxY() &&
minZ() <= maxZ();
}
// Compute radius
float getRadius()
{
assert(isValid());
// The radius is computed from the origin, not from the geometric
// center of the mesh.
return sqrt(X.getMaxSquared() + Y.getMaxSquared() + Z.getMaxSquared());
}
float minX() {
return X.min;
}
float maxX() {
return X.max;
}
float minY() {
return Y.min;
}
float maxY() {
return Y.max;
}
float minZ() {
return Z.min;
}
float maxZ() {
return Z.max;
}
};
NIFMeshLoader::LoaderMap NIFMeshLoader::sLoaders;
void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape)
{
const Nif::NiTriShapeData *data = shape->data.getPtr();
const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr());
std::vector<Ogre::Vector3> srcVerts = data->vertices;
std::vector<Ogre::Vector3> 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<Ogre::Vector3> newVerts(srcVerts.size(), Ogre::Vector3(0.0f));
std::vector<Ogre::Vector3> 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<Nif::NiSkinData::VertWeight> &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<Ogre::Vector4> &colors = data->colors;
if(colors.size())
{
Ogre::RenderSystem *rs = Ogre::Root::getSingleton().getRenderSystem();
std::vector<Ogre::RGBA> 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<Ogre::Vector2> allUVs;
allUVs.reserve(srcVerts.size()*numUVs);
for (size_t vert = 0; vert<srcVerts.size(); ++vert)
for(size_t i = 0; i < numUVs; i++)
allUVs.push_back(data->uvlist[i][vert]);
vbuf->writeData(0, elemSize*srcVerts.size()*numUVs, &allUVs[0], true);
bind->setBinding(nextBuf++, vbuf);
}
// Triangle faces
const std::vector<short> &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<Nif::NiSkinData::VertWeight> &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<const Nif::NiGeomMorpherController*>(ctrl.getPtr());
const std::vector<Nif::NiMorphData::MorphData>& 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<Ogre::Mesh*>(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<const Nif::NiTriShape*>(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);
}
}

@ -1,55 +0,0 @@
#ifndef COMPONENTS_NIFOGRE_MESH_HPP
#define COMPONENTS_NIFOGRE_MESH_HPP
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <OgreResource.h>
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<std::string,NIFMeshLoader> 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

File diff suppressed because it is too large Load Diff

@ -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 <OgreResource.h>
#include <OgreMaterial.h>
#include <OgreController.h>
#include <vector>
#include <string>
#include <map>
// 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<Ogre::MovableObject*, Ogre::MaterialPtr> mClonedMaterials;
};
typedef std::multimap<float,std::string> TextKeyMap;
static const char sTextKeyExtraDataID[] = "TextKeyExtraData";
struct ObjectScene {
Ogre::Entity *mSkelBase;
std::vector<Ogre::Entity*> mEntities;
std::vector<Ogre::ParticleSystem*> mParticles;
std::vector<Ogre::Light*> mLights;
// Nodes that should always face the camera when rendering
std::vector<Ogre::Node*> 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<Ogre::Controller<Ogre::Real> > 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<ObjectScene> 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<Ogre::Controller<Ogre::Real> > &ctrls);
private:
static bool sShowMarkers;
};
// FIXME: Should be with other general Ogre extensions.
template<typename T>
class NodeTargetValue : public Ogre::ControllerValue<T>
{
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<NodeTargetValue<Ogre::Real> > NodeTargetValueRealPtr;
}
#endif

@ -1,773 +0,0 @@
#include "particles.hpp"
#include <OgreStringConverter.h>
#include <OgreParticleSystem.h>
#include <OgreParticleEmitter.h>
#include <OgreParticleAffector.h>
#include <OgreParticle.h>
#include <OgreBone.h>
#include <OgreTagPoint.h>
#include <OgreEntity.h>
#include <OgreSkeletonInstance.h>
#include <OgreSceneNode.h>
#include <OgreSceneManager.h>
/* FIXME: "Nif" isn't really an appropriate emitter name. */
class NifEmitter : public Ogre::ParticleEmitter
{
public:
std::vector<Ogre::Bone*> 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<const NifEmitter*>(target)->getWidth());
}
void doSet(void *target, const Ogre::String &val)
{
static_cast<NifEmitter*>(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<const NifEmitter*>(target)->getHeight());
}
void doSet(void *target, const Ogre::String &val)
{
static_cast<NifEmitter*>(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<const NifEmitter*>(target)->getDepth());
}
void doSet(void *target, const Ogre::String &val)
{
static_cast<NifEmitter*>(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<const NifEmitter*>(target);
return Ogre::StringConverter::toString(self->getVerticalDirection().valueDegrees());
}
void doSet(void *target, const Ogre::String &val)
{
NifEmitter *self = static_cast<NifEmitter*>(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<const NifEmitter*>(target);
return Ogre::StringConverter::toString(self->getVerticalAngle().valueDegrees());
}
void doSet(void *target, const Ogre::String &val)
{
NifEmitter *self = static_cast<NifEmitter*>(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<const NifEmitter*>(target);
return Ogre::StringConverter::toString(self->getHorizontalDirection().valueDegrees());
}
void doSet(void *target, const Ogre::String &val)
{
NifEmitter *self = static_cast<NifEmitter*>(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<const NifEmitter*>(target);
return Ogre::StringConverter::toString(self->getHorizontalAngle().valueDegrees());
}
void doSet(void *target, const Ogre::String &val)
{
NifEmitter *self = static_cast<NifEmitter*>(target);
self->setHorizontalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
}
};
NifEmitter(Ogre::ParticleSystem *psys)
: Ogre::ParticleEmitter(psys)
, mEmitterBones(Ogre::any_cast<NiNodeHolder>(psys->getUserObjectBindings().getUserAny()).mBones)
{
assert (!mEmitterBones.empty());
Ogre::TagPoint* tag = static_cast<Ogre::TagPoint*>(mParent->getParentNode());
mParticleBone = static_cast<Ogre::Bone*>(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<const GrowFadeAffector*>(target);
return Ogre::StringConverter::toString(self->getGrowTime());
}
void doSet(void *target, const Ogre::String &val)
{
GrowFadeAffector *self = static_cast<GrowFadeAffector*>(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<const GrowFadeAffector*>(target);
return Ogre::StringConverter::toString(self->getFadeTime());
}
void doSet(void *target, const Ogre::String &val)
{
GrowFadeAffector *self = static_cast<GrowFadeAffector*>(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<const GravityAffector*>(target);
return Ogre::StringConverter::toString(self->getForce());
}
void doSet(void *target, const Ogre::String &val)
{
GravityAffector *self = static_cast<GravityAffector*>(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<const GravityAffector*>(target);
return getStringFromType(self->getForceType());
}
void doSet(void *target, const Ogre::String &val)
{
GravityAffector *self = static_cast<GravityAffector*>(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<const GravityAffector*>(target);
return Ogre::StringConverter::toString(self->getDirection());
}
void doSet(void *target, const Ogre::String &val)
{
GravityAffector *self = static_cast<GravityAffector*>(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<const GravityAffector*>(target);
return Ogre::StringConverter::toString(self->getPosition());
}
void doSet(void *target, const Ogre::String &val)
{
GravityAffector *self = static_cast<GravityAffector*>(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<Ogre::Bone*> bones = Ogre::any_cast<NiNodeHolder>(psys->getUserObjectBindings().getUserAny()).mBones;
assert (!bones.empty());
mEmitterBone = bones[0];
Ogre::TagPoint* tag = static_cast<Ogre::TagPoint*>(mParent->getParentNode());
mParticleBone = static_cast<Ogre::Bone*>(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;
}

@ -1,50 +0,0 @@
#ifndef OENGINE_OGRE_PARTICLES_H
#define OENGINE_OGRE_PARTICLES_H
#include <OgreParticleEmitterFactory.h>
#include <OgreParticleAffectorFactory.h>
/** 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<Ogre::Bone*> 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 */

@ -1,179 +0,0 @@
#include "skeleton.hpp"
#include <OgreSkeletonManager.h>
#include <OgreResource.h>
#include <OgreSkeleton.h>
#include <OgreBone.h>
#include <components/nif/node.hpp>
#include <components/nifcache/nifcache.hpp>
#include <components/misc/stringops.hpp>
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<const Nif::NiNode*>(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<Ogre::Skeleton*>(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<const Nif::Node*>(nif->getRoot(0));
try {
buildBones(skel, node);
}
catch(std::exception &e) {
std::cerr<< "Exception while loading "<<skel->getName() <<std::endl;
std::cerr<< e.what() <<std::endl;
return;
}
}
bool NIFSkeletonLoader::needSkeleton(const Nif::Node *node)
{
/* We need to be a little aggressive here, since some NIFs have a crap-ton
* of nodes and Ogre only supports 256 bones. We will skip a skeleton if:
* There are no bones used for skinning, there are no keyframe controllers, there
* are no nodes named "AttachLight" or "ArrowBone", and the tree consists of NiNode,
* NiTriShape, and RootCollisionNode types only.
*/
if(node->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<const Nif::NiNode*>(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<int,int>::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;
}

@ -1,62 +0,0 @@
#ifndef COMPONENTS_NIFOGRE_SKELETON_HPP
#define COMPONENTS_NIFOGRE_SKELETON_HPP
#include <iostream>
#include <string>
#include <cassert>
#include <OgreResource.h>
#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<int,int> mNifToOgreHandleMap;
typedef std::map<std::string,NIFSkeletonLoader> 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

@ -15,8 +15,6 @@
#include <OSX/macUtils.h>
#endif
#include <components/nifogre/particles.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
@ -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<Ogre::ParticleEmitterFactory*>::iterator ei;
for(ei = mEmitterFactories.begin();ei != mEmitterFactories.end();++ei)
OGRE_DELETE (*ei);
mEmitterFactories.clear();
std::vector<Ogre::ParticleAffectorFactory*>::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);
}
}

@ -48,13 +48,10 @@ namespace OgreInit
~OgreInit();
private:
std::vector<Ogre::ParticleEmitterFactory*> mEmitterFactories;
std::vector<Ogre::ParticleAffectorFactory*> mAffectorFactories;
Ogre::Root* mRoot;
void loadStaticPlugins();
void loadPlugins();
void loadParticleFactories();
#ifdef ENABLE_PLUGIN_CgProgramManager
Ogre::CgPlugin* mCgPlugin;

Loading…
Cancel
Save