aboutsummaryrefslogtreecommitdiff
path: root/src/client/particles.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/particles.cpp')
-rw-r--r--src/client/particles.cpp287
1 files changed, 161 insertions, 126 deletions
diff --git a/src/client/particles.cpp b/src/client/particles.cpp
index 5885987fc..7acd996dc 100644
--- a/src/client/particles.cpp
+++ b/src/client/particles.cpp
@@ -44,20 +44,28 @@ static f32 random_f32(f32 min, f32 max)
static v3f random_v3f(v3f min, v3f max)
{
- return v3f(random_f32(min.X, max.X), random_f32(min.Y, max.Y),
- random_f32(min.Z, max.Z));
+ return v3f(
+ random_f32(min.X, max.X),
+ random_f32(min.Y, max.Y),
+ random_f32(min.Z, max.Z));
}
/*
Particle
*/
-Particle::Particle(IGameDef *gamedef, LocalPlayer *player, ClientEnvironment *env,
- const ParticleParameters &p, video::ITexture *texture, v2f texpos,
- v2f texsize, video::SColor color) :
- scene::ISceneNode(
- RenderingEngine::get_scene_manager()->getRootSceneNode(),
- RenderingEngine::get_scene_manager())
+Particle::Particle(
+ IGameDef *gamedef,
+ LocalPlayer *player,
+ ClientEnvironment *env,
+ const ParticleParameters &p,
+ video::ITexture *texture,
+ v2f texpos,
+ v2f texsize,
+ video::SColor color
+):
+ scene::ISceneNode(RenderingEngine::get_scene_manager()->getRootSceneNode(),
+ RenderingEngine::get_scene_manager())
{
// Misc
m_gamedef = gamedef;
@@ -106,8 +114,7 @@ Particle::Particle(IGameDef *gamedef, LocalPlayer *player, ClientEnvironment *en
void Particle::OnRegisterSceneNode()
{
if (IsVisible)
- SceneManager->registerNodeForRendering(
- this, scene::ESNRP_TRANSPARENT_EFFECT);
+ SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT_EFFECT);
ISceneNode::OnRegisterSceneNode();
}
@@ -118,8 +125,9 @@ void Particle::render()
driver->setMaterial(m_material);
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
- u16 indices[] = {0, 1, 2, 2, 3, 0};
- driver->drawVertexPrimitiveList(m_vertices, 4, indices, 2, video::EVT_STANDARD,
+ u16 indices[] = {0,1,2, 2,3,0};
+ driver->drawVertexPrimitiveList(m_vertices, 4,
+ indices, 2, video::EVT_STANDARD,
scene::EPT_TRIANGLES, video::EIT_16BIT);
}
@@ -131,8 +139,8 @@ void Particle::step(float dtime)
v3f p_pos = m_pos * BS;
v3f p_velocity = m_velocity * BS;
collisionMoveResult r = collisionMoveSimple(m_env, m_gamedef, BS * 0.5f,
- box, 0.0f, dtime, &p_pos, &p_velocity,
- m_acceleration * BS, nullptr, m_object_collision);
+ box, 0.0f, dtime, &p_pos, &p_velocity, m_acceleration * BS, nullptr,
+ m_object_collision);
if (m_collision_removal && r.collides) {
// force expiration of the particle
m_expiration = -1.0;
@@ -147,7 +155,8 @@ void Particle::step(float dtime)
if (m_animation.type != TAT_NONE) {
m_animation_time += dtime;
int frame_length_i, frame_count;
- m_animation.determineParams(m_material.getTexture(0)->getSize(),
+ m_animation.determineParams(
+ m_material.getTexture(0)->getSize(),
&frame_count, &frame_length_i, NULL);
float frame_length = frame_length_i / 1000.0;
while (m_animation_time > frame_length) {
@@ -168,7 +177,11 @@ void Particle::updateLight()
u8 light = 0;
bool pos_ok;
- v3s16 p = v3s16(floor(m_pos.X + 0.5), floor(m_pos.Y + 0.5), floor(m_pos.Z + 0.5));
+ v3s16 p = v3s16(
+ floor(m_pos.X+0.5),
+ floor(m_pos.Y+0.5),
+ floor(m_pos.Z+0.5)
+ );
MapNode n = m_env->getClientMap().getNode(p, &pos_ok);
if (pos_ok)
light = n.getLightBlend(m_env->getDayNightRatio(), m_gamedef->ndef());
@@ -176,9 +189,10 @@ void Particle::updateLight()
light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0);
u8 m_light = decode_light(light + m_glow);
- m_color.set(255, m_light * m_base_color.getRed() / 255,
- m_light * m_base_color.getGreen() / 255,
- m_light * m_base_color.getBlue() / 255);
+ m_color.set(255,
+ m_light * m_base_color.getRed() / 255,
+ m_light * m_base_color.getGreen() / 255,
+ m_light * m_base_color.getBlue() / 255);
}
void Particle::updateVertices()
@@ -191,8 +205,7 @@ void Particle::updateVertices()
v2u32 framesize;
texcoord = m_animation.getTextureCoords(texsize, m_animation_frame);
m_animation.determineParams(texsize, NULL, NULL, &framesize);
- framesize_f = v2f(framesize.X / (float)texsize.X,
- framesize.Y / (float)texsize.Y);
+ framesize_f = v2f(framesize.X / (float) texsize.X, framesize.Y / (float) texsize.Y);
tx0 = m_texpos.X + texcoord.X;
tx1 = m_texpos.X + texcoord.X + framesize_f.X * m_texsize.X;
@@ -205,29 +218,27 @@ void Particle::updateVertices()
ty1 = m_texpos.Y + m_texsize.Y;
}
- m_vertices[0] = video::S3DVertex(
- -m_size / 2, -m_size / 2, 0, 0, 0, 0, m_color, tx0, ty1);
- m_vertices[1] = video::S3DVertex(
- m_size / 2, -m_size / 2, 0, 0, 0, 0, m_color, tx1, ty1);
- m_vertices[2] = video::S3DVertex(
- m_size / 2, m_size / 2, 0, 0, 0, 0, m_color, tx1, ty0);
- m_vertices[3] = video::S3DVertex(
- -m_size / 2, m_size / 2, 0, 0, 0, 0, m_color, tx0, ty0);
+ m_vertices[0] = video::S3DVertex(-m_size / 2, -m_size / 2,
+ 0, 0, 0, 0, m_color, tx0, ty1);
+ m_vertices[1] = video::S3DVertex(m_size / 2, -m_size / 2,
+ 0, 0, 0, 0, m_color, tx1, ty1);
+ m_vertices[2] = video::S3DVertex(m_size / 2, m_size / 2,
+ 0, 0, 0, 0, m_color, tx1, ty0);
+ m_vertices[3] = video::S3DVertex(-m_size / 2, m_size / 2,
+ 0, 0, 0, 0, m_color, tx0, ty0);
v3s16 camera_offset = m_env->getCameraOffset();
for (video::S3DVertex &vertex : m_vertices) {
if (m_vertical) {
- v3f ppos = m_player->getPosition() / BS;
- vertex.Pos.rotateXZBy(
- std::atan2(ppos.Z - m_pos.Z, ppos.X - m_pos.X) /
- core::DEGTORAD +
- 90);
+ v3f ppos = m_player->getPosition()/BS;
+ vertex.Pos.rotateXZBy(std::atan2(ppos.Z - m_pos.Z, ppos.X - m_pos.X) /
+ core::DEGTORAD + 90);
} else {
vertex.Pos.rotateYZBy(m_player->getPitch());
vertex.Pos.rotateXZBy(m_player->getYaw());
}
m_box.addInternalPoint(vertex.Pos);
- vertex.Pos += m_pos * BS - intToFloat(camera_offset, BS);
+ vertex.Pos += m_pos*BS - intToFloat(camera_offset, BS);
}
}
@@ -235,11 +246,15 @@ void Particle::updateVertices()
ParticleSpawner
*/
-ParticleSpawner::ParticleSpawner(IGameDef *gamedef, LocalPlayer *player,
- const ParticleSpawnerParameters &p, u16 attached_id,
- video::ITexture *texture, ParticleManager *p_manager) :
- m_particlemanager(p_manager),
- p(p)
+ParticleSpawner::ParticleSpawner(
+ IGameDef *gamedef,
+ LocalPlayer *player,
+ const ParticleSpawnerParameters &p,
+ u16 attached_id,
+ video::ITexture *texture,
+ ParticleManager *p_manager
+):
+ m_particlemanager(p_manager), p(p)
{
m_gamedef = gamedef;
m_player = player;
@@ -255,7 +270,7 @@ ParticleSpawner::ParticleSpawner(IGameDef *gamedef, LocalPlayer *player,
}
void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
- const core::matrix4 *attached_absolute_pos_rot_matrix)
+ const core::matrix4 *attached_absolute_pos_rot_matrix)
{
v3f ppos = m_player->getPosition() / BS;
v3f pos = random_v3f(p.minpos, p.maxpos);
@@ -297,10 +312,9 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
if (p.node.getContent() != CONTENT_IGNORE) {
const ContentFeatures &f =
- m_particlemanager->m_env->getGameDef()->ndef()->get(
- p.node);
+ m_particlemanager->m_env->getGameDef()->ndef()->get(p.node);
if (!ParticleManager::getNodeParticleParams(p.node, f, pp, &texture,
- texpos, texsize, &color, p.node_tile))
+ texpos, texsize, &color, p.node_tile))
return;
} else {
texture = m_texture;
@@ -313,7 +327,15 @@ void ParticleSpawner::spawnParticle(ClientEnvironment *env, float radius,
pp.size = random_f32(p.minsize, p.maxsize);
m_particlemanager->addParticle(new Particle(
- m_gamedef, m_player, env, pp, texture, texpos, texsize, color));
+ m_gamedef,
+ m_player,
+ env,
+ pp,
+ texture,
+ texpos,
+ texsize,
+ color
+ ));
}
void ParticleSpawner::step(float dtime, ClientEnvironment *env)
@@ -326,10 +348,8 @@ void ParticleSpawner::step(float dtime, ClientEnvironment *env)
bool unloaded = false;
const core::matrix4 *attached_absolute_pos_rot_matrix = nullptr;
if (m_attached_id) {
- if (GenericCAO *attached = dynamic_cast<GenericCAO *>(
- env->getActiveObject(m_attached_id))) {
- attached_absolute_pos_rot_matrix =
- attached->getAbsolutePosRotMatrix();
+ if (GenericCAO *attached = dynamic_cast<GenericCAO *>(env->getActiveObject(m_attached_id))) {
+ attached_absolute_pos_rot_matrix = attached->getAbsolutePosRotMatrix();
} else {
unloaded = true;
}
@@ -337,16 +357,14 @@ void ParticleSpawner::step(float dtime, ClientEnvironment *env)
if (p.time != 0) {
// Spawner exists for a predefined timespan
- for (auto i = m_spawntimes.begin(); i != m_spawntimes.end();) {
+ for (auto i = m_spawntimes.begin(); i != m_spawntimes.end(); ) {
if ((*i) <= m_time && p.amount > 0) {
--p.amount;
- // Pretend to, but don't actually spawn a particle if it
- // is attached to an unloaded object or distant from
- // player.
+ // Pretend to, but don't actually spawn a particle if it is
+ // attached to an unloaded object or distant from player.
if (!unloaded)
- spawnParticle(env, radius,
- attached_absolute_pos_rot_matrix);
+ spawnParticle(env, radius, attached_absolute_pos_rot_matrix);
i = m_spawntimes.erase(i);
} else {
@@ -362,8 +380,7 @@ void ParticleSpawner::step(float dtime, ClientEnvironment *env)
for (int i = 0; i <= p.amount; i++) {
if (rand() / (float)RAND_MAX < dtime)
- spawnParticle(env, radius,
- attached_absolute_pos_rot_matrix);
+ spawnParticle(env, radius, attached_absolute_pos_rot_matrix);
}
}
}
@@ -372,9 +389,9 @@ void ParticleSpawner::step(float dtime, ClientEnvironment *env)
ParticleManager
*/
-ParticleManager::ParticleManager(ClientEnvironment *env) : m_env(env)
-{
-}
+ParticleManager::ParticleManager(ClientEnvironment *env) :
+ m_env(env)
+{}
ParticleManager::~ParticleManager()
{
@@ -383,8 +400,8 @@ ParticleManager::~ParticleManager()
void ParticleManager::step(float dtime)
{
- stepParticles(dtime);
- stepSpawners(dtime);
+ stepParticles (dtime);
+ stepSpawners (dtime);
}
void ParticleManager::stepSpawners(float dtime)
@@ -425,80 +442,83 @@ void ParticleManager::clearAll()
m_particle_spawners.erase(i++);
}
- for (auto i = m_particles.begin(); i != m_particles.end();) {
+ for(auto i = m_particles.begin(); i != m_particles.end();)
+ {
(*i)->remove();
delete *i;
i = m_particles.erase(i);
}
}
-void ParticleManager::handleParticleEvent(
- ClientEvent *event, Client *client, LocalPlayer *player)
+void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client,
+ LocalPlayer *player)
{
switch (event->type) {
- case CE_DELETE_PARTICLESPAWNER: {
- deleteParticleSpawner(event->delete_particlespawner.id);
- // no allocated memory in delete event
- break;
- }
- case CE_ADD_PARTICLESPAWNER: {
- deleteParticleSpawner(event->add_particlespawner.id);
+ case CE_DELETE_PARTICLESPAWNER: {
+ deleteParticleSpawner(event->delete_particlespawner.id);
+ // no allocated memory in delete event
+ break;
+ }
+ case CE_ADD_PARTICLESPAWNER: {
+ deleteParticleSpawner(event->add_particlespawner.id);
- const ParticleSpawnerParameters &p = *event->add_particlespawner.p;
+ const ParticleSpawnerParameters &p = *event->add_particlespawner.p;
- video::ITexture *texture = client->tsrc()->getTextureForMesh(p.texture);
+ video::ITexture *texture =
+ client->tsrc()->getTextureForMesh(p.texture);
- auto toadd = new ParticleSpawner(client, player, p,
- event->add_particlespawner.attached_id, texture, this);
+ auto toadd = new ParticleSpawner(client, player,
+ p,
+ event->add_particlespawner.attached_id,
+ texture,
+ this);
- addParticleSpawner(event->add_particlespawner.id, toadd);
+ addParticleSpawner(event->add_particlespawner.id, toadd);
- delete event->add_particlespawner.p;
- break;
- }
- case CE_SPAWN_PARTICLE: {
- ParticleParameters &p = *event->spawn_particle;
+ delete event->add_particlespawner.p;
+ break;
+ }
+ case CE_SPAWN_PARTICLE: {
+ ParticleParameters &p = *event->spawn_particle;
- video::ITexture *texture;
- v2f texpos, texsize;
- video::SColor color(0xFFFFFFFF);
+ video::ITexture *texture;
+ v2f texpos, texsize;
+ video::SColor color(0xFFFFFFFF);
- f32 oldsize = p.size;
+ f32 oldsize = p.size;
- if (p.node.getContent() != CONTENT_IGNORE) {
- const ContentFeatures &f =
- m_env->getGameDef()->ndef()->get(p.node);
- if (!getNodeParticleParams(p.node, f, p, &texture, texpos,
- texsize, &color, p.node_tile))
- texture = nullptr;
- } else {
- texture = client->tsrc()->getTextureForMesh(p.texture);
- texpos = v2f(0.0f, 0.0f);
- texsize = v2f(1.0f, 1.0f);
- }
+ if (p.node.getContent() != CONTENT_IGNORE) {
+ const ContentFeatures &f = m_env->getGameDef()->ndef()->get(p.node);
+ if (!getNodeParticleParams(p.node, f, p, &texture, texpos,
+ texsize, &color, p.node_tile))
+ texture = nullptr;
+ } else {
+ texture = client->tsrc()->getTextureForMesh(p.texture);
+ texpos = v2f(0.0f, 0.0f);
+ texsize = v2f(1.0f, 1.0f);
+ }
- // Allow keeping default random size
- if (oldsize > 0.0f)
- p.size = oldsize;
+ // Allow keeping default random size
+ if (oldsize > 0.0f)
+ p.size = oldsize;
- if (texture) {
- Particle *toadd = new Particle(client, player, m_env, p, texture,
- texpos, texsize, color);
+ if (texture) {
+ Particle *toadd = new Particle(client, player, m_env,
+ p, texture, texpos, texsize, color);
- addParticle(toadd);
- }
+ addParticle(toadd);
+ }
- delete event->spawn_particle;
- break;
- }
- default:
- break;
+ delete event->spawn_particle;
+ break;
+ }
+ default: break;
}
}
-bool ParticleManager::getNodeParticleParams(const MapNode &n, const ContentFeatures &f,
- ParticleParameters &p, video::ITexture **texture, v2f &texpos,
- v2f &texsize, video::SColor *color, u8 tilenum)
+bool ParticleManager::getNodeParticleParams(const MapNode &n,
+ const ContentFeatures &f, ParticleParameters &p, video::ITexture **texture,
+ v2f &texpos, v2f &texsize, video::SColor *color, u8 tilenum)
{
// No particles for "airlike" nodes
if (f.drawtype == NDT_AIRLIKE)
@@ -538,8 +558,8 @@ bool ParticleManager::getNodeParticleParams(const MapNode &n, const ContentFeatu
// The final burst of particles when a node is finally dug, *not* particles
// spawned during the digging of a node.
-void ParticleManager::addDiggingParticles(IGameDef *gamedef, LocalPlayer *player,
- v3s16 pos, const MapNode &n, const ContentFeatures &f)
+void ParticleManager::addDiggingParticles(IGameDef *gamedef,
+ LocalPlayer *player, v3s16 pos, const MapNode &n, const ContentFeatures &f)
{
// No particles for "airlike" nodes
if (f.drawtype == NDT_AIRLIKE)
@@ -553,8 +573,8 @@ void ParticleManager::addDiggingParticles(IGameDef *gamedef, LocalPlayer *player
// During the digging of a node particles are spawned individually by this
// function, called from Game::handleDigging() in game.cpp.
-void ParticleManager::addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
- const MapNode &n, const ContentFeatures &f)
+void ParticleManager::addNodeParticle(IGameDef *gamedef,
+ LocalPlayer *player, v3s16 pos, const MapNode &n, const ContentFeatures &f)
{
ParticleParameters p;
video::ITexture *texture;
@@ -567,17 +587,31 @@ void ParticleManager::addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3
p.expirationtime = (rand() % 100) / 100.0f;
// Physics
- p.vel = v3f((rand() % 150) / 50.0f - 1.5f, (rand() % 150) / 50.0f,
- (rand() % 150) / 50.0f - 1.5f);
- p.acc = v3f(0.0f,
- -player->movement_gravity * player->physics_override_gravity / BS,
- 0.0f);
- p.pos = v3f((f32)pos.X + (rand() % 100) / 200.0f - 0.25f,
- (f32)pos.Y + (rand() % 100) / 200.0f - 0.25f,
- (f32)pos.Z + (rand() % 100) / 200.0f - 0.25f);
+ p.vel = v3f(
+ (rand() % 150) / 50.0f - 1.5f,
+ (rand() % 150) / 50.0f,
+ (rand() % 150) / 50.0f - 1.5f
+ );
+ p.acc = v3f(
+ 0.0f,
+ -player->movement_gravity * player->physics_override_gravity / BS,
+ 0.0f
+ );
+ p.pos = v3f(
+ (f32)pos.X + (rand() % 100) / 200.0f - 0.25f,
+ (f32)pos.Y + (rand() % 100) / 200.0f - 0.25f,
+ (f32)pos.Z + (rand() % 100) / 200.0f - 0.25f
+ );
Particle *toadd = new Particle(
- gamedef, player, m_env, p, texture, texpos, texsize, color);
+ gamedef,
+ player,
+ m_env,
+ p,
+ texture,
+ texpos,
+ texsize,
+ color);
addParticle(toadd);
}
@@ -588,6 +622,7 @@ void ParticleManager::addParticle(Particle *toadd)
m_particles.push_back(toadd);
}
+
void ParticleManager::addParticleSpawner(u64 id, ParticleSpawner *toadd)
{
MutexAutoLock lock(m_spawner_list_lock);