mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 17:19:39 +00:00
Particle improvements: particle systems now move with the particle bone, not the scene node. This difference is not noticable if the particle bone is static, but it makes the code *much* nicer and mirrors more closely what NifSkope does.
This commit is contained in:
parent
6400f23ab0
commit
a9526622b1
2 changed files with 25 additions and 127 deletions
|
@ -789,8 +789,6 @@ class NIFObjectLoader
|
||||||
emitter->setParameter("vertical_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->verticalAngle).valueDegrees()));
|
emitter->setParameter("vertical_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->verticalAngle).valueDegrees()));
|
||||||
emitter->setParameter("horizontal_direction", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalDir).valueDegrees()));
|
emitter->setParameter("horizontal_direction", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalDir).valueDegrees()));
|
||||||
emitter->setParameter("horizontal_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalAngle).valueDegrees()));
|
emitter->setParameter("horizontal_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalAngle).valueDegrees()));
|
||||||
emitter->setParameter("skelbase", skelBaseName);
|
|
||||||
emitter->setParameter("bone", bone->getName());
|
|
||||||
|
|
||||||
Nif::ExtraPtr e = partctrl->extra;
|
Nif::ExtraPtr e = partctrl->extra;
|
||||||
while(!e.empty())
|
while(!e.empty())
|
||||||
|
@ -883,11 +881,9 @@ class NIFObjectLoader
|
||||||
partsys->setParticleQuota(particledata->numParticles);
|
partsys->setParticleQuota(particledata->numParticles);
|
||||||
partsys->setKeepParticlesInLocalSpace(partflags & (Nif::NiNode::ParticleFlag_LocalSpace));
|
partsys->setKeepParticlesInLocalSpace(partflags & (Nif::NiNode::ParticleFlag_LocalSpace));
|
||||||
|
|
||||||
sceneNode->attachObject(partsys);
|
|
||||||
|
|
||||||
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partnode->recIndex);
|
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partnode->recIndex);
|
||||||
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
|
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
|
||||||
trgtbone->getUserObjectBindings().setUserAny(Ogre::Any(static_cast<Ogre::MovableObject*>(partsys)));
|
scene->mSkelBase->attachObjectToBone(trgtbone->getName(), partsys);
|
||||||
|
|
||||||
Nif::ControllerPtr ctrl = partnode->controller;
|
Nif::ControllerPtr ctrl = partnode->controller;
|
||||||
while(!ctrl.empty())
|
while(!ctrl.empty())
|
||||||
|
@ -900,6 +896,9 @@ class NIFObjectLoader
|
||||||
{
|
{
|
||||||
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partctrl->emitter->recIndex);
|
int trgtid = NIFSkeletonLoader::lookupOgreBoneHandle(name, partctrl->emitter->recIndex);
|
||||||
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
|
Ogre::Bone *trgtbone = scene->mSkelBase->getSkeleton()->getBone(trgtid);
|
||||||
|
// Set the emitter bone as user data on the particle system
|
||||||
|
// so the emitters/affectors can access it easily.
|
||||||
|
partsys->getUserObjectBindings().setUserAny(Ogre::Any(trgtbone));
|
||||||
createParticleEmitterAffectors(partsys, partctrl, trgtbone, scene->mSkelBase->getName());
|
createParticleEmitterAffectors(partsys, partctrl, trgtbone, scene->mSkelBase->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,17 +1273,6 @@ ObjectScenePtr Loader::createObjects(Ogre::Entity *parent, const std::string &bo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(size_t i = 0;i < scene->mParticles.size();i++)
|
|
||||||
{
|
|
||||||
Ogre::ParticleSystem *partsys = scene->mParticles[i];
|
|
||||||
if(partsys->isAttached())
|
|
||||||
partsys->detachFromParent();
|
|
||||||
|
|
||||||
Ogre::TagPoint *tag = scene->mSkelBase->attachObjectToBone(
|
|
||||||
scene->mSkelBase->getSkeleton()->getRootBone()->getName(), partsys);
|
|
||||||
tag->setScale(scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,46 +16,11 @@
|
||||||
class NifEmitter : public Ogre::ParticleEmitter
|
class NifEmitter : public Ogre::ParticleEmitter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string mSkelBaseName;
|
Ogre::Bone* mEmitterBone;
|
||||||
Ogre::Bone* mBone;
|
Ogre::Bone* mParticleBone;
|
||||||
|
|
||||||
Ogre::ParticleSystem* getPartSys() { return mParent; }
|
Ogre::ParticleSystem* getPartSys() { return mParent; }
|
||||||
|
|
||||||
class CmdSkelBase : public Ogre::ParamCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ogre::String doGet(const void *target) const
|
|
||||||
{
|
|
||||||
assert(false && "Unimplemented");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
void doSet(void *target, const Ogre::String &val)
|
|
||||||
{
|
|
||||||
NifEmitter* emitter = static_cast<NifEmitter*>(target);
|
|
||||||
emitter->mSkelBaseName = val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CmdBone : public Ogre::ParamCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ogre::String doGet(const void *target) const
|
|
||||||
{
|
|
||||||
assert(false && "Unimplemented");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
void doSet(void *target, const Ogre::String &val)
|
|
||||||
{
|
|
||||||
NifEmitter* emitter = static_cast<NifEmitter*>(target);
|
|
||||||
assert(!emitter->mSkelBaseName.empty() && "Base entity needs to be set first");
|
|
||||||
Ogre::ParticleSystem* partsys = emitter->getPartSys();
|
|
||||||
Ogre::Entity* ent = partsys->getParentSceneNode()->getCreator()->getEntity(emitter->mSkelBaseName);
|
|
||||||
Ogre::Bone* bone = ent->getSkeleton()->getBone(val);
|
|
||||||
assert(bone);
|
|
||||||
emitter->mBone = bone;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Command object for the emitter width (see Ogre::ParamCommand).*/
|
/** Command object for the emitter width (see Ogre::ParamCommand).*/
|
||||||
class CmdWidth : public Ogre::ParamCommand
|
class CmdWidth : public Ogre::ParamCommand
|
||||||
{
|
{
|
||||||
|
@ -165,8 +130,10 @@ public:
|
||||||
|
|
||||||
NifEmitter(Ogre::ParticleSystem *psys)
|
NifEmitter(Ogre::ParticleSystem *psys)
|
||||||
: Ogre::ParticleEmitter(psys)
|
: Ogre::ParticleEmitter(psys)
|
||||||
, mBone(NULL)
|
|
||||||
{
|
{
|
||||||
|
mEmitterBone = Ogre::any_cast<Ogre::Bone*>(psys->getUserObjectBindings().getUserAny());
|
||||||
|
Ogre::TagPoint* tag = static_cast<Ogre::TagPoint*>(mParent->getParentNode());
|
||||||
|
mParticleBone = static_cast<Ogre::Bone*>(tag->getParent());
|
||||||
initDefaults("Nif");
|
initDefaults("Nif");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +147,6 @@ public:
|
||||||
/** See Ogre::ParticleEmitter. */
|
/** See Ogre::ParticleEmitter. */
|
||||||
void _initParticle(Ogre::Particle *particle)
|
void _initParticle(Ogre::Particle *particle)
|
||||||
{
|
{
|
||||||
assert (mBone && "No node set");
|
|
||||||
Ogre::Vector3 xOff, yOff, zOff;
|
Ogre::Vector3 xOff, yOff, zOff;
|
||||||
|
|
||||||
// Call superclass
|
// Call superclass
|
||||||
|
@ -203,7 +169,10 @@ public:
|
||||||
Ogre::Real& totalTimeToLive = particle->totalTimeToLive;
|
Ogre::Real& totalTimeToLive = particle->totalTimeToLive;
|
||||||
Ogre::Real& timeToLive = particle->timeToLive;
|
Ogre::Real& timeToLive = particle->timeToLive;
|
||||||
#endif
|
#endif
|
||||||
position = mBone->_getDerivedPosition() + xOff + yOff + zOff;
|
|
||||||
|
position = xOff + yOff + zOff +
|
||||||
|
mParticleBone->_getDerivedOrientation().Inverse() * (mEmitterBone->_getDerivedPosition()
|
||||||
|
- mParticleBone->_getDerivedPosition());
|
||||||
|
|
||||||
// Generate complex data by reference
|
// Generate complex data by reference
|
||||||
genEmissionColour(colour);
|
genEmissionColour(colour);
|
||||||
|
@ -211,7 +180,9 @@ public:
|
||||||
// NOTE: We do not use mDirection/mAngle for the initial direction.
|
// NOTE: We do not use mDirection/mAngle for the initial direction.
|
||||||
Ogre::Radian hdir = mHorizontalDir + mHorizontalAngle*Ogre::Math::SymmetricRandom();
|
Ogre::Radian hdir = mHorizontalDir + mHorizontalAngle*Ogre::Math::SymmetricRandom();
|
||||||
Ogre::Radian vdir = mVerticalDir + mVerticalAngle*Ogre::Math::SymmetricRandom();
|
Ogre::Radian vdir = mVerticalDir + mVerticalAngle*Ogre::Math::SymmetricRandom();
|
||||||
direction = (mBone->_getDerivedOrientation() * Ogre::Quaternion(hdir, Ogre::Vector3::UNIT_Z) *
|
direction = (mParticleBone->_getDerivedOrientation().Inverse()
|
||||||
|
* mEmitterBone->_getDerivedOrientation() *
|
||||||
|
Ogre::Quaternion(hdir, Ogre::Vector3::UNIT_Z) *
|
||||||
Ogre::Quaternion(vdir, Ogre::Vector3::UNIT_X)) *
|
Ogre::Quaternion(vdir, Ogre::Vector3::UNIT_X)) *
|
||||||
Ogre::Vector3::UNIT_Z;
|
Ogre::Vector3::UNIT_Z;
|
||||||
|
|
||||||
|
@ -374,16 +345,6 @@ protected:
|
||||||
Ogre::PT_REAL),
|
Ogre::PT_REAL),
|
||||||
&msHorizontalAngleCmd);
|
&msHorizontalAngleCmd);
|
||||||
|
|
||||||
dict->addParameter(Ogre::ParameterDef("bone",
|
|
||||||
"The bone where the particles should be spawned",
|
|
||||||
Ogre::PT_STRING),
|
|
||||||
&msBoneCmd);
|
|
||||||
|
|
||||||
dict->addParameter(Ogre::ParameterDef("skelbase",
|
|
||||||
"The name of the entity containing the bone (see 'bone' parameter)",
|
|
||||||
Ogre::PT_STRING),
|
|
||||||
&msSkelBaseCmd);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -397,8 +358,6 @@ protected:
|
||||||
static CmdVerticalAngle msVerticalAngleCmd;
|
static CmdVerticalAngle msVerticalAngleCmd;
|
||||||
static CmdHorizontalDir msHorizontalDirCmd;
|
static CmdHorizontalDir msHorizontalDirCmd;
|
||||||
static CmdHorizontalAngle msHorizontalAngleCmd;
|
static CmdHorizontalAngle msHorizontalAngleCmd;
|
||||||
static CmdBone msBoneCmd;
|
|
||||||
static CmdSkelBase msSkelBaseCmd;
|
|
||||||
};
|
};
|
||||||
NifEmitter::CmdWidth NifEmitter::msWidthCmd;
|
NifEmitter::CmdWidth NifEmitter::msWidthCmd;
|
||||||
NifEmitter::CmdHeight NifEmitter::msHeightCmd;
|
NifEmitter::CmdHeight NifEmitter::msHeightCmd;
|
||||||
|
@ -407,8 +366,6 @@ NifEmitter::CmdVerticalDir NifEmitter::msVerticalDirCmd;
|
||||||
NifEmitter::CmdVerticalAngle NifEmitter::msVerticalAngleCmd;
|
NifEmitter::CmdVerticalAngle NifEmitter::msVerticalAngleCmd;
|
||||||
NifEmitter::CmdHorizontalDir NifEmitter::msHorizontalDirCmd;
|
NifEmitter::CmdHorizontalDir NifEmitter::msHorizontalDirCmd;
|
||||||
NifEmitter::CmdHorizontalAngle NifEmitter::msHorizontalAngleCmd;
|
NifEmitter::CmdHorizontalAngle NifEmitter::msHorizontalAngleCmd;
|
||||||
NifEmitter::CmdBone NifEmitter::msBoneCmd;
|
|
||||||
NifEmitter::CmdSkelBase NifEmitter::msSkelBaseCmd;
|
|
||||||
|
|
||||||
Ogre::ParticleEmitter* NifEmitterFactory::createEmitter(Ogre::ParticleSystem *psys)
|
Ogre::ParticleEmitter* NifEmitterFactory::createEmitter(Ogre::ParticleSystem *psys)
|
||||||
{
|
{
|
||||||
|
@ -575,47 +532,11 @@ class GravityAffector : public Ogre::ParticleAffector
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string mSkelBaseName;
|
Ogre::Bone* mEmitterBone;
|
||||||
Ogre::Bone* mBone;
|
Ogre::Bone* mParticleBone;
|
||||||
|
|
||||||
Ogre::ParticleSystem* getPartSys() { return mParent; }
|
Ogre::ParticleSystem* getPartSys() { return mParent; }
|
||||||
|
|
||||||
class CmdSkelBase : public Ogre::ParamCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ogre::String doGet(const void *target) const
|
|
||||||
{
|
|
||||||
assert(false && "Unimplemented");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
void doSet(void *target, const Ogre::String &val)
|
|
||||||
{
|
|
||||||
GravityAffector* affector = static_cast<GravityAffector*>(target);
|
|
||||||
affector->mSkelBaseName = val;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CmdBone : public Ogre::ParamCommand
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Ogre::String doGet(const void *target) const
|
|
||||||
{
|
|
||||||
assert(false && "Unimplemented");
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
void doSet(void *target, const Ogre::String &val)
|
|
||||||
{
|
|
||||||
GravityAffector* affector = static_cast<GravityAffector*>(target);
|
|
||||||
assert(!affector->mSkelBaseName.empty() && "Base entity needs to be set first");
|
|
||||||
Ogre::ParticleSystem* partsys = affector->getPartSys();
|
|
||||||
Ogre::Entity* ent = partsys->getParentSceneNode()->getCreator()->getEntity(affector->mSkelBaseName);
|
|
||||||
Ogre::Bone* bone = ent->getSkeleton()->getBone(val);
|
|
||||||
assert(bone);
|
|
||||||
affector->mBone = bone;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** Command object for force (see Ogre::ParamCommand).*/
|
/** Command object for force (see Ogre::ParamCommand).*/
|
||||||
class CmdForce : public Ogre::ParamCommand
|
class CmdForce : public Ogre::ParamCommand
|
||||||
{
|
{
|
||||||
|
@ -709,8 +630,11 @@ public:
|
||||||
, mForceType(Type_Wind)
|
, mForceType(Type_Wind)
|
||||||
, mPosition(0.0f)
|
, mPosition(0.0f)
|
||||||
, mDirection(0.0f)
|
, mDirection(0.0f)
|
||||||
, mBone(NULL)
|
|
||||||
{
|
{
|
||||||
|
mEmitterBone = Ogre::any_cast<Ogre::Bone*>(psys->getUserObjectBindings().getUserAny());
|
||||||
|
Ogre::TagPoint* tag = static_cast<Ogre::TagPoint*>(mParent->getParentNode());
|
||||||
|
mParticleBone = static_cast<Ogre::Bone*>(tag->getParent());
|
||||||
|
|
||||||
mType = "Gravity";
|
mType = "Gravity";
|
||||||
|
|
||||||
// Init parameters
|
// Init parameters
|
||||||
|
@ -731,16 +655,6 @@ public:
|
||||||
dict->addParameter(Ogre::ParameterDef(force_type_title, force_type_descr, Ogre::PT_STRING), &msForceTypeCmd);
|
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(direction_title, direction_descr, Ogre::PT_VECTOR3), &msDirectionCmd);
|
||||||
dict->addParameter(Ogre::ParameterDef(position_title, position_descr, Ogre::PT_VECTOR3), &msPositionCmd);
|
dict->addParameter(Ogre::ParameterDef(position_title, position_descr, Ogre::PT_VECTOR3), &msPositionCmd);
|
||||||
|
|
||||||
dict->addParameter(Ogre::ParameterDef("bone",
|
|
||||||
"The bone where the particles should be spawned",
|
|
||||||
Ogre::PT_STRING),
|
|
||||||
&msBoneCmd);
|
|
||||||
|
|
||||||
dict->addParameter(Ogre::ParameterDef("skelbase",
|
|
||||||
"The name of the entity containing the bone (see 'bone' parameter)",
|
|
||||||
Ogre::PT_STRING),
|
|
||||||
&msSkelBaseCmd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,13 +696,11 @@ public:
|
||||||
static CmdForceType msForceTypeCmd;
|
static CmdForceType msForceTypeCmd;
|
||||||
static CmdDirection msDirectionCmd;
|
static CmdDirection msDirectionCmd;
|
||||||
static CmdPosition msPositionCmd;
|
static CmdPosition msPositionCmd;
|
||||||
static CmdBone msBoneCmd;
|
|
||||||
static CmdSkelBase msSkelBaseCmd;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void applyWindForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
|
void applyWindForce(Ogre::ParticleSystem *psys, Ogre::Real timeElapsed)
|
||||||
{
|
{
|
||||||
const Ogre::Vector3 vec = mBone->_getDerivedOrientation() * mDirection * mForce * timeElapsed;
|
const Ogre::Vector3 vec = mDirection * mForce * timeElapsed;
|
||||||
Ogre::ParticleIterator pi = psys->_getIterator();
|
Ogre::ParticleIterator pi = psys->_getIterator();
|
||||||
while (!pi.end())
|
while (!pi.end())
|
||||||
{
|
{
|
||||||
|
@ -813,8 +725,8 @@ protected:
|
||||||
#else
|
#else
|
||||||
Ogre::Vector3 position = p->position;
|
Ogre::Vector3 position = p->position;
|
||||||
#endif
|
#endif
|
||||||
const Ogre::Vector3 vec = (
|
|
||||||
(mBone->_getDerivedOrientation() * mPosition + mBone->_getDerivedPosition()) - position).normalisedCopy() * force;
|
Ogre::Vector3 vec = (mPosition - position).normalisedCopy() * force;
|
||||||
#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0)
|
#if OGRE_VERSION >= (1 << 16 | 10 << 8 | 0)
|
||||||
p->mDirection += vec;
|
p->mDirection += vec;
|
||||||
#else
|
#else
|
||||||
|
@ -835,8 +747,6 @@ GravityAffector::CmdForce GravityAffector::msForceCmd;
|
||||||
GravityAffector::CmdForceType GravityAffector::msForceTypeCmd;
|
GravityAffector::CmdForceType GravityAffector::msForceTypeCmd;
|
||||||
GravityAffector::CmdDirection GravityAffector::msDirectionCmd;
|
GravityAffector::CmdDirection GravityAffector::msDirectionCmd;
|
||||||
GravityAffector::CmdPosition GravityAffector::msPositionCmd;
|
GravityAffector::CmdPosition GravityAffector::msPositionCmd;
|
||||||
GravityAffector::CmdBone GravityAffector::msBoneCmd;
|
|
||||||
GravityAffector::CmdSkelBase GravityAffector::msSkelBaseCmd;
|
|
||||||
|
|
||||||
Ogre::ParticleAffector *GravityAffectorFactory::createAffector(Ogre::ParticleSystem *psys)
|
Ogre::ParticleAffector *GravityAffectorFactory::createAffector(Ogre::ParticleSystem *psys)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue