Handle NiParticleBomb (feature #7634)

macos_ci_fix
Alexei Kotov 7 months ago
parent 0748e2094d
commit 715efe6cb1

@ -107,6 +107,7 @@
Feature #7546: Start the game on Fredas
Feature #7568: Uninterruptable scripted music
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 #7113: Move from std::atoi to std::from_char
Task #7117: Replace boost::scoped_array with std::vector

@ -1092,6 +1092,18 @@ namespace NifOsg
const Nif::NiGravity* gr = static_cast<const Nif::NiGravity*>(modifier.getPtr());
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)
{
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()
: osgParticle::Emitter()
, mFlags(0)

@ -199,6 +199,31 @@ namespace NifOsg
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.
// Alternatively, returns the node's parent Group if that node is not a Group (i.e. a leaf node).
class FindGroupByRecIndex : public osg::NodeVisitor

@ -167,7 +167,7 @@ namespace SceneUtil
"SceneUtil::DisableLight", "SceneUtil::MWShadowTechnique", "SceneUtil::TextKeyMapHolder",
"Shader::AddedState", "Shader::RemovedAlphaFunc", "NifOsg::FlipController",
"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::UpdateMorphGeometry", "NifOsg::UVController", "NifOsg::VisController", "osgMyGUI::Drawable",
"osg::DrawCallback", "osg::UniformBufferObject", "osgOQ::ClearQueriesCallback",

Loading…
Cancel
Save