Finish CSamusDoll

This commit is contained in:
Jack Andersen 2017-05-05 19:21:42 -10:00
parent 4ff1475f0e
commit b2d375a1d7
27 changed files with 1721 additions and 229 deletions

View File

@ -22,6 +22,7 @@ struct ITweakGuiColors : BigYAML
const zeus::CColor& shadow; const zeus::CColor& shadow;
}; };
virtual const zeus::CColor& GetInvPhazonSuitFilterMod() const=0;
virtual const zeus::CColor& GetRadarStuffColor() const=0; virtual const zeus::CColor& GetRadarStuffColor() const=0;
virtual const zeus::CColor& GetRadarPlayerPaintColor() const=0; virtual const zeus::CColor& GetRadarPlayerPaintColor() const=0;
virtual const zeus::CColor& GetRadarEnemyPaintColor() const=0; virtual const zeus::CColor& GetRadarEnemyPaintColor() const=0;

View File

@ -10,7 +10,7 @@ namespace DNAMP1
struct CTweakGuiColors : public ITweakGuiColors struct CTweakGuiColors : public ITweakGuiColors
{ {
DECL_YAML DECL_YAML
DNAColor x4_; DNAColor x4_invPhazonSuitFilterMod;
DNAColor x8_radarStuffColor; DNAColor x8_radarStuffColor;
DNAColor xc_radarPlayerPaintColor; DNAColor xc_radarPlayerPaintColor;
DNAColor x10_radarEnemyPaintColor; DNAColor x10_radarEnemyPaintColor;
@ -140,6 +140,7 @@ struct CTweakGuiColors : public ITweakGuiColors
CTweakGuiColors() = default; CTweakGuiColors() = default;
CTweakGuiColors(athena::io::IStreamReader& r) { this->read(r); } CTweakGuiColors(athena::io::IStreamReader& r) { this->read(r); }
const zeus::CColor& GetInvPhazonSuitFilterMod() const { return x4_invPhazonSuitFilterMod; }
const zeus::CColor& GetRadarStuffColor() const { return x8_radarStuffColor; } const zeus::CColor& GetRadarStuffColor() const { return x8_radarStuffColor; }
const zeus::CColor& GetRadarPlayerPaintColor() const { return xc_radarPlayerPaintColor; } const zeus::CColor& GetRadarPlayerPaintColor() const { return xc_radarPlayerPaintColor; }
const zeus::CColor& GetRadarEnemyPaintColor() const { return x10_radarEnemyPaintColor; } const zeus::CColor& GetRadarEnemyPaintColor() const { return x10_radarEnemyPaintColor; }

View File

@ -813,4 +813,10 @@ zeus::CAABox CAnimData::GetBoundingBox() const
return search->second; return search->second;
} }
void CAnimData::SubstituteModelData(const TCachedToken<CSkinnedModel>& model)
{
xd8_modelData = model;
x108_aabb = xd8_modelData->GetModel()->GetAABB();
}
} }

View File

@ -10,6 +10,7 @@
#include "CAdditiveAnimPlayback.hpp" #include "CAdditiveAnimPlayback.hpp"
#include "CCharLayoutInfo.hpp" #include "CCharLayoutInfo.hpp"
#include "CAnimPlaybackParms.hpp" #include "CAnimPlaybackParms.hpp"
#include "IAnimReader.hpp"
#include <set> #include <set>
enum class EUserEventType enum class EUserEventType
@ -219,6 +220,7 @@ public:
CSegId GetLocatorSegId(const std::string& name) const; CSegId GetLocatorSegId(const std::string& name) const;
zeus::CAABox GetBoundingBox(const zeus::CTransform& xf) const; zeus::CAABox GetBoundingBox(const zeus::CTransform& xf) const;
zeus::CAABox GetBoundingBox() const; zeus::CAABox GetBoundingBox() const;
void SubstituteModelData(const TCachedToken<CSkinnedModel>& model);
static void FreeCache(); static void FreeCache();
static void InitializeCache(); static void InitializeCache();
const CHierarchyPoseBuilder& GetPoseBuilder() const { return x2fc_poseBuilder; } const CHierarchyPoseBuilder& GetPoseBuilder() const { return x2fc_poseBuilder; }

View File

@ -379,4 +379,54 @@ void CModelData::Render(EWhichModel which, const zeus::CTransform& xf,
} }
} }
void CModelData::InvSuitDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights,
const zeus::CColor& alphaColor, const zeus::CColor& additiveColor)
{
CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale));
if (x10_animData)
{
CSkinnedModel& model = PickAnimatedModel(which);
model.GetModelInst()->DisableAllLights();
CModelFlags flags = {};
/* Z-prime */
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
flags.x4_color = zeus::CColor::skWhite;
x10_animData->Render(model, flags, {}, nullptr);
/* Normal Blended */
lights->ActivateLights(*model.GetModelInst());
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = alphaColor;
x10_animData->Render(model, flags, {}, nullptr);
/* Selection Additive */
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = additiveColor;
x10_animData->Render(model, flags, {}, nullptr);
}
else
{
CBooModel& model = *PickStaticModel(which);
model.DisableAllLights();
CModelFlags flags = {};
/* Z-prime */
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
flags.x4_color = zeus::CColor::skWhite;
model.Draw(flags, nullptr, nullptr);
/* Normal Blended */
lights->ActivateLights(model);
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = alphaColor;
model.Draw(flags, nullptr, nullptr);
/* Selection Additive */
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = additiveColor;
model.Draw(flags, nullptr, nullptr);
}
}
} }

View File

@ -139,6 +139,9 @@ public:
void Render(EWhichModel, const zeus::CTransform& xf, void Render(EWhichModel, const zeus::CTransform& xf,
const CActorLights* lights, const CModelFlags& drawFlags); const CActorLights* lights, const CModelFlags& drawFlags);
void InvSuitDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights,
const zeus::CColor& color0, const zeus::CColor& color1);
CAnimData* AnimationData() { return x10_animData.get(); } CAnimData* AnimationData() { return x10_animData.get(); }
const CAnimData* GetAnimationData() const { return x10_animData.get(); } const CAnimData* GetAnimationData() const { return x10_animData.get(); }
const TLockedToken<CModel>& GetNormalModel() const { return x1c_normalModel; } const TLockedToken<CModel>& GetNormalModel() const { return x1c_normalModel; }

View File

@ -865,6 +865,14 @@ void CBooRenderer::DrawStaticGeometry(int modelCount, int mask, int targetMask)
DrawSortedGeometry(modelCount, mask, targetMask); DrawSortedGeometry(modelCount, mask, targetMask);
} }
void CBooRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly)
{
model.GetInstance().DrawFlat(unsortedOnly ?
CBooModel::ESurfaceSelection::UnsortedOnly :
CBooModel::ESurfaceSelection::All,
flags.m_extendedShader);
}
void CBooRenderer::PostRenderFogs() void CBooRenderer::PostRenderFogs()
{ {
for (const auto& warp : x2c4_spaceWarps) for (const auto& warp : x2c4_spaceWarps)
@ -974,6 +982,14 @@ void CBooRenderer::BeginScene()
CGraphics::SetViewport(0, 0, g_Viewport.x8_width, g_Viewport.xc_height); CGraphics::SetViewport(0, 0, g_Viewport.x8_width, g_Viewport.xc_height);
CGraphics::SetPerspective(75.f, CGraphics::g_ProjAspect, 1.f, 4096.f); CGraphics::SetPerspective(75.f, CGraphics::g_ProjAspect, 1.f, 4096.f);
CGraphics::SetModelMatrix(zeus::CTransform::Identity()); CGraphics::SetModelMatrix(zeus::CTransform::Identity());
#if 0
if (x310_phazonSuitMaskCountdown != 0)
{
--x310_phazonSuitMaskCountdown;
if (x310_phazonSuitMaskCountdown == 0)
x314_phazonSuitMask.reset();
}
#endif
x318_27_currentRGBA6 = x318_26_requestRGBA6; x318_27_currentRGBA6 = x318_26_requestRGBA6;
if (!x318_31_persistRGBA6) if (!x318_31_persistRGBA6)
x318_26_requestRGBA6 = false; x318_26_requestRGBA6 = false;
@ -1175,6 +1191,53 @@ void CBooRenderer::SetWorldLightFadeLevel(float level)
x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f); x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f);
} }
void CBooRenderer::ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, /*const CTexture& maskTex,*/
const CTexture& indTex, const zeus::CColor& modColor,
float scale, float offX, float offY)
{
m_phazonSuitFilter.draw(modColor, scale, offX * scale, offY * scale);
}
void CBooRenderer::ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/)
{
m_phazonSuitFilter.draw(modColor, 0.f, 0.f, 0.f);
}
void CBooRenderer::DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, const TLockedToken<CTexture>& indTex)
{
m_phazonSuitFilter.drawBlurPasses(blurRadius, indTex.IsLoaded() ? indTex.GetObj() : nullptr);
}
void CBooRenderer::DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken<CTexture>& indTex,
const zeus::CColor& indirectMod, float blurRadius,
float scale, float offX, float offY)
{
/* Indirect background already in binding 0 */
/* Resolve alpha channel of just-drawn phazon suit into binding 1 */
SClipScreenRect rect;
rect.x4_left = g_Viewport.x0_left;
rect.x8_top = g_Viewport.x4_top;
rect.xc_width = g_Viewport.x8_width;
rect.x10_height = g_Viewport.xc_height;
CGraphics::ResolveSpareTexture(rect, 1);
/* Perform blur filter and resolve into binding 2 */
DoPhazonSuitIndirectAlphaBlur(blurRadius, indTex);
/* Draw effect; subtracting binding 1 from binding 2 for the filter 'cutout' */
if (indTex && indTex.IsLoaded())
ReallyDrawPhazonSuitIndirectEffect(zeus::CColor::skWhite, *indTex, indirectMod, scale, offX, offY);
else
ReallyDrawPhazonSuitEffect(nonIndirectMod);
}
void CBooRenderer::AllocatePhazonSuitMaskTexture()
{
x318_26_requestRGBA6 = true;
x310_phazonSuitMaskCountdown = 2;
}
void CBooRenderer::FindOverlappingWorldModels(std::vector<u32>& modelBits, const zeus::CAABox& aabb) const void CBooRenderer::FindOverlappingWorldModels(std::vector<u32>& modelBits, const zeus::CAABox& aabb) const
{ {
u32 bitmapWords = 0; u32 bitmapWords = 0;

View File

@ -10,6 +10,7 @@
#include "Shaders/CSpaceWarpFilter.hpp" #include "Shaders/CSpaceWarpFilter.hpp"
#include "Shaders/CFogVolumePlaneShader.hpp" #include "Shaders/CFogVolumePlaneShader.hpp"
#include "Shaders/CFogVolumeFilter.hpp" #include "Shaders/CFogVolumeFilter.hpp"
#include "Shaders/CPhazonSuitFilter.hpp"
#include "CRandom16.hpp" #include "CRandom16.hpp"
#include "CPVSVisSet.hpp" #include "CPVSVisSet.hpp"
#include "zeus/CRectangle.hpp" #include "zeus/CRectangle.hpp"
@ -149,6 +150,10 @@ class CBooRenderer : public IRenderer
std::vector<CLight> x300_dynamicLights; std::vector<CLight> x300_dynamicLights;
u32 x310_phazonSuitMaskCountdown = 0;
//std::unique_ptr<CTexture> x314_phazonSuitMask;
CPhazonSuitFilter m_phazonSuitFilter;
union union
{ {
struct struct
@ -182,6 +187,12 @@ class CBooRenderer : public IRenderer
CFogVolumePlaneShader* fvs); CFogVolumePlaneShader* fvs);
void SetupRendererStates() const; void SetupRendererStates() const;
void ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, /*const CTexture& maskTex,*/
const CTexture& indTex, const zeus::CColor& modColor,
float scale, float offX, float offY);
void ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/);
void DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, const TLockedToken<CTexture>& indTex);
public: public:
CBooRenderer(IObjectStore& store, IFactory& resFac); CBooRenderer(IObjectStore& store, IFactory& resFac);
@ -196,6 +207,7 @@ public:
void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask); void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask);
void DrawSortedGeometry(int areaIdx, int mask, int targetMask); void DrawSortedGeometry(int areaIdx, int mask, int targetMask);
void DrawStaticGeometry(int areaIdx, int mask, int targetMask); void DrawStaticGeometry(int areaIdx, int mask, int targetMask);
void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly);
void PostRenderFogs(); void PostRenderFogs();
void AddParticleGen(const CParticleGen&); void AddParticleGen(const CParticleGen&);
void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int); void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int);
@ -248,6 +260,10 @@ public:
void PrepareDynamicLights(const std::vector<CLight>& lights); void PrepareDynamicLights(const std::vector<CLight>& lights);
void SetWorldLightMultiplyColor(const zeus::CColor& color); void SetWorldLightMultiplyColor(const zeus::CColor& color);
void SetWorldLightFadeLevel(float level); void SetWorldLightFadeLevel(float level);
void DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken<CTexture>& indTex,
const zeus::CColor& indirectMod, float blurRadius,
float indScale, float indOffX, float indOffY);
void AllocatePhazonSuitMaskTexture();
void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb,
const CModel* model, const CSkinnedModel* sModel); const CModel* model, const CSkinnedModel* sModel);

View File

@ -14,7 +14,8 @@ if(WIN32)
Shaders/CFogVolumeFilterHLSL.cpp Shaders/CFogVolumeFilterHLSL.cpp
Shaders/CEnergyBarShaderHLSL.cpp Shaders/CEnergyBarShaderHLSL.cpp
Shaders/CRadarPaintShaderHLSL.cpp Shaders/CRadarPaintShaderHLSL.cpp
Shaders/CMapSurfaceShaderHLSL.cpp) Shaders/CMapSurfaceShaderHLSL.cpp
Shaders/CPhazonSuitFilterHLSL.cpp)
elseif(BOO_HAS_METAL) elseif(BOO_HAS_METAL)
set(PLAT_SRCS set(PLAT_SRCS
Shaders/CLineRendererShadersMetal.cpp Shaders/CLineRendererShadersMetal.cpp
@ -31,7 +32,8 @@ elseif(BOO_HAS_METAL)
Shaders/CFogVolumeFilterMetal.cpp Shaders/CFogVolumeFilterMetal.cpp
Shaders/CEnergyBarShaderMetal.cpp Shaders/CEnergyBarShaderMetal.cpp
Shaders/CRadarPaintShaderMetal.cpp Shaders/CRadarPaintShaderMetal.cpp
Shaders/CMapSurfaceShaderMetal.cpp) Shaders/CMapSurfaceShaderMetal.cpp
Shaders/CPhazonSuitFilterMetal.cpp)
endif() endif()
set(GRAPHICS_SOURCES set(GRAPHICS_SOURCES
@ -70,6 +72,7 @@ set(GRAPHICS_SOURCES
Shaders/CEnergyBarShader.hpp Shaders/CEnergyBarShader.cpp Shaders/CEnergyBarShaderGLSL.cpp Shaders/CEnergyBarShader.hpp Shaders/CEnergyBarShader.cpp Shaders/CEnergyBarShaderGLSL.cpp
Shaders/CRadarPaintShader.hpp Shaders/CRadarPaintShader.cpp Shaders/CRadarPaintShaderGLSL.cpp Shaders/CRadarPaintShader.hpp Shaders/CRadarPaintShader.cpp Shaders/CRadarPaintShaderGLSL.cpp
Shaders/CMapSurfaceShader.hpp Shaders/CMapSurfaceShader.cpp Shaders/CMapSurfaceShaderGLSL.cpp Shaders/CMapSurfaceShader.hpp Shaders/CMapSurfaceShader.cpp Shaders/CMapSurfaceShaderGLSL.cpp
Shaders/CPhazonSuitFilter.hpp Shaders/CPhazonSuitFilter.cpp Shaders/CPhazonSuitFilterGLSL.cpp
${PLAT_SRCS}) ${PLAT_SRCS})
runtime_add_list(Graphics GRAPHICS_SOURCES) runtime_add_list(Graphics GRAPHICS_SOURCES)

View File

@ -23,7 +23,7 @@ class CModel;
struct CModelFlags struct CModelFlags
{ {
u8 x0_blendMode = 0; /* Blend state 3/5 enable additive */ u8 x0_blendMode = 0; /* >6: additive, >4: blend, else opaque */
u8 x1_matSetIdx = 0; u8 x1_matSetIdx = 0;
EExtendedShader m_extendedShader = EExtendedShader::Flat; EExtendedShader m_extendedShader = EExtendedShader::Flat;
u16 x2_flags = 0; /* Flags */ u16 x2_flags = 0; /* Flags */
@ -36,6 +36,8 @@ struct CModelFlags
: x0_blendMode(blendMode), x1_matSetIdx(shadIdx), x2_flags(flags), x4_color(col) {} : x0_blendMode(blendMode), x1_matSetIdx(shadIdx), x2_flags(flags), x4_color(col) {}
/* Flags /* Flags
0x1: depth equal
0x2: depth update
0x4: render without texture lock 0x4: render without texture lock
0x8: depth greater 0x8: depth greater
0x10: depth non-inclusive 0x10: depth non-inclusive
@ -79,6 +81,13 @@ public:
void UnlockTextures(); void UnlockTextures();
}; };
enum class ESurfaceSelection
{
UnsortedOnly,
SortedOnly,
All
};
private: private:
CBooModel* m_next = nullptr; CBooModel* m_next = nullptr;
CBooModel* m_prev = nullptr; CBooModel* m_prev = nullptr;
@ -148,6 +157,7 @@ public:
bool IsOpaque() const {return x3c_firstSortedSurface == nullptr;} bool IsOpaque() const {return x3c_firstSortedSurface == nullptr;}
void ActivateLights(const std::vector<CLight>& lights); void ActivateLights(const std::vector<CLight>& lights);
void DisableAllLights();
void RemapMaterialData(SShader& shader); void RemapMaterialData(SShader& shader);
bool TryLockTextures() const; bool TryLockTextures() const;
void UnlockTextures() const; void UnlockTextures() const;
@ -165,6 +175,8 @@ public:
void Draw(const CModelFlags& flags, void Draw(const CModelFlags& flags,
const CSkinRules* cskr, const CSkinRules* cskr,
const CPoseAsTransforms* pose) const; const CPoseAsTransforms* pose) const;
void DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const;
const MaterialSet::Material& GetMaterialByIndex(int idx) const const MaterialSet::Material& GetMaterialByIndex(int idx) const
{ {
@ -217,6 +229,7 @@ public:
void DrawUnsortedParts(const CModelFlags& flags) const; void DrawUnsortedParts(const CModelFlags& flags) const;
void Draw(const CModelFlags& flags) const; void Draw(const CModelFlags& flags) const;
bool IsLoaded(int shaderIdx) const; bool IsLoaded(int shaderIdx) const;
void Touch(int shaderIdx) { x28_modelInst->Touch(shaderIdx); }
const zeus::CAABox& GetAABB() const {return m_aabb;} const zeus::CAABox& GetAABB() const {return m_aabb;}
CBooModel& GetInstance() {return *x28_modelInst;} CBooModel& GetInstance() {return *x28_modelInst;}

View File

@ -425,6 +425,19 @@ void CBooModel::ActivateLights(const std::vector<CLight>& lights)
} }
} }
void CBooModel::DisableAllLights()
{
m_lightingData.ambient = zeus::CColor::skBlack;
for (size_t curLight = 0 ; curLight<URDE_MAX_LIGHTS ; ++curLight)
{
CModelShaders::Light& lightOut = m_lightingData.lights[curLight];
lightOut.color = zeus::CColor::skClear;
lightOut.linAtt[0] = 1.f;
lightOut.angAtt[0] = 1.f;
}
}
void CBooModel::RemapMaterialData(SShader& shader) void CBooModel::RemapMaterialData(SShader& shader)
{ {
x4_matSet = &shader.m_matSet; x4_matSet = &shader.m_matSet;
@ -461,6 +474,33 @@ void CBooModel::UnlockTextures() const
const_cast<CBooModel*>(this)->x40_24_texturesLoaded = false; const_cast<CBooModel*>(this)->x40_24_texturesLoaded = false;
} }
void CBooModel::DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const
{
const CBooSurface* surf;
CModelFlags flags = {};
flags.m_extendedShader = extendedIdx;
if (sel != ESurfaceSelection::SortedOnly)
{
surf = x38_firstUnsortedSurface;
while (surf)
{
DrawSurface(*surf, flags);
surf = surf->m_next;
}
}
if (sel != ESurfaceSelection::UnsortedOnly)
{
surf = x3c_firstSortedSurface;
while (surf)
{
DrawSurface(*surf, flags);
surf = surf->m_next;
}
}
}
void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const
{ {
const CBooSurface* surf = x3c_firstSortedSurface; const CBooSurface* surf = x3c_firstSortedSurface;

View File

@ -21,6 +21,7 @@ class CModel;
class CSkinnedModel; class CSkinnedModel;
class CPVSVisSet; class CPVSVisSet;
struct CAreaRenderOctTree; struct CAreaRenderOctTree;
class CModelFlags;
class IRenderer class IRenderer
{ {
@ -51,6 +52,7 @@ public:
virtual void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask)=0; virtual void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask)=0;
virtual void DrawSortedGeometry(int areaIdx, int mask, int targetMask)=0; virtual void DrawSortedGeometry(int areaIdx, int mask, int targetMask)=0;
virtual void DrawStaticGeometry(int areaIdx, int mask, int targetMask)=0; virtual void DrawStaticGeometry(int areaIdx, int mask, int targetMask)=0;
virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly)=0;
virtual void PostRenderFogs()=0; virtual void PostRenderFogs()=0;
virtual void AddParticleGen(const CParticleGen&)=0; virtual void AddParticleGen(const CParticleGen&)=0;
virtual void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int)=0; virtual void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int)=0;

View File

@ -0,0 +1,96 @@
#include "CPhazonSuitFilter.hpp"
namespace urde
{
void CPhazonSuitFilter::drawBlurPasses(float radius, const CTexture* indTex)
{
if (!m_dataBind || indTex != m_indTex)
{
m_indTex = indTex;
m_gfxTok = CGraphics::CommitResources(
[this](boo::IGraphicsDataFactory::Context& ctx)
{
m_uniBufBlurX = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1);
m_uniBufBlurY = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1);
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f) * 2, 1);
struct BlurVert
{
zeus::CVector3f pos;
zeus::CVector2f uv;
} blurVerts[4] =
{
{{-1.f, 1.f, 0.f}, {0.f, 1.f}},
{{-1.f, -1.f, 0.f}, {0.f, 0.f}},
{{ 1.f, 1.f, 0.f}, {1.f, 1.f}},
{{ 1.f, -1.f, 0.f}, {1.f, 0.f}}
};
m_blurVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, blurVerts, sizeof(BlurVert), 4);
struct Vert
{
zeus::CVector3f pos;
zeus::CVector2f screenUv;
zeus::CVector2f indUv;
zeus::CVector2f maskUv;
} verts[4] =
{
{{-1.f, 1.f, 0.f}, {0.01f, 0.99f}, {0.f, 1.f}, {0.f, 1.f}},
{{-1.f, -1.f, 0.f}, {0.01f, 0.01f}, {0.f, 1.f}, {0.f, 1.f}},
{{ 1.f, 1.f, 0.f}, {0.99f, 0.99f}, {0.f, 1.f}, {0.f, 1.f}},
{{ 1.f, -1.f, 0.f}, {0.99f, 0.01f}, {0.f, 1.f}, {0.f, 1.f}}
};
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4);
m_dataBind = TShader<CPhazonSuitFilter>::BuildShaderDataBinding(ctx, *this);
return true;
});
}
SClipScreenRect rect;
rect.x4_left = g_Viewport.x0_left;
rect.x8_top = g_Viewport.x4_top;
rect.xc_width = g_Viewport.x8_width;
rect.x10_height = g_Viewport.xc_height;
/* X Pass */
zeus::CVector4f blurDir = zeus::CVector4f{2.f * radius / g_Viewport.x8_width, 0.f, 0.f, 0.f};
m_uniBufBlurX->load(&blurDir, sizeof(zeus::CVector4f));
CGraphics::SetShaderDataBinding(m_dataBindBlurX);
CGraphics::DrawArray(0, 4);
CGraphics::ResolveSpareTexture(rect, 2);
/* Y Pass */
blurDir = zeus::CVector4f{0.f, 2.f * radius / g_Viewport.xc_height, 0.f, 0.f};
m_uniBufBlurY->load(&blurDir, sizeof(zeus::CVector4f));
CGraphics::SetShaderDataBinding(m_dataBindBlurY);
CGraphics::DrawArray(0, 4);
CGraphics::ResolveSpareTexture(rect, 2);
}
void CPhazonSuitFilter::draw(const zeus::CColor& color,
float indScale, float indOffX, float indOffY)
{
struct Uniform
{
zeus::CColor color;
zeus::CVector4f indScaleOff;
} uniform =
{
color,
zeus::CVector4f(indScale, indScale, indOffX, indOffY)
};
m_uniBuf->load(&uniform, sizeof(Uniform));
CGraphics::SetShaderDataBinding(m_dataBind);
CGraphics::DrawArray(0, 4);
}
void CPhazonSuitFilter::Shutdown() {}
URDE_SPECIALIZE_SHADER(CPhazonSuitFilter)
}

View File

@ -0,0 +1,39 @@
#ifndef __URDE_CPHAZONSUITFILTER_HPP__
#define __URDE_CPHAZONSUITFILTER_HPP__
#include "TShader.hpp"
namespace urde
{
class CTexture;
class CPhazonSuitFilter
{
friend struct CPhazonSuitFilterGLDataBindingFactory;
friend struct CPhazonSuitFilterVulkanDataBindingFactory;
friend struct CPhazonSuitFilterMetalDataBindingFactory;
friend struct CPhazonSuitFilterD3DDataBindingFactory;
boo::GraphicsDataToken m_gfxTok;
boo::IGraphicsBufferD* m_uniBufBlurX;
boo::IGraphicsBufferD* m_uniBufBlurY;
boo::IGraphicsBufferD* m_uniBuf;
boo::IGraphicsBufferS* m_blurVbo;
boo::IGraphicsBufferS* m_vbo;
const CTexture* m_indTex = nullptr;
boo::IShaderDataBinding* m_dataBindBlurX = nullptr;
boo::IShaderDataBinding* m_dataBindBlurY = nullptr;
boo::IShaderDataBinding* m_dataBind = nullptr;
public:
void drawBlurPasses(float radius, const CTexture* indTex);
void draw(const zeus::CColor& color,
float indScale, float indOffX, float indOffY);
using _CLS = CPhazonSuitFilter;
#include "TShaderDecl.hpp"
};
}
#endif // __URDE_CPHAZONSUITFILTER_HPP__

View File

@ -0,0 +1,340 @@
#include "CPhazonSuitFilter.hpp"
#include "TShader.hpp"
#include "Graphics/CTexture.hpp"
namespace urde
{
static const char* VS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"layout(location=0) in vec4 posIn;\n"
"layout(location=1) in vec4 screenUvIn;\n"
"layout(location=2) in vec4 indUvIn;\n"
"layout(location=3) in vec4 maskUvIn;\n"
"\n"
"UBINDING0 uniform PhazonSuitUniform\n"
"{\n"
" vec4 color;\n"
" vec4 indScaleOff;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec4 indScaleOff;\n"
" vec2 screenUv;\n"
" vec2 indUv;\n"
" vec2 maskUv;\n"
"};\n"
"\n"
"SBINDING(0) out VertToFrag vtf;\n"
"void main()\n"
"{\n"
" vtf.color = color;\n"
" vtf.indScaleOff = indScaleOff;\n"
" vtf.screenUv = screenUvIn.xy;\n"
" vtf.indUv = indUvIn.xy;\n"
" vtf.maskUv = maskUvIn.xy;\n"
" gl_Position = vec4(posIn.xyz, 1.0);\n"
"}\n";
static const char* IndFS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec4 indScaleOff;\n"
" vec2 screenUv;\n"
" vec2 indUv;\n"
" vec2 maskUv;\n"
"};\n"
"\n"
"SBINDING(0) in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"TBINDING0 uniform sampler2D screenTex;\n"
"TBINDING1 uniform sampler2D indTex;\n"
"TBINDING2 uniform sampler2D maskTex;\n"
"TBINDING3 uniform sampler2D maskTexBlur;\n"
"void main()\n"
"{\n"
" vec2 indUv = (texture(indTex, vtf.indUv).rg - vec2(0.5, 0.5)) * \n"
" vtf.indScaleOff.xy + vtf.indScaleOff.zw;\n"
" colorOut = vtf.color * texture(screenTex, indUv + vtf.screenUv) * \n"
" (texture(maskTexBlur, vtf.maskUv).a - texture(maskTex, vtf.maskUv).a);\n"
"}\n";
static const char* FS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"struct VertToFrag\n"
"{\n"
" vec4 color;\n"
" vec4 indScaleOff;\n"
" vec2 screenUv;\n"
" vec2 indUv;\n"
" vec2 maskUv;\n"
"};\n"
"\n"
"SBINDING(0) in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"TBINDING0 uniform sampler2D screenTex;\n"
"TBINDING1 uniform sampler2D maskTex;\n"
"TBINDING2 uniform sampler2D maskTexBlur;\n"
"void main()\n"
"{\n"
" colorOut = vtf.color * texture(screenTex, vtf.screenUv) * \n"
" (texture(maskTexBlur, vtf.maskUv).a - texture(maskTex, vtf.maskUv).a);\n"
"}\n";
static const char* BlurVS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"layout(location=0) in vec4 posIn;\n"
"layout(location=3) in vec4 uvIn;\n"
"\n"
"UBINDING0 uniform PhazonSuitBlurUniform\n"
"{\n"
" vec4 blurDir;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" vec2 uv;\n"
" vec2 blurDir;\n"
"};\n"
"\n"
"SBINDING(0) out VertToFrag vtf;\n"
"void main()\n"
"{\n"
" vtf.uv = uvIn.xy;\n"
" vtf.blurDir = blurDir.xy;\n"
" gl_Position = vec4(posIn.xyz, 1.0);\n"
"}\n";
static const char* BlurFS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"struct VertToFrag\n"
"{\n"
" vec2 uv;\n"
" vec2 blurDir;\n"
"};\n"
"\n"
"SBINDING(0) in VertToFrag vtf;\n"
"layout(location=0) out vec4 colorOut;\n"
"TBINDING0 uniform sampler2D maskTex;\n"
"void main()\n"
"{\n"
" //this will be our alpha sum\n"
" float sum = 0.0;\n"
"\n"
" //apply blurring, using a 9-tap filter with predefined gaussian weights\n"
"\n"
" sum += texture(maskTex, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n"
" sum += texture(maskTex, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n"
" sum += texture(maskTex, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n"
" sum += texture(maskTex, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n"
"\n"
" sum += texture(maskTex, vtf.uv).a * 0.2270270270;\n"
"\n"
" sum += texture(maskTex, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n"
" sum += texture(maskTex, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n"
" sum += texture(maskTex, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n"
" sum += texture(maskTex, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n"
"\n"
" colorOut = vec4(1.0, 1.0, 1.0, sum);\n"
"}\n";
URDE_DECL_SPECIALIZE_SHADER(CPhazonSuitFilter)
static boo::IVertexFormat* s_VtxFmt = nullptr;
static boo::IVertexFormat* s_BlurVtxFmt = nullptr;
static boo::IShaderPipeline* s_IndPipeline = nullptr;
static boo::IShaderPipeline* s_Pipeline = nullptr;
static boo::IShaderPipeline* s_BlurPipeline = nullptr;
struct CPhazonSuitFilterGLDataBindingFactory : TShader<CPhazonSuitFilter>::IDataBindingFactory
{
boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CPhazonSuitFilter& filter)
{
boo::GLDataFactory::Context& cctx = static_cast<boo::GLDataFactory::Context&>(ctx);
const boo::VertexElementDescriptor BlurVtxVmt[] =
{
{filter.m_blurVbo, nullptr, boo::VertexSemantic::Position4},
{filter.m_blurVbo, nullptr, boo::VertexSemantic::UV4}
};
boo::IVertexFormat* blurVtxFmt = ctx.newVertexFormat(2, BlurVtxVmt);
boo::IGraphicsBuffer* bufs[] = {filter.m_uniBufBlurX};
boo::PipelineStage stages[] = {boo::PipelineStage::Vertex};
boo::ITexture* texs[4];
int texBindIdxs[4];
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 1;
filter.m_dataBindBlurX = cctx.newShaderDataBinding(s_BlurPipeline,
blurVtxFmt, filter.m_blurVbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr);
bufs[0] = filter.m_uniBufBlurY;
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 2;
filter.m_dataBindBlurY = cctx.newShaderDataBinding(s_BlurPipeline,
blurVtxFmt, filter.m_blurVbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr);
const boo::VertexElementDescriptor VtxVmt[] =
{
{filter.m_vbo, nullptr, boo::VertexSemantic::Position4},
{filter.m_vbo, nullptr, boo::VertexSemantic::UV4, 0},
{filter.m_vbo, nullptr, boo::VertexSemantic::UV4, 1},
{filter.m_vbo, nullptr, boo::VertexSemantic::UV4, 2}
};
boo::IVertexFormat* vtxFmt = ctx.newVertexFormat(4, VtxVmt);
bufs[0] = filter.m_uniBuf;
size_t texCount;
if (filter.m_indTex)
{
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 0;
texs[1] = filter.m_indTex->GetBooTexture();
texBindIdxs[1] = 0;
texs[2] = CGraphics::g_SpareTexture;
texBindIdxs[2] = 1;
texs[3] = CGraphics::g_SpareTexture;
texBindIdxs[3] = 2;
texCount = 4;
}
else
{
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 0;
texs[1] = CGraphics::g_SpareTexture;
texBindIdxs[1] = 1;
texs[2] = CGraphics::g_SpareTexture;
texBindIdxs[2] = 2;
texCount = 3;
}
return cctx.newShaderDataBinding(filter.m_indTex ? s_IndPipeline : s_Pipeline,
vtxFmt, filter.m_vbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, texCount, texs, texBindIdxs, nullptr);
}
};
#if BOO_HAS_VULKAN
struct CPhazonSuitFilterVulkanDataBindingFactory : TShader<CPhazonSuitFilter>::IDataBindingFactory
{
boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CPhazonSuitFilter& filter)
{
boo::VulkanDataFactory::Context& cctx = static_cast<boo::VulkanDataFactory::Context&>(ctx);
boo::IGraphicsBuffer* bufs[] = {filter.m_uniBufBlurX};
boo::PipelineStage stages[] = {boo::PipelineStage::Vertex};
boo::ITexture* texs[4];
int texBindIdxs[4];
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 1;
filter.m_dataBindBlurX = cctx.newShaderDataBinding(s_BlurPipeline,
s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr);
bufs[0] = filter.m_uniBufBlurY;
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 2;
filter.m_dataBindBlurY = cctx.newShaderDataBinding(s_BlurPipeline,
s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr);
bufs[0] = filter.m_uniBuf;
size_t texCount;
if (filter.m_indTex)
{
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 0;
texs[1] = filter.m_indTex->GetBooTexture();
texBindIdxs[1] = 0;
texs[2] = CGraphics::g_SpareTexture;
texBindIdxs[2] = 1;
texs[3] = CGraphics::g_SpareTexture;
texBindIdxs[3] = 2;
texCount = 4;
}
else
{
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 0;
texs[1] = CGraphics::g_SpareTexture;
texBindIdxs[1] = 1;
texs[2] = CGraphics::g_SpareTexture;
texBindIdxs[2] = 2;
texCount = 3;
}
return cctx.newShaderDataBinding(filter.m_indTex ? s_IndPipeline : s_Pipeline,
s_VtxFmt, filter.m_vbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, texCount, texs, texBindIdxs, nullptr);
}
};
#endif
TShader<CPhazonSuitFilter>::IDataBindingFactory*
CPhazonSuitFilter::Initialize(boo::GLDataFactory::Context& ctx)
{
const char* uniNames[] = {"PhazonSuitUniform"};
const char* texNames[] = {"screenTex", "indTex", "maskTex", "maskTexBlur"};
s_IndPipeline = ctx.newShaderPipeline(VS, IndFS, 4, texNames, 1, uniNames, boo::BlendFactor::One,
boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips,
boo::ZTest::None, false, true, false, boo::CullMode::None);
texNames[1] = "maskTex";
texNames[2] = "maskTexBlur";
s_Pipeline = ctx.newShaderPipeline(VS, FS, 3, texNames, 1, uniNames, boo::BlendFactor::One,
boo::BlendFactor::One, boo::Primitive::TriStrips,
boo::ZTest::None, false, true, false, boo::CullMode::None);
uniNames[0] = "PhazonSuitBlurUniform";
texNames[0] = "maskTex";
s_BlurPipeline = ctx.newShaderPipeline(BlurVS, BlurFS, 1, texNames, 1, uniNames, boo::BlendFactor::One,
boo::BlendFactor::Zero, boo::Primitive::TriStrips,
boo::ZTest::None, false, false, true, boo::CullMode::None);
return new CPhazonSuitFilterGLDataBindingFactory;
}
#if BOO_HAS_VULKAN
TShader<CPhazonSuitFilter>::IDataBindingFactory*
CPhazonSuitFilter::Initialize(boo::VulkanDataFactory::Context& ctx)
{
const boo::VertexElementDescriptor VtxVmt[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4},
{nullptr, nullptr, boo::VertexSemantic::UV4, 0},
{nullptr, nullptr, boo::VertexSemantic::UV4, 1},
{nullptr, nullptr, boo::VertexSemantic::UV4, 2}
};
s_VtxFmt = ctx.newVertexFormat(4, VtxVmt);
const boo::VertexElementDescriptor BlurVtxVmt[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4},
{nullptr, nullptr, boo::VertexSemantic::UV4}
};
s_BlurVtxFmt = ctx.newVertexFormat(2, BlurVtxVmt);
s_IndPipeline = ctx.newShaderPipeline(VS, IndFS, s_VtxFmt, boo::BlendFactor::One,
boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips,
boo::ZTest::None, false, true, false, boo::CullMode::None);
s_Pipeline = ctx.newShaderPipeline(VS, FS, s_VtxFmt, boo::BlendFactor::One,
boo::BlendFactor::One, boo::Primitive::TriStrips,
boo::ZTest::None, false, true, false, boo::CullMode::None);
s_BlurPipeline = ctx.newShaderPipeline(BlurVS, BlurFS, s_BlurVtxFmt, boo::BlendFactor::One,
boo::BlendFactor::Zero, boo::Primitive::TriStrips,
boo::ZTest::None, false, false, true, boo::CullMode::None);
return new CPhazonSuitFilterVulkanDataBindingFactory;
}
#endif
}

View File

@ -0,0 +1,255 @@
#include "CPhazonSuitFilter.hpp"
#include "TShader.hpp"
#include "Graphics/CTexture.hpp"
namespace urde
{
static const char* VS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"struct VertData\n"
"{\n"
" float4 posIn [[ attribute(0) ]];\n"
" float4 screenUvIn [[ attribute(1) ]];\n"
" float4 indUvIn [[ attribute(2) ]];\n"
" float4 maskUvIn [[ attribute(3) ]];\n"
"};\n"
"\n"
"struct PhazonSuitUniform\n"
"{\n"
" float4 color;\n"
" float4 indScaleOff;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" float4 position [[ position ]];\n"
" float4 color;\n"
" float4 indScaleOff;\n"
" float2 screenUv;\n"
" float2 indUv;\n"
" float2 maskUv;\n"
"};\n"
"\n"
"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant PhazonSuitUniform& psu [[ buffer(2) ]])\n"
"{\n"
" VertToFrag vtf;\n"
" vtf.color = psu.color;\n"
" vtf.indScaleOff = psu.indScaleOff;\n"
" vtf.screenUv = v.screenUvIn.xy;\n"
" vtf.indUv = v.indUvIn.xy;\n"
" vtf.maskUv = v.maskUvIn.xy;\n"
" vtf.position = float4(v.posIn.xyz, 1.0);\n"
" return vtf;\n"
"}\n";
static const char* IndFS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"constexpr sampler samp(address::repeat, filter::linear);\n"
"struct VertToFrag\n"
"{\n"
" float4 position [[ position ]];\n"
" float4 color;\n"
" float4 indScaleOff;\n"
" float2 screenUv;\n"
" float2 indUv;\n"
" float2 maskUv;\n"
"};\n"
"\n"
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n"
" texture2d<float> screenTex [[ texture(0) ]],\n"
" texture2d<float> indTex [[ texture(1) ]],\n"
" texture2d<float> maskTex [[ texture(2) ]],\n"
" texture2d<float> maskTexBlur [[ texture(3) ]])\n"
"{\n"
" float2 indUv = (indTex.sample(samp, vtf.indUv).rg - float2(0.5, 0.5)) * \n"
" vtf.indScaleOff.xy + vtf.indScaleOff.zw;\n"
" return vtf.color * screenTex.sample(samp, indUv + vtf.screenUv) * \n"
" (maskTexBlur.sample(samp, vtf.maskUv).a - maskTex.sample(samp, vtf.maskUv).a);\n"
"}\n";
static const char* FS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"constexpr sampler samp(address::repeat, filter::linear);\n"
"struct VertToFrag\n"
"{\n"
" float4 color;\n"
" float4 indScaleOff;\n"
" float2 screenUv;\n"
" float2 indUv;\n"
" float2 maskUv;\n"
"};\n"
"\n"
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n"
" texture2d<float> screenTex [[ texture(0) ]],\n"
" texture2d<float> maskTex [[ texture(1) ]],\n"
" texture2d<float> maskTexBlur [[ texture(2) ]])\n"
"{\n"
" return vtf.color * screenTex.sample(samp, vtf.screenUv) * \n"
" (maskTexBlur.sample(samp, vtf.maskUv).a - maskTex.sample(samp, vtf.maskUv).a);\n"
"}\n";
static const char* BlurVS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"struct VertData\n"
"{\n"
" float4 posIn [[ attribute(0) ]];\n"
" float4 uvIn [[ attribute(1) ]];\n"
"};\n"
"\n"
"struct PhazonSuitBlurUniform\n"
"{\n"
" float4 blurDir;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" float4 position [[ position ]];\n"
" float2 uv;\n"
" float2 blurDir;\n"
"};\n"
"\n"
"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant PhazonSuitBlurUniform& psu [[ buffer(2) ]])\n"
"{\n"
" VertToFrag vtf;\n"
" vtf.uv = uvIn.xy;\n"
" vtf.blurDir = blurDir.xy;\n"
" vtf.position = float4(posIn.xyz, 1.0);\n"
" return vtf;\n"
"}\n";
static const char* BlurFS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"constexpr sampler samp(address::repeat, filter::linear);\n"
"struct VertToFrag\n"
"{\n"
" float4 position [[ position ]];\n"
" float2 uv;\n"
" float2 blurDir;\n"
"};\n"
"\n"
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n"
" texture2d<float> maskTex [[ texture(0) ]])\n"
"{\n"
" //this will be our alpha sum\n"
" float sum = 0.0;\n"
"\n"
" //apply blurring, using a 9-tap filter with predefined gaussian weights\n"
"\n"
" sum += maskTex.sample(samp, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n"
" sum += maskTex.sample(samp, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n"
" sum += maskTex.sample(samp, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n"
" sum += maskTex.sample(samp, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n"
"\n"
" sum += maskTex.sample(samp, vtf.uv).a * 0.2270270270;\n"
"\n"
" sum += maskTex.sample(samp, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n"
" sum += maskTex.sample(samp, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n"
" sum += maskTex.sample(samp, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n"
" sum += maskTex.sample(samp, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n"
"\n"
" return float4(1.0, 1.0, 1.0, sum);\n"
"}\n";
URDE_DECL_SPECIALIZE_SHADER(CPhazonSuitFilter)
static boo::IVertexFormat* s_VtxFmt = nullptr;
static boo::IVertexFormat* s_BlurVtxFmt = nullptr;
static boo::IShaderPipeline* s_IndPipeline = nullptr;
static boo::IShaderPipeline* s_Pipeline = nullptr;
static boo::IShaderPipeline* s_BlurPipeline = nullptr;
struct CPhazonSuitFilterMetalDataBindingFactory : TShader<CPhazonSuitFilter>::IDataBindingFactory
{
boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CPhazonSuitFilter& filter)
{
boo::MetalDataFactory::Context& cctx = static_cast<boo::MetalDataFactory::Context&>(ctx);
boo::IGraphicsBuffer* bufs[] = {filter.m_uniBufBlurX};
boo::PipelineStage stages[] = {boo::PipelineStage::Vertex};
boo::ITexture* texs[4];
int texBindIdxs[4];
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 1;
filter.m_dataBindBlurX = cctx.newShaderDataBinding(s_BlurPipeline,
s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr);
bufs[0] = filter.m_uniBufBlurY;
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 2;
filter.m_dataBindBlurY = cctx.newShaderDataBinding(s_BlurPipeline,
s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr);
bufs[0] = filter.m_uniBuf;
size_t texCount;
if (filter.m_indTex)
{
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 0;
texs[1] = filter.m_indTex->GetBooTexture();
texBindIdxs[1] = 0;
texs[2] = CGraphics::g_SpareTexture;
texBindIdxs[2] = 1;
texs[3] = CGraphics::g_SpareTexture;
texBindIdxs[3] = 2;
texCount = 4;
}
else
{
texs[0] = CGraphics::g_SpareTexture;
texBindIdxs[0] = 0;
texs[1] = CGraphics::g_SpareTexture;
texBindIdxs[1] = 1;
texs[2] = CGraphics::g_SpareTexture;
texBindIdxs[2] = 2;
texCount = 3;
}
return cctx.newShaderDataBinding(filter.m_indTex ? s_IndPipeline : s_Pipeline,
s_VtxFmt, filter.m_vbo, nullptr, nullptr,
1, bufs, stages, nullptr, nullptr, texCount, texs, texBindIdxs, nullptr);
}
};
TShader<CPhazonSuitFilter>::IDataBindingFactory*
CPhazonSuitFilter::Initialize(boo::MetalDataFactory::Context& ctx)
{
const boo::VertexElementDescriptor VtxVmt[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4},
{nullptr, nullptr, boo::VertexSemantic::UV4, 0},
{nullptr, nullptr, boo::VertexSemantic::UV4, 1},
{nullptr, nullptr, boo::VertexSemantic::UV4, 2}
};
s_VtxFmt = ctx.newVertexFormat(4, VtxVmt);
const boo::VertexElementDescriptor BlurVtxVmt[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4},
{nullptr, nullptr, boo::VertexSemantic::UV4}
};
s_BlurVtxFmt = ctx.newVertexFormat(2, BlurVtxVmt);
s_IndPipeline = ctx.newShaderPipeline(VS, IndFS, s_VtxFmt,
CGraphics::g_ViewportSamples, boo::BlendFactor::One,
boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips,
boo::ZTest::None, false, true, false, boo::CullMode::None);
s_Pipeline = ctx.newShaderPipeline(VS, FS, s_VtxFmt,
CGraphics::g_ViewportSamples, boo::BlendFactor::One,
boo::BlendFactor::One, boo::Primitive::TriStrips,
boo::ZTest::None, false, true, false, boo::CullMode::None);
s_BlurPipeline = ctx.newShaderPipeline(BlurVS, BlurFS, s_BlurVtxFmt,
CGraphics::g_ViewportSamples, boo::BlendFactor::One,
boo::BlendFactor::Zero, boo::Primitive::TriStrips,
boo::ZTest::None, false, false, true, boo::CullMode::None);
return new CPhazonSuitFilterMetalDataBindingFactory;
}
}

View File

@ -1,10 +1,71 @@
#include "CInventoryScreen.hpp" #include "CInventoryScreen.hpp"
#include "GuiSys/CGuiTableGroup.hpp"
namespace urde namespace urde
{ {
namespace MP1 namespace MP1
{ {
struct SInventoryItem
{
u32 idx;
u32 nameStrIdx;
u32 entryStrIdx;
};
static const SInventoryItem ArmCannonItems[] =
{
{0, 0x24, 0x46}, // Power Beam
{1, 0x25, 0x48}, // Ice Beam
{2, 0x26, 0x4a}, // Wave Beam
{3, 0x27, 0x4c}, // Plasma Beam
{4, 0x28, 0x4e}, // Phazon Beam
};
static const SInventoryItem MorphballItems[] =
{
{5, 0x2e, 0x57}, // Morph Ball
{6, 0x2f, 0x58}, // Boost Ball
{7, 0x30, 0x59}, // Spider Ball
{8, 0x31, 0x5a}, // Morph Ball Bomb
{9, 0x32, 0x5b}, // Power Bomb
};
static const SInventoryItem SuitItems[] =
{
{10, 0x33, 0x52}, // Power Suit
{11, 0x34, 0x53}, // Varia Suit
{12, 0x35, 0x54}, // Gravity Suit
{13, 0x36, 0x55}, // Phazon Suit
{14, 0x37, 0x56}, // Energy Tank
};
static const SInventoryItem VisorItems[] =
{
{15, 0x38, 0x42}, // Combat Visor
{16, 0x39, 0x43}, // Scan Visor
{17, 0x3a, 0x44}, // X-Ray Visor
{18, 0x3b, 0x45}, // Thermal Visor
};
static const SInventoryItem SecondaryItems[] =
{
{19, 0x3c, 0x4f}, // Space Jump Boots
{20, 0x3d, 0x50}, // Grapple Beam
{21, 0x3e, 0x51}, // Missile Launcher
{22, 0x3f, 0x5c}, // Charge Beam
{23, 0x40, 0x5d}, // Beam Combo
};
static const std::pair<u32, const SInventoryItem*> InventoryRegistry[] =
{
{5, ArmCannonItems},
{5, MorphballItems},
{5, SuitItems},
{4, VisorItems},
{5, SecondaryItems},
};
CInventoryScreen::CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, CInventoryScreen::CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg,
const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp) const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp)
: CPauseScreenBase(mgr, frame, pauseStrg) : CPauseScreenBase(mgr, frame, pauseStrg)
@ -96,5 +157,38 @@ void CInventoryScreen::UpdateRightLogHighlight(bool active, int idx,
} }
void CInventoryScreen::UpdateSamusDollPulses()
{
bool pulseSuit = false;
bool pulseBeam = false;
bool pulseGrapple = false;
bool pulseBoots = false;
bool pulseVisor = false;
int userSel = x70_tablegroup_leftlog->GetUserSelection();
if (x10_mode == EMode::RightTable)
{
if (userSel == 2)
pulseSuit = true;
else if (userSel == 0)
pulseBeam = true;
else if (userSel == 3)
pulseVisor = true;
else if (userSel == 4)
{
pulseGrapple = SecondaryItems[x1c_rightSel].idx == 20;
pulseBoots = SecondaryItems[x1c_rightSel].idx == 19;
if (SecondaryItems[x1c_rightSel].idx == 21)
pulseBeam = true;
}
}
x19c_samusDoll->SetPulseSuit(pulseSuit);
x19c_samusDoll->SetPulseBeam(pulseBeam);
x19c_samusDoll->SetPulseGrapple(pulseGrapple);
x19c_samusDoll->SetPulseBoots(pulseBoots);
x19c_samusDoll->SetPulseVisor(pulseVisor);
}
} }
} }

View File

@ -38,6 +38,7 @@ public:
bool IsRightLogDynamic() const; bool IsRightLogDynamic() const;
void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor);
void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor);
void UpdateSamusDollPulses();
}; };
} }

View File

@ -128,7 +128,7 @@ void CPauseScreenBase::ChangeMode(EMode mode)
x70_tablegroup_leftlog->SetIsActive(true); x70_tablegroup_leftlog->SetIsActive(true);
UpdateSideTable(x70_tablegroup_leftlog); UpdateSideTable(x70_tablegroup_leftlog);
x18_ = 0; x18_ = 0;
x1c_ = 0; x1c_rightSel = 0;
x84_tablegroup_rightlog->SetUserSelection(1); x84_tablegroup_rightlog->SetUserSelection(1);
UpdateSideTable(x84_tablegroup_rightlog); UpdateSideTable(x84_tablegroup_rightlog);
break; break;
@ -171,11 +171,11 @@ void CPauseScreenBase::UpdateSideTable(CGuiTableGroup* table)
if (table == x84_tablegroup_rightlog) if (table == x84_tablegroup_rightlog)
{ {
int sel = x1c_ - x18_; int sel = x1c_rightSel - x18_;
x8c_model_righthighlight->SetLocalTransform( x8c_model_righthighlight->SetLocalTransform(
x8c_model_righthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_ * sel)); x8c_model_righthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_ * sel));
x8c_model_righthighlight->SetVisibility(x10_mode == EMode::RightTable, ETraversalMode::Children); x8c_model_righthighlight->SetVisibility(x10_mode == EMode::RightTable, ETraversalMode::Children);
int selInView = x1c_ % 5; int selInView = x1c_rightSel % 5;
if (IsRightLogDynamic()) if (IsRightLogDynamic())
{ {
UpdateRightLogHighlight(tableActive, selInView, selColor, deselColor); UpdateRightLogHighlight(tableActive, selInView, selColor, deselColor);
@ -249,7 +249,7 @@ void CPauseScreenBase::Draw(float mainAlpha, float frameAlpha, float yOff)
void CPauseScreenBase::UpdateRightTable() void CPauseScreenBase::UpdateRightTable()
{ {
x18_ = 0; x18_ = 0;
x1c_ = 0; x1c_rightSel = 0;
x84_tablegroup_rightlog->SetUserSelection(1); x84_tablegroup_rightlog->SetUserSelection(1);
UpdateSideTable(x84_tablegroup_rightlog); UpdateSideTable(x84_tablegroup_rightlog);
} }

View File

@ -38,7 +38,7 @@ protected:
EMode x10_mode = EMode::Invalid; EMode x10_mode = EMode::Invalid;
float x14_alpha = 0.f; float x14_alpha = 0.f;
u32 x18_ = 0; u32 x18_ = 0;
u32 x1c_ = 0; u32 x1c_rightSel = 0;
zeus::CVector3f x20_; zeus::CVector3f x20_;
zeus::CVector3f x2c_; zeus::CVector3f x2c_;
float x38_ = 0.f; float x38_ = 0.f;

View File

@ -4,6 +4,7 @@
#include "CDependencyGroup.hpp" #include "CDependencyGroup.hpp"
#include "zeus/CEulerAngles.hpp" #include "zeus/CEulerAngles.hpp"
#include "Collision/CollisionUtil.hpp" #include "Collision/CollisionUtil.hpp"
#include "Graphics/CBooRenderer.hpp"
namespace urde namespace urde
{ {
@ -113,6 +114,45 @@ static const u32 Character2and3Idxs[8][2] =
{30, 31} {30, 31}
}; };
static const u8 BallGlowColors[9][3] =
{
{0xff, 0xff, 0xff},
{0xff, 0xff, 0xff},
{0xff, 0xff, 0xff},
{0xff, 0xff, 0xff},
{0xff, 0xd5, 0x19},
{0xff, 0xff, 0xff},
{0xff, 0xff, 0xff},
{0xff, 0xff, 0xff},
{0xff, 0xff, 0xff},
};
static const u8 BallTransFlashColors[9][3] =
{
{0xc2, 0x7e, 0x10},
{0x66, 0xc4, 0xff},
{0x60, 0xff, 0x90},
{0x33, 0x33, 0xff},
{0xff, 0x20, 0x20},
{0x0, 0x9d, 0xb6},
{0xd3, 0xf1, 0x0},
{0xa6, 0x86, 0xd8},
{0xfb, 0x98, 0x21}
};
static const u8 BallAuxGlowColors[9][3] =
{
{0xc2, 0x7e, 0x10},
{0x66, 0xc4, 0xff},
{0x6c, 0xff, 0x61},
{0x33, 0x33, 0xff},
{0xff, 0x20, 0x20},
{0x0, 0x9d, 0xb6},
{0xd3, 0xf1, 0x0},
{0xa6, 0x86, 0xd8},
{0xfb, 0x98, 0x21}
};
CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp, CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp,
CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam, CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam,
bool hasSpiderBall, bool hasGrappleBeam) bool hasSpiderBall, bool hasGrappleBeam)
@ -166,7 +206,7 @@ bool CSamusDoll::IsLoaded() const
return false; return false;
if (x218_invFins && !x218_invFins.IsLoaded()) if (x218_invFins && !x218_invFins.IsLoaded())
return false; return false;
return xc8_suitModel1.operator bool(); return xc8_suitModel0.operator bool();
} }
CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit) CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit)
@ -196,7 +236,7 @@ bool CSamusDoll::CheckLoadComplete()
if (!tok.IsLoaded()) if (!tok.IsLoaded())
return false; return false;
xc8_suitModel1.emplace(BuildSuitModelData1(x44_suit)); xc8_suitModel0.emplace(BuildSuitModelData1(x44_suit));
for (int i=0 ; i<2 ; ++i) for (int i=0 ; i<2 ; ++i)
{ {
CAnimRes res(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, CAnimRes res(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id,
@ -222,55 +262,448 @@ bool CSamusDoll::CheckLoadComplete()
void CSamusDoll::Update(float dt, CRandom16& rand) void CSamusDoll::Update(float dt, CRandom16& rand)
{ {
if (x1f4_invBeam.IsLoaded())
x1f4_invBeam->Touch(0);
if (x200_invVisor.IsLoaded())
x200_invVisor->Touch(0);
if (x20c_invGrappleBeam.IsLoaded())
x20c_invGrappleBeam->Touch(0);
if (x1d4_spiderBallGlass.IsLoaded())
x1d4_spiderBallGlass->Touch(0);
if (x218_invFins.IsLoaded())
x218_invFins->Touch(0);
if (!CheckLoadComplete())
return;
x40_alphaIn = std::min(x40_alphaIn + 2.f * dt, 1.f);
if (x54_remTransitionTime > 0.f)
{
float oldRemTransTime = x54_remTransitionTime;
x54_remTransitionTime = std::max(0.f, x54_remTransitionTime - dt);
if (!x4c_completedMorphball && x4d_selectedMorphball &&
oldRemTransTime >= x50_totalTransitionTime - 0.5f &&
x54_remTransitionTime < x50_totalTransitionTime - 0.5f)
{
x238_ballTransitionFlashGen = std::make_unique<CElementGen>(x230_ballTransitionFlash,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x238_ballTransitionFlashGen->SetGlobalScale(zeus::CVector3f(0.625f));
}
if (x54_remTransitionTime == 0.f)
{
x4c_completedMorphball = x4d_selectedMorphball;
if (!x4d_selectedMorphball)
{
xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false);
x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false);
}
}
}
if (x270_26_pulseSuit)
x58_suitPulseFactor = std::min(x58_suitPulseFactor + 2.f * dt, 1.f);
else
x58_suitPulseFactor = std::max(x58_suitPulseFactor - 2.f * dt, 0.f);
if (x270_27_pulseBeam)
x5c_beamPulseFactor = std::min(x5c_beamPulseFactor + 2.f * dt, 1.f);
else
x5c_beamPulseFactor = std::max(x5c_beamPulseFactor - 2.f * dt, 0.f);
if (x270_28_pulseGrapple)
x60_grapplePulseFactor = std::min(x60_grapplePulseFactor + 2.f * dt, 1.f);
else
x60_grapplePulseFactor = std::max(x60_grapplePulseFactor - 2.f * dt, 0.f);
if (x270_29_pulseBoots)
x64_bootsPulseFactor = std::min(x64_bootsPulseFactor + 2.f * dt, 1.f);
else
x64_bootsPulseFactor = std::max(x64_bootsPulseFactor - 2.f * dt, 0.f);
if (x270_30_pulseVisor)
x68_visorPulseFactor = std::min(x68_visorPulseFactor + 2.f * dt, 1.f);
else
x68_visorPulseFactor = std::max(x68_visorPulseFactor - 2.f * dt, 0.f);
if (x4c_completedMorphball)
x6c_ballPulseFactor = std::min(x6c_ballPulseFactor + 2.f * dt, 1.f);
else
x6c_ballPulseFactor = std::max(x6c_ballPulseFactor - 2.f * dt, 0.f);
if (x44_suit == CPlayerState::EPlayerSuit::Phazon)
{
if (!x250_phazonIndirectTexture)
x250_phazonIndirectTexture = g_SimplePool->GetObj("PhazonIndirectTexture");
}
else
{
if (x250_phazonIndirectTexture)
x250_phazonIndirectTexture = TLockedToken<CTexture>();
}
if (x250_phazonIndirectTexture)
{
x260_phazonOffsetAngle += 0.03f;
g_Renderer->AllocatePhazonSuitMaskTexture();
}
xc8_suitModel0->AdvanceAnimationIgnoreParticles(dt, rand, true);
x134_suitModelBoots->AdvanceAnimationIgnoreParticles(dt, rand, true);
x184_ballModelData->AdvanceAnimationIgnoreParticles(dt, rand, true);
SetupLights();
x22c_ballInnerGlowGen->SetGlobalTranslation(x10_xf.origin);
x22c_ballInnerGlowGen->Update(dt);
if (x238_ballTransitionFlashGen)
{
if (x238_ballTransitionFlashGen->IsSystemDeletable())
x238_ballTransitionFlashGen.reset();
if (x238_ballTransitionFlashGen)
{
x22c_ballInnerGlowGen->SetGlobalTranslation(x10_xf.origin);
x22c_ballInnerGlowGen->Update(dt);
}
}
if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f)
{
if (xc4_viewInterp < 0.f)
xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 0.f);
else
xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 1.f);
float interp = std::fabs(xc4_viewInterp);
float oneMinusInterp = 1.f - interp;
xa4_offset = x84_interpStartOffset * interp + skInitialOffset * oneMinusInterp;
xb0_userRot = zeus::CQuaternion::slerpShort(x70_fixedRot, x90_userInterpRot, interp);
if (xc4_viewInterp <= 0.f) // Zoom out
xc0_userZoom = x80_fixedZoom * oneMinusInterp + xa0_userInterpZoom * interp;
else // Zoom in
xc0_userZoom = x80_fixedZoom * interp + xa0_userInterpZoom * oneMinusInterp;
}
} }
void CSamusDoll::Draw(const CStateManager& mgr, float alpha) void CSamusDoll::Draw(const CStateManager& mgr, float alpha)
{ {
if (!IsLoaded())
return;
alpha *= x40_alphaIn;
float itemPulse = zeus::clamp(0.f, (std::sin(5.f * CGraphics::GetSecondsMod900()) + 1.f) * 0.5f, 1.f) *
(1.f - std::fabs(xc4_viewInterp));
g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f);
CGraphics::SetViewPointMatrix(zeus::CTransform(xb0_userRot, xa4_offset) *
zeus::CTransform::Translate(0.f, xc0_userZoom, 0.f));
zeus::CTransform gunXf = xc8_suitModel0->GetScaledLocatorTransform("GUN_LCTR");
zeus::CTransform visorXf = xc8_suitModel0->GetScaledLocatorTransform("VISOR_LCTR");
zeus::CTransform grappleXf = xc8_suitModel0->GetScaledLocatorTransform("GRAPPLE_LCTR");
if (!x4c_completedMorphball || !x4d_selectedMorphball)
{
float suitPulse = itemPulse * x58_suitPulseFactor;
float bootsPulse = std::max(suitPulse, itemPulse * x64_bootsPulseFactor);
bool phazonSuit = x44_suit == CPlayerState::EPlayerSuit::Phazon;
// Enable dst alpha 1.0
for (int i=0 ; i<=x118_suitModel1and2.size() ; ++i)
{
TCachedToken<CSkinnedModel> backupModelData = xc8_suitModel0->GetAnimationData()->GetModelData();
if (i < x118_suitModel1and2.size())
xc8_suitModel0->AnimationData()->SubstituteModelData(x118_suitModel1and2[i]);
xc8_suitModel0->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(),
x24c_actorLights.get(), zeus::CColor(1.f, alpha),
zeus::CColor(1.f, alpha * suitPulse));
xc8_suitModel0->AnimationData()->SubstituteModelData(backupModelData);
}
x134_suitModelBoots->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(),
x24c_actorLights.get(), zeus::CColor(1.f, alpha),
zeus::CColor(1.f, alpha * bootsPulse));
{
CGraphics::SetModelMatrix(gunXf);
x1f4_invBeam->GetInstance().ActivateLights(x23c_lights);
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
flags.x4_color = zeus::CColor::skWhite;
x1f4_invBeam->Draw(flags);
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor(1.f, alpha);
x1f4_invBeam->Draw(flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x5c_beamPulseFactor);
x1f4_invBeam->Draw(flags);
}
{
CGraphics::SetModelMatrix(visorXf);
float visorT = std::fmod(CGraphics::GetSecondsMod900(), 1.f) * (1.f - std::fabs(xc4_viewInterp));
float alphaBlend = (visorT < 0.25f) ? 1.f - 2.f * visorT : (visorT < 0.5f) ? 2.f * (visorT - 0.25f) + 0.5f : 1.f;
float addBlend = (visorT > 0.75f) ? 1.f - 4.f * (visorT - 0.75f) : (visorT > 0.5f) ? 4.f * (visorT - 0.5f) : 0.f;
x200_invVisor->GetInstance().ActivateLights(x23c_lights);
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor::lerp(zeus::CColor(1.f, alpha), zeus::CColor(alphaBlend, alpha), x68_visorPulseFactor);
x200_invVisor->Draw(flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor(1.f, alpha * addBlend * x68_visorPulseFactor);
x200_invVisor->Draw(flags);
}
if (x270_25_hasGrappleBeam)
{
CGraphics::SetModelMatrix(grappleXf);
x20c_invGrappleBeam->GetInstance().ActivateLights(x23c_lights);
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor(1.f, alpha);
x20c_invGrappleBeam->Draw(flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x60_grapplePulseFactor);
x20c_invGrappleBeam->Draw(flags);
}
else if (x44_suit >= CPlayerState::EPlayerSuit::FusionPower)
{
CGraphics::SetModelMatrix(grappleXf);
x218_invFins->GetInstance().ActivateLights(x23c_lights);
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor(1.f, alpha);
x218_invFins->Draw(flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor(1.f, alpha * suitPulse);
x218_invFins->Draw(flags);
}
if (x54_remTransitionTime > 0.f)
{
float ballT = 1.f - x54_remTransitionTime / x50_totalTransitionTime;
float ballAlpha = 0.f;
if (x4d_selectedMorphball)
ballAlpha = 1.f - std::min(x54_remTransitionTime / 0.25f, 1.f);
else if (x4c_completedMorphball)
ballAlpha = std::max(0.f, (x54_remTransitionTime - (x50_totalTransitionTime - 0.25f)) / 0.25f);
if (ballAlpha > 0.f)
{
CModelFlags flags = {};
flags.x1_matSetIdx = x1e0_ballMatIdx;
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
flags.x4_color = zeus::CColor::skWhite;
x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags);
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = alpha * ballAlpha;
x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = x6c_ballPulseFactor * alpha * ballAlpha * itemPulse;
x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags);
}
if (x4d_selectedMorphball && ballT > 0.5f)
{
float ballEndT = (ballT - 0.5f) / 0.5f;
float oneMinusBallEndT = 1.f - ballEndT;
float spinScale = 0.75f * oneMinusBallEndT + 1.f;
float spinAlpha;
if (ballEndT < 0.1f)
spinAlpha = 0.f;
else if (ballEndT < 0.2f)
spinAlpha = (ballEndT - 0.1f) / 0.1f;
else if (ballEndT < 0.9f)
spinAlpha = 1.f;
else
spinAlpha = 1.f - (ballT - 0.9f) / 0.1f;
zeus::CRelAngle spinAngle = zeus::degToRad(360.f * oneMinusBallEndT);
spinAlpha *= 0.5f;
if (spinAlpha > 0.f)
{
CModelFlags flags = {};
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x1_matSetIdx = x1e0_ballMatIdx;
flags.x4_color = zeus::CColor(1.f, spinAlpha * alpha);
x184_ballModelData->Render(mgr, x10_xf * zeus::CTransform::RotateZ(spinAngle) * zeus::CTransform::Scale(spinScale),
x24c_actorLights.get(), flags);
}
}
if (x270_24_hasSpiderBall)
{
CGraphics::SetModelMatrix(x10_xf);
CModelFlags flags = {};
flags.x1_matSetIdx = x1e4_glassMatIdx;
x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights);
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
flags.x4_color = zeus::CColor::skWhite;
x1d4_spiderBallGlass->Draw(flags);
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = alpha;
x1d4_spiderBallGlass->Draw(flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = x6c_ballPulseFactor * alpha * itemPulse;
x1d4_spiderBallGlass->Draw(flags);
}
if (phazonSuit && alpha > 0.1f)
{
float radius = zeus::clamp(0.2f, (10.f - (xc0_userZoom >= 0.f ? xc0_userZoom : -xc0_userZoom)) / 20.f, 1.f);
float offset = std::sin(x260_phazonOffsetAngle);
zeus::CColor color = g_tweakGuiColors->GetInvPhazonSuitFilterMod();
color.a = alpha;
g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, alpha), x250_phazonIndirectTexture,
color, radius, 0.1f, offset, offset);
}
}
}
else
{
CModelFlags flags = {};
flags.x1_matSetIdx = x1e0_ballMatIdx;
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
flags.x4_color = zeus::CColor::skWhite;
x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags);
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = alpha;
x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = x6c_ballPulseFactor * alpha * itemPulse;
x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags);
const u8* c = BallGlowColors[x1e8_ballGlowColorIdx];
zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha};
x22c_ballInnerGlowGen->SetModulationColor(color);
if (alpha > 0.f)
{
if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 0)
{
const u8* c = BallTransFlashColors[x1e8_ballGlowColorIdx];
zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha};
x22c_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(color);
if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 1)
{
const u8* c = BallAuxGlowColors[x1e8_ballGlowColorIdx];
zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha};
x22c_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(color);
}
}
x22c_ballInnerGlowGen->Render();
}
if (x270_24_hasSpiderBall)
{
CGraphics::SetModelMatrix(x10_xf);
CModelFlags flags = {};
flags.x1_matSetIdx = x1e4_glassMatIdx;
x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights);
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
flags.x4_color = zeus::CColor::skWhite;
x1d4_spiderBallGlass->Draw(flags);
flags.m_extendedShader = EExtendedShader::Lighting;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = alpha;
x1d4_spiderBallGlass->Draw(flags);
flags.m_extendedShader = EExtendedShader::ForcedAdditive;
flags.x4_color = zeus::CColor::skWhite;
flags.x4_color.a = x6c_ballPulseFactor * alpha * itemPulse;
x1d4_spiderBallGlass->Draw(flags);
}
}
if (x238_ballTransitionFlashGen)
{
const u8* c = BallTransFlashColors[x1e8_ballGlowColorIdx];
zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f};
x238_ballTransitionFlashGen->SetModulationColor(color);
x238_ballTransitionFlashGen->Render();
}
CGraphics::DisableAllLights();
} }
void CSamusDoll::Touch() void CSamusDoll::Touch()
{ {
if (!CheckLoadComplete()) if (!CheckLoadComplete())
return; return;
xc8_suitModel1->AnimationData()->PreRender(); xc8_suitModel0->AnimationData()->PreRender();
x134_suitModelBoots->AnimationData()->PreRender(); x134_suitModelBoots->AnimationData()->PreRender();
x184_ballModelData->AnimationData()->PreRender(); x184_ballModelData->AnimationData()->PreRender();
xc8_suitModel1->Touch(CModelData::EWhichModel::Normal, 0); xc8_suitModel0->Touch(CModelData::EWhichModel::Normal, 0);
x134_suitModelBoots->Touch(CModelData::EWhichModel::Normal, 0); x134_suitModelBoots->Touch(CModelData::EWhichModel::Normal, 0);
x184_ballModelData->Touch(CModelData::EWhichModel::Normal, 0); x184_ballModelData->Touch(CModelData::EWhichModel::Normal, 0);
} }
void CSamusDoll::SetupLights() void CSamusDoll::SetupLights()
{ {
x23c_lights[0] = CLight::BuildDirectional(xb0_rot.toTransform().basis[1], zeus::CColor(0.75f, 1.f)); x23c_lights[0] = CLight::BuildDirectional(xb0_userRot.toTransform().basis[1], zeus::CColor(0.75f, 1.f));
x24c_actorLights->BuildFakeLightList(x23c_lights, zeus::CColor::skBlack); x24c_actorLights->BuildFakeLightList(x23c_lights, zeus::CColor::skBlack);
} }
void CSamusDoll::CheckTransition(bool morphballComplete) void CSamusDoll::SetInMorphball(bool morphball)
{ {
if (x54_ > 0.f) if (x54_remTransitionTime > 0.f)
return; return;
if (x4d_morphballComplete == morphballComplete) if (x4d_selectedMorphball == morphball)
return; return;
x4d_morphballComplete = morphballComplete; x4d_selectedMorphball = morphball;
SetTransitionAnimation(); SetTransitionAnimation();
} }
void CSamusDoll::SetTransitionAnimation() void CSamusDoll::SetTransitionAnimation()
{ {
if (!x4c_intoBallComplete) if (!x4c_completedMorphball)
{ {
xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); /* Into morphball */
xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false);
x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false);
x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(0); x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(0);
} }
else if (!x4d_morphballComplete) else if (!x4d_selectedMorphball)
{ {
xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); /* Outta morphball */
xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false);
x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false);
x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(1); x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(1);
} }
} }
@ -324,7 +757,7 @@ void CSamusDoll::SetRotation(float xDelta, float zDelta, float f3)
if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f)
return; return;
SetRotationSfxPlaying(xDelta != 0.f || zDelta != 0.f); SetRotationSfxPlaying(xDelta != 0.f || zDelta != 0.f);
zeus::CEulerAngles angles(xb0_rot); zeus::CEulerAngles angles(xb0_userRot);
zeus::CRelAngle angX(angles.x); zeus::CRelAngle angX(angles.x);
zeus::CRelAngle angZ(angles.z); zeus::CRelAngle angZ(angles.z);
@ -345,7 +778,7 @@ void CSamusDoll::SetRotation(float xDelta, float zDelta, float f3)
zeus::CQuaternion quat; zeus::CQuaternion quat;
quat.rotateZ(angZ); quat.rotateZ(angZ);
quat.rotateX(angX); quat.rotateX(angX);
xb0_rot = quat; xb0_userRot = quat;
} }
void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold) void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold)
@ -353,13 +786,13 @@ void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold)
if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f)
return; return;
zeus::CVector3f oldOffset = xa4_offset; zeus::CVector3f oldOffset = xa4_offset;
zeus::CMatrix3f rotMtx = xb0_rot.toTransform().basis; zeus::CMatrix3f rotMtx = xb0_userRot.toTransform().basis;
xa4_offset += rotMtx * zeus::CVector3f(offset.x, 0.f, offset.z); xa4_offset += rotMtx * zeus::CVector3f(offset.x, 0.f, offset.z);
SetOffsetSfxPlaying((oldOffset - xa4_offset).magnitude() > sfxThreshold); SetOffsetSfxPlaying((oldOffset - xa4_offset).magnitude() > sfxThreshold);
float oldZoom = xc0_zoom; float oldZoom = xc0_userZoom;
xc0_zoom = zeus::clamp(-4.f, xc0_zoom + offset.y, -2.2f); xc0_userZoom = zeus::clamp(-4.f, xc0_userZoom + offset.y, -2.2f);
bool zoomSfx = std::fabs(xc0_zoom - oldZoom) > sfxThreshold; bool zoomSfx = std::fabs(xc0_userZoom - oldZoom) > sfxThreshold;
float zoomDelta = offset.y - (xc0_zoom - oldZoom); float zoomDelta = offset.y - (xc0_userZoom - oldZoom);
zeus::CVector3f newOffset = rotMtx[1] * zoomDelta + xa4_offset; zeus::CVector3f newOffset = rotMtx[1] * zoomDelta + xa4_offset;
zeus::CVector3f delta = newOffset - xa4_offset; zeus::CVector3f delta = newOffset - xa4_offset;
oldOffset = xa4_offset; oldOffset = xa4_offset;
@ -388,7 +821,7 @@ void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold)
xa4_offset = delta.normalized() + skInitialOffset; xa4_offset = delta.normalized() + skInitialOffset;
} }
void CSamusDoll::BeginViewInterpolate(bool zoomOut) void CSamusDoll::BeginViewInterpolate(bool zoomIn)
{ {
if (xc4_viewInterp == 0.f) if (xc4_viewInterp == 0.f)
{ {
@ -402,12 +835,11 @@ void CSamusDoll::BeginViewInterpolate(bool zoomOut)
CSfxManager::SfxStart(1441, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); CSfxManager::SfxStart(1441, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
} }
xc4_viewInterp = zoomOut ? FLT_EPSILON : (-1.f + FLT_EPSILON); xc4_viewInterp = zoomIn ? FLT_EPSILON : (-1.f + FLT_EPSILON);
x84_interpStartOffset = xa4_offset; x84_interpStartOffset = xa4_offset;
x90_interpStartRot = xb0_rot; x90_userInterpRot = xb0_userRot;
xa0_interpStartZoom = xc0_zoom; xa0_userInterpZoom = xc0_userZoom;
x80_fixedZoom = zoomIn ? -2.2f : -3.6f;
x80_ = zoomOut ? -2.2f : -3.6f;
} }
} }

View File

@ -18,34 +18,33 @@ namespace MP1
class CSamusDoll class CSamusDoll
{ {
std::vector<CToken> x0_depToks; std::vector<CToken> x0_depToks;
zeus::CTransform x10_; zeus::CTransform x10_xf;
float x40_ = 0.f; float x40_alphaIn = 0.f;
CPlayerState::EPlayerSuit x44_suit; CPlayerState::EPlayerSuit x44_suit;
CPlayerState::EBeamId x48_beam; CPlayerState::EBeamId x48_beam;
bool x4c_intoBallComplete = false; bool x4c_completedMorphball = false;
bool x4d_morphballComplete = false; bool x4d_selectedMorphball = false;
float x50_ = 1.f; float x50_totalTransitionTime = 1.f;
float x54_ = 0.f; float x54_remTransitionTime = 0.f;
float x58_ = 0.f; float x58_suitPulseFactor = 0.f;
float x5c_ = 0.f; float x5c_beamPulseFactor = 0.f;
float x60_ = 0.f; float x60_grapplePulseFactor = 0.f;
float x64_ = 0.f; float x64_bootsPulseFactor = 0.f;
float x68_ = 0.f; float x68_visorPulseFactor = 0.f;
float x6c_ = 0.f; float x6c_ballPulseFactor = 0.f;
zeus::CQuaternion x70_; zeus::CQuaternion x70_fixedRot;
float x80_ = -3.6f; float x80_fixedZoom = -3.6f;
zeus::CVector3f x84_interpStartOffset = skInitialOffset; zeus::CVector3f x84_interpStartOffset = skInitialOffset;
zeus::CQuaternion x90_interpStartRot; zeus::CQuaternion x90_userInterpRot;
float xa0_interpStartZoom = -3.6f; float xa0_userInterpZoom = -3.6f;
zeus::CVector3f xa4_offset = skInitialOffset; zeus::CVector3f xa4_offset = skInitialOffset;
zeus::CQuaternion xb0_rot; zeus::CQuaternion xb0_userRot;
float xc0_zoom = -3.6f; float xc0_userZoom = -3.6f;
float xc4_viewInterp = 0.f; float xc4_viewInterp = 0.f;
std::experimental::optional<CModelData> xc8_suitModel1; std::experimental::optional<CModelData> xc8_suitModel0;
rstl::reserved_vector<TCachedToken<CSkinnedModel>, 2> x118_suitModel1and2; rstl::reserved_vector<TCachedToken<CSkinnedModel>, 2> x118_suitModel1and2;
std::experimental::optional<CModelData> x134_suitModelBoots; std::experimental::optional<CModelData> x134_suitModelBoots;
std::experimental::optional<CModelData> x184_ballModelData; std::experimental::optional<CModelData> x184_ballModelData;
bool x1d0_ = false;
TLockedToken<CModel> x1d4_spiderBallGlass; TLockedToken<CModel> x1d4_spiderBallGlass;
u32 x1e0_ballMatIdx; u32 x1e0_ballMatIdx;
u32 x1e4_glassMatIdx; u32 x1e4_glassMatIdx;
@ -58,10 +57,11 @@ class CSamusDoll
TLockedToken<CGenDescription> x224_ballInnerGlow; TLockedToken<CGenDescription> x224_ballInnerGlow;
std::unique_ptr<CElementGen> x22c_ballInnerGlowGen; std::unique_ptr<CElementGen> x22c_ballInnerGlowGen;
TLockedToken<CGenDescription> x230_ballTransitionFlash; TLockedToken<CGenDescription> x230_ballTransitionFlash;
std::unique_ptr<CElementGen> x238_ballTransitionFlashGen;
std::vector<CLight> x23c_lights; std::vector<CLight> x23c_lights;
std::unique_ptr<CActorLights> x24c_actorLights; std::unique_ptr<CActorLights> x24c_actorLights;
bool x25c_ = false; TLockedToken<CTexture> x250_phazonIndirectTexture; // Used to be optional
float x260_ = 0.f; zeus::CRelAngle x260_phazonOffsetAngle;
CSfxHandle x264_offsetSfx; CSfxHandle x264_offsetSfx;
CSfxHandle x268_rotateSfx; CSfxHandle x268_rotateSfx;
CSfxHandle x26c_zoomSfx; CSfxHandle x26c_zoomSfx;
@ -71,11 +71,11 @@ class CSamusDoll
{ {
bool x270_24_hasSpiderBall : 1; bool x270_24_hasSpiderBall : 1;
bool x270_25_hasGrappleBeam : 1; bool x270_25_hasGrappleBeam : 1;
bool x270_26_ : 1; bool x270_26_pulseSuit : 1;
bool x270_27_ : 1; bool x270_27_pulseBeam : 1;
bool x270_28_ : 1; bool x270_28_pulseGrapple : 1;
bool x270_29_ : 1; bool x270_29_pulseBoots : 1;
bool x270_30_ : 1; bool x270_30_pulseVisor : 1;
bool x270_31_loaded : 1; bool x270_31_loaded : 1;
}; };
u32 _dummy = 0; u32 _dummy = 0;
@ -98,10 +98,15 @@ public:
void Update(float dt, CRandom16& rand); void Update(float dt, CRandom16& rand);
void Draw(const CStateManager& mgr, float alpha); void Draw(const CStateManager& mgr, float alpha);
void Touch(); void Touch();
void CheckTransition(bool morphballComplete); void SetInMorphball(bool morphballComplete);
void SetRotation(float xDelta, float zDelta, float); void SetRotation(float xDelta, float zDelta, float);
void SetOffset(const zeus::CVector3f& offset, float sfxThreshold); void SetOffset(const zeus::CVector3f& offset, float sfxThreshold);
void BeginViewInterpolate(bool zoomOut); void BeginViewInterpolate(bool zoomOut);
void SetPulseSuit(bool b) { x270_26_pulseSuit = b; }
void SetPulseVisor(bool b) { x270_30_pulseVisor = b; }
void SetPulseBoots(bool b) { x270_29_pulseBoots = b; }
void SetPulseGrapple(bool b) { x270_28_pulseGrapple = b; }
void SetPulseBeam(bool b) { x270_27_pulseBeam = b; }
}; };
} }

View File

@ -11,6 +11,7 @@
#include "Graphics/Shaders/CEnergyBarShader.hpp" #include "Graphics/Shaders/CEnergyBarShader.hpp"
#include "Graphics/Shaders/CRadarPaintShader.hpp" #include "Graphics/Shaders/CRadarPaintShader.hpp"
#include "Graphics/Shaders/CMapSurfaceShader.hpp" #include "Graphics/Shaders/CMapSurfaceShader.hpp"
#include "Graphics/Shaders/CPhazonSuitFilter.hpp"
#include "Character/CCharLayoutInfo.hpp" #include "Character/CCharLayoutInfo.hpp"
#include "Audio/CStreamAudioManager.hpp" #include "Audio/CStreamAudioManager.hpp"
#include "CGBASupport.hpp" #include "CGBASupport.hpp"
@ -29,6 +30,7 @@ URDE_DECL_SPECIALIZE_SHADER(CFogVolumeFilter)
URDE_DECL_SPECIALIZE_SHADER(CEnergyBarShader) URDE_DECL_SPECIALIZE_SHADER(CEnergyBarShader)
URDE_DECL_SPECIALIZE_SHADER(CRadarPaintShader) URDE_DECL_SPECIALIZE_SHADER(CRadarPaintShader)
URDE_DECL_SPECIALIZE_SHADER(CMapSurfaceShader) URDE_DECL_SPECIALIZE_SHADER(CMapSurfaceShader)
URDE_DECL_SPECIALIZE_SHADER(CPhazonSuitFilter)
URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CColoredQuadFilter) URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CColoredQuadFilter)
URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilter) URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilter)
URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilterAlpha) URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilterAlpha)
@ -222,6 +224,7 @@ CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory,
TShader<CEnergyBarShader>::Initialize(); TShader<CEnergyBarShader>::Initialize();
TShader<CRadarPaintShader>::Initialize(); TShader<CRadarPaintShader>::Initialize();
TShader<CMapSurfaceShader>::Initialize(); TShader<CMapSurfaceShader>::Initialize();
TShader<CPhazonSuitFilter>::Initialize();
TMultiBlendShader<CColoredQuadFilter>::Initialize(); TMultiBlendShader<CColoredQuadFilter>::Initialize();
TMultiBlendShader<CTexturedQuadFilter>::Initialize(); TMultiBlendShader<CTexturedQuadFilter>::Initialize();
TMultiBlendShader<CTexturedQuadFilterAlpha>::Initialize(); TMultiBlendShader<CTexturedQuadFilterAlpha>::Initialize();
@ -354,6 +357,7 @@ void CMain::Shutdown()
TShader<CEnergyBarShader>::Shutdown(); TShader<CEnergyBarShader>::Shutdown();
TShader<CRadarPaintShader>::Shutdown(); TShader<CRadarPaintShader>::Shutdown();
TShader<CMapSurfaceShader>::Shutdown(); TShader<CMapSurfaceShader>::Shutdown();
TShader<CPhazonSuitFilter>::Shutdown();
TMultiBlendShader<CColoredQuadFilter>::Shutdown(); TMultiBlendShader<CColoredQuadFilter>::Shutdown();
TMultiBlendShader<CTexturedQuadFilter>::Shutdown(); TMultiBlendShader<CTexturedQuadFilter>::Shutdown();
TMultiBlendShader<CTexturedQuadFilterAlpha>::Shutdown(); TMultiBlendShader<CTexturedQuadFilterAlpha>::Shutdown();

View File

@ -283,7 +283,7 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
EModelOrientationType orientType, EModelOrientationType orientType,
EOptionalSystemFlags flags) EOptionalSystemFlags flags)
: x1c_genDesc(gen), x28_orientType(orientType), : x1c_genDesc(gen), x28_orientType(orientType),
x226_enableOPTS((flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None), x230_randState(x74_randomSeed) x226_enableOPTS((flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None), x27c_randState(x94_randomSeed)
{ {
CGenDescription* desc = x1c_genDesc.GetObj(); CGenDescription* desc = x1c_genDesc.GetObj();
@ -297,9 +297,9 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
{ {
int seedVal; int seedVal;
seedElem->GetValue(x50_curFrame, seedVal); seedElem->GetValue(x50_curFrame, seedVal);
x74_randomSeed = seedVal; x94_randomSeed = seedVal;
} }
x230_randState.SetSeed(x74_randomSeed); x27c_randState.SetSeed(x94_randomSeed);
++g_ParticleSystemAliveCount; ++g_ParticleSystemAliveCount;
x224_25_LIT_ = desc->x44_29_x30_29_LIT_; x224_25_LIT_ = desc->x44_29_x30_29_LIT_;
x224_26_AAPH = desc->x44_26_x30_26_AAPH; x224_26_AAPH = desc->x44_26_x30_26_AAPH;
@ -318,7 +318,7 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
CIntElement* cssdElem = desc->xa0_x8c_CSSD.get(); CIntElement* cssdElem = desc->xa0_x8c_CSSD.get();
if (cssdElem) if (cssdElem)
cssdElem->GetValue(0, x244_CSSD); cssdElem->GetValue(0, x2a0_CSSD);
SChildGeneratorDesc& idts = desc->xa4_x90_IDTS; SChildGeneratorDesc& idts = desc->xa4_x90_IDTS;
if (idts.m_found) if (idts.m_found)
@ -342,34 +342,52 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
CIntElement* pisyElem = desc->xc8_xb4_PISY.get(); CIntElement* pisyElem = desc->xc8_xb4_PISY.get();
if (pisyElem) if (pisyElem)
{ {
pisyElem->GetValue(0, x25c_PISY); pisyElem->GetValue(0, x2a8_PISY);
if (x25c_PISY <= 0) if (x2a8_PISY <= 0)
x25c_PISY = 1; x2a8_PISY = 1;
} }
CIntElement* sisyElem = desc->xcc_xb8_SISY.get(); CIntElement* sisyElem = desc->xcc_xb8_SISY.get();
if (sisyElem) if (sisyElem)
pisyElem->GetValue(0, x258_SISY); pisyElem->GetValue(0, x2a4_SISY);
CIntElement* sssdElem = desc->xe4_xd0_SSSD.get(); CIntElement* sssdElem = desc->xe4_xd0_SSSD.get();
if (sssdElem) if (sssdElem)
sssdElem->GetValue(0, x270_SSSD); sssdElem->GetValue(0, x2ac_SSSD);
CVectorElement* sspoElem = desc->xe8_xd4_SSPO.get(); CVectorElement* sspoElem = desc->xe8_xd4_SSPO.get();
if (sspoElem) if (sspoElem)
sspoElem->GetValue(0, x274_SSPO); {
sspoElem->GetValue(0, x2b0_SSPO);
if (!sspoElem->IsFastConstant())
x26c_24_ = true;
}
CIntElement* sesdElem = desc->xf8_xe4_SESD.get(); CIntElement* sesdElem = desc->xf8_xe4_SESD.get();
if (sesdElem) if (sesdElem)
sesdElem->GetValue(0, x290_SESD); sesdElem->GetValue(0, x2bc_SESD);
CVectorElement* sepoElem = desc->xfc_xe8_SEPO.get(); CVectorElement* sepoElem = desc->xfc_xe8_SEPO.get();
if (sepoElem) if (sepoElem)
sepoElem->GetValue(0, x294_SEPO); {
sepoElem->GetValue(0, x2c0_SEPO);
if (!sepoElem->IsFastConstant())
x26c_24_ = true;
}
CVectorElement* pofsElem = desc->x18_xc_POFS.get();
if (pofsElem)
{
pofsElem->GetValue(x50_curFrame, xf4_POFS);
if (!pofsElem->IsFastConstant())
x26c_24_ = true;
}
CIntElement* psltElem = desc->xc_x0_PSLT.get(); CIntElement* psltElem = desc->xc_x0_PSLT.get();
if (psltElem) if (psltElem)
psltElem->GetValue(0, x214_PSLT); psltElem->GetValue(0, x268_PSLT);
else
x268_PSLT = INT_MAX;
/* Removed from retail /* Removed from retail
CVectorElement* psivElem = desc->x0_PSIV.get(); CVectorElement* psivElem = desc->x0_PSIV.get();
@ -379,21 +397,17 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
CIntElement* maxpElem = desc->x28_x1c_MAXP.get(); CIntElement* maxpElem = desc->x28_x1c_MAXP.get();
if (maxpElem) if (maxpElem)
maxpElem->GetValue(x50_curFrame, x70_MAXP); maxpElem->GetValue(x50_curFrame, x90_MAXP);
x2c_particleLists.reserve(x70_MAXP); x30_particleLists.reserve(x90_MAXP);
if (x28_orientType == EModelOrientationType::One) if (x28_orientType == EModelOrientationType::One)
{ {
x3c_parentMatrices.insert(x3c_parentMatrices.end(), x70_MAXP, x60_parentMatrices.insert(x60_parentMatrices.end(), x90_MAXP,
zeus::CMatrix3f::skIdentityMatrix3f); zeus::CMatrix3f::skIdentityMatrix3f);
} }
x225_26_LINE = desc->x44_24_x30_24_LINE; x26c_31_LINE = desc->x44_24_x30_24_LINE;
x225_27_FXLL = desc->x44_25_x30_25_FXLL; x26d_24_FXLL = desc->x44_25_x30_25_FXLL;
CVectorElement* pofsElem = desc->x18_xc_POFS.get();
if (pofsElem)
pofsElem->GetValue(x50_curFrame, x94_POFS);
CIntElement* ltypElem = desc->x100_xec_LTYP.get(); CIntElement* ltypElem = desc->x100_xec_LTYP.get();
if (ltypElem) if (ltypElem)
@ -404,16 +418,16 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
{ {
case LightType::None: case LightType::None:
default: default:
x2dc_lightType = LightType::None; x308_lightType = LightType::None;
break; break;
case LightType::Directional: case LightType::Directional:
x2dc_lightType = LightType::Directional; x308_lightType = LightType::Directional;
break; break;
case LightType::Custom: case LightType::Custom:
x2dc_lightType = LightType::Custom; x308_lightType = LightType::Custom;
break; break;
case LightType::Spot: case LightType::Spot:
x2dc_lightType = LightType::Spot; x308_lightType = LightType::Spot;
break; break;
} }
} }
@ -426,32 +440,32 @@ CElementGen::CElementGen(const TToken<CGenDescription>& gen,
switch (EFalloffType(lfot)) switch (EFalloffType(lfot))
{ {
case EFalloffType::Constant: case EFalloffType::Constant:
x300_falloffType = EFalloffType::Constant; x32c_falloffType = EFalloffType::Constant;
break; break;
case EFalloffType::Linear: case EFalloffType::Linear:
default: default:
x300_falloffType = EFalloffType::Linear; x32c_falloffType = EFalloffType::Linear;
break; break;
case EFalloffType::Quadratic: case EFalloffType::Quadratic:
x300_falloffType = EFalloffType::Quadratic; x32c_falloffType = EFalloffType::Quadratic;
break; break;
} }
} }
if (x225_26_LINE) if (x26c_31_LINE)
{ {
CUVElement* texr = desc->x54_x40_TEXR.get(); CUVElement* texr = desc->x54_x40_TEXR.get();
boo::ITexture* tex = nullptr; boo::ITexture* tex = nullptr;
if (texr) if (texr)
tex = texr->GetValueTexture(0).GetObj()->GetBooTexture(); tex = texr->GetValueTexture(0).GetObj()->GetBooTexture();
int maxVerts = (x70_MAXP == 0 ? 256 : x70_MAXP); int maxVerts = (x90_MAXP == 0 ? 256 : x90_MAXP);
m_lineRenderer.reset(new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, m_lineRenderer.reset(new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines,
maxVerts * 2, tex, x224_26_AAPH)); maxVerts * 2, tex, x224_26_AAPH));
} }
else else
{ {
m_shaderClass = CElementGenShaders::GetShaderClass(*this); m_shaderClass = CElementGenShaders::GetShaderClass(*this);
size_t maxInsts = x224_29_MBLR ? (m_maxMBSP * x70_MAXP) : x70_MAXP; size_t maxInsts = x224_29_MBLR ? (m_maxMBSP * x90_MAXP) : x90_MAXP;
maxInsts = (maxInsts == 0 ? 256 : maxInsts); maxInsts = (maxInsts == 0 ? 256 : maxInsts);
m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{ {
@ -494,7 +508,7 @@ void CElementGen::Update(double t)
bool CElementGen::InternalUpdate(double dt) bool CElementGen::InternalUpdate(double dt)
{ {
CGlobalRandom gr(x230_randState); CGlobalRandom gr(x27c_randState);
CGenDescription* desc = x1c_genDesc.GetObj(); CGenDescription* desc = x1c_genDesc.GetObj();
double dt1 = 1.0 / 60.0; double dt1 = 1.0 / 60.0;
@ -533,7 +547,7 @@ bool CElementGen::InternalUpdate(double dt)
CRealElement* grteElem = desc->x2c_x20_GRTE.get(); CRealElement* grteElem = desc->x2c_x20_GRTE.get();
if (grteElem->GetValue(x50_curFrame, grte)) if (grteElem->GetValue(x50_curFrame, grte))
{ {
x2c_particleLists.clear(); x30_particleLists.clear();
return true; return true;
} }
@ -542,16 +556,16 @@ bool CElementGen::InternalUpdate(double dt)
int genCount = floorf(x6c_generatorRemainder); int genCount = floorf(x6c_generatorRemainder);
x6c_generatorRemainder = x6c_generatorRemainder - genCount; x6c_generatorRemainder = x6c_generatorRemainder - genCount;
if (!x68_particleEmission || x50_curFrame >= x214_PSLT) if (!x68_particleEmission || x50_curFrame >= x268_PSLT)
genCount = 0; genCount = 0;
CIntElement* maxpElem = desc->x28_x1c_MAXP.get(); CIntElement* maxpElem = desc->x28_x1c_MAXP.get();
if (maxpElem) if (maxpElem)
maxpElem->GetValue(x50_curFrame, x70_MAXP); maxpElem->GetValue(x50_curFrame, x90_MAXP);
UpdateExistingParticles(); UpdateExistingParticles();
CParticleGlobals::SetParticleLifetime(x214_PSLT); CParticleGlobals::SetParticleLifetime(x268_PSLT);
bool oldBoolVal = s_inCreateNewParticles; bool oldBoolVal = s_inCreateNewParticles;
s_inCreateNewParticles = true; s_inCreateNewParticles = true;
CreateNewParticles(genCount); CreateNewParticles(genCount);
@ -560,7 +574,7 @@ bool CElementGen::InternalUpdate(double dt)
UpdatePSTranslationAndOrientation(); UpdatePSTranslationAndOrientation();
UpdateChildParticleSystems(1 / 60.0); UpdateChildParticleSystems(1 / 60.0);
if (x2dc_lightType != LightType::None) if (x308_lightType != LightType::None)
UpdateLightParameters(); UpdateLightParameters();
++frameUpdateCount; ++frameUpdateCount;
@ -598,8 +612,8 @@ void CElementGen::UpdateExistingParticles()
x208_activeParticleCount = 0; x208_activeParticleCount = 0;
CParticleGlobals::SetEmitterTime(x50_curFrame); CParticleGlobals::SetEmitterTime(x50_curFrame);
for (std::vector<CParticleListItem>::iterator p = x2c_particleLists.begin(); for (std::vector<CParticleListItem>::iterator p = x30_particleLists.begin();
p != x2c_particleLists.end();) p != x30_particleLists.end();)
{ {
CElementGen::CParticle& particle = g_StaticParticleList[p->x0_partIdx]; CElementGen::CParticle& particle = g_StaticParticleList[p->x0_partIdx];
g_currentParticle = &particle; g_currentParticle = &particle;
@ -607,21 +621,21 @@ void CElementGen::UpdateExistingParticles()
if (particle.x0_endFrame < x50_curFrame) if (particle.x0_endFrame < x50_curFrame)
{ {
g_StaticFreeList[++g_FreeIndex] = p->x0_partIdx; g_StaticFreeList[++g_FreeIndex] = p->x0_partIdx;
if (p+1 == x2c_particleLists.end()) if (p+1 == x30_particleLists.end())
{ {
x2c_particleLists.pop_back(); x30_particleLists.pop_back();
break; break;
} }
else else
{ {
*p = *(x2c_particleLists.end()-1); *p = *(x30_particleLists.end()-1);
if (x28_orientType == EModelOrientationType::One) if (x28_orientType == EModelOrientationType::One)
{ {
size_t i = p - x2c_particleLists.begin(); size_t i = p - x30_particleLists.begin();
x3c_parentMatrices[i] = x3c_parentMatrices[x2c_particleLists.size()-1]; x60_parentMatrices[i] = x60_parentMatrices[x30_particleLists.size()-1];
} }
x2c_particleLists.pop_back(); x30_particleLists.pop_back();
if (p != x2c_particleLists.end()) if (p != x30_particleLists.end())
if (particle.x0_endFrame < x50_curFrame) if (particle.x0_endFrame < x50_curFrame)
continue; continue;
} }
@ -706,7 +720,7 @@ void CElementGen::UpdateExistingParticles()
} }
} }
if (x225_26_LINE) if (x26c_31_LINE)
{ {
CRealElement* leng = desc->x20_x14_LENG.get(); CRealElement* leng = desc->x20_x14_LENG.get();
if (leng) if (leng)
@ -743,13 +757,13 @@ void CElementGen::CreateNewParticles(int count)
if (!g_StaticListInitialized) if (!g_StaticListInitialized)
Initialize(); Initialize();
if (!count || x2c_particleLists.size() >= x70_MAXP) if (!count || x30_particleLists.size() >= x90_MAXP)
return; return;
if (count + x2c_particleLists.size() > x70_MAXP) if (count + x30_particleLists.size() > x90_MAXP)
count = x70_MAXP - x2c_particleLists.size(); count = x90_MAXP - x30_particleLists.size();
CGlobalRandom gr(x230_randState); CGlobalRandom gr(x27c_randState);
x2c_particleLists.reserve(x70_MAXP); x30_particleLists.reserve(x90_MAXP);
for (int i=0 ; i<count ; ++i) for (int i=0 ; i<count ; ++i)
{ {
@ -757,10 +771,10 @@ void CElementGen::CreateNewParticles(int count)
return; return;
s16 staticIdx = g_StaticFreeList[g_FreeIndex]; s16 staticIdx = g_StaticFreeList[g_FreeIndex];
x2c_particleLists.emplace_back(staticIdx); x30_particleLists.emplace_back(staticIdx);
++x208_activeParticleCount; ++x208_activeParticleCount;
if (x28_orientType == EModelOrientationType::One) if (x28_orientType == EModelOrientationType::One)
x3c_parentMatrices[x2c_particleLists.size()-1] = x178_orientation.buildMatrix3f(); x60_parentMatrices[x30_particleLists.size()-1] = x178_orientation.buildMatrix3f();
CElementGen::CParticle& particle = g_StaticParticleList[staticIdx]; CElementGen::CParticle& particle = g_StaticParticleList[staticIdx];
particle.x28_startFrame = x50_curFrame; particle.x28_startFrame = x50_curFrame;
@ -783,18 +797,18 @@ void CElementGen::CreateNewParticles(int count)
emtr->GetValue(x210_curEmitterFrame, particle.x4_pos, particle.x1c_vel); emtr->GetValue(x210_curEmitterFrame, particle.x4_pos, particle.x1c_vel);
zeus::CVector3f compXf1 = (xdc_globalScaleTransformInverse * x148_localScaleTransformInverse) * x7c_translation; zeus::CVector3f compXf1 = (xdc_globalScaleTransformInverse * x148_localScaleTransformInverse) * x7c_translation;
zeus::CVector3f compXf2 = x178_orientation * particle.x4_pos; zeus::CVector3f compXf2 = x178_orientation * particle.x4_pos;
particle.x4_pos = compXf1 + compXf2 + x94_POFS; particle.x4_pos = compXf1 + compXf2 + xf4_POFS;
particle.x1c_vel = x178_orientation * particle.x1c_vel; particle.x1c_vel = x178_orientation * particle.x1c_vel;
} }
else else
{ {
zeus::CVector3f compXf1 = (xdc_globalScaleTransformInverse * x148_localScaleTransformInverse) * x7c_translation; zeus::CVector3f compXf1 = (xdc_globalScaleTransformInverse * x148_localScaleTransformInverse) * x7c_translation;
particle.x4_pos = compXf1 + x94_POFS; particle.x4_pos = compXf1 + xf4_POFS;
particle.x1c_vel.zeroOut(); particle.x1c_vel.zeroOut();
} }
particle.x10_prevPos = particle.x4_pos; particle.x10_prevPos = particle.x4_pos;
if (x225_26_LINE) if (x26c_31_LINE)
{ {
CRealElement* leng = desc->x20_x14_LENG.get(); CRealElement* leng = desc->x20_x14_LENG.get();
if (leng) if (leng)
@ -834,8 +848,8 @@ void CElementGen::UpdatePSTranslationAndOrientation()
{ {
CGenDescription* desc = x1c_genDesc.GetObj(); CGenDescription* desc = x1c_genDesc.GetObj();
CGlobalRandom gr(x230_randState); CGlobalRandom gr(x27c_randState);
if (x214_PSLT < x50_curFrame) if (x268_PSLT < x50_curFrame)
return; return;
/* Removed from retail /* Removed from retail
@ -871,15 +885,15 @@ void CElementGen::UpdatePSTranslationAndOrientation()
CVectorElement* pofs = desc->x18_xc_POFS.get(); CVectorElement* pofs = desc->x18_xc_POFS.get();
if (pofs) if (pofs)
pofs->GetValue(x50_curFrame, x94_POFS); pofs->GetValue(x50_curFrame, xf4_POFS);
CVectorElement* sspo = desc->xe8_xd4_SSPO.get(); CVectorElement* sspo = desc->xe8_xd4_SSPO.get();
if (sspo) if (sspo)
sspo->GetValue(x50_curFrame, x274_SSPO); sspo->GetValue(x50_curFrame, x2b0_SSPO);
CVectorElement* sepo = desc->xfc_xe8_SEPO.get(); CVectorElement* sepo = desc->xfc_xe8_SEPO.get();
if (sepo) if (sepo)
sspo->GetValue(x50_curFrame, x294_SEPO); sspo->GetValue(x50_curFrame, x2c0_SEPO);
} }
CElementGen* CElementGen::ConstructChildParticleSystem(const TToken<CGenDescription>& desc) CElementGen* CElementGen::ConstructChildParticleSystem(const TToken<CGenDescription>& desc)
@ -901,9 +915,9 @@ void CElementGen::UpdateChildParticleSystems(double dt)
{ {
CGenDescription* desc = x1c_genDesc.GetObj(); CGenDescription* desc = x1c_genDesc.GetObj();
CGlobalRandom gr(x230_randState); CGlobalRandom gr(x27c_randState);
SChildGeneratorDesc& icts = desc->x8c_x78_ICTS; SChildGeneratorDesc& icts = desc->x8c_x78_ICTS;
if (icts.m_found && x64_prevFrame != x50_curFrame && x244_CSSD == x50_curFrame) if (icts.m_found && x64_prevFrame != x50_curFrame && x2a0_CSSD == x50_curFrame)
{ {
int ncsyVal = 1; int ncsyVal = 1;
CIntElement* ncsy = desc->x9c_x88_NCSY.get(); CIntElement* ncsy = desc->x9c_x88_NCSY.get();
@ -913,47 +927,47 @@ void CElementGen::UpdateChildParticleSystems(double dt)
CGenDescription* ictsDesc = icts.m_token.GetObj(); CGenDescription* ictsDesc = icts.m_token.GetObj();
if (!(x226_enableOPTS && ictsDesc->x45_31_x32_25_OPTS)) if (!(x226_enableOPTS && ictsDesc->x45_31_x32_25_OPTS))
{ {
x234_activePartChildren.reserve(ncsyVal + x234_activePartChildren.size()); x290_activePartChildren.reserve(ncsyVal + x290_activePartChildren.size());
for (int i=0 ; i<ncsyVal ; ++i) for (int i=0 ; i<ncsyVal ; ++i)
{ {
CElementGen* chGen = ConstructChildParticleSystem(icts.m_token); CElementGen* chGen = ConstructChildParticleSystem(icts.m_token);
x234_activePartChildren.emplace_back(chGen); x290_activePartChildren.emplace_back(chGen);
} }
} }
} }
SChildGeneratorDesc& iits = desc->xb8_xa4_IITS; SChildGeneratorDesc& iits = desc->xb8_xa4_IITS;
if (iits.m_found && x64_prevFrame != x50_curFrame && x50_curFrame < x214_PSLT && if (iits.m_found && x64_prevFrame != x50_curFrame && x50_curFrame < x268_PSLT &&
x68_particleEmission == 1 && x50_curFrame >= x258_SISY && x68_particleEmission == 1 && x50_curFrame >= x2a4_SISY &&
((x50_curFrame - x258_SISY) % x25c_PISY) == 0) ((x50_curFrame - x2a4_SISY) % x2a8_PISY) == 0)
{ {
CGenDescription* iitsDesc = iits.m_token.GetObj(); CGenDescription* iitsDesc = iits.m_token.GetObj();
if (!(x226_enableOPTS && iitsDesc->x45_31_x32_25_OPTS)) if (!(x226_enableOPTS && iitsDesc->x45_31_x32_25_OPTS))
{ {
CElementGen* chGen = ConstructChildParticleSystem(iits.m_token); CElementGen* chGen = ConstructChildParticleSystem(iits.m_token);
x234_activePartChildren.emplace_back(chGen); x290_activePartChildren.emplace_back(chGen);
} }
} }
CSpawnSystemKeyframeData* kssm = desc->xd0_xbc_KSSM.get(); CSpawnSystemKeyframeData* kssm = desc->xd0_xbc_KSSM.get();
if (kssm && x64_prevFrame != x50_curFrame && x50_curFrame < x214_PSLT) if (kssm && x64_prevFrame != x50_curFrame && x50_curFrame < x268_PSLT)
{ {
std::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo>& systems = std::vector<CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo>& systems =
kssm->GetSpawnedSystemsAtFrame(x50_curFrame); kssm->GetSpawnedSystemsAtFrame(x50_curFrame);
x234_activePartChildren.reserve(x234_activePartChildren.size() + systems.size()); x290_activePartChildren.reserve(x290_activePartChildren.size() + systems.size());
for (CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo& system : systems) for (CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo& system : systems)
{ {
TLockedToken<CGenDescription>& token = system.GetToken(); TLockedToken<CGenDescription>& token = system.GetToken();
if (!(x226_enableOPTS && token.GetObj()->x45_31_x32_25_OPTS)) if (!(x226_enableOPTS && token.GetObj()->x45_31_x32_25_OPTS))
{ {
CElementGen* chGen = ConstructChildParticleSystem(token); CElementGen* chGen = ConstructChildParticleSystem(token);
x234_activePartChildren.emplace_back(chGen); x290_activePartChildren.emplace_back(chGen);
} }
} }
} }
SSwooshGeneratorDesc& sswh = desc->xd4_xc0_SSWH; SSwooshGeneratorDesc& sswh = desc->xd4_xc0_SSWH;
if (sswh.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x270_SSSD) if (sswh.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x2ac_SSSD)
{ {
CParticleSwoosh* sswhGen = new CParticleSwoosh(sswh.m_token, 0); CParticleSwoosh* sswhGen = new CParticleSwoosh(sswh.m_token, 0);
sswhGen->SetGlobalTranslation(x88_globalTranslation); sswhGen->SetGlobalTranslation(x88_globalTranslation);
@ -965,7 +979,7 @@ void CElementGen::UpdateChildParticleSystems(double dt)
} }
SElectricGeneratorDesc& selc = desc->xec_xd8_SELC; SElectricGeneratorDesc& selc = desc->xec_xd8_SELC;
if (selc.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x290_SESD) if (selc.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x2bc_SESD)
{ {
CParticleElectric* selcGen = new CParticleElectric(selc.m_token); CParticleElectric* selcGen = new CParticleElectric(selc.m_token);
selcGen->SetGlobalTranslation(x88_globalTranslation); selcGen->SetGlobalTranslation(x88_globalTranslation);
@ -976,7 +990,7 @@ void CElementGen::UpdateChildParticleSystems(double dt)
x280_elscChildren.emplace_back(selcGen); x280_elscChildren.emplace_back(selcGen);
} }
for (auto p = x234_activePartChildren.begin() ; p != x234_activePartChildren.end() ;) for (auto p = x290_activePartChildren.begin() ; p != x290_activePartChildren.end() ;)
{ {
std::unique_ptr<CElementGen>& ch = *p; std::unique_ptr<CElementGen>& ch = *p;
@ -989,7 +1003,7 @@ void CElementGen::UpdateChildParticleSystems(double dt)
ch->Update(dt); ch->Update(dt);
if (ch->IsSystemDeletable()) if (ch->IsSystemDeletable())
{ {
p = x234_activePartChildren.erase(p); p = x290_activePartChildren.erase(p);
continue; continue;
} }
@ -1000,9 +1014,9 @@ void CElementGen::UpdateChildParticleSystems(double dt)
{ {
std::unique_ptr<CElementGen>& ch = *p; std::unique_ptr<CElementGen>& ch = *p;
if (x214_PSLT <= x50_curFrame) if (x268_PSLT <= x50_curFrame)
{ {
if (x214_PSLT == x50_curFrame && x64_prevFrame != x50_curFrame) if (x268_PSLT == x50_curFrame && x64_prevFrame != x50_curFrame)
{ {
ch->SetTranslation(x7c_translation); ch->SetTranslation(x7c_translation);
ch->SetOrientation(x178_orientation); ch->SetOrientation(x178_orientation);
@ -1023,9 +1037,9 @@ void CElementGen::UpdateChildParticleSystems(double dt)
{ {
std::unique_ptr<CParticleSwoosh>& ch = *p; std::unique_ptr<CParticleSwoosh>& ch = *p;
if ((x50_curFrame == x270_SSSD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame) if ((x50_curFrame == x2ac_SSSD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame)
{ {
zeus::CVector3f trans = x7c_translation + x274_SSPO; zeus::CVector3f trans = x7c_translation + x2b0_SSPO;
ch->SetTranslation(trans); ch->SetTranslation(trans);
ch->SetOrientation(x178_orientation); ch->SetOrientation(x178_orientation);
} }
@ -1044,9 +1058,9 @@ void CElementGen::UpdateChildParticleSystems(double dt)
{ {
std::unique_ptr<CParticleElectric>& ch = *p; std::unique_ptr<CParticleElectric>& ch = *p;
if ((x50_curFrame == x290_SESD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame) if ((x50_curFrame == x2bc_SESD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame)
{ {
zeus::CVector3f trans = x7c_translation + x294_SEPO; zeus::CVector3f trans = x7c_translation + x2c0_SEPO;
ch->SetTranslation(trans); ch->SetTranslation(trans);
ch->SetOrientation(x178_orientation); ch->SetOrientation(x178_orientation);
} }
@ -1076,7 +1090,7 @@ void CElementGen::UpdateLightParameters()
if (lint) if (lint)
lint->GetValue(x50_curFrame, x2e4_LINT); lint->GetValue(x50_curFrame, x2e4_LINT);
switch (x2dc_lightType) switch (x308_lightType)
{ {
default: default:
case LightType::None: case LightType::None:
@ -1091,7 +1105,7 @@ void CElementGen::UpdateLightParameters()
if (lfor) if (lfor)
lfor->GetValue(x50_curFrame, x304_LFOR); lfor->GetValue(x50_curFrame, x304_LFOR);
if (x2dc_lightType == LightType::Spot) if (x308_lightType == LightType::Spot)
{ {
CRealElement* lsla = desc->x11c_x108_LSLA.get(); CRealElement* lsla = desc->x11c_x108_LSLA.get();
if (lsla) if (lsla)
@ -1100,7 +1114,7 @@ void CElementGen::UpdateLightParameters()
} }
case LightType::Directional: case LightType::Directional:
{ {
if (x2dc_lightType != LightType::Custom) if (x308_lightType != LightType::Custom)
{ {
CVectorElement* ldir = desc->x110_xfc_LDIR.get(); CVectorElement* ldir = desc->x110_xfc_LDIR.get();
if (ldir) if (ldir)
@ -1114,7 +1128,7 @@ u32 CElementGen::GetParticleCountAllInternal() const
{ {
u32 ret = x208_activeParticleCount; u32 ret = x208_activeParticleCount;
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ret += ch->GetParticleCountAll(); ret += ch->GetParticleCountAll();
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -1125,8 +1139,8 @@ u32 CElementGen::GetParticleCountAllInternal() const
void CElementGen::EndLifetime() void CElementGen::EndLifetime()
{ {
x214_PSLT = 0; x268_PSLT = 0;
for (std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->EndLifetime(); ch->EndLifetime();
for (std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
ch->EndLifetime(); ch->EndLifetime();
@ -1152,7 +1166,7 @@ void CElementGen::BuildParticleSystemBounds()
zeus::CAABox aabb; zeus::CAABox aabb;
bool accumulated = false; bool accumulated = false;
for (std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
{ {
auto chBounds = ch->GetBounds(); auto chBounds = ch->GetBounds();
if (chBounds) if (chBounds)
@ -1212,7 +1226,7 @@ void CElementGen::BuildParticleSystemBounds()
u32 CElementGen::GetSystemCount() u32 CElementGen::GetSystemCount()
{ {
u32 ret = 0; u32 ret = 0;
for (const std::unique_ptr<CElementGen>& child : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& child : x290_activePartChildren)
ret += child->GetSystemCount(); ret += child->GetSystemCount();
for (const std::unique_ptr<CElementGen>& child : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& child : x248_finishPartChildren)
@ -1231,10 +1245,10 @@ void CElementGen::Render()
x22c_backupLightActive = CGraphics::g_LightActive; x22c_backupLightActive = CGraphics::g_LightActive;
CGraphics::DisableAllLights(); CGraphics::DisableAllLights();
for (std::unique_ptr<CElementGen>& child : x234_activePartChildren) for (std::unique_ptr<CElementGen>& child : x290_activePartChildren)
child->Render(); child->Render();
if (x214_PSLT <= x50_curFrame) if (x268_PSLT <= x50_curFrame)
for (std::unique_ptr<CElementGen>& child : x248_finishPartChildren) for (std::unique_ptr<CElementGen>& child : x248_finishPartChildren)
child->Render(); child->Render();
@ -1244,13 +1258,13 @@ void CElementGen::Render()
for (std::unique_ptr<CParticleElectric>& child : x280_elscChildren) for (std::unique_ptr<CParticleElectric>& child : x280_elscChildren)
child->Render(); child->Render();
if (x2c_particleLists.size()) if (x30_particleLists.size())
{ {
SParticleModel& pmdl = desc->x5c_x48_PMDL; SParticleModel& pmdl = desc->x5c_x48_PMDL;
if (pmdl.m_found || desc->x45_24_x31_26_PMUS) if (pmdl.m_found || desc->x45_24_x31_26_PMUS)
RenderModels(); RenderModels();
if (x225_26_LINE) if (x26c_31_LINE)
RenderLines(); RenderLines();
else else
RenderParticles(); RenderParticles();
@ -1265,7 +1279,7 @@ void CElementGen::RenderModels()
if (x225_29_modelsUseLights) if (x225_29_modelsUseLights)
CGraphics::SetLightState(x22c_backupLightActive); CGraphics::SetLightState(x22c_backupLightActive);
CGlobalRandom gr(x230_randState); CGlobalRandom gr(x27c_randState);
SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f};
CUVElement* texr = desc->x54_x40_TEXR.get(); CUVElement* texr = desc->x54_x40_TEXR.get();
@ -1296,7 +1310,7 @@ void CElementGen::RenderModels()
if (texr) if (texr)
{ {
CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; CParticle& target = g_StaticParticleList[x30_particleLists[0].x0_partIdx];
int partFrame = x50_curFrame - target.x28_startFrame; int partFrame = x50_curFrame - target.x28_startFrame;
cachedTex = texr->GetValueTexture(partFrame).GetObj(); cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::One); cachedTex->Load(0, CTexture::EClampMode::One);
@ -1338,8 +1352,8 @@ void CElementGen::RenderModels()
zeus::CColor col = {1.f, 1.f, 1.f, 1.f}; zeus::CColor col = {1.f, 1.f, 1.f, 1.f};
zeus::CVector3f pmopVec; zeus::CVector3f pmopVec;
auto matrixIt = x3c_parentMatrices.begin(); auto matrixIt = x60_parentMatrices.begin();
for (CParticleListItem& item : x2c_particleLists) for (CParticleListItem& item : x30_particleLists)
{ {
CParticle& particle = g_StaticParticleList[item.x0_partIdx]; CParticle& particle = g_StaticParticleList[item.x0_partIdx];
g_currentParticle = &particle; g_currentParticle = &particle;
@ -1454,7 +1468,7 @@ void CElementGen::RenderModels()
void CElementGen::RenderLines() void CElementGen::RenderLines()
{ {
CGenDescription* desc = x1c_genDesc.GetObj(); CGenDescription* desc = x1c_genDesc.GetObj();
CGlobalRandom gr(x230_randState); CGlobalRandom gr(x27c_randState);
zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix);
systemViewPointMatrix.origin.zeroOut(); systemViewPointMatrix.origin.zeroOut();
@ -1488,7 +1502,7 @@ void CElementGen::RenderLines()
zeus::CColor moduColor = zeus::CColor::skWhite; zeus::CColor moduColor = zeus::CColor::skWhite;
if (texr) if (texr)
{ {
CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; CParticle& target = g_StaticParticleList[x30_particleLists[0].x0_partIdx];
int partFrame = x50_curFrame - target.x28_startFrame; int partFrame = x50_curFrame - target.x28_startFrame;
cachedTex = texr->GetValueTexture(partFrame).GetObj(); cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::One); cachedTex->Load(0, CTexture::EClampMode::One);
@ -1515,7 +1529,7 @@ void CElementGen::RenderLines()
m_lineRenderer->Reset(); m_lineRenderer->Reset();
for (CParticleListItem& item : x2c_particleLists) for (CParticleListItem& item : x30_particleLists)
{ {
CParticle& particle = g_StaticParticleList[item.x0_partIdx]; CParticle& particle = g_StaticParticleList[item.x0_partIdx];
g_currentParticle = &particle; g_currentParticle = &particle;
@ -1536,7 +1550,7 @@ void CElementGen::RenderLines()
texr->GetValueUV(partFrame, uvs); texr->GetValueUV(partFrame, uvs);
zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos; zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos;
if (x225_27_FXLL) if (x26d_24_FXLL)
if (dVec.magSquared() >= 0.f) if (dVec.magSquared() >= 0.f)
dVec.normalize(); dVec.normalize();
@ -1564,7 +1578,7 @@ void CElementGen::RenderLines()
void CElementGen::RenderParticles() void CElementGen::RenderParticles()
{ {
CGenDescription* desc = x1c_genDesc.GetObj(); CGenDescription* desc = x1c_genDesc.GetObj();
CGlobalRandom gr(x230_randState); CGlobalRandom gr(x27c_randState);
CUVElement* texr = desc->x54_x40_TEXR.get(); CUVElement* texr = desc->x54_x40_TEXR.get();
CUVElement* tind = desc->x58_x44_TIND.get(); CUVElement* tind = desc->x58_x44_TIND.get();
@ -1608,7 +1622,7 @@ void CElementGen::RenderParticles()
if (texr) if (texr)
{ {
CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; CParticle& target = g_StaticParticleList[x30_particleLists[0].x0_partIdx];
int partFrame = x50_curFrame - target.x28_startFrame; int partFrame = x50_curFrame - target.x28_startFrame;
cachedTex = texr->GetValueTexture(partFrame).GetObj(); cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::One); cachedTex->Load(0, CTexture::EClampMode::One);
@ -1628,13 +1642,13 @@ void CElementGen::RenderParticles()
if (desc->x44_28_x30_28_SORT) if (desc->x44_28_x30_28_SORT)
{ {
for (CParticleListItem& item : x2c_particleLists) for (CParticleListItem& item : x30_particleLists)
{ {
CParticle& particle = g_StaticParticleList[item.x0_partIdx]; CParticle& particle = g_StaticParticleList[item.x0_partIdx];
item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos); item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
} }
std::sort(x2c_particleLists.begin(), x2c_particleLists.end(), std::sort(x30_particleLists.begin(), x30_particleLists.end(),
[](const CParticleListItem& a, const CParticleListItem& b) -> bool [](const CParticleListItem& a, const CParticleListItem& b) -> bool
{return a.x4_viewPoint[1] >= b.x4_viewPoint[1];}); {return a.x4_viewPoint[1] >= b.x4_viewPoint[1];});
} }
@ -1657,17 +1671,17 @@ void CElementGen::RenderParticles()
{ {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
g_instTexData.clear(); g_instTexData.clear();
g_instTexData.reserve(x2c_particleLists.size()); g_instTexData.reserve(x30_particleLists.size());
break; break;
case CElementGenShaders::EShaderClass::NoTex: case CElementGenShaders::EShaderClass::NoTex:
g_instNoTexData.clear(); g_instNoTexData.clear();
g_instNoTexData.reserve(x2c_particleLists.size()); g_instNoTexData.reserve(x30_particleLists.size());
break; break;
default: default:
Log.report(logvisor::Fatal, "unexpected particle shader class"); Log.report(logvisor::Fatal, "unexpected particle shader class");
break; break;
} }
for (CParticleListItem& item : x2c_particleLists) for (CParticleListItem& item : x30_particleLists)
{ {
CParticle& particle = g_StaticParticleList[item.x0_partIdx]; CParticle& particle = g_StaticParticleList[item.x0_partIdx];
g_currentParticle = &particle; g_currentParticle = &particle;
@ -1788,18 +1802,18 @@ void CElementGen::RenderParticles()
{ {
case CElementGenShaders::EShaderClass::Tex: case CElementGenShaders::EShaderClass::Tex:
g_instTexData.clear(); g_instTexData.clear();
g_instTexData.reserve(x2c_particleLists.size() * mbspVal); g_instTexData.reserve(x30_particleLists.size() * mbspVal);
break; break;
case CElementGenShaders::EShaderClass::NoTex: case CElementGenShaders::EShaderClass::NoTex:
g_instNoTexData.clear(); g_instNoTexData.clear();
g_instNoTexData.reserve(x2c_particleLists.size() * mbspVal); g_instNoTexData.reserve(x30_particleLists.size() * mbspVal);
break; break;
default: default:
Log.report(logvisor::Fatal, "unexpected particle shader class"); Log.report(logvisor::Fatal, "unexpected particle shader class");
break; break;
} }
float mbspFac = 1.f / float(mbspVal); float mbspFac = 1.f / float(mbspVal);
for (CParticleListItem& item : x2c_particleLists) for (CParticleListItem& item : x30_particleLists)
{ {
CParticle& particle = g_StaticParticleList[item.x0_partIdx]; CParticle& particle = g_StaticParticleList[item.x0_partIdx];
g_currentParticle = &particle; g_currentParticle = &particle;
@ -1956,7 +1970,7 @@ void CElementGen::RenderParticlesIndirectTexture()
} }
CUVElement* texr = desc->x54_x40_TEXR.get(); CUVElement* texr = desc->x54_x40_TEXR.get();
CParticle& firstParticle = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; CParticle& firstParticle = g_StaticParticleList[x30_particleLists[0].x0_partIdx];
int partFrame = x50_curFrame - firstParticle.x28_startFrame; int partFrame = x50_curFrame - firstParticle.x28_startFrame;
CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj(); CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj();
cachedTex->Load(0, CTexture::EClampMode::One); cachedTex->Load(0, CTexture::EClampMode::One);
@ -1977,21 +1991,21 @@ void CElementGen::RenderParticlesIndirectTexture()
if (desc->x44_28_x30_28_SORT) if (desc->x44_28_x30_28_SORT)
{ {
for (CParticleListItem& item : x2c_particleLists) for (CParticleListItem& item : x30_particleLists)
{ {
CParticle& particle = g_StaticParticleList[item.x0_partIdx]; CParticle& particle = g_StaticParticleList[item.x0_partIdx];
item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos); item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos);
} }
std::sort(x2c_particleLists.begin(), x2c_particleLists.end(), std::sort(x30_particleLists.begin(), x30_particleLists.end(),
[](const CParticleListItem& a, const CParticleListItem& b) -> bool [](const CParticleListItem& a, const CParticleListItem& b) -> bool
{return a.x4_viewPoint[1] >= b.x4_viewPoint[1];}); {return a.x4_viewPoint[1] >= b.x4_viewPoint[1];});
} }
g_instIndTexData.clear(); g_instIndTexData.clear();
g_instIndTexData.reserve(x2c_particleLists.size()); g_instIndTexData.reserve(x30_particleLists.size());
for (CParticleListItem& item : x2c_particleLists) for (CParticleListItem& item : x30_particleLists)
{ {
CParticle& particle = g_StaticParticleList[item.x0_partIdx]; CParticle& particle = g_StaticParticleList[item.x0_partIdx];
g_currentParticle = &particle; g_currentParticle = &particle;
@ -2066,7 +2080,7 @@ void CElementGen::SetOrientation(const zeus::CTransform& orientation)
x178_orientation = orientation; x178_orientation = orientation;
x1a8_orientationInverse = x178_orientation.inverse(); x1a8_orientationInverse = x178_orientation.inverse();
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetOrientation(orientation); ch->SetOrientation(orientation);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2083,24 +2097,24 @@ void CElementGen::SetTranslation(const zeus::CVector3f& translation)
{ {
x7c_translation = translation; x7c_translation = translation;
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetTranslation(translation); ch->SetTranslation(translation);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
ch->SetTranslation(translation); ch->SetTranslation(translation);
for (const std::unique_ptr<CParticleSwoosh>& ch : x260_swhcChildren) for (const std::unique_ptr<CParticleSwoosh>& ch : x260_swhcChildren)
ch->SetTranslation(translation + x274_SSPO); ch->SetTranslation(translation + x2b0_SSPO);
for (const std::unique_ptr<CParticleElectric>& ch : x280_elscChildren) for (const std::unique_ptr<CParticleElectric>& ch : x280_elscChildren)
ch->SetTranslation(translation + x294_SEPO); ch->SetTranslation(translation + x2c0_SEPO);
} }
void CElementGen::SetGlobalOrientation(const zeus::CTransform& rotation) void CElementGen::SetGlobalOrientation(const zeus::CTransform& rotation)
{ {
x1d8_globalOrientation.setRotation(rotation); x1d8_globalOrientation.setRotation(rotation);
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetGlobalOrientation(x1d8_globalOrientation); ch->SetGlobalOrientation(x1d8_globalOrientation);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2114,7 +2128,7 @@ void CElementGen::SetGlobalTranslation(const zeus::CVector3f& translation)
{ {
x88_globalTranslation = translation; x88_globalTranslation = translation;
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetGlobalTranslation(translation); ch->SetGlobalTranslation(translation);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2133,7 +2147,7 @@ void CElementGen::SetGlobalScale(const zeus::CVector3f& scale)
xac_globalScaleTransform = zeus::CTransform::Scale(scale); xac_globalScaleTransform = zeus::CTransform::Scale(scale);
xdc_globalScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); xdc_globalScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale);
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetGlobalScale(scale); ch->SetGlobalScale(scale);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2152,7 +2166,7 @@ void CElementGen::SetLocalScale(const zeus::CVector3f& scale)
x118_localScaleTransform = zeus::CTransform::Scale(scale); x118_localScaleTransform = zeus::CTransform::Scale(scale);
x148_localScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); x148_localScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale);
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetLocalScale(scale); ch->SetLocalScale(scale);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2163,7 +2177,7 @@ void CElementGen::SetParticleEmission(bool enabled)
{ {
x68_particleEmission = enabled; x68_particleEmission = enabled;
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetParticleEmission(enabled); ch->SetParticleEmission(enabled);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2180,7 +2194,7 @@ void CElementGen::SetModulationColor(const zeus::CColor& color)
{ {
x30c_moduColor = color; x30c_moduColor = color;
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->SetModulationColor(color); ch->SetModulationColor(color);
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2225,7 +2239,7 @@ const zeus::CColor& CElementGen::GetModulationColor() const
bool CElementGen::IsSystemDeletable() const bool CElementGen::IsSystemDeletable() const
{ {
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
if (!ch->IsSystemDeletable()) if (!ch->IsSystemDeletable())
return false; return false;
@ -2241,7 +2255,7 @@ bool CElementGen::IsSystemDeletable() const
if (!ch->IsSystemDeletable()) if (!ch->IsSystemDeletable())
return false; return false;
if (x214_PSLT < x50_curFrame && x208_activeParticleCount == 0) if (x268_PSLT < x50_curFrame && x208_activeParticleCount == 0)
return true; return true;
return false; return false;
@ -2262,12 +2276,12 @@ u32 CElementGen::GetParticleCount() const
bool CElementGen::SystemHasLight() const bool CElementGen::SystemHasLight() const
{ {
return x2dc_lightType != LightType::None; return x308_lightType != LightType::None;
} }
CLight CElementGen::GetLight() const CLight CElementGen::GetLight() const
{ {
switch (x2dc_lightType) switch (x308_lightType)
{ {
case LightType::Directional: case LightType::Directional:
return CLight::BuildDirectional(x2f4_LDIR.normalized(), x2e0_LCLR * x2e4_LINT); return CLight::BuildDirectional(x2f4_LDIR.normalized(), x2e0_LCLR * x2e4_LINT);
@ -2275,9 +2289,9 @@ CLight CElementGen::GetLight() const
return CLight::BuildSpot(x2e8_LOFF, x2f4_LDIR.normalized(), x2e0_LCLR * x2e4_LINT, x308_LSLA); return CLight::BuildSpot(x2e8_LOFF, x2f4_LDIR.normalized(), x2e0_LCLR * x2e4_LINT, x308_LSLA);
default: default:
{ {
float quad = x300_falloffType == EFalloffType::Quadratic ? x304_LFOR : 0.f; float quad = x32c_falloffType == EFalloffType::Quadratic ? x304_LFOR : 0.f;
float linear = x300_falloffType == EFalloffType::Linear ? x304_LFOR : 0.f; float linear = x32c_falloffType == EFalloffType::Linear ? x304_LFOR : 0.f;
float constant = x300_falloffType == EFalloffType::Constant ? 1.f : 0.f; float constant = x32c_falloffType == EFalloffType::Constant ? 1.f : 0.f;
return CLight::BuildCustom(x2e8_LOFF, {1.f, 0.f, 0.f}, x2e0_LCLR, return CLight::BuildCustom(x2e8_LOFF, {1.f, 0.f, 0.f}, x2e0_LCLR,
constant, linear, quad, x2e4_LINT, 0.f, 0.f); constant, linear, quad, x2e4_LINT, 0.f, 0.f);
} }
@ -2291,16 +2305,16 @@ bool CElementGen::GetParticleEmission() const
void CElementGen::DestroyParticles() void CElementGen::DestroyParticles()
{ {
for (CParticleListItem& p : x2c_particleLists) for (CParticleListItem& p : x30_particleLists)
{ {
g_StaticFreeList[++g_FreeIndex] = p.x0_partIdx; g_StaticFreeList[++g_FreeIndex] = p.x0_partIdx;
g_StaticParticleList[p.x0_partIdx].x0_endFrame = -1; g_StaticParticleList[p.x0_partIdx].x0_endFrame = -1;
} }
x2c_particleLists.clear(); x30_particleLists.clear();
x3c_parentMatrices.clear(); x60_parentMatrices.clear();
for (const std::unique_ptr<CElementGen>& ch : x234_activePartChildren) for (const std::unique_ptr<CElementGen>& ch : x290_activePartChildren)
ch->DestroyParticles(); ch->DestroyParticles();
for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren) for (const std::unique_ptr<CElementGen>& ch : x248_finishPartChildren)
@ -2309,9 +2323,9 @@ void CElementGen::DestroyParticles()
void CElementGen::Reset() void CElementGen::Reset()
{ {
x2c_particleLists.clear(); x30_particleLists.clear();
x3c_parentMatrices.clear(); x60_parentMatrices.clear();
x234_activePartChildren.clear();; x290_activePartChildren.clear();
x248_finishPartChildren.clear(); x248_finishPartChildren.clear();
x280_elscChildren.clear(); x280_elscChildren.clear();
x260_swhcChildren.clear(); x260_swhcChildren.clear();

View File

@ -78,8 +78,8 @@ private:
friend class CElementGenShaders; friend class CElementGenShaders;
TLockedToken<CGenDescription> x1c_genDesc; TLockedToken<CGenDescription> x1c_genDesc;
EModelOrientationType x28_orientType; EModelOrientationType x28_orientType;
std::vector<CParticleListItem> x2c_particleLists; std::vector<CParticleListItem> x30_particleLists;
std::vector<zeus::CMatrix3f> x3c_parentMatrices; std::vector<zeus::CMatrix3f> x60_parentMatrices;
u32 x4c_internalStartFrame = 0; u32 x4c_internalStartFrame = 0;
u32 x50_curFrame = 0; u32 x50_curFrame = 0;
double x58_curSeconds = 0.f; double x58_curSeconds = 0.f;
@ -87,12 +87,12 @@ private:
u32 x64_prevFrame = -1; u32 x64_prevFrame = -1;
bool x68_particleEmission = true; bool x68_particleEmission = true;
float x6c_generatorRemainder = 0.f; float x6c_generatorRemainder = 0.f;
int x70_MAXP = 0; int x90_MAXP = 0;
u16 x74_randomSeed = 99; u16 x94_randomSeed = 99;
float x78_generatorRate = 1.f; float x78_generatorRate = 1.f;
zeus::CVector3f x7c_translation; zeus::CVector3f x7c_translation;
zeus::CVector3f x88_globalTranslation; zeus::CVector3f x88_globalTranslation;
zeus::CVector3f x94_POFS; zeus::CVector3f xf4_POFS;
zeus::CVector3f xa0_globalScale = {1.f, 1.f, 1.f}; zeus::CVector3f xa0_globalScale = {1.f, 1.f, 1.f};
zeus::CTransform xac_globalScaleTransform = zeus::CTransform::Identity(); zeus::CTransform xac_globalScaleTransform = zeus::CTransform::Identity();
zeus::CTransform xdc_globalScaleTransformInverse = zeus::CTransform::Identity(); zeus::CTransform xdc_globalScaleTransformInverse = zeus::CTransform::Identity();
@ -105,7 +105,7 @@ private:
u32 x208_activeParticleCount = 0; u32 x208_activeParticleCount = 0;
u32 x20c_recursiveParticleCount = 0; u32 x20c_recursiveParticleCount = 0;
u32 x210_curEmitterFrame = 0; u32 x210_curEmitterFrame = 0;
int x214_PSLT = 90;//0x7fffff; int x268_PSLT = 90;//0x7fffff;
zeus::CVector3f x218_PSIV; zeus::CVector3f x218_PSIV;
bool x224_24_translationDirty = false; bool x224_24_translationDirty = false;
bool x224_25_LIT_; bool x224_25_LIT_;
@ -117,38 +117,48 @@ private:
bool x224_31_VMD2; bool x224_31_VMD2;
bool x225_24_VMD3; bool x225_24_VMD3;
bool x225_25_VMD4; bool x225_25_VMD4;
bool x225_26_LINE;
bool x225_27_FXLL;
bool x225_28_warmedUp = false; bool x225_28_warmedUp = false;
bool x225_29_modelsUseLights = false; bool x225_29_modelsUseLights = false;
bool x226_enableOPTS; bool x226_enableOPTS;
int x228_MBSP = 0; int m_maxMBSP = 0; int x228_MBSP = 0; int m_maxMBSP = 0;
union
{
struct
{
bool x26c_24_ : 1;
bool x26c_31_LINE : 1;
bool x26d_24_FXLL : 1;
};
u32 _dummy = 0;
};
ERglLightBits x22c_backupLightActive = ERglLightBits::None; ERglLightBits x22c_backupLightActive = ERglLightBits::None;
CRandom16 x230_randState; CRandom16 x27c_randState;
std::vector<std::unique_ptr<CElementGen>> x234_activePartChildren; std::vector<std::unique_ptr<CElementGen>> x290_activePartChildren;
int x244_CSSD = 0; int x2a0_CSSD = 0;
std::vector<std::unique_ptr<CElementGen>> x248_finishPartChildren; std::vector<std::unique_ptr<CElementGen>> x248_finishPartChildren;
int x258_SISY = 16; int x2a4_SISY = 16;
int x25c_PISY = 16; int x2a8_PISY = 16;
u32 x260_cumulativeParticles = 0; /* Retail */ u32 x260_cumulativeParticles = 0; /* Retail */
std::vector<std::unique_ptr<CParticleSwoosh>> x260_swhcChildren; std::vector<std::unique_ptr<CParticleSwoosh>> x260_swhcChildren;
int x270_SSSD = 0; int x2ac_SSSD = 0;
zeus::CVector3f x274_SSPO; zeus::CVector3f x2b0_SSPO;
std::vector<std::unique_ptr<CParticleElectric>> x280_elscChildren; std::vector<std::unique_ptr<CParticleElectric>> x280_elscChildren;
int x290_SESD = 0; int x2bc_SESD = 0;
zeus::CVector3f x294_SEPO; zeus::CVector3f x2c0_SEPO;
float x2a0 = 0.f; float x2a0 = 0.f;
float x2a4 = 0.f; float x2a4 = 0.f;
zeus::CVector3f x2a8_aabbMin; zeus::CVector3f x2a8_aabbMin;
zeus::CVector3f x2b4_aabbMax; zeus::CVector3f x2b4_aabbMax;
float x2c0_maxSize = 0.f; float x2c0_maxSize = 0.f;
zeus::CAABox x2c4_systemBounds = zeus::CAABox::skInvertedBox; zeus::CAABox x2c4_systemBounds = zeus::CAABox::skInvertedBox;
LightType x2dc_lightType; LightType x308_lightType;
zeus::CColor x2e0_LCLR = zeus::CColor::skWhite; zeus::CColor x2e0_LCLR = zeus::CColor::skWhite;
float x2e4_LINT = 1.f; float x2e4_LINT = 1.f;
zeus::CVector3f x2e8_LOFF; zeus::CVector3f x2e8_LOFF;
zeus::CVector3f x2f4_LDIR = {1.f, 0.f, 0.f}; zeus::CVector3f x2f4_LDIR = {1.f, 0.f, 0.f};
EFalloffType x300_falloffType = EFalloffType::Linear; EFalloffType x32c_falloffType = EFalloffType::Linear;
float x304_LFOR = 1.f; float x304_LFOR = 1.f;
float x308_LSLA = 45.f; float x308_LSLA = 45.f;
zeus::CColor x30c_moduColor = {1.f, 1.f, 1.f, 1.f}; zeus::CColor x30c_moduColor = {1.f, 1.f, 1.f, 1.f};
@ -185,7 +195,7 @@ public:
else else
x78_generatorRate = 0.0f; x78_generatorRate = 0.0f;
for (std::unique_ptr<CElementGen>& child : x234_activePartChildren) for (std::unique_ptr<CElementGen>& child : x290_activePartChildren)
child->SetGeneratorRateScalar(x78_generatorRate); child->SetGeneratorRateScalar(x78_generatorRate);
for (std::unique_ptr<CElementGen>& child : x248_finishPartChildren) for (std::unique_ptr<CElementGen>& child : x248_finishPartChildren)
@ -241,6 +251,8 @@ public:
bool GetParticleEmission() const; bool GetParticleEmission() const;
void DestroyParticles(); void DestroyParticles();
void Reset(); void Reset();
size_t GetNumActiveChildParticles() const { return x290_activePartChildren.size(); }
CElementGen& GetActiveChildParticle(size_t idx) const { return *x290_activePartChildren[idx]; }
static void SetMoveRedToAlphaBuffer(bool); static void SetMoveRedToAlphaBuffer(bool);
}; };

@ -1 +1 @@
Subproject commit f5f78fdeefd8a0d1a708ca31df8dc2cb2adc8482 Subproject commit 2faf7c87ed0548cd9152de4d1acd0791ba118308