diff options
| author | petrie911 <69443847+petrie911@users.noreply.github.com> | 2024-03-26 18:02:12 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-26 17:02:12 -0600 |
| commit | 8196258d2b06afcb06bd71b4b95d4db6e9be0208 (patch) | |
| tree | b14cbdd8265ad5d45dbf3c908d1278c693537026 | |
| parent | b101ad14bf80730a30d67cfed974f77113a41ab6 (diff) | |
Add Vec3s factory, fix colpoly, add some support for palettes (#54)
* tlut?
* tlut
| -rw-r--r-- | src/Companion.cpp | 5 | ||||
| -rw-r--r-- | src/factories/TextureFactory.cpp | 25 | ||||
| -rw-r--r-- | src/factories/Vec3fFactory.cpp | 2 | ||||
| -rw-r--r-- | src/factories/Vec3sFactory.cpp | 79 | ||||
| -rw-r--r-- | src/factories/Vec3sFactory.h | 36 | ||||
| -rw-r--r-- | src/factories/sf64/ColPolyFactory.cpp | 103 | ||||
| -rw-r--r-- | src/factories/sf64/ColPolyFactory.h | 4 | ||||
| -rw-r--r-- | src/factories/sf64/TriangleFactory.cpp | 4 |
8 files changed, 185 insertions, 73 deletions
diff --git a/src/Companion.cpp b/src/Companion.cpp index 225c4a1..e3d32d6 100644 --- a/src/Companion.cpp +++ b/src/Companion.cpp @@ -25,6 +25,7 @@ #include "factories/BlobFactory.h" #include "factories/LightsFactory.h" #include "factories/Vec3fFactory.h" +#include "factories/Vec3sFactory.h" #include "factories/sm64/AnimationFactory.h" #include "factories/sm64/DialogFactory.h" @@ -76,6 +77,7 @@ void Companion::Init(const ExportType type) { this->RegisterFactory("SAMPLE", std::make_shared<SampleFactory>()); this->RegisterFactory("BANK", std::make_shared<BankFactory>()); this->RegisterFactory("VEC3F", std::make_shared<Vec3fFactory>()); + this->RegisterFactory("VEC3S", std::make_shared<Vec3sFactory>()); // SM64 specific this->RegisterFactory("SM64:DIALOG", std::make_shared<SM64::DialogFactory>()); @@ -1074,13 +1076,13 @@ std::optional<YAML::Node> Companion::AddAsset(YAML::Node asset) { const auto symbol = GetSafeNode<std::string>(asset, "symbol", ""); const auto decl = this->GetNodeByAddr(offset); + if(decl.has_value()) { return std::get<1>(decl.value()); } auto rom = this->GetRomData(); auto factory = this->GetFactory(type); - if(!factory.has_value()) { return std::nullopt; } @@ -1102,6 +1104,7 @@ std::optional<YAML::Node> Companion::AddAsset(YAML::Node asset) { if(result.has_value()){ asset["path"] = std::get<0>(result.value()); + return std::get<1>(result.value()); } diff --git a/src/factories/TextureFactory.cpp b/src/factories/TextureFactory.cpp index 9d24c5c..2118e2e 100644 --- a/src/factories/TextureFactory.cpp +++ b/src/factories/TextureFactory.cpp @@ -3,6 +3,7 @@ #include "spdlog/spdlog.h" #include "Companion.h" #include <iomanip> +#include <regex> extern "C" { #include "n64graphics/n64graphics.h" @@ -153,7 +154,7 @@ ExportResult TextureCodeExporter::Export(std::ostream &write, std::shared_ptr<IP } if(start == offset){ - write << GetSafeNode<std::string>(node, "ctype", "static const u8") << " " << name << "[][" << texture->mBuffer.size() << "] = {\n"; + write << GetSafeNode<std::string>(node, "ctype", "static unsigned char") << " " << name << "[][" << texture->mBuffer.size() << "] = {\n"; } write << tab << "{\n"; @@ -283,7 +284,26 @@ std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse(std::vector<ui width = GetSafeNode<uint32_t>(node, "width"); height = GetSafeNode<uint32_t>(node, "height"); } - + + if((format == "CI4" || format == "CI8") && node["tlut"] && node["colors"]) { + YAML::Node tlutNode; + const auto tlutOffset = GetSafeNode<uint32_t>(node, "tlut"); + if(node["symbol"]) { + const auto symbol = GetSafeNode<std::string>(node, "symbol"); + const auto tlutSymbol = GetSafeNode(node, "tlut_symbol", symbol + "_tlut"); + std::ostringstream offsetSeg; + offsetSeg << std::uppercase << std::hex << tlutOffset; + tlutNode["symbol"] = std::regex_replace(tlutSymbol, std::regex(R"(OFFSET)"), offsetSeg.str()); + } + tlutNode["type"] = "TEXTURE"; + tlutNode["format"] = "TLUT"; + tlutNode["offset"] = tlutOffset; + tlutNode["colors"] = GetSafeNode<uint32_t>(node, "colors"); + if(node["tlut_ctype"]) { + tlutNode["ctype"] = GetSafeNode<std::string>(node, "tlut_ctype"); + } + Companion::Instance->AddAsset(tlutNode); + } size = GetSafeNode<uint32_t>(node, "size", CalculateTextureSize(gTextureFormats.at(format).type, width, height)); auto [_, segment] = Decompressor::AutoDecode(node, buffer, size); std::vector<uint8_t> result; @@ -369,6 +389,7 @@ std::optional<std::shared_ptr<IParsedData>> TextureFactory::parse_modding(std::v const auto imgi = png2ci(buffer.data(), buffer.size(), &width, &height); size = width * height * fmt.depth / 8; raw = new uint8_t[size]; + if(ci2raw_torch(raw, imgi, width, height, fmt.depth) <= 0){ throw std::runtime_error("Failed to convert PNG to texture"); } diff --git a/src/factories/Vec3fFactory.cpp b/src/factories/Vec3fFactory.cpp index ab8f7f3..32854b3 100644 --- a/src/factories/Vec3fFactory.cpp +++ b/src/factories/Vec3fFactory.cpp @@ -65,7 +65,7 @@ ExportResult Vec3fBinaryExporter::Export(std::ostream &write, std::shared_ptr<IP std::optional<std::shared_ptr<IParsedData>> Vec3fFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) { std::vector<Vec3f> vecs; const auto count = GetSafeNode<int>(node, "count"); - auto [root, segment] = Decompressor::AutoDecode(node, buffer, 0x1000); + auto [root, segment] = Decompressor::AutoDecode(node, buffer, count * sizeof(Vec3f)); LUS::BinaryReader reader(segment.data, segment.size); reader.SetEndianness(LUS::Endianness::Big); diff --git a/src/factories/Vec3sFactory.cpp b/src/factories/Vec3sFactory.cpp new file mode 100644 index 0000000..7e62d89 --- /dev/null +++ b/src/factories/Vec3sFactory.cpp @@ -0,0 +1,79 @@ +#include "Vec3sFactory.h" +#include "spdlog/spdlog.h" + +#include "Companion.h" +#include "utils/Decompressor.h" +#include "utils/TorchUtils.h" + +#define FORMAT_INT(x, w) std::dec << std::setfill(' ') << std::setw(w) << x + +Vec3sData::Vec3sData(std::vector<Vec3s> vecs): mVecs(vecs) { + mMaxWidth = 3; + for(Vec3s v : vecs) { + mMaxWidth = std::max(mMaxWidth, v.width()); + } +} + +ExportResult Vec3sHeaderExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement) { + const auto symbol = GetSafeNode(node, "symbol", entryName); + + if(Companion::Instance->IsOTRMode()){ + write << "static const char " << symbol << "[] = \"__OTR__" << (*replacement) << "\";\n\n"; + return std::nullopt; + } + + write << "extern Vec3s " << symbol << "[];\n"; + return std::nullopt; +} + + +int GetPrecision(Vec3s v) { + return std::max(std::max(GetPrecision(v.x), GetPrecision(v.y)), GetPrecision(v.z)); +} + +ExportResult Vec3sCodeExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { + const auto symbol = GetSafeNode(node, "symbol", entryName); + const auto offset = GetSafeNode<uint32_t>(node, "offset"); + auto vecData = std::static_pointer_cast<Vec3sData>(raw); + int i = 0; + + write << "Vec3s " << symbol << "[] = {"; + + int cols = 120 / (3 * vecData->mMaxWidth + 8); + for(Vec3s v : vecData->mVecs) { + if((i++ % cols) == 0) { + write << "\n" << fourSpaceTab; + } + write << FORMAT_INT(v, vecData->mMaxWidth) << ", "; + } + + write << "\n};\n"; + + if (Companion::Instance->IsDebug()) { + write << "// Count: " << vecData->mVecs.size() << " Vec3s\n"; + } + + return offset + vecData->mVecs.size() * sizeof(Vec3s); +} + +ExportResult Vec3sBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { + return std::nullopt; +} + +std::optional<std::shared_ptr<IParsedData>> Vec3sFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) { + std::vector<Vec3s> vecs; + const auto count = GetSafeNode<int>(node, "count"); + auto [root, segment] = Decompressor::AutoDecode(node, buffer, count * sizeof(Vec3s)); + LUS::BinaryReader reader(segment.data, segment.size); + reader.SetEndianness(LUS::Endianness::Big); + + for(int i = 0; i < count; i++) { + auto vx = reader.ReadInt16(); + auto vy = reader.ReadInt16(); + auto vz = reader.ReadInt16(); + + vecs.push_back(Vec3s(vx, vy, vz)); + } + + return std::make_shared<Vec3sData>(vecs); +} diff --git a/src/factories/Vec3sFactory.h b/src/factories/Vec3sFactory.h new file mode 100644 index 0000000..9ffb69a --- /dev/null +++ b/src/factories/Vec3sFactory.h @@ -0,0 +1,36 @@ +#pragma once + +#include "BaseFactory.h" +#include "types/Vec3D.h" + +class Vec3sData : public IParsedData { +public: + std::vector<Vec3s> mVecs; + int mMaxWidth; + + explicit Vec3sData(std::vector<Vec3s> vecs); +}; + +class Vec3sHeaderExporter : public BaseExporter { + ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class Vec3sBinaryExporter : public BaseExporter { + ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class Vec3sCodeExporter : public BaseExporter { + ExportResult Export(std::ostream& write, std::shared_ptr<IParsedData> data, std::string& entryName, YAML::Node& node, std::string* replacement) override; +}; + +class Vec3sFactory : public BaseFactory { +public: + std::optional<std::shared_ptr<IParsedData>> parse(std::vector<uint8_t>& buffer, YAML::Node& data) override; + inline std::unordered_map<ExportType, std::shared_ptr<BaseExporter>> GetExporters() override { + return { + REGISTER(Code, Vec3sCodeExporter) + REGISTER(Header, Vec3sHeaderExporter) + REGISTER(Binary, Vec3sBinaryExporter) + }; + } +}; diff --git a/src/factories/sf64/ColPolyFactory.cpp b/src/factories/sf64/ColPolyFactory.cpp index 67a6d86..5225894 100644 --- a/src/factories/sf64/ColPolyFactory.cpp +++ b/src/factories/sf64/ColPolyFactory.cpp @@ -8,8 +8,9 @@ #define NUM(x, w) std::dec << std::setfill(' ') << std::setw(w) << x +#define FORMAT_FLOAT(x, w, p) std::dec << std::setfill(' ') << std::fixed << std::setprecision(p) << std::setw(w) << x -SF64::ColPolyData::ColPolyData(std::vector<SF64::CollisionPoly> polys, std::vector<Vec3s> mesh): mPolys(polys), mMesh(mesh) { +SF64::ColPolyData::ColPolyData(std::vector<SF64::CollisionPoly> polys, std::vector<YAML::Node> meshNodes): mPolys(polys), mMeshNodes(meshNodes) { } @@ -29,16 +30,13 @@ ExportResult SF64::ColPolyCodeExporter::Export(std::ostream &write, std::shared_ const auto symbol = GetSafeNode(node, "symbol", entryName); const auto offset = GetSafeNode<uint32_t>(node, "offset"); auto colpolys = std::static_pointer_cast<SF64::ColPolyData>(raw); - auto off = ASSET_PTR(offset); - int i; + const auto meshSize = GetSafeNode(colpolys->mMeshNodes[0], "count", 0); write << "CollisionPoly " << symbol << "[] = {"; - int width = std::log10(colpolys->mMesh.size()) + 1; - // i = 0; + int width = std::log10(meshSize) + 1; + for(SF64::CollisionPoly poly : colpolys->mPolys) { - // if((i++ % 2) == 0) { - write << "\n" << fourSpaceTab; - // } + write << "\n" << fourSpaceTab; write << "{ " << NUM(poly.tri, width) << ", "; if (poly.unk_06 == 0) { write << "0, "; @@ -51,55 +49,19 @@ ExportResult SF64::ColPolyCodeExporter::Export(std::ostream &write, std::shared_ SPDLOG_ERROR("SF64:COLPOLY error: Nonzero value found in padding"); write << "/* ALERT: NONZERO PAD */ "; } - write << poly.dist << "}, "; + write << NUM(poly.dist, 9) << "}, "; } write << "\n};\n"; - + int endOffset = ASSET_PTR(offset) + colpolys->mPolys.size() * sizeof(SF64::CollisionPoly); if (Companion::Instance->IsDebug()) { write << "// CollisionPoly count: " << colpolys->mPolys.size() << "\n"; - write << "// 0x" << std::uppercase << std::hex << off + colpolys->mPolys.size() * sizeof(SF64::CollisionPoly) << "\n"; + write << "// 0x" << std::uppercase << std::hex << endOffset << "\n"; } write << "\n"; - std::ostringstream defaultMeshSymbol; - auto defaultMeshOffset = offset + colpolys->mPolys.size() * sizeof(SF64::CollisionPoly); - const auto meshOffset = GetSafeNode(node, "mesh_offset", defaultMeshOffset); - if (meshOffset != defaultMeshOffset) { - write << "// SF64:COLPOLY alert: Gap detected between polys and mesh\n\n"; - } - off = ASSET_PTR(meshOffset); - defaultMeshSymbol << symbol << "_mesh_" << std::uppercase << std::hex << off; - auto meshSymbol = GetSafeNode(node, "mesh_symbol", defaultMeshSymbol.str()); - - if (meshSymbol.find("OFFSET") != std::string::npos) { - std::ostringstream offsetSeg; - - offsetSeg << std::uppercase << std::hex << meshOffset; - meshSymbol = std::regex_replace(meshSymbol, std::regex(R"(OFFSET)"), offsetSeg.str()); - } - - if (Companion::Instance->IsDebug()) { - write << "// 0x" << std::uppercase << std::hex << off << "\n"; - } - - write << "Vec3s " << meshSymbol << "[] = {"; - i = 0; - for(Vec3s vtx : colpolys->mMesh) { - if((i++ % 4) == 0) { - write << "\n" << fourSpaceTab; - } - write << NUM(vtx, 6) << ", "; - } - - write << "\n};\n"; - - if (Companion::Instance->IsDebug()) { - write << "// Mesh vertex count: " << colpolys->mMesh.size() << "\n"; - } - - return off + colpolys->mMesh.size() * sizeof(Vec3s); + return endOffset; } ExportResult SF64::ColPolyBinaryExporter::Export(std::ostream &write, std::shared_ptr<IParsedData> raw, std::string& entryName, YAML::Node &node, std::string* replacement ) { @@ -109,8 +71,9 @@ ExportResult SF64::ColPolyBinaryExporter::Export(std::ostream &write, std::share std::optional<std::shared_ptr<IParsedData>> SF64::ColPolyFactory::parse(std::vector<uint8_t>& buffer, YAML::Node& node) { const auto offset = GetSafeNode<uint32_t>(node, "offset"); const auto count = GetSafeNode<uint32_t>(node, "count"); + const auto meshCount = GetSafeNode<uint32_t>(node, "mesh_count", 1); std::vector<SF64::CollisionPoly> polys; - std::vector<Vec3s> mesh; + std::vector<YAML::Node> meshNodes; int meshSize = 0; auto [_, segment] = Decompressor::AutoDecode(node, buffer, count * sizeof(SF64::CollisionPoly)); LUS::BinaryReader reader(segment.data, segment.size); @@ -133,21 +96,33 @@ std::optional<std::shared_ptr<IParsedData>> SF64::ColPolyFactory::parse(std::vec polys.push_back(CollisionPoly({{v0, v1, v2}, pad1, {nx, ny, nz}, pad2, dist})); } meshSize++; - const auto meshOffset = GetSafeNode<uint32_t>(node, "mesh_offset", offset + count * sizeof(SF64::CollisionPoly)); - YAML::Node meshNode; - meshNode["offset"] = meshOffset; - auto [__, meshSegment] = Decompressor::AutoDecode(meshNode, buffer, meshSize * sizeof(Vec3s)); - LUS::BinaryReader meshReader(meshSegment.data, meshSegment.size); - meshReader.SetEndianness(LUS::Endianness::Big); - - for(int i = 0; i < meshSize; i++) { - Vec3s vtx; - - vtx.x = meshReader.ReadInt16(); - vtx.y = meshReader.ReadInt16(); - vtx.z = meshReader.ReadInt16(); - mesh.push_back(vtx); + auto meshOffset = GetSafeNode<uint32_t>(node, "mesh_offset", offset + count * sizeof(SF64::CollisionPoly)); + for(int j = 0; j < meshCount; j++) { + YAML::Node meshNode; + + if(node["mesh_symbol"]) { + auto meshSymbol = GetSafeNode<std::string>(node, "mesh_symbol"); + if (meshSymbol.find("OFFSET") == std::string::npos) { + if(meshCount > 1) { + meshSymbol += "_" + std::to_string(j); + } + } else { + std::ostringstream offsetSeg; + offsetSeg << std::uppercase << std::hex << meshOffset; + + meshSymbol = std::regex_replace(meshSymbol, std::regex(R"(OFFSET)"), offsetSeg.str()); + } + meshNode["symbol"] = meshSymbol; + } + meshNode["type"] = "VEC3S"; + meshNode["count"] = meshSize; + meshNode["offset"] = meshOffset; + + meshNode = Companion::Instance->AddAsset(meshNode).value(); + + meshNodes.push_back(meshNode); + meshOffset += meshSize * sizeof(Vec3s); } - return std::make_shared<SF64::ColPolyData>(polys, mesh); + return std::make_shared<SF64::ColPolyData>(polys, meshNodes); } diff --git a/src/factories/sf64/ColPolyFactory.h b/src/factories/sf64/ColPolyFactory.h index 5d795ee..4b3dd64 100644 --- a/src/factories/sf64/ColPolyFactory.h +++ b/src/factories/sf64/ColPolyFactory.h @@ -16,9 +16,9 @@ struct CollisionPoly { class ColPolyData : public IParsedData { public: std::vector<CollisionPoly> mPolys; - std::vector<Vec3s> mMesh; + std::vector<YAML::Node> mMeshNodes; - ColPolyData(std::vector<CollisionPoly> polys, std::vector<Vec3s> mesh); + ColPolyData(std::vector<CollisionPoly> polys, std::vector<YAML::Node> meshNodes); }; class ColPolyHeaderExporter : public BaseExporter { diff --git a/src/factories/sf64/TriangleFactory.cpp b/src/factories/sf64/TriangleFactory.cpp index 52d3bc9..d379264 100644 --- a/src/factories/sf64/TriangleFactory.cpp +++ b/src/factories/sf64/TriangleFactory.cpp @@ -91,10 +91,8 @@ std::optional<std::shared_ptr<IParsedData>> SF64::TriangleFactory::parse(std::ve } } else { std::ostringstream offsetSeg; - std::string replaceOff = "OFFSET"; - std::string off; + offsetSeg << std::uppercase << std::hex << meshOffset; - off = offsetSeg.str(); meshSymbol = std::regex_replace(meshSymbol, std::regex(R"(OFFSET)"), offsetSeg.str()); } meshNode["symbol"] = meshSymbol; |
