2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-05-14 23:51:21 +00:00
metaforce/Runtime/Particle/CElementGen.cpp
2016-02-09 16:00:28 -10:00

406 lines
10 KiB
C++

#include "CElementGen.hpp"
#include "CGenDescription.hpp"
#include "CLight.hpp"
#include "CParticleGlobals.hpp"
namespace Retro
{
static LogVisor::LogModule Log("Retro::CElementGen");
static bool s_inCreateNewParticles = false;
int CElementGen::g_ParticleAliveCount;
int CElementGen::g_ParticleSystemAliveCount;
static rstl::reserved_vector<CElementGen::CParticle, 2560> g_StaticParticleList;
void CElementGen::Initialize()
{
g_ParticleAliveCount = 0;
g_ParticleSystemAliveCount = 0;
CParticle baseParticle;
std::uninitialized_fill_n(g_StaticParticleList.begin(), 2560, baseParticle);
}
CElementGen::CElementGen(const TToken<CGenDescription>& gen,
EModelOrientationType orientType,
EOptionalSystemFlags flags)
: x1c_genDesc(gen), x28_orientType(orientType),
x226((flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None), x230(x74)
{
CIntElement* pmedElem = x1c_genDesc.GetObj()->x1c_PMED.get();
if (pmedElem)
{
int pmedVal;
pmedElem->GetValue(x50_curFrame, pmedVal);
x74 = pmedVal;
}
x230.SetSeed(x74);
++g_ParticleSystemAliveCount;
x224_25_LIT_ = x1c_genDesc.GetObj()->x44_29_LIT_;
x224_26_AAPH = x1c_genDesc.GetObj()->x44_26_AAPH;
x224_27_ZBUF = x1c_genDesc.GetObj()->x44_27_ZBUF;
x224_29_MBLR = x1c_genDesc.GetObj()->x44_30_MBLR;
CIntElement* mbspElem = x1c_genDesc.GetObj()->x48_MBSP.get();
if (mbspElem)
mbspElem->GetValue(x50_curFrame, x228_MBSP);
x224_30_VMD1 = x1c_genDesc.GetObj()->x45_26_VMD1;
x224_31_VMD2 = x1c_genDesc.GetObj()->x45_27_VMD2;
x225_24_VMD2 = x1c_genDesc.GetObj()->x45_28_VMD3;
x225_25_VMD2 = x1c_genDesc.GetObj()->x45_29_VMD4;
CIntElement* cssdElem = x1c_genDesc.GetObj()->xa0_CSSD.get();
if (cssdElem)
cssdElem->GetValue(0, x244_CSSD);
SChildGeneratorDesc& idts = x1c_genDesc.GetObj()->xa4_IDTS;
if (idts.m_found)
{
int ndsyVal = 1;
CIntElement* ndsyElem = x1c_genDesc.GetObj()->xb4_NDSY.get();
if (ndsyElem)
ndsyElem->GetValue(0, ndsyVal);
x248_children.reserve(ndsyVal + x248_children.size());
for (int i=0 ; i<ndsyVal ; ++i)
{
CGenDescription* chDesc = x1c_genDesc.GetObj()->xa4_IDTS.m_gen.GetObj();
if (x226 && chDesc->x45_31_OPTS)
break;
x248_children.emplace_back(new CElementGen(x1c_genDesc.GetObj()->xa4_IDTS.m_gen,
EModelOrientationType::Normal,
x226 ? EOptionalSystemFlags::Two : EOptionalSystemFlags::One));
}
}
CIntElement* pisyElem = x1c_genDesc.GetObj()->xc8_PISY.get();
if (pisyElem)
{
pisyElem->GetValue(0, x25c_PISY);
if (x25c_PISY <= 0)
x25c_PISY = 1;
}
CIntElement* sisyElem = x1c_genDesc.GetObj()->xcc_SISY.get();
if (sisyElem)
pisyElem->GetValue(0, x258_SISY);
CIntElement* sssdElem = x1c_genDesc.GetObj()->xe4_SSSD.get();
if (sssdElem)
sssdElem->GetValue(0, x270_SSSD);
CVectorElement* sspoElem = x1c_genDesc.GetObj()->xe8_SSPO.get();
if (sspoElem)
sspoElem->GetValue(0, x274_SSPO);
CIntElement* sesdElem = x1c_genDesc.GetObj()->xf8_SESD.get();
if (sesdElem)
sesdElem->GetValue(0, x290_SESD);
CVectorElement* sepoElem = x1c_genDesc.GetObj()->xfc_SEPO.get();
if (sepoElem)
sepoElem->GetValue(0, x294_SEPO);
CIntElement* psltElem = x1c_genDesc.GetObj()->xc_PSLT.get();
if (psltElem)
psltElem->GetValue(0, x214_PSLT);
CVectorElement* psivElem = x1c_genDesc.GetObj()->x0_PSIV.get();
if (psivElem)
psivElem->GetValue(0, x218_PSIV);
CIntElement* maxpElem = x1c_genDesc.GetObj()->x28_MAXP.get();
if (maxpElem)
maxpElem->GetValue(x50_curFrame, x70_MAXP);
x2c_particleLists.reserve(std::min(256, x70_MAXP));
if (x28_orientType == EModelOrientationType::One)
{
x3c_parentMatrices.insert(x3c_parentMatrices.end(), x70_MAXP,
Zeus::CMatrix3f::skIdentityMatrix3f);
}
x225_26_LINE = x1c_genDesc.GetObj()->x44_24_LINE;
x225_27_FXLL = x1c_genDesc.GetObj()->x44_25_FXLL;
CRealElement* widtElem = x1c_genDesc.GetObj()->x24_WIDT.get();
if (widtElem)
widtElem->GetValue(x50_curFrame, x94_WIDT);
CIntElement* ltypElem = x1c_genDesc.GetObj()->x100_LTYP.get();
if (ltypElem)
{
int ltyp;
ltypElem->GetValue(x50_curFrame, ltyp);
switch (ELightType(ltyp))
{
case ELightType::LocalAmbient:
default:
x2dc_lightType = ELightType::LocalAmbient;
break;
case ELightType::Directional:
x2dc_lightType = ELightType::Directional;
break;
case ELightType::Custom:
x2dc_lightType = ELightType::Custom;
break;
case ELightType::Spot:
x2dc_lightType = ELightType::Spot;
break;
}
}
CIntElement* lfotElem = x1c_genDesc.GetObj()->x114_LFOT.get();
if (lfotElem)
{
int lfot;
lfotElem->GetValue(x50_curFrame, lfot);
switch (EFalloffType(lfot))
{
case EFalloffType::Constant:
x300_falloffType = EFalloffType::Constant;
break;
case EFalloffType::Linear:
default:
x300_falloffType = EFalloffType::Linear;
break;
case EFalloffType::Quadratic:
x300_falloffType = EFalloffType::Quadratic;
break;
}
}
}
CElementGen::~CElementGen()
{
--g_ParticleSystemAliveCount;
}
CElementGen::CParticleListItem::CParticleListItem()
{
++g_ParticleAliveCount;
}
CElementGen::CParticleListItem::~CParticleListItem()
{
--g_ParticleAliveCount;
}
void CElementGen::Update(double t)
{
CIntElement* pswtElem = x1c_genDesc.GetObj()->x10_PSWT.get();
if (pswtElem && !x225_28_warmedUp)
{
int pswt = 0;
pswtElem->GetValue(x50_curFrame, pswt);
if (pswt > 32)
{
Log.report(LogVisor::Info,
"Running warmup on particle system 0x%08x for %d ticks.",
x1c_genDesc.GetObj(), pswt);
InternalUpdate(pswt / 60.0);
x225_28_warmedUp = true;
}
}
InternalUpdate(t);
}
bool CElementGen::InternalUpdate(double dt)
{
CGlobalRandom gr(x230);
double dt1 = 1 / 60.0;
if (fabs(dt - 1 / 60.0) >= 1 / 60000.0)
dt1 = dt;
double t = x50_curFrame / 60.0;
CParticleGlobals::SetEmitterTime(x50_curFrame);
CRealElement* pstsElem = x1c_genDesc.GetObj()->x14_PSTS.get();
if (pstsElem)
{
float psts;
pstsElem->GetValue(x50_curFrame, psts);
double dt1Scaled = psts * dt1;
dt1 = std::max(0.0, dt1Scaled);
}
x58_curSeconds += dt1;
if (x224_29_MBLR && dt > 0.0)
{
CIntElement* mbspElem = x1c_genDesc.GetObj()->x48_MBSP.get();
if (mbspElem)
mbspElem->GetValue(x50_curFrame, x228_MBSP);
}
int frameUpdateCount = 0;
while (t < x58_curSeconds && fabs(t - x58_curSeconds) >= 1 / 60000.0)
{
x2a8.splat(FLT_MAX);
x2b4.splat(FLT_MIN);
x2c0 = 0.f;
float grte = 0.f;
CParticleGlobals::SetEmitterTime(x50_curFrame);
CRealElement* grteElem = x1c_genDesc.GetObj()->x2c_GRTE.get();
if (grteElem->GetValue(x50_curFrame, grte))
{
x2c_particleLists.clear();
return true;
}
grte = std::max(0.f, grte * x78_generatorRate);
x6c += grte;
int x6c_floor = floorf(x6c);
x6c = x6c - x6c_floor;
if (x50_curFrame < x214_PSLT)
{
if (!x68_particleEmission)
x6c_floor = 0;
}
else
x6c_floor = 0;
CIntElement* maxpElem = x1c_genDesc.GetObj()->x28_MAXP.get();
if (maxpElem)
maxpElem->GetValue(x50_curFrame, x70_MAXP);
UpdateExistingParticles();
CParticleGlobals::SetParticleLifetime(x214_PSLT);
bool oldBoolVal = s_inCreateNewParticles;
s_inCreateNewParticles = true;
CreateNewParticles(x6c_floor);
s_inCreateNewParticles = oldBoolVal;
UpdatePSTranslationAndOrientation();
UpdateChildParticleSystems(1 / 60.0);
if (x2dc_lightType != ELightType::LocalAmbient)
UpdateLightParameters();
++frameUpdateCount;
++x50_curFrame;
t += 1 / 60.0;
}
UpdateChildParticleSystems(frameUpdateCount * (-1 / 60.0) - dt1);
if (fabs(t - x58_curSeconds) < 1 / 60000.0)
x58_curSeconds = t;
BuildParticleSystemBounds();
x224_24 = false;
double passedTime = t - x58_curSeconds;
x60 = 1.0 - passedTime * 60.0;
return false;
}
void CElementGen::UpdateExistingParticles()
{
CParticleGlobals::SetEmitterTime(x50_curFrame);
}
void CElementGen::CreateNewParticles(int)
{
}
void CElementGen::UpdatePSTranslationAndOrientation()
{
}
void CElementGen::UpdateChildParticleSystems(double dt)
{
}
void CElementGen::UpdateLightParameters()
{
}
void CElementGen::BuildParticleSystemBounds()
{
}
void CElementGen::Render()
{
}
void CElementGen::SetOrientation(const Zeus::CTransform&)
{
}
void CElementGen::SetTranslation(const Zeus::CVector3f&)
{
}
void CElementGen::SetGlobalOrientation(const Zeus::CTransform&)
{
}
void CElementGen::SetGlobalTranslation(const Zeus::CVector3f&)
{
}
void CElementGen::SetGlobalScale(const Zeus::CVector3f&)
{
}
void CElementGen::SetLocalScale(const Zeus::CVector3f&)
{
}
void CElementGen::SetParticleEmission(bool)
{
}
void CElementGen::SetModulationColor(const Zeus::CColor&)
{
}
const Zeus::CTransform& CElementGen::GetOrientation() const
{
}
const Zeus::CVector3f& CElementGen::GetTranslation() const
{
}
const Zeus::CVector3f& CElementGen::GetGlobalScale() const
{
}
const Zeus::CColor& CElementGen::GetModulationColor() const
{
}
bool CElementGen::IsSystemDeletable() const
{
}
Zeus::CAABox CElementGen::GetBounds() const
{
}
u32 CElementGen::GetParticleCount() const
{
}
bool CElementGen::SystemHasLight() const
{
}
CLight CElementGen::GetLight() const
{
}
void CElementGen::DestroyParticles()
{
}
void CElementGen::AddModifier(CWarp*)
{
}
}