*/
#include "particles.h"
+#include <cmath>
#include "client.h"
#include "collision.h"
-#include <stdlib.h>
+#include "client/clientevent.h"
+#include "client/renderingengine.h"
#include "util/numeric.h"
#include "light.h"
#include "environment.h"
#include "clientmap.h"
#include "mapnode.h"
+#include "nodedef.h"
#include "client.h"
#include "settings.h"
Particle::Particle(
IGameDef *gamedef,
- scene::ISceneManager* smgr,
LocalPlayer *player,
ClientEnvironment *env,
v3f pos,
u8 glow,
video::SColor color
):
- scene::ISceneNode(smgr->getRootSceneNode(), smgr)
+ scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
+ RenderingEngine::get_scene_manager())
{
// Misc
m_gamedef = gamedef;
m_texpos = texpos;
m_texsize = texsize;
m_animation = anim;
- m_animation_frame = 0;
- m_animation_time = 0.0;
// Color
m_base_color = color;
m_velocity = velocity;
m_acceleration = acceleration;
m_expiration = expirationtime;
- m_time = 0;
m_player = player;
m_size = size;
m_collisiondetection = collisiondetection;
updateVertices();
}
-Particle::~Particle()
-{
-}
-
void Particle::OnRegisterSceneNode()
{
if (IsVisible)
0, 0, 0, 0, m_color, tx0, ty0);
v3s16 camera_offset = m_env->getCameraOffset();
- for(u16 i=0; i<4; i++)
- {
+ for (video::S3DVertex &vertex : m_vertices) {
if (m_vertical) {
v3f ppos = m_player->getPosition()/BS;
- m_vertices[i].Pos.rotateXZBy(atan2(ppos.Z-m_pos.Z, ppos.X-m_pos.X)/core::DEGTORAD+90);
+ vertex.Pos.rotateXZBy(std::atan2(ppos.Z - m_pos.Z, ppos.X - m_pos.X) /
+ core::DEGTORAD + 90);
} else {
- m_vertices[i].Pos.rotateYZBy(m_player->getPitch());
- m_vertices[i].Pos.rotateXZBy(m_player->getYaw());
+ vertex.Pos.rotateYZBy(m_player->getPitch());
+ vertex.Pos.rotateXZBy(m_player->getYaw());
}
- m_box.addInternalPoint(m_vertices[i].Pos);
- m_vertices[i].Pos += m_pos*BS - intToFloat(camera_offset, BS);
+ m_box.addInternalPoint(vertex.Pos);
+ vertex.Pos += m_pos*BS - intToFloat(camera_offset, BS);
}
}
ParticleSpawner
*/
-ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, LocalPlayer *player,
+ParticleSpawner::ParticleSpawner(IGameDef *gamedef, LocalPlayer *player,
u16 amount, float time,
v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
float minexptime, float maxexptime, float minsize, float maxsize,
m_particlemanager(p_manager)
{
m_gamedef = gamedef;
- m_smgr = smgr;
m_player = player;
m_amount = amount;
m_spawntime = time;
}
}
-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_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)
{
}
}
- if (m_spawntime != 0) // Spawner exists for a predefined timespan
- {
- for(std::vector<float>::iterator i = m_spawntimes.begin();
- i != m_spawntimes.end();)
- {
- if ((*i) <= m_time && m_amount > 0)
- {
+ if (m_spawntime != 0) {
+ // Spawner exists for a predefined timespan
+ for (std::vector<float>::iterator i = m_spawntimes.begin();
+ i != m_spawntimes.end();) {
+ if ((*i) <= m_time && m_amount > 0) {
m_amount--;
// Pretend to, but don't actually spawn a particle if it is
// attached to an unloaded object or distant from player.
- if (!unloaded) {
- v3f ppos = m_player->getPosition() / BS;
- v3f pos = random_v3f(m_minpos, m_maxpos);
-
- 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);
- pos += attached_pos;
- 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);
- }
- }
+ if (!unloaded)
+ spawnParticle(env, radius, is_attached, attached_pos, attached_yaw);
+
i = m_spawntimes.erase(i);
- }
- else
- {
+ } else {
++i;
}
}
- }
- else // Spawner exists for an infinity timespan, spawn on a per-second base
- {
+ } else {
+ // Spawner exists for an infinity timespan, spawn on a per-second base
+
// Skip this step if attached to an unloaded object
if (unloaded)
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);
-
- 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);
- pos += attached_pos;
- 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);
- }
- }
+
+ for (int i = 0; i <= m_amount; i++) {
+ if (rand() / (float)RAND_MAX < dtime)
+ spawnParticle(env, radius, is_attached, attached_pos, attached_yaw);
}
}
}
}
void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
- scene::ISceneManager* smgr, LocalPlayer *player)
+ LocalPlayer *player)
{
switch (event->type) {
case CE_DELETE_PARTICLESPAWNER: {
video::ITexture *texture =
client->tsrc()->getTextureForMesh(*(event->add_particlespawner.texture));
- ParticleSpawner* toadd = new ParticleSpawner(client, smgr, player,
+ ParticleSpawner *toadd = new ParticleSpawner(client, player,
event->add_particlespawner.amount,
event->add_particlespawner.spawntime,
*event->add_particlespawner.minpos,
video::ITexture *texture =
client->tsrc()->getTextureForMesh(*(event->spawn_particle.texture));
- Particle* toadd = new Particle(client, smgr, player, m_env,
+ Particle *toadd = new Particle(client, player, m_env,
*event->spawn_particle.pos,
*event->spawn_particle.vel,
*event->spawn_particle.acc,
}
void ParticleManager::addDiggingParticles(IGameDef* gamedef,
- scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos,
- const MapNode &n, const ContentFeatures &f)
+ LocalPlayer *player, v3s16 pos, const MapNode &n, const ContentFeatures &f)
{
- for (u16 j = 0; j < 32; j++) // set the amount of particles here
- {
- addNodeParticle(gamedef, smgr, player, pos, n, f);
- }
-}
+ // No particles for "airlike" nodes
+ if (f.drawtype == NDT_AIRLIKE)
+ return;
-void ParticleManager::addPunchingParticles(IGameDef* gamedef,
- scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos,
- const MapNode &n, const ContentFeatures &f)
-{
- addNodeParticle(gamedef, smgr, player, pos, n, f);
+ // set the amount of particles here
+ for (u16 j = 0; j < 32; j++) {
+ addNodeParticle(gamedef, player, pos, n, f);
+ }
}
void ParticleManager::addNodeParticle(IGameDef* gamedef,
- scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos,
- const MapNode &n, const ContentFeatures &f)
+ LocalPlayer *player, v3s16 pos, const MapNode &n, const ContentFeatures &f)
{
+ // No particles for "airlike" nodes
+ if (f.drawtype == NDT_AIRLIKE)
+ return;
+
// Texture
u8 texid = myrand_range(0, 5);
const TileLayer &tile = f.tiles[texid].layers[0];
// Only use first frame of animated texture
if (tile.material_flags & MATERIAL_FLAG_ANIMATION)
- texture = tile.frames[0].texture;
+ texture = (*tile.frames)[0].texture;
else
texture = tile.texture;
float size = rand() % 64 / 512.;
float visual_size = BS * size;
+ if (tile.scale)
+ size /= tile.scale;
v2f texsize(size * 2, size * 2);
v2f texpos;
texpos.X = ((rand() % 64) / 64. - texsize.X);
Particle* toadd = new Particle(
gamedef,
- smgr,
player,
m_env,
particlepos,