forked from mirror/openmw-tes3mp
Add particle system state loading
This commit is contained in:
parent
2a92fb57f7
commit
8d64f2081e
3 changed files with 111 additions and 16 deletions
|
@ -221,7 +221,7 @@ if (${OGRE_VERSION} VERSION_LESS "1.9")
|
||||||
message(FATAL_ERROR "OpenMW requires Ogre 1.9 or later, please install the latest stable version from http://ogre3d.org")
|
message(FATAL_ERROR "OpenMW requires Ogre 1.9 or later, please install the latest stable version from http://ogre3d.org")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(OpenSceneGraph 3.2.0 REQUIRED osgDB osgViewer osgGA osgAnimation)
|
find_package(OpenSceneGraph 3.2.0 REQUIRED osgDB osgViewer osgGA osgAnimation osgParticle)
|
||||||
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
|
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS})
|
||||||
|
|
||||||
find_package(MyGUI REQUIRED)
|
find_package(MyGUI REQUIRED)
|
||||||
|
|
|
@ -18,6 +18,10 @@
|
||||||
#include <osgAnimation/RigGeometry>
|
#include <osgAnimation/RigGeometry>
|
||||||
#include <osgAnimation/MorphGeometry>
|
#include <osgAnimation/MorphGeometry>
|
||||||
|
|
||||||
|
// particle
|
||||||
|
#include <osgParticle/ParticleSystem>
|
||||||
|
#include <osgParticle/ParticleSystemUpdater>
|
||||||
|
|
||||||
#include <osg/BlendFunc>
|
#include <osg/BlendFunc>
|
||||||
#include <osg/AlphaFunc>
|
#include <osg/AlphaFunc>
|
||||||
#include <osg/Depth>
|
#include <osg/Depth>
|
||||||
|
@ -177,6 +181,17 @@ namespace
|
||||||
osg::Node* mSkelRoot;
|
osg::Node* mSkelRoot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// HACK: Particle doesn't allow setting the initial age, but we need this for loading the particle system state
|
||||||
|
class ParticleAgeSetter : public osgParticle::Particle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ParticleAgeSetter(float age)
|
||||||
|
: Particle()
|
||||||
|
{
|
||||||
|
_t0 = age;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geometry> handleMorphGeometry(const Nif::NiGeomMorpherController* morpher)
|
osg::ref_ptr<osg::Geometry> handleMorphGeometry(const Nif::NiGeomMorpherController* morpher)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osgAnimation::MorphGeometry> morphGeom = new osgAnimation::MorphGeometry;
|
osg::ref_ptr<osgAnimation::MorphGeometry> morphGeom = new osgAnimation::MorphGeometry;
|
||||||
|
@ -220,7 +235,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
mRootNode = parentNode;
|
mRootNode = parentNode;
|
||||||
handleNode(nifNode, parentNode, false, std::map<int, int>(), 0);
|
handleNode(nifNode, parentNode, false, std::map<int, int>(), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::loadAsSkeleton(Nif::NIFFilePtr nif, osg::Group *parentNode)
|
void Loader::loadAsSkeleton(Nif::NIFFilePtr nif, osg::Group *parentNode)
|
||||||
|
@ -249,7 +264,7 @@ namespace NifOsg
|
||||||
mSkeleton = skel;
|
mSkeleton = skel;
|
||||||
mRootNode->addChild(mSkeleton);
|
mRootNode->addChild(mSkeleton);
|
||||||
|
|
||||||
handleNode(nifNode, mSkeleton, true, std::map<int, int>(), 0);
|
handleNode(nifNode, mSkeleton, true, std::map<int, int>(), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, std::map<int, int>& boundTextures, int animflags)
|
void Loader::applyNodeProperties(const Nif::Node *nifNode, osg::Node *applyTo, std::map<int, int>& boundTextures, int animflags)
|
||||||
|
@ -276,7 +291,7 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton,
|
void Loader::handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton,
|
||||||
std::map<int, int> boundTextures, int animflags, bool collisionNode)
|
std::map<int, int> boundTextures, int animflags, int particleflags, bool collisionNode)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::MatrixTransform> transformNode;
|
osg::ref_ptr<osg::MatrixTransform> transformNode;
|
||||||
if (createSkeleton)
|
if (createSkeleton)
|
||||||
|
@ -327,6 +342,9 @@ namespace NifOsg
|
||||||
handleMeshControllers(nifNode, transformNode, boundTextures, animflags);
|
handleMeshControllers(nifNode, transformNode, boundTextures, animflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(nifNode->recType == Nif::RC_NiAutoNormalParticles || nifNode->recType == Nif::RC_NiRotatingParticles)
|
||||||
|
handleParticleSystem(nifNode, transformNode, particleflags, animflags);
|
||||||
|
|
||||||
if (!nifNode->controller.empty())
|
if (!nifNode->controller.empty())
|
||||||
handleNodeControllers(nifNode, transformNode, animflags);
|
handleNodeControllers(nifNode, transformNode, animflags);
|
||||||
|
|
||||||
|
@ -337,7 +355,7 @@ namespace NifOsg
|
||||||
for(size_t i = 0;i < children.length();++i)
|
for(size_t i = 0;i < children.length();++i)
|
||||||
{
|
{
|
||||||
if(!children[i].empty())
|
if(!children[i].empty())
|
||||||
handleNode(children[i].getPtr(), transformNode, createSkeleton, boundTextures, animflags, collisionNode);
|
handleNode(children[i].getPtr(), transformNode, createSkeleton, boundTextures, animflags, particleflags, collisionNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,6 +364,8 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
|
continue;
|
||||||
if (ctrl->recType == Nif::RC_NiUVController)
|
if (ctrl->recType == Nif::RC_NiUVController)
|
||||||
{
|
{
|
||||||
const Nif::NiUVController *uvctrl = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
const Nif::NiUVController *uvctrl = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
||||||
|
@ -364,6 +384,8 @@ namespace NifOsg
|
||||||
bool seenKeyframeCtrl = false;
|
bool seenKeyframeCtrl = false;
|
||||||
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
|
continue;
|
||||||
if (ctrl->recType == Nif::RC_NiKeyframeController)
|
if (ctrl->recType == Nif::RC_NiKeyframeController)
|
||||||
{
|
{
|
||||||
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
|
const Nif::NiKeyframeController *key = static_cast<const Nif::NiKeyframeController*>(ctrl.getPtr());
|
||||||
|
@ -394,6 +416,8 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = materialProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
|
continue;
|
||||||
if (ctrl->recType == Nif::RC_NiAlphaController)
|
if (ctrl->recType == Nif::RC_NiAlphaController)
|
||||||
{
|
{
|
||||||
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
const Nif::NiAlphaController* alphactrl = static_cast<const Nif::NiAlphaController*>(ctrl.getPtr());
|
||||||
|
@ -415,6 +439,8 @@ namespace NifOsg
|
||||||
{
|
{
|
||||||
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
for (Nif::ControllerPtr ctrl = texProperty->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
{
|
{
|
||||||
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
|
continue;
|
||||||
if (ctrl->recType == Nif::RC_NiFlipController)
|
if (ctrl->recType == Nif::RC_NiFlipController)
|
||||||
{
|
{
|
||||||
const Nif::NiFlipController* flipctrl = static_cast<const Nif::NiFlipController*>(ctrl.getPtr());
|
const Nif::NiFlipController* flipctrl = static_cast<const Nif::NiFlipController*>(ctrl.getPtr());
|
||||||
|
@ -450,6 +476,71 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Loader::handleParticleSystem(const Nif::Node *nifNode, osg::Group *parentNode, int particleflags, int animflags)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osgParticle::ParticleSystem> partsys (new osgParticle::ParticleSystem);
|
||||||
|
|
||||||
|
const Nif::NiAutoNormalParticlesData *particledata = NULL;
|
||||||
|
if(nifNode->recType == Nif::RC_NiAutoNormalParticles)
|
||||||
|
particledata = static_cast<const Nif::NiAutoNormalParticles*>(nifNode)->data.getPtr();
|
||||||
|
else if(nifNode->recType == Nif::RC_NiRotatingParticles)
|
||||||
|
particledata = static_cast<const Nif::NiRotatingParticles*>(nifNode)->data.getPtr();
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Nif::NiParticleSystemController* partctrl = NULL;
|
||||||
|
for (Nif::ControllerPtr ctrl = nifNode->controller; !ctrl.empty(); ctrl = ctrl->next)
|
||||||
|
{
|
||||||
|
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||||
|
continue;
|
||||||
|
if(ctrl->recType == Nif::RC_NiParticleSystemController || ctrl->recType == Nif::RC_NiBSPArrayController)
|
||||||
|
partctrl = static_cast<Nif::NiParticleSystemController*>(ctrl.getPtr());
|
||||||
|
}
|
||||||
|
if (!partctrl)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
for (std::vector<Nif::NiParticleSystemController::Particle>::const_iterator it = partctrl->particles.begin();
|
||||||
|
i<particledata->activeCount && it != partctrl->particles.end(); ++it, ++i)
|
||||||
|
{
|
||||||
|
const Nif::NiParticleSystemController::Particle& particle = *it;
|
||||||
|
|
||||||
|
ParticleAgeSetter particletemplate(std::max(0.f, particle.lifespan - particle.lifetime));
|
||||||
|
|
||||||
|
osgParticle::Particle* created = partsys->createParticle(&particletemplate);
|
||||||
|
created->setLifeTime(500);//std::max(0.f, particle.lifespan));
|
||||||
|
created->setVelocity(particle.velocity);
|
||||||
|
created->setPosition(particledata->vertices.at(particle.vertex));
|
||||||
|
|
||||||
|
osg::Vec4f partcolor (1.f,1.f,1.f,1.f);
|
||||||
|
if (particle.vertex < int(particledata->colors.size()))
|
||||||
|
partcolor = particledata->colors.at(particle.vertex);
|
||||||
|
|
||||||
|
float size = particledata->sizes.at(particle.vertex) * partctrl->size;
|
||||||
|
|
||||||
|
created->setSizeRange(osgParticle::rangef(size, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::NodeVisitor visitor;
|
||||||
|
partsys->update(0.f, visitor);
|
||||||
|
partsys->setFrozen(true);
|
||||||
|
partsys->setSortMode(osgParticle::ParticleSystem::SORT_BACK_TO_FRONT);
|
||||||
|
|
||||||
|
std::vector<const Nif::Property*> materialProps;
|
||||||
|
collectMaterialProperties(nifNode, materialProps);
|
||||||
|
applyMaterialProperties(partsys->getOrCreateStateSet(), materialProps, true, animflags);
|
||||||
|
|
||||||
|
partsys->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
|
partsys->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
|
geode->addDrawable(partsys);
|
||||||
|
parentNode->addChild(geode);
|
||||||
|
|
||||||
|
osgParticle::ParticleSystemUpdater* updater = new osgParticle::ParticleSystemUpdater;
|
||||||
|
updater->addParticleSystem(partsys);
|
||||||
|
parentNode->addChild(updater);
|
||||||
|
}
|
||||||
|
|
||||||
void Loader::triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, const std::map<int, int>& boundTextures, int animflags)
|
void Loader::triShapeToGeometry(const Nif::NiTriShape *triShape, osg::Geometry *geometry, const std::map<int, int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||||
|
@ -554,18 +645,18 @@ namespace NifOsg
|
||||||
|
|
||||||
if (!geometry.get())
|
if (!geometry.get())
|
||||||
geometry = new osg::Geometry;
|
geometry = new osg::Geometry;
|
||||||
triShapeToGeometry(triShape, geometry.get(), boundTextures, animflags);
|
triShapeToGeometry(triShape, geometry, boundTextures, animflags);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
geode->addDrawable(geometry.get());
|
geode->addDrawable(geometry);
|
||||||
|
|
||||||
parentNode->addChild(geode.get());
|
parentNode->addChild(geode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, const std::map<int, int>& boundTextures, int animflags)
|
void Loader::handleSkinnedTriShape(const Nif::NiTriShape *triShape, osg::Group *parentNode, const std::map<int, int>& boundTextures, int animflags)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
osg::ref_ptr<osg::Geometry> geometry (new osg::Geometry);
|
||||||
triShapeToGeometry(triShape, geometry.get(), boundTextures, animflags);
|
triShapeToGeometry(triShape, geometry, boundTextures, animflags);
|
||||||
|
|
||||||
osg::ref_ptr<osgAnimation::RigGeometry> rig(new osgAnimation::RigGeometry);
|
osg::ref_ptr<osgAnimation::RigGeometry> rig(new osgAnimation::RigGeometry);
|
||||||
rig->setSourceGeometry(geometry);
|
rig->setSourceGeometry(geometry);
|
||||||
|
@ -600,16 +691,16 @@ namespace NifOsg
|
||||||
|
|
||||||
map->insert(std::make_pair(boneName, influence));
|
map->insert(std::make_pair(boneName, influence));
|
||||||
}
|
}
|
||||||
rig->setInfluenceMap(map.get());
|
rig->setInfluenceMap(map);
|
||||||
|
|
||||||
osg::ref_ptr<osg::MatrixTransform> trans(new osg::MatrixTransform);
|
osg::ref_ptr<osg::MatrixTransform> trans(new osg::MatrixTransform);
|
||||||
trans->setUpdateCallback(new InvertBoneMatrix(mSkeleton));
|
trans->setUpdateCallback(new InvertBoneMatrix(mSkeleton));
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
geode->addDrawable(rig.get());
|
geode->addDrawable(rig);
|
||||||
|
|
||||||
trans->addChild(geode.get());
|
trans->addChild(geode);
|
||||||
parentNode->addChild(trans.get());
|
parentNode->addChild(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::handleProperty(const Nif::Property *property, const Nif::Node* nifNode,
|
void Loader::handleProperty(const Nif::Property *property, const Nif::Node* nifNode,
|
||||||
|
@ -820,7 +911,8 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Loader::applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors, int animflags)
|
void Loader::applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties,
|
||||||
|
bool hasVertexColors, int animflags)
|
||||||
{
|
{
|
||||||
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
int specFlags = 0; // Specular is disabled by default, even if there's a specular color in the NiMaterialProperty
|
||||||
osg::Material* mat = new osg::Material;
|
osg::Material* mat = new osg::Material;
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace NifOsg
|
||||||
|
|
||||||
/// @param createSkeleton If true, use an osgAnimation::Bone for NIF nodes, otherwise an osg::MatrixTransform.
|
/// @param createSkeleton If true, use an osgAnimation::Bone for NIF nodes, otherwise an osg::MatrixTransform.
|
||||||
void handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton,
|
void handleNode(const Nif::Node* nifNode, osg::Group* parentNode, bool createSkeleton,
|
||||||
std::map<int, int> boundTextures, int animflags, bool collisionNode=false);
|
std::map<int, int> boundTextures, int animflags, int particleflags, bool collisionNode=false);
|
||||||
|
|
||||||
void handleMeshControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, const std::map<int, int>& boundTextures, int animflags);
|
void handleMeshControllers(const Nif::Node* nifNode, osg::MatrixTransform* transformNode, const std::map<int, int>& boundTextures, int animflags);
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ namespace NifOsg
|
||||||
void handleProperty (const Nif::Property* property, const Nif::Node* nifNode,
|
void handleProperty (const Nif::Property* property, const Nif::Node* nifNode,
|
||||||
osg::Node* node, std::map<int, int>& boundTextures, int animflags);
|
osg::Node* node, std::map<int, int>& boundTextures, int animflags);
|
||||||
|
|
||||||
|
void handleParticleSystem(const Nif::Node* nifNode, osg::Group* parentNode, int particleflags, int animflags);
|
||||||
|
|
||||||
// Creates an osg::Geometry object for the given TriShape, populates it, and attaches it to the given node.
|
// Creates an osg::Geometry object for the given TriShape, populates it, and attaches it to the given node.
|
||||||
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures, int animflags);
|
void handleTriShape(const Nif::NiTriShape* triShape, osg::Group* parentNode, const std::map<int, int>& boundTextures, int animflags);
|
||||||
|
|
||||||
|
@ -76,7 +78,8 @@ namespace NifOsg
|
||||||
// Applies the Properties of the given nifNode onto the StateSet of the given OSG node.
|
// Applies the Properties of the given nifNode onto the StateSet of the given OSG node.
|
||||||
void applyNodeProperties(const Nif::Node* nifNode, osg::Node* applyTo, std::map<int, int>& boundTextures, int animflags);
|
void applyNodeProperties(const Nif::Node* nifNode, osg::Node* applyTo, std::map<int, int>& boundTextures, int animflags);
|
||||||
|
|
||||||
void applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties, bool hasVertexColors, int animflags);
|
void applyMaterialProperties(osg::StateSet* stateset, const std::vector<const Nif::Property*>& properties,
|
||||||
|
bool hasVertexColors, int animflags);
|
||||||
|
|
||||||
void createController(const Nif::Controller* ctrl, boost::shared_ptr<ControllerValue> value, int animflags);
|
void createController(const Nif::Controller* ctrl, boost::shared_ptr<ControllerValue> value, int animflags);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue