Add particles
authorJeija <norrepli@gmail.com>
Mon, 31 Dec 2012 18:33:36 +0000 (19:33 +0100)
committerPilzAdam <PilzAdam@gmx.de>
Mon, 14 Jan 2013 14:27:00 +0000 (15:27 +0100)
src/CMakeLists.txt
src/client.h
src/defaultsettings.cpp
src/game.cpp
src/guiMainMenu.cpp
src/guiMainMenu.h
src/main.cpp
src/particles.cpp [new file with mode: 0644]
src/particles.h [new file with mode: 0644]

index 5e1bfd65d684c624bb1a6d472fea8f86614451de..24f682f3f5dc5c97289f41eaa4d559cc751d5749 100644 (file)
@@ -262,6 +262,7 @@ set(minetest_SRCS
        keycode.cpp
        camera.cpp
        clouds.cpp
+       particles.cpp
        clientobject.cpp
        chat.cpp
        guiMainMenu.cpp
index 7052e840ada92c0c6fd71a1a3823de4ab02dc878..43fac9c9ad39d7ccca95bd8626999adc647f45ea 100644 (file)
@@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "filecache.h"
 #include "localplayer.h"
 #include "server.h"
+#include "particles.h"
 #include "util/pointedthing.h"
 
 struct MeshMakeData;
index 9ada214ae96b44d493c7c35e88a0b5c1ae58860e..ca5f33609ce4b0803a886dcaca2ce7a16247c0f4 100644 (file)
@@ -124,6 +124,7 @@ void set_default_settings(Settings *settings)
        settings->setDefault("preload_item_visuals", "true");
        settings->setDefault("enable_shaders", "2");
        settings->setDefault("repeat_rightclick_time", "0.25");
+       settings->setDefault("enable_particles", "true");
 
        settings->setDefault("media_fetch_threads", "8");
 
index bed99837d936d9296d06aa078dd261760fdabaed..488d18f7a7221d3b4d395d436af62b0ff3879b58 100644 (file)
@@ -36,6 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "guiChatConsole.h"
 #include "config.h"
 #include "clouds.h"
+#include "particles.h"
 #include "camera.h"
 #include "farmesh.h"
 #include "mapblock.h"
@@ -2399,6 +2400,13 @@ void the_game(
                                else
                                {
                                        dig_time_complete = params.time;
+                                       if (g_settings->getBool("enable_particles"))
+                                       {
+                                               const ContentFeatures &features =
+                                                       client.getNodeDefManager()->get(n);
+                                               addPunchingParticles
+                                                       (gamedef, smgr, player, nodepos, features.tiles);
+                                       }
                                }
 
                                if(dig_time_complete >= 0.001)
@@ -2430,6 +2438,14 @@ void the_game(
                                        MapNode wasnode = map.getNode(nodepos);
                                        client.removeNode(nodepos);
 
+                                       if (g_settings->getBool("enable_particles"))
+                                       {
+                                               const ContentFeatures &features =
+                                                       client.getNodeDefManager()->get(wasnode);
+                                               addDiggingParticles
+                                                       (gamedef, smgr, player, nodepos, features.tiles);
+                                       }
+
                                        dig_time = 0;
                                        digging = false;
 
@@ -2698,6 +2714,12 @@ void the_game(
                        farmesh->update(v2f(player_position.X, player_position.Z),
                                        brightness, farmesh_range);
                }
+
+               /*
+                       Update particles
+               */
+
+               allparticles_step(dtime, client.getEnv());
                
                /*
                        Fog
index d7c3f54ff957c7eb75e5da5330f1f3a9193ab352..bac9052b946ad484f948fd111a26726444d482bf 100644 (file)
@@ -104,6 +104,7 @@ enum
        GUI_ID_TRILINEAR_CB,
        GUI_ID_SHADERS_CB,
        GUI_ID_PRELOAD_ITEM_VISUALS_CB,
+       GUI_ID_ENABLE_PARTICLES_CB,
        GUI_ID_DAMAGE_CB,
        GUI_ID_CREATIVE_CB,
        GUI_ID_JOIN_GAME_BUTTON,
@@ -618,7 +619,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
                                       GUI_ID_TRILINEAR_CB, wgettext("Tri-Linear Filtering"));
                }
 
-               // shader/on demand image loading settings
+               // shader/on demand image loading/particles settings
                {
                        core::rect<s32> rect(0, 0, option_w+20, 30);
                        rect += m_topleft_client + v2s32(option_x+175*2, option_y);
@@ -633,6 +634,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
                                        GUI_ID_PRELOAD_ITEM_VISUALS_CB, wgettext("Preload item visuals"));
                }
 
+               {
+                       core::rect<s32> rect(0, 0, option_w+20+20, 30);
+                       rect += m_topleft_client + v2s32(option_x+175*2, option_y+20*2);
+                       Environment->addCheckBox(m_data->enable_particles, rect, this,
+                                       GUI_ID_ENABLE_PARTICLES_CB, wgettext("Enable Particles"));
+               }
+
                // Key change button
                {
                        core::rect<s32> rect(0, 0, 120, 30);
@@ -849,6 +857,12 @@ void GUIMainMenu::readInput(MainMenuData *dst)
                        dst->preload_item_visuals = ((gui::IGUICheckBox*)e)->isChecked();
        }
 
+       {
+               gui::IGUIElement *e = getElementFromId(GUI_ID_ENABLE_PARTICLES_CB);
+               if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
+                       dst->enable_particles = ((gui::IGUICheckBox*)e)->isChecked();
+       }
+
        {
                gui::IGUIElement *e = getElementFromId(GUI_ID_WORLD_LISTBOX);
                if(e != NULL && e->getType() == gui::EGUIET_LIST_BOX)
index 604202461dad6f02c0bca168cc67f077d052cdb3..f87ad0fdb9714f56d3b7b3dcc48107edd63d2fd6 100644 (file)
@@ -47,6 +47,7 @@ struct MainMenuData
        bool trilinear_filter;
        int enable_shaders;
        bool preload_item_visuals;
+       bool enable_particles;
        // Server options
        bool creative_mode;
        bool enable_damage;
index ede9f63b06477308d091263809190ade2e934259..0af9d113c6241041b5725d62d9edd93beb511e9c 100644 (file)
@@ -1448,6 +1448,7 @@ int main(int argc, char *argv[])
                                menudata.trilinear_filter = g_settings->getBool("trilinear_filter");
                                menudata.enable_shaders = g_settings->getS32("enable_shaders");
                                menudata.preload_item_visuals = g_settings->getBool("preload_item_visuals");
+                               menudata.enable_particles = g_settings->getBool("enable_particles");
                                driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, menudata.mip_map);
                                menudata.creative_mode = g_settings->getBool("creative_mode");
                                menudata.enable_damage = g_settings->getBool("enable_damage");
@@ -1570,6 +1571,7 @@ int main(int argc, char *argv[])
 
                                g_settings->setS32("enable_shaders", menudata.enable_shaders);
                                g_settings->set("preload_item_visuals", itos(menudata.preload_item_visuals));
+                               g_settings->set("enable_particles", itos(menudata.enable_particles));
 
                                g_settings->set("creative_mode", itos(menudata.creative_mode));
                                g_settings->set("enable_damage", itos(menudata.enable_damage));
diff --git a/src/particles.cpp b/src/particles.cpp
new file mode 100644 (file)
index 0000000..d49e333
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+Minetest-c55
+Copyright (C) 2012 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.
+*/
+
+#include "particles.h"
+#include "constants.h"
+#include "debug.h"
+#include "main.h" // For g_profiler and g_settings
+#include "settings.h"
+#include "tile.h"
+#include "gamedef.h"
+#include "collision.h"
+#include <stdlib.h>
+#include "util/numeric.h"
+#include "light.h"
+#include "environment.h"
+#include "clientmap.h"
+#include "mapnode.h"
+
+Particle::Particle(
+       IGameDef *gamedef,
+       scene::ISceneManager* smgr,
+       LocalPlayer *player,
+       s32 id,
+       v3f pos,
+       v3f velocity,
+       v3f acceleration,
+       float expirationtime,
+       float size,
+       AtlasPointer ap
+):
+       scene::ISceneNode(smgr->getRootSceneNode(), smgr, id)
+{
+       // Misc
+       m_gamedef = gamedef;
+
+       // Texture
+       m_material.setFlag(video::EMF_LIGHTING, false);
+       m_material.setFlag(video::EMF_BACK_FACE_CULLING, false);
+       m_material.setFlag(video::EMF_BILINEAR_FILTER, false);
+       m_material.setFlag(video::EMF_FOG_ENABLE, true);
+       m_material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
+       m_material.setTexture(0, ap.atlas);
+       m_ap = ap;
+       m_light = 0;
+
+
+       // Particle related
+       m_pos = pos;
+       m_velocity = velocity;
+       m_acceleration = acceleration;
+       m_expiration = expirationtime;
+       m_time = 0;
+       m_player = player;
+       m_size = size;
+
+       // Irrlicht stuff (TODO)
+       m_collisionbox = core::aabbox3d<f32>(-size/2,-size/2,-size/2,size/2,size/2,size/2);
+       this->setAutomaticCulling(scene::EAC_OFF);
+}
+
+Particle::~Particle()
+{
+}
+
+void Particle::OnRegisterSceneNode()
+{
+       if (IsVisible)
+       {
+               SceneManager->registerNodeForRendering(this, scene::ESNRP_TRANSPARENT);
+               SceneManager->registerNodeForRendering(this, scene::ESNRP_SOLID);
+       }
+
+       ISceneNode::OnRegisterSceneNode();
+}
+
+void Particle::render()
+{
+       // TODO: Render particles in front of water and the selectionbox
+
+       video::IVideoDriver* driver = SceneManager->getVideoDriver();
+       driver->setMaterial(m_material);
+       driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
+       video::SColor c(255, m_light, m_light, m_light);
+
+       video::S3DVertex vertices[4] =
+       {
+               video::S3DVertex(-m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x0(), m_ap.y1()),
+               video::S3DVertex(m_size/2,-m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y1()),
+               video::S3DVertex(m_size/2,m_size/2,0, 0,0,0, c, m_ap.x1(), m_ap.y0()),
+               video::S3DVertex(-m_size/2,m_size/2,0, 0,0,0, c ,m_ap.x0(), m_ap.y0()),
+       };
+
+       for(u16 i=0; i<4; i++)
+       {
+               vertices[i].Pos.rotateYZBy(m_player->getPitch());
+               vertices[i].Pos.rotateXZBy(m_player->getYaw());
+               m_box.addInternalPoint(vertices[i].Pos);
+               vertices[i].Pos += m_pos*BS;
+       }
+
+       u16 indices[] = {0,1,2, 2,3,0};
+       driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
+                       video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
+}
+
+void Particle::step(float dtime, ClientEnvironment &env)
+{
+       core::aabbox3d<f32> box = m_collisionbox;
+       v3f p_pos = m_pos*BS;
+       v3f p_velocity = m_velocity*BS;
+       v3f p_acceleration = m_acceleration*BS;
+       collisionMoveSimple(&env.getClientMap(), m_gamedef,
+               BS*0.5, box,
+               0, dtime,
+               p_pos, p_velocity, p_acceleration);
+       m_pos = p_pos/BS;
+       m_velocity = p_velocity/BS;
+       m_acceleration = p_acceleration/BS;
+       m_time += dtime;
+
+       // Update lighting
+       u8 light = 0;
+       try{
+               v3s16 p = v3s16(
+                       floor(m_pos.X+0.5),
+                       floor(m_pos.Y+0.5),
+                       floor(m_pos.Z+0.5)
+               );
+               MapNode n = env.getClientMap().getNode(p);
+               light = n.getLightBlend(env.getDayNightRatio(), m_gamedef->ndef());
+       }
+       catch(InvalidPositionException &e){
+               light = blend_light(env.getDayNightRatio(), LIGHT_SUN, 0);
+       }
+       m_light = decode_light(light);
+}
+
+std::vector<Particle*> all_particles;
+
+void allparticles_step (float dtime, ClientEnvironment &env)
+{
+       for(std::vector<Particle*>::iterator i = all_particles.begin(); i != all_particles.end();)
+       {
+               if ((*i)->get_expired())
+               {
+                       (*i)->remove();
+                       delete *i;
+                       all_particles.erase(i);
+               }
+               else
+               {
+                       (*i)->step(dtime, env);
+                       i++;
+               }
+       }
+}
+
+void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
+{
+       for (u16 j = 0; j < 32; j++) // set the amount of particles here
+       {
+               addNodeParticle(gamedef, smgr, player, pos, tiles);
+       }
+}
+
+void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
+{
+       addNodeParticle(gamedef, smgr, player, pos, tiles);
+}
+
+// add a particle of a node
+// used by digging and punching particles
+void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[])
+{
+       // Texture
+       u8 texid = myrand_range(0,5);
+       AtlasPointer ap = tiles[texid].texture;
+       float size = rand()%64/512.;
+       float visual_size = BS*size;
+       float texsize = size*2;
+
+       float x1 = ap.x1();
+       float y1 = ap.y1();
+
+       ap.size.X = (ap.x1() - ap.x0()) * texsize;
+       ap.size.Y = (ap.x1() - ap.x0()) * texsize;
+
+       ap.pos.X = ap.x0() + (x1 - ap.x0()) * ((rand()%64)/64.-texsize);
+       ap.pos.Y = ap.y0() + (y1 - ap.y0()) * ((rand()%64)/64.-texsize);
+
+       // Physics
+       v3f velocity((rand()%100/50.-1)/1.5, rand()%100/35., (rand()%100/50.-1)/1.5);
+       v3f acceleration(0,-9,0);
+       v3f particlepos = v3f(
+               (f32)pos.X+rand()%100/200.-0.25,
+               (f32)pos.Y+rand()%100/200.-0.25,
+               (f32)pos.Z+rand()%100/200.-0.25
+       );
+
+       Particle *particle = new Particle(
+               gamedef,
+               smgr,
+               player,
+               0,
+               particlepos,
+               velocity,
+               acceleration,
+               rand()%100/100., // expiration time
+               visual_size,
+               ap);
+
+       all_particles.push_back(particle);
+}
diff --git a/src/particles.h b/src/particles.h
new file mode 100644 (file)
index 0000000..3ed9dfd
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+Minetest-c55
+Copyright (C) 2012 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.
+*/
+
+#ifndef PARTICLES_HEADER
+#define PARTICLES_HEADER
+
+#define DIGGING_PARTICLES_AMOUNT 10
+
+#include <iostream>
+#include "irrlichttypes_extrabloated.h"
+#include "tile.h"
+#include "localplayer.h"
+#include "environment.h"
+
+class Particle : public scene::ISceneNode
+{
+       public:
+       Particle(
+               IGameDef* gamedef,
+               scene::ISceneManager* mgr,
+               LocalPlayer *player,
+               s32 id,
+               v3f pos,
+               v3f velocity,
+               v3f acceleration,
+               float expirationtime,
+               float size,
+               AtlasPointer texture
+       );
+       ~Particle();
+
+       virtual const core::aabbox3d<f32>& 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, ClientEnvironment &env);
+
+       bool get_expired ()
+       { return m_expiration < m_time; }
+
+private:
+       float m_time;
+       float m_expiration;
+
+       IGameDef *m_gamedef;
+       core::aabbox3d<f32> m_box;
+       core::aabbox3d<f32> m_collisionbox;
+       video::SMaterial m_material;
+       v3f m_pos;
+       v3f m_velocity;
+       v3f m_acceleration;
+       float tex_x0;
+       float tex_x1;
+       float tex_y0;
+       float tex_y1;
+       LocalPlayer *m_player;
+       float m_size;
+       AtlasPointer m_ap;
+       u8 m_light;
+};
+
+void allparticles_step (float dtime, ClientEnvironment &env);
+
+void addDiggingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
+void addPunchingParticles(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
+void addNodeParticle(IGameDef* gamedef, scene::ISceneManager* smgr, LocalPlayer *player, v3s16 pos, const TileSpec tiles[]);
+
+#endif