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 struct MaterialPool
{ {
std::vector<const Mesh::Material*> materials; 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; size_t ret = 0;
newMat = false;
for (const Mesh::Material* testMat : materials) for (const Mesh::Material* testMat : materials)
{ {
if (mat == *testMat) if (mat == *testMat)
@ -1674,6 +1675,7 @@ bool WriteHMDLMREASecs(std::vector<std::vector<uint8_t>>& secsOut, const hecl::P
++ret; ++ret;
} }
materials.push_back(&mat); materials.push_back(&mat);
newMat = true;
return ret; return ret;
} }
} matPool; } 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]) 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); meshToGlobalMats.push_back(idx);
if (idx < matPool.materials.size() - 1) if (!newMat)
continue; continue;
for (const hecl::ProjectPath& path : mat.texs) 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 */ /* Iterate meshes */
auto matIt = surfToGlobalMats.cbegin(); auto matIt = surfToGlobalMats.cbegin();
int meshIdx = 0;
for (const Mesh& mesh : meshes) for (const Mesh& mesh : meshes)
{ {
zeus::CTransform meshXf(mesh.sceneXf.val); 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteCRSM<UniqueID32>(const CRSM<UniqueID32>& crsm, const hecl::ProjectPath& outPath); 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteDGRP<UniqueID32>(const DGRP<UniqueID32>& dgrp, const hecl::ProjectPath& outPath); 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 size_t binarySize(size_t __isz) const
{return __isz + 4;} {return __isz + 16;}
}; };
using FourCC = hecl::FourCC; 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteDPSM<UniqueID32>(const DPSM<UniqueID32>& dpsm, const hecl::ProjectPath& outPath); 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteELSM<UniqueID32>(const ELSM<UniqueID32>& gpsm, const hecl::ProjectPath& outPath); 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteFONT<UniqueID32>(const FONT<UniqueID32>& font, const hecl::ProjectPath& outPath); 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteFSM2<UniqueID32>(const FSM2<UniqueID32>& fsm2, const hecl::ProjectPath& outPath); 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.right.reset();
n.isLeaf = true; n.isLeaf = true;
n.leafData = std::make_unique<typename Node::LeafData>(); n.leafData = std::make_unique<typename Node::LeafData>();
n.leafData->edgeIndexCount = atUint32(index.size() * 3); n.leafData->triangleIndexCount = atUint32(index.size());
n.leafData->edgeIndices.reserve(n.leafData->edgeIndexCount); n.leafData->triangleIndices.reserve(n.leafData->triangleIndexCount);
for (int i : index) for (int i : index)
{ n.leafData->triangleIndices.push_back(i);
const ColMesh::Triangle& T = mesh.trianges[i];
for (int j = 0; j < 3; ++j)
n.leafData->edgeIndices.push_back(T.edges[j]);
}
} }
template <typename Node> 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteGPSM<UniqueID32>(const GPSM<UniqueID32>& gpsm, const hecl::ProjectPath& outPath); 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteSWSH<UniqueID32>(const SWSH<UniqueID32>& swsh, const hecl::ProjectPath& outPath); 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; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }

View File

@ -660,7 +660,7 @@ bool WriteWPSM(const WPSM<IDType>& wpsm, const hecl::ProjectPath& outPath)
int64_t rem = w.position() % 32; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }
template bool WriteWPSM<UniqueID32>(const WPSM<UniqueID32>& wpsm, const hecl::ProjectPath& outPath); 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()) if (bone->children.size())
{ {
int curId = 4; 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(); bones.emplace_back();

View File

@ -53,9 +53,9 @@ struct DCLN : BigDNA
struct LeafData : BigDNA struct LeafData : BigDNA
{ {
DECL_DNA DECL_DNA
Value<atUint32> edgeIndexCount; Value<atUint32> triangleIndexCount;
Vector<atUint16, DNA_COUNT(edgeIndexCount)> edgeIndices; Vector<atUint16, DNA_COUNT(triangleIndexCount)> triangleIndices;
size_t getMemoryUsage() const { return (((edgeIndices.size() * 2) + 16) + 3) & ~3; } size_t getMemoryUsage() const { return (((triangleIndices.size() * 2) + 16) + 3) & ~3; }
}; };
Value<atVec4f> xf[3]; Value<atVec4f> xf[3];
@ -234,6 +234,10 @@ struct DCLN : BigDNA
athena::io::FileWriter w(outPath.getAbsolutePath()); athena::io::FileWriter w(outPath.getAbsolutePath());
dcln.write(w); 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; return true;
} }
}; };

View File

@ -1,3 +1,5 @@
#include <hecl/ClientProcess.hpp>
#include <athena/MemoryReader.hpp>
#include "MREA.hpp" #include "MREA.hpp"
#include "SCLY.hpp" #include "SCLY.hpp"
#include "PATH.hpp" #include "PATH.hpp"
@ -167,8 +169,17 @@ bool MREA::Extract(const SpecBase& dataSpec,
rs.seek(secStart + head.secSizes[curSec++], athena::Begin); rs.seek(secStart + head.secSizes[curSec++], athena::Begin);
/* Dump VISI entities */ /* Dump VISI entities */
secStart = rs.position();
if (head.secSizes[curSec] && rs.readUint32Big() == 'VISI') 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"); athena::io::YAMLDocWriter visiWriter("VISI");
if (auto __vec = visiWriter.enterSubVector("entities")) if (auto __vec = visiWriter.enterSubVector("entities"))
{ {
@ -447,79 +458,121 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
if (auto __vec = r.enterSubVector("entities", entityCount)) if (auto __vec = r.enterSubVector("entities", entityCount))
{ {
entities.reserve(entityCount); entities.reserve(entityCount);
uint16_t entityId = r.readUint16(nullptr); for (size_t i=0 ; i<entityCount ; ++i)
for (const SCLY::ScriptLayer& layer : sclyData.layers)
{ {
for (const std::unique_ptr<IScriptObject>& obj : layer.objects) uint16_t entityId = r.readUint16(nullptr);
for (const SCLY::ScriptLayer& layer : sclyData.layers)
{ {
if ((obj->id & 0xffff) == entityId) for (const std::unique_ptr<IScriptObject>& obj : layer.objects)
{ {
zeus::CAABox entAABB = obj->getVISIAABB(btok); if ((obj->id & 0xffff) == entityId)
if (entAABB.min.x < entAABB.max.x) {
entities.emplace_back(entityId, entAABB); zeus::CAABox entAABB = obj->getVISIAABB(btok);
if (!entAABB.invalid())
entities.emplace_back(entityId, entAABB);
}
} }
} }
} }
} }
hecl::ProjectPath visiIntOut = outPath.getWithExtension(_S(".visiint")); // Check if pre-generated visi exists, recycle if able
hecl::ProjectPath visiIn = outPath.getWithExtension(_S(".visi")); hecl::ProjectPath preVisiPath = inPath.getWithExtension(_S(".visi"), true);
athena::io::FileWriter w(visiIntOut.getAbsolutePath()); if (preVisiPath.getPathType() == hecl::ProjectPath::Type::File)
w.writeUint32Big(meshes.size());
for (const DNACMDL::Mesh& mesh : meshes)
{ {
w.writeUint32Big(uint32_t(mesh.topology)); athena::io::FileReader preVisiReader(preVisiPath.getAbsolutePath());
atUint64 preVisiLen = preVisiReader.length();
w.writeUint32Big(mesh.pos.size()); if (preVisiLen > 26)
for (const auto& v : mesh.pos)
{ {
atVec3f xfPos = hecl::BlenderConnection::DataStream::MtxVecMul4RM(mesh.sceneXf, v); auto preVisiData = preVisiReader.readUBytes(preVisiLen);
w.writeVec3fBig(xfPos); athena::io::MemoryReader preVisiDataReader(preVisiData.get(), preVisiLen);
}
w.writeUint32Big(mesh.surfaces.size()); atUint32 preVisiFourCC = preVisiDataReader.readUint32Big();
for (const DNACMDL::Mesh::Surface& surf : mesh.surfaces) atUint32 preVisiVersion = preVisiDataReader.readUint32Big();
{ preVisiDataReader.readBool();
w.writeUint32Big(surf.verts.size()); preVisiDataReader.readBool();
for (const DNACMDL::Mesh::Surface::Vert& vert : surf.verts) atUint32 preFeatureCount = preVisiDataReader.readUint32Big();
w.writeUint32Big(vert.iPos); atUint32 preLightsCount = preVisiDataReader.readUint32Big();
const DNACMDL::Mesh::Material& mat = mesh.materialSets[0][surf.materialIdx]; atUint32 preLayer2LightCount = preVisiDataReader.readUint32Big();
w.writeBool(mat.transparent); 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;
}
} }
} }
w.writeUint32Big(entities.size()); if (!visiGood)
for (const auto& ent : entities)
{ {
w.writeUint32Big(ent.first); hecl::ProjectPath visiIntOut = outPath.getWithExtension(_S(".visiint"));
w.writeVec3fBig(ent.second.min); hecl::ProjectPath visiIn = inPath.getWithExtension(_S(".visi"));
w.writeVec3fBig(ent.second.max); athena::io::FileWriter w(visiIntOut.getAbsolutePath());
} w.writeUint32Big(meshes.size());
for (const DNACMDL::Mesh& mesh : meshes)
{
w.writeUint32Big(uint32_t(mesh.topology));
w.writeUint32Big(lightsVisi[0].size() + lightsVisi[1].size()); w.writeUint32Big(mesh.pos.size());
w.writeUint32Big(lightsVisi[1].size()); for (const auto& v : mesh.pos)
for (const auto& light : lightsVisi[1]) {
w.writeVec3fBig(light); atVec3f xfPos = hecl::BlenderConnection::DataStream::MtxVecMul4RM(mesh.sceneXf, v);
for (const auto& light : lightsVisi[0]) w.writeVec3fBig(xfPos);
w.writeVec3fBig(light); }
w.close(); w.writeUint32Big(mesh.surfaces.size());
for (const DNACMDL::Mesh::Surface& surf : mesh.surfaces)
{
w.writeUint32Big(surf.verts.size());
for (const DNACMDL::Mesh::Surface::Vert& vert : surf.verts)
w.writeUint32Big(vert.iPos);
const DNACMDL::Mesh::Material& mat = mesh.materialSets[0][surf.materialIdx];
w.writeBool(mat.transparent);
}
}
hecl::SystemString VisiGenPath = ExeDir + _S("/visigen"); w.writeUint32Big(entities.size());
for (const auto& ent : entities)
{
w.writeUint32Big(ent.first);
w.writeVec3fBig(ent.second.min);
w.writeVec3fBig(ent.second.max);
}
w.writeUint32Big(lightsVisi[0].size() + lightsVisi[1].size());
w.writeUint32Big(lightsVisi[1].size());
for (const auto& light : lightsVisi[1])
w.writeVec3fBig(light);
for (const auto& light : lightsVisi[0])
w.writeVec3fBig(light);
w.close();
hecl::SystemString VisiGenPath = ExeDir + _S("/visigen");
#if _WIN32 #if _WIN32
VisiGenPath += _S(".exe"); VisiGenPath += _S(".exe");
#endif #endif
const hecl::SystemChar* args[] = {VisiGenPath.c_str(), char thrIdx[16];
visiIntOut.getAbsolutePath().c_str(), snprintf(thrIdx, 16, "%d", hecl::ClientProcess::GetThreadWorkerIdx());
visiIn.getAbsolutePath().c_str(), const hecl::SystemChar* args[] = {VisiGenPath.c_str(),
nullptr}; visiIntOut.getAbsolutePath().c_str(),
if (0 == hecl::RunProcess(VisiGenPath.c_str(), args)) visiIn.getAbsolutePath().c_str(),
{ thrIdx,
athena::io::FileReader r(visiIn.getAbsolutePath()); nullptr};
size_t length = r.length(); if (0 == hecl::RunProcess(VisiGenPath.c_str(), args))
secs.emplace_back(length, 0); {
r.readBytesToBuf(secs.back().data(), length); athena::io::FileReader r(visiIn.getAbsolutePath());
visiGood = true; size_t length = r.length();
secs.emplace_back(length, 0);
r.readBytesToBuf(secs.back().data(), length);
visiGood = true;
}
} }
} }
} }
@ -578,7 +631,7 @@ bool MREA::CookPath(const hecl::ProjectPath& outPath,
int64_t rem = w.position() % 32; int64_t rem = w.position() % 32;
if (rem) if (rem)
for (int64_t i=0 ; i<32-rem ; ++i) for (int64_t i=0 ; i<32-rem ; ++i)
w.writeBytes((atInt8*)"\xff", 1); w.writeUByte(0xff);
return true; return true;
} }

View File

@ -133,7 +133,26 @@ makeProj:
m_mainMP1.emplace(m_factoryMP1, m_objStore, m_vm.m_mainBooFactory, m_mainMP1.emplace(m_factoryMP1, m_objStore, m_vm.m_mainBooFactory,
m_vm.m_mainCommandQueue, m_vm.m_renderTex); m_vm.m_mainCommandQueue, m_vm.m_renderTex);
m_vm.InitMP1(*m_mainMP1); 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) if (needsSave)
saveProject(); saveProject();
@ -182,6 +201,14 @@ bool ProjectManager::saveProject()
void ProjectManager::mainUpdate() void ProjectManager::mainUpdate()
{ {
if (m_precooking)
{
if (!m_factoryMP1.IsBusy())
m_precooking = false;
else
return;
}
if (m_mainMP1) if (m_mainMP1)
{ {
if (m_mainMP1->Proc()) if (m_mainMP1->Proc())
@ -194,6 +221,9 @@ void ProjectManager::mainUpdate()
void ProjectManager::mainDraw() void ProjectManager::mainDraw()
{ {
if (m_precooking)
return;
if (m_mainMP1) if (m_mainMP1)
m_mainMP1->Draw(); m_mainMP1->Draw();
} }

View File

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

View File

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

View File

@ -25,8 +25,11 @@ using YAMLNode = athena::io::YAMLNode;
namespace urde 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_testGameView.reset(new TestGameView(*this, m_viewResources, *m_rootView));
m_rootView->accessContentViews().clear(); m_rootView->accessContentViews().clear();
@ -34,12 +37,6 @@ void ViewManager::BuildTestPART()
m_rootView->updateSize(); 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) void ViewManager::TestGameView::resized(const boo::SWindowRect& root, const boo::SWindowRect& sub)
{ {
specter::View::resized(root, 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) void ViewManager::TestGameView::draw(boo::IGraphicsCommandQueue* gfxQ)
{ {
gfxQ->clearTarget(true, true);
m_vm.m_projManager.mainDraw(); m_vm.m_projManager.mainDraw();
} }

View File

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

View File

@ -28,7 +28,7 @@ void CMapArea::PostConstruct()
{ {
x38_moStart = x44_buf.get(); x38_moStart = x44_buf.get();
x3c_vertexStart = x38_moStart + (x28_mappableObjCount * 0x50); 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); m_mappableObjects.reserve(x28_mappableObjCount);
for (u32 i = 0, j=0 ; i<x28_mappableObjCount ; ++i, j += 0x50) 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) CMapUniverse::CMapUniverse(CInputStream& in, u32 version)
: x0_hexagonId(in.readUint32Big()) : 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(); u32 count = in.readUint32Big();
x10_worldDatas.reserve(count); x10_worldDatas.reserve(count);
for (u32 i = 0 ; i<count ; ++i) for (u32 i = 0 ; i<count ; ++i)

View File

@ -78,7 +78,7 @@ public:
void Lock() { x0_area.Lock(); } void Lock() { x0_area.Lock(); }
void Unlock() { x0_area.Unlock(); } void Unlock() { x0_area.Unlock(); }
bool IsLoaded() const { return x0_area.IsLoaded(); } 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; } const CMapAreaData* GetNextMapAreaData() const { return x14_next; }
EMapAreaList GetContainingList() const { return x10_list; } EMapAreaList GetContainingList() const { return x10_list; }
CMapAreaData* NextMapAreaData() { return x14_next; } CMapAreaData* NextMapAreaData() { return x14_next; }

View File

@ -127,6 +127,8 @@ IObj* CToken::GetObj()
} }
CToken& CToken::operator=(const CToken& other) CToken& CToken::operator=(const CToken& other)
{ {
Unlock();
RemoveRef();
x0_objRef = other.x0_objRef; x0_objRef = other.x0_objRef;
if (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 tf1 = lT;
float tf2 = hT; float tf2 = hT;
if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2)) 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 false;
} }
return true; return true;
@ -201,7 +201,7 @@ bool CAreaOctTree::Node::LineTestInternal(const zeus::CLine& line, const CMateri
{ {
Node child = GetChild(r26b); Node child = GetChild(r26b);
if (child.x20_nodeType != ETreeType::Invalid) 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; return false;
} }
if (i < idx.first) if (i < idx.first)
@ -306,7 +306,7 @@ void CAreaOctTree::Node::LineTestExInternal(const zeus::CLine& line, const CMate
float tf1 = lT; float tf1 = lT;
float tf2 = hT; float tf2 = hT;
if (BoxLineTest(child.GetBoundingBox(), line, tf1, tf2)) 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) 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) if (i >= 0)
selector ^= 1 << r19[i]; 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) if (hiT > lowT && loT <= hiT)
{ {
Node child = GetChild(selector); Node child = GetChild(selector);
if (child.x20_nodeType != ETreeType::Invalid) 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.x10_surface)
if (res.x3c_t > highT) if (res.x3c_t > highT)
res = SRayResult(); res = SRayResult();

View File

@ -5,6 +5,7 @@
#include "RetroTypes.hpp" #include "RetroTypes.hpp"
#include "zeus/CTransform.hpp" #include "zeus/CTransform.hpp"
#include "zeus/CAABox.hpp" #include "zeus/CAABox.hpp"
#include "hecl/Runtime.hpp"
namespace urde namespace urde
{ {
@ -21,9 +22,21 @@ class CMetroidModelInstance
zeus::CAABox x34_aabb; zeus::CAABox x34_aabb;
std::vector<CBooSurface> m_surfaces; std::vector<CBooSurface> m_surfaces;
std::unique_ptr<CBooModel> m_instance; std::unique_ptr<CBooModel> m_instance;
hecl::HMDLMeta m_hmdlMeta;
std::vector<std::shared_ptr<hecl::Runtime::ShaderPipelines>> m_shaders;
public: public:
CMetroidModelInstance() = default; CMetroidModelInstance() = default;
CMetroidModelInstance(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; int m_matSetIdx;
SShader(int idx) : m_matSetIdx(idx) {} SShader(int idx) : m_matSetIdx(idx) {}
void UnlockTextures(); 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 enum class ESurfaceSelection
@ -101,7 +106,8 @@ private:
CBooModel* m_next = nullptr; CBooModel* m_next = nullptr;
CBooModel* m_prev = nullptr; CBooModel* m_prev = nullptr;
size_t m_uniUpdateCount = 0; size_t m_uniUpdateCount = 0;
TLockedToken<CModel> m_model; TToken<CModel> m_modelTok;
CModel* m_model;
std::vector<CBooSurface>* x0_surfaces; std::vector<CBooSurface>* x0_surfaces;
const MaterialSet* x4_matSet; const MaterialSet* x4_matSet;
int m_matSetIdx = -1; int m_matSetIdx = -1;
@ -161,9 +167,11 @@ private:
static float g_TransformedTime2; static float g_TransformedTime2;
static CBooModel* g_LastModelCached; static CBooModel* g_LastModelCached;
static bool g_DummyTextures;
public: public:
~CBooModel(); ~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, boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo,
const zeus::CAABox& aabb, u8 renderMask, const zeus::CAABox& aabb, u8 renderMask,
int numInsts, boo::ITexture* txtrOverrides[8]); int numInsts, boo::ITexture* txtrOverrides[8]);
@ -178,6 +186,8 @@ public:
void ActivateLights(const std::vector<CLight>& lights); void ActivateLights(const std::vector<CLight>& lights);
void DisableAllLights(); void DisableAllLights();
void RemapMaterialData(SShader& shader); void RemapMaterialData(SShader& shader);
void RemapMaterialData(SShader& shader,
const std::vector<std::shared_ptr<hecl::Runtime::ShaderPipelines>>& pipelines);
bool TryLockTextures() const; bool TryLockTextures() const;
void UnlockTextures() const; void UnlockTextures() const;
void SyncLoadTextures() const; void SyncLoadTextures() const;
@ -197,6 +207,9 @@ public:
const CPoseAsTransforms* pose) const; const CPoseAsTransforms* pose) const;
void DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) 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 const MaterialSet::Material& GetMaterialByIndex(int idx) const
{ {
@ -220,6 +233,8 @@ public:
static zeus::CTransform g_shadowTexXf; static zeus::CTransform g_shadowTexXf;
static void EnableShadowMaps(boo::ITexture* map, const zeus::CTransform& texXf); static void EnableShadowMaps(boo::ITexture* map, const zeus::CTransform& texXf);
static void DisableShadowMaps(); static void DisableShadowMaps();
static void SetDummyTextures(bool b) { g_DummyTextures = true; }
}; };
class CModel class CModel
@ -258,7 +273,9 @@ public:
const zeus::CAABox& GetAABB() const {return m_aabb;} const zeus::CAABox& GetAABB() const {return m_aabb;}
CBooModel& GetInstance() {return *x28_modelInst;} CBooModel& GetInstance() {return *x28_modelInst;}
const CBooModel& GetInstance() const {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(); } void UpdateLastFrame() const { const_cast<CModel&>(*this).x38_lastFrame = CGraphics::GetFrameCounter(); }
size_t GetPoolVertexOffset(size_t idx) const; size_t GetPoolVertexOffset(size_t idx) const;

View File

@ -46,6 +46,8 @@ void CBooModel::KillCachedViewDepState()
g_LastModelCached = nullptr; g_LastModelCached = nullptr;
} }
bool CBooModel::g_DummyTextures = false;
zeus::CVector3f CBooModel::g_ReflectViewPos = {}; zeus::CVector3f CBooModel::g_ReflectViewPos = {};
static const zeus::CMatrix4f ReflectBaseMtx = static const zeus::CMatrix4f ReflectBaseMtx =
@ -146,13 +148,13 @@ CBooModel::~CBooModel()
g_FirstModel = m_next; 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, boo::IVertexFormat* vtxFmt, boo::IGraphicsBufferS* vbo, boo::IGraphicsBufferS* ibo,
const zeus::CAABox& aabb, u8 renderMask, const zeus::CAABox& aabb, u8 renderMask,
int numInsts, boo::ITexture* txtrOverrides[8]) int numInsts, boo::ITexture* txtrOverrides[8])
: m_model(token), x0_surfaces(surfaces), x4_matSet(&shader.m_matSet), m_matSetIdx(shader.m_matSetIdx), : m_modelTok(token), m_model(parent), x0_surfaces(surfaces), x4_matSet(&shader.m_matSet),
m_pipelines(&shader.m_shaders), x1c_textures(shader.x0_textures), x20_aabb(aabb), m_matSetIdx(shader.m_matSetIdx), m_pipelines(&shader.m_shaders), x1c_textures(shader.x0_textures),
x40_24_texturesLoaded(false), x40_25_modelVisible(0), x41_mask(renderMask), x20_aabb(aabb), x40_24_texturesLoaded(false), x40_25_modelVisible(0), x41_mask(renderMask),
m_staticVtxFmt(vtxFmt), m_staticVbo(vbo), m_staticIbo(ibo) m_staticVtxFmt(vtxFmt), m_staticVbo(vbo), m_staticIbo(ibo)
{ {
if (txtrOverrides) if (txtrOverrides)
@ -224,7 +226,7 @@ boo::IVertexFormat* CBooModel::ModelInstance::GetBooVtxFmt(const CBooModel& mode
CBooModel::ModelInstance* CBooModel::PushNewModelInstance() CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
{ {
if (!x40_24_texturesLoaded) if (!x40_24_texturesLoaded && !g_DummyTextures)
return nullptr; return nullptr;
if (m_instances.size() >= 256) if (m_instances.size() >= 256)
@ -233,7 +235,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
ModelInstance& newInst = m_instances.back(); ModelInstance& newInst = m_instances.back();
size_t skinBankCount = 0; size_t skinBankCount = 0;
size_t weightVecCount = 0; size_t weightVecCount = 0;
if (const CModel* model = m_model.GetObj()) if (const CModel* model = m_model)
{ {
skinBankCount = model->m_hmdlMeta.bankCount; skinBankCount = model->m_hmdlMeta.bankCount;
weightVecCount = model->m_hmdlMeta.weightCount; weightVecCount = model->m_hmdlMeta.weightCount;
@ -276,6 +278,7 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance()
} }
/* Animated UV transform matrices */ /* Animated UV transform matrices */
size_t matCount = x4_matSet->materials.size();
for (const MaterialSet::Material& mat : x4_matSet->materials) for (const MaterialSet::Material& mat : x4_matSet->materials)
{ {
size_t thisSz = ROUND_UP_256(/*mat.uvAnims.size()*/ 8 * (sizeof(zeus::CMatrix4f) * 2)); 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; texs[texCount++] = overtex;
} }
else if (g_DummyTextures)
{
texs[texCount++] = g_Renderer->x220_sphereRamp;
}
else else
{ {
TCachedToken<CTexture>& tex = x1c_textures[idx]; TCachedToken<CTexture>& tex = x1c_textures[idx];
@ -472,6 +479,17 @@ void CBooModel::RemapMaterialData(SShader& shader)
m_instances.clear(); 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 bool CBooModel::TryLockTextures() const
{ {
if (!x40_24_texturesLoaded) if (!x40_24_texturesLoaded)
@ -614,13 +632,10 @@ void CBooModel::WarmupDrawSurface(const CBooSurface& surf) const
return; return;
const ModelInstance& inst = m_instances[m_uniUpdateCount-1]; const ModelInstance& inst = m_instances[m_uniUpdateCount-1];
for (const std::vector<boo::IShaderDataBinding*>& extendeds : inst.m_shaderDataBindings) for (boo::IShaderDataBinding* binding : inst.m_shaderDataBindings[surf.selfIdx])
{ {
for (boo::IShaderDataBinding* binding : extendeds) CGraphics::SetShaderDataBinding(binding);
{ CGraphics::DrawArrayIndexed(surf.m_data.idxStart, std::min(u32(3), surf.m_data.idxCount));
CGraphics::SetShaderDataBinding(binding);
CGraphics::DrawArrayIndexed(surf.m_data.idxStart, std::min(u32(3), surf.m_data.idxCount));
}
} }
} }
@ -816,7 +831,7 @@ boo::IGraphicsBufferD* CBooModel::UpdateUniformData(const CModelFlags& flags,
{ {
size_t skinBankCount = 0; size_t skinBankCount = 0;
size_t weightVecCount = 0; size_t weightVecCount = 0;
if (const CModel* model = m_model.GetObj()) if (const CModel* model = m_model)
{ {
skinBankCount = model->m_hmdlMeta.bankCount; skinBankCount = model->m_hmdlMeta.bankCount;
weightVecCount = model->m_hmdlMeta.weightCount; weightVecCount = model->m_hmdlMeta.weightCount;
@ -1024,13 +1039,44 @@ static const u8* MemoryFromPartData(const u8*& dataCur, const u32*& secSizeCur)
return ret; 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()) if (shaderIdx >= x18_matSets.size())
shaderIdx = 0; 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_staticVtxFmt, m_staticVbo, m_ibo,
m_aabb, (m_flags & 0x2) != 0, subInsts, txtrOverrides); 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) 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); const u8* surfInfo = MemoryFromPartData(dataCur, secSizeCur);
for (CBooModel::SShader& matSet : x18_matSets) for (CBooModel::SShader& matSet : x18_matSets)
{ matSet.BuildShaders(m_hmdlMeta);
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));
}
}
m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool 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); 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]), 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])); 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() void CBooModel::SShader::UnlockTextures()
@ -1228,6 +1256,7 @@ void CModel::ApplyVerticesCPU(boo::IGraphicsBufferD* vertBuf,
void CModel::_WarmupShaders() void CModel::_WarmupShaders()
{ {
CBooModel::SetDummyTextures(true);
CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp, zeus::CTransform::Identity()); CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp, zeus::CTransform::Identity());
CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState();
zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix; zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix;
@ -1239,7 +1268,6 @@ void CModel::_WarmupShaders()
for (CBooModel::SShader& shader : x18_matSets) for (CBooModel::SShader& shader : x18_matSets)
{ {
GetInstance().RemapMaterialData(shader); GetInstance().RemapMaterialData(shader);
GetInstance().SyncLoadTextures();
GetInstance().UpdateUniformData(defaultFlags, nullptr, nullptr); GetInstance().UpdateUniformData(defaultFlags, nullptr, nullptr);
GetInstance().WarmupDrawSurfaces(); GetInstance().WarmupDrawSurfaces();
} }
@ -1247,6 +1275,7 @@ void CModel::_WarmupShaders()
CGraphics::SetViewPointMatrix(backupViewPoint); CGraphics::SetViewPointMatrix(backupViewPoint);
CGraphics::SetModelMatrix(backupModel); CGraphics::SetModelMatrix(backupModel);
CBooModel::DisableShadowMaps(); CBooModel::DisableShadowMaps();
CBooModel::SetDummyTextures(false);
} }
void CModel::WarmupShaders(const SObjectTag& cmdlTag) void CModel::WarmupShaders(const SObjectTag& cmdlTag)

View File

@ -28,7 +28,7 @@ static const char* VS =
"{\n" "{\n"
" VertToFrag vtf;\n" " VertToFrag vtf;\n"
" vtf.color = bu.color;\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" " return vtf;\n"
"}\n"; "}\n";

View File

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

View File

@ -248,15 +248,7 @@ CModelShaders::GetShaderExtensionsGLSL(boo::IGraphicsDataFactory::Platform plat)
hecl::Backend::BlendFactor::SrcAlpha, hecl::Backend::BlendFactor::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
hecl::Backend::ZTest::Equal, hecl::Backend::ZTest::Equal,
false, false, false, true); false, false, false, true, 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);
/* World shadow shading (modified lighting) */ /* World shadow shading (modified lighting) */
ext.registerExtensionSlot({LightingShadowGLSL, "LightingShadowFunc"}, {MainPostGLSL, "MainPostFunc"}, 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::SrcAlpha,
hecl::Backend::BlendFactor::InvSrcAlpha, hecl::Backend::BlendFactor::InvSrcAlpha,
hecl::Backend::ZTest::Equal, hecl::Backend::ZTest::Equal,
false, false, false, true); false, false, false, true, true);
/* World shadow shading (modified lighting) */ /* World shadow shading (modified lighting) */
ext.registerExtensionSlot({LightingShadowHLSL, "LightingShadowFunc"}, {MainPostHLSL, "MainPostFunc"}, ext.registerExtensionSlot({LightingShadowHLSL, "LightingShadowFunc"}, {MainPostHLSL, "MainPostFunc"},

View File

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

View File

@ -73,7 +73,7 @@ struct OGLParticleSwooshDataBindingFactory : TShader<CParticleSwooshShaders>::ID
CSwooshDescription* desc = gen.GetDesc(); CSwooshDescription* desc = gen.GetDesc();
CUVElement* texr = desc->x3c_TEXR.get(); 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[] = const boo::VertexElementDescriptor VtxFmt[] =
{ {

View File

@ -71,7 +71,7 @@ struct D3DParticleSwooshDataBindingFactory : TShader<CParticleSwooshShaders>::ID
CSwooshDescription* desc = gen.GetDesc(); CSwooshDescription* desc = gen.GetDesc();
CUVElement* texr = desc->x3c_TEXR.get(); 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}; boo::IGraphicsBuffer* uniforms[] = {gen.m_uniformBuf};
gen.m_dataBind = ctx.newShaderDataBinding(shaders.m_pipeline, CParticleSwooshShaders::m_vtxFormat, 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(); CSwooshDescription* desc = gen.GetDesc();
CUVElement* texr = desc->x3c_TEXR.get(); 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}; boo::IGraphicsBuffer* uniforms[] = {gen.m_uniformBuf};
gen.m_dataBind = ctx.newShaderDataBinding(shaders.m_pipeline, CParticleSwooshShaders::m_vtxFormat, 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" "vertex VertToFrag vmain(VertData v [[ stage_in ]], constant PhazonSuitBlurUniform& psu [[ buffer(2) ]])\n"
"{\n" "{\n"
" VertToFrag vtf;\n" " VertToFrag vtf;\n"
" vtf.uv = uvIn.xy;\n" " vtf.uv = v.uvIn.xy;\n"
" vtf.blurDir = blurDir.xy;\n" " vtf.blurDir = psu.blurDir.xy;\n"
" vtf.position = float4(posIn.xyz, 1.0);\n" " vtf.position = float4(v.posIn.xyz, 1.0);\n"
" return vtf;\n" " return vtf;\n"
"}\n"; "}\n";

View File

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

View File

@ -243,6 +243,7 @@ private:
// Warmup state // Warmup state
std::vector<SObjectTag> m_warmupTags; std::vector<SObjectTag> m_warmupTags;
std::vector<SObjectTag>::iterator m_warmupIt; std::vector<SObjectTag>::iterator m_warmupIt;
bool m_needsWarmupClear = false;
void InitializeSubsystems(const hecl::Runtime::FileStoreManager& storeMgr); void InitializeSubsystems(const hecl::Runtime::FileStoreManager& storeMgr);
@ -269,20 +270,7 @@ public:
void Shutdown(); void Shutdown();
boo::IWindow* GetMainWindow() const; boo::IWindow* GetMainWindow() const;
void MemoryCardInitializePump() 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();
}
}
}
bool CheckReset() { return false; } bool CheckReset() { return false; }
bool CheckTerminate() { return false; } bool CheckTerminate() { return false; }

View File

@ -168,13 +168,13 @@ namespace urde
{ {
template <class T> 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> template <class T>
TCastToPtr<T>::TCastToPtr(CEntity& p) { p.Accept(*this); } TCastToPtr<T>::TCastToPtr(CEntity& p) { p.Accept(*this); }
template <class T> 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> template <class T>
TCastToPtr<T>& TCastToPtr<T>::operator=(CEntity& p) { p.Accept(*this); return *this; } 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) CGameArea::CGameArea(CAssetId mreaId)
: x84_mrea(mreaId) : x84_mrea(mreaId)
{ {
while (StartStreamingMainArea()) {} while (StartStreamingMainArea())
for (auto& req : xf8_loadTransactions)
for (auto& req : xf8_loadTransactions) req->WaitForComplete();
req->WaitForComplete();
MREAHeader header = VerifyHeader(); 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()); CBooModel::EnableShadowMaps(g_Renderer->x220_sphereRamp, zeus::CTransform::Identity());
CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState(); CGraphics::CProjectionState backupProj = CGraphics::GetProjectionState();
zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix; zeus::CTransform backupViewPoint = CGraphics::g_ViewMatrix;
@ -434,7 +434,6 @@ CGameArea::CGameArea(CAssetId mreaId)
for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts)
{ {
CGraphics::SetModelMatrix(zeus::CTransform::Translate(-inst.x34_aabb.center())); CGraphics::SetModelMatrix(zeus::CTransform::Translate(-inst.x34_aabb.center()));
inst.m_instance->SyncLoadTextures();
inst.m_instance->UpdateUniformData(defaultFlags, nullptr, nullptr); inst.m_instance->UpdateUniformData(defaultFlags, nullptr, nullptr);
inst.m_instance->WarmupDrawSurfaces(); inst.m_instance->WarmupDrawSurfaces();
} }
@ -442,6 +441,7 @@ CGameArea::CGameArea(CAssetId mreaId)
CGraphics::SetViewPointMatrix(backupViewPoint); CGraphics::SetViewPointMatrix(backupViewPoint);
CGraphics::SetModelMatrix(backupModel); CGraphics::SetModelMatrix(backupModel);
CBooModel::DisableShadowMaps(); CBooModel::DisableShadowMaps();
CBooModel::SetDummyTextures(false);
} }
bool CGameArea::IGetScriptingMemoryAlways() const bool CGameArea::IGetScriptingMemoryAlways() const
@ -932,7 +932,7 @@ void CGameArea::PostConstructArea()
u32 sec = 3; u32 sec = 3;
/* Models */ /* Models */
x12c_postConstructed->x4c_insts.reserve(header.modelCount); x12c_postConstructed->x4c_insts.resize(header.modelCount);
for (u32 i=0 ; i<header.modelCount ; ++i) for (u32 i=0 ; i<header.modelCount ; ++i)
{ {
u32 surfCount = hecl::SBig(*reinterpret_cast<const u32*>((secIt+4)->first)); 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 */ /* Materials */
CBooModel::SShader& matSet = x12c_postConstructed->m_materialSet;
auto secIt = m_resolvedBufs.begin() + 2; auto secIt = m_resolvedBufs.begin() + 2;
{ {
athena::io::MemoryReader r(secIt->first, secIt->second); 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; ++secIt;
} }
x12c_postConstructed->m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool x12c_postConstructed->m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool
{ {
/* Models */ /* 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; DataSpec::DNAMP1::MREA::MeshHeader header;
athena::io::MemoryReader r(secIt->first, secIt->second); athena::io::MemoryReader r(secIt->first, secIt->second);
@ -1081,30 +1083,31 @@ void CGameArea::FillInStaticGeometry()
++secIt; ++secIt;
} }
hecl::HMDLMeta hmdlMeta;
{ {
athena::io::MemoryReader r(secIt->first, secIt->second); athena::io::MemoryReader r(secIt->first, secIt->second);
hmdlMeta.read(r); inst.m_hmdlMeta.read(r);
} }
++secIt; ++secIt;
boo::IGraphicsBufferS* vbo; boo::IGraphicsBufferS* vbo;
boo::IGraphicsBufferS* ibo; boo::IGraphicsBufferS* ibo;
boo::IVertexFormat* vtxFmt; 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; ++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; ++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)); u32 surfCount = hecl::SBig(*reinterpret_cast<const u32*>(secIt->first));
inst.m_surfaces.reserve(surfCount); inst.m_surfaces.reserve(surfCount);
inst.m_shaders.resize(matSet.m_matSet.materials.size());
++secIt; ++secIt;
for (u32 i=0 ; i<surfCount ; ++i) for (u32 j=0 ; j<surfCount ; ++j)
{ {
inst.m_surfaces.emplace_back(); inst.m_surfaces.emplace_back();
CBooSurface& surf = inst.m_surfaces.back(); CBooSurface& surf = inst.m_surfaces.back();
surf.selfIdx = i; surf.selfIdx = j;
athena::io::MemoryReader r(secIt->first, secIt->second); athena::io::MemoryReader r(secIt->first, secIt->second);
surf.m_data.read(r); surf.m_data.read(r);
++secIt; ++secIt;
@ -1112,13 +1115,24 @@ void CGameArea::FillInStaticGeometry()
TToken<CModel> nullModel; TToken<CModel> nullModel;
inst.m_instance = std::make_unique<CBooModel> inst.m_instance = std::make_unique<CBooModel>
(nullModel, &inst.m_surfaces, x12c_postConstructed->m_materialSet, vtxFmt, vbo, ibo, (nullModel, nullptr, &inst.m_surfaces, matSet, vtxFmt, vbo, ibo,
inst.x34_aabb, inst.x0_visorFlags, 1, nullptr); inst.x34_aabb, inst.x0_visorFlags, 0, nullptr);
} }
return true; 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; x12c_postConstructed->x1108_25_modelsConstructed = true;
} }

View File

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

View File

@ -364,7 +364,7 @@ public:
if (size > base::x0_size) if (size > base::x0_size)
{ {
for (size_t i = base::x0_size; i < size; ++i) 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; base::x0_size = size;
} }
else if (size < base::x0_size) else if (size < base::x0_size)
@ -428,7 +428,7 @@ class prereserved_vector : public _reserved_vector_base<T, N>
void _init() void _init()
{ {
for (auto& i : base::x4_data) 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() 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; VISIRenderer* m_renderer;
NSWindow* m_window; NSWindow* m_window;
NSOpenGLView* m_glView; NSOpenGLView* m_glView;
int m_instanceIdx;
} }
- (id)initWithRenderer:(VISIRenderer*)renderer; - (id)initWithRenderer:(VISIRenderer*)renderer instIdx:(int)instIdx;
@end @end
@implementation AppDelegate @implementation AppDelegate
- (id)initWithRenderer:(VISIRenderer*)renderer - (id)initWithRenderer:(VISIRenderer*)renderer instIdx:(int)instIdx
{ {
self = [super init]; self = [super init];
m_renderer = renderer; m_renderer = renderer;
m_instanceIdx = instIdx;
return self; return self;
} }
- (void)applicationDidFinishLaunching:(NSNotification*)notification - (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 m_window = [[NSWindow alloc] initWithContentRect:cRect
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskMiniaturizable
backing:NSBackingStoreBuffered backing:NSBackingStoreBuffered
@ -109,12 +118,15 @@ int main(int argc, const char** argv)
logvisor::RegisterConsoleLogger(); logvisor::RegisterConsoleLogger();
atSetExceptionHandler(AthenaExc); atSetExceptionHandler(AthenaExc);
VISIRenderer renderer(argc, argv); VISIRenderer renderer(argc, argv);
int instIdx = -1;
if (argc > 3)
instIdx = atoi(argv[3]);
@autoreleasepool @autoreleasepool
{ {
[[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular];
/* Delegate (OS X callbacks) */ /* Delegate (OS X callbacks) */
AppDelegate* appDelegate = [[AppDelegate alloc] initWithRenderer:&renderer]; AppDelegate* appDelegate = [[AppDelegate alloc] initWithRenderer:&renderer instIdx:instIdx];
[[NSApplication sharedApplication] setDelegate:appDelegate]; [[NSApplication sharedApplication] setDelegate:appDelegate];
[[NSApplication sharedApplication] run]; [[NSApplication sharedApplication] run];
} }

View File

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

View File

@ -194,7 +194,19 @@ int main(int argc, const char** argv)
swa.border_pixmap = 0; swa.border_pixmap = 0;
swa.event_mask = 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, CopyFromParent, CopyFromParent, selectedVisual,
CWBorderPixel | CWEventMask | CWColormap, &swa); CWBorderPixel | CWEventMask | CWColormap, &swa);

View File

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

View File

@ -105,7 +105,7 @@ struct VISIBuilder
uint8_t flags = 0; uint8_t flags = 0;
void buildChildren(int level, int divisions, const zeus::CAABox& curAabb, 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 calculateSizesAndOffs(size_t& cur, size_t leafSz);
void writeNodes(athena::io::MemoryWriter& w, size_t leafBytes) const; 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); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_aabbIBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 20 * 4, AABBIdxs, GL_STATIC_DRAW); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 20 * 4, AABBIdxs, GL_STATIC_DRAW);
glGenQueries(1, &m_query);
return true; return true;
} }
@ -138,6 +136,7 @@ std::vector<VISIRenderer::Model::Vert> VISIRenderer::AABBToVerts(const zeus::CAA
static zeus::CColor ColorForIndex(int i) static zeus::CColor ColorForIndex(int i)
{ {
i += 1;
return zeus::CColor((i & 0xff) / 255.f, return zeus::CColor((i & 0xff) / 255.f,
((i >> 8) & 0xff) / 255.f, ((i >> 8) & 0xff) / 255.f,
((i >> 16) & 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); 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; return true;
} }
@ -277,7 +281,7 @@ void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bo
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST); 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); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (int j=0 ; j<6 ; ++j) for (int j=0 ; j<6 ; ++j)
@ -297,26 +301,6 @@ void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bo
zeus::CFrustum frustum; zeus::CFrustum frustum;
frustum.updatePlanes(mv, g_Proj); 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 // Draw frontfaces
glCullFace(GL_BACK); glCullFace(GL_BACK);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 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; zeus::CFrustum frustum;
frustum.updatePlanes(mv, g_Proj); frustum.updatePlanes(mv, g_Proj);
memset(m_queryBools.get(), 0, m_queryCount);
int idx = 0; int idx = 0;
for (const Model& model : m_models) for (const Model& model : m_models)
{ {
@ -371,23 +357,29 @@ void VISIRenderer::RenderPVSTransparent(const std::function<void(int)>& passFunc
continue; continue;
} }
glBindVertexArray(model.vao); glBindVertexArray(model.vao);
glBeginQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, m_queries[idx]);
m_queryBools[idx] = true;
for (const Model::Surface& surf : model.surfaces) for (const Model::Surface& surf : model.surfaces)
{ {
// transparents // transparents
if (surf.transparent) if (surf.transparent)
{
glBeginQuery(GL_ANY_SAMPLES_PASSED, m_query);
glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT, glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT,
reinterpret_cast<void*>(uintptr_t(surf.first * 4))); 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; ++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; zeus::CFrustum frustum;
frustum.updatePlanes(mv, g_Proj); frustum.updatePlanes(mv, g_Proj);
memset(m_queryBools.get(), 0, m_queryCount);
int idx = m_models.size(); int idx = m_models.size();
for (const Entity& ent : m_entities) for (const Entity& ent : m_entities)
{ {
@ -423,36 +417,56 @@ void VISIRenderer::RenderPVSEntitiesAndLights(const std::function<void(int)>& pa
continue; continue;
} }
glBindVertexArray(ent.vao); 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); glDrawElements(GL_TRIANGLE_STRIP, 20, GL_UNSIGNED_INT, 0);
glEndQuery(GL_ANY_SAMPLES_PASSED); glEndQuery(GL_ANY_SAMPLES_PASSED_CONSERVATIVE);
GLint res; ++idx;
glGetQueryObjectiv(m_query, GL_QUERY_RESULT, &res); }
if (res)
passFunc(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_queries[idx], GL_QUERY_RESULT, &res);
if (res)
passFunc(idx);
}
++idx; ++idx;
} }
int lightIdx = 0; int lightIdx = 0;
for (const Light& light : m_lights) for (const Light& light : m_lights)
{ {
if (!frustum.pointFrustumTest(light.point)) if (m_queryBools[idx])
{ {
++lightIdx; GLint res;
continue; 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);
} }
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);
EPVSVisSetState state = m_totalAABB.pointInside(light.point) ?
EPVSVisSetState::EndOfTree : EPVSVisSetState::OutOfBounds;
if (res && state == EPVSVisSetState::EndOfTree)
state = EPVSVisSetState::NodeFound;
lightPassFunc(lightIdx, state);
++lightIdx; ++lightIdx;
++idx;
} }
} }
} }

View File

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