mirror of https://github.com/AxioDL/metaforce.git
PVS implementations
This commit is contained in:
parent
56328c3e4d
commit
50fe6d34ab
|
@ -21,7 +21,7 @@ struct HINT : BigYAML
|
|||
Value<float> immediateTime;
|
||||
Value<float> normalTime;
|
||||
UniqueID32 stringID;
|
||||
Value<atUint32> continueDelayTime;
|
||||
Value<atUint32> textPageCount;
|
||||
struct Location : BigYAML
|
||||
{
|
||||
DECL_YAML
|
||||
|
|
|
@ -560,6 +560,16 @@ bool ProjectResourceFactoryBase::AsyncTask::AsyncPump()
|
|||
return m_failed;
|
||||
}
|
||||
|
||||
void ProjectResourceFactoryBase::AsyncTask::WaitForComplete()
|
||||
{
|
||||
using ItType = std::unordered_map<SObjectTag, std::shared_ptr<AsyncTask>>::iterator;
|
||||
ItType search = m_parent.m_asyncLoadList.find(x0_tag);
|
||||
if (search == m_parent.m_asyncLoadList.end())
|
||||
return;
|
||||
for (ItType tmp = search ; !m_parent.AsyncPumpTask(tmp) ; tmp = search)
|
||||
{std::this_thread::sleep_for(std::chrono::milliseconds(2));}
|
||||
}
|
||||
|
||||
bool ProjectResourceFactoryBase::WaitForTagReady(const urde::SObjectTag& tag,
|
||||
const hecl::ProjectPath*& pathOut)
|
||||
{
|
||||
|
@ -921,6 +931,70 @@ void ProjectResourceFactoryBase::EnumerateNamedResources(
|
|||
}
|
||||
}
|
||||
|
||||
bool ProjectResourceFactoryBase::AsyncPumpTask(
|
||||
std::unordered_map<SObjectTag, std::shared_ptr<AsyncTask>>::iterator& it)
|
||||
{
|
||||
/* Ensure requested resource is in the index */
|
||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||
AsyncTask& task = *it->second;
|
||||
auto search = m_tagToPath.find(task.x0_tag);
|
||||
if (search == m_tagToPath.end())
|
||||
{
|
||||
if (!m_backgroundRunning)
|
||||
{
|
||||
Log.report(logvisor::Error, _S("unable to find async load resource (%s, %08X)"),
|
||||
task.x0_tag.type.toString().c_str(), task.x0_tag.id);
|
||||
it = m_asyncLoadList.erase(it);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
lk.unlock();
|
||||
task.EnsurePath(task.x0_tag, search->second);
|
||||
|
||||
/* Pump load pipeline (cooking if needed) */
|
||||
if (task.AsyncPump())
|
||||
{
|
||||
if (task.m_complete)
|
||||
{
|
||||
/* Load complete, build resource */
|
||||
if (task.xc_targetObjPtr)
|
||||
{
|
||||
/* Factory build */
|
||||
std::unique_ptr<IObj> newObj;
|
||||
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
|
||||
{
|
||||
newObj = m_factoryMgr.MakeObjectFromMemory(task.x0_tag, std::move(task.x10_loadBuffer),
|
||||
task.x14_resSize, false, task.x18_cvXfer,
|
||||
task.m_selfRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
|
||||
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer, task.m_selfRef);
|
||||
}
|
||||
|
||||
*task.xc_targetObjPtr = newObj.release();
|
||||
Log.report(logvisor::Info, "async-built %.4s %08X",
|
||||
task.x0_tag.type.toString().c_str(),
|
||||
u32(task.x0_tag.id));
|
||||
}
|
||||
else if (task.xc_targetDataPtr)
|
||||
{
|
||||
/* Buffer only */
|
||||
*task.xc_targetDataPtr = std::move(task.x10_loadBuffer);
|
||||
Log.report(logvisor::Info, "async-loaded %.4s %08X",
|
||||
task.x0_tag.type.toString().c_str(),
|
||||
u32(task.x0_tag.id));
|
||||
}
|
||||
}
|
||||
|
||||
it = m_asyncLoadList.erase(it);
|
||||
return true;
|
||||
}
|
||||
++it;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProjectResourceFactoryBase::AsyncIdle()
|
||||
{
|
||||
/* Consume completed transactions, they will be processed this cycle at the latest */
|
||||
|
@ -936,64 +1010,7 @@ void ProjectResourceFactoryBase::AsyncIdle()
|
|||
if (std::chrono::duration_cast<std::chrono::milliseconds>(resStart - start).count() > 8)
|
||||
break;
|
||||
|
||||
/* Ensure requested resource is in the index */
|
||||
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
|
||||
AsyncTask& task = *it->second;
|
||||
auto search = m_tagToPath.find(task.x0_tag);
|
||||
if (search == m_tagToPath.end())
|
||||
{
|
||||
if (!m_backgroundRunning)
|
||||
{
|
||||
Log.report(logvisor::Error, _S("unable to find async load resource (%s, %08X)"),
|
||||
task.x0_tag.type.toString().c_str(), task.x0_tag.id);
|
||||
it = m_asyncLoadList.erase(it);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
lk.unlock();
|
||||
task.EnsurePath(task.x0_tag, search->second);
|
||||
|
||||
/* Pump load pipeline (cooking if needed) */
|
||||
if (task.AsyncPump())
|
||||
{
|
||||
if (task.m_complete)
|
||||
{
|
||||
/* Load complete, build resource */
|
||||
if (task.xc_targetObjPtr)
|
||||
{
|
||||
/* Factory build */
|
||||
std::unique_ptr<IObj> newObj;
|
||||
if (m_factoryMgr.CanMakeMemory(task.x0_tag))
|
||||
{
|
||||
newObj = m_factoryMgr.MakeObjectFromMemory(task.x0_tag, std::move(task.x10_loadBuffer),
|
||||
task.x14_resSize, false, task.x18_cvXfer,
|
||||
task.m_selfRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
athena::io::MemoryReader mr(task.x10_loadBuffer.get(), task.x14_resSize);
|
||||
newObj = m_factoryMgr.MakeObject(task.x0_tag, mr, task.x18_cvXfer, task.m_selfRef);
|
||||
}
|
||||
|
||||
*task.xc_targetObjPtr = newObj.release();
|
||||
Log.report(logvisor::Info, "async-built %.4s %08X",
|
||||
task.x0_tag.type.toString().c_str(),
|
||||
u32(task.x0_tag.id));
|
||||
}
|
||||
else if (task.xc_targetDataPtr)
|
||||
{
|
||||
/* Buffer only */
|
||||
*task.xc_targetDataPtr = std::move(task.x10_loadBuffer);
|
||||
Log.report(logvisor::Info, "async-loaded %.4s %08X",
|
||||
task.x0_tag.type.toString().c_str(),
|
||||
u32(task.x0_tag.id));
|
||||
}
|
||||
}
|
||||
|
||||
it = m_asyncLoadList.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
AsyncPumpTask(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
const hecl::ProjectPath& path);
|
||||
void CookComplete();
|
||||
bool AsyncPump();
|
||||
void WaitForComplete();
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -133,6 +134,7 @@ public:
|
|||
std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag);
|
||||
std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off);
|
||||
|
||||
bool AsyncPumpTask(std::unordered_map<SObjectTag, std::shared_ptr<AsyncTask>>::iterator& it);
|
||||
void AsyncIdle();
|
||||
void Shutdown() {CancelBackgroundIndex();}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ CGameHintInfo::CGameHint::CGameHint(CInputStream& in, s32 version)
|
|||
, x10_immediateTime(in.readFloatBig())
|
||||
, x14_normalTime(in.readFloatBig())
|
||||
, x18_stringId(in.readUint32Big())
|
||||
, x1c_continueDelayTime(3.f * float(version <= 0 ? 1 : in.readUint32Big()))
|
||||
, x1c_textTime(3.f * float(version <= 0 ? 1 : in.readUint32Big()))
|
||||
{
|
||||
u32 locationCount = in.readUint32Big();
|
||||
x20_locations.reserve(locationCount);
|
||||
|
|
|
@ -24,14 +24,14 @@ public:
|
|||
float x10_immediateTime;
|
||||
float x14_normalTime;
|
||||
ResId x18_stringId;
|
||||
float x1c_continueDelayTime;
|
||||
float x1c_textTime;
|
||||
std::vector<SHintLocation> x20_locations;
|
||||
public:
|
||||
CGameHint(CInputStream&, s32);
|
||||
|
||||
float GetNormalTime() const { return x14_normalTime; }
|
||||
float GetImmediateTime() const { return x10_immediateTime; }
|
||||
float GetContinueDelayTime() const { return x1c_continueDelayTime; }
|
||||
float GetTextTime() const { return x1c_textTime; }
|
||||
const std::string& GetName() const { return x0_name; }
|
||||
ResId GetStringID() const { return x18_stringId; }
|
||||
const std::vector<SHintLocation>& GetLocations() const { return x20_locations; }
|
||||
|
|
|
@ -564,7 +564,7 @@ void CHintOptions::SetNextHintTime()
|
|||
if (x10_nextHintIdx == -1)
|
||||
return;
|
||||
x0_hintStates[x10_nextHintIdx].x4_time =
|
||||
g_MemoryCardSys->GetHints()[x10_nextHintIdx].GetContinueDelayTime() + 5.f;
|
||||
g_MemoryCardSys->GetHints()[x10_nextHintIdx].GetTextTime() + 5.f;
|
||||
}
|
||||
|
||||
void CHintOptions::InitializeMemoryState()
|
||||
|
@ -583,7 +583,7 @@ const CHintOptions::SHintState* CHintOptions::GetCurrentDisplayedHint() const
|
|||
|
||||
const SHintState& hintState = x0_hintStates[x10_nextHintIdx];
|
||||
const CGameHintInfo::CGameHint& hint = g_MemoryCardSys->GetHints()[x10_nextHintIdx];
|
||||
if (hintState.x4_time >= hint.GetContinueDelayTime())
|
||||
if (hintState.x4_time >= hint.GetTextTime())
|
||||
return nullptr;
|
||||
|
||||
if (hintState.x4_time < 3.f)
|
||||
|
@ -602,12 +602,9 @@ void CHintOptions::DelayHint(const char* name)
|
|||
return;
|
||||
|
||||
if (x10_nextHintIdx == idx)
|
||||
{
|
||||
for (SHintState& state : x0_hintStates)
|
||||
state.x4_time += 60.f;
|
||||
|
||||
}
|
||||
|
||||
x0_hintStates[idx].x0_state = EHintState::Delayed;
|
||||
}
|
||||
|
||||
|
@ -639,7 +636,7 @@ void CHintOptions::ActivateContinueDelayHintTimer(const char* name)
|
|||
if (hintState.x0_state != EHintState::Two)
|
||||
return;
|
||||
|
||||
hintState.x4_time = hint.GetContinueDelayTime();
|
||||
hintState.x4_time = hint.GetTextTime();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -366,7 +366,64 @@ void CStateManager::SetupFogForArea(const CGameArea& area) const {}
|
|||
|
||||
void CStateManager::PreRender() {}
|
||||
|
||||
void CStateManager::GetVisSetForArea(TAreaId, TAreaId) const {}
|
||||
bool CStateManager::GetVisSetForArea(TAreaId a, TAreaId b, CPVSVisSet& setOut) const
|
||||
{
|
||||
if (b == kInvalidAreaId)
|
||||
return false;
|
||||
|
||||
zeus::CVector3f viewPoint = CGraphics::g_ViewMatrix.origin;
|
||||
zeus::CVector3f closestDockPoint = viewPoint;
|
||||
bool hasClosestDock = false;
|
||||
if (a != b)
|
||||
{
|
||||
CGameArea& area = *x850_world->GetGameAreas()[b];
|
||||
if (area.IsPostConstructed())
|
||||
{
|
||||
for (const CGameArea::Dock& dock : area.GetDocks())
|
||||
{
|
||||
for (int i=0 ; i<dock.GetDockRefs().size() ; ++i)
|
||||
{
|
||||
TAreaId connArea = dock.GetConnectedAreaId(i);
|
||||
if (connArea == a)
|
||||
{
|
||||
const auto& verts = dock.GetPlaneVertices();
|
||||
zeus::CVector3f dockCenter = (verts[0] + verts[1] + verts[2] + verts[4]) * 0.25f;
|
||||
if (hasClosestDock)
|
||||
if ((dockCenter - viewPoint).magSquared() >=
|
||||
(closestDockPoint - viewPoint).magSquared())
|
||||
continue;
|
||||
closestDockPoint = dockCenter;
|
||||
hasClosestDock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hasClosestDock = true;
|
||||
}
|
||||
|
||||
if (hasClosestDock)
|
||||
{
|
||||
if (CPVSAreaSet* pvs = x850_world->GetGameAreas()[a]->GetPostConstructed()->xa0_pvs.get())
|
||||
{
|
||||
const CPVSVisOctree& octree = pvs->GetVisOctree();
|
||||
zeus::CVector3f closestDockLocal =
|
||||
x850_world->GetGameAreas()[a]->GetInverseTransform() * closestDockPoint;
|
||||
CPVSVisSet set;
|
||||
set.SetTestPoint(octree, closestDockLocal);
|
||||
|
||||
if (set.GetState() == EPVSVisSetState::NodeFound)
|
||||
{
|
||||
setOut = set;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CStateManager::RecursiveDrawTree(TUniqueId) const {}
|
||||
|
||||
|
@ -557,14 +614,14 @@ std::pair<TEditorId, TUniqueId> CStateManager::GenerateObject(TEditorId)
|
|||
return {kInvalidEditorId, kInvalidUniqueId};
|
||||
}
|
||||
|
||||
void CStateManager::InitScriptObjects(std::vector<TEditorId>& ids)
|
||||
void CStateManager::InitScriptObjects(const std::vector<TEditorId>& ids)
|
||||
{
|
||||
for (TEditorId id : ids)
|
||||
{
|
||||
if (id == kInvalidEditorId)
|
||||
continue;
|
||||
TUniqueId uid = GetIdForScript(id);
|
||||
SendScriptMsg(uid, kInvalidUniqueId, EScriptObjectMessage::InternalMessage13);
|
||||
SendScriptMsg(uid, kInvalidUniqueId, EScriptObjectMessage::Constructed);
|
||||
}
|
||||
MurderScriptInstanceNames();
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ public:
|
|||
void DrawWorld() const;
|
||||
void SetupFogForArea(const CGameArea& area) const;
|
||||
void PreRender();
|
||||
void GetVisSetForArea(TAreaId, TAreaId) const;
|
||||
bool GetVisSetForArea(TAreaId, TAreaId, CPVSVisSet& setOut) const;
|
||||
void RecursiveDrawTree(TUniqueId) const;
|
||||
void SendScriptMsg(CEntity* dest, TUniqueId src, EScriptObjectMessage msg);
|
||||
void SendScriptMsg(TUniqueId dest, TUniqueId src, EScriptObjectMessage msg);
|
||||
|
@ -285,9 +285,10 @@ public:
|
|||
std::multimap<TEditorId, TUniqueId>::const_iterator>
|
||||
GetIdListForScript(TEditorId) const;
|
||||
void LoadScriptObjects(TAreaId, CInputStream& in, std::vector<TEditorId>& idsOut);
|
||||
void InitializeScriptObjects(const std::vector<TEditorId>& objIds);
|
||||
std::pair<TEditorId, TUniqueId> LoadScriptObject(TAreaId, EScriptObjectType, u32, CInputStream& in);
|
||||
std::pair<TEditorId, TUniqueId> GenerateObject(TEditorId);
|
||||
void InitScriptObjects(std::vector<TEditorId>& ids);
|
||||
void InitScriptObjects(const std::vector<TEditorId>& ids);
|
||||
void InformListeners(const zeus::CVector3f&, EListenNoiseType);
|
||||
bool ApplyKnockBack(CActor& actor, const CDamageInfo& info,
|
||||
const CDamageVulnerability&, const zeus::CVector3f&, float);
|
||||
|
|
|
@ -386,13 +386,13 @@ void CBooRenderer::DrawUnsortedGeometry(int areaIdx, int mask, int targetMask)
|
|||
if (xe0_pvsModelCount != item.x10_models.size())
|
||||
pvs = nullptr;
|
||||
|
||||
int idx = 0;
|
||||
u32 idx = 0;
|
||||
for (auto it = item.x10_models.begin() ; it != item.x10_models.end() ; ++it, ++idx)
|
||||
{
|
||||
CBooModel* model = *it;
|
||||
if (pvs)
|
||||
{
|
||||
bool vis = pvs->GetVisible(idx);
|
||||
bool vis = pvs->GetVisible(idx) != EPVSVisSetState::EndOfTree;
|
||||
switch (xc4_pvsMode)
|
||||
{
|
||||
case EPVSMode::PVS:
|
||||
|
|
|
@ -41,7 +41,6 @@ set(GRAPHICS_SOURCES
|
|||
CGraphicsPalette.hpp CGraphicsPalette.cpp
|
||||
CPVSVisSet.hpp CPVSVisSet.cpp
|
||||
CPVSVisOctree.hpp CPVSVisOctree.cpp
|
||||
CPVSBounds.hpp CPVSBounds.cpp
|
||||
CPVSAreaSet.hpp CPVSAreaSet.cpp
|
||||
CGraphics.hpp CGraphics.cpp
|
||||
CSimpleShadow.hpp CSimpleShadow.cpp
|
||||
|
|
|
@ -3,12 +3,19 @@
|
|||
namespace urde
|
||||
{
|
||||
|
||||
CPVSAreaSet::CPVSAreaHolder::CPVSAreaHolder(CInputStream& in)
|
||||
{
|
||||
}
|
||||
|
||||
CPVSAreaSet::CPVSAreaSet(CInputStream& in)
|
||||
CPVSAreaSet::CPVSAreaSet(const u8* data, u32 len)
|
||||
{
|
||||
CMemoryInStream r(data, len);
|
||||
x0_numFeatures = r.readUint32Big();
|
||||
x4_numLights = r.readUint32Big();
|
||||
x8_c = r.readUint32Big();
|
||||
xc_numActors = r.readUint32Big();
|
||||
x10_leafSize = r.readUint32Big();
|
||||
x14_lightIndexCount = r.readUint32Big();
|
||||
x18_entityIndex = data + r.position();
|
||||
x1c_lightLeaves = x18_entityIndex + xc_numActors * 4;
|
||||
const u8* octreeData = x1c_lightLeaves + x14_lightIndexCount * x10_leafSize;
|
||||
x20_octree = CPVSVisOctree::MakePVSVisOctree(octreeData);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,21 +2,29 @@
|
|||
#define __URDE_CPVSAREASET_HPP__
|
||||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "CPVSVisOctree.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
class CPVSAreaSet
|
||||
{
|
||||
u32 x0_numFeatures;
|
||||
u32 x4_numLights;
|
||||
u32 x8_c;
|
||||
u32 xc_numActors;
|
||||
u32 x10_leafSize;
|
||||
u32 x14_lightIndexCount;
|
||||
const u8* x18_entityIndex;
|
||||
const u8* x1c_lightLeaves;
|
||||
CPVSVisOctree x20_octree;
|
||||
|
||||
public:
|
||||
struct CPVSAreaHolder
|
||||
{
|
||||
CPVSAreaHolder(CInputStream& in);
|
||||
};
|
||||
private:
|
||||
std::vector<CPVSAreaHolder> xunk;
|
||||
public:
|
||||
CPVSAreaSet(CInputStream& in);
|
||||
CPVSAreaSet(const u8* data, u32 len);
|
||||
u32 GetNumFeatures() const { return x0_numFeatures; }
|
||||
u32 GetNumActors() const { return xc_numActors; }
|
||||
u32 GetEntityIdByIndex(int idx) const { return x18_entityIndex[idx]; }
|
||||
const CPVSVisOctree& GetVisOctree() { return x20_octree; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
#include "CPVSBounds.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
CPVSBounds::CPVSBounds(CInputStream& in)
|
||||
{
|
||||
}
|
||||
|
||||
u32 CPVSBounds::GetBoundsFileSize()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CPVSBounds::PointInBounds(const zeus::CVector3f&) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef __URDE_CPVSBOUNDS_HPP__
|
||||
#define __URDE_CPVSBOUNDS_HPP__
|
||||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "zeus/CVector3f.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
class CPVSBounds
|
||||
{
|
||||
public:
|
||||
CPVSBounds(CInputStream& in);
|
||||
u32 GetBoundsFileSize();
|
||||
bool PointInBounds(const zeus::CVector3f&) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // __URDE_CPVSBOUNDS_HPP__
|
|
@ -3,23 +3,111 @@
|
|||
namespace urde
|
||||
{
|
||||
|
||||
CPVSVisOctree::CPVSVisOctree(CInputStream& in)
|
||||
CPVSVisOctree CPVSVisOctree::MakePVSVisOctree(const u8* data)
|
||||
{
|
||||
CMemoryInStream r(data, 68);
|
||||
zeus::CAABox aabb = aabb.ReadBoundingBoxBig(r);
|
||||
u32 a = r.readUint32Big();
|
||||
u32 b = r.readUint32Big();
|
||||
r.readUint32Big();
|
||||
return CPVSVisOctree(aabb, a, b, data + r.position());
|
||||
}
|
||||
|
||||
u32 CPVSVisOctree::GetNumChildren(const unsigned char*) const
|
||||
CPVSVisOctree::CPVSVisOctree(const zeus::CAABox& aabb, u32 a, u32 b, const u8* c)
|
||||
: x0_aabb(aabb), x18_totalBits(a), x1c_lightBits(b), x20_bufferFlag(c != nullptr), x24_octreeData(c)
|
||||
{
|
||||
x2c_searchAabb = x0_aabb;
|
||||
x20_bufferFlag = 0;
|
||||
}
|
||||
|
||||
static const u32 NumChildTable[] =
|
||||
{
|
||||
0, 2, 2, 4, 2, 4, 4, 8
|
||||
};
|
||||
|
||||
u32 CPVSVisOctree::GetNumChildren(u8 byte) const
|
||||
{
|
||||
return NumChildTable[byte & 0x7];
|
||||
}
|
||||
|
||||
u32 CPVSVisOctree::GetChildIndex(const u8*, const zeus::CVector3f&) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 CPVSVisOctree::GetChildIndex(const unsigned char*, const zeus::CVector3f&) const
|
||||
s32 CPVSVisOctree::IterateSearch(u8 nodeData, const zeus::CVector3f& tp) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!(nodeData & 0x7))
|
||||
return -1; // Leaf node
|
||||
|
||||
u32 CPVSVisOctree::SetTestPoint(const zeus::CVector3f&) const
|
||||
{
|
||||
return 0;
|
||||
zeus::CVector3f newMin = x2c_searchAabb.center();
|
||||
zeus::CVector3f newMax;
|
||||
bool highFlags[3];
|
||||
|
||||
if (tp.x > newMin.x)
|
||||
{
|
||||
newMax.x = x2c_searchAabb.max.x;
|
||||
highFlags[0] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newMax.x = newMin.x;
|
||||
newMin.x = x2c_searchAabb.min.x;
|
||||
highFlags[0] = false;
|
||||
}
|
||||
|
||||
if (tp.y > newMin.y)
|
||||
{
|
||||
newMax.y = x2c_searchAabb.max.y;
|
||||
highFlags[1] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newMax.y = newMin.y;
|
||||
newMin.y = x2c_searchAabb.min.y;
|
||||
highFlags[1] = false;
|
||||
}
|
||||
|
||||
if (tp.z > newMin.z)
|
||||
{
|
||||
newMax.z = x2c_searchAabb.max.z;
|
||||
highFlags[2] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
newMax.z = newMin.z;
|
||||
newMin.z = x2c_searchAabb.min.z;
|
||||
highFlags[2] = false;
|
||||
}
|
||||
|
||||
u8 axisCounts[2] = {1, 1};
|
||||
if (nodeData & 0x1)
|
||||
axisCounts[0] = 2;
|
||||
if (nodeData & 0x2)
|
||||
axisCounts[1] = 2;
|
||||
|
||||
zeus::CAABox& newSearch = const_cast<zeus::CAABox&>(x2c_searchAabb);
|
||||
if (nodeData & 0x1)
|
||||
{
|
||||
newSearch.min.x = newMin.x;
|
||||
newSearch.max.x = newMax.x;
|
||||
}
|
||||
if (nodeData & 0x2)
|
||||
{
|
||||
newSearch.min.y = newMin.y;
|
||||
newSearch.max.y = newMax.y;
|
||||
}
|
||||
if (nodeData & 0x4)
|
||||
{
|
||||
newSearch.min.z = newMin.z;
|
||||
newSearch.max.z = newMax.z;
|
||||
}
|
||||
|
||||
// Branch node - calculate next relative pointer
|
||||
return
|
||||
highFlags[0] * bool(nodeData & 0x1) +
|
||||
highFlags[1] * axisCounts[0] * bool(nodeData & 0x2) +
|
||||
highFlags[2] * axisCounts[0] * axisCounts[1] * bool(nodeData & 0x4);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,17 +3,32 @@
|
|||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "zeus/CVector3f.hpp"
|
||||
#include "CPVSVisSet.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
class CPVSVisOctree
|
||||
{
|
||||
zeus::CAABox x0_aabb;
|
||||
u32 x18_totalBits;
|
||||
u32 x1c_lightBits;
|
||||
bool x20_bufferFlag;
|
||||
const u8* x24_octreeData;
|
||||
zeus::CAABox x2c_searchAabb;
|
||||
public:
|
||||
CPVSVisOctree(CInputStream& in);
|
||||
u32 GetNumChildren(const unsigned char*) const;
|
||||
u32 GetChildIndex(const unsigned char*, const zeus::CVector3f&) const;
|
||||
u32 SetTestPoint(const zeus::CVector3f&) const;
|
||||
static CPVSVisOctree MakePVSVisOctree(const u8* data);
|
||||
CPVSVisOctree() = default;
|
||||
CPVSVisOctree(const zeus::CAABox& aabb, u32 a, u32 b, const u8* c);
|
||||
u32 GetNumChildren(u8 byte) const;
|
||||
u32 GetChildIndex(const u8*, const zeus::CVector3f&) const;
|
||||
const zeus::CAABox& GetBounds() const { return x0_aabb; }
|
||||
const u8* GetOctreeData() const { return x24_octreeData; }
|
||||
|
||||
u32 GetTotalBits() const { return x18_totalBits; }
|
||||
u32 GetLightBits() const { return x1c_lightBits; }
|
||||
void ResetSearch() const { const_cast<CPVSVisOctree&>(*this).x2c_searchAabb = x0_aabb; }
|
||||
s32 IterateSearch(u8 nodeData, const zeus::CVector3f& tp) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,23 +1,110 @@
|
|||
#include "CPVSVisSet.hpp"
|
||||
#include "CPVSVisOctree.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
void CPVSVisSet::Reset(bool)
|
||||
void CPVSVisSet::Reset(EPVSVisSetState state)
|
||||
{
|
||||
x0_state = state;
|
||||
x4_numBits = 0;
|
||||
x8_numLights = 0;
|
||||
//xc_ = false;
|
||||
x10_ptr = nullptr;
|
||||
}
|
||||
|
||||
bool CPVSVisSet::GetVisible(int)
|
||||
EPVSVisSetState CPVSVisSet::GetVisible(u32 idx) const
|
||||
{
|
||||
return false;
|
||||
if (x0_state != EPVSVisSetState::NodeFound)
|
||||
return x0_state;
|
||||
|
||||
u32 numFeatures = x4_numBits - x8_numLights;
|
||||
if (idx < numFeatures)
|
||||
{
|
||||
/* This is a feature lookup */
|
||||
if (!x10_ptr[idx / 8] & (1 << (idx & 0x7)))
|
||||
return EPVSVisSetState::EndOfTree;
|
||||
return EPVSVisSetState::OutOfBounds;
|
||||
}
|
||||
|
||||
/* This is a light lookup */
|
||||
u32 lightTest = idx - numFeatures + x4_numBits;
|
||||
const u8* ptr = &x10_ptr[lightTest / 8];
|
||||
lightTest &= 0x7;
|
||||
if (lightTest != 0x7)
|
||||
return EPVSVisSetState((ptr[0] & (0x3 << lightTest)) >> lightTest);
|
||||
return EPVSVisSetState((ptr[0] >> 7) | ((ptr[1] & 0x1) << 1));
|
||||
}
|
||||
|
||||
void CPVSVisSet::SetVisible(int,bool)
|
||||
void CPVSVisSet::SetFromMemory(u32 numBits, u32 numLights, const u8* leafPtr)
|
||||
{
|
||||
x0_state = EPVSVisSetState::NodeFound;
|
||||
x4_numBits = numBits;
|
||||
x8_numLights = numLights;
|
||||
x10_ptr = leafPtr;
|
||||
}
|
||||
|
||||
void CPVSVisSet::SetFromMemory(const unsigned char*)
|
||||
void CPVSVisSet::SetTestPoint(const CPVSVisOctree& octree, const zeus::CVector3f& point)
|
||||
{
|
||||
if (!octree.GetBounds().pointInside(point))
|
||||
{
|
||||
Reset(EPVSVisSetState::OutOfBounds);
|
||||
return;
|
||||
}
|
||||
|
||||
const u8* octCur = octree.GetOctreeData();
|
||||
octree.ResetSearch();
|
||||
s32 nextNodeRel;
|
||||
u8 curNode;
|
||||
while ((nextNodeRel = octree.IterateSearch((curNode = *octCur++), point)) != -1)
|
||||
{
|
||||
if (nextNodeRel)
|
||||
{
|
||||
/* Skip node data */
|
||||
if (!(curNode & 0x60))
|
||||
{
|
||||
octCur += hecl::SBig(reinterpret_cast<const u16*>(octCur)[nextNodeRel - 1]);
|
||||
}
|
||||
else if (curNode & 0x20)
|
||||
{
|
||||
octCur += *(octCur + nextNodeRel - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
const u8* tmp = octCur + (nextNodeRel - 1) * 3;
|
||||
octCur += (tmp[0] << 16) + (tmp[1] << 8) + tmp[2];
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip children data */
|
||||
if (!(curNode & 0x60))
|
||||
{
|
||||
octCur += (octree.GetNumChildren(curNode) - 1) * 2;
|
||||
}
|
||||
else if (curNode & 0x20)
|
||||
{
|
||||
octCur += octree.GetNumChildren(curNode) - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
octCur += (octree.GetNumChildren(curNode) - 1) * 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle leaf type */
|
||||
switch (curNode & 0x18)
|
||||
{
|
||||
case 0x18:
|
||||
SetFromMemory(octree.GetTotalBits(), octree.GetLightBits(), octCur);
|
||||
break;
|
||||
case 0x10:
|
||||
Reset(EPVSVisSetState::EndOfTree);
|
||||
break;
|
||||
case 0x08:
|
||||
default:
|
||||
Reset(EPVSVisSetState::OutOfBounds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,24 +2,33 @@
|
|||
#define __URDE_CPVSVISSET_HPP__
|
||||
|
||||
#include "RetroTypes.hpp"
|
||||
#include "zeus/CAABox.hpp"
|
||||
#include <memory>
|
||||
|
||||
namespace urde
|
||||
{
|
||||
class CPVSVisOctree;
|
||||
|
||||
enum class EPVSVisSetState
|
||||
{
|
||||
EndOfTree,
|
||||
NodeFound,
|
||||
OutOfBounds
|
||||
};
|
||||
|
||||
class CPVSVisSet
|
||||
{
|
||||
int x0_bitCount;
|
||||
int x4_setCount = 0;
|
||||
std::vector<unsigned char> x8_bitset;
|
||||
EPVSVisSetState x0_state;
|
||||
u32 x4_numBits;
|
||||
u32 x8_numLights;
|
||||
//bool xc_; Used to be part of auto_ptr
|
||||
const u8* x10_ptr;
|
||||
public:
|
||||
CPVSVisSet(int count) : x0_bitCount(count) {}
|
||||
CPVSVisSet(int a, std::vector<unsigned char>&& bitset)
|
||||
: x0_bitCount(1), x4_setCount(a), x8_bitset(std::move(bitset)) {}
|
||||
void Reset(bool);
|
||||
bool GetVisible(int);
|
||||
void SetVisible(int,bool);
|
||||
void SetFromMemory(const unsigned char*);
|
||||
void Reset(EPVSVisSetState state);
|
||||
EPVSVisSetState GetState() const { return x0_state; }
|
||||
EPVSVisSetState GetVisible(u32 idx) const;
|
||||
void SetFromMemory(u32 numBits, u32 numLights, const u8* leafPtr);
|
||||
void SetTestPoint(const CPVSVisOctree& octree, const zeus::CVector3f&);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2008,7 +2008,7 @@ CFrontEndUI::CFrontEndUI()
|
|||
m_touchBar = NewFrontEndUITouchBar();
|
||||
m_touchBar->SetPhase(CFrontEndUITouchBar::EPhase::None);
|
||||
|
||||
//x14_phase = EPhase::ExitFrontEnd;
|
||||
x14_phase = EPhase::ExitFrontEnd;
|
||||
}
|
||||
|
||||
void CFrontEndUI::StartSlideShow(CArchitectureQueue& queue)
|
||||
|
|
|
@ -65,7 +65,7 @@ void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMana
|
|||
#endif
|
||||
}
|
||||
break;
|
||||
case EScriptObjectMessage::InternalMessage13: // 35
|
||||
case EScriptObjectMessage::Constructed: // 35
|
||||
{
|
||||
for (const SConnection& conn : x20_conns)
|
||||
{
|
||||
|
|
|
@ -709,9 +709,76 @@ void CGameArea::StartStreamIn(CStateManager& mgr)
|
|||
{
|
||||
}
|
||||
|
||||
bool CGameArea::Validate(CStateManager& mgr)
|
||||
void CGameArea::Validate(CStateManager& mgr)
|
||||
{
|
||||
return false;
|
||||
if (xf0_24_postConstructed)
|
||||
return;
|
||||
|
||||
while (StartStreamingMainArea()) {}
|
||||
|
||||
for (auto& req : xf8_loadTransactions)
|
||||
req->WaitForComplete();
|
||||
|
||||
if (xdc_tokens.empty())
|
||||
{
|
||||
VerifyTokenList(mgr);
|
||||
for (CToken& tok : xdc_tokens)
|
||||
tok.Lock();
|
||||
for (CToken& tok : xdc_tokens)
|
||||
tok.GetObj();
|
||||
xf0_26_tokensReady = true;
|
||||
}
|
||||
|
||||
xf8_loadTransactions.clear();
|
||||
|
||||
PostConstructArea();
|
||||
if (x4_selfIdx != kInvalidAreaId)
|
||||
mgr.WorldNC()->MoveAreaToChain3(x4_selfIdx);
|
||||
|
||||
LoadScriptObjects(mgr);
|
||||
|
||||
CPVSAreaSet* pvs = x12c_postConstructed->xa0_pvs.get();
|
||||
if (pvs && x12c_postConstructed->x1108_29_)
|
||||
{
|
||||
for (int i=0 ; i<pvs->GetNumActors() ; ++i)
|
||||
{
|
||||
TEditorId entId = pvs->GetEntityIdByIndex(i) | (x4_selfIdx << 16);
|
||||
TUniqueId id = mgr.GetIdForScript(entId);
|
||||
if (id != kInvalidUniqueId)
|
||||
{
|
||||
CPostConstructed::MapEntry& ent = x12c_postConstructed->xa8_pvsEntityMap[id & 0x3ff];
|
||||
ent.x0_id = i + (pvs->GetNumFeatures() - pvs->GetNumActors());
|
||||
ent.x4_uid = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xf0_28_validated = true;
|
||||
mgr.AreaLoaded(x4_selfIdx);
|
||||
}
|
||||
|
||||
void CGameArea::LoadScriptObjects(CStateManager& mgr)
|
||||
{
|
||||
CWorldLayerState& layerState = *mgr.LayerState();
|
||||
u32 layerCount = layerState.GetAreaLayerCount(x4_selfIdx);
|
||||
std::vector<TEditorId> objIds;
|
||||
for (u32 i=0 ; i<layerCount ; ++i)
|
||||
{
|
||||
if (layerState.IsLayerActive(x4_selfIdx, i))
|
||||
{
|
||||
auto layerBuf = GetLayerScriptBuffer(i);
|
||||
CMemoryInStream r(layerBuf.first, layerBuf.second);
|
||||
mgr.LoadScriptObjects(x4_selfIdx, r, objIds);
|
||||
}
|
||||
}
|
||||
mgr.InitScriptObjects(objIds);
|
||||
}
|
||||
|
||||
std::pair<u8*, u32> CGameArea::GetLayerScriptBuffer(int layer)
|
||||
{
|
||||
if (!xf0_24_postConstructed)
|
||||
return {};
|
||||
return x12c_postConstructed->x110c_layerPtrs[layer];
|
||||
}
|
||||
|
||||
void CGameArea::PostConstructArea()
|
||||
|
@ -797,7 +864,8 @@ void CGameArea::PostConstructArea()
|
|||
{
|
||||
x12c_postConstructed->x1108_29_ = r.readBool();
|
||||
x12c_postConstructed->x1108_30_ = r.readBool();
|
||||
x12c_postConstructed->xa0_pvs.reset(new CPVSAreaSet::CPVSAreaHolder(r));
|
||||
x12c_postConstructed->xa0_pvs = std::make_unique<CPVSAreaSet>(secIt->first.get() + r.position(),
|
||||
secIt->second - r.position());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -848,7 +916,7 @@ void CGameArea::FillInStaticGeometry()
|
|||
|
||||
void CGameArea::VerifyTokenList(CStateManager& stateMgr)
|
||||
{
|
||||
if (xdc_tokens.empty())
|
||||
if (xdc_tokens.size())
|
||||
return;
|
||||
ClearTokenList();
|
||||
|
||||
|
@ -881,7 +949,7 @@ void CGameArea::ClearTokenList()
|
|||
else
|
||||
xdc_tokens.clear();
|
||||
|
||||
xf0_26_tokensReady = 0;
|
||||
xf0_26_tokensReady = false;
|
||||
}
|
||||
|
||||
u32 CGameArea::GetPreConstructedSize() const
|
||||
|
|
|
@ -105,7 +105,7 @@ class CGameArea : public IGameArea
|
|||
bool xf0_25_active : 1;
|
||||
bool xf0_26_tokensReady : 1;
|
||||
bool xf0_27_paused : 1;
|
||||
bool xf0_28_ : 1;
|
||||
bool xf0_28_validated : 1;
|
||||
};
|
||||
u8 _dummy = 0;
|
||||
};
|
||||
|
@ -174,13 +174,13 @@ public:
|
|||
std::vector<CLight> x70_gfxLightsA;
|
||||
std::vector<CWorldLight> x80_lightsB;
|
||||
std::vector<CLight> x90_gfxLightsB;
|
||||
std::unique_ptr<CPVSAreaSet::CPVSAreaHolder> xa0_pvs;
|
||||
std::unique_ptr<CPVSAreaSet> xa0_pvs;
|
||||
u32 xa4_elemCount = 1024;
|
||||
struct MapEntry
|
||||
{
|
||||
s16 x0_id = -1;
|
||||
TUniqueId x4_uid = kInvalidUniqueId;
|
||||
} xa8_map[1024];
|
||||
} xa8_pvsEntityMap[1024];
|
||||
u32 x10a8_pvsVersion = 0;
|
||||
TLockedToken<CPFArea> x10ac_path;
|
||||
// bool x10b8_ = 0; optional flag for CToken
|
||||
|
@ -301,7 +301,9 @@ public:
|
|||
bool Invalidate(CStateManager& mgr);
|
||||
void CullDeadAreaRequests();
|
||||
void StartStreamIn(CStateManager& mgr);
|
||||
bool Validate(CStateManager& mgr);
|
||||
void Validate(CStateManager& mgr);
|
||||
void LoadScriptObjects(CStateManager& mgr);
|
||||
std::pair<u8*, u32> GetLayerScriptBuffer(int layer);
|
||||
void PostConstructArea();
|
||||
void FillInStaticGeometry();
|
||||
void VerifyTokenList(CStateManager& stateMgr);
|
||||
|
@ -313,7 +315,7 @@ public:
|
|||
const zeus::CTransform& GetInverseTransform() const {return x3c_invTransform;}
|
||||
const zeus::CAABox& GetAABB() const {return x6c_aabb;}
|
||||
|
||||
const std::vector<Dock> GetDocks() const {return xcc_docks;}
|
||||
const std::vector<Dock>& GetDocks() const {return xcc_docks;}
|
||||
const Dock* GetDock(s32 dock) const { return &xcc_docks[dock]; }
|
||||
s32 GetDockCount() const { return xcc_docks.size(); }
|
||||
Dock* DockNC(s32 dock) { return &xcc_docks[dock]; }
|
||||
|
|
|
@ -57,7 +57,7 @@ void CScriptActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
|
|||
{
|
||||
CScriptColorModulate::FadeOutHelper(mgr, x8_uid, x2d4_alphaMin);
|
||||
}
|
||||
else if (msg == EScriptObjectMessage::InternalMessage13)
|
||||
else if (msg == EScriptObjectMessage::Constructed)
|
||||
{
|
||||
for (const SConnection& conn : x20_conns)
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@ void CScriptAiJumpPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId oth
|
|||
{
|
||||
AcceptScriptMsg(msg, other, mgr);
|
||||
|
||||
if (msg != EScriptObjectMessage::InternalMessage13)
|
||||
if (msg != EScriptObjectMessage::Constructed)
|
||||
return;
|
||||
|
||||
for (SConnection& conn : x20_conns)
|
||||
|
|
|
@ -33,7 +33,7 @@ void CScriptAreaAttributes::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
|
|||
if (x4_areaId == kInvalidAreaId)
|
||||
return;
|
||||
|
||||
if (msg == EScriptObjectMessage::InternalMessage13)
|
||||
if (msg == EScriptObjectMessage::Constructed)
|
||||
{
|
||||
CGameArea* area = stateMgr.WorldNC()->GetArea(x4_areaId);
|
||||
area->SetAreaAttributes(this);
|
||||
|
|
|
@ -41,7 +41,7 @@ void CScriptDistanceFog::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId obj
|
|||
if (x4_areaId == kInvalidAreaId || !GetActive())
|
||||
return;
|
||||
|
||||
if (msg == EScriptObjectMessage::InternalMessage13)
|
||||
if (msg == EScriptObjectMessage::Constructed)
|
||||
{
|
||||
if (!x60_explicit)
|
||||
return;
|
||||
|
|
|
@ -103,7 +103,7 @@ void CScriptDock::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat
|
|||
case EScriptObjectMessage::Deleted:
|
||||
CleanUp();
|
||||
break;
|
||||
case EScriptObjectMessage::InternalMessage13:
|
||||
case EScriptObjectMessage::Constructed:
|
||||
AreaLoaded(mgr);
|
||||
break;
|
||||
case EScriptObjectMessage::InternalMessage14:
|
||||
|
|
|
@ -64,7 +64,7 @@ void CScriptShadowProjector::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId
|
|||
|
||||
x110_25_shadowInvalidated = true;
|
||||
}
|
||||
else if (msg == EScriptObjectMessage::InternalMessage13)
|
||||
else if (msg == EScriptObjectMessage::Constructed)
|
||||
{
|
||||
for (const SConnection& conn : x20_conns)
|
||||
{
|
||||
|
|
|
@ -235,6 +235,11 @@ void CWorld::MoveToChain(CGameArea* area, EChain chain)
|
|||
x4c_chainHeads[int(chain)] = area;
|
||||
}
|
||||
|
||||
void CWorld::MoveAreaToChain3(TAreaId aid)
|
||||
{
|
||||
MoveToChain(x18_areas[aid].get(), EChain::Three);
|
||||
}
|
||||
|
||||
void CWorld::LoadSoundGroup(int groupId, ResId agscId, CSoundGroupData& data) {}
|
||||
|
||||
void CWorld::LoadSoundGroups() {}
|
||||
|
|
|
@ -152,6 +152,7 @@ private:
|
|||
public:
|
||||
|
||||
void MoveToChain(CGameArea* area, EChain chain);
|
||||
void MoveAreaToChain3(TAreaId aid);
|
||||
bool CheckWorldComplete(CStateManager* mgr, TAreaId id, ResId mreaId);
|
||||
bool ScheduleAreaToLoad(CGameArea* area, CStateManager& mgr);
|
||||
void TravelToArea(TAreaId aid, CStateManager& mgr, bool);
|
||||
|
|
|
@ -212,7 +212,7 @@ enum class EScriptObjectMessage
|
|||
InternalMessage10 = 32,
|
||||
InternalMessage11 = 33,
|
||||
Deleted = 34,
|
||||
InternalMessage13 = 35,
|
||||
Constructed = 35,
|
||||
InternalMessage14 = 36,
|
||||
InternalMessage15 = 37,
|
||||
InternalMessage16 = 38,
|
||||
|
|
Loading…
Reference in New Issue