Add an option to disable pre-generation for explosion particles

Also remove some unused code
This commit is contained in:
Benau 2017-10-15 11:32:58 +08:00
parent b1f4ced6f0
commit 998b11ed51
7 changed files with 48 additions and 512 deletions

View File

@ -26,12 +26,11 @@
#include "graphics/material_manager.hpp"
#include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/stk_particle.hpp"
#include "items/projectile_manager.hpp"
#include "race/race_manager.hpp"
#include "utils/vec3.hpp"
#include <IParticleSystemSceneNode.h>
const float burst_time = 0.1f;
/** Creates an explosion effect. */
@ -50,6 +49,7 @@ Explosion::Explosion(const Vec3& coord, const char* explosion_sound, const char
if (UserConfigParams::m_graphical_effects > 1)
{
m_emitter = new ParticleEmitter(particles, coord, NULL);
m_emitter->getNode()->setPreGenerating(false);
}
#endif
} // Explosion
@ -81,27 +81,6 @@ bool Explosion::updateAndDelete(float dt)
m_emission_frames++;
m_remaining_time -= dt;
#ifndef SERVER_ONLY
if (m_remaining_time < 0.0f && m_remaining_time >= -explosion_time &&
m_emitter != NULL)
{
scene::ISceneNode* node = m_emitter->getNode();
const int intensity = (int)(255-(m_remaining_time/-explosion_time)*255);
node->getMaterial(0).AmbientColor.setGreen(intensity);
node->getMaterial(0).DiffuseColor.setGreen(intensity);
node->getMaterial(0).EmissiveColor.setGreen(intensity);
node->getMaterial(0).AmbientColor.setBlue(intensity);
node->getMaterial(0).DiffuseColor.setBlue(intensity);
node->getMaterial(0).EmissiveColor.setBlue(intensity);
node->getMaterial(0).AmbientColor.setRed(intensity);
node->getMaterial(0).DiffuseColor.setRed(intensity);
node->getMaterial(0).EmissiveColor.setRed(intensity);
}
#endif
// Do nothing more if the animation is still playing
if (m_remaining_time>0) return false;

View File

@ -32,264 +32,9 @@
#include "utils/constants.hpp"
#include "utils/helpers.hpp"
#include <SParticle.h>
#include <IParticleAffector.h>
#include <ICameraSceneNode.h>
#include <IParticleSystemSceneNode.h>
#include <IParticleBoxEmitter.h>
#include <ISceneManager.h>
#include <algorithm>
class FadeAwayAffector : public scene::IParticleAffector
{
/** (Squared) distance from camera at which a particle started being faded out */
float m_start_fading;
/** (Squared) distance from camera at which a particle is completely faded out */
float m_end_fading;
public:
FadeAwayAffector(float start, float end)
{
m_start_fading = start;
m_end_fading = end;
assert(m_end_fading >= m_start_fading);
} // FadeAwayAffector
// ------------------------------------------------------------------------
virtual void affect(u32 now, scene::SParticle* particlearray, u32 count)
{
scene::ICameraSceneNode* curr_cam =
irr_driver->getSceneManager()->getActiveCamera();
const core::vector3df& cam_pos = curr_cam->getPosition();
// printf("Affect called with now=%u, camera=%s\n", now, curr_cam->getName());
for (unsigned int n=0; n<count; n++)
{
scene::SParticle& curr = particlearray[n];
core::vector3df diff = curr.pos - cam_pos;
const float x = diff.X;
const float y = diff.Y;
const float z = diff.Z;
const float distance_squared = x*x + y*y + z*z;
if (distance_squared < m_start_fading)
{
curr.color.setAlpha(255);
}
else if (distance_squared > m_end_fading)
{
curr.color.setAlpha(0);
}
else
{
curr.color.setAlpha((int)((distance_squared - m_start_fading)
/ (m_end_fading - m_start_fading)));
}
} // for n<count
} // affect
// ------------------------------------------------------------------------
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
{
// FIXME: this method seems to make sense only for built-in affectors
return scene::EPAT_FADE_OUT;
}
}; // FadeAwayAffector
// ============================================================================
class HeightMapCollisionAffector : public scene::IParticleAffector
{
std::vector< std::vector<float> > m_height_map;
Track* m_track;
bool m_first_time;
public:
HeightMapCollisionAffector(Track* t) : m_height_map(t->buildHeightMap())
{
m_track = t;
m_first_time = true;
}
virtual void affect(u32 now, scene::SParticle* particlearray, u32 count)
{
const Vec3* aabb_min;
const Vec3* aabb_max;
m_track->getAABB(&aabb_min, &aabb_max);
float track_x = aabb_min->getX();
float track_z = aabb_min->getZ();
const float track_x_len = aabb_max->getX() - aabb_min->getX();
const float track_z_len = aabb_max->getZ() - aabb_min->getZ();
for (unsigned int n=0; n<count; n++)
{
scene::SParticle& curr = particlearray[n];
const int i = (int)( (curr.pos.X - track_x)
/track_x_len*(HEIGHT_MAP_RESOLUTION) );
const int j = (int)( (curr.pos.Z - track_z)
/track_z_len*(HEIGHT_MAP_RESOLUTION) );
if (i >= HEIGHT_MAP_RESOLUTION || j >= HEIGHT_MAP_RESOLUTION) continue;
if (i < 0 || j < 0) continue;
/*
// debug draw
core::vector3df lp = curr.pos;
core::vector3df lp2 = curr.pos;
lp2.Y = m_height_map[i][j] + 0.02f;
irr_driver->getVideoDriver()->draw3DLine(lp, lp2, video::SColor(255,255,0,0));
core::vector3df lp3 = lp2;
lp3.X += 0.1f;
lp3.Y += 0.02f;
lp3.Z += 0.1f;
lp2.X -= 0.1f;
lp2.Y -= 0.02f;
lp2.Z -= 0.1f;
irr_driver->getVideoDriver()->draw3DBox(core::aabbox3d< f32 >(lp2, lp3), video::SColor(255,255,0,0));
*/
if (m_first_time)
{
curr.pos.Y = m_height_map[i][j]
+ (curr.pos.Y - m_height_map[i][j])
*((rand()%500)/500.0f);
}
else
{
if (curr.pos.Y < m_height_map[i][j])
{
//curr.color = video::SColor(255,255,0,0);
curr.endTime = curr.startTime; // destroy particle
}
}
}
if (m_first_time) m_first_time = false;
}
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
{
// FIXME: this method seems to make sense only for built-in affectors
return scene::EPAT_FADE_OUT;
}
};
// ============================================================================
class WindAffector : public scene::IParticleAffector
{
/** (Squared) distance from camera at which a particle is completely faded out */
float m_speed;
float m_seed;
public:
WindAffector(float speed): m_speed(speed)
{
m_seed = (float)((rand() % 1000) - 500);
}
// ------------------------------------------------------------------------
virtual void affect(u32 now, scene::SParticle* particlearray, u32 count)
{
const float time = irr_driver->getDevice()->getTimer()->getTime() / 10000.0f;
core::vector3df dir = irr_driver->getWind();
dir *= m_speed * std::min(noise2d(time, m_seed), -0.2f);
for (u32 n = 0; n < count; n++)
{
scene::SParticle& cur = particlearray[n];
cur.pos += dir;
} // for n<count
} // affect
// ------------------------------------------------------------------------
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
{
// FIXME: this method seems to make sense only for built-in affectors
return scene::EPAT_FADE_OUT;
}
}; // WindAffector
// ============================================================================
class ScaleAffector : public scene::IParticleAffector
{
public:
ScaleAffector(const core::vector2df& scaleFactor = core::vector2df(1.0f, 1.0f)) : ScaleFactor(scaleFactor)
{
}
virtual void affect(u32 now, scene::SParticle *particlearray, u32 count)
{
for (u32 i = 0; i<count; i++)
{
const u32 maxdiff = particlearray[i].endTime - particlearray[i].startTime;
const u32 curdiff = now - particlearray[i].startTime;
const f32 timefraction = (f32)curdiff / maxdiff;
core::dimension2df destsize = particlearray[i].startSize * ScaleFactor;
particlearray[i].size = particlearray[i].startSize + (destsize - particlearray[i].startSize) * timefraction;
}
}
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
{
return scene::EPAT_SCALE;
}
protected:
core::vector2df ScaleFactor;
};
// ============================================================================
class ColorAffector : public scene::IParticleAffector
{
protected:
core::vector3df m_color_from;
core::vector3df m_color_to;
public:
ColorAffector(const core::vector3df& colorFrom, const core::vector3df& colorTo) :
m_color_from(colorFrom), m_color_to(colorTo)
{
}
virtual void affect(u32 now, scene::SParticle *particlearray, u32 count)
{
for (u32 i = 0; i<count; i++)
{
const u32 maxdiff = particlearray[i].endTime - particlearray[i].startTime;
const u32 curdiff = now - particlearray[i].startTime;
f32 timefraction = 0.0f;
if (maxdiff > 0)
timefraction = (f32)curdiff / maxdiff;
core::vector3df curr_color = m_color_from + (m_color_to - m_color_from)* timefraction;
particlearray[i].color = video::SColor(255, (int)curr_color.X, (int)curr_color.Y, (int)curr_color.Z);
}
}
virtual scene::E_PARTICLE_AFFECTOR_TYPE getType() const
{
return scene::EPAT_SCALE;
}
};
// ============================================================================
//-----------------------------------------------------------------------------
ParticleEmitter::ParticleEmitter(const ParticleKind* type,
const Vec3 &position,
scene::ISceneNode* parent,
@ -304,15 +49,13 @@ ParticleEmitter::ParticleEmitter(const ParticleKind* type,
m_particle_type = NULL;
m_parent = parent;
m_emission_decay_rate = 0;
m_is_glsl = true;//CVS->isGLSL();
m_randomize_initial_y = randomize_initial_y;
m_important = important;
setParticleType(type);
assert(m_node != NULL);
} // KartParticleSystem
} // ParticleEmitter
//-----------------------------------------------------------------------------
/** Destructor, removes
@ -328,7 +71,6 @@ ParticleEmitter::~ParticleEmitter()
} // ~ParticleEmitter
//-----------------------------------------------------------------------------
void ParticleEmitter::update(float dt)
{
assert(m_magic_number == 0x58781325);
@ -392,32 +134,9 @@ void ParticleEmitter::setCreationRateAbsolute(float f)
m_min_rate = f;
m_max_rate = f;
#if 0
// FIXME: to work around irrlicht bug, when an emitter is paused by setting the rate
// to 0 results in a massive emission when enabling it back. In irrlicht 1.8
// the node has a method called "clearParticles" that should be cleaner than this
if (f <= 0.0f && m_node->getEmitter())
{
m_node->clearParticles();
}
else if (m_node->getEmitter() == NULL)
{
m_node->setEmitter(m_emitter);
}
#endif
/* if (f <= 0.0f)
{
m_node->setVisible(false);
}
else
{
m_node->setVisible(true);
}*/
} // setCreationRateAbsolute
//-----------------------------------------------------------------------------
int ParticleEmitter::getCreationRate()
{
if (m_node->getEmitter() == NULL) return 0;
@ -443,14 +162,6 @@ void ParticleEmitter::setRotation(const Vec3 &rot)
} // setRotation
//-----------------------------------------------------------------------------
void ParticleEmitter::clearParticles()
{
m_node->clearParticles();
}
//-----------------------------------------------------------------------------
void ParticleEmitter::setParticleType(const ParticleKind* type)
{
assert(m_magic_number == 0x58781325);
@ -465,10 +176,7 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
}
else
{
if (m_is_glsl)
m_node = STKParticle::addParticleNode(m_is_glsl, type->randomizeInitialY());
else
m_node = irr_driver->addParticleNode();
m_node = new STKParticle(type->randomizeInitialY());
}
if (m_parent != NULL)
@ -556,27 +264,6 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread()
);
#if VISUALIZE_BOX_EMITTER
if (m_parent != NULL)
{
for (int x=0; x<2; x++)
{
for (int y=0; y<2; y++)
{
for (int z=0; z<2; z++)
{
m_visualisation.push_back(
irr_driver->getSceneManager()->addSphereSceneNode(0.05f, 16, m_parent, -1,
core::vector3df((x ? box_size_x : -box_size_x),
(y ? box_size_y : -box_size_y),
-0.6 - (z ? 0 : type->getBoxSizeZ())))
);
}
}
}
}
#endif
break;
}
case EMITTER_SPHERE:
@ -611,123 +298,48 @@ void ParticleEmitter::setParticleType(const ParticleKind* type)
{
m_node->setEmitter(m_emitter); // this grabs the emitter
scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255),
type->getFadeoutTime());
m_node->addAffector(af);
af->drop();
if (type->getGravityStrength() != 0)
{
scene::IParticleGravityAffector *gaf = m_node->createGravityAffector(core::vector3df(00.0f, type->getGravityStrength(), 0.0f),
type->getForceLostToGravityTime());
m_node->addAffector(gaf);
gaf->drop();
}
const float fas = type->getFadeAwayStart();
const float fae = type->getFadeAwayEnd();
if (fas > 0.0f && fae > 0.0f)
{
FadeAwayAffector* faa = new FadeAwayAffector(fas*fas, fae*fae);
m_node->addAffector(faa);
faa->drop();
}
if (type->hasScaleAffector())
{
if (m_is_glsl)
{
static_cast<STKParticle*>(m_node)->setIncreaseFactor(type->getScaleAffectorFactorX());
}
else
{
core::vector2df factor = core::vector2df(type->getScaleAffectorFactorX(),
type->getScaleAffectorFactorY());
scene::IParticleAffector* scale_affector = new ScaleAffector(factor);
m_node->addAffector(scale_affector);
scale_affector->drop();
}
m_node->setIncreaseFactor(type->getScaleAffectorFactorX());
}
if (type->getMinColor() != type->getMaxColor())
{
if (m_is_glsl)
{
video::SColor color_from = type->getMinColor();
static_cast<STKParticle*>(m_node)->setColorFrom(color_from.getRed() / 255.0f,
color_from.getGreen() / 255.0f,
color_from.getBlue() / 255.0f);
video::SColor color_to = type->getMaxColor();
static_cast<STKParticle*>(m_node)->setColorTo(color_to.getRed() / 255.0f,
color_to.getGreen() / 255.0f,
color_to.getBlue() / 255.0f);
}
else
{
video::SColor color_from = type->getMinColor();
core::vector3df color_from_v =
core::vector3df(float(color_from.getRed()),
float(color_from.getGreen()),
float(color_from.getBlue()));
video::SColor color_from = type->getMinColor();
m_node->setColorFrom(color_from.getRed() / 255.0f,
color_from.getGreen() / 255.0f,
color_from.getBlue() / 255.0f);
video::SColor color_to = type->getMaxColor();
core::vector3df color_to_v = core::vector3df(float(color_to.getRed()),
float(color_to.getGreen()),
float(color_to.getBlue()));
ColorAffector* affector = new ColorAffector(color_from_v, color_to_v);
m_node->addAffector(affector);
affector->drop();
}
}
const float windspeed = type->getWindSpeed();
if (windspeed > 0.01f)
{
WindAffector *waf = new WindAffector(windspeed);
m_node->addAffector(waf);
waf->drop();
// TODO: wind affector for GLSL particles
video::SColor color_to = type->getMaxColor();
m_node->setColorTo(color_to.getRed() / 255.0f,
color_to.getGreen() / 255.0f,
color_to.getBlue() / 255.0f);
}
const bool flips = type->getFlips();
if (flips)
{
if (m_is_glsl)
static_cast<STKParticle*>(m_node)->setFlips();
m_node->setFlips();
}
}
} // setParticleType
//-----------------------------------------------------------------------------
void ParticleEmitter::addHeightMapAffector(Track* t)
{
if (m_is_glsl)
{
const Vec3* aabb_min;
const Vec3* aabb_max;
t->getAABB(&aabb_min, &aabb_max);
float track_x = aabb_min->getX();
float track_z = aabb_min->getZ();
const float track_x_len = aabb_max->getX() - aabb_min->getX();
const float track_z_len = aabb_max->getZ() - aabb_min->getZ();
std::vector<std::vector<float> > array = t->buildHeightMap();
static_cast<STKParticle*>(m_node)->setHeightmap(array,
track_x, track_z, track_x_len, track_z_len);
}
else
{
HeightMapCollisionAffector* hmca = new HeightMapCollisionAffector(t);
m_node->addAffector(hmca);
hmca->drop();
}
const Vec3* aabb_min;
const Vec3* aabb_max;
t->getAABB(&aabb_min, &aabb_max);
float track_x = aabb_min->getX();
float track_z = aabb_min->getZ();
const float track_x_len = aabb_max->getX() - aabb_min->getX();
const float track_z_len = aabb_max->getZ() - aabb_min->getZ();
std::vector<std::vector<float> > array = t->buildHeightMap();
m_node->setHeightmap(array, track_x, track_z, track_x_len, track_z_len);
}
//-----------------------------------------------------------------------------
void ParticleEmitter::resizeBox(float size)
{
scene::IParticleBoxEmitter* emitter = (scene::IParticleBoxEmitter*)m_emitter;
@ -735,31 +347,9 @@ void ParticleEmitter::resizeBox(float size)
const float box_size_x = m_particle_type->getBoxSizeX()/2.0f;
const float box_size_y = m_particle_type->getBoxSizeY()/2.0f;
emitter->setBox( core::aabbox3df(-box_size_x, -box_size_y, -0.6f,
box_size_x, box_size_y, -0.6f - size) );
#if VISUALIZE_BOX_EMITTER
if (m_parent != NULL)
{
int n = 0;
for (int x=0; x<2; x++)
{
for (int y=0; y<2; y++)
{
for (int z=0; z<2; z++)
{
m_visualisation[n]->setPosition(
core::vector3df((x ? box_size_x : -box_size_x),
(y ? box_size_y : -box_size_y),
-0.6 - (z ? 0 : size))
);
n++;
}
}
}
}
#endif
}
#endif // !SERVER_ONLY

View File

@ -21,7 +21,7 @@
namespace irr
{
namespace scene { class IParticleSystemSceneNode; class ISceneNode; class IParticleEmitter; }
namespace scene { class ISceneNode; class IParticleEmitter; }
}
using namespace irr;
@ -29,14 +29,9 @@ using namespace irr;
#include "utils/no_copy.hpp"
#include "utils/vec3.hpp"
#define VISUALIZE_BOX_EMITTER 0
#if VISUALIZE_BOX_EMITTER
#include <vector>
#endif
class Material;
class ParticleKind;
class STKParticle;
class Track;
/**
@ -46,11 +41,8 @@ class Track;
class ParticleEmitter : public NoCopy
{
private:
bool m_is_glsl;
/** Irrlicht's particle systems. */
scene::IParticleSystemSceneNode *m_node;
/** STK particle systems. */
STKParticle* m_node;
Vec3 m_position;
@ -60,10 +52,6 @@ private:
* particles per second. */
scene::IParticleEmitter *m_emitter;
#if VISUALIZE_BOX_EMITTER
std::vector<scene::ISceneNode*> m_visualisation;
#endif
const ParticleKind *m_particle_type;
unsigned int m_magic_number;
@ -103,9 +91,7 @@ public:
void resizeBox(float size);
void clearParticles();
scene::IParticleSystemSceneNode* getNode() { return m_node; }
STKParticle* getNode() { return m_node; }
/** call this if the node was freed otherwise */
void unsetNode() { m_node = NULL; }

View File

@ -30,31 +30,15 @@
std::vector<float> STKParticle::m_flips_data;
GLuint STKParticle::m_flips_buffer = 0;
// ----------------------------------------------------------------------------
scene::IParticleSystemSceneNode* STKParticle::addParticleNode(
bool withDefaultEmitter, bool randomize_initial_y, ISceneNode* parent,
s32 id, const core::vector3df& position, const core::vector3df& rotation,
const core::vector3df& scale)
{
if (!parent)
{
parent = irr_driver->getSceneManager()->getRootSceneNode();
}
IParticleSystemSceneNode* node = new STKParticle(withDefaultEmitter,
parent, irr_driver->getSceneManager(), id, position, rotation, scale,
randomize_initial_y);
node->drop();
return node;
} // addParticleNode
// ----------------------------------------------------------------------------
STKParticle::STKParticle(bool createDefaultEmitter,
ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale,
bool randomize_initial_y)
: CParticleSystemSceneNode(createDefaultEmitter, parent, mgr, id,
STKParticle::STKParticle(bool randomize_initial_y, ISceneNode* parent, s32 id,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale)
: CParticleSystemSceneNode(true,
parent ? parent :
irr_driver->getSceneManager()
->getRootSceneNode(),
irr_driver->getSceneManager(), id,
position, rotation, scale)
{
m_hm = NULL;
@ -62,9 +46,11 @@ STKParticle::STKParticle(bool createDefaultEmitter,
m_color_from = m_color_to;
m_size_increase_factor = 0.0f;
m_first_execution = true;
m_pre_generating = true;
m_randomize_initial_y = randomize_initial_y;
m_flips = false;
m_max_count = 0;
drop();
} // STKParticle
// ----------------------------------------------------------------------------
@ -226,6 +212,7 @@ void STKParticle::setEmitter(scene::IParticleEmitter* emitter)
delete m_hm;
m_hm = NULL;
m_first_execution = true;
m_pre_generating = true;
m_flips = false;
m_max_count = emitter->getMaxParticlesPerSecond() * emitter->getMaxLifeTime() / 1000;
@ -261,7 +248,8 @@ void STKParticle::generate(std::vector<CPUParticle>* out)
if (m_first_execution)
{
m_previous_frame_matrix = AbsoluteTransformation;
for (int i = 0; i < (m_max_count > 5000 ? 5 : 100); i++)
for (int i = 0; i <
(m_max_count > 5000 ? 5 : m_pre_generating ? 100 : 0); i++)
{
if (m_hm != NULL)
{

View File

@ -63,7 +63,7 @@ private:
float m_size_increase_factor;
bool m_first_execution, m_randomize_initial_y, m_flips;
bool m_first_execution, m_randomize_initial_y, m_flips, m_pre_generating;
/** Previous frame particles emitter source matrix */
core::matrix4 m_previous_frame_matrix;
@ -88,20 +88,12 @@ private:
public:
// ------------------------------------------------------------------------
static IParticleSystemSceneNode *addParticleNode(
bool withDefaultEmitter = true, bool randomize_initial_y = false,
STKParticle(bool randomize_initial_y = false,
ISceneNode* parent = 0, s32 id = -1,
const core::vector3df& position = core::vector3df(0, 0, 0),
const core::vector3df& rotation = core::vector3df(0, 0, 0),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
// ------------------------------------------------------------------------
STKParticle(bool createDefaultEmitter,
ISceneNode* parent, scene::ISceneManager* mgr, s32 id,
const core::vector3df& position,
const core::vector3df& rotation,
const core::vector3df& scale,
bool randomize_initial_y);
// ------------------------------------------------------------------------
~STKParticle()
{
delete m_hm;
@ -142,6 +134,8 @@ public:
// ------------------------------------------------------------------------
unsigned getMaxCount() const { return m_max_count; }
// ------------------------------------------------------------------------
void setPreGenerating(bool val) { m_pre_generating = val; }
// ------------------------------------------------------------------------
static void updateFlips(unsigned maximum_particle_count);
// ------------------------------------------------------------------------
static void destroyFlipsBuffer()

View File

@ -225,7 +225,6 @@ void KartGFX::reset()
if(m_all_emitters[i])
{
m_all_emitters[i]->setCreationRateAbsolute(0);
m_all_emitters[i]->clearParticles();
}
}
#endif

View File

@ -31,6 +31,7 @@
#include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/stk_mesh_scene_node.hpp"
#include "graphics/stk_particle.hpp"
#include "graphics/stk_tex_manager.hpp"
#include "graphics/render_info.hpp"
#include "io/file_manager.hpp"
@ -987,7 +988,6 @@ void TrackObjectPresentationParticles::stop()
if (m_emitter != NULL)
{
m_emitter->setCreationRateAbsolute(0.0f);
m_emitter->clearParticles();
}
#endif
}