[ZoneBuilder] Add support for iw3 techsets, decl, vs, and ps

This commit is contained in:
TheApadayo 2019-02-01 16:16:42 -05:00
parent c845572be5
commit 07278ebbfa
13 changed files with 341 additions and 31 deletions

View File

@ -1,7 +1,56 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
#define IW4X_TECHSET_VERSION "0"
namespace Assets namespace Assets
{ {
void IMaterialPixelShader::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one
if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game
}
void IMaterialPixelShader::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/)
{
header->pixelShader = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).pixelShader;
}
void IMaterialPixelShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
Components::FileSystem::File psFile(Utils::String::VA("ps/%s.iw4xPS", name.data()));
if (!psFile.exists()) return;
Utils::Stream::Reader reader(builder->getAllocator(), psFile.getBuffer());
char* magic = reader.readArray<char>(8);
if (std::memcmp(magic, "IW4xPIXL", 8))
{
Components::Logger::Error(0, "Reading pixel shader '%s' failed, header is invalid!", name.data());
}
std::string version;
version.push_back(reader.read<char>());
if (version != IW4X_TECHSET_VERSION)
{
Components::Logger::Error("Reading pixel shader '%s' failed, expected version is %d, but it was %d!", name.data(), atoi(IW4X_TECHSET_VERSION), atoi(version.data()));
}
Game::MaterialPixelShader* asset = reader.readObject<Game::MaterialPixelShader>();
if (asset->name)
{
asset->name = reader.readCString();
}
if (asset->prog.loadDef.program)
{
asset->prog.loadDef.program = reader.readArray<unsigned int>(asset->prog.loadDef.programSize);
}
header->pixelShader = asset;
}
void IMaterialPixelShader::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) void IMaterialPixelShader::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{ {
AssertSize(Game::MaterialPixelShader, 16); AssertSize(Game::MaterialPixelShader, 16);

View File

@ -8,5 +8,9 @@ namespace Assets
virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_PIXELSHADER; }; virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_PIXELSHADER; };
virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
virtual void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override;
void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
}; };
} }

View File

@ -1,7 +1,142 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
#define IW4X_TECHSET_VERSION "0"
namespace Assets namespace Assets
{ {
void IMaterialTechniqueSet::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one
if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game
}
void IMaterialTechniqueSet::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/)
{
header->techniqueSet = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).techniqueSet;
}
void IMaterialTechniqueSet::loadBinaryTechnique(Game::MaterialTechnique** tech, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
AssertSize(Game::MaterialPass, 20);
Components::FileSystem::File techFile(Utils::String::VA("techniques/%s.iw4xTech", name.data()));
if (!techFile.exists()) {
*tech = nullptr;
Components::Logger::Print("Warning: Missing technique '%s'\n", name.data());
return;
}
Utils::Stream::Reader reader(builder->getAllocator(), techFile.getBuffer());
char* magic = reader.readArray<char>(8);
if (std::memcmp(magic, "IW4xTECH", 8))
{
Components::Logger::Error(0, "Reading technique '%s' failed, header is invalid!", name.data());
}
std::string version;
version.push_back(reader.read<char>());
if (version != IW4X_TECHSET_VERSION)
{
Components::Logger::Error("Reading technique '%s' failed, expected version is %d, but it was %d!", name.data(), atoi(IW4X_TECHSET_VERSION), atoi(version.data()));
}
unsigned short flags = reader.read<unsigned short>();
unsigned short passCount = reader.read<unsigned short>();
Game::MaterialTechnique* asset = (Game::MaterialTechnique*)builder->getAllocator()->allocateArray<unsigned char>(sizeof(Game::MaterialTechnique) + (sizeof(Game::MaterialPass) * (passCount - 1)));
asset->name = builder->getAllocator()->duplicateString(name);
asset->flags = flags;
asset->passCount = passCount;
Game::MaterialPass* passes = reader.readArray<Game::MaterialPass>(passCount);
std::memcpy(asset->passArray, passes, sizeof(Game::MaterialPass) * passCount);
for (unsigned short i = 0; i < asset->passCount; i++)
{
Game::MaterialPass* pass = &asset->passArray[i];
if (pass->vertexDecl)
{
const char* declName = reader.readCString();
pass->vertexDecl = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_VERTEXDECL, declName, builder).vertexDecl;
}
if (pass->vertexShader)
{
const char* vsName = reader.readCString();
pass->vertexShader = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, vsName, builder).vertexShader;
}
if (pass->pixelShader)
{
const char* psName = reader.readCString();
pass->pixelShader = Components::AssetHandler::FindAssetForZone(Game::XAssetType::ASSET_TYPE_PIXELSHADER, psName, builder).pixelShader;
}
pass->args = reader.readArray<Game::MaterialShaderArgument>(pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount);
for (int j = 0; j < pass->perPrimArgCount + pass->perObjArgCount + pass->stableArgCount; j++)
{
if (pass->args[j].type == 1 || pass->args[j].type == 7)
{
pass->args[j].u.literalConst = reader.readArray<float>(4);
}
if (pass->args[j].type == 3 || pass->args[j].type == 5)
{
pass->args[j].u.codeConst.index = *reader.readObject<unsigned short>();
pass->args[j].u.codeConst.firstRow = *reader.readObject<unsigned char>();
pass->args[j].u.codeConst.rowCount = *reader.readObject<unsigned char>();
}
}
}
*tech = asset;
}
void IMaterialTechniqueSet::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
Components::FileSystem::File tsFile(Utils::String::VA("techsets/%s.iw4xTS", name.data()));
if (!tsFile.exists()) return;
Utils::Stream::Reader reader(builder->getAllocator(), tsFile.getBuffer());
char* magic = reader.readArray<char>(8);
if (std::memcmp(magic, "IW4xTSET", 8))
{
Components::Logger::Error(0, "Reading techset '%s' failed, header is invalid!", name.data());
}
std::string version;
version.push_back(reader.read<char>());
if (version != IW4X_TECHSET_VERSION)
{
Components::Logger::Error("Reading techset '%s' failed, expected version is %d, but it was %d!", name.data(), atoi(IW4X_TECHSET_VERSION), atoi(version.data()));
}
Game::MaterialTechniqueSet* asset = reader.readObject<Game::MaterialTechniqueSet>();
if (asset->name)
{
asset->name = reader.readCString();
}
for (int i = 0; i < 48; i++)
{
if (asset->techniques[i])
{
const char* techName = reader.readCString();
this->loadBinaryTechnique(&asset->techniques[i], techName, builder);
}
}
header->techniqueSet = asset;
}
void IMaterialTechniqueSet::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) void IMaterialTechniqueSet::mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{ {
Game::MaterialTechniqueSet* asset = header.techniqueSet; Game::MaterialTechniqueSet* asset = header.techniqueSet;

View File

@ -9,5 +9,11 @@ namespace Assets
virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
virtual void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; virtual void mark(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
virtual void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override;
void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
void loadBinaryTechnique(Game::MaterialTechnique** tech, const std::string& name, Components::ZoneBuilder::Zone* builder);
}; };
} }

View File

@ -1,7 +1,50 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
#define IW4X_TECHSET_VERSION "0"
namespace Assets namespace Assets
{ {
void IMaterialVertexDeclaration::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one
if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game
}
void IMaterialVertexDeclaration::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/)
{
header->vertexDecl = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).vertexDecl;
}
void IMaterialVertexDeclaration::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
Components::FileSystem::File declFile(Utils::String::VA("decl/%s.iw4xDECL", name.data()));
if (!declFile.exists()) return;
Utils::Stream::Reader reader(builder->getAllocator(), declFile.getBuffer());
char* magic = reader.readArray<char>(8);
if (std::memcmp(magic, "IW4xDECL", 8))
{
Components::Logger::Error(0, "Reading vertex declaration '%s' failed, header is invalid!", name.data());
}
std::string version;
version.push_back(reader.read<char>());
if (version != IW4X_TECHSET_VERSION)
{
Components::Logger::Error("Reading vertex declaration '%s' failed, expected version is %d, but it was %d!", name.data(), atoi(IW4X_TECHSET_VERSION), atoi(version.data()));
}
Game::MaterialVertexDeclaration* asset = reader.readObject<Game::MaterialVertexDeclaration>();
if (asset->name)
{
asset->name = reader.readCString();
}
header->vertexDecl = asset;
}
void IMaterialVertexDeclaration::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) void IMaterialVertexDeclaration::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{ {
AssertSize(Game::MaterialVertexDeclaration, 100); AssertSize(Game::MaterialVertexDeclaration, 100);

View File

@ -8,5 +8,9 @@ namespace Assets
virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_VERTEXDECL; }; virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_VERTEXDECL; };
virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
virtual void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override;
void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
}; };
} }

View File

@ -1,7 +1,55 @@
#include "STDInclude.hpp" #include "STDInclude.hpp"
#define IW4X_TECHSET_VERSION "0"
namespace Assets namespace Assets
{ {
void IMaterialVertexShader::load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
if (!header->data) this->loadNative(header, name, builder); // Check if there is a native one
if (!header->data) this->loadBinary(header, name, builder); // Check if we need to import a new one into the game
}
void IMaterialVertexShader::loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* /*builder*/)
{
header->vertexShader = Components::AssetHandler::FindOriginalAsset(this->getType(), name.data()).vertexShader;
}
void IMaterialVertexShader::loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder)
{
Components::FileSystem::File vsFile(Utils::String::VA("vs/%s.iw4xVS", name.data()));
if (!vsFile.exists()) return;
Utils::Stream::Reader reader(builder->getAllocator(), vsFile.getBuffer());
char* magic = reader.readArray<char>(8);
if (std::memcmp(magic, "IW4xVERT", 8))
{
Components::Logger::Error(0, "Reading vertex shader '%s' failed, header is invalid!", name.data());
}
std::string version;
version.push_back(reader.read<char>());
if (version != IW4X_TECHSET_VERSION)
{
Components::Logger::Error("Reading vertex shader '%s' failed, expected version is %d, but it was %d!", name.data(), atoi(IW4X_TECHSET_VERSION), atoi(version.data()));
}
Game::MaterialVertexShader* asset = reader.readObject<Game::MaterialVertexShader>();
if (asset->name)
{
asset->name = reader.readCString();
}
if (asset->prog.loadDef.program)
{
asset->prog.loadDef.program = reader.readArray<unsigned int>(asset->prog.loadDef.programSize);
}
header->vertexShader = asset;
}
void IMaterialVertexShader::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) void IMaterialVertexShader::save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder)
{ {
AssertSize(Game::MaterialVertexShader, 16); AssertSize(Game::MaterialVertexShader, 16);

View File

@ -8,5 +8,9 @@ namespace Assets
virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_VERTEXSHADER; }; virtual Game::XAssetType getType() override { return Game::XAssetType::ASSET_TYPE_VERTEXSHADER; };
virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override; virtual void save(Game::XAssetHeader header, Components::ZoneBuilder::Zone* builder) override;
virtual void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override;
void loadNative(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
void loadBinary(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder);
}; };
} }

View File

@ -17,7 +17,7 @@ namespace Assets
} }
} }
void IXModel::loadXSurface(Game::XSurface* surf, Utils::Stream::Reader* reader) void IXModel::loadXSurface(Game::XSurface* surf, Utils::Stream::Reader* reader, Components::ZoneBuilder::Zone* builder)
{ {
if (surf->vertInfo.vertsBlend) if (surf->vertInfo.vertsBlend)
{ {
@ -48,13 +48,23 @@ namespace Assets
} }
// Access index block // Access index block
if (surf->triIndices) if (surf->triIndices)
{ {
surf->triIndices = reader->readArray<unsigned short>(surf->triCount * 3); void* oldPtr = surf->triIndices;
} surf->triIndices = reader->readArray<unsigned short>(surf->triCount * 3);
if (builder->getAllocator()->isPointerMapped(oldPtr))
{
surf->triIndices = builder->getAllocator()->getPointer<unsigned short>(oldPtr);
}
else
{
builder->getAllocator()->mapPointer(oldPtr, surf->triIndices);
}
}
} }
void IXModel::loadXModelSurfs(Game::XModelSurfs* asset, Utils::Stream::Reader* reader) void IXModel::loadXModelSurfs(Game::XModelSurfs* asset, Utils::Stream::Reader* reader, Components::ZoneBuilder::Zone* builder)
{ {
if (asset->name) if (asset->name)
{ {
@ -67,7 +77,7 @@ namespace Assets
for (int i = 0; i < asset->numsurfs; ++i) for (int i = 0; i < asset->numsurfs; ++i)
{ {
this->loadXSurface(&asset->surfs[i], reader); this->loadXSurface(&asset->surfs[i], reader, builder);
} }
} }
} }
@ -165,7 +175,7 @@ namespace Assets
if (asset->lodInfo[i].modelSurfs) if (asset->lodInfo[i].modelSurfs)
{ {
asset->lodInfo[i].modelSurfs = reader.readObject<Game::XModelSurfs>(); asset->lodInfo[i].modelSurfs = reader.readObject<Game::XModelSurfs>();
this->loadXModelSurfs(asset->lodInfo[i].modelSurfs, &reader); this->loadXModelSurfs(asset->lodInfo[i].modelSurfs, &reader, builder);
Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_XMODEL_SURFS, { asset->lodInfo[i].modelSurfs }); Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_XMODEL_SURFS, { asset->lodInfo[i].modelSurfs });
asset->lodInfo[i].surfs = asset->lodInfo[i].modelSurfs->surfs; asset->lodInfo[i].surfs = asset->lodInfo[i].modelSurfs->surfs;
@ -293,7 +303,7 @@ namespace Assets
} }
Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP, { asset->physCollmap }); Components::AssetHandler::StoreTemporaryAsset(Game::XAssetType::ASSET_TYPE_PHYSCOLLMAP, { asset->physCollmap });
//asset->physCollmap = nullptr; // asset->physCollmap = nullptr;
} }
} }

View File

@ -12,8 +12,9 @@ namespace Assets
virtual void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override; virtual void load(Game::XAssetHeader* header, const std::string& name, Components::ZoneBuilder::Zone* builder) override;
private: private:
void loadXModelSurfs(Game::XModelSurfs* asset, Utils::Stream::Reader* reader); std::map<void*, void*> triIndicies;
void loadXSurface(Game::XSurface* surf, Utils::Stream::Reader* reader); void loadXModelSurfs(Game::XModelSurfs* asset, Utils::Stream::Reader* reader, Components::ZoneBuilder::Zone* builder);
void loadXSurface(Game::XSurface* surf, Utils::Stream::Reader* reader, Components::ZoneBuilder::Zone* builder);
void loadXSurfaceCollisionTree(Game::XSurfaceCollisionTree* entry, Utils::Stream::Reader* reader); void loadXSurfaceCollisionTree(Game::XSurfaceCollisionTree* entry, Utils::Stream::Reader* reader);
}; };
} }

View File

@ -81,12 +81,16 @@ namespace Assets
// Access index block // Access index block
buffer->pushBlock(Game::XFILE_BLOCK_INDEX); buffer->pushBlock(Game::XFILE_BLOCK_INDEX);
if (surf->triIndices) if (builder->hasPointer(surf->triIndices))
{ {
buffer->align(Utils::Stream::ALIGN_16); destSurf->triIndices = builder->getPointer(surf->triIndices);
buffer->saveArray(surf->triIndices, surf->triCount * 3); }
Utils::Stream::ClearPointer(&destSurf->triIndices); else
} {
buffer->align(Utils::Stream::ALIGN_16);
buffer->saveArray(surf->triIndices, surf->triCount * 3);
Utils::Stream::ClearPointer(&destSurf->triIndices);
}
buffer->popBlock(); buffer->popBlock();
} }

View File

@ -745,18 +745,21 @@ namespace Components
if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawAabbTrees").get<bool>()) return; if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawAabbTrees").get<bool>()) return;
float cyan[4] = { 0.0f, 0.5f, 0.5f, 1.0f }; float cyan[4] = { 0.0f, 0.5f, 0.5f, 1.0f };
float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
//Game::clipMap_t* clipMap = *reinterpret_cast<Game::clipMap_t**>(0x7998E0); Game::clipMap_t* clipMap = *reinterpret_cast<Game::clipMap_t**>(0x7998E0);
Game::GfxWorld* gameWorld = *reinterpret_cast<Game::GfxWorld**>(0x66DEE94); //Game::GfxWorld* gameWorld = *reinterpret_cast<Game::GfxWorld**>(0x66DEE94);
if (!gameWorld) return; if (!clipMap) return;
for (int i = 0; i < gameWorld->dpvsPlanes.cellCount; ++i) for (unsigned short i = 0; i < clipMap->smodelNodeCount; ++i)
{ {
for (int j = 0; j < gameWorld->aabbTreeCounts[i].aabbTreeCount; ++j) Game::R_AddDebugBounds(cyan, &clipMap->smodelNodes[i].bounds);
{ }
Game::R_AddDebugBounds(cyan, &gameWorld->aabbTrees[i].aabbTree[j].bounds);
} for (unsigned int i = 0; i < clipMap->numStaticModels; i += 2)
} {
Game::R_AddDebugBounds(red, &clipMap->staticModelList[i].absBounds);
}
}); });

View File

@ -223,8 +223,7 @@ namespace Components
Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this, isSubAsset); Game::XAssetHeader assetHeader = AssetHandler::FindAssetForZone(type, name, this, isSubAsset);
if (!assetHeader.data) if (!assetHeader.data)
{ { Logger::Error("Error: Missing asset '%s' of type '%s'\n", name.data(), Game::DB_GetXAssetTypeName(type));
Logger::Error("Error: Missing asset '%s' of type '%s'\n", name.data(), Game::DB_GetXAssetTypeName(type));
return false; return false;
} }
@ -708,7 +707,7 @@ namespace Components
{ {
Game::XAssetEntry* entry = Game::DB_FindXAssetEntry(type, name.data()); Game::XAssetEntry* entry = Game::DB_FindXAssetEntry(type, name.data());
if (entry->zoneIndex == zoneIndex) if (entry && entry->zoneIndex == zoneIndex)
{ {
// Allocate an empty asset (filled with zeros) // Allocate an empty asset (filled with zeros)
header.data = builder->getAllocator()->allocate(Game::DB_GetXAssetSizeHandlers[type]()); header.data = builder->getAllocator()->allocate(Game::DB_GetXAssetSizeHandlers[type]());