-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathparticle_manager.cpp
More file actions
102 lines (87 loc) · 3.05 KB
/
Copy pathparticle_manager.cpp
File metadata and controls
102 lines (87 loc) · 3.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include "particle_manager.h"
#include <algorithm>
#include "billboard.h"
#include "camera.h"
using namespace DirectX;
ParticleManager::ParticleManager(const char* texturePath, std::size_t maxParticles)
: m_pBillboard(new Billboard(
XMFLOAT3(0.0f, 0.0f, 0.0f),
XMFLOAT2(1.0f, 1.0f),
XMFLOAT3(0.0f, 0.0f, 0.0f),
texturePath,
false)),
m_MaxParticles(maxParticles)
{
m_Particles.reserve(maxParticles);
m_DrawOrder.reserve(maxParticles);
m_pBillboard->SetBillboardMode(true);
m_pBillboard->SetWallFadeEnabled(false);
}
ParticleManager::~ParticleManager()
{
delete m_pBillboard;
m_pBillboard = nullptr;
}
void ParticleManager::Emit(const Particle& particle)
{
if (particle.lifetime <= 0.0f || m_MaxParticles == 0)
return;
if (m_Particles.size() >= m_MaxParticles)
{
// 上限時は最も古い粒子(インデックス0)を末尾の粒子で上書きして末尾を消すことで、O(1)で要素数を減らし、O(N)シフトを避ける
m_Particles[0] = m_Particles.back();
m_Particles.pop_back();
}
m_Particles.push_back(particle);
}
void ParticleManager::Update(float deltaTime)
{
// 派生クラスから渡された物理パラメータだけで共通更新する。
for (Particle& particle : m_Particles)
{
particle.age += deltaTime;
particle.velocity.x += particle.acceleration.x * deltaTime;
particle.velocity.y += particle.acceleration.y * deltaTime;
particle.velocity.z += particle.acceleration.z * deltaTime;
const float damping = (std::max)(0.0f, 1.0f - particle.damping * deltaTime);
particle.velocity.x *= damping;
particle.velocity.y *= damping;
particle.velocity.z *= damping;
particle.position.x += particle.velocity.x * deltaTime;
particle.position.y += particle.velocity.y * deltaTime;
particle.position.z += particle.velocity.z * deltaTime;
particle.rotation += particle.angularVelocity * deltaTime;
}
m_Particles.erase(
std::remove_if(
m_Particles.begin(),
m_Particles.end(),
[](const Particle& particle) { return particle.age >= particle.lifetime; }),
m_Particles.end());
}
void ParticleManager::Draw()
{
m_DrawOrder.clear();
for (const Particle& particle : m_Particles)
m_DrawOrder.push_back(&particle);
const XMMATRIX view = GetCamera()->GetView();
std::stable_sort(
m_DrawOrder.begin(),
m_DrawOrder.end(),
[&view](const Particle* lhs, const Particle* rhs)
{
XMVECTOR lhsViewPos = XMVector3TransformCoord(XMLoadFloat3(&lhs->position), view);
XMVECTOR rhsViewPos = XMVector3TransformCoord(XMLoadFloat3(&rhs->position), view);
return XMVectorGetZ(lhsViewPos) > XMVectorGetZ(rhsViewPos);
});
// 奥から手前へ描きつつ、1枚のBillboardを全粒子で使い回す。
for (const Particle* particle : m_DrawOrder)
{
const float progress = (std::min)(particle->age / particle->lifetime, 1.0f);
const float size = particle->startSize + (particle->endSize - particle->startSize) * progress;
m_pBillboard->SetPos(particle->position);
m_pBillboard->SetSize({ size, size });
m_pBillboard->SetRotation({ 0.0f, 0.0f, particle->rotation });
m_pBillboard->Draw();
}
}