forked from teamnwah/openmw-tes3coop
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
7.2 KiB
C++
242 lines
7.2 KiB
C++
#ifndef OPENMW_COMPONENTS_NIFOSG_PARTICLE_H
|
|
#define OPENMW_COMPONENTS_NIFOSG_PARTICLE_H
|
|
|
|
#include <osgParticle/Particle>
|
|
#include <osgParticle/Shooter>
|
|
#include <osgParticle/Operator>
|
|
#include <osgParticle/Emitter>
|
|
#include <osgParticle/Placer>
|
|
#include <osgParticle/Counter>
|
|
|
|
#include <osg/NodeCallback>
|
|
|
|
#include "controller.hpp" // ValueInterpolator
|
|
|
|
namespace Nif
|
|
{
|
|
class NiGravity;
|
|
class NiPlanarCollider;
|
|
class NiSphericalCollider;
|
|
class NiColorData;
|
|
}
|
|
|
|
namespace NifOsg
|
|
{
|
|
|
|
// Subclass ParticleSystem to support a limit on the number of active particles.
|
|
class ParticleSystem : public osgParticle::ParticleSystem
|
|
{
|
|
public:
|
|
ParticleSystem();
|
|
ParticleSystem(const ParticleSystem& copy, const osg::CopyOp& copyop);
|
|
|
|
META_Object(NifOsg, ParticleSystem)
|
|
|
|
virtual osgParticle::Particle* createParticle(const osgParticle::Particle *ptemplate);
|
|
|
|
void setQuota(int quota);
|
|
|
|
private:
|
|
int mQuota;
|
|
};
|
|
|
|
// HACK: Particle doesn't allow setting the initial age, but we need this for loading the particle system state
|
|
class ParticleAgeSetter : public osgParticle::Particle
|
|
{
|
|
public:
|
|
ParticleAgeSetter(float age)
|
|
: Particle()
|
|
{
|
|
_t0 = age;
|
|
}
|
|
};
|
|
|
|
// Node callback used to set the inverse of the parent's world matrix on the MatrixTransform
|
|
// that the callback is attached to. Used for certain particle systems,
|
|
// so that the particles do not move with the node they are attached to.
|
|
class InverseWorldMatrix : public osg::NodeCallback
|
|
{
|
|
public:
|
|
InverseWorldMatrix()
|
|
{
|
|
}
|
|
InverseWorldMatrix(const InverseWorldMatrix& copy, const osg::CopyOp& op)
|
|
: osg::Object(), osg::NodeCallback()
|
|
{
|
|
}
|
|
|
|
META_Object(NifOsg, InverseWorldMatrix)
|
|
|
|
void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
|
};
|
|
|
|
class ParticleShooter : public osgParticle::Shooter
|
|
{
|
|
public:
|
|
ParticleShooter(float minSpeed, float maxSpeed, float horizontalDir, float horizontalAngle, float verticalDir, float verticalAngle,
|
|
float lifetime, float lifetimeRandom);
|
|
ParticleShooter();
|
|
ParticleShooter(const ParticleShooter& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(NifOsg, ParticleShooter)
|
|
|
|
virtual void shoot(osgParticle::Particle* particle) const;
|
|
|
|
private:
|
|
float mMinSpeed;
|
|
float mMaxSpeed;
|
|
float mHorizontalDir;
|
|
float mHorizontalAngle;
|
|
float mVerticalDir;
|
|
float mVerticalAngle;
|
|
float mLifetime;
|
|
float mLifetimeRandom;
|
|
};
|
|
|
|
class PlanarCollider : public osgParticle::Operator
|
|
{
|
|
public:
|
|
PlanarCollider(const Nif::NiPlanarCollider* collider);
|
|
PlanarCollider();
|
|
PlanarCollider(const PlanarCollider& copy, const osg::CopyOp& copyop);
|
|
|
|
META_Object(NifOsg, PlanarCollider)
|
|
|
|
virtual void beginOperate(osgParticle::Program* program);
|
|
virtual void operate(osgParticle::Particle* particle, double dt);
|
|
|
|
private:
|
|
float mBounceFactor;
|
|
osg::Plane mPlane;
|
|
osg::Plane mPlaneInParticleSpace;
|
|
};
|
|
|
|
class SphericalCollider : public osgParticle::Operator
|
|
{
|
|
public:
|
|
SphericalCollider(const Nif::NiSphericalCollider* collider);
|
|
SphericalCollider();
|
|
SphericalCollider(const SphericalCollider& copy, const osg::CopyOp& copyop);
|
|
|
|
META_Object(NifOsg, SphericalCollider)
|
|
|
|
virtual void beginOperate(osgParticle::Program* program);
|
|
virtual void operate(osgParticle::Particle* particle, double dt);
|
|
private:
|
|
float mBounceFactor;
|
|
osg::BoundingSphere mSphere;
|
|
osg::BoundingSphere mSphereInParticleSpace;
|
|
};
|
|
|
|
class GrowFadeAffector : public osgParticle::Operator
|
|
{
|
|
public:
|
|
GrowFadeAffector(float growTime, float fadeTime);
|
|
GrowFadeAffector();
|
|
GrowFadeAffector(const GrowFadeAffector& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(NifOsg, GrowFadeAffector)
|
|
|
|
virtual void beginOperate(osgParticle::Program* program);
|
|
virtual void operate(osgParticle::Particle* particle, double dt);
|
|
|
|
private:
|
|
float mGrowTime;
|
|
float mFadeTime;
|
|
|
|
float mCachedDefaultSize;
|
|
};
|
|
|
|
typedef ValueInterpolator<Nif::Vector4KeyMap, LerpFunc> Vec4Interpolator;
|
|
class ParticleColorAffector : public osgParticle::Operator
|
|
{
|
|
public:
|
|
ParticleColorAffector(const Nif::NiColorData* clrdata);
|
|
ParticleColorAffector();
|
|
ParticleColorAffector(const ParticleColorAffector& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(NifOsg, ParticleColorAffector)
|
|
|
|
virtual void operate(osgParticle::Particle* particle, double dt);
|
|
|
|
private:
|
|
Vec4Interpolator mData;
|
|
};
|
|
|
|
class GravityAffector : public osgParticle::Operator
|
|
{
|
|
public:
|
|
GravityAffector(const Nif::NiGravity* gravity);
|
|
GravityAffector();
|
|
GravityAffector(const GravityAffector& copy, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY);
|
|
|
|
META_Object(NifOsg, GravityAffector)
|
|
|
|
virtual void operate(osgParticle::Particle* particle, double dt);
|
|
virtual void beginOperate(osgParticle::Program *);
|
|
|
|
private:
|
|
float mForce;
|
|
enum ForceType {
|
|
Type_Wind,
|
|
Type_Point
|
|
};
|
|
ForceType mType;
|
|
osg::Vec3f mPosition;
|
|
osg::Vec3f mDirection;
|
|
float mDecay;
|
|
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
|
|
{
|
|
public:
|
|
FindGroupByRecIndex(int recIndex);
|
|
|
|
virtual void apply(osg::Node &node);
|
|
|
|
// Technically not required as the default implementation would trickle down to apply(Node&) anyway,
|
|
// but we'll shortcut instead to avoid the chain of virtual function calls
|
|
virtual void apply(osg::MatrixTransform& node);
|
|
virtual void apply(osg::Geometry& node);
|
|
|
|
void applyNode(osg::Node& searchNode);
|
|
|
|
osg::Group* mFound;
|
|
osg::NodePath mFoundPath;
|
|
private:
|
|
int mRecIndex;
|
|
};
|
|
|
|
// Subclass emitter to support randomly choosing one of the child node's transforms for the emit position of new particles.
|
|
class Emitter : public osgParticle::Emitter
|
|
{
|
|
public:
|
|
Emitter(const std::vector<int>& targets);
|
|
Emitter();
|
|
Emitter(const Emitter& copy, const osg::CopyOp& copyop);
|
|
|
|
META_Object(NifOsg, Emitter)
|
|
|
|
virtual void emitParticles(double dt);
|
|
|
|
void setShooter(osgParticle::Shooter* shooter);
|
|
void setPlacer(osgParticle::Placer* placer);
|
|
void setCounter(osgParticle::Counter* counter);
|
|
|
|
private:
|
|
// NIF Record indices
|
|
std::vector<int> mTargets;
|
|
|
|
osg::ref_ptr<osgParticle::Placer> mPlacer;
|
|
osg::ref_ptr<osgParticle::Shooter> mShooter;
|
|
osg::ref_ptr<osgParticle::Counter> mCounter;
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|