mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-11 06:40:34 +00:00
Merge branch 'killerqueen' into 'master'
Support NiParticleBomb (feature #7634) Closes #7634 See merge request OpenMW/openmw!3512
This commit is contained in:
commit
698fd00269
@ -109,6 +109,7 @@
|
|||||||
Feature #7546: Start the game on Fredas
|
Feature #7546: Start the game on Fredas
|
||||||
Feature #7568: Uninterruptable scripted music
|
Feature #7568: Uninterruptable scripted music
|
||||||
Feature #7618: Show the player character's health in the save details
|
Feature #7618: Show the player character's health in the save details
|
||||||
|
Feature #7634: Support NiParticleBomb
|
||||||
Task #5896: Do not use deprecated MyGUI properties
|
Task #5896: Do not use deprecated MyGUI properties
|
||||||
Task #7113: Move from std::atoi to std::from_char
|
Task #7113: Move from std::atoi to std::from_char
|
||||||
Task #7117: Replace boost::scoped_array with std::vector
|
Task #7117: Replace boost::scoped_array with std::vector
|
||||||
|
@ -308,6 +308,7 @@ namespace Nif
|
|||||||
|
|
||||||
// Modifiers, 4.0.0.2
|
// Modifiers, 4.0.0.2
|
||||||
{ "NiGravity", &construct<NiGravity, RC_NiGravity> },
|
{ "NiGravity", &construct<NiGravity, RC_NiGravity> },
|
||||||
|
{ "NiParticleBomb", &construct<NiParticleBomb, RC_NiParticleBomb> },
|
||||||
{ "NiParticleColorModifier", &construct<NiParticleColorModifier, RC_NiParticleColorModifier> },
|
{ "NiParticleColorModifier", &construct<NiParticleColorModifier, RC_NiParticleColorModifier> },
|
||||||
{ "NiParticleGrowFade", &construct<NiParticleGrowFade, RC_NiParticleGrowFade> },
|
{ "NiParticleGrowFade", &construct<NiParticleGrowFade, RC_NiParticleGrowFade> },
|
||||||
{ "NiParticleRotation", &construct<NiParticleRotation, RC_NiParticleRotation> },
|
{ "NiParticleRotation", &construct<NiParticleRotation, RC_NiParticleRotation> },
|
||||||
|
@ -51,6 +51,20 @@ namespace Nif
|
|||||||
nif->read(mDirection);
|
nif->read(mDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NiParticleBomb::read(NIFStream* nif)
|
||||||
|
{
|
||||||
|
NiParticleModifier::read(nif);
|
||||||
|
|
||||||
|
nif->read(mRange);
|
||||||
|
nif->read(mDuration);
|
||||||
|
nif->read(mStrength);
|
||||||
|
nif->read(mStartTime);
|
||||||
|
mDecayType = static_cast<DecayType>(nif->get<uint32_t>());
|
||||||
|
mSymmetryType = static_cast<SymmetryType>(nif->get<uint32_t>());
|
||||||
|
nif->read(mPosition);
|
||||||
|
nif->read(mDirection);
|
||||||
|
}
|
||||||
|
|
||||||
void NiParticleCollider::read(NIFStream* nif)
|
void NiParticleCollider::read(NIFStream* nif)
|
||||||
{
|
{
|
||||||
NiParticleModifier::read(nif);
|
NiParticleModifier::read(nif);
|
||||||
@ -294,10 +308,10 @@ namespace Nif
|
|||||||
|
|
||||||
mBombObject.read(nif);
|
mBombObject.read(nif);
|
||||||
nif->read(mBombAxis);
|
nif->read(mBombAxis);
|
||||||
nif->read(mDecay);
|
nif->read(mRange);
|
||||||
nif->read(mDeltaV);
|
nif->read(mStrength);
|
||||||
nif->read(mDecayType);
|
mDecayType = static_cast<DecayType>(nif->get<uint32_t>());
|
||||||
nif->read(mSymmetryType);
|
mSymmetryType = static_cast<SymmetryType>(nif->get<uint32_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NiPSysBombModifier::post(Reader& nif)
|
void NiPSysBombModifier::post(Reader& nif)
|
||||||
|
@ -40,6 +40,20 @@ namespace Nif
|
|||||||
Point = 1, // Fixed origin
|
Point = 1, // Fixed origin
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class DecayType : uint32_t
|
||||||
|
{
|
||||||
|
None = 0, // f(Distance) = 1.0
|
||||||
|
Linear = 1, // f(Distance) = (Range - Distance) / Range
|
||||||
|
Exponential = 2, // f(Distance) = exp(-Distance / Range)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SymmetryType : uint32_t
|
||||||
|
{
|
||||||
|
Spherical = 0,
|
||||||
|
Cylindrical = 1, // Perpendicular to direction axis
|
||||||
|
Planar = 2, // Parallel to direction axis
|
||||||
|
};
|
||||||
|
|
||||||
struct NiGravity : NiParticleModifier
|
struct NiGravity : NiParticleModifier
|
||||||
{
|
{
|
||||||
float mDecay{ 0.f };
|
float mDecay{ 0.f };
|
||||||
@ -51,6 +65,20 @@ namespace Nif
|
|||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NiParticleBomb : NiParticleModifier
|
||||||
|
{
|
||||||
|
float mRange;
|
||||||
|
float mDuration;
|
||||||
|
float mStrength;
|
||||||
|
float mStartTime;
|
||||||
|
DecayType mDecayType;
|
||||||
|
SymmetryType mSymmetryType;
|
||||||
|
osg::Vec3f mPosition;
|
||||||
|
osg::Vec3f mDirection;
|
||||||
|
|
||||||
|
void read(NIFStream* nif);
|
||||||
|
};
|
||||||
|
|
||||||
struct NiParticleCollider : NiParticleModifier
|
struct NiParticleCollider : NiParticleModifier
|
||||||
{
|
{
|
||||||
float mBounceFactor;
|
float mBounceFactor;
|
||||||
@ -210,10 +238,10 @@ namespace Nif
|
|||||||
{
|
{
|
||||||
NiAVObjectPtr mBombObject;
|
NiAVObjectPtr mBombObject;
|
||||||
osg::Vec3f mBombAxis;
|
osg::Vec3f mBombAxis;
|
||||||
float mDecay;
|
float mRange;
|
||||||
float mDeltaV;
|
float mStrength;
|
||||||
uint32_t mDecayType;
|
DecayType mDecayType;
|
||||||
uint32_t mSymmetryType;
|
SymmetryType mSymmetryType;
|
||||||
|
|
||||||
void read(NIFStream* nif) override;
|
void read(NIFStream* nif) override;
|
||||||
void post(Reader& nif) override;
|
void post(Reader& nif) override;
|
||||||
|
@ -206,6 +206,7 @@ namespace Nif
|
|||||||
RC_NiMultiTargetTransformController,
|
RC_NiMultiTargetTransformController,
|
||||||
RC_NiNode,
|
RC_NiNode,
|
||||||
RC_NiPalette,
|
RC_NiPalette,
|
||||||
|
RC_NiParticleBomb,
|
||||||
RC_NiParticleColorModifier,
|
RC_NiParticleColorModifier,
|
||||||
RC_NiParticleGrowFade,
|
RC_NiParticleGrowFade,
|
||||||
RC_NiParticleRotation,
|
RC_NiParticleRotation,
|
||||||
|
@ -1092,6 +1092,18 @@ namespace NifOsg
|
|||||||
const Nif::NiGravity* gr = static_cast<const Nif::NiGravity*>(modifier.getPtr());
|
const Nif::NiGravity* gr = static_cast<const Nif::NiGravity*>(modifier.getPtr());
|
||||||
program->addOperator(new GravityAffector(gr));
|
program->addOperator(new GravityAffector(gr));
|
||||||
}
|
}
|
||||||
|
else if (modifier->recType == Nif::RC_NiParticleBomb)
|
||||||
|
{
|
||||||
|
auto bomb = static_cast<const Nif::NiParticleBomb*>(modifier.getPtr());
|
||||||
|
osg::ref_ptr<osgParticle::ModularProgram> bombProgram(new osgParticle::ModularProgram);
|
||||||
|
attachTo->addChild(bombProgram);
|
||||||
|
bombProgram->setParticleSystem(partsys);
|
||||||
|
bombProgram->setReferenceFrame(rf);
|
||||||
|
bombProgram->setStartTime(bomb->mStartTime);
|
||||||
|
bombProgram->setLifeTime(bomb->mDuration);
|
||||||
|
bombProgram->setEndless(false);
|
||||||
|
bombProgram->addOperator(new ParticleBomb(bomb));
|
||||||
|
}
|
||||||
else if (modifier->recType == Nif::RC_NiParticleColorModifier)
|
else if (modifier->recType == Nif::RC_NiParticleColorModifier)
|
||||||
{
|
{
|
||||||
const Nif::NiParticleColorModifier* cl
|
const Nif::NiParticleColorModifier* cl
|
||||||
|
@ -346,6 +346,84 @@ namespace NifOsg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParticleBomb::ParticleBomb(const Nif::NiParticleBomb* bomb)
|
||||||
|
: mRange(bomb->mRange)
|
||||||
|
, mStrength(bomb->mStrength)
|
||||||
|
, mDecayType(bomb->mDecayType)
|
||||||
|
, mSymmetryType(bomb->mSymmetryType)
|
||||||
|
, mPosition(bomb->mPosition)
|
||||||
|
, mDirection(bomb->mDirection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleBomb::ParticleBomb(const ParticleBomb& copy, const osg::CopyOp& copyop)
|
||||||
|
: osgParticle::Operator(copy, copyop)
|
||||||
|
{
|
||||||
|
mRange = copy.mRange;
|
||||||
|
mStrength = copy.mStrength;
|
||||||
|
mDecayType = copy.mDecayType;
|
||||||
|
mSymmetryType = copy.mSymmetryType;
|
||||||
|
mCachedWorldPosition = copy.mCachedWorldPosition;
|
||||||
|
mCachedWorldDirection = copy.mCachedWorldDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleBomb::beginOperate(osgParticle::Program* program)
|
||||||
|
{
|
||||||
|
bool absolute = (program->getReferenceFrame() == osgParticle::ParticleProcessor::ABSOLUTE_RF);
|
||||||
|
|
||||||
|
mCachedWorldPosition = absolute ? program->transformLocalToWorld(mPosition) : mPosition;
|
||||||
|
|
||||||
|
// We don't need the direction for Spherical bomb
|
||||||
|
if (mSymmetryType != Nif::SymmetryType::Spherical)
|
||||||
|
{
|
||||||
|
mCachedWorldDirection = absolute ? program->rotateLocalToWorld(mDirection) : mDirection;
|
||||||
|
mCachedWorldDirection.normalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleBomb::operate(osgParticle::Particle* particle, double dt)
|
||||||
|
{
|
||||||
|
float decay = 1.f;
|
||||||
|
osg::Vec3f explosionDir;
|
||||||
|
|
||||||
|
osg::Vec3f particleDir = particle->getPosition() - mCachedWorldPosition;
|
||||||
|
float distance = particleDir.length();
|
||||||
|
particleDir.normalize();
|
||||||
|
|
||||||
|
switch (mDecayType)
|
||||||
|
{
|
||||||
|
case Nif::DecayType::None:
|
||||||
|
break;
|
||||||
|
case Nif::DecayType::Linear:
|
||||||
|
decay = 1.f - distance / mRange;
|
||||||
|
break;
|
||||||
|
case Nif::DecayType::Exponential:
|
||||||
|
decay = std::exp(-distance / mRange);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decay <= 0.f)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (mSymmetryType)
|
||||||
|
{
|
||||||
|
case Nif::SymmetryType::Spherical:
|
||||||
|
explosionDir = particleDir;
|
||||||
|
break;
|
||||||
|
case Nif::SymmetryType::Cylindrical:
|
||||||
|
explosionDir = particleDir - mCachedWorldDirection * (mCachedWorldDirection * particleDir);
|
||||||
|
explosionDir.normalize();
|
||||||
|
break;
|
||||||
|
case Nif::SymmetryType::Planar:
|
||||||
|
explosionDir = mCachedWorldDirection;
|
||||||
|
if (explosionDir * particleDir < 0)
|
||||||
|
explosionDir = -explosionDir;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
particle->addVelocity(explosionDir * mStrength * decay * dt);
|
||||||
|
}
|
||||||
|
|
||||||
Emitter::Emitter()
|
Emitter::Emitter()
|
||||||
: osgParticle::Emitter()
|
: osgParticle::Emitter()
|
||||||
, mFlags(0)
|
, mFlags(0)
|
||||||
|
@ -199,6 +199,31 @@ namespace NifOsg
|
|||||||
osg::Vec3f mCachedWorldDirection;
|
osg::Vec3f mCachedWorldDirection;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ParticleBomb : public osgParticle::Operator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ParticleBomb(const Nif::NiParticleBomb* bomb);
|
||||||
|
ParticleBomb() = default;
|
||||||
|
ParticleBomb(const ParticleBomb& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
||||||
|
|
||||||
|
ParticleBomb& operator=(const ParticleBomb&) = delete;
|
||||||
|
|
||||||
|
META_Object(NifOsg, ParticleBomb)
|
||||||
|
|
||||||
|
void operate(osgParticle::Particle* particle, double dt) override;
|
||||||
|
void beginOperate(osgParticle::Program*) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float mRange{ 0.f };
|
||||||
|
float mStrength{ 0.f };
|
||||||
|
Nif::DecayType mDecayType{ Nif::DecayType::None };
|
||||||
|
Nif::SymmetryType mSymmetryType{ Nif::SymmetryType::Spherical };
|
||||||
|
osg::Vec3f mPosition;
|
||||||
|
osg::Vec3f mDirection;
|
||||||
|
osg::Vec3f mCachedWorldPosition;
|
||||||
|
osg::Vec3f mCachedWorldDirection;
|
||||||
|
};
|
||||||
|
|
||||||
// NodeVisitor to find a Group node with the given record index, stored in the node's user data container.
|
// NodeVisitor to find a Group node with the given record index, stored in the node's user data container.
|
||||||
// Alternatively, returns the node's parent Group if that node is not a Group (i.e. a leaf node).
|
// Alternatively, returns the node's parent Group if that node is not a Group (i.e. a leaf node).
|
||||||
class FindGroupByRecIndex : public osg::NodeVisitor
|
class FindGroupByRecIndex : public osg::NodeVisitor
|
||||||
|
@ -167,7 +167,7 @@ namespace SceneUtil
|
|||||||
"SceneUtil::DisableLight", "SceneUtil::MWShadowTechnique", "SceneUtil::TextKeyMapHolder",
|
"SceneUtil::DisableLight", "SceneUtil::MWShadowTechnique", "SceneUtil::TextKeyMapHolder",
|
||||||
"Shader::AddedState", "Shader::RemovedAlphaFunc", "NifOsg::FlipController",
|
"Shader::AddedState", "Shader::RemovedAlphaFunc", "NifOsg::FlipController",
|
||||||
"NifOsg::KeyframeController", "NifOsg::Emitter", "NifOsg::ParticleColorAffector",
|
"NifOsg::KeyframeController", "NifOsg::Emitter", "NifOsg::ParticleColorAffector",
|
||||||
"NifOsg::ParticleSystem", "NifOsg::GravityAffector", "NifOsg::GrowFadeAffector",
|
"NifOsg::ParticleSystem", "NifOsg::GravityAffector", "NifOsg::ParticleBomb", "NifOsg::GrowFadeAffector",
|
||||||
"NifOsg::InverseWorldMatrix", "NifOsg::StaticBoundingBoxCallback", "NifOsg::GeomMorpherController",
|
"NifOsg::InverseWorldMatrix", "NifOsg::StaticBoundingBoxCallback", "NifOsg::GeomMorpherController",
|
||||||
"NifOsg::UpdateMorphGeometry", "NifOsg::UVController", "NifOsg::VisController", "osgMyGUI::Drawable",
|
"NifOsg::UpdateMorphGeometry", "NifOsg::UVController", "NifOsg::VisController", "osgMyGUI::Drawable",
|
||||||
"osg::DrawCallback", "osg::UniformBufferObject", "osgOQ::ClearQueriesCallback",
|
"osg::DrawCallback", "osg::UniformBufferObject", "osgOQ::ClearQueriesCallback",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user