Initial fog rendering

This commit is contained in:
Jack Andersen 2016-08-07 18:48:18 -10:00
parent 9b9eed39f4
commit a910ddd912
16 changed files with 335 additions and 92 deletions

View File

@ -534,7 +534,7 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
if (asyncSearch != m_asyncLoadList.end()) if (asyncSearch != m_asyncLoadList.end())
{ {
/* Async spinloop */ /* Async spinloop */
AsyncTask& task = asyncSearch->second; AsyncTask& task = *asyncSearch->second;
task.EnsurePath(task.x0_tag, *resPath); task.EnsurePath(task.x0_tag, *resPath);
/* Pump load pipeline (cooking if needed) */ /* Pump load pipeline (cooking if needed) */
@ -574,13 +574,21 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
return BuildSync(tag, *resPath, paramXfer); return BuildSync(tag, *resPath, paramXfer);
} }
void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag, std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
ProjectResourceFactoryBase::BuildAsyncInternal(const urde::SObjectTag& tag,
const urde::CVParamTransfer& paramXfer, const urde::CVParamTransfer& paramXfer,
urde::IObj** objOut) urde::IObj** objOut)
{ {
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end()) if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return; return {};
m_asyncLoadList.emplace(std::make_pair(tag, AsyncTask(*this, tag, objOut, paramXfer))); return m_asyncLoadList.emplace(std::make_pair(tag, std::make_unique<AsyncTask>(*this, tag, objOut, paramXfer))).first->second;
}
void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag,
const urde::CVParamTransfer& paramXfer,
urde::IObj** objOut)
{
BuildAsyncInternal(tag, paramXfer, objOut);
} }
u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag) u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag)
@ -598,23 +606,23 @@ u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag)
return fr->length(); return fr->length();
} }
bool ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag, std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>& target) std::unique_ptr<u8[]>& target)
{ {
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end()) if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return false; return {};
m_asyncLoadList.emplace(std::make_pair(tag, AsyncTask(*this, tag, target))); return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared<AsyncTask>(*this, tag, target))).first->second;
return true;
} }
bool ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag,
u32 size, u32 off, u32 size, u32 off,
std::unique_ptr<u8[]>& target) std::unique_ptr<u8[]>& target)
{ {
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end()) if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return false; return {};
m_asyncLoadList.emplace(std::make_pair(tag, AsyncTask(*this, tag, target, size, off))); return m_asyncLoadList.emplace(std::make_pair(tag, std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second;
return true;
} }
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag)
@ -736,7 +744,7 @@ void ProjectResourceFactoryBase::AsyncIdle()
/* Ensure requested resource is in the index */ /* Ensure requested resource is in the index */
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex); std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
AsyncTask& task = it->second; AsyncTask& task = *it->second;
auto search = m_tagToPath.find(task.x0_tag); auto search = m_tagToPath.find(task.x0_tag);
if (search == m_tagToPath.end()) if (search == m_tagToPath.end())
{ {

View File

@ -18,23 +18,8 @@ class ProjectResourceFactoryBase : public urde::IFactory
{ {
friend class ProjectResourcePool; friend class ProjectResourcePool;
hecl::ClientProcess& m_clientProc; hecl::ClientProcess& m_clientProc;
protected:
std::unordered_map<urde::SObjectTag, hecl::ProjectPath> m_tagToPath;
std::unordered_map<std::string, urde::SObjectTag> m_catalogNameToTag;
void Clear();
const hecl::Database::Project* m_proj = nullptr;
const hecl::Database::DataSpecEntry* m_origSpec = nullptr;
const hecl::Database::DataSpecEntry* m_pcSpec = nullptr;
/* Used to resolve cooked paths */
std::unique_ptr<hecl::Database::IDataSpec> m_cookSpec;
urde::CFactoryMgr m_factoryMgr;
hecl::BlenderToken m_backgroundBlender;
std::thread m_backgroundIndexTh;
std::mutex m_backgroundIndexMutex;
bool m_backgroundRunning = false;
public:
struct AsyncTask struct AsyncTask
{ {
ProjectResourceFactoryBase& m_parent; ProjectResourceFactoryBase& m_parent;
@ -73,7 +58,25 @@ protected:
void CookComplete(); void CookComplete();
bool AsyncPump(); bool AsyncPump();
}; };
std::unordered_map<SObjectTag, AsyncTask> m_asyncLoadList;
protected:
std::unordered_map<urde::SObjectTag, hecl::ProjectPath> m_tagToPath;
std::unordered_map<std::string, urde::SObjectTag> m_catalogNameToTag;
void Clear();
const hecl::Database::Project* m_proj = nullptr;
const hecl::Database::DataSpecEntry* m_origSpec = nullptr;
const hecl::Database::DataSpecEntry* m_pcSpec = nullptr;
/* Used to resolve cooked paths */
std::unique_ptr<hecl::Database::IDataSpec> m_cookSpec;
urde::CFactoryMgr m_factoryMgr;
hecl::BlenderToken m_backgroundBlender;
std::thread m_backgroundIndexTh;
std::mutex m_backgroundIndexMutex;
bool m_backgroundRunning = false;
std::unordered_map<SObjectTag, std::shared_ptr<AsyncTask>> m_asyncLoadList;
bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut); bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut);
bool bool
@ -107,14 +110,15 @@ public:
ProjectResourceFactoryBase(hecl::ClientProcess& clientProc) : m_clientProc(clientProc) {} ProjectResourceFactoryBase(hecl::ClientProcess& clientProc) : m_clientProc(clientProc) {}
std::unique_ptr<urde::IObj> Build(const urde::SObjectTag&, const urde::CVParamTransfer&); std::unique_ptr<urde::IObj> Build(const urde::SObjectTag&, const urde::CVParamTransfer&);
void BuildAsync(const urde::SObjectTag&, const urde::CVParamTransfer&, urde::IObj**); void BuildAsync(const urde::SObjectTag&, const urde::CVParamTransfer&, urde::IObj**);
std::shared_ptr<AsyncTask> BuildAsyncInternal(const urde::SObjectTag&, const urde::CVParamTransfer&, urde::IObj**);
void CancelBuild(const urde::SObjectTag&); void CancelBuild(const urde::SObjectTag&);
bool CanBuild(const urde::SObjectTag&); bool CanBuild(const urde::SObjectTag&);
const urde::SObjectTag* GetResourceIdByName(const char*) const; const urde::SObjectTag* GetResourceIdByName(const char*) const;
FourCC GetResourceTypeById(ResId id) const; FourCC GetResourceTypeById(ResId id) const;
u32 ResourceSize(const SObjectTag& tag); u32 ResourceSize(const SObjectTag& tag);
bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target); std::shared_ptr<AsyncTask> LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target);
bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target); std::shared_ptr<AsyncTask> LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target);
std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag); std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag);
std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off); std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off);

View File

@ -91,7 +91,9 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ)
boo::SWindowRect windowRect = m_vm.m_mainWindow->getWindowFrame(); boo::SWindowRect windowRect = m_vm.m_mainWindow->getWindowFrame();
float aspect = windowRect.size[0] / float(windowRect.size[1]); float aspect = windowRect.size[0] / float(windowRect.size[1]);
CGraphics::SetPerspective(55.0, aspect, 0.1f, 1000.f); CGraphics::SetPerspective(55.0, aspect, 1.f, 15.f);
CGraphics::SetFog(ERglFogMode::PerspExp, 10.f, 15.f, zeus::CColor::skRed);
//CGraphics::SetFog(ERglFogMode::PerspExp, 10.f + std::sin(m_theta) * 5.f, 15.f + std::sin(m_theta) * 5.f, zeus::CColor::skRed);
zeus::CFrustum frustum; zeus::CFrustum frustum;
frustum.updatePlanes(CGraphics::g_GXModelView, zeus::SProjPersp(55.0, aspect, 0.1f, 1000.f)); frustum.updatePlanes(CGraphics::g_GXModelView, zeus::SProjPersp(55.0, aspect, 0.1f, 1000.f));
g_Renderer->SetClippingPlanes(frustum); g_Renderer->SetClippingPlanes(frustum);
@ -100,13 +102,14 @@ void ViewManager::ParticleView::draw(boo::IGraphicsCommandQueue *gfxQ)
CLight::BuildCustom({5.f, -20.f, 10.f}, {0.f, 1.f, 0.f}, CLight::BuildCustom({5.f, -20.f, 10.f}, {0.f, 1.f, 0.f},
{200.f, 200.f, 200.f}, 0.f, 0.f, 1.f, 1.f, 0.f, 0.f)}; {200.f, 200.f, 200.f}, 0.f, 0.f, 1.f, 1.f, 0.f, 0.f)};
//lights = {CLight::BuildLocalAmbient({}, {1.0f, 0.0f, 0.0f, 1.f})}; //lights = {CLight::BuildLocalAmbient({}, {1.0f, 0.0f, 0.0f, 1.f})};
//m_vm.m_modelTest->GetInstance().ActivateLights(lights); m_vm.m_modelTest->GetInstance().ActivateLights(lights);
g_Renderer->SetThermal(true, 1.f, zeus::CColor::skWhite); //g_Renderer->SetThermal(true, 1.f, zeus::CColor::skWhite);
g_Renderer->SetThermalColdScale(std::sin(m_theta) * 0.5f + 0.5f); //g_Renderer->SetThermalColdScale(std::sin(m_theta) * 0.5f + 0.5f);
g_Renderer->DoThermalBlendCold(); //g_Renderer->DoThermalBlendCold();
flags.m_extendedShaderIdx = 2; //flags.m_extendedShaderIdx = 2;
flags.m_extendedShaderIdx = 1;
m_vm.m_modelTest->Draw(flags); m_vm.m_modelTest->Draw(flags);
g_Renderer->DoThermalBlendHot(); //g_Renderer->DoThermalBlendHot();
//m_spaceWarpFilter.setStrength(std::sin(m_theta * 5.f) * 0.5f + 0.5f); //m_spaceWarpFilter.setStrength(std::sin(m_theta * 5.f) * 0.5f + 0.5f);
//m_spaceWarpFilter.draw(zeus::CVector2f{0.f, 0.f}); //m_spaceWarpFilter.draw(zeus::CVector2f{0.f, 0.f});
} }

View File

@ -107,7 +107,7 @@ void CCameraManager::Update(float dt, CStateManager& stateMgr)
// TODO: Finish // TODO: Finish
zeus::CColor tmpColor; // Get from water zeus::CColor tmpColor; // Get from water
zeus::CVector2f tmpVector; // Get from camera zeus::CVector2f tmpVector; // Get from camera
x3c_fog.SetFogExplicit(ERglFogMode::Four, tmpColor, tmpVector); x3c_fog.SetFogExplicit(ERglFogMode::PerspExp, tmpColor, tmpVector);
stateMgr.GetCameraFilterPass(4).SetFilter(CCameraFilterPass::EFilterType::One, stateMgr.GetCameraFilterPass(4).SetFilter(CCameraFilterPass::EFilterType::One,
CCameraFilterPass::EFilterShape::Zero, CCameraFilterPass::EFilterShape::Zero,
0.f, tmpColor, -1); 0.f, tmpColor, -1);

View File

@ -636,8 +636,11 @@ void CBooRenderer::SetWireframeFlags(int)
{ {
} }
void CBooRenderer::SetWorldFog(ERglFogMode, float, float, const zeus::CColor&) void CBooRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color)
{ {
if (x318_28_disableFog)
mode = ERglFogMode::None;
CGraphics::SetFog(mode, startz, endz, color);
} }
void CBooRenderer::RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken<CModel>*, const CSkinnedModel*) void CBooRenderer::RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken<CModel>*, const CSkinnedModel*)

View File

@ -119,7 +119,7 @@ class CBooRenderer : public IRenderer
bool x318_25_drawWireframe : 1; bool x318_25_drawWireframe : 1;
bool x318_26_ : 1; bool x318_26_ : 1;
bool x318_27_ : 1; bool x318_27_ : 1;
bool x318_28_ : 1; bool x318_28_disableFog : 1;
bool x318_29_thermalVisor : 1; bool x318_29_thermalVisor : 1;
bool x318_30_ : 1; bool x318_30_ : 1;
bool x318_31_ : 1; bool x318_31_ : 1;

View File

@ -10,6 +10,7 @@ namespace urde
{ {
CGraphics::CProjectionState CGraphics::g_Proj; CGraphics::CProjectionState CGraphics::g_Proj;
CGraphics::CFogState CGraphics::g_Fog;
float CGraphics::g_ProjAspect = 1.f; float CGraphics::g_ProjAspect = 1.f;
u32 CGraphics::g_NumLightsActive = 0; u32 CGraphics::g_NumLightsActive = 0;
u32 CGraphics::g_NumBreakpointsWaiting = 0; u32 CGraphics::g_NumBreakpointsWaiting = 0;
@ -66,6 +67,23 @@ void CGraphics::SetAmbientColor(const zeus::CColor& col)
// TODO: set for real // TODO: set for real
} }
void CGraphics::SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color)
{
if (mode == ERglFogMode::None)
{
g_Fog.m_start = 1.f;
}
else
{
float projRange = g_Proj.x18_far - g_Proj.x14_near;
float userRange = endz - startz;
g_Fog.m_color = color;
g_Fog.m_start = (startz - g_Proj.x14_near) / projRange;
g_Fog.m_rangeScale = projRange / userRange;
}
}
void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write) void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write)
{ {

View File

@ -4,6 +4,7 @@
#include "RetroTypes.hpp" #include "RetroTypes.hpp"
#include "zeus/CTransform.hpp" #include "zeus/CTransform.hpp"
#include "zeus/CVector2i.hpp" #include "zeus/CVector2i.hpp"
#include "zeus/CColor.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "boo/graphicsdev/IGraphicsCommandQueue.hpp" #include "boo/graphicsdev/IGraphicsCommandQueue.hpp"
@ -121,6 +122,23 @@ enum class ERglAlphaOp
XNor = 3 XNor = 3
}; };
enum class ERglFogMode
{
None = 0x00,
PerspLin = 0x02,
PerspExp = 0x04,
PerspExp2 = 0x05,
PerspRevExp = 0x06,
PerspRevExp2 = 0x07,
OrthoLin = 0x0A,
OrthoExp = 0x0C,
OrthoExp2 = 0x0D,
OrthoRevExp = 0x0E,
OrthoRevExp2 = 0x0F
};
struct SClipScreenRect struct SClipScreenRect
{ {
bool x0_valid; bool x0_valid;
@ -166,7 +184,16 @@ public:
float x14_near; float x14_near;
float x18_far; float x18_far;
}; };
struct CFogState
{
zeus::CColor m_color;
float m_rangeScale = 4096.f;
float m_start = 1.f;
};
static CProjectionState g_Proj; static CProjectionState g_Proj;
static CFogState g_Fog;
static float g_ProjAspect; static float g_ProjAspect;
static u32 g_NumLightsActive; static u32 g_NumLightsActive;
static u32 g_NumBreakpointsWaiting; static u32 g_NumBreakpointsWaiting;
@ -192,6 +219,7 @@ public:
static void EnableLight(ERglLight light); static void EnableLight(ERglLight light);
static void SetLightState(ERglLightBits lightState); static void SetLightState(ERglLightBits lightState);
static void SetAmbientColor(const zeus::CColor& col); static void SetAmbientColor(const zeus::CColor& col);
static void SetFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color);
static void SetDepthWriteMode(bool test, ERglEnum comp, bool write); static void SetDepthWriteMode(bool test, ERglEnum comp, bool write);
static void SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp); static void SetBlendMode(ERglBlendMode, ERglBlendFactor, ERglBlendFactor, ERglLogicOp);
static void SetCullMode(ERglCullMode); static void SetCullMode(ERglCullMode);

View File

@ -521,6 +521,7 @@ void CBooModel::UpdateUniformData(const CModelFlags& flags) const
lightingOut.colorRegs[0] = flags.regColors[0]; lightingOut.colorRegs[0] = flags.regColors[0];
lightingOut.colorRegs[1] = flags.regColors[1]; lightingOut.colorRegs[1] = flags.regColors[1];
lightingOut.colorRegs[2] = flags.regColors[2]; lightingOut.colorRegs[2] = flags.regColors[2];
lightingOut.fog = CGraphics::g_Fog;
} }
m_uniformBuffer->unmap(); m_uniformBuffer->unmap();

View File

@ -8,6 +8,7 @@
#include "zeus/CPlane.hpp" #include "zeus/CPlane.hpp"
#include "zeus/CFrustum.hpp" #include "zeus/CFrustum.hpp"
#include "zeus/CColor.hpp" #include "zeus/CColor.hpp"
#include "CGraphics.hpp"
namespace urde namespace urde
{ {
@ -37,9 +38,6 @@ public:
enum class EPrimitiveType enum class EPrimitiveType
{ {
}; };
enum class ERglFogMode
{
};
virtual ~IRenderer() = default; virtual ~IRenderer() = default;
virtual void AddStaticGeometry(const std::vector<CMetroidModelInstance>*, const CAreaRenderOctTree*, int)=0; virtual void AddStaticGeometry(const std::vector<CMetroidModelInstance>*, const CAreaRenderOctTree*, int)=0;

View File

@ -5,6 +5,7 @@
#include "optional.hpp" #include "optional.hpp"
#include "zeus/CVector3f.hpp" #include "zeus/CVector3f.hpp"
#include "zeus/CColor.hpp" #include "zeus/CColor.hpp"
#include "Graphics/CGraphics.hpp"
#define URDE_MAX_LIGHTS 16 #define URDE_MAX_LIGHTS 16
@ -36,6 +37,7 @@ public:
Light lights[URDE_MAX_LIGHTS]; Light lights[URDE_MAX_LIGHTS];
zeus::CColor ambient; zeus::CColor ambient;
zeus::CColor colorRegs[3]; zeus::CColor colorRegs[3];
CGraphics::CFogState fog;
}; };
struct ThermalUniform struct ThermalUniform

View File

@ -13,6 +13,12 @@ static const char* LightingGLSL =
" vec4 linAtt;\n" " vec4 linAtt;\n"
" vec4 angAtt;\n" " vec4 angAtt;\n"
"};\n" "};\n"
"struct Fog\n"
"{\n"
" vec4 color;\n"
" float rangeScale;\n"
" float start;\n"
"};\n"
"\n" "\n"
"UBINDING2 uniform LightingUniform\n" "UBINDING2 uniform LightingUniform\n"
"{\n" "{\n"
@ -21,6 +27,7 @@ static const char* LightingGLSL =
" vec4 colorReg0;\n" " vec4 colorReg0;\n"
" vec4 colorReg1;\n" " vec4 colorReg1;\n"
" vec4 colorReg2;\n" " vec4 colorReg2;\n"
" Fog fog;\n"
"};\n" "};\n"
"\n" "\n"
"vec4 LightingFunc(vec4 mvPosIn, vec4 mvNormIn)\n" "vec4 LightingFunc(vec4 mvPosIn, vec4 mvNormIn)\n"
@ -44,6 +51,15 @@ static const char* LightingGLSL =
" return clamp(ret, vec4(0.0,0.0,0.0,0.0), vec4(1.0,1.0,1.0,1.0));\n" " return clamp(ret, vec4(0.0,0.0,0.0,0.0), vec4(1.0,1.0,1.0,1.0));\n"
"}\n"; "}\n";
static const char* MainPostGLSL =
"vec4 MainPostFunc(vec4 colorIn)\n"
"{\n"
" float fogZ = (vtf.mvPos.z - fog.start) * fog.rangeScale;\n"
" return vec4(fogZ, fogZ, fogZ, 1.0);\n"
" return mix(fog.color, colorIn, clamp(exp2(-8.0 * fogZ), 0.0, 1.0));\n"
"}\n"
"\n";
static const char* ThermalPostGLSL = static const char* ThermalPostGLSL =
"UBINDING2 uniform ThermalUniform\n" "UBINDING2 uniform ThermalUniform\n"
"{\n" "{\n"
@ -70,7 +86,7 @@ CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat)
hecl::Runtime::ShaderCacheExtensions ext(plat); hecl::Runtime::ShaderCacheExtensions ext(plat);
/* Normal lit shading */ /* Normal lit shading */
ext.registerExtensionSlot({LightingGLSL, "LightingFunc"}, {}, 3, BlockNames, 0, nullptr, ext.registerExtensionSlot({LightingGLSL, "LightingFunc"}, {MainPostGLSL, "MainPostFunc"}, 3, BlockNames, 0, nullptr,
hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original); hecl::Backend::BlendFactor::Original, hecl::Backend::BlendFactor::Original);
/* Thermal Visor shading */ /* Thermal Visor shading */

View File

@ -30,8 +30,8 @@ public:
/* Non-factory versions, replaces CResLoader */ /* Non-factory versions, replaces CResLoader */
virtual u32 ResourceSize(const urde::SObjectTag& tag)=0; virtual u32 ResourceSize(const urde::SObjectTag& tag)=0;
virtual bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target)=0; //virtual bool LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target)=0;
virtual bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target)=0; //virtual bool LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target)=0;
virtual std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag)=0; virtual std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag)=0;
virtual std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off)=0; virtual std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off)=0;
}; };

View File

@ -177,33 +177,98 @@ void CAreaRenderOctTree::FindOverlappingModels(std::vector<u32>& out, const zeus
void CGameArea::CAreaFog::SetCurrent() const void CGameArea::CAreaFog::SetCurrent() const
{ {
g_Renderer->SetWorldFog(x0_fogMode, x4_rangeCur[0], x4_rangeCur[1], x1c_colorCur);
} }
void CGameArea::CAreaFog::Update(float dt) void CGameArea::CAreaFog::Update(float dt)
{ {
} if (x0_fogMode == ERglFogMode::None)
return;
if (x1c_colorCur == x28_colorTarget && x4_rangeCur == xc_rangeTarget)
return;
void CGameArea::CAreaFog::RollFogOut(float, float, const zeus::CColor& color) float colorDelta = x34_colorDelta * dt;
zeus::CVector2f rangeDelta = x14_rangeDelta * dt;
for (int i=0 ; i<3 ; ++i)
{ {
float delta = x28_colorTarget[i] - x1c_colorCur[i];
if (std::fabs(delta) <= colorDelta)
{
x1c_colorCur[i] = x28_colorTarget[i];
}
else
{
if (delta < 0.f)
x1c_colorCur[i] -= colorDelta;
else
x1c_colorCur[i] += colorDelta;
}
} }
void CGameArea::CAreaFog::FadeFog(ERglFogMode, for (int i=0 ; i<2 ; ++i)
{
float delta = xc_rangeTarget[i] - x4_rangeCur[i];
if (std::fabs(delta) <= rangeDelta[i])
{
x4_rangeCur[i] = xc_rangeTarget[i];
}
else
{
if (delta < 0.f)
x4_rangeCur[i] -= rangeDelta[i];
else
x4_rangeCur[i] += rangeDelta[i];
}
}
}
void CGameArea::CAreaFog::RollFogOut(float rangeDelta, float colorDelta, const zeus::CColor& color)
{
x14_rangeDelta = {rangeDelta, rangeDelta * 2.f};
xc_rangeTarget = {4096.f, 4096.f};
x34_colorDelta = colorDelta;
x28_colorTarget = color;
}
void CGameArea::CAreaFog::FadeFog(ERglFogMode mode,
const zeus::CColor& color, const zeus::CVector2f& vec1, const zeus::CColor& color, const zeus::CVector2f& vec1,
float, const zeus::CVector2f& vec2) float speed, const zeus::CVector2f& vec2)
{ {
if (x0_fogMode == ERglFogMode::None)
{
x1c_colorCur = color;
x28_colorTarget = color;
x4_rangeCur = {vec1[1], vec1[1]};
xc_rangeTarget = vec1;
}
else
{
x28_colorTarget = color;
xc_rangeTarget = vec1;
}
x0_fogMode = mode;
x34_colorDelta = speed;
x14_rangeDelta = vec2;
} }
void CGameArea::CAreaFog::SetFogExplicit(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec) void CGameArea::CAreaFog::SetFogExplicit(ERglFogMode mode, const zeus::CColor& color, const zeus::CVector2f& range)
{ {
x0_fogMode = mode;
x1c_colorCur = color;
x28_colorTarget = color;
x4_rangeCur = range;
xc_rangeTarget = range;
} }
bool CGameArea::CAreaFog::IsFogDisabled() const bool CGameArea::CAreaFog::IsFogDisabled() const
{ {
return true; return x0_fogMode == ERglFogMode::None;
} }
void CGameArea::CAreaFog::DisableFog() void CGameArea::CAreaFog::DisableFog()
{ {
x0_fogMode = ERglFogMode::None;
} }
static std::vector<SObjectTag> ReadDependencyList(CInputStream& in) static std::vector<SObjectTag> ReadDependencyList(CInputStream& in)
@ -257,38 +322,37 @@ bool CDummyGameArea::IGetScriptingMemoryAlways() const
TAreaId CDummyGameArea::IGetAreaId() const TAreaId CDummyGameArea::IGetAreaId() const
{ {
return 0; return x10_areaId;
} }
ResId CDummyGameArea::IGetAreaAssetId() const ResId CDummyGameArea::IGetAreaAssetId() const
{ {
return 0; return xc_mrea;
} }
bool CDummyGameArea::IIsActive() const bool CDummyGameArea::IIsActive() const
{ {
return false; return true;
} }
TAreaId CDummyGameArea::IGetAttachedAreaId(int) const TAreaId CDummyGameArea::IGetAttachedAreaId(int idx) const
{ {
return 0; return x44_attachedAreaIndices[idx];
} }
u32 CDummyGameArea::IGetNumAttachedAreas() const u32 CDummyGameArea::IGetNumAttachedAreas() const
{ {
return 0; return x44_attachedAreaIndices.size();
} }
ResId CDummyGameArea::IGetStringTableAssetId() const ResId CDummyGameArea::IGetStringTableAssetId() const
{ {
return 0; return x8_nameSTRG;
} }
static zeus::CTransform identityXf(zeus::CMatrix3f::skIdentityMatrix3f);
const zeus::CTransform& CDummyGameArea::IGetTM() const const zeus::CTransform& CDummyGameArea::IGetTM() const
{ {
return identityXf; return x14_transform;
} }
CGameArea::CGameArea(CInputStream& in, int idx, int mlvlVersion) CGameArea::CGameArea(CInputStream& in, int idx, int mlvlVersion)
@ -357,24 +421,24 @@ bool CGameArea::IIsActive() const
return false; return false;
} }
TAreaId CGameArea::IGetAttachedAreaId(int) const TAreaId CGameArea::IGetAttachedAreaId(int idx) const
{ {
return 0; return x8c_attachedAreaIndices[idx];
} }
u32 CGameArea::IGetNumAttachedAreas() const u32 CGameArea::IGetNumAttachedAreas() const
{ {
return 0; return x8c_attachedAreaIndices.size();
} }
ResId CGameArea::IGetStringTableAssetId() const ResId CGameArea::IGetStringTableAssetId() const
{ {
return 0; return x8_nameSTRG;
} }
const zeus::CTransform& CGameArea::IGetTM() const const zeus::CTransform& CGameArea::IGetTM() const
{ {
return identityXf; return xc_transform;
} }
bool CGameArea::DoesAreaNeedEnvFx() const bool CGameArea::DoesAreaNeedEnvFx() const
@ -469,17 +533,93 @@ void CGameArea::SetChain(CGameArea* other, int)
{ {
} }
void CGameArea::StartStreamingMainArea() bool CGameArea::StartStreamingMainArea()
{ {
if (xf0_24_postConstructed)
return false;
switch (xf4_phase)
{
case Phase::LoadHeader:
{
x110_mreaSecBufs.reserve(3);
AllocNewAreaData(0, 96);
x12c_postConstructed.reset(new CPostConstructed());
xf4_phase = Phase::LoadSecSizes;
break;
}
case Phase::LoadSecSizes:
{
CullDeadAreaRequests();
if (xf8_loadTransactions.size())
break;
MREAHeader header = VerifyHeader();
AllocNewAreaData(x110_mreaSecBufs[0].second, ROUND_UP_32(header.secCount * 4));
xf4_phase = Phase::ReserveSections;
break;
}
case Phase::ReserveSections:
{
CullDeadAreaRequests();
if (xf8_loadTransactions.size())
break;
x110_mreaSecBufs.reserve(GetNumPartSizes() + 2);
x124_secCount = 0;
x128_mreaDataOffset = x110_mreaSecBufs[0].second + x110_mreaSecBufs[1].second;
xf4_phase = Phase::LoadDataSections;
break;
}
case Phase::LoadDataSections:
{
CullDeadAreaRequests();
u32 totalSz = 0;
u32 secCount = GetNumPartSizes();
for (int i=2 ; i<secCount ; ++i)
totalSz += hecl::SBig(reinterpret_cast<u32*>(x110_mreaSecBufs[1].first.get())[i]);
AllocNewAreaData(x128_mreaDataOffset, totalSz);
m_resolvedBufs.reserve(secCount);
m_resolvedBufs.emplace_back(x110_mreaSecBufs[0].first.get(), x110_mreaSecBufs[0].second);
m_resolvedBufs.emplace_back(x110_mreaSecBufs[1].first.get(), x110_mreaSecBufs[1].second);
u32 curOff = 0;
for (int i=2 ; i<secCount ; ++i)
{
u32 size = hecl::SBig(reinterpret_cast<u32*>(x110_mreaSecBufs[1].first.get())[i]);
m_resolvedBufs.emplace_back(x110_mreaSecBufs[2].first.get() + curOff, size);
curOff += size;
}
xf4_phase = Phase::WaitForFinish;
break;
}
case Phase::WaitForFinish:
{
CullDeadAreaRequests();
if (xf8_loadTransactions.size())
break;
return false;
}
default: break;
}
return true;
} }
u32 CGameArea::GetNumPartSizes() const u32 CGameArea::GetNumPartSizes() const
{ {
return 0; return hecl::SBig(*reinterpret_cast<u32*>(x110_mreaSecBufs[0].first.get() + 60));
} }
void CGameArea::AllocNewAreaData(int, int) void CGameArea::AllocNewAreaData(int offset, int size)
{ {
x110_mreaSecBufs.emplace_back(new u8[size], size);
xf8_loadTransactions.push_back(
static_cast<ProjectResourceFactoryBase*>(g_ResFactory)->
LoadResourcePartAsync(SObjectTag{FOURCC('MREA'), x84_mrea}, size, offset,
x110_mreaSecBufs.back().first));
} }
void CGameArea::Invalidate(CStateManager& mgr) void CGameArea::Invalidate(CStateManager& mgr)
@ -488,6 +628,15 @@ void CGameArea::Invalidate(CStateManager& mgr)
void CGameArea::CullDeadAreaRequests() void CGameArea::CullDeadAreaRequests()
{ {
for (auto it = xf8_loadTransactions.begin() ; it != xf8_loadTransactions.end() ;)
{
if ((*it)->m_complete)
{
it = xf8_loadTransactions.erase(it);
continue;
}
++it;
}
} }
void CGameArea::StartStreamIn(CStateManager& mgr) void CGameArea::StartStreamIn(CStateManager& mgr)
@ -629,6 +778,8 @@ void CGameArea::PostConstructArea()
void CGameArea::FillInStaticGeometry() void CGameArea::FillInStaticGeometry()
{ {
x12c_postConstructed->x4c_insts.clear();
} }
void CGameArea::VerifyTokenList(CStateManager& stateMgr) void CGameArea::VerifyTokenList(CStateManager& stateMgr)

View File

@ -13,16 +13,13 @@
#include "CObjectList.hpp" #include "CObjectList.hpp"
#include "CWorldLight.hpp" #include "CWorldLight.hpp"
#include "Graphics/CPVSAreaSet.hpp" #include "Graphics/CPVSAreaSet.hpp"
#include "Graphics/CGraphics.hpp"
#include "CPathFindArea.hpp"
#include "Editor/ProjectResourceFactoryBase.hpp"
namespace urde namespace urde
{ {
class CStateManager; class CStateManager;
class CPFArea;
enum class ERglFogMode
{
Four = 4
};
class CDummyGameArea : public IGameArea class CDummyGameArea : public IGameArea
{ {
@ -113,24 +110,34 @@ class CGameArea : public IGameArea
u8 _dummy = 0; u8 _dummy = 0;
}; };
std::list<std::shared_ptr<const hecl::ClientProcess::BufferTransaction>> xf8_loadTransactions; enum class Phase
{
LoadHeader,
LoadSecSizes,
ReserveSections,
LoadDataSections,
WaitForFinish
} xf4_phase = Phase::LoadHeader;
std::list<std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>> xf8_loadTransactions;
public: public:
class CAreaFog class CAreaFog
{ {
zeus::CVector2f x4_ = {0.f, 1024.f}; ERglFogMode x0_fogMode = ERglFogMode::None;
zeus::CVector2f xc_ = {0.f, 1024.f}; zeus::CVector2f x4_rangeCur = {0.f, 1024.f};
zeus::CVector2f x14_; zeus::CVector2f xc_rangeTarget = {0.f, 1024.f};
zeus::CVector3f x1c_ = {0.5f}; zeus::CVector2f x14_rangeDelta;
zeus::CVector3f x28_ = {0.5f}; zeus::CColor x1c_colorCur = {0.5f, 0.5f, 0.5f, 1.f};
float x34_ = 0.f; zeus::CColor x28_colorTarget = {0.5f, 0.5f, 0.5f, 1.f};
float x34_colorDelta = 0.f;
public: public:
void SetCurrent() const; void SetCurrent() const;
void Update(float dt); void Update(float dt);
void RollFogOut(float, float, const zeus::CColor& color); void RollFogOut(float rangeDelta, float colorDelta, const zeus::CColor& color);
void FadeFog(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec1, void FadeFog(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec1,
float, const zeus::CVector2f& vec2); float, const zeus::CVector2f& vec2);
void SetFogExplicit(ERglFogMode, const zeus::CColor& color, const zeus::CVector2f& vec); void SetFogExplicit(ERglFogMode mode, const zeus::CColor& color, const zeus::CVector2f& range);
bool IsFogDisabled() const; bool IsFogDisabled() const;
void DisableFog(); void DisableFog();
}; };
@ -154,7 +161,7 @@ public:
TUniqueId x4_uid = kInvalidUniqueId; TUniqueId x4_uid = kInvalidUniqueId;
} xa8_map[1024]; } xa8_map[1024];
u32 x10a8_pvsVersion = 0; u32 x10a8_pvsVersion = 0;
TLockedToken<CPFArea> x10ac_path; TLockedToken<CPathFindArea> x10ac_path;
// bool x10b8_ = 0; optional flag for CToken // bool x10b8_ = 0; optional flag for CToken
u32 x10bc_ = 0; u32 x10bc_ = 0;
std::unique_ptr<CObjectList> x10c0_areaObjs; std::unique_ptr<CObjectList> x10c0_areaObjs;
@ -197,6 +204,9 @@ public:
}; };
private: private:
std::vector<std::pair<std::unique_ptr<u8[]>, int>> x110_mreaSecBufs; std::vector<std::pair<std::unique_ptr<u8[]>, int>> x110_mreaSecBufs;
std::vector<std::pair<u8*, int>> m_resolvedBufs;
u32 x124_secCount = 0;
u32 x128_mreaDataOffset = 0;
std::unique_ptr<CPostConstructed> x12c_postConstructed; std::unique_ptr<CPostConstructed> x12c_postConstructed;
void UpdateFog(float dt); void UpdateFog(float dt);
@ -256,7 +266,7 @@ public:
//void TransferTokensToARAM(); //void TransferTokensToARAM();
//void TransferARAMTokensOver(); //void TransferARAMTokensOver();
void SetChain(CGameArea* other, int); void SetChain(CGameArea* other, int);
void StartStreamingMainArea(); bool StartStreamingMainArea();
//void UnloadAllLoadedTextures(); //void UnloadAllLoadedTextures();
//void ReloadAllLoadedTextures(); //void ReloadAllLoadedTextures();
u32 GetNumPartSizes() const; u32 GetNumPartSizes() const;

View File

@ -5,6 +5,7 @@
#include "CStateManager.hpp" #include "CStateManager.hpp"
#include "CInGameTweakManagerBase.hpp" #include "CInGameTweakManagerBase.hpp"
#include "Audio/CAudioGroupSet.hpp" #include "Audio/CAudioGroupSet.hpp"
#include "Editor/ProjectResourceFactoryBase.hpp"
namespace urde namespace urde
{ {
@ -19,7 +20,7 @@ CDummyWorld::CDummyWorld(ResId mlvlId, bool loadMap)
: x4_loadMap(loadMap) : x4_loadMap(loadMap)
{ {
SObjectTag tag{FOURCC('MLVL'), mlvlId}; SObjectTag tag{FOURCC('MLVL'), mlvlId};
g_ResFactory->LoadResourceAsync(tag, x34_loadBuf); static_cast<ProjectResourceFactoryBase*>(g_ResFactory)->LoadResourceAsync(tag, x34_loadBuf);
} }
ResId CDummyWorld::IGetWorldAssetId() const ResId CDummyWorld::IGetWorldAssetId() const
@ -198,7 +199,7 @@ CWorld::CWorld(IObjectStore& objStore, IFactory& resFactory, ResId mlvlId)
: x60_objectStore(objStore), x64_resFactory(resFactory) : x60_objectStore(objStore), x64_resFactory(resFactory)
{ {
SObjectTag tag{FOURCC('MLVL'), mlvlId}; SObjectTag tag{FOURCC('MLVL'), mlvlId};
resFactory.LoadResourceAsync(tag, x40_loadBuf); static_cast<ProjectResourceFactoryBase&>(resFactory).LoadResourceAsync(tag, x40_loadBuf);
} }
ResId CWorld::IGetWorldAssetId() const ResId CWorld::IGetWorldAssetId() const