1 /* 2 * This file is part of the Colobot: Gold Edition source code 3 * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam 4 * http://epsitec.ch; http://colobot.info; http://github.com/colobot 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 * See the GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see http://gnu.org/licenses 18 */ 19 20 /** 21 * \file graphics/engine/particle.h 22 * \brief Particle rendering - CParticle class (aka particle) 23 */ 24 25 #pragma once 26 27 28 #include "graphics/engine/engine.h" 29 30 #include "object/interface/trace_drawing_object.h" 31 32 #include "sound/sound_type.h" 33 34 35 class CRobotMain; 36 class CObject; 37 class CSoundInterface; 38 39 40 // Graphics module namespace 41 namespace Gfx 42 { 43 44 const short MAXPARTICULE = 500; 45 const short MAXPARTITYPE = 6; 46 const short MAXTRACK = 100; 47 const short MAXTRACKLEN = 10; 48 const short MAXPARTIFOG = 100; 49 const short MAXWHEELTRACE = 1000; 50 51 const short SH_WORLD = 0; // particle in the world in the interface 52 const short SH_FRONT = 1; // particle in the world on the interface 53 const short SH_INTERFACE = 2; // particle in the interface 54 const short SH_MAX = 3; 55 56 // type == 0 -> triangles 57 // type == 1 -> effect00 (black background) 58 // type == 2 -> effect01 (black background) 59 // type == 3 -> effect02 (black background) 60 // type == 4 -> text (white background) 61 62 63 enum ParticleType 64 { 65 PARTIEXPLOT = 1, //! < technology explosion 66 PARTIEXPLOO = 2, //! < organic explosion 67 PARTIMOTOR = 3, //! < the engine exhaust gas 68 PARTIGLINT = 4, //! < reflection 69 PARTIBLITZ = 5, //! < lightning recharging battery 70 PARTICRASH = 6, //! < dust after fall 71 PARTIGAS = 7, //! < gas from the reactor 72 PARTIFIRE = 9, //! < fireball shrinks 73 PARTIFIREZ = 10, //! < fireball grows 74 PARTIBLUE = 11, //! < blue ball 75 PARTISELY = 12, //! < yellow robot lights 76 PARTISELR = 13, //! < red robot lights 77 PARTIGUN1 = 18, //! < bullet 1 (fireball) 78 PARTIGUN2 = 19, //! < bullet 2 (ant) 79 PARTIGUN3 = 20, //! < bullet 3 (spider) 80 PARTIGUN4 = 21, //! < bullet 4 (orgaball) 81 PARTIFRAG = 22, //! < triangular fragment 82 PARTIQUEUE = 23, //! < inflamed tail (TODO: unused?) 83 PARTIORGANIC1 = 24, //! < organic ball mother 84 PARTIORGANIC2 = 25, //! < organic ball daughter 85 PARTISMOKE1 = 26, //! < black smoke 86 PARTISMOKE2 = 27, //! < black smoke 87 PARTISMOKE3 = 28, //! < black smoke 88 PARTIBLOOD = 30, //! < human blood 89 PARTIBLOODM = 31, //! < AlienQueen blood 90 PARTIVAPOR = 32, //! < steam 91 PARTIVIRUS = 33, //! < virus (random letter) 92 PARTIRAY1 = 43, //! < ray 1 (turn) 93 PARTIRAY2 = 44, //! < ray 2 (electric arc) 94 PARTIRAY3 = 45, //! < ray 3 (ExchangePost) 95 PARTIFLAME = 47, //! < flame 96 PARTIBUBBLE = 48, //! < bubble 97 PARTIFLIC = 49, //! < circles in the water 98 PARTIEJECT = 50, //! < ejection from the reactor 99 PARTISCRAPS = 51, //! < waste from the reactor 100 PARTITOTO = 52, //! < Robby's reactor 101 PARTIERROR = 53, //! < Robby says no 102 PARTIWARNING = 54, //! < Robby says blah 103 PARTIINFO = 54, //! < Robby says yes 104 PARTIQUARTZ = 55, //! < reflection crystal 105 PARTISPHERE0 = 56, //! < explosion sphere 106 PARTISPHERE1 = 57, //! < energy sphere 107 PARTISPHERE2 = 58, //! < analysis sphere 108 PARTISPHERE3 = 59, //! < shield sphere 109 PARTISPHERE4 = 60, //! < information sphere (emit) 110 PARTISPHERE5 = 61, //! < botanical sphere (gravity root) 111 PARTISPHERE6 = 62, //! < information sphere (receive) 112 PARTIGUNDEL = 66, //! < bullet destroyed by shield 113 PARTIPART = 67, //! < object part 114 PARTITRACK1 = 68, //! < drag 1 115 PARTITRACK2 = 69, //! < drag 2 116 PARTITRACK3 = 70, //! < drag 3 117 PARTITRACK4 = 71, //! < drag 4 118 PARTITRACK5 = 72, //! < drag 5 119 PARTITRACK6 = 73, //! < drag 6 120 PARTITRACK7 = 74, //! < drag 7 121 PARTITRACK8 = 75, //! < drag 8 122 PARTITRACK9 = 76, //! < drag 9 123 PARTITRACK10 = 77, //! < drag 10 124 PARTITRACK11 = 78, //! < drag 11 125 PARTITRACK12 = 79, //! < drag 12 (TODO: unused?) 126 PARTIGLINTb = 88, //! < blue reflection 127 PARTIGLINTr = 89, //! < red reflection 128 PARTILENS1 = 90, //! < brilliance 1 (orange) 129 PARTILENS2 = 91, //! < brilliance 2 (yellow) 130 PARTILENS3 = 92, //! < brilliance 3 (red) 131 PARTILENS4 = 93, //! < brilliance 4 (violet) 132 PARTICONTROL = 94, //! < reflection on button 133 PARTISHOW = 95, //! < shows a place 134 PARTICHOC = 96, //! < shock wave 135 PARTIGFLAT = 97, //! < shows if the ground is flat 136 PARTIRECOVER = 98, //! < blue ball recycler 137 PARTIROOT = 100, //! < gravity root smoke 138 PARTIPLOUF0 = 101, //! < splash 139 PARTIDROP = 106, //! < drop 140 PARTIFOG0 = 107, //! < fog 0 141 PARTIFOG1 = 108, //! < fog 1 142 PARTIFOG2 = 109, //! < fog 2 143 PARTIFOG3 = 110, //! < fog 3 144 PARTIFOG4 = 111, //! < fog 4 145 PARTIFOG5 = 112, //! < fog 5 146 PARTIFOG6 = 113, //! < fog 6 147 PARTIFOG7 = 114, //! < fog 7 148 PARTILIMIT1 = 117, //! < shows the limits 1 149 PARTILIMIT2 = 118, //! < shows the limits 2 150 PARTILIMIT3 = 119, //! < shows the limits 3 151 PARTIWATER = 121, //! < drop of water 152 PARTIEXPLOG1 = 122, //! < ball explosion 1 153 PARTIEXPLOG2 = 123, //! < ball explosion 2 154 PARTIBASE = 124, //! < gases of spaceship 155 }; 156 157 enum ParticlePhase 158 { 159 PARPHSTART = 0, 160 PARPHEND = 1, 161 }; 162 163 struct Particle 164 { 165 bool used = false; // TRUE -> particle used 166 bool ray = false; // TRUE -> ray with goal 167 unsigned short uniqueStamp = 0; // unique mark 168 short sheet = 0; // sheet (0..n) 169 ParticleType type = {}; // type PARTI* 170 ParticlePhase phase = {}; // phase PARPH* 171 float mass = 0.0f; // mass of the particle (in rebounding) 172 float weight = 0.0f; // weight of the particle (for noise) 173 float duration = 0.0f; // length of life 174 Math::Vector pos; // absolute position (relative if object links) 175 Math::Vector goal; // goal position (if ray) 176 Math::Vector speed; // speed of displacement 177 float windSensitivity = 0.0f; 178 short bounce = 0; // number of rebounds 179 Math::Point dim; // dimensions of the rectangle 180 float zoom = 0.0f; // zoom (0..1) 181 float angle = 0.0f; // angle of rotation 182 float intensity = 0.0f; // intensity 183 Math::Point texSup; // coordinated upper texture 184 Math::Point texInf; // coordinated lower texture 185 float time = 0.0f; // age of the particle (0..n) 186 float phaseTime = 0.0f; // age at the beginning of phase 187 float testTime = 0.0f; // time since last test 188 CObject* objLink = nullptr; // father object (for example reactor) 189 CObject* objFather = nullptr; // father object (for example reactor) 190 short objRank = 0; // rank of the object, or -1 191 short trackRank = 0; // rank of the drag 192 char text = 0; 193 Color color = Color(1.0f, 1.0f, 1.0f, 1.0f); 194 }; 195 196 struct Track 197 { 198 char used = 0; // TRUE -> drag used 199 char drawParticle = 0; 200 float step = 0.0f; // duration of not 201 float last = 0.0f; // increase last not memorized 202 float intensity = 0.0f; // intensity at starting (0..1) 203 float width = 0.0f; // tail width 204 int posUsed = 0.0f; // number of positions in "pos" 205 int head = 0; // head to write index 206 Math::Vector pos[MAXTRACKLEN]; 207 float len[MAXTRACKLEN] = {}; 208 }; 209 210 struct WheelTrace 211 { 212 TraceColor color = TraceColor::Black; 213 Math::Vector pos[4]; 214 }; 215 216 217 /** 218 * \class CParticle 219 * \brief Particle engine 220 * 221 * TODO: documentation 222 */ 223 class CParticle 224 { 225 public: 226 CParticle(CEngine* engine); 227 ~CParticle(); 228 229 //! Sets the device to use 230 void SetDevice(CDevice* device); 231 232 //! Removes all particles 233 void FlushParticle(); 234 235 //! Removes all particles of a sheet 236 void FlushParticle(int sheet); 237 238 //! Creates a new particle 239 int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim, 240 ParticleType type, float duration = 1.0f, float mass = 0.0f, 241 float windSensitivity = 1.0f, int sheet = 0); 242 243 //! Creates a new triangular particle (debris) 244 int CreateFrag(Math::Vector pos, Math::Vector speed, EngineTriangle* triangle, 245 ParticleType type, float duration = 1.0f, float mass = 0.0f, 246 float windSensitivity = 1.0f, int sheet = 0); 247 248 //! Creates a new particle being a part of object 249 int CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type, 250 float duration = 1.0f, float mass = 0.0f, float weight = 0.0f, 251 float windSensitivity = 1.0f, int sheet = 0); 252 253 //! Creates a new linear particle (radius) 254 int CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim, 255 float duration = 1.0f, int sheet = 0); 256 257 //! Creates a particle with a trail 258 int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type, 259 float duration = 1.0f, float mass = 0.0f, float length = 10.0f, float width = 1.0f); 260 261 //! Creates a tire mark 262 void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3, 263 const Math::Vector &p4, TraceColor color); 264 265 //! Removes all particles of a given type 266 void DeleteParticle(ParticleType type); 267 //! Removes all particles of a given channel 268 void DeleteParticle(int channel); 269 //! Specifies the object to which the particle is bound 270 void SetObjectLink(int channel, CObject *object); 271 //! Specifies the parent object that created the particle 272 void SetObjectFather(int channel, CObject *object); 273 void SetPosition(int channel, Math::Vector pos); 274 void SetDimension(int channel, Math::Point dim); 275 void SetZoom(int channel, float zoom); 276 void SetAngle(int channel, float angle); 277 void SetIntensity(int channel, float intensity); 278 void SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity); 279 void SetPhase(int channel, ParticlePhase phase, float duration); 280 281 //! Returns the position of the particle 282 bool GetPosition(int channel, Math::Vector &pos); 283 284 //! Returns the color if you're in the fog or black if you're not 285 Color GetFogColor(Math::Vector pos); 286 287 //! Indicates whether a sheet is updated or not 288 void SetFrameUpdate(int sheet, bool update); 289 //! Updates all the particles. 290 void FrameParticle(float rTime); 291 //! Draws all the particles 292 void DrawParticle(int sheet); 293 294 //! Indicates that the object binds to the particle no longer exists, without deleting it 295 void CutObjectLink(CObject* obj); 296 297 protected: 298 //! Removes a particle of given rank 299 void DeleteRank(int rank); 300 /** 301 * \brief Adapts the channel so it can be used as an offset in m_particle 302 * \param channel Channel number to process, will be modified to be index of particle in m_particle 303 * \return true if success, false if particle doesn't exist anymore 304 **/ 305 bool CheckChannel(int &channel); 306 //! Draws a triangular particle 307 void DrawParticleTriangle(int i); 308 //! Draw a normal particle 309 void DrawParticleNorm(int i); 310 //! Draw a particle flat (horizontal) 311 void DrawParticleFlat(int i); 312 //! Draw a particle to a flat sheet of fog 313 void DrawParticleFog(int i); 314 //! Draw a particle in the form of radius 315 void DrawParticleRay(int i); 316 //! Draws a spherical particle 317 void DrawParticleSphere(int i); 318 //! Draws a cylindrical particle 319 void DrawParticleCylinder(int i); 320 //! Draws a text particle 321 void DrawParticleText(int i); 322 //! Draws a tire mark 323 void DrawParticleWheel(int i); 324 //! Seeks if an object collided with a bullet 325 CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father); 326 //! Seeks if an object collided with a ray 327 CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father); 328 //! Sounded one 329 void Play(SoundType sound, Math::Vector pos, float amplitude); 330 //! Moves a drag; returns true if the drag is finished 331 bool TrackMove(int i, Math::Vector pos, float progress); 332 //! Draws a drag 333 void TrackDraw(int i, ParticleType type); 334 335 protected: 336 CEngine* m_engine = nullptr; 337 CDevice* m_device = nullptr; 338 CTerrain* m_terrain = nullptr; 339 CWater* m_water = nullptr; 340 CRobotMain* m_main = nullptr; 341 CSoundInterface* m_sound = nullptr; 342 343 Particle m_particle[MAXPARTICULE*MAXPARTITYPE]; 344 EngineTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0 345 Track m_track[MAXTRACK]; 346 int m_wheelTraceTotal = 0; 347 int m_wheelTraceIndex = 0; 348 WheelTrace m_wheelTrace[MAXWHEELTRACE]; 349 int m_totalInterface[MAXPARTITYPE][SH_MAX] = {}; 350 bool m_frameUpdate[SH_MAX] = {}; 351 int m_fogTotal = 0; 352 int m_fog[MAXPARTIFOG] = {}; 353 int m_uniqueStamp = 0; 354 int m_exploGunCounter = 0; 355 float m_lastTimeGunDel = 0.0f; 356 float m_absTime = 0.0f; 357 }; 358 359 360 } // namespace Gfx 361