ParticleSpawner::step cleanup and rotation fix (#6486)

* Particles: Move spawner code to a separate fucntion
This commit is contained in:
SmallJoker 2017-10-02 20:40:59 +02:00 committed by SmallJoker
parent 6b0fb94d60
commit 200e9cc4a2
2 changed files with 74 additions and 114 deletions

View File

@ -290,6 +290,59 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr,
ParticleSpawner::~ParticleSpawner() {} ParticleSpawner::~ParticleSpawner() {}
void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
bool is_attached, const v3f &attached_pos, float attached_yaw)
{
v3f ppos = m_player->getPosition() / BS;
v3f pos = random_v3f(m_minpos, m_maxpos);
// Need to apply this first or the following check
// will be wrong for attached spawners
if (is_attached) {
pos.rotateXZBy(attached_yaw);
pos += attached_pos;
}
if (pos.getDistanceFrom(ppos) > radius)
return;
v3f vel = random_v3f(m_minvel, m_maxvel);
v3f acc = random_v3f(m_minacc, m_maxacc);
if (is_attached) {
// Apply attachment yaw
vel.rotateXZBy(attached_yaw);
acc.rotateXZBy(attached_yaw);
}
float exptime = rand() / (float)RAND_MAX
* (m_maxexptime - m_minexptime)
+ m_minexptime;
float size = rand() / (float)RAND_MAX
* (m_maxsize - m_minsize)
+ m_minsize;
m_particlemanager->addParticle(new Particle(
m_gamedef,
m_smgr,
m_player,
env,
pos,
vel,
acc,
exptime,
size,
m_collisiondetection,
m_collision_removal,
m_vertical,
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0),
m_animation,
m_glow
));
}
void ParticleSpawner::step(float dtime, ClientEnvironment* env) void ParticleSpawner::step(float dtime, ClientEnvironment* env)
{ {
m_time += dtime; m_time += dtime;
@ -311,130 +364,33 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env)
} }
} }
if (m_spawntime != 0) // Spawner exists for a predefined timespan if (m_spawntime != 0) {
{ // Spawner exists for a predefined timespan
for(std::vector<float>::iterator i = m_spawntimes.begin(); for (std::vector<float>::iterator i = m_spawntimes.begin();
i != m_spawntimes.end();) i != m_spawntimes.end();) {
{ if ((*i) <= m_time && m_amount > 0) {
if ((*i) <= m_time && m_amount > 0)
{
m_amount--; m_amount--;
// Pretend to, but don't actually spawn a particle if it is // Pretend to, but don't actually spawn a particle if it is
// attached to an unloaded object or distant from player. // attached to an unloaded object or distant from player.
if (!unloaded) { if (!unloaded)
v3f ppos = m_player->getPosition() / BS; spawnParticle(env, radius, is_attached, attached_pos, attached_yaw);
v3f pos = random_v3f(m_minpos, m_maxpos);
// Need to apply this first or the following check
// will be wrong for attached spawners
if (is_attached)
pos += attached_pos;
if (pos.getDistanceFrom(ppos) <= radius) {
v3f vel = random_v3f(m_minvel, m_maxvel);
v3f acc = random_v3f(m_minacc, m_maxacc);
if (is_attached) {
// Apply attachment yaw and position
pos.rotateXZBy(attached_yaw);
vel.rotateXZBy(attached_yaw);
acc.rotateXZBy(attached_yaw);
}
float exptime = rand()/(float)RAND_MAX
*(m_maxexptime-m_minexptime)
+m_minexptime;
float size = rand()/(float)RAND_MAX
*(m_maxsize-m_minsize)
+m_minsize;
Particle* toadd = new Particle(
m_gamedef,
m_smgr,
m_player,
env,
pos,
vel,
acc,
exptime,
size,
m_collisiondetection,
m_collision_removal,
m_vertical,
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0),
m_animation,
m_glow);
m_particlemanager->addParticle(toadd);
}
}
i = m_spawntimes.erase(i); i = m_spawntimes.erase(i);
} } else {
else
{
++i; ++i;
} }
} }
} } else {
else // Spawner exists for an infinity timespan, spawn on a per-second base // Spawner exists for an infinity timespan, spawn on a per-second base
{
// Skip this step if attached to an unloaded object // Skip this step if attached to an unloaded object
if (unloaded) if (unloaded)
return; return;
for (int i = 0; i <= m_amount; i++)
{
if (rand()/(float)RAND_MAX < dtime)
{
// Do not spawn particle if distant from player
v3f ppos = m_player->getPosition() / BS;
v3f pos = random_v3f(m_minpos, m_maxpos);
// Need to apply this first or the following check for (int i = 0; i <= m_amount; i++) {
// will be wrong for attached spawners if (rand() / (float)RAND_MAX < dtime)
if (is_attached) spawnParticle(env, radius, is_attached, attached_pos, attached_yaw);
pos += attached_pos;
if (pos.getDistanceFrom(ppos) <= radius) {
v3f vel = random_v3f(m_minvel, m_maxvel);
v3f acc = random_v3f(m_minacc, m_maxacc);
if (is_attached) {
// Apply attachment yaw and position
pos.rotateXZBy(attached_yaw);
vel.rotateXZBy(attached_yaw);
acc.rotateXZBy(attached_yaw);
}
float exptime = rand()/(float)RAND_MAX
*(m_maxexptime-m_minexptime)
+m_minexptime;
float size = rand()/(float)RAND_MAX
*(m_maxsize-m_minsize)
+m_minsize;
Particle* toadd = new Particle(
m_gamedef,
m_smgr,
m_player,
env,
pos,
vel,
acc,
exptime,
size,
m_collisiondetection,
m_collision_removal,
m_vertical,
m_texture,
v2f(0.0, 0.0),
v2f(1.0, 1.0),
m_animation,
m_glow);
m_particlemanager->addParticle(toadd);
}
}
} }
} }
} }

View File

@ -117,7 +117,7 @@ private:
class ParticleSpawner class ParticleSpawner
{ {
public: public:
ParticleSpawner(IGameDef* gamedef, ParticleSpawner(IGameDef* gamedef,
scene::ISceneManager *smgr, scene::ISceneManager *smgr,
LocalPlayer *player, LocalPlayer *player,
@ -144,8 +144,12 @@ class ParticleSpawner
bool get_expired () bool get_expired ()
{ return (m_amount <= 0) && m_spawntime != 0; } { return (m_amount <= 0) && m_spawntime != 0; }
private: private:
ParticleManager* m_particlemanager; void spawnParticle(ClientEnvironment *env, float radius,
bool is_attached, const v3f &attached_pos,
float attached_yaw);
ParticleManager *m_particlemanager;
float m_time; float m_time;
IGameDef *m_gamedef; IGameDef *m_gamedef;
scene::ISceneManager *m_smgr; scene::ISceneManager *m_smgr;