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")
|
||||
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})
|
||||
|
||||
find_package(MyGUI REQUIRED)
|
||||
|
|
|
@ -18,6 +18,10 @@
|
|||
#include <osgAnimation/RigGeometry>
|
||||
#include <osgAnimation/MorphGeometry>
|
||||
|
||||
// particle
|
||||
#include <osgParticle/ParticleSystem>
|
||||
#include <osgParticle/ParticleSystemUpdater>
|
||||
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/AlphaFunc>
|
||||
#include <osg/Depth>
|
||||
|
@ -177,6 +181,17 @@ namespace
|
|||
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<osgAnimation::MorphGeometry> morphGeom = new osgAnimation::MorphGeometry;
|
||||
|
@ -220,7 +235,7 @@ namespace NifOsg
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -249,7 +264,7 @@ namespace NifOsg
|
|||
mSkeleton = skel;
|
||||
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)
|
||||
|
@ -276,7 +291,7 @@ namespace NifOsg
|
|||
}
|
||||
|
||||
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;
|
||||
if (createSkeleton)
|
||||
|
@ -327,6 +342,9 @@ namespace NifOsg
|
|||
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())
|
||||
handleNodeControllers(nifNode, transformNode, animflags);
|
||||
|
||||
|
@ -337,7 +355,7 @@ namespace NifOsg
|
|||
for(size_t i = 0;i < children.length();++i)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||
continue;
|
||||
if (ctrl->recType == Nif::RC_NiUVController)
|
||||
{
|
||||
const Nif::NiUVController *uvctrl = static_cast<const Nif::NiUVController*>(ctrl.getPtr());
|
||||
|
@ -364,6 +384,8 @@ namespace NifOsg
|
|||
bool seenKeyframeCtrl = false;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||
continue;
|
||||
if (ctrl->recType == Nif::RC_NiAlphaController)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!(ctrl->flags & Nif::NiNode::ControllerFlag_Active))
|
||||
continue;
|
||||
if (ctrl->recType == Nif::RC_NiFlipController)
|
||||
{
|
||||
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)
|
||||
{
|
||||
const Nif::NiTriShapeData* data = triShape->data.getPtr();
|
||||
|
@ -554,18 +645,18 @@ namespace NifOsg
|
|||
|
||||
if (!geometry.get())
|
||||
geometry = new osg::Geometry;
|
||||
triShapeToGeometry(triShape, geometry.get(), boundTextures, animflags);
|
||||
triShapeToGeometry(triShape, geometry, boundTextures, animflags);
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
rig->setSourceGeometry(geometry);
|
||||
|
@ -600,16 +691,16 @@ namespace NifOsg
|
|||
|
||||
map->insert(std::make_pair(boneName, influence));
|
||||
}
|
||||
rig->setInfluenceMap(map.get());
|
||||
rig->setInfluenceMap(map);
|
||||
|
||||
osg::ref_ptr<osg::MatrixTransform> trans(new osg::MatrixTransform);
|
||||
trans->setUpdateCallback(new InvertBoneMatrix(mSkeleton));
|
||||
|
||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||
geode->addDrawable(rig.get());
|
||||
geode->addDrawable(rig);
|
||||
|
||||
trans->addChild(geode.get());
|
||||
parentNode->addChild(trans.get());
|
||||
trans->addChild(geode);
|
||||
parentNode->addChild(trans);
|
||||
}
|
||||
|
||||
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
|
||||
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.
|
||||
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);
|
||||
|
||||
|
@ -64,6 +64,8 @@ namespace NifOsg
|
|||
void handleProperty (const Nif::Property* property, const Nif::Node* nifNode,
|
||||
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.
|
||||
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.
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue