Lots of bug fixes (Windows still needs some fixes)

This commit is contained in:
Jack Andersen 2017-10-21 20:11:22 -10:00
parent 5e88b99769
commit 15d60493f2
53 changed files with 620 additions and 313 deletions

View File

@ -1664,9 +1664,10 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::P
struct MaterialPool
{
std::vector<const Mesh::Material*> materials;
size_t addMaterial(const Mesh::Material& mat)
size_t addMaterial(const Mesh::Material& mat, bool& newMat)
{
size_t ret = 0;
newMat = false;
for (const Mesh::Material* testMat : materials)
{
if (mat == *testMat)
@ -1674,6 +1675,7 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::P
++ret;
}
materials.push_back(&mat);
newMat = true;
return ret;
}
} matPool;
@ -1696,9 +1698,10 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::P
for (const Mesh::Material& mat : mesh.materialSets[0])
{
size_t idx = matPool.addMaterial(mat);
bool newMat;
size_t idx = matPool.addMaterial(mat, newMat);
meshToGlobalMats.push_back(idx);
if (idx < matPool.materials.size() - 1)
if (!newMat)
continue;
for (const hecl::ProjectPath& path : mat.texs)
@ -1736,6 +1739,7 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::P
/* Iterate meshes */
auto matIt = surfToGlobalMats.cbegin();
int meshIdx = 0;
for (const Mesh& mesh : meshes)
{
zeus::CTransform meshXf(mesh.sceneXf.val);

View File

@ -322,7 +322,7 @@ bool WriteCRSM(const CRSM<IDType>& crsm, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteCRSM<UniqueID32>(const CRSM<UniqueID32>& crsm, const hecl::ProjectPath& outPath);

View File

@ -133,7 +133,7 @@ bool WriteDGRP(const DGRP<IDType>& dgrp, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteDGRP<UniqueID32>(const DGRP<UniqueID32>& dgrp, const hecl::ProjectPath& outPath);

View File

@ -82,7 +82,7 @@ public:
}
}
size_t binarySize(size_t __isz) const
{return __isz + 4;}
{return __isz + 16;}
};
using FourCC = hecl::FourCC;

View File

@ -404,7 +404,7 @@ bool WriteDPSM(const DPSM<IDType>& dpsm, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteDPSM<UniqueID32>(const DPSM<UniqueID32>& dpsm, const hecl::ProjectPath& outPath);

View File

@ -421,7 +421,7 @@ bool WriteELSM(const ELSM<IDType>& elsm, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteELSM<UniqueID32>(const ELSM<UniqueID32>& gpsm, const hecl::ProjectPath& outPath);

View File

@ -565,7 +565,7 @@ bool WriteFONT(const FONT<IDType>& font, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteFONT<UniqueID32>(const FONT<UniqueID32>& font, const hecl::ProjectPath& outPath);

View File

@ -1007,7 +1007,7 @@ bool WriteFSM2(const FSM2<IDType>& fsm2, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteFSM2<UniqueID32>(const FSM2<UniqueID32>& fsm2, const hecl::ProjectPath& outPath);

View File

@ -144,14 +144,10 @@ static void MakeLeaf(const ColMesh& mesh, const std::vector<int>& index, Node& n
n.right.reset();
n.isLeaf = true;
n.leafData = std::make_unique<typename Node::LeafData>();
n.leafData->edgeIndexCount = atUint32(index.size() * 3);
n.leafData->edgeIndices.reserve(n.leafData->edgeIndexCount);
n.leafData->triangleIndexCount = atUint32(index.size());
n.leafData->triangleIndices.reserve(n.leafData->triangleIndexCount);
for (int i : index)
{
const ColMesh::Triangle& T = mesh.trianges[i];
for (int j = 0; j < 3; ++j)
n.leafData->edgeIndices.push_back(T.edges[j]);
}
n.leafData->triangleIndices.push_back(i);
}
template <typename Node>

View File

@ -1390,7 +1390,7 @@ bool WriteGPSM(const GPSM<IDType>& gpsm, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteGPSM<UniqueID32>(const GPSM<UniqueID32>& gpsm, const hecl::ProjectPath& outPath);

View File

@ -523,7 +523,7 @@ bool WriteSWSH(const SWSH<IDType>& swsh, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteSWSH<UniqueID32>(const SWSH<UniqueID32>& swsh, const hecl::ProjectPath& outPath);

View File

@ -16,7 +16,7 @@ bool WriteTweak(const T& tweak, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}

View File

@ -660,7 +660,7 @@ bool WriteWPSM(const WPSM<IDType>& wpsm, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}
template bool WriteWPSM<UniqueID32>(const WPSM<UniqueID32>& wpsm, const hecl::ProjectPath& outPath);

View File

@ -135,7 +135,9 @@ CINF::CINF(const Armature& armature, std::unordered_map<std::string, atInt32>& i
if (bone->children.size())
{
int curId = 4;
RecursiveAddArmatureBone(armature, armature.getChild(bone, 0), 3, curId, idMap, nameMap);
const Armature::Bone* child;
for (size_t i=0 ; (child = armature.getChild(bone, i)) ; ++i)
RecursiveAddArmatureBone(armature, child, 3, curId, idMap, nameMap);
}
bones.emplace_back();

View File

@ -53,9 +53,9 @@ struct DCLN : BigDNA
struct LeafData : BigDNA
{
DECL_DNA
Value<atUint32> edgeIndexCount;
Vector<atUint16, DNA_COUNT(edgeIndexCount)> edgeIndices;
size_t getMemoryUsage() const { return (((edgeIndices.size() * 2) + 16) + 3) & ~3; }
Value<atUint32> triangleIndexCount;
Vector<atUint16, DNA_COUNT(triangleIndexCount)> triangleIndices;
size_t getMemoryUsage() const { return (((triangleIndices.size() * 2) + 16) + 3) & ~3; }
};
Value<atVec4f> xf[3];
@ -234,6 +234,10 @@ struct DCLN : BigDNA
athena::io::FileWriter w(outPath.getAbsolutePath());
dcln.write(w);
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeUByte(0xff);
return true;
}
};

View File

@ -1,3 +1,5 @@
#include <hecl/ClientProcess.hpp>
#include <athena/MemoryReader.hpp>
#include "MREA.hpp"
#include "SCLY.hpp"
#include "PATH.hpp"
@ -167,8 +169,17 @@ bool MREA::Extract(const SpecBase& dataSpec,
rs.seek(secStart + head.secSizes[curSec++], athena::Begin);
/* Dump VISI entities */
secStart = rs.position();
if (head.secSizes[curSec] && rs.readUint32Big() == 'VISI')
{
{
rs.seek(secStart, athena::Begin);
auto visiData = rs.readUBytes(head.secSizes[curSec]);
athena::io::FileWriter visiOut(outPath.getWithExtension(_S(".visi"), true).getAbsolutePath());
visiOut.writeUBytes(visiData.get(), head.secSizes[curSec]);
rs.seek(secStart + 4, athena::Begin);
}
athena::io::YAMLDocWriter visiWriter("VISI");
if (auto __vec = visiWriter.enterSubVector("entities"))
{
@ -447,6 +458,8 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
if (auto __vec = r.enterSubVector("entities", entityCount))
{
entities.reserve(entityCount);
for (size_t i=0 ; i<entityCount ; ++i)
{
uint16_t entityId = r.readUint16(nullptr);
for (const SCLY::ScriptLayer& layer : sclyData.layers)
{
@ -455,15 +468,51 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
if ((obj->id & 0xffff) == entityId)
{
zeus::CAABox entAABB = obj->getVISIAABB(btok);
if (entAABB.min.x < entAABB.max.x)
if (!entAABB.invalid())
entities.emplace_back(entityId, entAABB);
}
}
}
}
}
// Check if pre-generated visi exists, recycle if able
hecl::ProjectPath preVisiPath = inPath.getWithExtension(_S(".visi"), true);
if (preVisiPath.getPathType() == hecl::ProjectPath::Type::File)
{
athena::io::FileReader preVisiReader(preVisiPath.getAbsolutePath());
atUint64 preVisiLen = preVisiReader.length();
if (preVisiLen > 26)
{
auto preVisiData = preVisiReader.readUBytes(preVisiLen);
athena::io::MemoryReader preVisiDataReader(preVisiData.get(), preVisiLen);
atUint32 preVisiFourCC = preVisiDataReader.readUint32Big();
atUint32 preVisiVersion = preVisiDataReader.readUint32Big();
preVisiDataReader.readBool();
preVisiDataReader.readBool();
atUint32 preFeatureCount = preVisiDataReader.readUint32Big();
atUint32 preLightsCount = preVisiDataReader.readUint32Big();
atUint32 preLayer2LightCount = preVisiDataReader.readUint32Big();
atUint32 preEntityCount = preVisiDataReader.readUint32Big();
if (preVisiFourCC == 'VISI' && preVisiVersion == 2 &&
preFeatureCount == meshes.size() + entities.size() &&
preLightsCount == lightsVisi[0].size() + lightsVisi[1].size() &&
preLayer2LightCount == lightsVisi[1].size() &&
preEntityCount == entities.size())
{
secs.emplace_back(preVisiLen, 0);
memcpy(secs.back().data(), preVisiData.get(), preVisiLen);
visiGood = true;
}
}
}
if (!visiGood)
{
hecl::ProjectPath visiIntOut = outPath.getWithExtension(_S(".visiint"));
hecl::ProjectPath visiIn = outPath.getWithExtension(_S(".visi"));
hecl::ProjectPath visiIn = inPath.getWithExtension(_S(".visi"));
athena::io::FileWriter w(visiIntOut.getAbsolutePath());
w.writeUint32Big(meshes.size());
for (const DNACMDL::Mesh& mesh : meshes)
@ -509,9 +558,12 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
#if _WIN32
VisiGenPath += _S(".exe");
#endif
char thrIdx[16];
snprintf(thrIdx, 16, "%d", hecl::ClientProcess::GetThreadWorkerIdx());
const hecl::SystemChar* args[] = {VisiGenPath.c_str(),
visiIntOut.getAbsolutePath().c_str(),
visiIn.getAbsolutePath().c_str(),
thrIdx,
nullptr};
if (0 == hecl::RunProcess(VisiGenPath.c_str(), args))
{
@ -523,6 +575,7 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
}
}
}
}
if (!visiGood)
secs.emplace_back(4, 0);
@ -578,7 +631,7 @@ bool MREA::CookPath(const hecl::ProjectPath& outPath,
int64_t rem = w.position() % 32;
if (rem)
for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1);
w.writeUByte(0xff);
return true;
}

View File

@ -133,7 +133,26 @@ makeProj:
m_mainMP1.emplace(m_factoryMP1, m_objStore, m_vm.m_mainBooFactory,
m_vm.m_mainCommandQueue, m_vm.m_renderTex);
m_vm.InitMP1(*m_mainMP1);
m_vm.BuildTestPART();
// precook
m_precooking = true;
std::vector<SObjectTag> nonMlvls;
std::vector<SObjectTag> mlvls;
mlvls.reserve(8);
m_factoryMP1.EnumerateResources([this, &nonMlvls, &mlvls](const SObjectTag& tag)
{
if (tag.type == FOURCC('CMDL') || tag.type == FOURCC('MREA'))
m_factoryMP1.CookResourceAsync(tag);
else if (tag.type != FOURCC('MLVL'))
nonMlvls.push_back(tag);
else // (tag.type == FOURCC('MLVL'))
mlvls.push_back(tag);
return true;
});
for (const SObjectTag& tag : nonMlvls)
m_factoryMP1.CookResourceAsync(tag);
for (const SObjectTag& tag : mlvls)
m_factoryMP1.CookResourceAsync(tag);
if (needsSave)
saveProject();
@ -182,6 +201,14 @@ bool ProjectManager::saveProject()
void ProjectManager::mainUpdate()
{
if (m_precooking)
{
if (!m_factoryMP1.IsBusy())
m_precooking = false;
else
return;
}
if (m_mainMP1)
{
if (m_mainMP1->Proc())
@ -194,6 +221,9 @@ void ProjectManager::mainUpdate()
void ProjectManager::mainDraw()
{
if (m_precooking)
return;
if (m_mainMP1)
m_mainMP1->Draw();
}

View File

@ -34,6 +34,7 @@ class ProjectManager
ProjectResourceFactoryMP1 m_factoryMP1;
ProjectResourcePool m_objStore;
std::experimental::optional<MP1::CMain> m_mainMP1;
bool m_precooking = false;
public:
static ProjectManager* g_SharedManager;

View File

@ -548,18 +548,23 @@ void ProjectResourceFactoryBase::AsyncTask::CookComplete()
xc_targetDataRawPtr,
x14_resSize, x14_resOffset);
}
else
else if (xc_targetDataPtr || xc_targetObjPtr)
{
x10_loadBuffer.reset(new u8[x14_resSize]);
m_bufTransaction = m_parent.m_clientProc.addBufferTransaction(m_cookedPath,
x10_loadBuffer.get(),
x14_resSize, x14_resOffset);
}
else
{
/* Skip buffer transaction if no target pointers set */
m_complete = true;
}
}
bool ProjectResourceFactoryBase::AsyncTask::AsyncPump()
{
if (m_failed)
if (m_failed || m_complete)
return true;
if (m_bufTransaction)
@ -581,14 +586,49 @@ bool ProjectResourceFactoryBase::AsyncTask::AsyncPump()
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())
using ItType = std::unordered_map<SObjectTag,
std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator;
ItType search = m_parent.m_asyncLoadMap.find(x0_tag);
if (search == m_parent.m_asyncLoadMap.end())
return;
for (ItType tmp = search ; !m_parent.AsyncPumpTask(tmp) ; tmp = search)
{std::this_thread::sleep_for(std::chrono::milliseconds(2));}
}
using AsyncTask = ProjectResourceFactoryBase::AsyncTask;
std::shared_ptr<AsyncTask>
ProjectResourceFactoryBase::_AddTask(const std::shared_ptr<AsyncTask>& ptr)
{
m_asyncLoadMap.insert({ptr->x0_tag, m_asyncLoadList.insert(m_asyncLoadList.end(), ptr)});
return ptr;
}
std::list<std::shared_ptr<AsyncTask>>::iterator
ProjectResourceFactoryBase::_RemoveTask(std::list<std::shared_ptr<AsyncTask>>::iterator it)
{
m_asyncLoadMap.erase((*it)->x0_tag);
return m_asyncLoadList.erase(it);
}
std::unordered_map<SObjectTag, std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator
ProjectResourceFactoryBase::_RemoveTask(std::unordered_map<SObjectTag,
std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator it)
{
if (it != m_asyncLoadMap.end())
{
m_asyncLoadList.erase(it->second);
return m_asyncLoadMap.erase(it);
}
return it;
};
std::unordered_map<SObjectTag, std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator
ProjectResourceFactoryBase::_RemoveTask(const SObjectTag& tag)
{
return _RemoveTask(m_asyncLoadMap.find(tag));
};
bool ProjectResourceFactoryBase::WaitForTagReady(const urde::SObjectTag& tag,
const hecl::ProjectPath*& pathOut)
{
@ -687,17 +727,17 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
const hecl::ProjectPath* resPath = nullptr;
if (!WaitForTagReady(tag, resPath))
return {};
auto asyncSearch = m_asyncLoadList.find(tag);
if (asyncSearch != m_asyncLoadList.end())
auto asyncSearch = m_asyncLoadMap.find(tag);
if (asyncSearch != m_asyncLoadMap.end())
{
/* Async spinloop */
AsyncTask& task = *asyncSearch->second;
AsyncTask& task = **asyncSearch->second;
task.EnsurePath(task.x0_tag, *resPath);
/* Pump load pipeline (cooking if needed) */
while (!task.AsyncPump()) {std::this_thread::sleep_for(std::chrono::milliseconds(2));}
if (task.m_complete)
if (task.m_complete && task.x10_loadBuffer)
{
/* Load complete, build resource */
std::unique_ptr<IObj> newObj;
@ -714,16 +754,23 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
*task.xc_targetObjPtr = newObj.get();
Log.report(logvisor::Warning, "spin-built %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id.Value()));
task.x0_tag.type.toString().c_str(), u32(task.x0_tag.id.Value()));
m_asyncLoadList.erase(asyncSearch);
_RemoveTask(asyncSearch);
return newObj;
}
else if (task.m_complete)
{
Log.report(logvisor::Error, "unable to spin-build %.4s %08X; Resource requested as cook-only",
task.x0_tag.type.toString().c_str(), u32(task.x0_tag.id.Value()));
}
else
{
Log.report(logvisor::Error, "unable to spin-build %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id.Value()));
m_asyncLoadList.erase(asyncSearch);
task.x0_tag.type.toString().c_str(), u32(task.x0_tag.id.Value()));
}
_RemoveTask(asyncSearch);
return {};
}
@ -731,16 +778,15 @@ std::unique_ptr<urde::IObj> ProjectResourceFactoryBase::Build(const urde::SObjec
return BuildSync(tag, *resPath, paramXfer, selfRef);
}
std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
std::shared_ptr<AsyncTask>
ProjectResourceFactoryBase::BuildAsyncInternal(const urde::SObjectTag& tag,
const urde::CVParamTransfer& paramXfer,
urde::IObj** objOut,
CObjectReference* selfRef)
{
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
return {};
return m_asyncLoadList.emplace(std::make_pair(tag,
std::make_unique<AsyncTask>(*this, tag, objOut, paramXfer, selfRef))).first->second;
return _AddTask(std::make_unique<AsyncTask>(*this, tag, objOut, paramXfer, selfRef));
}
void ProjectResourceFactoryBase::BuildAsync(const urde::SObjectTag& tag,
@ -772,40 +818,37 @@ u32 ProjectResourceFactoryBase::ResourceSize(const SObjectTag& tag)
return fr->length();
}
std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
std::shared_ptr<AsyncTask>
ProjectResourceFactoryBase::LoadResourceAsync(const urde::SObjectTag& tag,
std::unique_ptr<u8[]>& target)
{
if (!tag.id.IsValid())
Log.report(logvisor::Fatal, "attempted to access null id");
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
return {};
return m_asyncLoadList.emplace(std::make_pair(tag,
std::make_shared<AsyncTask>(*this, tag, target))).first->second;
return _AddTask(std::make_shared<AsyncTask>(*this, tag, target));
}
std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
std::shared_ptr<AsyncTask>
ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag,
u32 size, u32 off,
std::unique_ptr<u8[]>& target)
{
if (!tag.id.IsValid())
Log.report(logvisor::Fatal, "attempted to access null id");
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
return {};
return m_asyncLoadList.emplace(std::make_pair(tag,
std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second;
return _AddTask(std::make_shared<AsyncTask>(*this, tag, target, size, off));
}
std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
std::shared_ptr<AsyncTask>
ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, u8* target)
{
if (!tag.id.IsValid())
Log.report(logvisor::Fatal, "attempted to access null id");
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
return {};
return m_asyncLoadList.emplace(std::make_pair(tag,
std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second;
return _AddTask(std::make_shared<AsyncTask>(*this, tag, target, size, off));
}
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag)
@ -847,9 +890,19 @@ std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourcePartSync(const urd
return fr->readUBytes(sz);
}
std::shared_ptr<AsyncTask>
ProjectResourceFactoryBase::CookResourceAsync(const urde::SObjectTag& tag)
{
if (!tag.id.IsValid())
Log.report(logvisor::Fatal, "attempted to access null id");
if (m_asyncLoadMap.find(tag) != m_asyncLoadMap.end())
return {};
return _AddTask(std::make_shared<AsyncTask>(*this, tag));
}
void ProjectResourceFactoryBase::CancelBuild(const urde::SObjectTag& tag)
{
m_asyncLoadList.erase(tag);
_RemoveTask(tag);
}
bool ProjectResourceFactoryBase::CanBuild(const urde::SObjectTag& tag)
@ -961,12 +1014,12 @@ void ProjectResourceFactoryBase::EnumerateNamedResources(
}
}
bool ProjectResourceFactoryBase::AsyncPumpTask(
std::unordered_map<SObjectTag, std::shared_ptr<AsyncTask>>::iterator& it)
template <typename ItType>
bool ProjectResourceFactoryBase::AsyncPumpTask(ItType& it)
{
/* Ensure requested resource is in the index */
std::unique_lock<std::mutex> lk(m_backgroundIndexMutex);
AsyncTask& task = *it->second;
AsyncTask& task = _GetAsyncTask(it);
auto search = m_tagToPath.find(task.x0_tag);
if (search == m_tagToPath.end())
{
@ -974,7 +1027,7 @@ bool ProjectResourceFactoryBase::AsyncPumpTask(
{
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);
it = _RemoveTask(it);
}
return true;
}
@ -1025,13 +1078,19 @@ bool ProjectResourceFactoryBase::AsyncPumpTask(
}
}
it = m_asyncLoadList.erase(it);
it = _RemoveTask(it);
return true;
}
++it;
return false;
}
template bool ProjectResourceFactoryBase::AsyncPumpTask<std::list<std::shared_ptr<AsyncTask>>::iterator>(
std::list<std::shared_ptr<AsyncTask>>::iterator& it);
template bool ProjectResourceFactoryBase::AsyncPumpTask<std::unordered_map<SObjectTag,
std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator>(
std::unordered_map<SObjectTag, std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator& it);
void ProjectResourceFactoryBase::AsyncIdle()
{
/* Consume completed transactions, they will be processed this cycle at the latest */

View File

@ -60,6 +60,10 @@ public:
IObj** ptr, const CVParamTransfer& xfer, CObjectReference* selfRef)
: m_parent(parent), x0_tag(tag), xc_targetObjPtr(ptr), x18_cvXfer(xfer), m_selfRef(selfRef) {}
/* Cook only */
AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag)
: m_parent(parent), x0_tag(tag) {}
void EnsurePath(const urde::SObjectTag& tag,
const hecl::ProjectPath& path);
void CookComplete();
@ -85,7 +89,27 @@ protected:
std::mutex m_backgroundIndexMutex;
bool m_backgroundRunning = false;
std::unordered_map<SObjectTag, std::shared_ptr<AsyncTask>> m_asyncLoadList;
std::list<std::shared_ptr<AsyncTask>> m_asyncLoadList;
std::unordered_map<SObjectTag, std::list<std::shared_ptr<AsyncTask>>::iterator> m_asyncLoadMap;
std::shared_ptr<AsyncTask>
_AddTask(const std::shared_ptr<AsyncTask>& ptr);
std::list<std::shared_ptr<AsyncTask>>::iterator
_RemoveTask(std::list<std::shared_ptr<AsyncTask>>::iterator it);
std::unordered_map<SObjectTag, std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator
_RemoveTask(std::unordered_map<SObjectTag,
std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator it);
std::unordered_map<SObjectTag, std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator
_RemoveTask(const SObjectTag& tag);
static AsyncTask& _GetAsyncTask(std::list<std::shared_ptr<AsyncTask>>::iterator it)
{
return **it;
}
static AsyncTask& _GetAsyncTask(
std::unordered_map<SObjectTag, std::list<std::shared_ptr<AsyncTask>>::iterator>::iterator it)
{
return **it->second;
}
bool WaitForTagReady(const urde::SObjectTag& tag, const hecl::ProjectPath*& pathOut);
bool
@ -141,9 +165,13 @@ 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);
std::shared_ptr<AsyncTask> CookResourceAsync(const urde::SObjectTag& tag);
template <typename ItType>
bool AsyncPumpTask(ItType& it);
void AsyncIdle();
void Shutdown() { CancelBackgroundIndex(); }
bool IsBusy() const { return m_asyncLoadMap.size() != 0; }
SObjectTag TagFromPath(const hecl::SystemChar* path) const
{

View File

@ -25,8 +25,11 @@ using YAMLNode = athena::io::YAMLNode;
namespace urde
{
void ViewManager::BuildTestPART()
void ViewManager::InitMP1(MP1::CMain& main)
{
main.Init(m_fileStoreManager, m_mainWindow.get(), m_voiceEngine.get(), *m_amuseAllocWrapper);
main.WarmupShaders();
m_testGameView.reset(new TestGameView(*this, m_viewResources, *m_rootView));
m_rootView->accessContentViews().clear();
@ -34,12 +37,6 @@ void ViewManager::BuildTestPART()
m_rootView->updateSize();
}
void ViewManager::InitMP1(MP1::CMain& main)
{
main.Init(m_fileStoreManager, m_mainWindow.get(), m_voiceEngine.get(), *m_amuseAllocWrapper);
main.WarmupShaders();
}
void ViewManager::TestGameView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{
specter::View::resized(root, sub);
@ -48,7 +45,6 @@ void ViewManager::TestGameView::resized(const boo::SWindowRect& root, const boo:
void ViewManager::TestGameView::draw(boo::IGraphicsCommandQueue* gfxQ)
{
gfxQ->clearTarget(true, true);
m_vm.m_projManager.mainDraw();
}

View File

@ -143,7 +143,6 @@ class ViewManager : public specter::IViewManager
unsigned m_editorFrames = 120;
void FadeInEditors() {m_editorFrames = 0;}
void BuildTestPART();
void InitMP1(MP1::CMain& main);
Space* m_deferSplit = nullptr;

View File

@ -28,7 +28,7 @@ void CMapArea::PostConstruct()
{
x38_moStart = x44_buf.get();
x3c_vertexStart = x38_moStart + (x28_mappableObjCount * 0x50);
x40_surfaceStart = x40_surfaceStart + (x2c_vertexCount * 12);
x40_surfaceStart = x3c_vertexStart + (x2c_vertexCount * 12);
m_mappableObjects.reserve(x28_mappableObjCount);
for (u32 i = 0, j=0 ; i<x28_mappableObjCount ; ++i, j += 0x50)

View File

@ -9,7 +9,7 @@ namespace urde
CMapUniverse::CMapUniverse(CInputStream& in, u32 version)
: x0_hexagonId(in.readUint32Big())
{
x4_hexagonToken = g_SimplePool->GetObj({'MAPA', x0_hexagonId});
x4_hexagonToken = g_SimplePool->GetObj({FOURCC('MAPA'), x0_hexagonId});
u32 count = in.readUint32Big();
x10_worldDatas.reserve(count);
for (u32 i = 0 ; i<count ; ++i)

View File

@ -78,7 +78,7 @@ public:
void Lock() { x0_area.Lock(); }
void Unlock() { x0_area.Unlock(); }
bool IsLoaded() const { return x0_area.IsLoaded(); }
const CMapArea* GetMapArea() const { return x0_area.IsLoaded() ? x0_area.GetObj() : nullptr; }
const CMapArea* GetMapArea() const { return x0_area.GetObj(); }
const CMapAreaData* GetNextMapAreaData() const { return x14_next; }
EMapAreaList GetContainingList() const { return x10_list; }
CMapAreaData* NextMapAreaData() { return x14_next; }

View File

@ -127,6 +127,8 @@ IObj* CToken::GetObj()
}
CToken& CToken::operator=(const CToken& other)
{
Unlock();
RemoveRef();
x0_objRef = other.x0_objRef;
if (x0_objRef)
{

View File

@ -166,7 +166,7 @@ bool CAreaOctTree::Node::LineTestInternal(const zeus::CLine& line, const CMateri
float tf1 = lT;
float tf2 = hT;
if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2))
if (!LineTestInternal(line, filter, tf1, tf2, maxT, vec))
if (!child.LineTestInternal(line, filter, tf1, tf2, maxT, vec))
return false;
}
return true;
@ -201,7 +201,7 @@ bool CAreaOctTree::Node::LineTestInternal(const zeus::CLine& line, const CMateri
{
Node child = GetChild(r26b);
if (child.x20_nodeType != ETreeType::Invalid)
if (!LineTestInternal(line, filter, f21, f22, maxT, vec))
if (!child.LineTestInternal(line, filter, f21, f22, maxT, vec))
return false;
}
if (i < idx.first)
@ -306,7 +306,7 @@ void CAreaOctTree::Node::LineTestExInternal(const zeus::CLine& line, const CMate
float tf1 = lT;
float tf2 = hT;
if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2))
LineTestExInternal(line, filter, tmpRes[i], tf1, tf2, maxT, vec);
child.LineTestExInternal(line, filter, tmpRes[i], tf1, tf2, maxT, vec);
}
if (!tmpRes[0].x10_surface && !tmpRes[1].x10_surface)
@ -425,12 +425,12 @@ void CAreaOctTree::Node::LineTestExInternal(const zeus::CLine& line, const CMate
{
if (i >= 0)
selector ^= 1 << r19[i];
float hiT = (i < r17-1) ? hiT = r20[r19[i+1]] : hiT = hT;
float hiT = (i < r17-1) ? r20[r19[i+1]] : hT;
if (hiT > lowT && loT <= hiT)
{
Node child = GetChild(selector);
if (child.x20_nodeType != ETreeType::Invalid)
LineTestExInternal(line, filter, res, loT, hiT, maxT, vec);
child.LineTestExInternal(line, filter, res, loT, hiT, maxT, vec);
if (res.x10_surface)
if (res.x3c_t > highT)
res = SRayResult();

View File

@ -5,6 +5,7 @@
#include "RetroTypes.hpp"
#include "zeus/CTransform.hpp"
#include "zeus/CAABox.hpp"
#include "hecl/Runtime.hpp"
namespace urde
{
@ -21,9 +22,21 @@ class CMetroidModelInstance
zeus::CAABox x34_aabb;
std::vector<CBooSurface> m_surfaces;
std::unique_ptr<CBooModel> m_instance;
hecl::HMDLMeta m_hmdlMeta;
std::vector<std::shared_ptr<hecl::Runtime::ShaderPipelines>> m_shaders;
public:
CMetroidModelInstance() = default;
CMetroidModelInstance(CMetroidModelInstance&&) = default;
void Clear()
{
x0_visorFlags = 0;
x4_xf = {};
x34_aabb = {};
m_surfaces.clear();
m_instance.reset();
m_hmdlMeta = {};
m_shaders.clear();
}
};
}

View File

@ -88,6 +88,11 @@ public:
int m_matSetIdx;
SShader(int idx) : m_matSetIdx(idx) {}
void UnlockTextures();
std::shared_ptr<hecl::Runtime::ShaderPipelines>
BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat);
void BuildShaders(const hecl::HMDLMeta& meta,
std::vector<std::shared_ptr<hecl::Runtime::ShaderPipelines>>& shaders);
void BuildShaders(const hecl::HMDLMeta& meta) { BuildShaders(meta, m_shaders); }
};
enum class ESurfaceSelection
@ -101,7 +106,8 @@ private:
CBooModel* m_next = nullptr;
CBooModel* m_prev = nullptr;
size_t m_uniUpdateCount = 0;
TLockedToken<CModel> m_model;
TToken<CModel> m_modelTok;
CModel* m_model;
std::vector<CBooSurface>* x0_surfaces;
const MaterialSet* x4_matSet;
int m_matSetIdx = -1;
@ -161,9 +167,11 @@ private:
static float g_TransformedTime2;
static CBooModel* g_LastModelCached;
static bool g_DummyTextures;
public:
~CBooModel();
CBooModel(TToken<CModel>& token, std::vector<CBooSurface>* surfaces, SShader& shader,
CBooModel(TToken<CModel>& token, CModel* parent, std::vector<CBooSurface>* surfaces, SShader& shader,
boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo,
const zeus::CAABox& aabb, u8 renderMask,
int numInsts, boo::ITexture* txtrOverrides[8]);
@ -178,6 +186,8 @@ public:
void ActivateLights(const std::vector<CLight>& lights);
void DisableAllLights();
void RemapMaterialData(SShader& shader);
void RemapMaterialData(SShader& shader,
const std::vector<std::shared_ptr<hecl::Runtime::ShaderPipelines>>& pipelines);
bool TryLockTextures() const;
void UnlockTextures() const;
void SyncLoadTextures() const;
@ -197,6 +207,9 @@ public:
const CPoseAsTransforms* pose) const;
void DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const;
void LockParent() { m_modelTok.Lock(); }
void UnlockParent() { m_modelTok.Unlock(); }
const MaterialSet::Material& GetMaterialByIndex(int idx) const
{
@ -220,6 +233,8 @@ public:
static zeus::CTransform g_shadowTexXf;
static void EnableShadowMaps(boo::ITexture* map, const zeus::CTransform& texXf);
static void DisableShadowMaps();
static void SetDummyTextures(bool b) { g_DummyTextures = true; }
};
class CModel
@ -258,7 +273,9 @@ public:
const zeus::CAABox& GetAABB() const {return m_aabb;}
CBooModel& GetInstance() {return *x28_modelInst;}
const CBooModel& GetInstance() const {return *x28_modelInst;}
std::unique_ptr<CBooModel> MakeNewInstance(int shaderIdx, int subInsts, boo::ITexture* txtrOverrides[8] = nullptr);
std::unique_ptr<CBooModel> MakeNewInstance(int shaderIdx, int subInsts,
boo::ITexture* txtrOverrides[8] = nullptr,
bool lockParent = true);
void UpdateLastFrame() const { const_cast<CModel&>(*this).x38_lastFrame = CGraphics::GetFrameCounter(); }
size_t GetPoolVertexOffset(size_t idx) const;

View File

@ -46,6 +46,8 @@ void CBooModel::KillCachedViewDepState()
g_LastModelCached = nullptr;
}
bool CBooModel::g_DummyTextures = false;
zeus::CVector3f CBooModel::g_ReflectViewPos = {};
static const zeus::CMatrix4f ReflectBaseMtx =
@ -146,13 +148,13 @@ CBooModel::~CBooModel()
g_FirstModel = m_next;
}
CBooModel::CBooModel(TToken<CModel>& token, std::vector<CBooSurface>* surfaces, SShader& shader,
CBooModel::CBooModel(TToken<CModel>& token, CModel* parent, std::vector<CBooSurface>* surfaces, SShader& shader,
boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo,
const zeus::CAABox& aabb, u8 renderMask,
int numInsts, boo::ITexture* txtrOverrides[8])
: m_model(token), x0_surfaces(surfaces), x4_matSet(&shader.m_matSet), m_matSetIdx(shader.m_matSetIdx),
m_pipelines(&shader.m_shaders), x1c_textures(shader.x0_textures), x20_aabb(aabb),
x40_24_texturesLoaded(false), x40_25_modelVisible(0), x41_mask(renderMask),
: m_modelTok(token), m_model(parent), x0_surfaces(surfaces), x4_matSet(&shader.m_matSet),
m_matSetIdx(shader.m_matSetIdx), m_pipelines(&shader.m_shaders), x1c_textures(shader.x0_textures),
x20_aabb(aabb), x40_24_texturesLoaded(false), x40_25_modelVisible(0), x41_mask(renderMask),
m_staticVtxFmt(vtxFmt), m_staticVbo(vbo), m_staticIbo(ibo)
{
if (txtrOverrides)
@ -224,7 +226,7 @@ boo::IVertexFormat* CBooModel::ModelInstance::GetBooVtxFmt(const CBooModel& mode
CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
{
if (!x40_24_texturesLoaded)
if (!x40_24_texturesLoaded && !g_DummyTextures)
return nullptr;
if (m_instances.size() >= 256)
@ -233,7 +235,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
ModelInstance& newInst = m_instances.back();
size_t skinBankCount = 0;
size_t weightVecCount = 0;
if (const CModel* model = m_model.GetObj())
if (const CModel* model = m_model)
{
skinBankCount = model->m_hmdlMeta.bankCount;
weightVecCount = model->m_hmdlMeta.weightCount;
@ -276,6 +278,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
}
/* Animated UV transform matrices */
size_t matCount = x4_matSet->materials.size();
for (const MaterialSet::Material& mat : x4_matSet->materials)
{
size_t thisSz = ROUND_UP_256(/*mat.uvAnims.size()*/ 8 * (sizeof(zeus::CMatrix4f) * 2));
@ -341,6 +344,10 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
{
texs[texCount++] = overtex;
}
else if (g_DummyTextures)
{
texs[texCount++] = g_Renderer->x220_sphereRamp;
}
else
{
TCachedToken<CTexture>& tex = x1c_textures[idx];
@ -472,6 +479,17 @@ void CBooModel::RemapMaterialData(SShader& shader)
m_instances.clear();
}
void CBooModel::RemapMaterialData(SShader& shader,
const std::vector<std::shared_ptr<hecl::Runtime::ShaderPipelines>>& pipelines)
{
x4_matSet = &shader.m_matSet;
m_matSetIdx = shader.m_matSetIdx;
x1c_textures = shader.x0_textures;
m_pipelines = &pipelines;
x40_24_texturesLoaded = false;
m_instances.clear();
}
bool CBooModel::TryLockTextures() const
{
if (!x40_24_texturesLoaded)
@ -614,15 +632,12 @@ void CBooModel::WarmupDrawSurface(const CBooSurface& surf) const
return;
const ModelInstance& inst = m_instances[m_uniUpdateCount-1];
for (const std::vector<boo::IShaderDataBinding*>& extendeds : inst.m_shaderDataBindings)
{
for (boo::IShaderDataBinding* binding : extendeds)
for (boo::IShaderDataBinding* binding : inst.m_shaderDataBindings[surf.selfIdx])
{
CGraphics::SetShaderDataBinding(binding);
CGraphics::DrawArrayIndexed(surf.m_data.idxStart, std::min(u32(3), surf.m_data.idxCount));
}
}
}
void CBooModel::UVAnimationBuffer::ProcessAnimation(u8*& bufOut, const UVAnimation& anim)
{
@ -816,7 +831,7 @@ boo::IGraphicsBufferD* CBooModel::UpdateUniformData(const CModelFlags& flags,
{
size_t skinBankCount = 0;
size_t weightVecCount = 0;
if (const CModel* model = m_model.GetObj())
if (const CModel* model = m_model)
{
skinBankCount = model->m_hmdlMeta.bankCount;
weightVecCount = model->m_hmdlMeta.weightCount;
@ -1024,13 +1039,44 @@ static const u8* MemoryFromPartData(const u8*& dataCur, const u32*& secSizeCur)
return ret;
}
std::unique_ptr<CBooModel> CModel::MakeNewInstance(int shaderIdx, int subInsts, boo::ITexture* txtrOverrides[8])
std::unique_ptr<CBooModel> CModel::MakeNewInstance(int shaderIdx, int subInsts,
boo::ITexture* txtrOverrides[8],
bool lockParent)
{
if (shaderIdx >= x18_matSets.size())
shaderIdx = 0;
return std::make_unique<CBooModel>(m_selfToken, &x8_surfaces, x18_matSets[shaderIdx],
auto ret = std::make_unique<CBooModel>(m_selfToken, this, &x8_surfaces, x18_matSets[shaderIdx],
m_staticVtxFmt, m_staticVbo, m_ibo,
m_aabb, (m_flags & 0x2) != 0, subInsts, txtrOverrides);
if (lockParent)
ret->LockParent();
return ret;
}
std::shared_ptr<hecl::Runtime::ShaderPipelines>
CBooModel::SShader::BuildShader(const hecl::HMDLMeta& meta, const MaterialSet::Material& mat)
{
hecl::Backend::ReflectionType reflectionType;
if (mat.flags.samusReflectionIndirectTexture())
reflectionType = hecl::Backend::ReflectionType::Indirect;
else if (mat.flags.samusReflection())
reflectionType = hecl::Backend::ReflectionType::Simple;
else
reflectionType = hecl::Backend::ReflectionType::None;
hecl::Runtime::ShaderTag tag(mat.heclIr,
meta.colorCount, meta.uvCount, meta.weightCount,
meta.weightCount * 4, 8, boo::Primitive(meta.topology),
reflectionType, true, true, true);
return CModelShaders::g_ModelShaders->buildExtendedShader
(tag, mat.heclIr, "CMDL", *CGraphics::g_BooFactory);
}
void CBooModel::SShader::BuildShaders(const hecl::HMDLMeta& meta,
std::vector<std::shared_ptr<hecl::Runtime::ShaderPipelines>>& shaders)
{
shaders.reserve(m_matSet.materials.size());
for (const MaterialSet::Material& mat : m_matSet.materials)
shaders.push_back(BuildShader(meta, mat));
}
CModel::CModel(std::unique_ptr<u8[]>&& in, u32 /* dataLen */, IObjectStore* store, CObjectReference* selfRef)
@ -1072,25 +1118,7 @@ CModel::CModel(std::unique_ptr<u8[]>&& in, u32 /* dataLen */, IObjectStore* stor
const u8* surfInfo = MemoryFromPartData(dataCur, secSizeCur);
for (CBooModel::SShader& matSet : x18_matSets)
{
matSet.m_shaders.reserve(matSet.m_matSet.materials.size());
for (const MaterialSet::Material& mat : matSet.m_matSet.materials)
{
hecl::Backend::ReflectionType reflectionType;
if (mat.flags.samusReflectionIndirectTexture())
reflectionType = hecl::Backend::ReflectionType::Indirect;
else if (mat.flags.samusReflection())
reflectionType = hecl::Backend::ReflectionType::Simple;
else
reflectionType = hecl::Backend::ReflectionType::None;
hecl::Runtime::ShaderTag tag(mat.heclIr,
m_hmdlMeta.colorCount, m_hmdlMeta.uvCount, m_hmdlMeta.weightCount,
m_hmdlMeta.weightCount * 4, 8, boo::Primitive(m_hmdlMeta.topology),
reflectionType, true, true, true);
matSet.m_shaders.push_back(CModelShaders::g_ModelShaders->buildExtendedShader
(tag, mat.heclIr, "CMDL", *CGraphics::g_BooFactory));
}
}
matSet.BuildShaders(m_hmdlMeta);
m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
@ -1131,7 +1159,7 @@ CModel::CModel(std::unique_ptr<u8[]>&& in, u32 /* dataLen */, IObjectStore* stor
const float* aabbPtr = reinterpret_cast<const float*>(data.get() + 0xc);
m_aabb = zeus::CAABox(hecl::SBig(aabbPtr[0]), hecl::SBig(aabbPtr[1]), hecl::SBig(aabbPtr[2]),
hecl::SBig(aabbPtr[3]), hecl::SBig(aabbPtr[4]), hecl::SBig(aabbPtr[5]));
x28_modelInst = MakeNewInstance(0, 1);
x28_modelInst = MakeNewInstance(0, 1, nullptr, false);
}
void CBooModel::SShader::UnlockTextures()
@ -1228,6 +1256,7 @@ void CModel::ApplyVerticesCPU(boo::IGraphicsBufferD* vertBuf,
void CModel::_WarmupShaders()
{
CBooModel::SetDummyTextures(true);
CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp, zeus::CTransform::Identity());
CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState();
zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix;
@ -1239,7 +1268,6 @@ void CModel::_WarmupShaders()
for (CBooModel::SShader& shader : x18_matSets)
{
GetInstance().RemapMaterialData(shader);
GetInstance().SyncLoadTextures();
GetInstance().UpdateUniformData(defaultFlags, nullptr, nullptr);
GetInstance().WarmupDrawSurfaces();
}
@ -1247,6 +1275,7 @@ void CModel::_WarmupShaders()
CGraphics::SetViewPointMatrix(backupViewPoint);
CGraphics::SetModelMatrix(backupModel);
CBooModel::DisableShadowMaps();
CBooModel::SetDummyTextures(false);
}
void CModel::WarmupShaders(const SObjectTag& cmdlTag)

View File

@ -28,7 +28,7 @@ static const char* VS =
"{\n"
" VertToFrag vtf;\n"
" vtf.color = bu.color;\n"
" vtf.pos = bu.xf * vec4(v.posIn.xyz, 1.0);\n"
" vtf.pos = bu.xf * float4(v.posIn.xyz, 1.0);\n"
" return vtf;\n"
"}\n";

View File

@ -33,7 +33,6 @@ class CModelShaders
{
friend class CModel;
hecl::Runtime::ShaderCacheManager m_shaderCache;
static std::experimental::optional<CModelShaders> g_ModelShaders;
static hecl::Runtime::ShaderCacheExtensions GetShaderExtensions(boo::IGraphicsDataFactory::Platform plat);
static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat);
static hecl::Runtime::ShaderCacheExtensions GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat);
@ -42,6 +41,8 @@ class CModelShaders
static const hecl::Backend::TextureInfo BallFadeTextures[];
static const hecl::Backend::TextureInfo WorldShadowTextures[];
public:
static std::experimental::optional<CModelShaders> g_ModelShaders;
struct Light
{
zeus::CVector3f pos;

View File

@ -248,15 +248,7 @@ CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat)
hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha,
hecl::Backend::ZTest::Equal,
false, false, false, true);
/* MorphBall shadow shading */
ext.registerExtensionSlot({}, {MBShadowPostGLSL, "MBShadowPostFunc"},
3, MBShadowBlockNames, 3, BallFadeTextures,
hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha,
hecl::Backend::ZTest::Equal,
false, false, false, true);
false, false, false, true, true);
/* World shadow shading (modified lighting) */
ext.registerExtensionSlot({LightingShadowGLSL, "LightingShadowFunc"}, {MainPostGLSL, "MainPostFunc"},

View File

@ -231,7 +231,7 @@ CModelShaders::GetShaderExtensionsHLSL(boo::IGraphicsDataFactory::Platform plat)
hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha,
hecl::Backend::ZTest::Equal,
false, false, false, true);
false, false, false, true, true);
/* World shadow shading (modified lighting) */
ext.registerExtensionSlot({LightingShadowHLSL, "LightingShadowFunc"}, {MainPostHLSL, "MainPostFunc"},

View File

@ -126,7 +126,7 @@ static const char* ThermalPostMetal =
" float4 tmulColor;\n"
" float4 addColor;\n"
"};\n"
"static float4 ThermalPostFunc(thread VertToFrag& vtf, constant ThermalUniform& lu, texture2d<float> extTex7, float4 colorIn)\n"
"static float4 EXTThermalPostFunc(thread VertToFrag& vtf, constant ThermalUniform& lu, texture2d<float> extTex7, float4 colorIn)\n"
"{\n"
" return float4(extTex7.sample(samp, vtf.extTcgs0).rrr * lu.tmulColor.rgb + lu.addColor.rgb, 1.0);\n"
"}\n"
@ -149,7 +149,7 @@ static const char* MBShadowPostMetal =
" float4 shadowUp;\n"
" float shadowId;\n"
"};\n"
"static float4 MBShadowPostFunc(thread VertToFrag& vtf, constant MBShadowUniform& su,\n"
"static float4 EXTMBShadowPostFunc(thread VertToFrag& vtf, constant MBShadowUniform& su,\n"
" texture2d<float> extTex0, texture2d<float> extTex1, texture2d<float> extTex2, float4 colorIn)\n"
"{\n"
" float idTexel = extTex0.sample(samp, vtf.extTcgs0).a;\n"
@ -179,7 +179,7 @@ CModelShaders::GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat
false, false, false, true);
/* Thermal Visor shading */
ext.registerExtensionSlot({}, {ThermalPostMetal, "ThermalPostFunc"}, 1, ThermalBlockNames,
ext.registerExtensionSlot({}, {ThermalPostMetal, "EXTThermalPostFunc"}, 1, ThermalBlockNames,
1, ThermalTextures, hecl::Backend::BlendFactor::One,
hecl::Backend::BlendFactor::One, hecl::Backend::ZTest::Original,
false, false, false, true);
@ -233,12 +233,12 @@ CModelShaders::GetShaderExtensionsMetal(boo::IGraphicsDataFactory::Platform plat
false, true, true, false);
/* MorphBall shadow shading */
ext.registerExtensionSlot({}, {MBShadowPostMetal, "MBShadowPostFunc"},
ext.registerExtensionSlot({}, {MBShadowPostMetal, "EXTMBShadowPostFunc"},
1, MBShadowBlockNames, 3, BallFadeTextures,
hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha,
hecl::Backend::ZTest::Equal,
false, false, false, true);
false, false, false, true, true);
/* World shadow shading (modified lighting) */
ext.registerExtensionSlot({LightingShadowMetal, "EXTLightingShadowFunc"}, {MainPostMetal, "MainPostFunc"},

View File

@ -73,7 +73,7 @@ struct OGLParticleSwooshDataBindingFactory : TShader<CParticleSwooshShaders>::ID
CSwooshDescription* desc = gen.GetDesc();
CUVElement* texr = desc->x3c_TEXR.get();
boo::ITexture* textures[] = {texr->GetValueTexture(0).GetObj()->GetBooTexture()};
boo::ITexture* textures[] = {texr ? texr->GetValueTexture(0).GetObj()->GetBooTexture() : nullptr};
const boo::VertexElementDescriptor VtxFmt[] =
{

View File

@ -71,7 +71,7 @@ struct D3DParticleSwooshDataBindingFactory : TShader<CParticleSwooshShaders>::ID
CSwooshDescription* desc = gen.GetDesc();
CUVElement* texr = desc->x3c_TEXR.get();
boo::ITexture* textures[] = {texr->GetValueTexture(0).GetObj()->GetBooTexture()};
boo::ITexture* textures[] = {texr ? texr->GetValueTexture(0).GetObj()->GetBooTexture() : nullptr};
boo::IGraphicsBuffer* uniforms[] = {gen.m_uniformBuf};
gen.m_dataBind = ctx.newShaderDataBinding(shaders.m_pipeline, CParticleSwooshShaders::m_vtxFormat,

View File

@ -77,7 +77,7 @@ struct MetalParticleSwooshDataBindingFactory : TShader<CParticleSwooshShaders>::
CSwooshDescription* desc = gen.GetDesc();
CUVElement* texr = desc->x3c_TEXR.get();
boo::ITexture* textures[] = {texr->GetValueTexture(0).GetObj()->GetBooTexture()};
boo::ITexture* textures[] = {texr ? texr->GetValueTexture(0).GetObj()->GetBooTexture() : nullptr};
boo::IGraphicsBuffer* uniforms[] = {gen.m_uniformBuf};
gen.m_dataBind = ctx.newShaderDataBinding(shaders.m_pipeline, CParticleSwooshShaders::m_vtxFormat,

View File

@ -116,9 +116,9 @@ static const char* BlurVS =
"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant PhazonSuitBlurUniform& psu [[ buffer(2) ]])\n"
"{\n"
" VertToFrag vtf;\n"
" vtf.uv = uvIn.xy;\n"
" vtf.blurDir = blurDir.xy;\n"
" vtf.position = float4(posIn.xyz, 1.0);\n"
" vtf.uv = v.uvIn.xy;\n"
" vtf.blurDir = psu.blurDir.xy;\n"
" vtf.position = float4(v.posIn.xyz, 1.0);\n"
" return vtf;\n"
"}\n";

View File

@ -270,6 +270,21 @@ void CMain::InitializeSubsystems(const hecl::Runtime::FileStoreManager& storeMgr
CGBASupport::Initialize();
}
void CMain::MemoryCardInitializePump()
{
if (!g_MemoryCardSys)
{
std::unique_ptr<CMemoryCardSys>& memSys = x128_globalObjects.x0_memoryCardSys;
if (!memSys)
memSys.reset(new CMemoryCardSys());
if (memSys->InitializePump())
{
g_MemoryCardSys = memSys.get();
g_GameState->InitializeMemoryStates();
}
}
}
void CMain::FillInAssetIDs()
{
}
@ -326,6 +341,7 @@ void CMain::WarmupShaders()
if (m_warmupTags.size())
return;
m_needsWarmupClear = true;
size_t modelCount = 0;
g_ResFactory->EnumerateResources([&](const SObjectTag& tag)
{
@ -376,6 +392,11 @@ void CMain::Draw()
// Warmup cycle overrides draw
if (m_warmupTags.size())
{
if (m_needsWarmupClear)
{
CGraphics::g_BooMainCommandQueue->clearTarget(true, true);
m_needsWarmupClear = false;
}
auto startTime = std::chrono::steady_clock::now();
while (m_warmupIt != m_warmupTags.end())
{
@ -400,6 +421,7 @@ void CMain::Draw()
return;
}
CGraphics::g_BooMainCommandQueue->clearTarget(true, true);
x164_archSupport->Draw();
}

View File

@ -243,6 +243,7 @@ private:
// Warmup state
std::vector<SObjectTag> m_warmupTags;
std::vector<SObjectTag>::iterator m_warmupIt;
bool m_needsWarmupClear = false;
void InitializeSubsystems(const hecl::Runtime::FileStoreManager& storeMgr);
@ -269,20 +270,7 @@ public:
void Shutdown();
boo::IWindow* GetMainWindow() const;
void MemoryCardInitializePump()
{
if (!g_MemoryCardSys)
{
std::unique_ptr<CMemoryCardSys>& memSys = x128_globalObjects.x0_memoryCardSys;
if (!memSys)
memSys.reset(new CMemoryCardSys());
if (memSys->InitializePump())
{
g_MemoryCardSys = memSys.get();
g_GameState->InitializeMemoryStates();
}
}
}
void MemoryCardInitializePump();
bool CheckReset() { return false; }
bool CheckTerminate() { return false; }

View File

@ -168,13 +168,13 @@ namespace urde
{
template <class T>
TCastToPtr<T>::TCastToPtr(CEntity* p) { p->Accept(*this); }
TCastToPtr<T>::TCastToPtr(CEntity* p) { if (p) p->Accept(*this); else ptr = nullptr; }
template <class T>
TCastToPtr<T>::TCastToPtr(CEntity& p) { p.Accept(*this); }
template <class T>
TCastToPtr<T>& TCastToPtr<T>::operator=(CEntity* p) { p->Accept(*this); return *this; }
TCastToPtr<T>& TCastToPtr<T>::operator=(CEntity* p) { if (p) p->Accept(*this); else ptr = nullptr; return *this; }
template <class T>
TCastToPtr<T>& TCastToPtr<T>::operator=(CEntity& p) { p.Accept(*this); return *this; }

View File

@ -414,16 +414,16 @@ CGameArea::CGameArea(CInputStream& in, int idx, int mlvlVersion)
CGameArea::CGameArea(CAssetId mreaId)
: x84_mrea(mreaId)
{
while (StartStreamingMainArea()) {}
while (StartStreamingMainArea())
for (auto& req : xf8_loadTransactions)
req->WaitForComplete();
MREAHeader header = VerifyHeader();
x12c_postConstructed->x4c_insts.reserve(header.modelCount);
x12c_postConstructed->x4c_insts.resize(header.modelCount);
FillInStaticGeometry();
FillInStaticGeometry(false);
CBooModel::SetDummyTextures(true);
CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp, zeus::CTransform::Identity());
CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState();
zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix;
@ -434,7 +434,6 @@ CGameArea::CGameArea(CAssetId mreaId)
for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts)
{
CGraphics::SetModelMatrix(zeus::CTransform::Translate(-inst.x34_aabb.center()));
inst.m_instance->SyncLoadTextures();
inst.m_instance->UpdateUniformData(defaultFlags, nullptr, nullptr);
inst.m_instance->WarmupDrawSurfaces();
}
@ -442,6 +441,7 @@ CGameArea::CGameArea(CAssetId mreaId)
CGraphics::SetViewPointMatrix(backupViewPoint);
CGraphics::SetModelMatrix(backupModel);
CBooModel::DisableShadowMaps();
CBooModel::SetDummyTextures(false);
}
bool CGameArea::IGetScriptingMemoryAlways() const
@ -932,7 +932,7 @@ void CGameArea::PostConstructArea()
u32 sec = 3;
/* Models */
x12c_postConstructed->x4c_insts.reserve(header.modelCount);
x12c_postConstructed->x4c_insts.resize(header.modelCount);
for (u32 i=0 ; i<header.modelCount ; ++i)
{
u32 surfCount = hecl::SBig(*reinterpret_cast<const u32*>((secIt+4)->first));
@ -1051,26 +1051,28 @@ void CGameArea::PostConstructArea()
}
}
void CGameArea::FillInStaticGeometry()
void CGameArea::FillInStaticGeometry(bool textures)
{
x12c_postConstructed->x4c_insts.clear();
if (!x12c_postConstructed->x4c_insts.empty())
for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts)
inst.Clear();
/* Materials */
CBooModel::SShader& matSet = x12c_postConstructed->m_materialSet;
auto secIt = m_resolvedBufs.begin() + 2;
{
athena::io::MemoryReader r(secIt->first, secIt->second);
x12c_postConstructed->m_materialSet.m_matSet.read(r);
matSet.m_matSet.read(r);
if (textures)
CBooModel::MakeTexturesFromMats(matSet.m_matSet, matSet.x0_textures, *g_SimplePool);
++secIt;
}
x12c_postConstructed->m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{
/* Models */
for (u32 i=0 ; i<x12c_postConstructed->x4c_insts.capacity() ; ++i)
for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts)
{
x12c_postConstructed->x4c_insts.emplace_back();
CMetroidModelInstance& inst = x12c_postConstructed->x4c_insts.back();
{
DataSpec::DNAMP1::MREA::MeshHeader header;
athena::io::MemoryReader r(secIt->first, secIt->second);
@ -1081,30 +1083,31 @@ void CGameArea::FillInStaticGeometry()
++secIt;
}
hecl::HMDLMeta hmdlMeta;
{
athena::io::MemoryReader r(secIt->first, secIt->second);
hmdlMeta.read(r);
inst.m_hmdlMeta.read(r);
}
++secIt;
boo::IGraphicsBufferS* vbo;
boo::IGraphicsBufferS* ibo;
boo::IVertexFormat* vtxFmt;
vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, secIt->first, hmdlMeta.vertStride, hmdlMeta.vertCount);
vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, secIt->first, inst.m_hmdlMeta.vertStride,
inst.m_hmdlMeta.vertCount);
++secIt;
ibo = ctx.newStaticBuffer(boo::BufferUse::Index, secIt->first, 4, hmdlMeta.indexCount);
ibo = ctx.newStaticBuffer(boo::BufferUse::Index, secIt->first, 4, inst.m_hmdlMeta.indexCount);
++secIt;
vtxFmt = hecl::Runtime::HMDLData::NewVertexFormat(ctx, hmdlMeta, vbo, ibo);
vtxFmt = hecl::Runtime::HMDLData::NewVertexFormat(ctx, inst.m_hmdlMeta, vbo, ibo);
u32 surfCount = hecl::SBig(*reinterpret_cast<const u32*>(secIt->first));
inst.m_surfaces.reserve(surfCount);
inst.m_shaders.resize(matSet.m_matSet.materials.size());
++secIt;
for (u32 i=0 ; i<surfCount ; ++i)
for (u32 j=0 ; j<surfCount ; ++j)
{
inst.m_surfaces.emplace_back();
CBooSurface& surf = inst.m_surfaces.back();
surf.selfIdx = i;
surf.selfIdx = j;
athena::io::MemoryReader r(secIt->first, secIt->second);
surf.m_data.read(r);
++secIt;
@ -1112,13 +1115,24 @@ void CGameArea::FillInStaticGeometry()
TToken<CModel> nullModel;
inst.m_instance = std::make_unique<CBooModel>
(nullModel, &inst.m_surfaces, x12c_postConstructed->m_materialSet, vtxFmt, vbo, ibo,
inst.x34_aabb, inst.x0_visorFlags, 1, nullptr);
(nullModel, nullptr, &inst.m_surfaces, matSet, vtxFmt, vbo, ibo,
inst.x34_aabb, inst.x0_visorFlags, 0, nullptr);
}
return true;
});
for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts)
{
for (CBooSurface& surf : inst.m_surfaces)
{
auto& shad = inst.m_shaders[surf.m_data.matIdx];
if (!shad)
shad = matSet.BuildShader(inst.m_hmdlMeta, matSet.m_matSet.materials[surf.m_data.matIdx]);
}
inst.m_instance->RemapMaterialData(matSet, inst.m_shaders);
}
x12c_postConstructed->x1108_25_modelsConstructed = true;
}

View File

@ -340,7 +340,7 @@ public:
void LoadScriptObjects(CStateManager& mgr);
std::pair<const u8*, u32> GetLayerScriptBuffer(int layer);
void PostConstructArea();
void FillInStaticGeometry();
void FillInStaticGeometry(bool textures = true);
void VerifyTokenList(CStateManager& stateMgr);
void ClearTokenList();
u32 GetPreConstructedSize() const;

View File

@ -364,7 +364,7 @@ public:
if (size > base::x0_size)
{
for (size_t i = base::x0_size; i < size; ++i)
::new (static_cast<void*>(std::addressof(base::_value(i)))) T;
::new (static_cast<void*>(std::addressof(base::_value(i)))) T();
base::x0_size = size;
}
else if (size < base::x0_size)
@ -428,7 +428,7 @@ class prereserved_vector : public _reserved_vector_base<T, N>
void _init()
{
for (auto& i : base::x4_data)
::new (static_cast<void*>(std::addressof(i._value))) T;
::new (static_cast<void*>(std::addressof(i._value))) T();
}
void _deinit()
{

2
hecl

@ -1 +1 @@
Subproject commit f949aabf5c4632df97746c273cab27a1ea1bffe4
Subproject commit 84393676f125f87c443b770738b552015998228d

View File

@ -59,20 +59,29 @@ static void UpdatePercent(float percent)
VISIRenderer* m_renderer;
NSWindow* m_window;
NSOpenGLView* m_glView;
int m_instanceIdx;
}
- (id)initWithRenderer:(VISIRenderer*)renderer;
- (id)initWithRenderer:(VISIRenderer*)renderer instIdx:(int)instIdx;
@end
@implementation AppDelegate
- (id)initWithRenderer:(VISIRenderer*)renderer
- (id)initWithRenderer:(VISIRenderer*)renderer instIdx:(int)instIdx
{
self = [super init];
m_renderer = renderer;
m_instanceIdx = instIdx;
return self;
}
- (void)applicationDidFinishLaunching:(NSNotification*)notification
{
NSRect cRect = NSMakeRect(100, 100, 768, 512);
int x = 0;
int y = 0;
if (m_instanceIdx != -1)
{
x = (m_instanceIdx & 1) != 0;
y = (m_instanceIdx & 2) != 0;
}
NSRect cRect = NSMakeRect(x * 768, y * 534, 768, 512);
m_window = [[NSWindow alloc] initWithContentRect:cRect
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable
backing:NSBackingStoreBuffered
@ -109,12 +118,15 @@ int main(int argc, const char** argv)
logvisor::RegisterConsoleLogger();
atSetExceptionHandler(AthenaExc);
VISIRenderer renderer(argc, argv);
int instIdx = -1;
if (argc > 3)
instIdx = atoi(argv[3]);
@autoreleasepool
{
[[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular];
/* Delegate (OS X callbacks) */
AppDelegate* appDelegate = [[AppDelegate alloc] initWithRenderer:&renderer];
AppDelegate* appDelegate = [[AppDelegate alloc] initWithRenderer:&renderer instIdx:instIdx];
[[NSApplication sharedApplication] setDelegate:appDelegate];
[[NSApplication sharedApplication] run];
}

View File

@ -56,6 +56,10 @@ int wmain(int argc, const hecl::SystemChar** argv)
VISIRenderer renderer(argc, argv);
s_Renderer = &renderer;
int instIdx = -1;
if (argc > 3)
instIdx = _wtoi(argv[3]);
WNDCLASS wndClass =
{
CS_NOCLOSE,
@ -74,8 +78,16 @@ int wmain(int argc, const hecl::SystemChar** argv)
RECT clientRect = {0, 0, 768, 512};
AdjustWindowRect(&clientRect, dwStyle, FALSE);
int x = 0;
int y = 0;
if (instIdx != -1)
{
x = (instIdx & 1) != 0;
y = (instIdx & 2) != 0;
}
HWND window = CreateWindowW(L"VISIGenWindow", L"VISIGen", dwStyle,
100, 100,
x, y,
clientRect.right - clientRect.left,
clientRect.bottom - clientRect.top,
NULL, NULL, NULL, NULL);

View File

@ -194,7 +194,19 @@ int main(int argc, const char** argv)
swa.border_pixmap = 0;
swa.event_mask = 0;
windowId = XCreateWindow(xDisp, screen->root, 0, 0, 768, 512, 10,
int instIdx = -1;
if (argc > 3)
instIdx = atoi(argv[3]);
int x = 0;
int y = 0;
if (instIdx != -1)
{
x = (instIdx & 1) != 0;
y = (instIdx & 2) != 0;
}
windowId = XCreateWindow(xDisp, screen->root, x, y, 768, 512, 10,
CopyFromParent, CopyFromParent, selectedVisual,
CWBorderPixel | CWEventMask | CWColormap, &swa);

View File

@ -1,6 +1,11 @@
#include "VISIBuilder.hpp"
#include <logvisor/logvisor.hpp>
#ifndef _WIN32
#include <unistd.h>
#include <signal.h>
#endif
#define VISI_MAX_LEVEL 10
#define VISI_MIN_LENGTH 8.0
@ -31,8 +36,8 @@ const VISIBuilder::Leaf& VISIBuilder::PVSRenderCache::GetLeaf(const zeus::CVecto
{
const VISIRenderer::RGBA8& pixel = RGBABuf[i];
uint32_t id = (pixel.b << 16) | (pixel.g << 8) | pixel.r;
if (id != 0xffffff)
leafOut->setBit(id);
if (id != 0)
leafOut->setBit(id - 1);
}
auto setBitLambda = [&](int idx) { leafOut->setBit(idx); };
@ -51,16 +56,16 @@ const VISIBuilder::Leaf& VISIBuilder::PVSRenderCache::GetLeaf(const zeus::CVecto
void VISIBuilder::Progress::report(int divisions)
{
m_prog += 1.f / divisions;
printf(" %g%% \r", m_prog * 100.f);
fflush(stdout);
//printf(" %g%% \r", m_prog * 100.f);
//fflush(stdout);
if (m_updatePercent)
m_updatePercent(m_prog);
}
void VISIBuilder::Node::buildChildren(int level, int divisions, const zeus::CAABox& curAabb,
PVSRenderCache& rc, Progress& prog, const bool& terminate)
PVSRenderCache& rc, Progress& prog, const std::function<bool()>& terminate)
{
if (terminate)
if (terminate())
return;
// Recurse in while building node structure
@ -316,9 +321,10 @@ std::vector<uint8_t> VISIBuilder::build(const zeus::CAABox& fullAabb,
renderCache.m_lightMetaBit = featureCount;
Progress prog(updatePercent);
bool& terminate = renderCache.m_renderer.m_terminate;
pid_t parentPid = getppid();
auto terminate = [this, parentPid]() { return renderCache.m_renderer.m_terminate || kill(parentPid, 0); };
rootNode.buildChildren(0, 1, fullAabb, renderCache, prog, terminate);
if (terminate)
if (terminate())
return {};
// Lights cache their CPVSVisSet result enum as 2 bits
@ -365,7 +371,6 @@ std::vector<uint8_t> VISIBuilder::build(const zeus::CAABox& fullAabb,
w.seekAlign32();
printf("\n");
Log.report(logvisor::Info, "Finished!");
return dataOut;
}

View File

@ -105,7 +105,7 @@ struct VISIBuilder
uint8_t flags = 0;
void buildChildren(int level, int divisions, const zeus::CAABox& curAabb,
PVSRenderCache& rc, Progress& prog, const bool& terminate);
PVSRenderCache& rc, Progress& prog, const std::function<bool()>& terminate);
void calculateSizesAndOffs(size_t& cur, size_t leafSz);
void writeNodes(athena::io::MemoryWriter& w, size_t leafBytes) const;

View File

@ -110,8 +110,6 @@ bool VISIRenderer::SetupShaders()
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_aabbIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 20 * 4, AABBIdxs, GL_STATIC_DRAW);
glGenQueries(1, &m_query);
return true;
}
@ -138,6 +136,7 @@ std::vector<VISIRenderer::Model::Vert> VISIRenderer::AABBToVerts(const zeus::CAA
static zeus::CColor ColorForIndex(int i)
{
i += 1;
return zeus::CColor((i & 0xff) / 255.f,
((i >> 8) & 0xff) / 255.f,
((i >> 16) & 0xff) / 255.f,
@ -202,6 +201,11 @@ bool VISIRenderer::SetupVertexBuffersAndFormats()
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Model::Vert), (void*)16);
}
m_queryCount = m_models.size() + m_entities.size() + m_lights.size();
m_queries.reset(new GLuint[m_queryCount]);
m_queryBools.reset(new bool[m_queryCount]);
glGenQueries(GLsizei(m_queryCount), m_queries.get());
return true;
}
@ -277,7 +281,7 @@ void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bo
glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glClearColor(1.f, 1.f, 1.f, 1.f);
glClearColor(0.f, 0.f, 0.f, 1.f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int j=0 ; j<6 ; ++j)
@ -297,26 +301,6 @@ void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bo
zeus::CFrustum frustum;
frustum.updatePlanes(mv, g_Proj);
// Fill depth buffer with backfaces initially
glCullFace(GL_FRONT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
for (const Model& model : m_models)
{
if (!frustum.aabbFrustumTest(model.aabb))
continue;
glBindVertexArray(model.vao);
for (const Model::Surface& surf : model.surfaces)
{
// Non-transparents first
if (!surf.transparent)
glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT,
reinterpret_cast<void*>(uintptr_t(surf.first * 4)));
else
needTransparent = true;
}
}
// Draw frontfaces
glCullFace(GL_BACK);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -362,6 +346,8 @@ void VISIRenderer::RenderPVSTransparent(const std::function<void(int)>& passFunc
zeus::CFrustum frustum;
frustum.updatePlanes(mv, g_Proj);
memset(m_queryBools.get(), 0, m_queryCount);
int idx = 0;
for (const Model& model : m_models)
{
@ -371,23 +357,29 @@ void VISIRenderer::RenderPVSTransparent(const std::function<void(int)>& passFunc
continue;
}
glBindVertexArray(model.vao);
glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]);
m_queryBools[idx] = true;
for (const Model::Surface& surf : model.surfaces)
{
// transparents
if (surf.transparent)
{
glBeginQuery(GL_ANY_SAMPLES_PASSED, m_query);
glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT,
reinterpret_cast<void*>(uintptr_t(surf.first * 4)));
glEndQuery(GL_ANY_SAMPLES_PASSED);
GLint res;
glGetQueryObjectiv(m_query, GL_QUERY_RESULT, &res);
if (res)
passFunc(idx);
}
}
glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE);
++idx;
}
for (int i=0 ; i<idx ; ++i)
{
if (m_queryBools[i])
{
GLint res;
glGetQueryObjectiv(m_queries[i], GL_QUERY_RESULT, &res);
if (res)
passFunc(i);
}
}
}
}
@ -414,6 +406,8 @@ void VISIRenderer::RenderPVSEntitiesAndLights(const std::function<void(int)>& pa
zeus::CFrustum frustum;
frustum.updatePlanes(mv, g_Proj);
memset(m_queryBools.get(), 0, m_queryCount);
int idx = m_models.size();
for (const Entity& ent : m_entities)
{
@ -423,36 +417,56 @@ void VISIRenderer::RenderPVSEntitiesAndLights(const std::function<void(int)>& pa
continue;
}
glBindVertexArray(ent.vao);
glBeginQuery(GL_ANY_SAMPLES_PASSED, m_query);
m_queryBools[idx] = true;
glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]);
glDrawElements(GL_TRIANGLE_STRIP, 20, GL_UNSIGNED_INT, 0);
glEndQuery(GL_ANY_SAMPLES_PASSED);
glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE);
++idx;
}
for (const Light& light : m_lights)
{
if (!frustum.pointFrustumTest(light.point))
{
++idx;
continue;
}
glBindVertexArray(light.vao);
m_queryBools[idx] = true;
glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]);
glDrawArrays(GL_POINTS, 0, 1);
glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE);
++idx;
}
idx = m_models.size();
for (const Entity& ent : m_entities)
{
if (m_queryBools[idx])
{
GLint res;
glGetQueryObjectiv(m_query, GL_QUERY_RESULT, &res);
glGetQueryObjectiv(m_queries[idx], GL_QUERY_RESULT, &res);
if (res)
passFunc(idx);
}
++idx;
}
int lightIdx = 0;
for (const Light& light : m_lights)
{
if (!frustum.pointFrustumTest(light.point))
if (m_queryBools[idx])
{
++lightIdx;
continue;
}
glBindVertexArray(light.vao);
glBeginQuery(GL_ANY_SAMPLES_PASSED, m_query);
glDrawArrays(GL_POINTS, 0, 1);
glEndQuery(GL_ANY_SAMPLES_PASSED);
GLint res;
glGetQueryObjectiv(m_query, GL_QUERY_RESULT, &res);
glGetQueryObjectiv(m_queries[idx], GL_QUERY_RESULT, &res);
EPVSVisSetState state = m_totalAABB.pointInside(light.point) ?
EPVSVisSetState::EndOfTree : EPVSVisSetState::OutOfBounds;
if (res && state == EPVSVisSetState::EndOfTree)
state = EPVSVisSetState::NodeFound;
lightPassFunc(lightIdx, state);
}
++lightIdx;
++idx;
}
}
}

View File

@ -78,7 +78,9 @@ class VISIRenderer
std::vector<Light> m_lights;
bool SetupVertexBuffersAndFormats();
GLuint m_query;
size_t m_queryCount;
std::unique_ptr<GLuint[]> m_queries;
std::unique_ptr<bool[]> m_queryBools;
FPercent m_updatePercent;