X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fparticles.cpp;h=0a6651ce453624a68c1a02b034cfe735480f3bca;hb=8a99c8c94a40640c7c337278277f5c027e96f3cb;hp=5f17763e013373cf2ef4423facbb1122635496fe;hpb=7279f0b37335396c85f6bdd7dc67ff56e53df0f9;p=dragonfireclient.git diff --git a/src/particles.cpp b/src/particles.cpp index 5f17763e0..0a6651ce4 100644 --- a/src/particles.cpp +++ b/src/particles.cpp @@ -20,13 +20,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "particles.h" #include "client.h" #include "collision.h" -#include +#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" /* Utility @@ -41,7 +44,6 @@ v3f random_v3f(v3f min, v3f max) Particle::Particle( IGameDef *gamedef, - scene::ISceneManager* smgr, LocalPlayer *player, ClientEnvironment *env, v3f pos, @@ -56,9 +58,11 @@ Particle::Particle( v2f texpos, v2f texsize, const struct TileAnimationParams &anim, - u8 glow + 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; @@ -74,15 +78,16 @@ Particle::Particle( m_texpos = texpos; m_texsize = texsize; m_animation = anim; - m_animation_frame = 0; - m_animation_time = 0.0; + + // Color + m_base_color = color; + m_color = color; // Particle related m_pos = pos; m_velocity = velocity; m_acceleration = acceleration; m_expiration = expirationtime; - m_time = 0; m_player = player; m_size = size; m_collisiondetection = collisiondetection; @@ -102,10 +107,6 @@ Particle::Particle( updateVertices(); } -Particle::~Particle() -{ -} - void Particle::OnRegisterSceneNode() { if (IsVisible) @@ -183,12 +184,15 @@ void Particle::updateLight() else light = blend_light(m_env->getDayNightRatio(), LIGHT_SUN, 0); - m_light = decode_light(light + m_glow); + 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); } void Particle::updateVertices() { - video::SColor c(255, m_light, m_light, m_light); f32 tx0, tx1, ty0, ty1; if (m_animation.type != TAT_NONE) { @@ -210,27 +214,26 @@ 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, - c, tx0, ty1); - m_vertices[1] = video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0, - c, tx1, ty1); - m_vertices[2] = video::S3DVertex(m_size/2,m_size/2,0, 0,0,0, - c, tx1, ty0); - m_vertices[3] = video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0, - c, 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(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(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); } } @@ -238,7 +241,7 @@ void Particle::updateVertices() 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, @@ -249,7 +252,6 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, m_particlemanager(p_manager) { m_gamedef = gamedef; - m_smgr = smgr; m_player = player; m_amount = amount; m_spawntime = time; @@ -279,12 +281,65 @@ ParticleSpawner::ParticleSpawner(IGameDef* gamedef, scene::ISceneManager *smgr, } } -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) { m_time += dtime; + static thread_local const float radius = + g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE; + bool unloaded = false; bool is_attached = false; v3f attached_pos = v3f(0,0,0); @@ -299,114 +354,33 @@ void ParticleSpawner::step(float dtime, ClientEnvironment* env) } } - if (m_spawntime != 0) // Spawner exists for a predefined timespan - { - for(std::vector::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::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. - if (!unloaded) { - v3f pos = random_v3f(m_minpos, m_maxpos); - 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); - } + // 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, 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) - { - v3f pos = random_v3f(m_minpos, m_maxpos); - 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); } } } @@ -490,7 +464,7 @@ void ParticleManager::clearAll () } void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client, - scene::ISceneManager* smgr, LocalPlayer *player) + LocalPlayer *player) { switch (event->type) { case CE_DELETE_PARTICLESPAWNER: { @@ -516,7 +490,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client, 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, @@ -561,7 +535,7 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client, 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, @@ -589,38 +563,43 @@ void ParticleManager::handleParticleEvent(ClientEvent *event, Client *client, } } -void ParticleManager::addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, - LocalPlayer *player, v3s16 pos, const TileSpec tiles[]) +void ParticleManager::addDiggingParticles(IGameDef* gamedef, + 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, tiles); + // No particles for "airlike" nodes + if (f.drawtype == NDT_AIRLIKE) + return; + + // set the amount of particles here + for (u16 j = 0; j < 32; j++) { + addNodeParticle(gamedef, player, pos, n, f); } } -void ParticleManager::addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, - LocalPlayer *player, v3s16 pos, const TileSpec tiles[]) +void ParticleManager::addNodeParticle(IGameDef* gamedef, + LocalPlayer *player, v3s16 pos, const MapNode &n, const ContentFeatures &f) { - addNodeParticle(gamedef, smgr, player, pos, tiles); -} + // No particles for "airlike" nodes + if (f.drawtype == NDT_AIRLIKE) + return; -void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, - LocalPlayer *player, v3s16 pos, const TileSpec tiles[]) -{ // Texture u8 texid = myrand_range(0, 5); + const TileLayer &tile = f.tiles[texid].layers[0]; video::ITexture *texture; struct TileAnimationParams anim; anim.type = TAT_NONE; // Only use first frame of animated texture - if (tiles[texid].material_flags & MATERIAL_FLAG_ANIMATION) - texture = tiles[texid].frames[0].texture; + if (tile.material_flags & MATERIAL_FLAG_ANIMATION) + texture = (*tile.frames)[0].texture; else - texture = tiles[texid].texture; + 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); @@ -638,9 +617,14 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s (f32) pos.Z + rand() %100 /200. - 0.25 ); + video::SColor color; + if (tile.has_color) + color = tile.color; + else + n.getColor(f, &color); + Particle* toadd = new Particle( gamedef, - smgr, player, m_env, particlepos, @@ -655,7 +639,8 @@ void ParticleManager::addNodeParticle(IGameDef* gamedef, scene::ISceneManager* s texpos, texsize, anim, - 0); + 0, + color); addParticle(toadd); }