mirror of https://github.com/AxioDL/metaforce.git
CVisorFlare implementation
This commit is contained in:
parent
f80813b9cc
commit
05ad95bdd0
|
@ -42,8 +42,7 @@ void CSimpleShadow::Render(TLockedToken<CTexture>& tex) {
|
||||||
ERglLogicOp::Clear);
|
ERglLogicOp::Clear);
|
||||||
CGraphics::StreamBegin(GX::QUADS);
|
CGraphics::StreamBegin(GX::QUADS);
|
||||||
float radius = x34_radius * x30_scale;
|
float radius = x34_radius * x30_scale;
|
||||||
float t = x3c_heightAlpha * x38_userAlpha;
|
CGraphics::StreamColor(zeus::CColor{1.f, x3c_heightAlpha * x38_userAlpha});
|
||||||
CGraphics::StreamColor(zeus::CColor{t, t} /* TODO double check */);
|
|
||||||
CGraphics::StreamTexcoord(0.f, 0.f);
|
CGraphics::StreamTexcoord(0.f, 0.f);
|
||||||
CGraphics::StreamVertex(-radius, 0.f, -radius);
|
CGraphics::StreamVertex(-radius, 0.f, -radius);
|
||||||
CGraphics::StreamTexcoord(0.f, 1.f);
|
CGraphics::StreamTexcoord(0.f, 1.f);
|
||||||
|
|
|
@ -934,8 +934,8 @@ void CDrone::SetVisorFlareEnabled(CStateManager& mgr, bool activate) {
|
||||||
x57a_visorFlareId = mgr.AllocateUniqueId();
|
x57a_visorFlareId = mgr.AllocateUniqueId();
|
||||||
flare = new CScriptVisorFlare(x57a_visorFlareId, "DroneVisorFlare"sv,
|
flare = new CScriptVisorFlare(x57a_visorFlareId, "DroneVisorFlare"sv,
|
||||||
CEntityInfo{GetAreaIdAlways(), CEntity::NullConnectionList}, activate,
|
CEntityInfo{GetAreaIdAlways(), CEntity::NullConnectionList}, activate,
|
||||||
GetLctrTransform("Beacon_LCTR"sv).origin, CVisorFlare::EBlendMode::Zero, true, 0.1f,
|
GetLctrTransform("Beacon_LCTR"sv).origin, CVisorFlare::EBlendMode::Additive, true,
|
||||||
1.f, 2.f, 0, 0, x57c_flares);
|
0.1f, 1.f, 2.f, 0, 0, x57c_flares);
|
||||||
mgr.AddObject(flare);
|
mgr.AddObject(flare);
|
||||||
}
|
}
|
||||||
mgr.SendScriptMsg(flare, GetUniqueId(), activate ? EScriptObjectMessage::Activate : EScriptObjectMessage::Deactivate);
|
mgr.SendScriptMsg(flare, GetUniqueId(), activate ? EScriptObjectMessage::Activate : EScriptObjectMessage::Deactivate);
|
||||||
|
|
|
@ -14,7 +14,8 @@ CScriptVisorFlare::CScriptVisorFlare(TUniqueId uid, std::string_view name, const
|
||||||
float f2, float f3, u32 w1, u32 w2, std::vector<CVisorFlare::CFlareDef> flares)
|
float f2, float f3, u32 w1, u32 w2, std::vector<CVisorFlare::CFlareDef> flares)
|
||||||
: CActor(uid, active, name, info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(),
|
: CActor(uid, active, name, info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(),
|
||||||
CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId)
|
CMaterialList(EMaterialTypes::NoStepLogic), CActorParameters::None(), kInvalidUniqueId)
|
||||||
, xe8_flare(blendMode, b1, f1, f2, f3, w1, w2, std::move(flares)) {
|
, xe8_flare(blendMode, b1, f1, f2, f3, w1, w2, std::move(flares))
|
||||||
|
, x11c_notInRenderLast(true) {
|
||||||
xe6_27_thermalVisorFlags = 2;
|
xe6_27_thermalVisorFlags = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "Runtime/GameGlobalObjects.hpp"
|
#include "Runtime/GameGlobalObjects.hpp"
|
||||||
#include "Runtime/CStateManager.hpp"
|
#include "Runtime/CStateManager.hpp"
|
||||||
#include "Runtime/CSimplePool.hpp"
|
#include "Runtime/CSimplePool.hpp"
|
||||||
|
#include "Runtime/Graphics/CCubeRenderer.hpp"
|
||||||
|
#include "Runtime/Graphics/CGX.hpp"
|
||||||
|
|
||||||
namespace metaforce {
|
namespace metaforce {
|
||||||
|
|
||||||
|
@ -31,7 +33,7 @@ CVisorFlare::CVisorFlare(EBlendMode blendMode, bool b1, float f1, float f2, floa
|
||||||
: x0_blendMode(blendMode)
|
: x0_blendMode(blendMode)
|
||||||
, x4_flareDefs(std::move(flares))
|
, x4_flareDefs(std::move(flares))
|
||||||
, x14_b1(b1)
|
, x14_b1(b1)
|
||||||
, x18_f1(std::max(f1, FLT_EPSILON))
|
, x18_f1(std::max(f1, 1.0E-4f))
|
||||||
, x1c_f2(f2)
|
, x1c_f2(f2)
|
||||||
, x20_f3(f3)
|
, x20_f3(f3)
|
||||||
, x2c_w1(w1)
|
, x2c_w1(w1)
|
||||||
|
@ -45,56 +47,182 @@ void CVisorFlare::Update(float dt, const zeus::CVector3f& pos, const CActor* act
|
||||||
|
|
||||||
zeus::CVector3f camPos = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation();
|
zeus::CVector3f camPos = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation();
|
||||||
zeus::CVector3f camDiff = pos - camPos;
|
zeus::CVector3f camDiff = pos - camPos;
|
||||||
const float mag = (camDiff.magnitude());
|
const float mag = camDiff.magnitude();
|
||||||
|
camDiff = camDiff * (1.f / mag);
|
||||||
EntityList nearVec;
|
EntityList nearVec;
|
||||||
mgr.BuildNearList(nearVec, camPos, camDiff * (1.f / mag), mag,
|
mgr.BuildNearList(nearVec, camPos, camDiff, mag,
|
||||||
CMaterialFilter::MakeInclude({EMaterialTypes::Occluder}), act);
|
CMaterialFilter::MakeInclude({EMaterialTypes::Occluder}), act);
|
||||||
TUniqueId id;
|
TUniqueId id;
|
||||||
CRayCastResult result = mgr.RayWorldIntersection(
|
CRayCastResult result = mgr.RayWorldIntersection(
|
||||||
id, camPos, camDiff, mag,
|
id, camPos, camDiff, mag,
|
||||||
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::SeeThrough}), nearVec);
|
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::SeeThrough}), nearVec);
|
||||||
|
|
||||||
if (result.IsValid()) {
|
if (result.IsInvalid()) {
|
||||||
x28_ -= mag;
|
x28_ -= dt;
|
||||||
} else {
|
} else {
|
||||||
x28_ += mag;
|
x28_ += dt;
|
||||||
}
|
}
|
||||||
x28_ = zeus::clamp(0.f, x28_, x18_f1);
|
x28_ = zeus::clamp(0.f, x28_, x18_f1);
|
||||||
x24_ = 1.f - (x28_ / x18_f1);
|
x24_ = 1.f - (x28_ / x18_f1);
|
||||||
|
|
||||||
const CGameCamera* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
|
const auto* curCam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
|
||||||
x24_ *= std::max(
|
const auto dir = (pos - curCam->GetTranslation()).normalized();
|
||||||
0.f, 1.f - (4.f * x1c_f2 * (1.f - (pos - curCam->GetTranslation()).dot(curCam->GetTransform().basis[1]))));
|
float dot = dir.dot(curCam->GetTransform().frontVector());
|
||||||
|
x24_ *= std::max(0.f, 1.f - (x1c_f2 * 4.f * (1.f - dot)));
|
||||||
|
|
||||||
if (x2c_w1 == 2) {
|
if (x2c_w1 == 2) {
|
||||||
mgr.SetThermalColdScale2(mgr.GetThermalColdScale2() + x24_);
|
mgr.SetThermalColdScale2(mgr.GetThermalColdScale2() + x24_);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#ifndef NDEBUG
|
|
||||||
// printf("%08X %f %f\n", act->GetEditorId().id, x24_, x28_);
|
|
||||||
//#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVisorFlare::Render(const zeus::CVector3f& pos, const CStateManager& mgr) const {
|
void CVisorFlare::Render(const zeus::CVector3f& pos, const CStateManager& mgr) const {
|
||||||
if (zeus::close_enough(x28_, x18_f1) &&
|
if (zeus::close_enough(x28_, x18_f1, 1.0E-5f) ||
|
||||||
mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) {
|
mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed) {
|
||||||
int iVar;
|
return;
|
||||||
|
}
|
||||||
|
SCOPED_GRAPHICS_DEBUG_GROUP("CVisorFlare::Render", zeus::skGrey);
|
||||||
|
|
||||||
|
u32 type;
|
||||||
const auto visor = mgr.GetPlayerState()->GetActiveVisor(mgr);
|
const auto visor = mgr.GetPlayerState()->GetActiveVisor(mgr);
|
||||||
if (visor == CPlayerState::EPlayerVisor::Thermal) {
|
if (visor == CPlayerState::EPlayerVisor::Thermal) {
|
||||||
iVar = x2c_w1;
|
type = x2c_w1;
|
||||||
} else if (visor == CPlayerState::EPlayerVisor::XRay) {
|
} else if (visor == CPlayerState::EPlayerVisor::XRay) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
iVar = x30_w2;
|
type = x30_w2;
|
||||||
}
|
}
|
||||||
if (iVar != 0)
|
if (type != 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CGraphics::DisableAllLights();
|
CGraphics::DisableAllLights();
|
||||||
// g_Renderer->SetDepthReadWrite(false, false);
|
g_Renderer->SetDepthReadWrite(false, false);
|
||||||
// const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
|
const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
|
||||||
// zeus::CVector3f camPos = cam->GetTranslation();
|
zeus::CVector3f camPos = cam->GetTranslation();
|
||||||
|
zeus::CVector3f camFront = cam->GetTransform().frontVector();
|
||||||
|
const auto invPos = CGraphics::g_ViewMatrix.inverse() * pos;
|
||||||
|
const auto invPos2 = CGraphics::g_ViewMatrix * zeus::CVector3f{-invPos.x(), invPos.y(), -invPos.z()};
|
||||||
|
if (!zeus::close_enough(x24_, 0.f, 1.0E-5f)) {
|
||||||
|
float acos = 0.f;
|
||||||
|
if (!zeus::close_enough(x20_f3, 0.f, 1.0E-5f)) {
|
||||||
|
zeus::CVector3f camDist{pos.x() - camPos.x(), pos.y() - camPos.y(), 0.f};
|
||||||
|
camDist.normalize();
|
||||||
|
zeus::CVector3f camDir{camFront.x(), camFront.y(), 0.f};
|
||||||
|
camDir.normalize();
|
||||||
|
acos = std::acos(camDist.dot(camDir));
|
||||||
|
if (camDist.x() * camDir.y() - camDir.x() * camDist.y() < 0.f) {
|
||||||
|
acos = -acos;
|
||||||
|
}
|
||||||
|
acos = x20_f3 * acos;
|
||||||
|
}
|
||||||
|
SetupRenderState(mgr);
|
||||||
|
for (const auto& item : x4_flareDefs) {
|
||||||
|
const auto origin = pos * (1.f - item.GetPosition()) + invPos2 * item.GetPosition();
|
||||||
|
g_Renderer->SetModelMatrix(zeus::lookAt(origin, camPos));
|
||||||
|
float scale = 0.5f * x24_ * item.GetScale();
|
||||||
|
if (x14_b1) {
|
||||||
|
auto dist = origin - camPos;
|
||||||
|
if (dist.canBeNormalized()) {
|
||||||
|
scale *= dist.magnitude();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.GetTexture()) {
|
||||||
|
item.GetTexture()->Load(GX::TEXMAP0, EClampMode::Repeat);
|
||||||
|
float f1;
|
||||||
|
if (zeus::close_enough(acos, 0.f)) {
|
||||||
|
f1 = 0.f;
|
||||||
|
} else {
|
||||||
|
f1 = scale * std::sin(acos);
|
||||||
|
scale *= std::cos(acos);
|
||||||
|
}
|
||||||
|
if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) {
|
||||||
|
DrawDirect(item.GetColor(), f1, scale);
|
||||||
|
} else {
|
||||||
|
DrawStreamed(item.GetColor(), f1, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResetTevSwapMode(mgr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CVisorFlare::SetupRenderState(const CStateManager& mgr) const {
|
||||||
|
if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) {
|
||||||
|
CGX::SetBlendMode(GX::BM_BLEND, GX::BL_ONE, GX::BL_ONE, GX::LO_CLEAR);
|
||||||
|
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE0);
|
||||||
|
CGX::SetTevOrder(GX::TEVSTAGE0, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
|
||||||
|
CGX::SetAlphaCompare(GX::ALWAYS, 0, GX::AOP_OR, GX::ALWAYS, 0);
|
||||||
|
GXSetTevSwapMode(GX::TEVSTAGE0, GX::TEV_SWAP0, GX::TEV_SWAP1);
|
||||||
|
CGX::SetTevKColorSel(GX::TEVSTAGE0, GX::TEV_KCSEL_K0_A);
|
||||||
|
CGX::SetTevKAlphaSel(GX::TEVSTAGE0, GX::TEV_KASEL_K0_A);
|
||||||
|
CGX::SetTevColorIn(GX::TEVSTAGE0, GX::CC_ZERO, GX::CC_TEXC, GX::CC_KONST, GX::CC_ZERO);
|
||||||
|
CGX::SetTevAlphaIn(GX::TEVSTAGE0, GX::CA_ZERO, GX::CA_TEXA, GX::CA_KONST, GX::CA_ZERO);
|
||||||
|
CGX::SetNumTexGens(1);
|
||||||
|
CGX::SetNumChans(0);
|
||||||
|
CGX::SetTexCoordGen(GX::TEXCOORD0, GX::TG_MTX2x4, GX::TG_TEX0, GX::IDENTITY, false, GX::PTIDENTITY);
|
||||||
|
if (x0_blendMode == EBlendMode::Blend) {
|
||||||
|
CGX::SetStandardTevColorAlphaOp(GX::TEVSTAGE1);
|
||||||
|
CGX::SetTevOrder(GX::TEVSTAGE1, GX::TEXCOORD0, GX::TEXMAP0, GX::COLOR_NULL);
|
||||||
|
CGX::SetTevColorIn(GX::TEVSTAGE1, GX::CC_ZERO, GX::CC_TEXA, GX::CC_CPREV, GX::CC_ZERO);
|
||||||
|
CGX::SetTevAlphaIn(GX::TEVSTAGE1, GX::CA_ZERO, GX::CA_TEXA, GX::CA_APREV, GX::CA_ZERO);
|
||||||
|
CGX::SetNumTevStages(2);
|
||||||
|
} else if (x0_blendMode == EBlendMode::Additive) {
|
||||||
|
CGX::SetNumTevStages(1);
|
||||||
|
}
|
||||||
|
constexpr std::array vtxDescList{
|
||||||
|
GX::VtxDescList{GX::VA_POS, GX::DIRECT},
|
||||||
|
GX::VtxDescList{GX::VA_TEX0, GX::DIRECT},
|
||||||
|
GX::VtxDescList{},
|
||||||
|
};
|
||||||
|
CGX::SetVtxDescv(vtxDescList.data());
|
||||||
|
} else {
|
||||||
|
if (x0_blendMode == EBlendMode::Blend) {
|
||||||
|
g_Renderer->SetBlendMode_AlphaBlended();
|
||||||
|
} else if (x0_blendMode == EBlendMode::Additive) {
|
||||||
|
g_Renderer->SetBlendMode_AdditiveAlpha();
|
||||||
|
}
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage0, CTevCombiners::sTevPass805a5ebc);
|
||||||
|
CGraphics::SetTevOp(ERglTevStage::Stage1, CTevCombiners::skPassThru);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVisorFlare::ResetTevSwapMode(const CStateManager& mgr) const {
|
||||||
|
if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) {
|
||||||
|
GXSetTevSwapMode(GX::TEVSTAGE0, GX::TEV_SWAP0, GX::TEV_SWAP0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVisorFlare::DrawDirect(const zeus::CColor& color, float f1, float f2) const {
|
||||||
|
zeus::CColor kcolor = color;
|
||||||
|
kcolor.a() *= x24_;
|
||||||
|
CGX::SetTevKColor(GX::KCOLOR0, kcolor);
|
||||||
|
CGX::Begin(GX::TRIANGLESTRIP, GX::VTXFMT0, 4);
|
||||||
|
GXPosition3f32(f1 - f2, 0.f, f2 + f1);
|
||||||
|
GXTexCoord2f32(0.f, 1.f);
|
||||||
|
GXPosition3f32(f2 + f1, 0.f, f2 - f1);
|
||||||
|
GXTexCoord2f32(1.f, 1.f);
|
||||||
|
GXPosition3f32(-(f2 - f1), 0.f, -(f2 - f1));
|
||||||
|
GXTexCoord2f32(0.f, 0.f);
|
||||||
|
GXPosition3f32(-f1 + f2, 0.f, -f2 - f1);
|
||||||
|
GXTexCoord2f32(1.f, 0.f);
|
||||||
|
CGX::End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CVisorFlare::DrawStreamed(const zeus::CColor& color, float f1, float f2) const {
|
||||||
|
CGraphics::StreamBegin(GX::TRIANGLESTRIP);
|
||||||
|
zeus::CColor kcolor = color;
|
||||||
|
kcolor.a() *= x24_;
|
||||||
|
CGraphics::StreamColor(kcolor);
|
||||||
|
CGraphics::StreamTexcoord(0.f, 1.f);
|
||||||
|
CGraphics::StreamVertex(f1 - f2, 0.f, f2 + f1);
|
||||||
|
CGraphics::StreamTexcoord(1.f, 1.f);
|
||||||
|
CGraphics::StreamVertex(f1 + f2, 0.f, f2 - f1);
|
||||||
|
CGraphics::StreamTexcoord(0.f, 0.f);
|
||||||
|
CGraphics::StreamVertex(-(f1 + f2), 0.f, -(f2 - f1));
|
||||||
|
CGraphics::StreamTexcoord(1.f, 0.f);
|
||||||
|
CGraphics::StreamVertex(-f1 + f2, 0.f, -f2 - f1);
|
||||||
|
CGraphics::StreamEnd();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace metaforce
|
} // namespace metaforce
|
||||||
|
|
|
@ -16,26 +16,27 @@ class CTexture;
|
||||||
class CVisorFlare {
|
class CVisorFlare {
|
||||||
public:
|
public:
|
||||||
enum class EBlendMode {
|
enum class EBlendMode {
|
||||||
Zero = 0,
|
Additive = 0,
|
||||||
|
Blend = 1,
|
||||||
};
|
};
|
||||||
class CFlareDef {
|
class CFlareDef {
|
||||||
TToken<CTexture> x0_tex;
|
mutable TToken<CTexture> x0_tex;
|
||||||
float x8_f1;
|
float x8_pos;
|
||||||
float xc_f2;
|
float xc_scale;
|
||||||
zeus::CColor x10_color;
|
zeus::CColor x10_color;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CFlareDef() = default;
|
CFlareDef() = default;
|
||||||
CFlareDef(const CFlareDef&) = default;
|
CFlareDef(const CFlareDef&) = default;
|
||||||
CFlareDef(const TToken<CTexture>& tex, float f1, float f2, const zeus::CColor& color)
|
CFlareDef(const TToken<CTexture>& tex, float pos, float scale, const zeus::CColor& color)
|
||||||
: x0_tex(tex), x8_f1(f1), xc_f2(f2), x10_color(color) {
|
: x0_tex(tex), x8_pos(pos), xc_scale(scale), x10_color(color) {
|
||||||
x0_tex.Lock();
|
x0_tex.Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
TToken<CTexture> GetTexture() const { return x0_tex; }
|
TToken<CTexture>& GetTexture() const { return x0_tex; }
|
||||||
zeus::CColor GetColor() const { return x10_color; }
|
zeus::CColor GetColor() const { return x10_color; }
|
||||||
float GetScale() const;
|
float GetPosition() const { return x8_pos; }
|
||||||
float GetPosition() const;
|
float GetScale() const { return xc_scale; }
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -50,6 +51,11 @@ private:
|
||||||
u32 x2c_w1;
|
u32 x2c_w1;
|
||||||
u32 x30_w2;
|
u32 x30_w2;
|
||||||
|
|
||||||
|
void SetupRenderState(const CStateManager& mgr) const;
|
||||||
|
void ResetTevSwapMode(const CStateManager& mgr) const;
|
||||||
|
void DrawDirect(const zeus::CColor& color, float f1, float f2) const;
|
||||||
|
void DrawStreamed(const zeus::CColor& color, float f1, float f2) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CVisorFlare(EBlendMode blendMode, bool, float, float, float, u32, u32, std::vector<CFlareDef> flares);
|
CVisorFlare(EBlendMode blendMode, bool, float, float, float, u32, u32, std::vector<CFlareDef> flares);
|
||||||
void Update(float dt, const zeus::CVector3f& pos, const CActor* act, CStateManager& mgr);
|
void Update(float dt, const zeus::CVector3f& pos, const CActor* act, CStateManager& mgr);
|
||||||
|
|
Loading…
Reference in New Issue