metaforce/Runtime/Character/CModelData.cpp

376 lines
11 KiB
C++
Raw Normal View History

2016-04-14 03:32:27 +00:00
#include "CModelData.hpp"
#include "CAnimData.hpp"
2016-04-14 21:42:47 +00:00
#include "IAnimReader.hpp"
#include "Graphics/CGraphics.hpp"
#include "Graphics/CSkinnedModel.hpp"
#include "Graphics/CFrustumPlanes.hpp"
#include "Graphics/CVertexMorphEffect.hpp"
#include "Editor/ProjectManager.hpp"
#include "CActorLights.hpp"
#include "CStateManager.hpp"
#include "CPlayerState.hpp"
#include "GameGlobalObjects.hpp"
#include "CAssetFactory.hpp"
#include "CCharacterFactory.hpp"
2016-04-16 03:24:25 +00:00
#include "CAdditiveAnimPlayback.hpp"
2016-04-14 03:32:27 +00:00
namespace urde
{
2016-08-31 23:08:09 +00:00
static logvisor::Module Log("urde::CModelData");
2016-04-14 03:32:27 +00:00
2016-04-15 03:02:21 +00:00
CModelData::~CModelData() {}
2016-04-14 03:32:27 +00:00
CModelData::CModelData() {}
2016-04-15 03:02:21 +00:00
CModelData CModelData::CModelDataNull() {return CModelData();}
2016-04-14 03:32:27 +00:00
CModelData::CModelData(const CStaticRes& res)
: x0_particleScale(res.GetScale())
2016-04-14 03:32:27 +00:00
{
x1c_normalModel = g_SimplePool->GetObj({SBIG('CMDL'), res.GetId()});
2016-08-31 23:08:09 +00:00
if (!x1c_normalModel)
Log.report(logvisor::Fatal, "unable to find CMDL %08X", res.GetId());
2016-04-14 03:32:27 +00:00
}
CModelData::CModelData(const CAnimRes& res)
: x0_particleScale(res.GetScale())
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
TToken<CCharacterFactory> factory = g_CharFactoryBuilder->GetFactory(res);
2016-04-29 10:08:46 +00:00
x10_animData = factory->CreateCharacter(res.GetCharacterNodeId(), res.CanLoop(), factory, res.GetDefaultAnim());
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
SAdvancementDeltas CModelData::GetAdvancementDeltas(const CCharAnimTime& a,
const CCharAnimTime& b) const
2016-04-14 03:32:27 +00:00
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
return x10_animData->GetAdvancementDeltas(a, b);
2016-04-14 21:42:47 +00:00
else
return {};
2016-04-14 03:32:27 +00:00
}
void CModelData::Render(const CStateManager& stateMgr, const zeus::CTransform& xf,
2016-08-21 00:04:50 +00:00
const CActorLights* lights, const CModelFlags& drawFlags)
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
Render(GetRenderingModel(stateMgr), xf, lights, drawFlags);
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
CModelData::EWhichModel CModelData::GetRenderingModel(const CStateManager& stateMgr) const
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
switch (stateMgr.GetPlayerState()->GetActiveVisor(stateMgr))
{
case CPlayerState::EPlayerVisor::XRay:
return CModelData::EWhichModel::XRay;
case CPlayerState::EPlayerVisor::Thermal:
return CModelData::EWhichModel::Thermal;
default:
return CModelData::EWhichModel::Normal;
}
2016-04-14 03:32:27 +00:00
}
2016-08-21 00:04:50 +00:00
CSkinnedModel& CModelData::PickAnimatedModel(EWhichModel which) const
2016-04-14 03:32:27 +00:00
{
2016-08-21 00:04:50 +00:00
CSkinnedModel* ret = nullptr;
2016-04-14 21:42:47 +00:00
switch (which)
{
case EWhichModel::XRay:
2016-04-29 10:08:46 +00:00
ret = x10_animData->xf4_xrayModel.get();
2016-04-14 21:42:47 +00:00
case EWhichModel::Thermal:
2016-04-29 10:08:46 +00:00
ret = x10_animData->xf8_infraModel.get();
2016-04-14 21:42:47 +00:00
default: break;
}
if (ret)
return *ret;
2016-04-29 10:08:46 +00:00
return *x10_animData->xd8_modelData.GetObj();
2016-04-14 03:32:27 +00:00
}
2016-08-21 00:04:50 +00:00
TLockedToken<CModel>& CModelData::PickStaticModel(EWhichModel which)
2016-04-14 03:32:27 +00:00
{
2016-08-21 00:04:50 +00:00
TLockedToken<CModel>* ret = nullptr;
2016-04-14 21:42:47 +00:00
switch (which)
{
case EWhichModel::XRay:
ret = &x2c_xrayModel;
case EWhichModel::Thermal:
ret = &x3c_infraModel;
default: break;
}
if (ret)
return *ret;
return x1c_normalModel;
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
void CModelData::SetXRayModel(const std::pair<ResId, ResId>& modelSkin)
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
if (modelSkin.first)
{
2016-04-15 03:02:21 +00:00
if (g_ResFactory->GetResourceTypeById(modelSkin.first) == SBIG('CMDL'))
2016-04-14 21:42:47 +00:00
{
2016-04-29 10:08:46 +00:00
if (x10_animData && modelSkin.second &&
2016-04-15 03:02:21 +00:00
g_ResFactory->GetResourceTypeById(modelSkin.second) == SBIG('CSKR'))
2016-04-14 21:42:47 +00:00
{
2016-04-29 10:08:46 +00:00
x10_animData->SetXRayModel(g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}),
2016-04-15 03:02:21 +00:00
g_SimplePool->GetObj({SBIG('CSKR'), modelSkin.second}));
2016-04-14 21:42:47 +00:00
}
else
{
2016-04-15 03:02:21 +00:00
x2c_xrayModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first});
2016-04-14 21:42:47 +00:00
}
}
}
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
void CModelData::SetInfraModel(const std::pair<ResId, ResId>& modelSkin)
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
if (modelSkin.first)
{
2016-04-15 03:02:21 +00:00
if (g_ResFactory->GetResourceTypeById(modelSkin.first) == SBIG('CMDL'))
2016-04-14 21:42:47 +00:00
{
2016-04-29 10:08:46 +00:00
if (x10_animData && modelSkin.second &&
2016-04-15 03:02:21 +00:00
g_ResFactory->GetResourceTypeById(modelSkin.second) == SBIG('CSKR'))
2016-04-14 21:42:47 +00:00
{
2016-04-29 10:08:46 +00:00
x10_animData->SetInfraModel(g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first}),
2016-04-15 03:02:21 +00:00
g_SimplePool->GetObj({SBIG('CSKR'), modelSkin.second}));
2016-04-14 21:42:47 +00:00
}
else
{
2016-04-15 03:02:21 +00:00
x3c_infraModel = g_SimplePool->GetObj({SBIG('CMDL'), modelSkin.first});
2016-04-14 21:42:47 +00:00
}
}
}
2016-04-14 03:32:27 +00:00
}
2016-08-21 00:04:50 +00:00
bool CModelData::IsDefinitelyOpaque(EWhichModel which)
2016-04-14 03:32:27 +00:00
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
2016-04-14 21:42:47 +00:00
{
2016-08-21 00:04:50 +00:00
CSkinnedModel& model = PickAnimatedModel(which);
2016-04-14 21:42:47 +00:00
return model.GetModel()->GetInstance().IsOpaque();
}
else
{
2016-08-21 00:04:50 +00:00
TLockedToken<CModel>& model = PickStaticModel(which);
2016-04-14 21:42:47 +00:00
return model->GetInstance().IsOpaque();
}
2016-04-14 03:32:27 +00:00
}
bool CModelData::GetIsLoop() const
{
2016-04-29 10:08:46 +00:00
if (!x10_animData)
2016-04-14 21:42:47 +00:00
return false;
2016-04-29 10:08:46 +00:00
return x10_animData->GetIsLoop();
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
float CModelData::GetAnimationDuration(int idx) const
2016-04-14 03:32:27 +00:00
{
2016-04-29 10:08:46 +00:00
if (!x10_animData)
2016-04-14 21:42:47 +00:00
return 0.f;
2016-04-29 10:08:46 +00:00
return x10_animData->GetAnimationDuration(idx);
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
void CModelData::EnableLooping(bool enable)
2016-04-14 03:32:27 +00:00
{
2016-04-29 10:08:46 +00:00
if (!x10_animData)
2016-04-14 21:42:47 +00:00
return;
2016-04-29 10:08:46 +00:00
x10_animData->EnableLooping(enable);
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
void CModelData::AdvanceParticles(const zeus::CTransform& xf, float dt,
2016-04-14 03:32:27 +00:00
CStateManager& stateMgr)
{
2016-04-29 10:08:46 +00:00
if (!x10_animData)
2016-04-14 21:42:47 +00:00
return;
2016-04-29 10:08:46 +00:00
x10_animData->AdvanceParticles(xf, dt, x0_particleScale, stateMgr);
2016-04-14 03:32:27 +00:00
}
zeus::CAABox CModelData::GetBounds() const
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
2016-04-14 21:42:47 +00:00
{
2016-04-29 10:08:46 +00:00
return x10_animData->GetBoundingBox(zeus::CTransform::Scale(x0_particleScale));
2016-04-14 21:42:47 +00:00
}
else
{
const zeus::CAABox& aabb = x1c_normalModel->GetAABB();
2016-04-29 10:08:46 +00:00
return zeus::CAABox(aabb.min * x0_particleScale, aabb.max * x0_particleScale);
2016-04-14 21:42:47 +00:00
}
2016-04-14 03:32:27 +00:00
}
zeus::CAABox CModelData::GetBounds(const zeus::CTransform& xf) const
{
2016-04-14 21:42:47 +00:00
zeus::CTransform xf2 = xf * zeus::CTransform::Scale(x0_particleScale);
2016-04-29 10:08:46 +00:00
if (x10_animData)
return x10_animData->GetBoundingBox(xf2);
2016-04-14 21:42:47 +00:00
else
return x1c_normalModel->GetAABB().getTransformedAABox(xf2);
2016-04-14 03:32:27 +00:00
}
zeus::CTransform CModelData::GetScaledLocatorTransformDynamic(const std::string& name,
const CCharAnimTime* time) const
{
2016-04-14 21:42:47 +00:00
zeus::CTransform xf = GetLocatorTransformDynamic(name, time);
2016-04-29 10:08:46 +00:00
xf.origin *= x0_particleScale;
2016-04-14 21:42:47 +00:00
return xf;
2016-04-14 03:32:27 +00:00
}
zeus::CTransform CModelData::GetScaledLocatorTransform(const std::string& name) const
{
2016-04-14 21:42:47 +00:00
zeus::CTransform xf = GetLocatorTransform(name);
2016-04-29 10:08:46 +00:00
xf.origin *= x0_particleScale;
2016-04-14 21:42:47 +00:00
return xf;
2016-04-14 03:32:27 +00:00
}
zeus::CTransform CModelData::GetLocatorTransformDynamic(const std::string& name,
const CCharAnimTime* time) const
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
return x10_animData->GetLocatorTransform(name, time);
2016-04-14 21:42:47 +00:00
else
return {};
2016-04-14 03:32:27 +00:00
}
zeus::CTransform CModelData::GetLocatorTransform(const std::string& name) const
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
return x10_animData->GetLocatorTransform(name, nullptr);
2016-04-14 21:42:47 +00:00
else
return {};
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
SAdvancementDeltas CModelData::AdvanceAnimationIgnoreParticles(float dt, CRandom16& rand, bool flag)
2016-04-14 03:32:27 +00:00
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
return x10_animData->AdvanceIgnoreParticles(dt, rand, flag);
2016-04-14 21:42:47 +00:00
else
return {};
2016-04-14 03:32:27 +00:00
}
2016-08-21 20:39:18 +00:00
SAdvancementDeltas CModelData::AdvanceAnimation(float dt, CStateManager& stateMgr, TAreaId aid, bool flag)
2016-04-14 03:32:27 +00:00
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
2016-08-21 20:39:18 +00:00
return x10_animData->Advance(dt, x0_particleScale, stateMgr, aid, flag);
2016-04-14 21:42:47 +00:00
else
return {};
2016-04-14 03:32:27 +00:00
}
bool CModelData::IsAnimating() const
{
2016-04-29 10:08:46 +00:00
if (!x10_animData)
2016-04-14 21:42:47 +00:00
return false;
2016-04-29 10:08:46 +00:00
return x10_animData->IsAnimating();
2016-04-14 03:32:27 +00:00
}
bool CModelData::IsInFrustum(const zeus::CTransform& xf,
const CFrustumPlanes& frustum) const
{
2016-04-29 10:08:46 +00:00
if (!x10_animData && !x1c_normalModel)
2016-04-14 21:42:47 +00:00
return true;
return frustum.BoxInFrustumPlanes(GetBounds(xf));
2016-04-14 03:32:27 +00:00
}
void CModelData::RenderParticles(const CFrustumPlanes& frustum) const
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
x10_animData->RenderAuxiliary(frustum);
2016-04-14 03:32:27 +00:00
}
2016-08-21 00:04:50 +00:00
void CModelData::Touch(EWhichModel which, int shaderIdx)
2016-04-14 03:32:27 +00:00
{
2016-04-29 10:08:46 +00:00
if (x10_animData)
x10_animData->Touch(PickAnimatedModel(which), shaderIdx);
2016-04-14 21:42:47 +00:00
else
PickStaticModel(which)->Touch(shaderIdx);
2016-04-14 03:32:27 +00:00
}
2016-08-21 00:04:50 +00:00
void CModelData::Touch(const CStateManager& stateMgr, int shaderIdx)
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
Touch(GetRenderingModel(stateMgr), shaderIdx);
2016-04-14 03:32:27 +00:00
}
void CModelData::RenderThermal(const zeus::CTransform& xf,
2016-08-21 00:04:50 +00:00
const zeus::CColor& a, const zeus::CColor& b)
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_particleScale));
CGraphics::DisableAllLights();
CModelFlags drawFlags;
drawFlags.m_extendedShaderIdx = 3;
2016-04-29 10:08:46 +00:00
if (x10_animData)
2016-04-14 21:42:47 +00:00
{
2016-08-21 20:39:18 +00:00
CSkinnedModel& model = PickAnimatedModel(EWhichModel::Thermal);
x10_animData->SetupRender(model, drawFlags, {}, nullptr);
2016-04-14 21:42:47 +00:00
model.Draw(drawFlags);
}
else
{
2016-08-21 20:39:18 +00:00
TLockedToken<CModel>& model = PickStaticModel(EWhichModel::Thermal);
2016-04-14 21:42:47 +00:00
model->Draw(drawFlags);
}
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
void CModelData::RenderUnsortedParts(EWhichModel which, const zeus::CTransform& xf,
2016-08-21 00:04:50 +00:00
const CActorLights* lights, const CModelFlags& drawFlags)
2016-04-14 03:32:27 +00:00
{
2016-04-14 21:42:47 +00:00
if ((x14_25_sortThermal && which == EWhichModel::Thermal) ||
2016-04-29 10:08:46 +00:00
x10_animData || !x1c_normalModel || drawFlags.m_blendMode > 2)
2016-04-14 21:42:47 +00:00
{
2016-08-29 04:22:54 +00:00
const_cast<CModelData*>(this)->x14_24_renderSorted = false;
2016-04-14 21:42:47 +00:00
return;
}
CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_particleScale));
2016-08-21 00:04:50 +00:00
TLockedToken<CModel>& model = PickStaticModel(which);
2016-04-14 21:42:47 +00:00
if (lights)
2016-08-21 00:04:50 +00:00
lights->ActivateLights(model->GetInstance());
2016-04-14 21:42:47 +00:00
else
2016-08-21 00:04:50 +00:00
model->GetInstance().ActivateLights({});
2016-04-14 21:42:47 +00:00
2016-08-21 00:04:50 +00:00
model->DrawUnsortedParts(drawFlags);
2016-04-14 21:42:47 +00:00
// Set ambient to white
CGraphics::DisableAllLights();
2016-08-29 04:22:54 +00:00
const_cast<CModelData*>(this)->x14_24_renderSorted = true;
2016-04-14 03:32:27 +00:00
}
2016-04-14 21:42:47 +00:00
void CModelData::Render(EWhichModel which, const zeus::CTransform& xf,
2016-08-21 00:04:50 +00:00
const CActorLights* lights, const CModelFlags& drawFlags)
2016-08-23 03:12:50 +00:00
{
2016-04-14 21:42:47 +00:00
if (x14_25_sortThermal && which == EWhichModel::Thermal)
{
zeus::CColor mul(drawFlags.color.a, drawFlags.color.a, drawFlags.color.a, drawFlags.color.a);
RenderThermal(xf, mul, {0.f, 0.f, 0.f, 0.25f});
}
else
{
CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_particleScale));
2016-04-29 10:08:46 +00:00
if (x10_animData)
2016-04-14 21:42:47 +00:00
{
2016-08-21 00:04:50 +00:00
CSkinnedModel& model = PickAnimatedModel(which);
if (lights)
lights->ActivateLights(model.GetModel()->GetInstance());
else
model.GetModel()->GetInstance().ActivateLights({});
x10_animData->Render(model, drawFlags, {}, nullptr);
2016-04-14 21:42:47 +00:00
}
else
{
2016-08-21 00:04:50 +00:00
TLockedToken<CModel>& model = PickStaticModel(which);
if (lights)
lights->ActivateLights(model->GetInstance());
else
model->GetInstance().ActivateLights({});
2016-04-14 21:42:47 +00:00
if (x14_24_renderSorted)
model->DrawSortedParts(drawFlags);
else
model->Draw(drawFlags);
}
// Set ambient to white
CGraphics::DisableAllLights();
2016-08-29 04:22:54 +00:00
const_cast<CModelData*>(this)->x14_24_renderSorted = false;
2016-04-14 21:42:47 +00:00
}
2016-04-14 03:32:27 +00:00
}
}