2016-02-08 05:10:17 +00:00
|
|
|
#include "CElementGen.hpp"
|
|
|
|
#include "CGenDescription.hpp"
|
2016-02-10 02:00:28 +00:00
|
|
|
#include "CParticleGlobals.hpp"
|
2016-02-11 22:38:25 +00:00
|
|
|
#include "CParticleSwoosh.hpp"
|
|
|
|
#include "CParticleElectric.hpp"
|
2016-02-13 00:57:09 +00:00
|
|
|
#include "CModel.hpp"
|
2016-02-08 05:10:17 +00:00
|
|
|
|
|
|
|
namespace Retro
|
|
|
|
{
|
2016-02-10 02:00:28 +00:00
|
|
|
static LogVisor::LogModule Log("Retro::CElementGen");
|
|
|
|
|
|
|
|
static bool s_inCreateNewParticles = false;
|
2016-02-08 05:10:17 +00:00
|
|
|
|
2016-02-09 22:52:33 +00:00
|
|
|
int CElementGen::g_ParticleAliveCount;
|
|
|
|
int CElementGen::g_ParticleSystemAliveCount;
|
2016-02-11 02:36:21 +00:00
|
|
|
s32 CElementGen::g_FreeIndex;
|
|
|
|
bool CElementGen::g_StaticListInitialized = false;
|
2016-02-13 00:57:09 +00:00
|
|
|
bool CElementGen::g_MoveRedToAlphaBuffer = false;
|
2016-02-10 02:00:28 +00:00
|
|
|
static rstl::reserved_vector<CElementGen::CParticle, 2560> g_StaticParticleList;
|
2016-02-11 02:36:21 +00:00
|
|
|
static rstl::reserved_vector<u16, 2560> g_StaticFreeList;
|
2016-02-09 22:52:33 +00:00
|
|
|
void CElementGen::Initialize()
|
|
|
|
{
|
2016-02-11 02:36:21 +00:00
|
|
|
if (g_StaticListInitialized)
|
|
|
|
return;
|
|
|
|
Log.report(LogVisor::Info, "Initialize - Static Particle List - ");
|
|
|
|
|
2016-02-09 22:52:33 +00:00
|
|
|
g_ParticleAliveCount = 0;
|
|
|
|
g_ParticleSystemAliveCount = 0;
|
2016-02-10 02:00:28 +00:00
|
|
|
|
2016-02-11 02:36:21 +00:00
|
|
|
g_StaticParticleList.clear();
|
|
|
|
g_StaticParticleList.insert(g_StaticParticleList.end(), 2560, CParticle());
|
|
|
|
|
|
|
|
g_StaticFreeList.clear();
|
|
|
|
int c=0;
|
|
|
|
for (int i=0 ; i<512 ; ++i)
|
|
|
|
{
|
|
|
|
g_StaticFreeList.push_back(c++);
|
|
|
|
g_StaticFreeList.push_back(c++);
|
|
|
|
g_StaticFreeList.push_back(c++);
|
|
|
|
g_StaticFreeList.push_back(c++);
|
|
|
|
g_StaticFreeList.push_back(c++);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_FreeIndex = 2559;
|
|
|
|
Log.report(LogVisor::Info, "size %d (%d each part).", (56 + 2) * 2560, 56);
|
|
|
|
g_StaticListInitialized = true;
|
2016-02-09 22:52:33 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CElementGen::CElementGen(const TToken<IGenDescription>& gen) : x1c_genDesc(gen), x230_randState(x74) {}
|
|
|
|
|
2016-02-08 05:10:17 +00:00
|
|
|
CElementGen::CElementGen(const TToken<CGenDescription>& gen,
|
|
|
|
EModelOrientationType orientType,
|
|
|
|
EOptionalSystemFlags flags)
|
2016-02-09 22:52:33 +00:00
|
|
|
: x1c_genDesc(gen), x28_orientType(orientType),
|
2016-02-11 02:36:21 +00:00
|
|
|
x226((flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None), x230_randState(x74)
|
2016-02-09 22:52:33 +00:00
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
|
|
|
CIntElement* pmedElem = desc->x1c_PMED.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (pmedElem)
|
|
|
|
{
|
|
|
|
int pmedVal;
|
2016-02-10 02:00:28 +00:00
|
|
|
pmedElem->GetValue(x50_curFrame, pmedVal);
|
2016-02-09 22:52:33 +00:00
|
|
|
x74 = pmedVal;
|
|
|
|
}
|
2016-02-11 02:36:21 +00:00
|
|
|
x230_randState.SetSeed(x74);
|
2016-02-09 22:52:33 +00:00
|
|
|
++g_ParticleSystemAliveCount;
|
2016-02-11 23:05:42 +00:00
|
|
|
x224_25_LIT_ = desc->x44_29_LIT_;
|
|
|
|
x224_26_AAPH = desc->x44_26_AAPH;
|
|
|
|
x224_27_ZBUF = desc->x44_27_ZBUF;
|
|
|
|
x224_29_MBLR = desc->x44_30_MBLR;
|
2016-02-09 22:52:33 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* mbspElem = desc->x48_MBSP.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (mbspElem)
|
2016-02-10 02:00:28 +00:00
|
|
|
mbspElem->GetValue(x50_curFrame, x228_MBSP);
|
2016-02-09 22:52:33 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
x224_30_VMD1 = desc->x45_26_VMD1;
|
|
|
|
x224_31_VMD2 = desc->x45_27_VMD2;
|
|
|
|
x225_24_VMD3 = desc->x45_28_VMD3;
|
|
|
|
x225_25_VMD4 = desc->x45_29_VMD4;
|
2016-02-09 22:52:33 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* cssdElem = desc->xa0_CSSD.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (cssdElem)
|
|
|
|
cssdElem->GetValue(0, x244_CSSD);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
SChildGeneratorDesc& idts = desc->xa4_IDTS;
|
2016-02-09 22:52:33 +00:00
|
|
|
if (idts.m_found)
|
|
|
|
{
|
|
|
|
int ndsyVal = 1;
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* ndsyElem = desc->xb4_NDSY.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (ndsyElem)
|
|
|
|
ndsyElem->GetValue(0, ndsyVal);
|
2016-02-11 22:38:25 +00:00
|
|
|
x248_finishPartChildren.reserve(ndsyVal + x248_finishPartChildren.size());
|
2016-02-09 22:52:33 +00:00
|
|
|
for (int i=0 ; i<ndsyVal ; ++i)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* chDesc = desc->xa4_IDTS.m_gen.GetObj();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (x226 && chDesc->x45_31_OPTS)
|
|
|
|
break;
|
2016-02-11 23:05:42 +00:00
|
|
|
x248_finishPartChildren.emplace_back(new CElementGen(desc->xa4_IDTS.m_gen,
|
2016-02-09 22:52:33 +00:00
|
|
|
EModelOrientationType::Normal,
|
|
|
|
x226 ? EOptionalSystemFlags::Two : EOptionalSystemFlags::One));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* pisyElem = desc->xc8_PISY.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (pisyElem)
|
|
|
|
{
|
|
|
|
pisyElem->GetValue(0, x25c_PISY);
|
|
|
|
if (x25c_PISY <= 0)
|
|
|
|
x25c_PISY = 1;
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* sisyElem = desc->xcc_SISY.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (sisyElem)
|
|
|
|
pisyElem->GetValue(0, x258_SISY);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* sssdElem = desc->xe4_SSSD.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (sssdElem)
|
|
|
|
sssdElem->GetValue(0, x270_SSSD);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* sspoElem = desc->xe8_SSPO.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (sspoElem)
|
|
|
|
sspoElem->GetValue(0, x274_SSPO);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* sesdElem = desc->xf8_SESD.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (sesdElem)
|
|
|
|
sesdElem->GetValue(0, x290_SESD);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* sepoElem = desc->xfc_SEPO.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (sepoElem)
|
|
|
|
sepoElem->GetValue(0, x294_SEPO);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* psltElem = desc->xc_PSLT.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (psltElem)
|
|
|
|
psltElem->GetValue(0, x214_PSLT);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* psivElem = desc->x0_PSIV.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (psivElem)
|
|
|
|
psivElem->GetValue(0, x218_PSIV);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* maxpElem = desc->x28_MAXP.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (maxpElem)
|
2016-02-10 02:00:28 +00:00
|
|
|
maxpElem->GetValue(x50_curFrame, x70_MAXP);
|
2016-02-09 22:52:33 +00:00
|
|
|
|
|
|
|
x2c_particleLists.reserve(std::min(256, x70_MAXP));
|
|
|
|
if (x28_orientType == EModelOrientationType::One)
|
|
|
|
{
|
|
|
|
x3c_parentMatrices.insert(x3c_parentMatrices.end(), x70_MAXP,
|
|
|
|
Zeus::CMatrix3f::skIdentityMatrix3f);
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
x225_26_LINE = desc->x44_24_LINE;
|
|
|
|
x225_27_FXLL = desc->x44_25_FXLL;
|
2016-02-09 22:52:33 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* pofsElem = desc->x18_POFS.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (pofsElem)
|
|
|
|
pofsElem->GetValue(x50_curFrame, x94_POFS);
|
2016-02-09 22:52:33 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* ltypElem = desc->x100_LTYP.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (ltypElem)
|
|
|
|
{
|
|
|
|
int ltyp;
|
2016-02-10 02:00:28 +00:00
|
|
|
ltypElem->GetValue(x50_curFrame, ltyp);
|
2016-02-09 22:52:33 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* lfotElem = desc->x114_LFOT.get();
|
2016-02-09 22:52:33 +00:00
|
|
|
if (lfotElem)
|
|
|
|
{
|
|
|
|
int lfot;
|
2016-02-10 02:00:28 +00:00
|
|
|
lfotElem->GetValue(x50_curFrame, lfot);
|
2016-02-09 22:52:33 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-02-10 02:00:28 +00:00
|
|
|
void CElementGen::Update(double t)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
CIntElement* pswtElem = desc->x10_PSWT.get();
|
2016-02-10 02:00:28 +00:00
|
|
|
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.",
|
2016-02-11 23:05:42 +00:00
|
|
|
desc, pswt);
|
2016-02-10 02:00:28 +00:00
|
|
|
InternalUpdate(pswt / 60.0);
|
|
|
|
x225_28_warmedUp = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
InternalUpdate(t);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CElementGen::InternalUpdate(double dt)
|
|
|
|
{
|
2016-02-11 02:36:21 +00:00
|
|
|
CGlobalRandom gr(x230_randState);
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
2016-02-10 02:00:28 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* pstsElem = desc->x14_PSTS.get();
|
2016-02-10 02:00:28 +00:00
|
|
|
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)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* mbspElem = desc->x48_MBSP.get();
|
2016-02-10 02:00:28 +00:00
|
|
|
if (mbspElem)
|
|
|
|
mbspElem->GetValue(x50_curFrame, x228_MBSP);
|
|
|
|
}
|
|
|
|
|
|
|
|
int frameUpdateCount = 0;
|
|
|
|
while (t < x58_curSeconds && fabs(t - x58_curSeconds) >= 1 / 60000.0)
|
|
|
|
{
|
2016-02-11 02:36:21 +00:00
|
|
|
x2a8_aabbMin.splat(FLT_MAX);
|
|
|
|
x2b4_aabbMax.splat(FLT_MIN);
|
|
|
|
x2c0_maxSize = 0.f;
|
2016-02-10 02:00:28 +00:00
|
|
|
float grte = 0.f;
|
|
|
|
CParticleGlobals::SetEmitterTime(x50_curFrame);
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* grteElem = desc->x2c_GRTE.get();
|
2016-02-10 02:00:28 +00:00
|
|
|
if (grteElem->GetValue(x50_curFrame, grte))
|
|
|
|
{
|
|
|
|
x2c_particleLists.clear();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
grte = std::max(0.f, grte * x78_generatorRate);
|
2016-02-11 02:36:21 +00:00
|
|
|
x6c_generatorRemainder += grte;
|
|
|
|
int genCount = floorf(x6c_generatorRemainder);
|
|
|
|
x6c_generatorRemainder = x6c_generatorRemainder - genCount;
|
2016-02-10 02:00:28 +00:00
|
|
|
|
2016-02-11 22:38:25 +00:00
|
|
|
if (!x68_particleEmission || x50_curFrame >= x214_PSLT)
|
2016-02-11 02:36:21 +00:00
|
|
|
genCount = 0;
|
2016-02-10 02:00:28 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* maxpElem = desc->x28_MAXP.get();
|
2016-02-10 02:00:28 +00:00
|
|
|
if (maxpElem)
|
|
|
|
maxpElem->GetValue(x50_curFrame, x70_MAXP);
|
|
|
|
|
|
|
|
UpdateExistingParticles();
|
|
|
|
|
|
|
|
CParticleGlobals::SetParticleLifetime(x214_PSLT);
|
|
|
|
bool oldBoolVal = s_inCreateNewParticles;
|
|
|
|
s_inCreateNewParticles = true;
|
2016-02-11 02:36:21 +00:00
|
|
|
CreateNewParticles(genCount);
|
2016-02-10 02:00:28 +00:00
|
|
|
s_inCreateNewParticles = oldBoolVal;
|
|
|
|
|
|
|
|
UpdatePSTranslationAndOrientation();
|
|
|
|
UpdateChildParticleSystems(1 / 60.0);
|
|
|
|
|
|
|
|
if (x2dc_lightType != ELightType::LocalAmbient)
|
|
|
|
UpdateLightParameters();
|
|
|
|
|
|
|
|
++frameUpdateCount;
|
|
|
|
++x50_curFrame;
|
|
|
|
t += 1 / 60.0;
|
|
|
|
}
|
|
|
|
|
2016-02-11 02:36:21 +00:00
|
|
|
UpdateChildParticleSystems(-(frameUpdateCount / 60.0 - dt1));
|
2016-02-10 02:00:28 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2016-02-11 02:36:21 +00:00
|
|
|
void CElementGen::AccumulateBounds(Zeus::CVector3f& pos, float size)
|
|
|
|
{
|
|
|
|
x2b4_aabbMax[0] = std::max(pos[0], x2b4_aabbMax[0]);
|
|
|
|
x2b4_aabbMax[1] = std::max(pos[1], x2b4_aabbMax[1]);
|
|
|
|
x2b4_aabbMax[2] = std::max(pos[2], x2b4_aabbMax[2]);
|
|
|
|
x2a8_aabbMin[0] = std::min(pos[0], x2a8_aabbMin[0]);
|
|
|
|
x2a8_aabbMin[1] = std::min(pos[1], x2a8_aabbMin[1]);
|
|
|
|
x2a8_aabbMin[2] = std::min(pos[2], x2a8_aabbMin[2]);
|
|
|
|
x2c0_maxSize = std::max(size, x2c0_maxSize);
|
|
|
|
}
|
|
|
|
|
2016-02-10 02:00:28 +00:00
|
|
|
void CElementGen::UpdateExistingParticles()
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
2016-02-11 02:36:21 +00:00
|
|
|
x208_activeParticleCount = 0;
|
2016-02-10 02:00:28 +00:00
|
|
|
CParticleGlobals::SetEmitterTime(x50_curFrame);
|
2016-02-11 02:36:21 +00:00
|
|
|
for (std::vector<CParticleListItem>::iterator p = x2c_particleLists.begin();
|
|
|
|
p != x2c_particleLists.end();)
|
|
|
|
{
|
|
|
|
CElementGen::CParticle& particle = g_StaticParticleList[p->x0_partIdx];
|
|
|
|
if (particle.x0_endFrame < x50_curFrame)
|
|
|
|
{
|
|
|
|
--g_ParticleAliveCount;
|
|
|
|
g_StaticFreeList[++g_FreeIndex] = p->x0_partIdx;
|
|
|
|
if (p+1 == x2c_particleLists.end())
|
|
|
|
{
|
|
|
|
x2c_particleLists.pop_back();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*p = *(x2c_particleLists.end()-1);
|
|
|
|
if (x28_orientType == EModelOrientationType::One)
|
|
|
|
{
|
|
|
|
size_t i = p - x2c_particleLists.begin();
|
|
|
|
x3c_parentMatrices[i] = x3c_parentMatrices[x2c_particleLists.size()-1];
|
|
|
|
}
|
|
|
|
x2c_particleLists.pop_back();
|
|
|
|
if (p != x2c_particleLists.end())
|
|
|
|
if (particle.x0_endFrame < x50_curFrame)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
particle.x10_prevPos = particle.x4_pos;
|
|
|
|
particle.x4_pos += particle.x1c_vel;
|
|
|
|
}
|
|
|
|
|
|
|
|
++x208_activeParticleCount;
|
|
|
|
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
|
|
|
|
int particleFrame = x50_curFrame - particle.x28_startFrame;
|
|
|
|
CParticleGlobals::UpdateParticleLifetimeTweenValues(particleFrame);
|
|
|
|
|
2016-02-11 22:38:25 +00:00
|
|
|
bool err = false;
|
2016-02-11 23:05:42 +00:00
|
|
|
CModVectorElement* vel1 = desc->x7c_VEL1.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (vel1)
|
|
|
|
{
|
|
|
|
if (x224_30_VMD1)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f xfVel = x1a8 * particle.x1c_vel;
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f xfPos = x1a8 * (particle.x4_pos - x7c_translation);
|
2016-02-11 02:36:21 +00:00
|
|
|
err = vel1->GetValue(particleFrame, xfVel, xfPos);
|
2016-02-11 22:38:25 +00:00
|
|
|
particle.x1c_vel = x178_orientation * xfVel;
|
|
|
|
particle.x4_pos = x178_orientation * xfPos + x7c_translation;
|
2016-02-11 02:36:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err = vel1->GetValue(particleFrame, particle.x1c_vel, particle.x4_pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CModVectorElement* vel2 = desc->x80_VEL2.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (vel2)
|
|
|
|
{
|
|
|
|
if (x224_31_VMD2)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f xfVel = x1a8 * particle.x1c_vel;
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f xfPos = x1a8 * (particle.x4_pos - x7c_translation);
|
2016-02-11 02:36:21 +00:00
|
|
|
err |= vel2->GetValue(particleFrame, xfVel, xfPos);
|
2016-02-11 22:38:25 +00:00
|
|
|
particle.x1c_vel = x178_orientation * xfVel;
|
|
|
|
particle.x4_pos = x178_orientation * xfPos + x7c_translation;
|
2016-02-11 02:36:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err |= vel2->GetValue(particleFrame, particle.x1c_vel, particle.x4_pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CModVectorElement* vel3 = desc->x84_VEL3.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (vel3)
|
|
|
|
{
|
|
|
|
if (x225_24_VMD3)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f xfVel = x1a8 * particle.x1c_vel;
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f xfPos = x1a8 * (particle.x4_pos - x7c_translation);
|
2016-02-11 02:36:21 +00:00
|
|
|
err |= vel3->GetValue(particleFrame, xfVel, xfPos);
|
2016-02-11 22:38:25 +00:00
|
|
|
particle.x1c_vel = x178_orientation * xfVel;
|
|
|
|
particle.x4_pos = x178_orientation * xfPos + x7c_translation;
|
2016-02-11 02:36:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err |= vel3->GetValue(particleFrame, particle.x1c_vel, particle.x4_pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CModVectorElement* vel4 = desc->x88_VEL4.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (vel4)
|
|
|
|
{
|
|
|
|
if (x225_25_VMD4)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f xfVel = x1a8 * particle.x1c_vel;
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f xfPos = x1a8 * (particle.x4_pos - x7c_translation);
|
2016-02-11 02:36:21 +00:00
|
|
|
err |= vel4->GetValue(particleFrame, xfVel, xfPos);
|
2016-02-11 22:38:25 +00:00
|
|
|
particle.x1c_vel = x178_orientation * xfVel;
|
|
|
|
particle.x4_pos = x178_orientation * xfPos + x7c_translation;
|
2016-02-11 02:36:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
err |= vel4->GetValue(particleFrame, particle.x1c_vel, particle.x4_pos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x225_26_LINE)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* leng = desc->x20_LENG.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (leng)
|
|
|
|
err |= leng->GetValue(particleFrame, particle.x2c_lineLengthOrSize);
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* widt = desc->x24_WIDT.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (widt)
|
|
|
|
err |= widt->GetValue(particleFrame, particle.x30_lineWidthOrRota);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* rota = desc->x50_ROTA.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (rota)
|
|
|
|
err |= rota->GetValue(particleFrame, particle.x30_lineWidthOrRota);
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* size = desc->x4c_SIZE.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (size)
|
|
|
|
err |= size->GetValue(particleFrame, particle.x2c_lineLengthOrSize);
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CColorElement* colr = desc->x30_COLR.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (colr)
|
|
|
|
err |= colr->GetValue(particleFrame, particle.x34_color);
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
particle.x0_endFrame = -1;
|
|
|
|
|
|
|
|
AccumulateBounds(particle.x4_pos, particle.x2c_lineLengthOrSize);
|
|
|
|
++p;
|
|
|
|
}
|
2016-02-10 02:00:28 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 02:36:21 +00:00
|
|
|
void CElementGen::CreateNewParticles(int count)
|
2016-02-10 02:00:28 +00:00
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
2016-02-11 02:36:21 +00:00
|
|
|
if (!g_StaticListInitialized)
|
|
|
|
Initialize();
|
|
|
|
if (x2c_particleLists.size() >= x70_MAXP)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (count + x2c_particleLists.size() > x70_MAXP)
|
|
|
|
count = x70_MAXP - x2c_particleLists.size();
|
|
|
|
CGlobalRandom gr(x230_randState);
|
|
|
|
x2c_particleLists.reserve(x70_MAXP);
|
|
|
|
|
|
|
|
for (int i=0 ; i<count ; ++i)
|
|
|
|
{
|
|
|
|
if (g_FreeIndex < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
s16 staticIdx = g_StaticFreeList[g_FreeIndex];
|
|
|
|
x2c_particleLists.push_back(staticIdx);
|
|
|
|
++x208_activeParticleCount;
|
|
|
|
if (x28_orientType == EModelOrientationType::One)
|
2016-02-11 22:38:25 +00:00
|
|
|
x3c_parentMatrices[x2c_particleLists.size()-1] = x178_orientation.buildMatrix3f();
|
2016-02-11 02:36:21 +00:00
|
|
|
|
|
|
|
CElementGen::CParticle& particle = g_StaticParticleList[staticIdx];
|
|
|
|
particle.x28_startFrame = x50_curFrame;
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* ltme = desc->x34_LTME.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (ltme)
|
|
|
|
ltme->GetValue(0, particle.x0_endFrame);
|
|
|
|
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame);
|
|
|
|
CParticleGlobals::UpdateParticleLifetimeTweenValues(0);
|
|
|
|
particle.x0_endFrame += x50_curFrame;
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CColorElement* colr = desc->x30_COLR.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (colr)
|
|
|
|
colr->GetValue(0, particle.x34_color);
|
|
|
|
else
|
|
|
|
particle.x34_color = Zeus::CColor::skWhite;
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CEmitterElement* emtr = desc->x40_EMTR.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (emtr)
|
|
|
|
{
|
|
|
|
emtr->GetValue(x210_curEmitterFrame, particle.x4_pos, particle.x1c_vel);
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f compXf1 = (xdc * x148) * x7c_translation;
|
|
|
|
Zeus::CVector3f compXf2 = x178_orientation * particle.x4_pos;
|
2016-02-11 02:36:21 +00:00
|
|
|
particle.x4_pos = compXf1 + compXf2 + x94_POFS;
|
2016-02-11 22:38:25 +00:00
|
|
|
particle.x1c_vel = x178_orientation * particle.x1c_vel;
|
2016-02-11 02:36:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f compXf1 = (xdc * x148) * x7c_translation;
|
2016-02-11 02:36:21 +00:00
|
|
|
particle.x4_pos = compXf1 + x94_POFS;
|
|
|
|
particle.x1c_vel.zeroOut();
|
|
|
|
}
|
|
|
|
particle.x10_prevPos = particle.x4_pos;
|
|
|
|
|
|
|
|
if (x225_26_LINE)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* leng = desc->x20_LENG.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (leng)
|
|
|
|
leng->GetValue(0, particle.x2c_lineLengthOrSize);
|
|
|
|
else
|
|
|
|
particle.x2c_lineLengthOrSize = 1.f;
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* widt = desc->x24_WIDT.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (widt)
|
|
|
|
widt->GetValue(0, particle.x30_lineWidthOrRota);
|
|
|
|
else
|
|
|
|
particle.x30_lineWidthOrRota = 1.f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* rota = desc->x50_ROTA.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (rota)
|
|
|
|
rota->GetValue(0, particle.x30_lineWidthOrRota);
|
|
|
|
else
|
|
|
|
particle.x30_lineWidthOrRota = 0.f;
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* size = desc->x4c_SIZE.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (size)
|
|
|
|
size->GetValue(0, particle.x2c_lineLengthOrSize);
|
|
|
|
else
|
|
|
|
particle.x2c_lineLengthOrSize = 0.1f;
|
|
|
|
}
|
|
|
|
|
|
|
|
AccumulateBounds(particle.x4_pos, particle.x2c_lineLengthOrSize);
|
|
|
|
++x210_curEmitterFrame;
|
|
|
|
--g_FreeIndex;
|
|
|
|
}
|
2016-02-10 02:00:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::UpdatePSTranslationAndOrientation()
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
2016-02-11 02:36:21 +00:00
|
|
|
CGlobalRandom gr(x230_randState);
|
|
|
|
if (x214_PSLT < x50_curFrame)
|
|
|
|
return;
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CModVectorElement* psvm = desc->x4_PSVM.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (psvm)
|
|
|
|
{
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f vel = x7c_translation;
|
2016-02-11 02:36:21 +00:00
|
|
|
psvm->GetValue(x50_curFrame, x218_PSIV, vel);
|
2016-02-11 22:38:25 +00:00
|
|
|
if (vel != x7c_translation)
|
2016-02-11 02:36:21 +00:00
|
|
|
{
|
|
|
|
x224_24 = true;
|
2016-02-11 22:38:25 +00:00
|
|
|
x7c_translation = vel;
|
2016-02-11 02:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CVector3f v = x178_orientation * x218_PSIV;
|
2016-02-11 02:36:21 +00:00
|
|
|
if (v != Zeus::CVector3f::skZero)
|
|
|
|
x224_24 = true;
|
2016-02-11 22:38:25 +00:00
|
|
|
x7c_translation += v;
|
2016-02-11 02:36:21 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* psov = desc->x8_PSOV.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (psov)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f angles;
|
|
|
|
psov->GetValue(x50_curFrame, angles);
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CTransform xf(x178_orientation);
|
2016-02-11 02:36:21 +00:00
|
|
|
xf.rotateLocalX(angles[0] * M_PI / 180.f);
|
|
|
|
xf.rotateLocalY(angles[1] * M_PI / 180.f);
|
|
|
|
xf.rotateLocalZ(angles[2] * M_PI / 180.f);
|
|
|
|
SetOrientation(xf);
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* pofs = desc->x18_POFS.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (pofs)
|
|
|
|
pofs->GetValue(x50_curFrame, x94_POFS);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* sspo = desc->xe8_SSPO.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (sspo)
|
|
|
|
sspo->GetValue(x50_curFrame, x274_SSPO);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* sepo = desc->xfc_SEPO.get();
|
2016-02-11 02:36:21 +00:00
|
|
|
if (sepo)
|
|
|
|
sspo->GetValue(x50_curFrame, x294_SEPO);
|
2016-02-10 02:00:28 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 06:58:33 +00:00
|
|
|
CElementGen* CElementGen::ConstructChildParticleSystem(const TToken<CGenDescription>& desc)
|
|
|
|
{
|
2016-02-11 22:38:25 +00:00
|
|
|
CElementGen* ret = new CElementGen(desc, EModelOrientationType::Normal,
|
|
|
|
x226 ? EOptionalSystemFlags::Two : EOptionalSystemFlags::One);
|
|
|
|
ret->SetGlobalTranslation(x88_globalTranslation);
|
|
|
|
ret->SetGlobalOrientation(x1d8_globalOrientation);
|
|
|
|
ret->SetGlobalScale(xa0_globalScale);
|
|
|
|
ret->SetLocalScale(x10c_localScale);
|
|
|
|
ret->SetTranslation(x7c_translation);
|
|
|
|
ret->SetOrientation(x178_orientation);
|
|
|
|
ret->SetParticleEmission(x68_particleEmission);
|
|
|
|
ret->SetModulationColor(x30c_moduColor);
|
|
|
|
return ret;
|
2016-02-11 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2016-02-10 02:00:28 +00:00
|
|
|
void CElementGen::UpdateChildParticleSystems(double dt)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
2016-02-11 06:58:33 +00:00
|
|
|
CGlobalRandom gr(x230_randState);
|
2016-02-11 23:05:42 +00:00
|
|
|
SChildGeneratorDesc& icts = desc->x8c_ICTS;
|
2016-02-11 22:38:25 +00:00
|
|
|
if (icts.m_found && x64_prevFrame != x50_curFrame && x244_CSSD == x50_curFrame)
|
2016-02-11 06:58:33 +00:00
|
|
|
{
|
|
|
|
int ncsyVal = 1;
|
2016-02-11 23:05:42 +00:00
|
|
|
CIntElement* ncsy = desc->x9c_NCSY.get();
|
2016-02-11 06:58:33 +00:00
|
|
|
if (ncsy)
|
|
|
|
ncsy->GetValue(x50_curFrame, ncsyVal);
|
|
|
|
|
|
|
|
CGenDescription* ictsDesc = icts.m_gen.GetObj();
|
|
|
|
if (!(x226 && ictsDesc->x45_31_OPTS))
|
|
|
|
{
|
2016-02-11 22:38:25 +00:00
|
|
|
x234_activePartChildren.reserve(ncsyVal + x234_activePartChildren.size());
|
2016-02-11 06:58:33 +00:00
|
|
|
for (int i=0 ; i<ncsyVal ; ++i)
|
|
|
|
{
|
|
|
|
CElementGen* chGen = ConstructChildParticleSystem(icts.m_gen);
|
2016-02-11 22:38:25 +00:00
|
|
|
x234_activePartChildren.emplace_back(chGen);
|
2016-02-11 06:58:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
SChildGeneratorDesc& iits = desc->xb8_IITS;
|
2016-02-11 22:38:25 +00:00
|
|
|
if (iits.m_found && x64_prevFrame != x50_curFrame && x50_curFrame < x214_PSLT &&
|
2016-02-11 06:58:33 +00:00
|
|
|
x68_particleEmission == 1 && x50_curFrame >= x258_SISY &&
|
|
|
|
((x50_curFrame - x258_SISY) % x25c_PISY) == 0)
|
|
|
|
{
|
|
|
|
CGenDescription* iitsDesc = iits.m_gen.GetObj();
|
|
|
|
if (!(x226 && iitsDesc->x45_31_OPTS))
|
|
|
|
{
|
|
|
|
CElementGen* chGen = ConstructChildParticleSystem(iits.m_gen);
|
2016-02-11 22:38:25 +00:00
|
|
|
x234_activePartChildren.emplace_back(chGen);
|
2016-02-11 06:58:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CSpawnSystemKeyframeData* kssm = desc->xd0_KSSM.get();
|
2016-02-11 22:38:25 +00:00
|
|
|
if (kssm && x64_prevFrame != x50_curFrame && x50_curFrame < x214_PSLT)
|
|
|
|
{
|
|
|
|
std::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo>& systems =
|
|
|
|
kssm->GetSpawnedSystemsAtFrame(x50_curFrame);
|
|
|
|
x234_activePartChildren.reserve(x234_activePartChildren.size() + systems.size());
|
|
|
|
for (CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo& system : systems)
|
|
|
|
{
|
|
|
|
TLockedToken<CGenDescription>& token = system.GetToken();
|
|
|
|
if (!(x226 && token.GetObj()->x45_31_OPTS))
|
|
|
|
{
|
|
|
|
CElementGen* chGen = ConstructChildParticleSystem(token);
|
|
|
|
x234_activePartChildren.emplace_back(chGen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
SSwooshGeneratorDesc& sswh = desc->xd4_SSWH;
|
2016-02-11 22:38:25 +00:00
|
|
|
if (sswh.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x270_SSSD)
|
|
|
|
{
|
|
|
|
CParticleSwoosh* sswhGen = new CParticleSwoosh(sswh.m_swoosh, 0);
|
|
|
|
sswhGen->SetGlobalTranslation(x88_globalTranslation);
|
|
|
|
sswhGen->SetGlobalScale(xa0_globalScale);
|
|
|
|
sswhGen->SetTranslation(x7c_translation);
|
|
|
|
sswhGen->SetOrientation(x178_orientation);
|
|
|
|
sswhGen->SetParticleEmission(x68_particleEmission);
|
|
|
|
x260_swhcChildren.emplace_back(sswhGen);
|
|
|
|
}
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
SElectricGeneratorDesc& selc = desc->xec_SELC;
|
2016-02-11 22:38:25 +00:00
|
|
|
if (selc.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x290_SESD)
|
|
|
|
{
|
|
|
|
CParticleElectric* selcGen = new CParticleElectric(selc.m_electric);
|
|
|
|
selcGen->SetGlobalTranslation(x88_globalTranslation);
|
|
|
|
selcGen->SetGlobalScale(xa0_globalScale);
|
|
|
|
selcGen->SetTranslation(x7c_translation);
|
|
|
|
selcGen->SetOrientation(x178_orientation);
|
|
|
|
selcGen->SetParticleEmission(x68_particleEmission);
|
|
|
|
x280_elscChildren.emplace_back(selcGen);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto p = x234_activePartChildren.begin() ; p != x234_activePartChildren.end() ;)
|
|
|
|
{
|
|
|
|
std::unique_ptr<CElementGen>& ch = *p;
|
|
|
|
|
|
|
|
if ((x50_curFrame == x4c || x224_24) && x64_prevFrame != x50_curFrame)
|
|
|
|
{
|
|
|
|
ch->SetTranslation(x7c_translation);
|
|
|
|
ch->SetOrientation(x178_orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
ch->Update(dt);
|
|
|
|
if (ch->IsSystemDeletable())
|
|
|
|
{
|
|
|
|
p = x234_activePartChildren.erase(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto p = x248_finishPartChildren.begin() ; p != x248_finishPartChildren.end() ;)
|
|
|
|
{
|
|
|
|
std::unique_ptr<CElementGen>& ch = *p;
|
|
|
|
|
|
|
|
if (x214_PSLT <= x50_curFrame)
|
|
|
|
{
|
|
|
|
if (x214_PSLT == x50_curFrame && x64_prevFrame != x50_curFrame)
|
|
|
|
{
|
|
|
|
ch->SetTranslation(x7c_translation);
|
|
|
|
ch->SetOrientation(x178_orientation);
|
|
|
|
}
|
|
|
|
ch->Update(dt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ch->IsSystemDeletable())
|
|
|
|
{
|
|
|
|
p = x248_finishPartChildren.erase(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto p = x260_swhcChildren.begin() ; p != x260_swhcChildren.end() ;)
|
|
|
|
{
|
|
|
|
std::unique_ptr<CParticleSwoosh>& ch = *p;
|
|
|
|
|
|
|
|
if ((x50_curFrame == x270_SSSD || x224_24) && x64_prevFrame != x50_curFrame)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f trans = x7c_translation + x274_SSPO;
|
|
|
|
ch->SetTranslation(trans);
|
|
|
|
ch->SetOrientation(x178_orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
ch->Update(dt);
|
|
|
|
if (ch->IsSystemDeletable())
|
|
|
|
{
|
|
|
|
p = x260_swhcChildren.erase(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++p;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto p = x280_elscChildren.begin() ; p != x280_elscChildren.end() ;)
|
2016-02-11 06:58:33 +00:00
|
|
|
{
|
2016-02-11 22:38:25 +00:00
|
|
|
std::unique_ptr<CParticleElectric>& ch = *p;
|
|
|
|
|
|
|
|
if ((x50_curFrame == x290_SESD || x224_24) && x64_prevFrame != x50_curFrame)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f trans = x7c_translation + x294_SEPO;
|
|
|
|
ch->SetTranslation(trans);
|
|
|
|
ch->SetOrientation(x178_orientation);
|
|
|
|
}
|
|
|
|
|
|
|
|
ch->Update(dt);
|
|
|
|
if (ch->IsSystemDeletable())
|
|
|
|
{
|
|
|
|
p = x280_elscChildren.erase(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
++p;
|
2016-02-11 06:58:33 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 22:38:25 +00:00
|
|
|
x64_prevFrame = x50_curFrame;
|
2016-02-10 02:00:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::UpdateLightParameters()
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
|
|
|
CColorElement* lclr = desc->x104_LCLR.get();
|
2016-02-11 22:38:25 +00:00
|
|
|
if (lclr)
|
|
|
|
lclr->GetValue(x50_curFrame, x2e0_LCLR);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* lint = desc->x108_LINT.get();
|
2016-02-11 22:38:25 +00:00
|
|
|
if (lint)
|
|
|
|
lint->GetValue(x50_curFrame, x2e4_LINT);
|
|
|
|
|
|
|
|
switch (x2dc_lightType)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case ELightType::LocalAmbient:
|
|
|
|
case ELightType::Directional:
|
|
|
|
case ELightType::Spot:
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* loff = desc->x10c_LOFF.get();
|
2016-02-11 22:38:25 +00:00
|
|
|
if (loff)
|
|
|
|
loff->GetValue(x50_curFrame, x2e8_LOFF);
|
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* lfor = desc->x118_LFOR.get();
|
2016-02-11 22:38:25 +00:00
|
|
|
if (lfor)
|
|
|
|
lfor->GetValue(x50_curFrame, x304_LFOR);
|
|
|
|
|
|
|
|
if (x2dc_lightType == ELightType::Spot)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CRealElement* lsla = desc->x11c_LSLA.get();
|
2016-02-11 22:38:25 +00:00
|
|
|
if (lsla)
|
|
|
|
lsla->GetValue(x50_curFrame, x308_LSLA);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case ELightType::Custom:
|
|
|
|
{
|
|
|
|
if (x2dc_lightType != ELightType::Directional)
|
|
|
|
{
|
2016-02-11 23:05:42 +00:00
|
|
|
CVectorElement* ldir = desc->x110_LDIR.get();
|
2016-02-11 22:38:25 +00:00
|
|
|
if (ldir)
|
|
|
|
ldir->GetValue(x50_curFrame, x2f4_LDIR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 CElementGen::GetParticleCountAllInternal() const
|
|
|
|
{
|
|
|
|
u32 ret = x208_activeParticleCount;
|
|
|
|
|
|
|
|
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren)
|
|
|
|
ret += ch->GetParticleCountAll();
|
|
|
|
|
|
|
|
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
|
|
|
|
ret += ch->GetParticleCountAll();
|
|
|
|
|
|
|
|
return ret;
|
2016-02-10 02:00:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::BuildParticleSystemBounds()
|
2016-02-09 22:52:33 +00:00
|
|
|
{
|
2016-02-11 22:38:25 +00:00
|
|
|
Zeus::CAABox aabb;
|
|
|
|
bool accumulated = false;
|
|
|
|
|
|
|
|
for (std::unique_ptr<CElementGen>& ch : x234_activePartChildren)
|
|
|
|
{
|
|
|
|
std::pair<Zeus::CAABox, bool> chBounds = ch->GetBounds();
|
|
|
|
if (chBounds.second)
|
|
|
|
{
|
|
|
|
accumulated = true;
|
|
|
|
aabb.accumulateBounds(chBounds.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
|
|
|
|
{
|
|
|
|
std::pair<Zeus::CAABox, bool> chBounds = ch->GetBounds();
|
|
|
|
if (chBounds.second)
|
|
|
|
{
|
|
|
|
accumulated = true;
|
|
|
|
aabb.accumulateBounds(chBounds.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (std::unique_ptr<CParticleSwoosh>& ch : x260_swhcChildren)
|
|
|
|
{
|
|
|
|
std::pair<Zeus::CAABox, bool> chBounds = ch->GetBounds();
|
|
|
|
if (chBounds.second)
|
|
|
|
{
|
|
|
|
accumulated = true;
|
|
|
|
aabb.accumulateBounds(chBounds.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (std::unique_ptr<CParticleElectric>& ch : x280_elscChildren)
|
|
|
|
{
|
|
|
|
std::pair<Zeus::CAABox, bool> chBounds = ch->GetBounds();
|
|
|
|
if (chBounds.second)
|
|
|
|
{
|
|
|
|
accumulated = true;
|
|
|
|
aabb.accumulateBounds(chBounds.first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
x20c_recursiveParticleCount = GetParticleCountAllInternal();
|
|
|
|
if (GetParticleCount())
|
|
|
|
{
|
|
|
|
Zeus::CVector3f scale = xa0_globalScale * x2c0_maxSize;
|
|
|
|
Zeus::CTransform xf = (xac * x1d8_globalOrientation) * x118;
|
|
|
|
Zeus::CAABox box = Zeus::CAABox(x2a8_aabbMin, x2b4_aabbMax).getTransformedAABox(xf);
|
|
|
|
Zeus::CVector3f min = box.m_min + x88_globalTranslation - scale;
|
|
|
|
Zeus::CVector3f max = box.m_max + x88_globalTranslation + scale;
|
|
|
|
x2c4_systemBounds = Zeus::CAABox(min, max);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
x2c4_systemBounds = Zeus::CAABox::skInvertedBox;
|
|
|
|
|
|
|
|
if (accumulated)
|
|
|
|
x2c4_systemBounds.accumulateBounds(aabb);
|
2016-02-09 22:52:33 +00:00
|
|
|
}
|
|
|
|
|
2016-02-11 19:18:14 +00:00
|
|
|
u32 CElementGen::GetSystemCount()
|
|
|
|
{
|
|
|
|
u32 ret = 0;
|
2016-02-11 23:05:42 +00:00
|
|
|
for (const std::unique_ptr<CElementGen>& child : x234_activePartChildren)
|
|
|
|
ret += child->GetSystemCount();
|
2016-02-11 19:18:14 +00:00
|
|
|
|
2016-02-11 23:05:42 +00:00
|
|
|
for (const std::unique_ptr<CElementGen>& child : x248_finishPartChildren)
|
|
|
|
ret += child->GetSystemCount();
|
2016-02-11 19:18:14 +00:00
|
|
|
|
|
|
|
return (ret + (x208_activeParticleCount != 0));
|
|
|
|
}
|
|
|
|
|
2016-02-09 22:52:33 +00:00
|
|
|
void CElementGen::Render()
|
2016-02-12 02:36:34 +00:00
|
|
|
{
|
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
|
|
|
x22c_backupLightActive = CGraphics::g_LightActive;
|
|
|
|
CGraphics::DisableAllLights();
|
|
|
|
|
|
|
|
for (std::unique_ptr<CElementGen>& child : x234_activePartChildren)
|
|
|
|
child->Render();
|
|
|
|
|
|
|
|
if (x214_PSLT <= x50_curFrame)
|
|
|
|
for (std::unique_ptr<CElementGen>& child : x248_finishPartChildren)
|
|
|
|
child->Render();
|
|
|
|
|
|
|
|
for (std::unique_ptr<CParticleSwoosh>& child : x260_swhcChildren)
|
|
|
|
child->Render();
|
|
|
|
|
|
|
|
for (std::unique_ptr<CParticleElectric>& child : x280_elscChildren)
|
|
|
|
child->Render();
|
|
|
|
|
|
|
|
if (x2c_particleLists.size())
|
|
|
|
{
|
|
|
|
SParticleModel& pmdl = desc->x5c_PMDL;
|
|
|
|
if (pmdl.m_found || desc->x45_24_PMUS)
|
|
|
|
RenderModels();
|
|
|
|
|
|
|
|
if (x225_26_LINE)
|
|
|
|
RenderLines();
|
|
|
|
else
|
|
|
|
RenderParticles();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::RenderModels()
|
|
|
|
{
|
2016-02-13 00:57:09 +00:00
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
|
|
|
|
if (x225_29_modelsUseLights)
|
|
|
|
CGraphics::SetLightState(x22c_backupLightActive);
|
|
|
|
CGlobalRandom gr(x230_randState);
|
|
|
|
|
|
|
|
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
|
|
|
|
CUVElement* texr = desc->x54_TEXR.get();
|
|
|
|
CTexture* cachedTex = nullptr;
|
|
|
|
bool texConst = true;
|
|
|
|
bool moveRedToAlphaBuffer = false;
|
|
|
|
|
|
|
|
if (desc->x45_24_PMUS)
|
|
|
|
{
|
|
|
|
if (g_MoveRedToAlphaBuffer && desc->x44_31_PMAB && desc->x54_TEXR)
|
|
|
|
moveRedToAlphaBuffer = true;
|
|
|
|
|
|
|
|
if (desc->x44_31_PMAB)
|
|
|
|
{
|
|
|
|
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, false);
|
|
|
|
if (moveRedToAlphaBuffer)
|
|
|
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
|
|
|
|
else
|
|
|
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CGraphics::SetDepthWriteMode(true, ERglEnum::LEqual, true);
|
|
|
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear);
|
|
|
|
}
|
2016-02-12 02:36:34 +00:00
|
|
|
|
2016-02-13 00:57:09 +00:00
|
|
|
CGraphics::SetCullMode(ERglCullMode::None);
|
|
|
|
|
|
|
|
if (texr)
|
|
|
|
{
|
|
|
|
CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx];
|
|
|
|
int partFrame = x50_curFrame - target.x28_startFrame;
|
|
|
|
cachedTex = texr->GetValueTexture(partFrame).GetObj();
|
|
|
|
cachedTex->Load(0, CTexture::EClampMode::One);
|
|
|
|
/* Shade as TEXC * RASC and TEXA * RASA */
|
|
|
|
if (moveRedToAlphaBuffer)
|
|
|
|
{
|
|
|
|
/* Color = Prev.rgb * Prev.a */
|
|
|
|
/* Alpha = Tex.r * Prev.a */
|
|
|
|
}
|
|
|
|
texConst = texr->HasConstantTexture();
|
|
|
|
texr->GetValueUV(partFrame, uvs);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Zeus::CTransform orient = Zeus::CTransform::Identity();
|
|
|
|
if (desc->x45_25_PMOO)
|
|
|
|
orient = x178_orientation;
|
|
|
|
orient = orient * x1d8_globalOrientation;
|
|
|
|
|
|
|
|
CVectorElement* pmrt = desc->x70_PMRT.get();
|
|
|
|
bool pmrtConst = false;
|
|
|
|
if (pmrt)
|
|
|
|
pmrtConst = pmrt->IsFastConstant();
|
|
|
|
|
|
|
|
Zeus::CVector3f trans = (xdc * x148) * x88_globalTranslation;
|
|
|
|
|
|
|
|
Zeus::CTransform rot = Zeus::CTransform::Identity();
|
|
|
|
if (pmrtConst)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f pmrtVal;
|
|
|
|
pmrt->GetValue(x50_curFrame, pmrtVal);
|
|
|
|
rot = Zeus::CTransform::RotateZ(pmrtVal[2] * M_PI / 180.f);
|
|
|
|
rot.rotateLocalY(pmrtVal[1] * M_PI / 180.f);
|
|
|
|
rot.rotateLocalX(pmrtVal[0] * M_PI / 180.f);
|
|
|
|
}
|
|
|
|
rot = orient * rot;
|
|
|
|
|
|
|
|
CParticleGlobals::SetEmitterTime(x50_curFrame);
|
|
|
|
Zeus::CColor col = {1.f, 1.f, 1.f, 1.f};
|
|
|
|
|
|
|
|
Zeus::CVector3f pmopVec;
|
|
|
|
auto matrixIt = x3c_parentMatrices.begin();
|
|
|
|
for (CParticleListItem& item : x2c_particleLists)
|
|
|
|
{
|
|
|
|
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
|
|
|
|
if (particle.x0_endFrame == -1)
|
|
|
|
{
|
|
|
|
++matrixIt;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
|
|
|
|
int partFrame = x50_curFrame - particle.x28_startFrame - 1;
|
|
|
|
CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame);
|
|
|
|
CVectorElement* pmop = desc->x6c_PMOP.get();
|
|
|
|
if (pmop)
|
|
|
|
pmop->GetValue(partFrame, pmopVec);
|
|
|
|
|
|
|
|
Zeus::CTransform partTrans = Zeus::CTransform::Translate(particle.x4_pos + trans);
|
|
|
|
if (x28_orientType == EModelOrientationType::One)
|
|
|
|
{
|
|
|
|
Zeus::CTransform partRot(*matrixIt);
|
|
|
|
Zeus::CVector3f pmopRotateOffset = (orient * partRot) * pmopVec;
|
|
|
|
partTrans = partTrans * partRot;
|
|
|
|
partTrans += pmopRotateOffset;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
partTrans += orient * pmopVec;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pmrtConst)
|
|
|
|
{
|
|
|
|
partTrans = partTrans * rot;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (pmrt)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f pmrtVal;
|
|
|
|
pmrt->GetValue(partFrame, pmrtVal);
|
|
|
|
rot = Zeus::CTransform::RotateZ(pmrtVal[2] * M_PI / 180.f);
|
|
|
|
rot.rotateLocalY(pmrtVal[1] * M_PI / 180.f);
|
|
|
|
rot.rotateLocalX(pmrtVal[0] * M_PI / 180.f);
|
|
|
|
partTrans = partTrans * (orient * rot);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
partTrans = partTrans * rot;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CVectorElement* pmsc = desc->x74_PMSC.get();
|
|
|
|
if (pmsc)
|
|
|
|
{
|
|
|
|
Zeus::CVector3f pmscVal;
|
|
|
|
pmsc->GetValue(partFrame, pmscVal);
|
|
|
|
partTrans = partTrans * Zeus::CTransform::Scale(pmscVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
CColorElement* pmcl = desc->x78_PMCL.get();
|
|
|
|
if (pmcl)
|
|
|
|
pmcl->GetValue(partFrame, col);
|
|
|
|
|
|
|
|
CGraphics::SetModelMatrix((xac * partTrans) * x118);
|
|
|
|
|
|
|
|
if (desc->x45_24_PMUS)
|
|
|
|
{
|
|
|
|
if (!texConst)
|
|
|
|
{
|
|
|
|
CTexture* tex = texr->GetValueTexture(x50_curFrame - particle.x28_startFrame).GetObj();
|
|
|
|
if (tex != cachedTex)
|
|
|
|
{
|
|
|
|
tex->Load(0, CTexture::EClampMode::One);
|
|
|
|
cachedTex = tex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Draw: */
|
|
|
|
/* Pos: {0.5, 0.0, 0.5} Color: <col-variable> UV0: {uv[2], uv[3]} */
|
|
|
|
/* Pos: {-0.5, 0.0, 0.5} Color: <col-variable> UV0: {uv[0], uv[3]} */
|
|
|
|
/* Pos: {-0.5, 0.0, -0.5} Color: <col-variable> UV0: {uv[0], uv[1]} */
|
|
|
|
/* Pos: {0.5, 0.0, -0.5} Color: <col-variable> UV0: {uv[2], uv[1]} */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CModel* model = desc->x5c_PMDL.m_model.GetObj();
|
|
|
|
if (desc->x44_31_PMAB)
|
|
|
|
{
|
|
|
|
model->Draw({3, 0, 1, col});
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (1.f == col.a)
|
|
|
|
model->Draw({0, 0, 3, Zeus::CColor::skWhite});
|
|
|
|
else
|
|
|
|
model->Draw({4, 0, 1, col});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
++matrixIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x225_29_modelsUseLights)
|
|
|
|
CGraphics::DisableAllLights();
|
|
|
|
|
|
|
|
CGraphics::SetCullMode(ERglCullMode::Front);
|
|
|
|
if (moveRedToAlphaBuffer)
|
|
|
|
{
|
|
|
|
/* Restore passthrough */
|
|
|
|
}
|
2016-02-12 02:36:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::RenderLines()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::RenderParticles()
|
2016-02-13 00:57:09 +00:00
|
|
|
{
|
|
|
|
CGenDescription* desc = x1c_genDesc.CastObj<CGenDescription>();
|
|
|
|
CGlobalRandom gr(x230_randState);
|
|
|
|
|
|
|
|
CUVElement* texr = desc->x54_TEXR.get();
|
|
|
|
CUVElement* tind = desc->x58_TIND.get();
|
|
|
|
if (texr && tind)
|
|
|
|
{
|
|
|
|
RenderParticlesIndirectTexture();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CRealElement* size = desc->x4c_SIZE.get();
|
|
|
|
if (size && size->IsConstant())
|
|
|
|
{
|
|
|
|
float sizeVal;
|
|
|
|
size->GetValue(0, sizeVal);
|
|
|
|
if (sizeVal == 0.f)
|
|
|
|
{
|
|
|
|
size->GetValue(1, sizeVal);
|
|
|
|
if (sizeVal == 0.f)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Zeus::CTransform xf(CGraphics::g_ViewMatrix);
|
|
|
|
Zeus::CTransform xf2 = xf.inverse() * x1d8_globalOrientation;
|
|
|
|
|
|
|
|
xf = ((Zeus::CTransform::Translate(x88_globalTranslation) * xac) * xf) * x118;
|
|
|
|
CGraphics::SetModelMatrix(xf);
|
|
|
|
CGraphics::SetAlphaCompare(ERglAlphaFunc::Always, 0, ERglAlphaOp::And, ERglAlphaFunc::Always, 0);
|
|
|
|
|
|
|
|
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
|
|
|
|
bool constTexr = true;
|
|
|
|
bool constUVs = true;
|
|
|
|
CTexture* cachedTex = nullptr;
|
|
|
|
|
|
|
|
if (texr)
|
|
|
|
{
|
|
|
|
CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx];
|
|
|
|
int partFrame = x50_curFrame - target.x28_startFrame;
|
|
|
|
cachedTex = texr->GetValueTexture(partFrame).GetObj();
|
|
|
|
cachedTex->Load(0, CTexture::EClampMode::One);
|
|
|
|
|
|
|
|
if (x30c_moduColor != Zeus::CColor::skBlack)
|
|
|
|
{
|
|
|
|
/* Add RASC * PREVC pass for MODU color loaded into channel mat-color */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Pass-thru */
|
|
|
|
}
|
|
|
|
|
|
|
|
constTexr = texr->HasConstantTexture();
|
|
|
|
texr->GetValueUV(partFrame, uvs);
|
|
|
|
constUVs = texr->HasConstantUV();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Pass-thru */
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desc->x44_28_SORT)
|
|
|
|
{
|
|
|
|
for (CParticleListItem& item : x2c_particleLists)
|
|
|
|
{
|
|
|
|
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
|
|
|
|
item.x4_viewPoint = xf2 * ((particle.x4_pos - particle.x10_prevPos) * x60 + particle.x10_prevPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::sort(x2c_particleLists.begin(), x2c_particleLists.end(),
|
|
|
|
[](const CParticleListItem& a, const CParticleListItem& b) -> bool
|
|
|
|
{return a.x4_viewPoint[1] >= b.x4_viewPoint[1];});
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
bool done = false;
|
|
|
|
while (!done)
|
|
|
|
{
|
|
|
|
done = true;
|
|
|
|
for (int i=0 ; i<x2c_particleLists.size()-1 ; ++i)
|
|
|
|
{
|
|
|
|
CParticleListItem& p1 = x2c_particleLists[i];
|
|
|
|
CParticleListItem& p2 = x2c_particleLists[i+1];
|
|
|
|
if (p1.x4_viewPoint[1] < p2.x4_viewPoint[1])
|
|
|
|
{
|
|
|
|
CParticleListItem tmp = p2;
|
|
|
|
p2 = p1;
|
|
|
|
p1 = tmp;
|
|
|
|
done = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (x30c_moduColor != Zeus::CColor::skBlack)
|
|
|
|
{
|
|
|
|
/* Load mat-color here */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Pass-thru */
|
|
|
|
}
|
|
|
|
|
|
|
|
bool moveRedToAlphaBuffer = false;
|
|
|
|
if (g_MoveRedToAlphaBuffer && x224_26_AAPH)
|
|
|
|
moveRedToAlphaBuffer = true;
|
|
|
|
|
|
|
|
if (moveRedToAlphaBuffer)
|
|
|
|
{
|
|
|
|
CGraphics::SetDepthWriteMode(x224_28_zTest, ERglEnum::LEqual, false);
|
|
|
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
|
|
|
|
/* Color = Prev.rgb * Prev.a */
|
|
|
|
/* Alpha = Tex.r * Prev.a */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (x224_26_AAPH)
|
|
|
|
{
|
|
|
|
CGraphics::SetDepthWriteMode(x224_28_zTest, ERglEnum::LEqual, false);
|
|
|
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CGraphics::SetDepthWriteMode(x224_28_zTest, ERglEnum::LEqual, x224_27_ZBUF);
|
|
|
|
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int mbspVal = std::max(1, x228_MBSP);
|
|
|
|
if (!x224_29_MBLR)
|
|
|
|
{
|
|
|
|
/* Begin quad draw of x2c_particleLists.size() * 4 verts */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Begin quad draw of x2c_particleLists.size() * 4 * mbspVal verts */
|
|
|
|
}
|
|
|
|
|
|
|
|
CParticleGlobals::SetEmitterTime(x50_curFrame);
|
|
|
|
if (!x224_29_MBLR)
|
|
|
|
{
|
|
|
|
for (CParticleListItem& item : x2c_particleLists)
|
|
|
|
{
|
|
|
|
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
|
|
|
|
int partFrame = x50_curFrame - particle.x28_startFrame - 1;
|
|
|
|
Zeus::CVector3f viewPoint;
|
|
|
|
if (desc->x44_28_SORT)
|
|
|
|
viewPoint = item.x4_viewPoint;
|
|
|
|
else
|
|
|
|
viewPoint = xf2 * ((particle.x4_pos - particle.x10_prevPos) * x60 + particle.x10_prevPos);
|
|
|
|
|
|
|
|
if (!constTexr)
|
|
|
|
{
|
|
|
|
CTexture* tex = texr->GetValueTexture(partFrame).GetObj();
|
|
|
|
if (tex != cachedTex)
|
|
|
|
{
|
|
|
|
tex->Load(0, CTexture::EClampMode::One);
|
|
|
|
cachedTex = tex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!constUVs)
|
|
|
|
{
|
|
|
|
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
|
|
|
|
CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame);
|
|
|
|
texr->GetValueUV(partFrame, uvs);
|
|
|
|
}
|
|
|
|
|
|
|
|
float size = 0.5f * particle.x2c_lineLengthOrSize;
|
|
|
|
if (0.f == particle.x30_lineWidthOrRota)
|
|
|
|
{
|
|
|
|
/* Draw: */
|
|
|
|
/* Pos: {viewPoint.x + size, 0.0, viewPoint.z + size} Color: particle.color UV0: {uv[2], uv[3]} */
|
|
|
|
/* Pos: {viewPoint.x - size, 0.0, viewPoint.z + size} Color: particle.color UV0: {uv[0], uv[3]} */
|
|
|
|
/* Pos: {viewPoint.x - size, 0.0, viewPoint.z - size} Color: particle.color UV0: {uv[0], uv[1]} */
|
|
|
|
/* Pos: {viewPoint.x + size, 0.0, viewPoint.z - size} Color: particle.color UV0: {uv[2], uv[1]} */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float theta = particle.x30_lineWidthOrRota * M_PI / 180.f;
|
|
|
|
float sinT = sinf(theta) * size;
|
|
|
|
float cosT = sinf(theta) * size;
|
|
|
|
|
|
|
|
/* Draw:
|
|
|
|
viewPoint.x + sinT + cosT;
|
|
|
|
0.f;
|
|
|
|
viewPoint.z + cosT - sinT;
|
|
|
|
|
|
|
|
viewPoint.x + sinT - cosT;
|
|
|
|
0.f;
|
|
|
|
viewPoint.z + sinT + cosT;
|
|
|
|
|
|
|
|
viewPoint.x - (sinT + cosT);
|
|
|
|
0.f;
|
|
|
|
viewPoint.z - (cosT - sinT);
|
|
|
|
|
|
|
|
viewPoint.x + (cosT - sinT);
|
|
|
|
0.f;
|
|
|
|
viewPoint.z + (-cosT - sinT);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float mbspFac = 1.f / float(mbspVal);
|
|
|
|
for (CParticleListItem& item : x2c_particleLists)
|
|
|
|
{
|
|
|
|
CParticle& particle = g_StaticParticleList[item.x0_partIdx];
|
|
|
|
int partFrame = x50_curFrame - particle.x28_startFrame - 1;
|
|
|
|
|
|
|
|
if (!constTexr)
|
|
|
|
{
|
|
|
|
CTexture* tex = texr->GetValueTexture(partFrame).GetObj();
|
|
|
|
if (tex != cachedTex)
|
|
|
|
{
|
|
|
|
tex->Load(0, CTexture::EClampMode::One);
|
|
|
|
cachedTex = tex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!constUVs)
|
|
|
|
{
|
|
|
|
CParticleGlobals::SetParticleLifetime(particle.x0_endFrame - particle.x28_startFrame);
|
|
|
|
CParticleGlobals::UpdateParticleLifetimeTweenValues(partFrame);
|
|
|
|
texr->GetValueUV(partFrame, uvs);
|
|
|
|
}
|
|
|
|
|
|
|
|
Zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos;
|
|
|
|
Zeus::CVector3f vec = dVec * x60 + particle.x10_prevPos;
|
|
|
|
Zeus::CVector3f mbspVec = dVec * mbspFac;
|
|
|
|
float size = 0.5f * particle.x2c_lineLengthOrSize;
|
|
|
|
if (0.f == particle.x30_lineWidthOrRota)
|
|
|
|
{
|
|
|
|
for (int i=0 ; i<mbspVal ; ++i)
|
|
|
|
{
|
|
|
|
vec += mbspVec;
|
|
|
|
Zeus::CVector3f vec2 = xf2 * vec;
|
|
|
|
/* Draw: */
|
|
|
|
/* Pos: {vec2.x + size, vec2.y, vec2.z + size} Color: particle.color UV0: {uv[2], uv[3]} */
|
|
|
|
/* Pos: {vec2.x - size, vec2.y, vec2.z + size} Color: particle.color UV0: {uv[0], uv[3]} */
|
|
|
|
/* Pos: {vec2.x - size, vec2.y, vec2.z - size} Color: particle.color UV0: {uv[0], uv[1]} */
|
|
|
|
/* Pos: {vec2.x + size, vec2.y, vec2.z - size} Color: particle.color UV0: {uv[2], uv[1]} */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float theta = particle.x30_lineWidthOrRota * M_PI / 180.f;
|
|
|
|
float sinT = sinf(theta) * size;
|
|
|
|
float cosT = sinf(theta) * size;
|
|
|
|
|
|
|
|
for (int i=0 ; i<mbspVal ; ++i)
|
|
|
|
{
|
|
|
|
vec += mbspVec;
|
|
|
|
Zeus::CVector3f vec2 = xf2 * vec;
|
|
|
|
/* Draw:
|
|
|
|
vec2.x + sinT + cosT;
|
|
|
|
vec2.y;
|
|
|
|
vec2.z + cosT - sinT;
|
|
|
|
|
|
|
|
vec2.x + sinT - cosT;
|
|
|
|
vec2.y;
|
|
|
|
vec2.z + sinT + cosT;
|
|
|
|
|
|
|
|
vec2.x - (sinT + cosT);
|
|
|
|
vec2.y;
|
|
|
|
vec2.z - (cosT - sinT);
|
|
|
|
|
|
|
|
vec2.x + (cosT - sinT);
|
|
|
|
vec2.y;
|
|
|
|
vec2.z + (-cosT - sinT);
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (moveRedToAlphaBuffer)
|
|
|
|
{
|
|
|
|
/* Restore */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::RenderParticlesIndirectTexture()
|
2016-02-09 22:52:33 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
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&)
|
2016-02-08 05:10:17 +00:00
|
|
|
{
|
2016-02-09 22:52:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Zeus::CTransform& CElementGen::GetOrientation() const
|
|
|
|
{
|
2016-02-11 19:18:14 +00:00
|
|
|
return x178_orientation;
|
2016-02-09 22:52:33 +00:00
|
|
|
}
|
2016-02-08 05:10:17 +00:00
|
|
|
|
2016-02-09 22:52:33 +00:00
|
|
|
const Zeus::CVector3f& CElementGen::GetTranslation() const
|
|
|
|
{
|
2016-02-11 19:18:14 +00:00
|
|
|
return x7c_translation;
|
2016-02-09 22:52:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const Zeus::CVector3f& CElementGen::GetGlobalScale() const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
const Zeus::CColor& CElementGen::GetModulationColor() const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CElementGen::IsSystemDeletable() const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-02-11 22:38:25 +00:00
|
|
|
std::pair<Zeus::CAABox, bool> CElementGen::GetBounds() const
|
2016-02-09 22:52:33 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 CElementGen::GetParticleCount() const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CElementGen::SystemHasLight() const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CLight CElementGen::GetLight() const
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::DestroyParticles()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void CElementGen::AddModifier(CWarp*)
|
|
|
|
{
|
2016-02-08 05:10:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|