mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-04 21:40:03 +00:00
Handle the vertical and horizontal parameters of Nif particles
Note that 'horizontal' is mapped to rotate around the Z axis, not Y. The Nif particle parameters seem to be set up to expect a normal OpenGL (Direct3D?) orientation, rather than the 90-degree pitch offset of the game.
This commit is contained in:
parent
7191f6ed2a
commit
dd981077b9
@ -352,16 +352,18 @@ class NIFObjectLoader
|
|||||||
static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl)
|
static void createParticleEmitterAffectors(Ogre::ParticleSystem *partsys, const Nif::NiParticleSystemController *partctrl)
|
||||||
{
|
{
|
||||||
Ogre::ParticleEmitter *emitter = partsys->addEmitter("Nif");
|
Ogre::ParticleEmitter *emitter = partsys->addEmitter("Nif");
|
||||||
emitter->setDirection(Ogre::Vector3(0.0f, 0.0f, std::cos(partctrl->verticalDir)));
|
|
||||||
emitter->setAngle(Ogre::Radian(partctrl->verticalAngle));
|
|
||||||
emitter->setParticleVelocity(partctrl->velocity-partctrl->velocityRandom,
|
emitter->setParticleVelocity(partctrl->velocity-partctrl->velocityRandom,
|
||||||
partctrl->velocity+partctrl->velocityRandom);
|
partctrl->velocity+partctrl->velocityRandom);
|
||||||
emitter->setEmissionRate(partctrl->emitRate);
|
emitter->setEmissionRate(partctrl->emitRate);
|
||||||
emitter->setTimeToLive(partctrl->lifetime-partctrl->lifetimeRandom,
|
emitter->setTimeToLive(partctrl->lifetime-partctrl->lifetimeRandom,
|
||||||
partctrl->lifetime+partctrl->lifetimeRandom);
|
partctrl->lifetime+partctrl->lifetimeRandom);
|
||||||
emitter->setParameter("width", Ogre::StringConverter::toString(partctrl->offsetRandom.x));
|
emitter->setParameter("width", Ogre::StringConverter::toString(partctrl->offsetRandom.x));
|
||||||
emitter->setParameter("height", Ogre::StringConverter::toString(partctrl->offsetRandom.z));
|
emitter->setParameter("height", Ogre::StringConverter::toString(partctrl->offsetRandom.y));
|
||||||
emitter->setParameter("depth", Ogre::StringConverter::toString(partctrl->offsetRandom.y));
|
emitter->setParameter("depth", Ogre::StringConverter::toString(partctrl->offsetRandom.z));
|
||||||
|
emitter->setParameter("vertical_direction", Ogre::StringConverter::toString(Ogre::Radian(partctrl->verticalDir).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_angle", Ogre::StringConverter::toString(Ogre::Radian(partctrl->horizontalAngle).valueDegrees()));
|
||||||
|
|
||||||
Nif::ExtraPtr e = partctrl->extra;
|
Nif::ExtraPtr e = partctrl->extra;
|
||||||
while(!e.empty())
|
while(!e.empty())
|
||||||
|
@ -52,6 +52,70 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Command object for the emitter vertical_direction (see Ogre::ParamCommand).*/
|
||||||
|
class CmdVerticalDir : public Ogre::ParamCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ogre::String doGet(const void *target) const
|
||||||
|
{
|
||||||
|
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||||
|
return Ogre::StringConverter::toString(self->getVerticalDirection().valueDegrees());
|
||||||
|
}
|
||||||
|
void doSet(void *target, const Ogre::String &val)
|
||||||
|
{
|
||||||
|
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||||
|
self->setVerticalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Command object for the emitter vertical_angle (see Ogre::ParamCommand).*/
|
||||||
|
class CmdVerticalAngle : public Ogre::ParamCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ogre::String doGet(const void *target) const
|
||||||
|
{
|
||||||
|
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||||
|
return Ogre::StringConverter::toString(self->getVerticalAngle().valueDegrees());
|
||||||
|
}
|
||||||
|
void doSet(void *target, const Ogre::String &val)
|
||||||
|
{
|
||||||
|
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||||
|
self->setVerticalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Command object for the emitter horizontal_direction (see Ogre::ParamCommand).*/
|
||||||
|
class CmdHorizontalDir : public Ogre::ParamCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ogre::String doGet(const void *target) const
|
||||||
|
{
|
||||||
|
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||||
|
return Ogre::StringConverter::toString(self->getHorizontalDirection().valueDegrees());
|
||||||
|
}
|
||||||
|
void doSet(void *target, const Ogre::String &val)
|
||||||
|
{
|
||||||
|
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||||
|
self->setHorizontalDirection(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Command object for the emitter horizontal_angle (see Ogre::ParamCommand).*/
|
||||||
|
class CmdHorizontalAngle : public Ogre::ParamCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Ogre::String doGet(const void *target) const
|
||||||
|
{
|
||||||
|
const NifEmitter *self = static_cast<const NifEmitter*>(target);
|
||||||
|
return Ogre::StringConverter::toString(self->getHorizontalAngle().valueDegrees());
|
||||||
|
}
|
||||||
|
void doSet(void *target, const Ogre::String &val)
|
||||||
|
{
|
||||||
|
NifEmitter *self = static_cast<NifEmitter*>(target);
|
||||||
|
self->setHorizontalAngle(Ogre::Degree(Ogre::StringConverter::parseReal(val)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
NifEmitter(Ogre::ParticleSystem *psys)
|
NifEmitter(Ogre::ParticleSystem *psys)
|
||||||
: Ogre::ParticleEmitter(psys)
|
: Ogre::ParticleEmitter(psys)
|
||||||
@ -82,7 +146,14 @@ public:
|
|||||||
|
|
||||||
// Generate complex data by reference
|
// Generate complex data by reference
|
||||||
genEmissionColour(particle->colour);
|
genEmissionColour(particle->colour);
|
||||||
genEmissionDirection(particle->direction);
|
|
||||||
|
// NOTE: We do not use mDirection/mAngle for the initial direction.
|
||||||
|
Ogre::Radian vdir = mVerticalDir + mVerticalAngle*Ogre::Math::SymmetricRandom();
|
||||||
|
Ogre::Radian hdir = mHorizontalDir + mHorizontalAngle*Ogre::Math::SymmetricRandom();
|
||||||
|
particle->direction = (Ogre::Quaternion(vdir, Ogre::Vector3::UNIT_X) *
|
||||||
|
Ogre::Quaternion(hdir, Ogre::Vector3::UNIT_Z)) *
|
||||||
|
Ogre::Vector3::UNIT_Z;
|
||||||
|
|
||||||
genEmissionVelocity(particle->direction);
|
genEmissionVelocity(particle->direction);
|
||||||
|
|
||||||
// Generate simpler data
|
// Generate simpler data
|
||||||
@ -152,10 +223,36 @@ public:
|
|||||||
Ogre::Real getDepth(void) const
|
Ogre::Real getDepth(void) const
|
||||||
{ return mSize.z; }
|
{ return mSize.z; }
|
||||||
|
|
||||||
|
void setVerticalDirection(Ogre::Radian vdir)
|
||||||
|
{ mVerticalDir = vdir; }
|
||||||
|
Ogre::Radian getVerticalDirection(void) const
|
||||||
|
{ return mVerticalDir; }
|
||||||
|
|
||||||
|
void setVerticalAngle(Ogre::Radian vangle)
|
||||||
|
{ mVerticalAngle = vangle; }
|
||||||
|
Ogre::Radian getVerticalAngle(void) const
|
||||||
|
{ return mVerticalAngle; }
|
||||||
|
|
||||||
|
void setHorizontalDirection(Ogre::Radian hdir)
|
||||||
|
{ mHorizontalDir = hdir; }
|
||||||
|
Ogre::Radian getHorizontalDirection(void) const
|
||||||
|
{ return mHorizontalDir; }
|
||||||
|
|
||||||
|
void setHorizontalAngle(Ogre::Radian hangle)
|
||||||
|
{ mHorizontalAngle = hangle; }
|
||||||
|
Ogre::Radian getHorizontalAngle(void) const
|
||||||
|
{ return mHorizontalAngle; }
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Size of the area
|
/// Size of the area
|
||||||
Ogre::Vector3 mSize;
|
Ogre::Vector3 mSize;
|
||||||
|
|
||||||
|
Ogre::Radian mVerticalDir;
|
||||||
|
Ogre::Radian mVerticalAngle;
|
||||||
|
Ogre::Radian mHorizontalDir;
|
||||||
|
Ogre::Radian mHorizontalAngle;
|
||||||
|
|
||||||
/// Local axes, not normalised, their magnitude reflects area size
|
/// Local axes, not normalised, their magnitude reflects area size
|
||||||
Ogre::Vector3 mXRange, mYRange, mZRange;
|
Ogre::Vector3 mXRange, mYRange, mZRange;
|
||||||
|
|
||||||
@ -163,7 +260,6 @@ protected:
|
|||||||
void genAreaAxes(void)
|
void genAreaAxes(void)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 mLeft = mUp.crossProduct(mDirection);
|
Ogre::Vector3 mLeft = mUp.crossProduct(mDirection);
|
||||||
|
|
||||||
mXRange = mLeft * (mSize.x * 0.5f);
|
mXRange = mLeft * (mSize.x * 0.5f);
|
||||||
mYRange = mUp * (mSize.y * 0.5f);
|
mYRange = mUp * (mSize.y * 0.5f);
|
||||||
mZRange = mDirection * (mSize.z * 0.5f);
|
mZRange = mDirection * (mSize.z * 0.5f);
|
||||||
@ -200,6 +296,23 @@ protected:
|
|||||||
Ogre::PT_REAL),
|
Ogre::PT_REAL),
|
||||||
&msDepthCmd);
|
&msDepthCmd);
|
||||||
|
|
||||||
|
dict->addParameter(Ogre::ParameterDef("vertical_direction",
|
||||||
|
"Vertical direction of emitted particles (in degrees).",
|
||||||
|
Ogre::PT_REAL),
|
||||||
|
&msVerticalDirCmd);
|
||||||
|
dict->addParameter(Ogre::ParameterDef("vertical_angle",
|
||||||
|
"Vertical direction variance of emitted particles (in degrees).",
|
||||||
|
Ogre::PT_REAL),
|
||||||
|
&msVerticalAngleCmd);
|
||||||
|
dict->addParameter(Ogre::ParameterDef("horizontal_direction",
|
||||||
|
"Horizontal direction of emitted particles (in degrees).",
|
||||||
|
Ogre::PT_REAL),
|
||||||
|
&msHorizontalDirCmd);
|
||||||
|
dict->addParameter(Ogre::ParameterDef("horizontal_angle",
|
||||||
|
"Horizontal direction variance of emitted particles (in degrees).",
|
||||||
|
Ogre::PT_REAL),
|
||||||
|
&msHorizontalAngleCmd);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -209,10 +322,18 @@ protected:
|
|||||||
static CmdWidth msWidthCmd;
|
static CmdWidth msWidthCmd;
|
||||||
static CmdHeight msHeightCmd;
|
static CmdHeight msHeightCmd;
|
||||||
static CmdDepth msDepthCmd;
|
static CmdDepth msDepthCmd;
|
||||||
|
static CmdVerticalDir msVerticalDirCmd;
|
||||||
|
static CmdVerticalAngle msVerticalAngleCmd;
|
||||||
|
static CmdHorizontalDir msHorizontalDirCmd;
|
||||||
|
static CmdHorizontalAngle msHorizontalAngleCmd;
|
||||||
};
|
};
|
||||||
NifEmitter::CmdWidth NifEmitter::msWidthCmd;
|
NifEmitter::CmdWidth NifEmitter::msWidthCmd;
|
||||||
NifEmitter::CmdHeight NifEmitter::msHeightCmd;
|
NifEmitter::CmdHeight NifEmitter::msHeightCmd;
|
||||||
NifEmitter::CmdDepth NifEmitter::msDepthCmd;
|
NifEmitter::CmdDepth NifEmitter::msDepthCmd;
|
||||||
|
NifEmitter::CmdVerticalDir NifEmitter::msVerticalDirCmd;
|
||||||
|
NifEmitter::CmdVerticalAngle NifEmitter::msVerticalAngleCmd;
|
||||||
|
NifEmitter::CmdHorizontalDir NifEmitter::msHorizontalDirCmd;
|
||||||
|
NifEmitter::CmdHorizontalAngle NifEmitter::msHorizontalAngleCmd;
|
||||||
|
|
||||||
Ogre::ParticleEmitter* NifEmitterFactory::createEmitter(Ogre::ParticleSystem *psys)
|
Ogre::ParticleEmitter* NifEmitterFactory::createEmitter(Ogre::ParticleSystem *psys)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user