verus/Verus/src/Effects/Particles.h

186 lines
6.3 KiB
C++

// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
#pragma once
namespace verus::Effects
{
enum class BillboardType : int
{
none,
screenViewplaneOriented,
screenViewpointOriented,
worldViewplaneOriented,
worldViewpointOriented,
axial
};
class Particle
{
public:
Point3 _position = Point3(0);
Point3 _prevPosition = Point3(0);
Vector3 _velocity = Vector3(0, 1, 0);
Vector3 _axis = Vector3(0, 1, 0);
Vector4 _tcOffset = Vector4(0);
Vector4 _beginColor = Vector4::Replicate(1);
Vector4 _endColor = Vector4::Replicate(1);
void* _pUser = nullptr;
float _invTotalTime = 0;
float _timeLeft = -1;
float _beginAdditive = 0;
float _endAdditive = 0;
float _beginSize = 0;
float _endSize = 0;
float _beginSpin = 0;
float _endSpin = 0;
bool _inContact = false;
};
VERUS_TYPEDEFS(Particle);
class Particles;
class ParticlesDelegate
{
public:
virtual void Particles_OnUpdate(Particles& particles, int index, RParticle particle,
RVector3 up, RVector3 normal, RTransform3 matAim) = 0;
};
VERUS_TYPEDEFS(ParticlesDelegate);
class Particles : public Object
{
#include "../Shaders/Particles.inc.hlsl"
enum PIPE
{
PIPE_MAIN,
PIPE_BILLBOARDS,
PIPE_COUNT
};
struct Vertex
{
glm::vec4 pos;
glm::vec2 tc0;
UINT32 color;
float psize;
};
VERUS_TYPEDEFS(Vertex);
static CGI::ShaderPwn s_shader;
static CGI::PipelinePwns<PIPE_COUNT> s_pipe;
static UB_ParticlesVS s_ubParticlesVS;
static UB_ParticlesFS s_ubParticlesFS;
Vector4 _tilesetSize = Vector4::Replicate(1);
Vector3 _lifeTimeRange = Vector3(0, 1, 1);
Vector3 _speedRange = Vector3(0, 1, 1);
Vector3 _beginAdditiveRange = Vector3(0);
Vector3 _endAdditiveRange = Vector3(0);
Vector4 _beginColorMin = Vector4(0);
Vector4 _beginColorDelta = Vector4(0);
Vector4 _endColorMin = Vector4(0);
Vector4 _endColorDelta = Vector4(0);
Vector3 _beginSizeRange = Vector3(0, 1, 1);
Vector3 _endSizeRange = Vector3(0, 1, 1);
Vector3 _beginSpinRange = Vector3(0, 1, 1);
Vector3 _endSpinRange = Vector3(0, 1, 1);
Vector3 _gravity = Vector3(0, -9.8f, 0);
String _url;
Vector<Particle> _vParticles;
Vector<Vertex> _vVB;
Vector<UINT16> _vIB;
CGI::GeometryPwn _geo;
CGI::TexturePwn _tex;
CGI::CSHandle _csh;
PParticlesDelegate _pDelegate = nullptr;
const float* _pUserZone = nullptr;
BillboardType _billboardType = BillboardType::none;
int _tilesetX = 0;
int _tilesetY = 0;
int _indexCount = 0;
int _capacity = 0;
int _addAt = 0;
int _drawCount = 0;
float _ratio = 1;
float _brightness = 1;
float _bounceStrength = 0.5f;
float _gravityStrength = 1;
float _windStrength = 0;
float _flowRemainder = 0;
float _particlesPerSecond = 0;
float _zone = 0;
bool _collide = false;
bool _decal = false;
bool _flowEnabled = true;
public:
Particles();
~Particles();
static void InitStatic();
static void DoneStatic();
void Init(CSZ url);
void Done();
void Update(); // Call this after adding particles!
void Draw();
Str GetURL() const { return _C(_url); }
int GetTilesetX() const { return _tilesetX; }
int GetTilesetY() const { return _tilesetY; }
int GetCapacity() const { return _capacity; }
int GetDrawCount() const { return _drawCount; }
PParticlesDelegate SetDelegate(PParticlesDelegate p) { return Utils::Swap(_pDelegate, p); }
void SetUserZone(const float* pZone) { _pUserZone = pZone; }
void GetLifeTime(float& mn, float& mx) const;
void SetLifeTime(float mn, float mx);
void GetSpeed(float& mn, float& mx) const;
void SetSpeed(float mn, float mx);
void GetBeginAdditive(float& mn, float& mx) const;
void SetBeginAdditive(float mn, float mx);
void GetBeginColor(RVector4 mn, RVector4 mx) const;
void SetBeginColor(RcVector4 mn, RcVector4 mx);
void GetEndColor(RVector4 mn, RVector4 mx) const;
void SetEndColor(RcVector4 mn, RcVector4 mx);
void GetEndAdditive(float& mn, float& mx) const;
void SetEndAdditive(float mn, float mx);
void GetBeginSize(float& mn, float& mx) const;
void SetBeginSize(float mn, float mx);
void GetEndSize(float& mn, float& mx) const;
void SetEndSize(float mn, float mx);
void GetBeginSpin(float& mn, float& mx) const;
void SetBeginSpin(float mn, float mx);
void GetEndSpin(float& mn, float& mx) const;
void SetEndSpin(float mn, float mx);
float GetBrightness() const { return _brightness; }
void SetBrightness(float value) { _brightness = value; }
float GetBounce() const { return _bounceStrength; }
void SetBounce(float value) { _bounceStrength = value; }
float GetGravity() const { return _gravityStrength; }
void SetGravity(float value) { _gravityStrength = value; }
float GetWind() const { return _windStrength; }
void SetWind(float value) { _windStrength = value; }
float GetParticlesPerSecond() const { return _particlesPerSecond; }
void SetParticlesPerSecond(float value) { _particlesPerSecond = value; }
float GetZone() const { return _zone; }
void SetZone(float value) { _zone = value; }
int Add(RcPoint3 pos, RcVector3 dir,
float scale = 1, PcVector4 pUserColor = nullptr, void* pUser = nullptr);
void AddFlow(RcPoint3 pos, RcVector3 dirOffset,
float scale = 1, PcVector4 pUserColor = nullptr, float* pUserFlowRemainder = nullptr, float intensity = 1);
bool IsFlowEnabled() const { return _flowEnabled; }
void EnableFlow(bool b = true) { _flowEnabled = b; }
bool TimeCorrectedVerletIntegration(RParticle particle, RPoint3 point, RVector3 normal);
bool EulerIntegration(RParticle particle, RPoint3 point, RVector3 normal);
void PushPointSprite(int index, RcVector4 color, float size, float additive);
void PushBillboard(int index, RcVector4 color, RcTransform3 matW, float additive);
Transform3 GetBillboardMatrix(int index, float size, float spin, RcVector3 up, RcVector3 normal, RTransform3 matAim);
};
VERUS_TYPEDEFS(Particles);
}