Create particle systems for NiAutoNormalParticles and NiRotatingParticles nodes

Very incomplete, but it's something to work with.
actorid
Chris Robinson 12 years ago
parent 77ba0fbe73
commit b5719e0ec7

@ -35,6 +35,8 @@
#include <OgreEntity.h>
#include <OgreSubEntity.h>
#include <OgreTagPoint.h>
#include <OgreParticleSystem.h>
#include <OgreParticleEmitter.h>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
@ -317,7 +319,9 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro
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_NiTriShape || /* Handled in the mesh loader */
node->recType == Nif::RC_NiAutoNormalParticles ||
node->recType == Nif::RC_NiRotatingParticles
))
warn("Unhandled "+node->recName+" "+node->name+" in "+skel->getName());
@ -326,7 +330,8 @@ void buildBones(Ogre::Skeleton *skel, const Nif::Node *node, Ogre::Bone *&animro
{
if(ctrl->recType == Nif::RC_NiKeyframeController)
ctrls.push_back(static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr()));
else
else if(!(ctrl->recType == Nif::RC_NiParticleSystemController
))
warn("Unhandled "+ctrl->recName+" from node "+node->name+" in "+skel->getName());
ctrl = ctrl->next;
}
@ -588,7 +593,8 @@ static std::string findTextureName(const std::string &filename)
}
public:
static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String &name, const Ogre::String &group,
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,
@ -617,7 +623,7 @@ static Ogre::String getMaterial(const Nif::NiTriShape *shape, const Ogre::String
int specFlags = 0;
Ogre::String texName[7];
bool vertexColour = (shape->data->colors.size() != 0);
bool vertexColour = (shapedata->colors.size() != 0);
// Texture
if(texprop)
@ -819,12 +825,12 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
std::string mGroup;
size_t mShapeIndex;
void warn(const std::string &msg)
static void warn(const std::string &msg)
{
std::cerr << "NIFMeshLoader: Warn: " << msg << std::endl;
}
void fail(const std::string &msg)
static void fail(const std::string &msg)
{
std::cerr << "NIFMeshLoader: Fail: "<< msg << std::endl;
abort();
@ -1039,9 +1045,10 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
}
bool needTangents=false;
std::string matname = NIFMaterialLoader::getMaterial(shape, mesh->getName(), mGroup,
std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup,
texprop, matprop, alphaprop,
vertprop, zprop, specprop, needTangents);
vertprop, zprop, specprop,
needTangents);
if(matname.length() > 0)
sub->setMaterialName(matname);
@ -1114,6 +1121,146 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
static LoaderMap sLoaders;
static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl)
{
Ogre::ParticleEmitter *emitter = partsys->addEmitter("Point");
emitter->setDirection(Ogre::Vector3::UNIT_Z);
emitter->setParticleVelocity(partctrl->velocity-partctrl->velocityRandom,
partctrl->velocity+partctrl->velocityRandom);
emitter->setEmissionRate(partctrl->emitRate);
emitter->setTimeToLive(partctrl->lifetime-partctrl->lifetimeRandom,
partctrl->lifetime+partctrl->lifetimeRandom);
Nif::ExtraPtr e = partctrl->extra;
while(!e.empty())
{
if(e->recType == Nif::RC_NiParticleGrowFade)
{
// TODO: Implement
}
else if(e->recType == Nif::RC_NiParticleColorModifier)
{
// TODO: Implement (Ogre::ColourInterpolatorAffector?)
}
else if(e->recType == Nif::RC_NiGravity)
{
// TODO: Implement (Ogre::LinearForceAffector?)
}
else
warn("Unhandled particle modifier "+e->recName);
e = e->extra;
}
}
Ogre::ParticleSystem *createParticleSystem(Ogre::SceneManager *sceneMgr, Ogre::Entity *entitybase,
const Nif::Node *partnode)
{
const Nif::NiAutoNormalParticlesData *particledata = NULL;
if(partnode->recType == Nif::RC_NiAutoNormalParticles)
particledata = static_cast<const Nif::NiAutoNormalParticles*>(partnode)->data.getPtr();
else if(partnode->recType == Nif::RC_NiRotatingParticles)
particledata = static_cast<const Nif::NiRotatingParticles*>(partnode)->data.getPtr();
Ogre::ParticleSystem *partsys = sceneMgr->createParticleSystem();
try {
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;
if(partnode->parent)
{
// FIXME: We should probably search down the whole tree instead of just the parent
const Nif::PropertyList &proplist = partnode->parent->props;
for(size_t i = 0;i < proplist.length();i++)
{
// Entries may be empty
if(proplist[i].empty())
continue;
const Nif::Property *pr = proplist[i].getPtr();
if(pr->recType == Nif::RC_NiTexturingProperty)
texprop = static_cast<const Nif::NiTexturingProperty*>(pr);
else if(pr->recType == Nif::RC_NiMaterialProperty)
matprop = static_cast<const Nif::NiMaterialProperty*>(pr);
else if(pr->recType == Nif::RC_NiAlphaProperty)
alphaprop = static_cast<const Nif::NiAlphaProperty*>(pr);
else if(pr->recType == Nif::RC_NiVertexColorProperty)
vertprop = static_cast<const Nif::NiVertexColorProperty*>(pr);
else if(pr->recType == Nif::RC_NiZBufferProperty)
zprop = static_cast<const Nif::NiZBufferProperty*>(pr);
else if(pr->recType == Nif::RC_NiSpecularProperty)
specprop = static_cast<const Nif::NiSpecularProperty*>(pr);
else
warn("Unhandled property type: "+pr->recName);
}
}
const Nif::PropertyList &proplist = partnode->props;
for(size_t i = 0;i < proplist.length();i++)
{
// Entries may be empty
if(proplist[i].empty())
continue;
const Nif::Property *pr = proplist[i].getPtr();
if(pr->recType == Nif::RC_NiTexturingProperty)
texprop = static_cast<const Nif::NiTexturingProperty*>(pr);
else if(pr->recType == Nif::RC_NiMaterialProperty)
matprop = static_cast<const Nif::NiMaterialProperty*>(pr);
else if(pr->recType == Nif::RC_NiAlphaProperty)
alphaprop = static_cast<const Nif::NiAlphaProperty*>(pr);
else if(pr->recType == Nif::RC_NiVertexColorProperty)
vertprop = static_cast<const Nif::NiVertexColorProperty*>(pr);
else if(pr->recType == Nif::RC_NiZBufferProperty)
zprop = static_cast<const Nif::NiZBufferProperty*>(pr);
else if(pr->recType == Nif::RC_NiSpecularProperty)
specprop = static_cast<const Nif::NiSpecularProperty*>(pr);
else
warn("Unhandled property type: "+pr->recName);
}
std::string fullname = mName+"@index="+Ogre::StringConverter::toString(partnode->recIndex);
if(partnode->name.length() > 0)
fullname += "@type="+partnode->name;
Misc::StringUtils::toLower(fullname);
bool needTangents;
partsys->setMaterialName(NIFMaterialLoader::getMaterial(particledata, fullname, mGroup,
texprop, matprop, alphaprop,
vertprop, zprop, specprop,
needTangents));
partsys->setDefaultDimensions(particledata->particleSize, particledata->particleSize);
partsys->setCullIndividually(false);
partsys->setParticleQuota(particledata->activeCount);
Nif::ControllerPtr ctrl = partnode->controller;
while(!ctrl.empty())
{
if(ctrl->recType == Nif::RC_NiParticleSystemController)
{
const Nif::NiParticleSystemController *partctrl = static_cast<const Nif::NiParticleSystemController*>(ctrl.getPtr());
createParticleEmitterAffectors(partsys, partctrl);
if(!partctrl->emitter.empty() && !partsys->isAttached())
entitybase->attachObjectToBone(partctrl->emitter->name, partsys);
}
ctrl = ctrl->next;
}
if(!partsys->isAttached())
entitybase->attachObjectToBone(partnode->name, partsys);
}
catch(std::exception &e) {
std::cerr<< "Particles exception: "<<e.what() <<std::endl;
sceneMgr->destroyParticleSystem(partsys);
partsys = NULL;
};
return partsys;
}
NIFMeshLoader(const std::string &name, const std::string &group)
: mName(name), mGroup(group), mShapeIndex(~(size_t)0)
{ }
@ -1199,6 +1346,14 @@ class NIFMeshLoader : Ogre::ManualResourceLoader
}
}
if((node->recType == Nif::RC_NiAutoNormalParticles ||
node->recType == Nif::RC_NiRotatingParticles) && !(flags&0x01))
{
Ogre::ParticleSystem *partsys = createParticleSystem(sceneMgr, entities.mSkelBase, node);
if(partsys != NULL)
entities.mParticles.push_back(partsys);
}
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(node);
if(ninode)
{

Loading…
Cancel
Save