Implement CFlameWarp

This commit is contained in:
Jack Andersen 2017-09-09 23:04:51 -10:00
parent 149eed4b73
commit 53ec80ce72
8 changed files with 137 additions and 54 deletions

View File

@ -123,16 +123,6 @@ void CPlayerState::PutTo(CBitStreamWriter& stream)
stream.WriteEncoded(x180_scanCompletionRate.second, CBitStreamWriter::GetBitCount(0x100));
}
static const float unk[] =
{
0.2f, 0.1f, 0.2f, 0.2f, 1.f
};
float CPlayerState::sub_80091204() const
{
return unk[u32(x8_currentBeam)];
}
static const u32 costs[] =
{
5, 10, 10, 10, 1

View File

@ -128,7 +128,6 @@ private:
CStaticInterference x188_staticIntf;
public:
float sub_80091204() const;
u32 GetMissileCostForAltAttack() const;
float GetComboFireAmmoPeriod() const;
static constexpr float GetMissileComboChargeFactor() { return 1.8f; }

View File

@ -6,8 +6,8 @@
#include "CParticleSwoosh.hpp"
#include "CParticleElectric.hpp"
#include "Graphics/CModel.hpp"
#include "Graphics/Shaders/CElementGenShaders.hpp"
#include "CWarp.hpp"
#define MAX_GLOBAL_PARTICLES 2560
@ -24,7 +24,7 @@ int CElementGen::g_ParticleAliveCount;
int CElementGen::g_ParticleSystemAliveCount;
bool CElementGen::g_ParticleSystemInitialized = false;
bool CElementGen::sMoveRedToAlphaBuffer = false;
CElementGen::CParticle* CElementGen::g_currentParticle = nullptr;
CParticle* CElementGen::g_currentParticle = nullptr;
struct SParticleInstanceTex
{
@ -533,6 +533,13 @@ void CElementGen::UpdateExistingParticles()
AccumulateBounds(particle.x4_pos, particle.x2c_lineLengthOrSize);
++it;
}
if (x30_particles.empty())
return;
for (CWarp* warp : x4_modifierList)
if (warp->UpdateWarp())
warp->ModifyParticles(x30_particles);
}
void CElementGen::CreateNewParticles(int count)
@ -566,7 +573,7 @@ void CElementGen::CreateNewParticles(int count)
if (x2c_orientType == EModelOrientationType::One)
x50_parentMatrices[x30_particles.size()-1] = x1d8_orientation.buildMatrix3f();
CElementGen::CParticle& particle = x30_particles.back();
CParticle& particle = x30_particles.back();
particle.x28_startFrame = x74_curFrame;
if (CIntElement* ltme = desc->x34_x28_LTME.get())
ltme->GetValue(0, particle.x0_endFrame);

View File

@ -58,17 +58,6 @@ public:
CParticleListItem(s16 idx)
: x0_partIdx(idx) {}
};
struct CParticle
{
int x0_endFrame = 0;
zeus::CVector3f x4_pos;
zeus::CVector3f x10_prevPos;
zeus::CVector3f x1c_vel;
int x28_startFrame = 0;
float x2c_lineLengthOrSize = 0.f;
float x30_lineWidthOrRota = 0.f;
zeus::CColor x34_color = {0.f, 0.f, 0.f, 1.f};
};
static CParticle* g_currentParticle;
private:
friend class CElementGenShaders;

View File

@ -1,6 +1,92 @@
#include "CFlameWarp.hpp"
#include "CStateManager.hpp"
namespace urde
{
void CFlameWarp::ModifyParticles(std::vector<CParticle>& particles)
{
if (x9c_stateMgr == 0 || particles.size() < 9)
return;
std::vector<std::pair<float, u8>> vec;
vec.reserve(particles.size());
x90_minSize = FLT_MAX;
x94_maxSize = FLT_MIN;
float maxTransp = 0.f;
u8 idx = 0;
for (CParticle& particle : particles)
{
float transp = 1.f - particle.x34_color.a;
if (transp > maxTransp)
{
float distSq = (particle.x4_pos - x74_warpPoint).magSquared();
if (distSq > x8c_maxDistSq && distSq < x98_maxInfluenceDistSq)
{
x8c_maxDistSq = distSq;
maxTransp = transp;
x80_floatingPoint = particle.x4_pos;
}
}
if (particle.x2c_lineLengthOrSize < x90_minSize)
x90_minSize = particle.x2c_lineLengthOrSize;
if (particle.x2c_lineLengthOrSize > x94_maxSize)
x94_maxSize = particle.x2c_lineLengthOrSize;
vec.emplace_back(transp, idx);
if (xa0_25_collisionWarp)
{
zeus::CVector3f delta = particle.x4_pos - particle.x10_prevPos;
if (delta.magSquared() >= 0.0011920929f)
{
zeus::CVector3f deltaNorm = delta.normalized();
zeus::CVector3f behindPos = particle.x10_prevPos - deltaNorm * 5.f;
zeus::CVector3f fullDelta = particle.x4_pos - behindPos;
CRayCastResult result =
x9c_stateMgr->RayStaticIntersection(behindPos, deltaNorm, fullDelta.magnitude(),
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid},
{EMaterialTypes::ProjectilePassthrough}));
if (result.IsValid())
{
float dist = result.GetPlane().pointToPlaneDist(particle.x4_pos);
if (dist <= 0.f)
{
particle.x4_pos =- result.GetPlane().normal() * dist;
if (result.GetPlane().normal().dot(particle.x1c_vel) < 0.f)
{
zeus::CVector3f prevStepPos = particle.x4_pos - particle.x1c_vel;
particle.x4_pos += (-result.GetPlane().pointToPlaneDist(prevStepPos) /
particle.x1c_vel.dot(result.GetPlane().normal()) - 1.f) * particle.x1c_vel;
particle.x1c_vel -= particle.x1c_vel * 0.001f;
}
}
}
}
}
++idx;
}
std::sort(vec.begin(), vec.end(), [](auto& a, auto& b) { return a.first < b.first; });
for (int i=0 ; i<9 ; ++i)
{
CParticle& part = particles[vec[i].second];
x4_vecs[i] = part.x4_pos;
if (i > 0)
{
zeus::CVector3f delta = x4_vecs[i] - x4_vecs[i-1];
if (delta.magnitude() < 0.0011920929f)
x4_vecs[i] += delta.normalized() * 0.0011920929f;
}
}
x4_vecs[0] = x74_warpPoint;
x80_floatingPoint = x4_vecs[8];
xa0_26_processed = true;
}
}

View File

@ -5,33 +5,36 @@
namespace urde
{
class CStateManager;
class CFlameWarp : public CWarp
{
zeus::CVector3f x4;
zeus::CVector3f xc;
float x1c;
float x20;
int x24;
bool x28_activated : 1;
rstl::reserved_vector<zeus::CVector3f, 9> x4_vecs;
zeus::CVector3f x74_warpPoint;
zeus::CVector3f x80_floatingPoint;
float x8c_maxDistSq = 0.f;
float x90_minSize = FLT_MAX;
float x94_maxSize = FLT_MIN;
float x98_maxInfluenceDistSq;
CStateManager* x9c_stateMgr = nullptr;
bool xa0_24_activated : 1;
bool xa0_25_collisionWarp : 1;
bool xa0_26_processed : 1;
public:
CFlameWarp(float a, const zeus::CVector3f& b)
: x4(b), x1c(0.0), x20(a * a), x24(0)
CFlameWarp(float maxInfluenceDist, const zeus::CVector3f& warpPoint, bool collisionWarp)
: x74_warpPoint(warpPoint), x80_floatingPoint(warpPoint),
x98_maxInfluenceDistSq(maxInfluenceDist * maxInfluenceDist)
{
x28_activated = false;
x4_vecs.resize(9, warpPoint);
xa0_24_activated = false;
xa0_25_collisionWarp = collisionWarp;
xa0_26_processed = false;
}
~CFlameWarp() {}
bool UpdateWarp() { return x28_activated; }
void ModifyParticles(int, int, int *,
zeus::CVector3f*,
zeus::CVector3f*,
zeus::CVector3f*,
zeus::CColor*,
float*, float*) {}
void Activate(bool val) { x28_activated = val; }
bool IsActivated() { return x28_activated; }
bool UpdateWarp() { return xa0_24_activated; }
void ModifyParticles(std::vector<CParticle>& particles);
void Activate(bool val) { xa0_24_activated = val; }
bool IsActivated() { return xa0_24_activated; }
FourCC Get4CharID() { return FOURCC('FWRP'); }
};
}

View File

@ -3,7 +3,6 @@
#include "RetroTypes.hpp"
#include "Graphics/CLight.hpp"
#include "CWarp.hpp"
#include "zeus/CColor.hpp"
#include "zeus/CVector3f.hpp"
#include "zeus/CTransform.hpp"
@ -12,9 +11,23 @@
namespace urde
{
class CWarp;
struct CParticle
{
int x0_endFrame = 0;
zeus::CVector3f x4_pos;
zeus::CVector3f x10_prevPos;
zeus::CVector3f x1c_vel;
int x28_startFrame = 0;
float x2c_lineLengthOrSize = 0.f;
float x30_lineWidthOrRota = 0.f;
zeus::CColor x34_color = {0.f, 0.f, 0.f, 1.f};
};
class CParticleGen
{
protected:
std::list<CWarp*> x4_modifierList;
public:
virtual ~CParticleGen() = default;

View File

@ -4,6 +4,7 @@
#include "zeus/CColor.hpp"
#include "zeus/CVector3f.hpp"
#include "RetroTypes.hpp"
#include "CParticleGen.hpp"
namespace urde
{
@ -11,14 +12,9 @@ namespace urde
class CWarp
{
public:
virtual ~CWarp() {}
virtual ~CWarp() = default;
virtual bool UpdateWarp()=0;
virtual void ModifyParticles(int, int, int*,
zeus::CVector3f*,
zeus::CVector3f*,
zeus::CVector3f*,
zeus::CColor*,
float*, float*)=0;
virtual void ModifyParticles(std::vector<CParticle>& particles)=0;
virtual void Activate(bool)=0;
virtual bool IsActivated()=0;
virtual FourCC Get4CharID()=0;