aboutsummaryrefslogtreecommitdiff
path: root/src/client/particles.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/particles.h')
-rw-r--r--src/client/particles.h242
1 files changed, 242 insertions, 0 deletions
diff --git a/src/client/particles.h b/src/client/particles.h
new file mode 100644
index 000000000..0818b796b
--- /dev/null
+++ b/src/client/particles.h
@@ -0,0 +1,242 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#pragma once
+
+#include <iostream>
+#include "irrlichttypes_extrabloated.h"
+#include "client/tile.h"
+#include "localplayer.h"
+#include "../particles.h"
+
+struct ClientEvent;
+class ParticleManager;
+class ClientEnvironment;
+struct MapNode;
+struct ContentFeatures;
+
+struct ClientTexture
+{
+ /* per-spawner structure used to store the ParticleTexture structs
+ * that spawned particles will refer to through ClientTexRef */
+ ParticleTexture tex;
+ video::ITexture *ref = nullptr;
+
+ ClientTexture() = default;
+ ClientTexture(const ServerParticleTexture& p, ITextureSource *t):
+ tex(p),
+ ref(t->getTextureForMesh(p.string)) {};
+};
+
+struct ClientTexRef
+{
+ /* per-particle structure used to avoid massively duplicating the
+ * fairly large ParticleTexture struct */
+ ParticleTexture* tex = nullptr;
+ video::ITexture* ref = nullptr;
+ ClientTexRef() = default;
+
+ /* constructor used by particles spawned from a spawner */
+ ClientTexRef(ClientTexture& t):
+ tex(&t.tex), ref(t.ref) {};
+
+ /* constructor used for node particles */
+ ClientTexRef(decltype(ref) tp): ref(tp) {};
+};
+
+class ParticleSpawner;
+
+class Particle : public scene::ISceneNode
+{
+public:
+ Particle(
+ IGameDef *gamedef,
+ LocalPlayer *player,
+ ClientEnvironment *env,
+ const ParticleParameters &p,
+ const ClientTexRef &texture,
+ v2f texpos,
+ v2f texsize,
+ video::SColor color
+ );
+ ~Particle();
+
+ virtual const aabb3f &getBoundingBox() const
+ {
+ return m_box;
+ }
+
+ virtual u32 getMaterialCount() const
+ {
+ return 1;
+ }
+
+ virtual video::SMaterial& getMaterial(u32 i)
+ {
+ return m_material;
+ }
+
+ virtual void OnRegisterSceneNode();
+ virtual void render();
+
+ void step(float dtime);
+
+ bool get_expired ()
+ { return m_expiration < m_time; }
+
+ ParticleSpawner *m_parent;
+
+private:
+ void updateLight();
+ void updateVertices();
+ void setVertexAlpha(float a);
+
+ video::S3DVertex m_vertices[4];
+ float m_time = 0.0f;
+ float m_expiration;
+
+ ClientEnvironment *m_env;
+ IGameDef *m_gamedef;
+ aabb3f m_box;
+ aabb3f m_collisionbox;
+ ClientTexRef m_texture;
+ video::SMaterial m_material;
+ v2f m_texpos;
+ v2f m_texsize;
+ v3f m_pos;
+ v3f m_velocity;
+ v3f m_acceleration;
+ v3f m_drag;
+ ParticleParamTypes::v3fRange m_jitter;
+ ParticleParamTypes::f32Range m_bounce;
+ LocalPlayer *m_player;
+ float m_size;
+
+ //! Color without lighting
+ video::SColor m_base_color;
+ //! Final rendered color
+ video::SColor m_color;
+ bool m_collisiondetection;
+ bool m_collision_removal;
+ bool m_object_collision;
+ bool m_vertical;
+ v3s16 m_camera_offset;
+ struct TileAnimationParams m_animation;
+ float m_animation_time = 0.0f;
+ int m_animation_frame = 0;
+ u8 m_glow;
+ float m_alpha = 0.0f;
+};
+
+class ParticleSpawner
+{
+public:
+ ParticleSpawner(IGameDef *gamedef,
+ LocalPlayer *player,
+ const ParticleSpawnerParameters &p,
+ u16 attached_id,
+ std::unique_ptr<ClientTexture[]> &texpool,
+ size_t texcount,
+ ParticleManager* p_manager);
+
+ void step(float dtime, ClientEnvironment *env);
+
+ size_t m_active;
+
+ bool getExpired() const
+ { return m_dying || (p.amount <= 0 && p.time != 0); }
+ void setDying() { m_dying = true; }
+
+private:
+ void spawnParticle(ClientEnvironment *env, float radius,
+ const core::matrix4 *attached_absolute_pos_rot_matrix);
+
+ ParticleManager *m_particlemanager;
+ float m_time;
+ bool m_dying;
+ IGameDef *m_gamedef;
+ LocalPlayer *m_player;
+ ParticleSpawnerParameters p;
+ std::unique_ptr<ClientTexture[]> m_texpool;
+ size_t m_texcount;
+ std::vector<float> m_spawntimes;
+ u16 m_attached_id;
+};
+
+/**
+ * Class doing particle as well as their spawners handling
+ */
+class ParticleManager
+{
+friend class ParticleSpawner;
+public:
+ ParticleManager(ClientEnvironment* env);
+ ~ParticleManager();
+
+ void step (float dtime);
+
+ void handleParticleEvent(ClientEvent *event, Client *client,
+ LocalPlayer *player);
+
+ void addDiggingParticles(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
+ const MapNode &n, const ContentFeatures &f);
+
+ void addNodeParticle(IGameDef *gamedef, LocalPlayer *player, v3s16 pos,
+ const MapNode &n, const ContentFeatures &f);
+
+ void reserveParticleSpace(size_t max_estimate);
+
+ /**
+ * This function is only used by client particle spawners
+ *
+ * We don't need to check the particle spawner list because client ID will
+ * never overlap (u64)
+ * @return new id
+ */
+ u64 generateSpawnerId()
+ {
+ return m_next_particle_spawner_id++;
+ }
+
+protected:
+ static bool getNodeParticleParams(const MapNode &n, const ContentFeatures &f,
+ ParticleParameters &p, video::ITexture **texture, v2f &texpos,
+ v2f &texsize, video::SColor *color, u8 tilenum = 0);
+
+ void addParticle(Particle* toadd);
+
+private:
+ void addParticleSpawner(u64 id, ParticleSpawner *toadd);
+ void deleteParticleSpawner(u64 id);
+
+ void stepParticles(float dtime);
+ void stepSpawners(float dtime);
+
+ void clearAll();
+
+ std::vector<Particle*> m_particles;
+ std::unordered_map<u64, ParticleSpawner*> m_particle_spawners;
+ // Start the particle spawner ids generated from here after u32_max. lower values are
+ // for server sent spawners.
+ u64 m_next_particle_spawner_id = U32_MAX + 1;
+
+ ClientEnvironment* m_env;
+ std::mutex m_particle_list_lock;
+ std::mutex m_spawner_list_lock;
+};