mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-04 00:45:33 +00:00
Load initial particle system state from NIF files (Fixes #2178)
This commit is contained in:
parent
a67e7c64ea
commit
65536f0857
4 changed files with 86 additions and 8 deletions
|
@ -114,10 +114,6 @@ void Animation::setObjectRoot(const std::string &model, bool baseonly)
|
|||
mObjectRoot = (!baseonly ? NifOgre::Loader::createObjects(mInsert, mdlname) :
|
||||
NifOgre::Loader::createObjectBase(mInsert, mdlname));
|
||||
|
||||
// Fast forward auto-play particles, which will have been set up as Emitting by the loader.
|
||||
for (unsigned int i=0; i<mObjectRoot->mParticles.size(); ++i)
|
||||
mObjectRoot->mParticles[i]->fastForward(1, 0.1);
|
||||
|
||||
if(mObjectRoot->mSkelBase)
|
||||
{
|
||||
mSkelBase = mObjectRoot->mSkelBase;
|
||||
|
|
|
@ -571,10 +571,6 @@ NifOgre::ObjectScenePtr NpcAnimation::insertBoundedPart(const std::string &model
|
|||
std::for_each(objects->mEntities.begin(), objects->mEntities.end(), SetObjectGroup(group));
|
||||
std::for_each(objects->mParticles.begin(), objects->mParticles.end(), SetObjectGroup(group));
|
||||
|
||||
// Fast forward auto-play particles, which will have been set up as Emitting by the loader.
|
||||
for (unsigned int i=0; i<objects->mParticles.size(); ++i)
|
||||
objects->mParticles[i]->fastForward(1, 0.1);
|
||||
|
||||
if(objects->mSkelBase)
|
||||
{
|
||||
Ogre::AnimationStateSet *aset = objects->mSkelBase->getAllAnimationStates();
|
||||
|
|
|
@ -161,6 +161,38 @@ void ObjectScene::rotateBillboardNodes(Ogre::Camera *camera)
|
|||
}
|
||||
}
|
||||
|
||||
void ObjectScene::_notifyAttached()
|
||||
{
|
||||
// convert initial particle positions to world space for world-space particle systems
|
||||
// this can't be done on creation because the particle system is not in its correct world space position yet
|
||||
for (std::vector<Ogre::ParticleSystem*>::iterator it = mParticles.begin(); it != mParticles.end(); ++it)
|
||||
{
|
||||
Ogre::ParticleSystem* psys = *it;
|
||||
if (psys->getKeepParticlesInLocalSpace())
|
||||
continue;
|
||||
Ogre::ParticleIterator pi = psys->_getIterator();
|
||||
while (!pi.end())
|
||||
{
|
||||
Ogre::Particle *p = pi.getNext();
|
||||
|
||||
#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0)
|
||||
Ogre::Vector3& position = p->mPosition;
|
||||
Ogre::Vector3& direction = p->mDirection;
|
||||
#else
|
||||
Ogre::Vector3& position = p->position;
|
||||
Ogre::Vector3& direction = p->direction;
|
||||
#endif
|
||||
|
||||
position =
|
||||
(psys->getParentNode()->_getDerivedOrientation() *
|
||||
(psys->getParentNode()->_getDerivedScale() * position))
|
||||
+ psys->getParentNode()->_getDerivedPosition();
|
||||
direction =
|
||||
(psys->getParentNode()->_getDerivedOrientation() * direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Animates a texture
|
||||
class FlipController
|
||||
{
|
||||
|
@ -949,6 +981,8 @@ class NIFObjectLoader
|
|||
createParticleEmitterAffectors(partsys, partctrl, trgtbone, scene->mSkelBase->getName());
|
||||
}
|
||||
|
||||
createParticleInitialState(partsys, particledata, partctrl);
|
||||
|
||||
Ogre::ControllerValueRealPtr srcval((partflags&Nif::NiNode::ParticleFlag_AutoPlay) ?
|
||||
Ogre::ControllerManager::getSingleton().getFrameTimeSource() :
|
||||
Ogre::ControllerValueRealPtr());
|
||||
|
@ -975,6 +1009,50 @@ class NIFObjectLoader
|
|||
createMaterialControllers(partnode, partsys, animflags, scene);
|
||||
}
|
||||
|
||||
static void createParticleInitialState(Ogre::ParticleSystem* partsys, const Nif::NiAutoNormalParticlesData* particledata,
|
||||
const Nif::NiParticleSystemController* partctrl)
|
||||
{
|
||||
partsys->_update(0.f); // seems to be required to allocate mFreeParticles
|
||||
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;
|
||||
|
||||
Ogre::Particle* created = partsys->createParticle();
|
||||
if (!created)
|
||||
break;
|
||||
|
||||
#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0)
|
||||
Ogre::Vector3& position = created->mPosition;
|
||||
Ogre::Vector3& direction = created->mDirection;
|
||||
Ogre::ColourValue& colour = created->mColour;
|
||||
float& totalTimeToLive = created->mTotalTimeToLive;
|
||||
float& timeToLive = created->mTimeToLive;
|
||||
#else
|
||||
Ogre::Vector3& position = created->position;
|
||||
Ogre::Vector3& direction = created->direction;
|
||||
Ogre::ColourValue& colour = created->colour;
|
||||
float& totalTimeToLive = created->totalTimeToLive;
|
||||
float& timeToLive = created->timeToLive;
|
||||
#endif
|
||||
|
||||
direction = particle.velocity;
|
||||
position = particledata->vertices.at(particle.vertex);
|
||||
|
||||
if (particle.vertex < int(particledata->colors.size()))
|
||||
{
|
||||
Ogre::Vector4 partcolour = particledata->colors.at(particle.vertex);
|
||||
colour = Ogre::ColourValue(partcolour.x, partcolour.y, partcolour.z, partcolour.w);
|
||||
}
|
||||
else
|
||||
colour = Ogre::ColourValue(1.f, 1.f, 1.f, 1.f);
|
||||
float size = particledata->sizes.at(particle.vertex);
|
||||
created->setDimensions(size, size);
|
||||
totalTimeToLive = std::max(0.f, particle.lifespan);
|
||||
timeToLive = std::max(0.f, particle.lifespan - particle.lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
static void createNodeControllers(const Nif::NIFFilePtr& nif, const std::string &name, Nif::ControllerPtr ctrl, ObjectScenePtr scene, int animflags)
|
||||
{
|
||||
|
@ -1275,6 +1353,8 @@ ObjectScenePtr Loader::createObjects(Ogre::SceneNode *parentNode, std::string na
|
|||
parentNode->attachObject(entity);
|
||||
}
|
||||
|
||||
scene->_notifyAttached();
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
|
@ -1342,6 +1422,8 @@ ObjectScenePtr Loader::createObjects(Ogre::Entity *parent, const std::string &bo
|
|||
}
|
||||
}
|
||||
|
||||
scene->_notifyAttached();
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,10 @@ struct ObjectScene {
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue