colobot/src/graphics/engine/particle.h

374 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
/**
* \file graphics/engine/particle.h
* \brief Particle rendering - CParticle class (aka particle)
*/
#pragma once
#include "graphics/engine/engine.h"
#include "sound/sound_type.h"
class CRobotMain;
class CObject;
class CSoundInterface;
// Graphics module namespace
namespace Gfx
{
const short MAXPARTICULE = 500;
const short MAXPARTITYPE = 6;
const short MAXTRACK = 100;
const short MAXTRACKLEN = 10;
const short MAXPARTIFOG = 100;
const short MAXWHEELTRACE = 1000;
const short SH_WORLD = 0; // particle in the world in the interface
const short SH_FRONT = 1; // particle in the world on the interface
const short SH_INTERFACE = 2; // particle in the interface
const short SH_MAX = 3;
// type == 0 -> triangles
// type == 1 -> effect00 (black background)
// type == 2 -> effect01 (black background)
// type == 3 -> effect02 (black background)
// type == 4 -> text (white background)
enum ParticleType
{
PARTIEXPLOT = 1, //! < technology explosion
PARTIEXPLOO = 2, //! < organic explosion
PARTIMOTOR = 3, //! < the engine exhaust gas
PARTIGLINT = 4, //! < reflection
PARTIBLITZ = 5, //! < lightning recharging battery
PARTICRASH = 6, //! < dust after fall
PARTIGAS = 7, //! < gas from the reactor
PARTIFIRE = 9, //! < fireball shrinks
PARTIFIREZ = 10, //! < fireball grows
PARTIBLUE = 11, //! < blue ball
PARTISELY = 12, //! < yellow robot lights
PARTISELR = 13, //! < red robot lights
PARTIGUN1 = 18, //! < bullet 1 (fireball)
PARTIGUN2 = 19, //! < bullet 2 (ant)
PARTIGUN3 = 20, //! < bullet 3 (spider)
PARTIGUN4 = 21, //! < bullet 4 (orgaball)
PARTIFRAG = 22, //! < triangular fragment
PARTIQUEUE = 23, //! < inflamed tail (TODO: unused?)
PARTIORGANIC1 = 24, //! < organic ball mother
PARTIORGANIC2 = 25, //! < organic ball daughter
PARTISMOKE1 = 26, //! < black smoke
PARTISMOKE2 = 27, //! < black smoke
PARTISMOKE3 = 28, //! < black smoke
PARTIBLOOD = 30, //! < human blood
PARTIBLOODM = 31, //! < blood laying
PARTIVAPOR = 32, //! < steam
PARTIVIRUS = 33, //! < virus (random letter)
PARTIRAY1 = 43, //! < ray 1 (turn)
PARTIRAY2 = 44, //! < ray 2 (electric arc)
PARTIRAY3 = 45, //! < ray 3 (ExchangePost)
PARTIFLAME = 47, //! < flame
PARTIBUBBLE = 48, //! < bubble
PARTIFLIC = 49, //! < circles in the water
PARTIEJECT = 50, //! < ejection from the reactor
PARTISCRAPS = 51, //! < waste from the reactor
PARTITOTO = 52, //! < Robby's reactor
PARTIERROR = 53, //! < Robby says no
PARTIWARNING = 54, //! < Robby says blah
PARTIINFO = 54, //! < Robby says yes
PARTIQUARTZ = 55, //! < reflection crystal
PARTISPHERE0 = 56, //! < explosion sphere
PARTISPHERE1 = 57, //! < energy sphere
PARTISPHERE2 = 58, //! < analysis sphere
PARTISPHERE3 = 59, //! < shield sphere
PARTISPHERE4 = 60, //! < information sphere (emit)
PARTISPHERE5 = 61, //! < botanical sphere (gravity root)
PARTISPHERE6 = 62, //! < information sphere (receive)
PARTIGUNDEL = 66, //! < bullet destroyed by shield
PARTIPART = 67, //! < object part
PARTITRACK1 = 68, //! < drag 1
PARTITRACK2 = 69, //! < drag 2
PARTITRACK3 = 70, //! < drag 3
PARTITRACK4 = 71, //! < drag 4
PARTITRACK5 = 72, //! < drag 5
PARTITRACK6 = 73, //! < drag 6
PARTITRACK7 = 74, //! < drag 7
PARTITRACK8 = 75, //! < drag 8
PARTITRACK9 = 76, //! < drag 9
PARTITRACK10 = 77, //! < drag 10
PARTITRACK11 = 78, //! < drag 11
PARTITRACK12 = 79, //! < drag 12 (TODO: unused?)
PARTIGLINTb = 88, //! < blue reflection
PARTIGLINTr = 89, //! < red reflection
PARTILENS1 = 90, //! < brilliance 1 (orange)
PARTILENS2 = 91, //! < brilliance 2 (yellow)
PARTILENS3 = 92, //! < brilliance 3 (red)
PARTILENS4 = 93, //! < brilliance 4 (violet)
PARTICONTROL = 94, //! < reflection on button
PARTISHOW = 95, //! < shows a place
PARTICHOC = 96, //! < shock wave
PARTIGFLAT = 97, //! < shows if the ground is flat
PARTIRECOVER = 98, //! < blue ball recycler
PARTIROOT = 100, //! < gravity root smoke
PARTIPLOUF0 = 101, //! < splash
PARTIDROP = 106, //! < drop
PARTIFOG0 = 107, //! < fog 0
PARTIFOG1 = 108, //! < fog 1
PARTIFOG2 = 109, //! < fog 2
PARTIFOG3 = 110, //! < fog 3
PARTIFOG4 = 111, //! < fog 4
PARTIFOG5 = 112, //! < fog 5
PARTIFOG6 = 113, //! < fog 6
PARTIFOG7 = 114, //! < fog 7
PARTILIMIT1 = 117, //! < shows the limits 1
PARTILIMIT2 = 118, //! < shows the limits 2
PARTILIMIT3 = 119, //! < shows the limits 3
PARTIWATER = 121, //! < drop of water
PARTIEXPLOG1 = 122, //! < ball explosion 1
PARTIEXPLOG2 = 123, //! < ball explosion 2
PARTIBASE = 124, //! < gases of spaceship
PARTITRACE0 = 140, //! < trace
PARTITRACE1 = 141, //! < trace
PARTITRACE2 = 142, //! < trace
PARTITRACE3 = 143, //! < trace
PARTITRACE4 = 144, //! < trace
PARTITRACE5 = 145, //! < trace
PARTITRACE6 = 146, //! < trace
PARTITRACE7 = 147, //! < trace
PARTITRACE8 = 148, //! < trace
PARTITRACE9 = 149, //! < trace
PARTITRACE10 = 150, //! < trace
PARTITRACE11 = 151, //! < trace
PARTITRACE12 = 152, //! < trace
PARTITRACE13 = 153, //! < trace
PARTITRACE14 = 154, //! < trace
PARTITRACE15 = 155, //! < trace
PARTITRACE16 = 156, //! < trace
PARTITRACE17 = 157, //! < trace
};
enum ParticlePhase
{
PARPHSTART = 0,
PARPHEND = 1,
};
struct Particle
{
bool used = false; // TRUE -> particle used
bool ray = false; // TRUE -> ray with goal
unsigned short uniqueStamp = 0; // unique mark
short sheet = 0; // sheet (0..n)
ParticleType type = {}; // type PARTI*
ParticlePhase phase = {}; // phase PARPH*
float mass = 0.0f; // mass of the particle (in rebounding)
float weight = 0.0f; // weight of the particle (for noise)
float duration = 0.0f; // length of life
Math::Vector pos; // absolute position (relative if object links)
Math::Vector goal; // goal position (if ray)
Math::Vector speed; // speed of displacement
float windSensitivity = 0.0f;
short bounce = 0; // number of rebounds
Math::Point dim; // dimensions of the rectangle
float zoom = 0.0f; // zoom (0..1)
float angle = 0.0f; // angle of rotation
float intensity = 0.0f; // intensity
Math::Point texSup; // coordinated upper texture
Math::Point texInf; // coordinated lower texture
float time = 0.0f; // age of the particle (0..n)
float phaseTime = 0.0f; // age at the beginning of phase
float testTime = 0.0f; // time since last test
CObject* objLink = nullptr; // father object (for example reactor)
CObject* objFather = nullptr; // father object (for example reactor)
short objRank = 0; // rank of the object, or -1
short trackRank = 0; // rank of the drag
char text = 0;
Color color = Color(1.0f, 1.0f, 1.0f, 1.0f);
};
struct Track
{
char used = 0; // TRUE -> drag used
char drawParticle = 0;
float step = 0.0f; // duration of not
float last = 0.0f; // increase last not memorized
float intensity = 0.0f; // intensity at starting (0..1)
float width = 0.0f; // tail width
int posUsed = 0.0f; // number of positions in "pos"
int head = 0; // head to write index
Math::Vector pos[MAXTRACKLEN];
float len[MAXTRACKLEN] = {0.0f};
};
struct WheelTrace
{
ParticleType type = {}; // type PARTI*
Math::Vector pos[4]; // rectangle positions
float startTime = 0.0f; // beginning of life
};
/**
* \class CParticle
* \brief Particle engine
*
* TODO: documentation
*/
class CParticle
{
public:
CParticle(CEngine* engine);
~CParticle();
//! Sets the device to use
void SetDevice(CDevice* device);
//! Removes all particles
void FlushParticle();
//! Removes all particles of a sheet
void FlushParticle(int sheet);
//! Creates a new particle
int CreateParticle(Math::Vector pos, Math::Vector speed, Math::Point dim,
ParticleType type, float duration = 1.0f, float mass = 0.0f,
float windSensitivity = 1.0f, int sheet = 0);
//! Creates a new triangular particle (debris)
int CreateFrag(Math::Vector pos, Math::Vector speed, EngineTriangle* triangle,
ParticleType type, float duration = 1.0f, float mass = 0.0f,
float windSensitivity = 1.0f, int sheet = 0);
//! Creates a new particle being a part of object
int CreatePart(Math::Vector pos, Math::Vector speed, ParticleType type,
float duration = 1.0f, float mass = 0.0f, float weight = 0.0f,
float windSensitivity = 1.0f, int sheet = 0);
//! Creates a new linear particle (radius)
int CreateRay(Math::Vector pos, Math::Vector goal, ParticleType type, Math::Point dim,
float duration = 1.0f, int sheet = 0);
//! Creates a particle with a trail
int CreateTrack(Math::Vector pos, Math::Vector speed, Math::Point dim, ParticleType type,
float duration = 1.0f, float mass = 0.0f, float length = 10.0f, float width = 1.0f);
//! Creates a tire mark
void CreateWheelTrace(const Math::Vector &p1, const Math::Vector &p2, const Math::Vector &p3,
const Math::Vector &p4, ParticleType type);
//! Removes all particles of a given type
void DeleteParticle(ParticleType type);
//! Removes all particles of a given channel
void DeleteParticle(int channel);
//! Specifies the object to which the particle is bound
void SetObjectLink(int channel, CObject *object);
//! Specifies the parent object that created the particle
void SetObjectFather(int channel, CObject *object);
void SetPosition(int channel, Math::Vector pos);
void SetDimension(int channel, Math::Point dim);
void SetZoom(int channel, float zoom);
void SetAngle(int channel, float angle);
void SetIntensity(int channel, float intensity);
void SetParam(int channel, Math::Vector pos, Math::Point dim, float zoom, float angle, float intensity);
void SetPhase(int channel, ParticlePhase phase, float duration);
//! Returns the position of the particle
bool GetPosition(int channel, Math::Vector &pos);
//! Returns the color if you're in the fog or black if you're not
Color GetFogColor(Math::Vector pos);
//! Indicates whether a sheet is updated or not
void SetFrameUpdate(int sheet, bool update);
//! Updates all the particles.
void FrameParticle(float rTime);
//! Draws all the particles
void DrawParticle(int sheet);
//! Writes a file containing all the tire tracks
bool WriteWheelTrace(const char *filename, int width, int height, Math::Vector dl, Math::Vector ur);
protected:
//! Removes a particle of given rank
void DeleteRank(int rank);
//! Check a channel number
bool CheckChannel(int &channel);
//! Draws a triangular particle
void DrawParticleTriangle(int i);
//! Draw a normal particle
void DrawParticleNorm(int i);
//! Draw a particle flat (horizontal)
void DrawParticleFlat(int i);
//! Draw a particle to a flat sheet of fog
void DrawParticleFog(int i);
//! Draw a particle in the form of radius
void DrawParticleRay(int i);
//! Draws a spherical particle
void DrawParticleSphere(int i);
//! Draws a cylindrical particle
void DrawParticleCylinder(int i);
//! Draws a text particle
void DrawParticleText(int i);
//! Draws a tire mark
void DrawParticleWheel(int i);
//! Seeks if an object collided with a bullet
CObject* SearchObjectGun(Math::Vector old, Math::Vector pos, ParticleType type, CObject *father);
//! Seeks if an object collided with a ray
CObject* SearchObjectRay(Math::Vector pos, Math::Vector goal, ParticleType type, CObject *father);
//! Sounded one
void Play(SoundType sound, Math::Vector pos, float amplitude);
//! Moves a drag; returns true if the drag is finished
bool TrackMove(int i, Math::Vector pos, float progress);
//! Draws a drag
void TrackDraw(int i, ParticleType type);
protected:
CEngine* m_engine = nullptr;
CDevice* m_device = nullptr;
CTerrain* m_terrain = nullptr;
CWater* m_water = nullptr;
CRobotMain* m_main = nullptr;
CSoundInterface* m_sound = nullptr;
Particle m_particle[MAXPARTICULE*MAXPARTITYPE];
EngineTriangle m_triangle[MAXPARTICULE]; // triangle if PartiType == 0
Track m_track[MAXTRACK];
int m_wheelTraceTotal = 0;
int m_wheelTraceIndex = 0;
WheelTrace m_wheelTrace[MAXWHEELTRACE];
int m_totalInterface[MAXPARTITYPE][SH_MAX] = {};
bool m_frameUpdate[SH_MAX] = {false};
int m_fogTotal = 0;
int m_fog[MAXPARTIFOG] = {};
int m_uniqueStamp = 0;
int m_exploGunCounter = 0;
float m_lastTimeGunDel = 0.0f;
float m_absTime = 0.0f;
};
} // namespace Gfx