mirror of https://github.com/AxioDL/metaforce.git
120 lines
3.8 KiB
C++
120 lines
3.8 KiB
C++
#include "Runtime/Particle/CDecalManager.hpp"
|
|
|
|
#include "Runtime/CStateManager.hpp"
|
|
#include "Runtime/GameGlobalObjects.hpp"
|
|
#include "Runtime/Graphics/CBooRenderer.hpp"
|
|
#include "Runtime/Graphics/Shaders/CDecalShaders.hpp"
|
|
#include "Runtime/Particle/CDecal.hpp"
|
|
#include "Runtime/Particle/CDecalDescription.hpp"
|
|
|
|
namespace metaforce {
|
|
bool CDecalManager::m_PoolInitialized = false;
|
|
s32 CDecalManager::m_FreeIndex = 63;
|
|
float CDecalManager::m_DeltaTimeSinceLastDecalCreation = 0.f;
|
|
s32 CDecalManager::m_LastDecalCreatedIndex = -1;
|
|
CAssetId CDecalManager::m_LastDecalCreatedAssetId = -1;
|
|
rstl::reserved_vector<CDecalManager::SDecal, 64> CDecalManager::m_DecalPool;
|
|
rstl::reserved_vector<s32, 64> CDecalManager::m_ActiveIndexList;
|
|
|
|
void CDecalManager::Initialize() {
|
|
if (m_PoolInitialized)
|
|
return;
|
|
|
|
m_DecalPool.clear();
|
|
for (int i = 0; i < 64; ++i) {
|
|
m_DecalPool.emplace_back(std::nullopt, 0, i - 1, false);
|
|
}
|
|
|
|
m_FreeIndex = 63;
|
|
m_PoolInitialized = true;
|
|
m_DeltaTimeSinceLastDecalCreation = 0.f;
|
|
m_LastDecalCreatedIndex = -1;
|
|
m_LastDecalCreatedAssetId = -1;
|
|
|
|
/* Compile shaders */
|
|
CDecalShaders::Initialize();
|
|
}
|
|
|
|
void CDecalManager::Reinitialize() {
|
|
if (!m_PoolInitialized)
|
|
Initialize();
|
|
|
|
m_DecalPool.clear();
|
|
for (int i = 0; i < 64; ++i) {
|
|
m_DecalPool.emplace_back(std::nullopt, 0, i - 1, false);
|
|
}
|
|
|
|
m_ActiveIndexList.clear();
|
|
|
|
m_FreeIndex = 63;
|
|
}
|
|
|
|
void CDecalManager::Shutdown() {
|
|
m_ActiveIndexList.clear();
|
|
m_DecalPool.clear();
|
|
CDecalShaders::Shutdown();
|
|
}
|
|
|
|
void CDecalManager::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) {
|
|
for (s32 idx : m_ActiveIndexList) {
|
|
CDecalManager::SDecal& decal = m_DecalPool[idx];
|
|
if (decal.x75_24_notIce || mgr.GetThermalDrawFlag() != EThermalDrawFlag::Hot) {
|
|
const zeus::CVector3f& point = decal.x0_decal->xc_transform.origin;
|
|
zeus::CAABox aabb(point, point);
|
|
g_Renderer->AddDrawable(&*decal.x0_decal, point, aabb, 2, IRenderer::EDrawableSorting::SortedCallback);
|
|
}
|
|
}
|
|
}
|
|
|
|
rstl::reserved_vector<s32, 64>::iterator
|
|
CDecalManager::RemoveFromActiveList(rstl::reserved_vector<s32, 64>::iterator it, s32 idx) {
|
|
it = m_ActiveIndexList.erase(it);
|
|
m_DecalPool[idx].x74_index = u8(m_FreeIndex);
|
|
m_FreeIndex = idx;
|
|
if (m_LastDecalCreatedIndex == m_FreeIndex)
|
|
m_LastDecalCreatedIndex = -1;
|
|
return it;
|
|
}
|
|
|
|
void CDecalManager::Update(float dt, CStateManager& mgr) {
|
|
m_DeltaTimeSinceLastDecalCreation += dt;
|
|
for (auto it = m_ActiveIndexList.begin(); it != m_ActiveIndexList.end();) {
|
|
SDecal& decal = m_DecalPool[*it];
|
|
if (decal.x70_areaId != mgr.GetNextAreaId() ||
|
|
(decal.x0_decal->x5c_29_modelInvalid && decal.x0_decal->x5c_30_quad2Invalid &&
|
|
decal.x0_decal->x5c_31_quad1Invalid)) {
|
|
it = RemoveFromActiveList(it, *it);
|
|
continue;
|
|
}
|
|
decal.x0_decal->Update(dt);
|
|
++it;
|
|
}
|
|
}
|
|
|
|
void CDecalManager::AddDecal(const TToken<CDecalDescription>& decal, const zeus::CTransform& xf, bool notIce,
|
|
CStateManager& mgr) {
|
|
if (m_LastDecalCreatedIndex != -1 && m_DeltaTimeSinceLastDecalCreation < 0.75f &&
|
|
m_LastDecalCreatedAssetId == decal.GetObjectTag()->id) {
|
|
SDecal& existingDecal = m_DecalPool[m_LastDecalCreatedIndex];
|
|
if ((existingDecal.x0_decal->xc_transform.origin - xf.origin).magSquared() < 0.01f)
|
|
return;
|
|
}
|
|
|
|
if (m_FreeIndex == -1)
|
|
RemoveFromActiveList(m_ActiveIndexList.begin(), m_ActiveIndexList[0]);
|
|
|
|
s32 thisIndex = m_FreeIndex;
|
|
SDecal& freeDecal = m_DecalPool[thisIndex];
|
|
m_FreeIndex = freeDecal.x74_index;
|
|
freeDecal.x0_decal.emplace(decal, xf);
|
|
|
|
freeDecal.x70_areaId = mgr.GetNextAreaId();
|
|
freeDecal.x75_24_notIce = notIce;
|
|
m_DeltaTimeSinceLastDecalCreation = 0.f;
|
|
m_LastDecalCreatedIndex = thisIndex;
|
|
m_LastDecalCreatedAssetId = decal.GetObjectTag()->id;
|
|
m_ActiveIndexList.push_back(thisIndex);
|
|
}
|
|
|
|
} // namespace metaforce
|