mirror of https://github.com/AxioDL/metaforce.git
Lots of bug fixes (Windows still needs some fixes)
This commit is contained in:
parent
5e88b99769
commit
15d60493f2
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
}
|
||||
}
|
||||
size_t binarySize(size_t __isz) const
|
||||
{return __isz + 4;}
|
||||
{return __isz + 16;}
|
||||
};
|
||||
|
||||
using FourCC = hecl::FourCC;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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,79 +458,121 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
|
|||
if (auto __vec = r.enterSubVector("entities", entityCount))
|
||||
{
|
||||
entities.reserve(entityCount);
|
||||
uint16_t entityId = r.readUint16(nullptr);
|
||||
for (const SCLY::ScriptLayer& layer : sclyData.layers)
|
||||
for (size_t i=0 ; i<entityCount ; ++i)
|
||||
{
|
||||
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 (entAABB.min.x < entAABB.max.x)
|
||||
entities.emplace_back(entityId, entAABB);
|
||||
if ((obj->id & 0xffff) == entityId)
|
||||
{
|
||||
zeus::CAABox entAABB = obj->getVISIAABB(btok);
|
||||
if (!entAABB.invalid())
|
||||
entities.emplace_back(entityId, entAABB);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hecl::ProjectPath visiIntOut = outPath.getWithExtension(_S(".visiint"));
|
||||
hecl::ProjectPath visiIn = outPath.getWithExtension(_S(".visi"));
|
||||
athena::io::FileWriter w(visiIntOut.getAbsolutePath());
|
||||
w.writeUint32Big(meshes.size());
|
||||
for (const DNACMDL::Mesh& mesh : meshes)
|
||||
// Check if pre-generated visi exists, recycle if able
|
||||
hecl::ProjectPath preVisiPath = inPath.getWithExtension(_S(".visi"), true);
|
||||
if (preVisiPath.getPathType() == hecl::ProjectPath::Type::File)
|
||||
{
|
||||
w.writeUint32Big(uint32_t(mesh.topology));
|
||||
|
||||
w.writeUint32Big(mesh.pos.size());
|
||||
for (const auto& v : mesh.pos)
|
||||
athena::io::FileReader preVisiReader(preVisiPath.getAbsolutePath());
|
||||
atUint64 preVisiLen = preVisiReader.length();
|
||||
if (preVisiLen > 26)
|
||||
{
|
||||
atVec3f xfPos = hecl::BlenderConnection::DataStream::MtxVecMul4RM(mesh.sceneXf, v);
|
||||
w.writeVec3fBig(xfPos);
|
||||
}
|
||||
auto preVisiData = preVisiReader.readUBytes(preVisiLen);
|
||||
athena::io::MemoryReader preVisiDataReader(preVisiData.get(), preVisiLen);
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w.writeUint32Big(entities.size());
|
||||
for (const auto& ent : entities)
|
||||
if (!visiGood)
|
||||
{
|
||||
w.writeUint32Big(ent.first);
|
||||
w.writeVec3fBig(ent.second.min);
|
||||
w.writeVec3fBig(ent.second.max);
|
||||
}
|
||||
hecl::ProjectPath visiIntOut = outPath.getWithExtension(_S(".visiint"));
|
||||
hecl::ProjectPath visiIn = inPath.getWithExtension(_S(".visi"));
|
||||
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(lightsVisi[1].size());
|
||||
for (const auto& light : lightsVisi[1])
|
||||
w.writeVec3fBig(light);
|
||||
for (const auto& light : lightsVisi[0])
|
||||
w.writeVec3fBig(light);
|
||||
w.writeUint32Big(mesh.pos.size());
|
||||
for (const auto& v : mesh.pos)
|
||||
{
|
||||
atVec3f xfPos = hecl::BlenderConnection::DataStream::MtxVecMul4RM(mesh.sceneXf, v);
|
||||
w.writeVec3fBig(xfPos);
|
||||
}
|
||||
|
||||
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
|
||||
VisiGenPath += _S(".exe");
|
||||
VisiGenPath += _S(".exe");
|
||||
#endif
|
||||
const hecl::SystemChar* args[] = {VisiGenPath.c_str(),
|
||||
visiIntOut.getAbsolutePath().c_str(),
|
||||
visiIn.getAbsolutePath().c_str(),
|
||||
nullptr};
|
||||
if (0 == hecl::RunProcess(VisiGenPath.c_str(), args))
|
||||
{
|
||||
athena::io::FileReader r(visiIn.getAbsolutePath());
|
||||
size_t length = r.length();
|
||||
secs.emplace_back(length, 0);
|
||||
r.readBytesToBuf(secs.back().data(), length);
|
||||
visiGood = true;
|
||||
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))
|
||||
{
|
||||
athena::io::FileReader r(visiIn.getAbsolutePath());
|
||||
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;
|
||||
if (rem)
|
||||
for (int64_t i=0 ; i<32-rem ; ++i)
|
||||
w.writeBytes((atInt8*)"\xff", 1);
|
||||
w.writeUByte(0xff);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
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);
|
||||
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()));
|
||||
}
|
||||
|
||||
_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 */
|
||||
|
|
|
@ -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();}
|
||||
void Shutdown() { CancelBackgroundIndex(); }
|
||||
bool IsBusy() const { return m_asyncLoadMap.size() != 0; }
|
||||
|
||||
SObjectTag TagFromPath(const hecl::SystemChar* path) const
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -127,6 +127,8 @@ IObj* CToken::GetObj()
|
|||
}
|
||||
CToken& CToken::operator=(const CToken& other)
|
||||
{
|
||||
Unlock();
|
||||
RemoveRef();
|
||||
x0_objRef = other.x0_objRef;
|
||||
if (x0_objRef)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,13 +632,10 @@ 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 : 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 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)
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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"},
|
||||
|
|
|
@ -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,8 +149,8 @@ static const char* MBShadowPostMetal =
|
|||
" float4 shadowUp;\n"
|
||||
" float shadowId;\n"
|
||||
"};\n"
|
||||
"static float4 MBShadowPostFunc(thread VertToFrag& vtf, constant MBShadowUniform& su,\n"
|
||||
" texture2d<float> extTex0, texture2d<float> extTex1, texture2d<float> extTex2, float4 colorIn)\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"
|
||||
" float sphereTexel = extTex1.sample(samp, vtf.extTcgs1).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"},
|
||||
|
|
|
@ -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[] =
|
||||
{
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -414,16 +414,16 @@ CGameArea::CGameArea(CInputStream& in, int idx, int mlvlVersion)
|
|||
CGameArea::CGameArea(CAssetId mreaId)
|
||||
: x84_mrea(mreaId)
|
||||
{
|
||||
while (StartStreamingMainArea()) {}
|
||||
|
||||
for (auto& req : xf8_loadTransactions)
|
||||
req->WaitForComplete();
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
2
hecl
|
@ -1 +1 @@
|
|||
Subproject commit f949aabf5c4632df97746c273cab27a1ea1bffe4
|
||||
Subproject commit 84393676f125f87c443b770738b552015998228d
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
GLint res;
|
||||
glGetQueryObjectiv(m_query, GL_QUERY_RESULT, &res);
|
||||
if (res)
|
||||
passFunc(idx);
|
||||
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_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;
|
||||
GLint 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);
|
||||
}
|
||||
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;
|
||||
++idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue