PVS implementations

This commit is contained in:
Jack Andersen 2017-02-18 23:27:01 -10:00
parent 56328c3e4d
commit 50fe6d34ab
31 changed files with 498 additions and 175 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();}

View File

@ -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);

View File

@ -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; }

View File

@ -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();
}
}

View File

@ -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();
}

View File

@ -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);

View File

@ -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:

View File

@ -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

View File

@ -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);
}
}

View File

@ -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; }
};
}

View File

@ -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;
}
}

View File

@ -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__

View File

@ -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);
}
}

View File

@ -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;
};
}

View File

@ -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;
}
}
}

View File

@ -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&);
};
}

View File

@ -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)

View File

@ -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)
{

View File

@ -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

View File

@ -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]; }

View File

@ -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)
{

View File

@ -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)

View File

@ -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);

View File

@ -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;

View File

@ -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:

View File

@ -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)
{

View File

@ -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() {}

View File

@ -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);

View File

@ -212,7 +212,7 @@ enum class EScriptObjectMessage
InternalMessage10 = 32,
InternalMessage11 = 33,
Deleted = 34,
InternalMessage13 = 35,
Constructed = 35,
InternalMessage14 = 36,
InternalMessage15 = 37,
InternalMessage16 = 38,