From 96054fafb35fddbe3b04b9e5a8fd672cac8c6133 Mon Sep 17 00:00:00 2001 From: burninrubber0 Date: Tue, 28 Feb 2023 21:27:48 -0500 Subject: [PATCH 1/6] Housekeeping Normalize class layout, use read() with Vector3, add missing getters, move all getters to the header, remove extraneous comments, and other miscellaneous changes. --- CMakeLists.txt | 1 + include/binary-io/data-stream.h | 7 +- include/converter.h | 38 ++--- include/trigger-data.h | 245 +++++++++++++++----------------- include/types.h | 81 ++--------- src/binary-io/data-stream.cpp | 6 +- src/converter.cpp | 48 +++---- src/trigger-data.cpp | 87 ++---------- src/types.cpp | 41 ++++++ 9 files changed, 226 insertions(+), 328 deletions(-) create mode 100644 src/types.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ef735d..92d53b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ set(SOURCES src/main.cpp src/converter.cpp src/trigger-data.cpp + src/types.cpp src/binary-io/data-stream.cpp ) diff --git a/include/binary-io/data-stream.h b/include/binary-io/data-stream.h index a0fcf2c..74b77cd 100644 --- a/include/binary-io/data-stream.h +++ b/include/binary-io/data-stream.h @@ -36,7 +36,7 @@ class DataStream : public QDataStream return s; } - // callocs and reads data from the stream using DataStream's operator>>(DataStream&, T&) method + // callocs and reads data from the stream using DataStream's operator>>(DataStream&, T&) template void cAllocAndQtRead(T*& entries, int count) { @@ -47,7 +47,7 @@ class DataStream : public QDataStream *this >> entries[i]; } - // callocs and reads data from the stream using T's read(DataStream&) method + // callocs and reads data from the stream using T's read(DataStream&) template void cAllocAndCustomRead(T*& entries, int count) { @@ -68,7 +68,8 @@ class DataStream : public QDataStream // Reads a specified number of bytes from this stream to another stream, writing to a specified // offset in the other stream. By default, this offset is the current offset of this stream. // This is most useful for storing unknown data and padding to prevent data loss - void readRawData(DataStream& stream, quint32 length, qint64 position = -1); + // TODO: Come up with a more accurate name for this + void readRawData(DataStream& other, quint32 length, qint64 position = -1); // Get the current offset the device is reading/writing from qint64 pos(); diff --git a/include/converter.h b/include/converter.h index cdfeb6e..936a491 100644 --- a/include/converter.h +++ b/include/converter.h @@ -9,6 +9,9 @@ #include +using namespace BrnTrigger; +using namespace tinygltf; + class Converter { public: @@ -23,34 +26,35 @@ class Converter std::string inFileName; std::string outFileName; - BrnTrigger::TriggerData* triggerData = nullptr; + TriggerData* triggerData = nullptr; + const int minArgCount = 3; int getArgs(int argc, char* argv[]); int checkArgs(int argc, char* argv[]); void showUsage(); void readTriggerData(); - tinygltf::Buffer createGLTFBuffer(); + Buffer createGLTFBuffer(); void writeBoxRegion(DataStream& stream); Vector4 EulerToQuatRot(Vector3 euler); void convertTriggersToGLTF(); - bool triggerRegionExists(BrnTrigger::TriggerRegion region, bool checkGenericRegions = true); - void addTriggerRegionFields(BrnTrigger::TriggerRegion region, tinygltf::Value::Object& extras); + bool triggerRegionExists(TriggerRegion region, bool checkGenericRegions = true); + void addTriggerRegionFields(TriggerRegion region, Value::Object& extras); - void convertLandmark(BrnTrigger::Landmark landmark, tinygltf::Node& node, int index); - void convertStartingGrid(BrnTrigger::StartingGrid grid, tinygltf::Node& node, int index); - void convertBlackspot(BrnTrigger::Blackspot blackspot, tinygltf::Node& node, int index); - void convertVfxBoxRegion(BrnTrigger::VFXBoxRegion vfxBoxRegion, tinygltf::Node& node, int index); - void convertSignatureStunt(BrnTrigger::SignatureStunt signatureStunt, tinygltf::Node& node, int index); - void convertKillzone(BrnTrigger::Killzone killzone, tinygltf::Node& node, int index); - void convertGenericRegion(BrnTrigger::GenericRegion region, tinygltf::Node& node, int index); - void convertTriggerRegion(BrnTrigger::TriggerRegion triggerRegion, tinygltf::Node& node, int index); - void convertRoamingLocation(BrnTrigger::RoamingLocation location, tinygltf::Node& node, int index); - void convertSpawnLocation(BrnTrigger::SpawnLocation location, tinygltf::Node& node, int index); + void convertLandmark(Landmark landmark, Node& node, int index); + void convertStartingGrid(StartingGrid grid, Node& node, int index); + void convertBlackspot(Blackspot blackspot, Node& node, int index); + void convertVfxBoxRegion(VFXBoxRegion vfxBoxRegion, Node& node, int index); + void convertSignatureStunt(SignatureStunt signatureStunt, Node& node, int index); + void convertKillzone(Killzone killzone, Node& node, int index); + void convertGenericRegion(GenericRegion region, Node& node, int index); + void convertTriggerRegion(TriggerRegion triggerRegion, Node& node, int index); + void convertRoamingLocation(RoamingLocation location, Node& node, int index); + void convertSpawnLocation(SpawnLocation location, Node& node, int index); template - void addBoxRegionTransform(T entry, tinygltf::Node& node) + void addBoxRegionTransform(T entry, Node& node) { node.translation = { entry.getBoxRegion().getPosX(), @@ -75,7 +79,7 @@ class Converter }; } - void addPointTransform(Vector3 pos, Vector3 rot, tinygltf::Node& node) + void addPointTransform(Vector3 pos, Vector3 rot, Node& node) { node.translation = { pos.getX(), @@ -95,7 +99,7 @@ class Converter }; } - void addPointTransform(Vector3 pos, tinygltf::Node& node) + void addPointTransform(Vector3 pos, Node& node) { node.translation = { pos.getX(), diff --git a/include/trigger-data.h b/include/trigger-data.h index 9d59eb7..24fbce6 100644 --- a/include/trigger-data.h +++ b/include/trigger-data.h @@ -4,73 +4,6 @@ namespace BrnTrigger { - // Forward declare classes - class Landmark; - class SignatureStunt; - class GenericRegion; - class Killzone; - class Blackspot; - class VFXBoxRegion; - class RoamingLocation; - class SpawnLocation; - class TriggerRegion; - class StartingGrid; - - // The header for the TriggerData resource. - // Lists all relevant offsets and counts. - class TriggerData - { - public: - void read(DataStream& file); - - Landmark getLandmark(int index); - SignatureStunt getSignatureStunt(int index); - GenericRegion getGenericRegion(int index); - Killzone getKillzone(int index); - Blackspot getBlackspot(int index); - VFXBoxRegion getVfxBoxRegion(int index); - RoamingLocation getRoamingLocation(int index); - SpawnLocation getSpawnLocation(int index); - TriggerRegion getTriggerRegion(int index); - - int32_t getLandmarkCount() { return landmarkCount; } - int32_t getSignatureStuntCount() { return signatureStuntCount; } - int32_t getGenericRegionCount() { return genericRegionCount; } - int32_t getKillzoneCount() { return killzoneCount; } - int32_t getBlackspotCount() { return blackspotCount; } - int32_t getVfxBoxRegionCount() { return vfxBoxRegionCount; } - int32_t getRoamingLocationCount() { return roamingLocationCount; } - int32_t getSpawnLocationCount() { return spawnLocationCount; } - int32_t getRegionCount() { return regionCount; } - int32_t getTotalRegionCount(); - - private: - int32_t versionNumber = 0; - uint32_t size = 0; - Vector3 playerStartPosition; - Vector3 playerStartDirection; - Landmark* landmarks = nullptr; - int32_t landmarkCount = 0; - int32_t onlineLandmarkCount = 0; - SignatureStunt* signatureStunts = nullptr; - int32_t signatureStuntCount = 0; - GenericRegion* genericRegions = nullptr; - int32_t genericRegionCount = 0; - Killzone* killzones = nullptr; - int32_t killzoneCount = 0; - Blackspot* fileBlackspots = nullptr; - Blackspot* blackspots = nullptr; - int32_t blackspotCount = 0; - VFXBoxRegion* vfxBoxRegions = nullptr; - int32_t vfxBoxRegionCount = 0; - RoamingLocation* roamingLocations = nullptr; - int32_t roamingLocationCount = 0; - SpawnLocation* spawnLocations = nullptr; - int32_t spawnLocationCount = 0; - TriggerRegion** regions = nullptr; - int32_t regionCount = 0; - }; - // Box trigger type. Sphere and line types are not supported. class BoxRegion { @@ -125,13 +58,29 @@ namespace BrnTrigger BoxRegion boxRegion; int32_t id = 0; - int16_t regionIndex = 0; // Landmarks come after GenericRegions + int16_t regionIndex = 0; Type type = (Type)0; - uint8_t unk0 = 0; // Flags? 0 or 1. No longer padding + uint8_t unk0 = 0; // Flags? 0 or 1. No longer padding. TODO: Find out what version introduced this }; - // Used for finish lines and event starts. Big Surf Island has an - // overabundance of Landmarks. + // Starting grid for race events. Unused in retail. + class StartingGrid + { + public: + StartingGrid(); + + void read(DataStream& file); + + Vector3 getStartingPosition(int index) { return startingPositions[index]; } + Vector3 getStartingDirection(int index) { return startingDirections[index]; } + + private: + Vector3 startingPositions[8]; + Vector3 startingDirections[8]; + }; + + // Used for finish lines and event starts. + // Big Surf Island has an overabundance of Landmarks. class Landmark : public TriggerRegion { enum class Flags : uint8_t; @@ -139,14 +88,13 @@ namespace BrnTrigger public: void read(DataStream& file); - StartingGrid getStartingGrid(int index); + StartingGrid getStartingGrid(int index) { return startingGrids[index]; } + int8_t getStartingGridCount() { return startingGridCount; } uint8_t getDesignIndex() { return designIndex; } uint8_t getDistrict() { return district; } Flags getFlags() { return flags; } bool getIsOnline() { return ((uint8_t)flags & (uint8_t)Flags::isOnline) != 0; }; - int8_t getStartingGridCount() { return startingGridCount; } - private: // The flags field in the Landmark structure. enum class Flags : uint8_t @@ -161,39 +109,6 @@ namespace BrnTrigger Flags flags = (Flags)0; }; - // Starting grid for race events. Unused in retail. - class StartingGrid - { - public: - void read(DataStream& file); - - Vector3 getStartingPosition(int index) { return startingPositions[index]; } - Vector3 getStartingDirection(int index) { return startingDirections[index]; } - - private: - Vector3 startingPositions[8]; - Vector3 startingDirections[8]; - }; - - // - class SignatureStunt - { - public: - void read(DataStream& file); - - CgsID getId() { return id; } - int64_t getCamera() { return camera; } - GenericRegion getStuntElement(int index); - - int32_t getStuntElementCount() { return stuntElementCount; } - - private: - CgsID id = 0; - int64_t camera = 0; - GenericRegion** stuntElements = nullptr; - int32_t stuntElementCount = 0; - }; - // Generic box trigger. The main trigger type used. Used for many things. class GenericRegion : public TriggerRegion { @@ -267,25 +182,6 @@ namespace BrnTrigger int8_t isOneWay = 0; }; - // TODO: Description - class Killzone - { - public: - void read(DataStream& file); - - GenericRegion getTrigger(int index) { return triggers[index][0]; } - CgsID getRegionId(int index) { return regionIds[index]; } - - int32_t getTriggerCount() { return triggerCount; } - int32_t getRegionIdCount() { return regionIdCount; } - - private: - GenericRegion** triggers = nullptr; - int32_t triggerCount = 0; - CgsID* regionIds = nullptr; // GameDB IDs - int32_t regionIdCount = 0; - }; - // Accident blackspot (crash mode). Unused in retail. class Blackspot : public TriggerRegion { @@ -314,9 +210,42 @@ namespace BrnTrigger { public: void read(DataStream& file); + }; + + // TODO: Description + class SignatureStunt + { + public: + void read(DataStream& file); + + CgsID getId() { return id; } + int64_t getCamera() { return camera; } + GenericRegion getStuntElement(int index) { return stuntElements[index][0]; } + int32_t getStuntElementCount() { return stuntElementCount; } private: + CgsID id = 0; + int64_t camera = 0; + GenericRegion** stuntElements = nullptr; + int32_t stuntElementCount = 0; + }; + // TODO: Description + class Killzone + { + public: + void read(DataStream& file); + + GenericRegion getTrigger(int index) { return triggers[index][0]; } + int32_t getTriggerCount() { return triggerCount; } + CgsID getRegionId(int index) { return regionIds[index]; } + int32_t getRegionIdCount() { return regionIdCount; } + + private: + GenericRegion** triggers = nullptr; + int32_t triggerCount = 0; + CgsID* regionIds = nullptr; // GameDB IDs + int32_t regionIdCount = 0; }; // Spawn locations for roaming rivals (shutdown cars) @@ -329,7 +258,7 @@ namespace BrnTrigger uint8_t getDistrictIndex() { return districtIndex; } private: - Vector3 position; + Vector3 position = Vector3(true); uint8_t districtIndex = 0; }; @@ -356,9 +285,67 @@ namespace BrnTrigger carUnlock }; - Vector3 position; - Vector3 direction; + Vector3 position = Vector3(true); + Vector3 direction = Vector3(true); CgsID junkyardId = 0; // GameDB ID Type type = (Type)0; }; + + // The header for the TriggerData resource. + // Lists all relevant offsets and counts. + class TriggerData + { + public: + void read(DataStream& file); + + int32_t getVersionNumber() { return versionNumber; } + uint32_t getSize() { return size; } + Vector3 getPlayerStartPosition() { return playerStartPosition; } + Vector3 getPlayerStartDirection() { return playerStartDirection; } + Landmark getLandmark(int index) { return landmarks[index]; } + int32_t getLandmarkCount() { return landmarkCount; } + int32_t getOnlineLandmarkCount() { return onlineLandmarkCount; } + SignatureStunt getSignatureStunt(int index) { return signatureStunts[index]; } + int32_t getSignatureStuntCount() { return signatureStuntCount; } + GenericRegion getGenericRegion(int index) { return genericRegions[index]; } + int32_t getGenericRegionCount() { return genericRegionCount; } + Killzone getKillzone(int index) { return killzones[index]; } + int32_t getKillzoneCount() { return killzoneCount; } + Blackspot getBlackspot(int index) { return blackspots[index]; } + int32_t getBlackspotCount() { return blackspotCount; } + VFXBoxRegion getVfxBoxRegion(int index) { return vfxBoxRegions[index]; } + int32_t getVfxBoxRegionCount() { return vfxBoxRegionCount; } + RoamingLocation getRoamingLocation(int index) { return roamingLocations[index]; } + int32_t getRoamingLocationCount() { return roamingLocationCount; } + SpawnLocation getSpawnLocation(int index) { return spawnLocations[index]; } + int32_t getSpawnLocationCount() { return spawnLocationCount; } + TriggerRegion getTriggerRegion(int index) { return regions[index][0]; } + int32_t getRegionCount() { return regionCount; } + + private: + int32_t versionNumber = 0; + uint32_t size = 0; + Vector3 playerStartPosition = Vector3(true); + Vector3 playerStartDirection = Vector3(true); + Landmark* landmarks = nullptr; + int32_t landmarkCount = 0; + int32_t onlineLandmarkCount = 0; + SignatureStunt* signatureStunts = nullptr; + int32_t signatureStuntCount = 0; + GenericRegion* genericRegions = nullptr; + int32_t genericRegionCount = 0; + Killzone* killzones = nullptr; + int32_t killzoneCount = 0; + Blackspot* fileBlackspots = nullptr; + Blackspot* blackspots = nullptr; + int32_t blackspotCount = 0; + VFXBoxRegion* vfxBoxRegions = nullptr; + int32_t vfxBoxRegionCount = 0; + RoamingLocation* roamingLocations = nullptr; + int32_t roamingLocationCount = 0; + SpawnLocation* spawnLocations = nullptr; + int32_t spawnLocationCount = 0; + TriggerRegion** regions = nullptr; + int32_t regionCount = 0; + }; }; diff --git a/include/types.h b/include/types.h index da73a68..21d1bb1 100644 --- a/include/types.h +++ b/include/types.h @@ -12,66 +12,30 @@ typedef uint64_t CgsID; class Vector3 { public: - Vector3() - { - - } + Vector3(bool isVpu = false); + Vector3(float x, float y, float z, bool vpu = false); - Vector3(float x, float y, float z) - { - this->x = x; - this->y = y; - this->z = z; - } - - void readFPU(DataStream& file) - { - file >> x; - file >> y; - file >> z; - } - - void readVPU(DataStream& file) - { - file >> x; - file >> y; - file >> z; - file.skip(0x4); - } + void read(DataStream& stream); float getX() { return x; } float getY() { return y; } float getZ() { return z; } + bool getIsVpu() { return isVpu; } private: float x = 0; float y = 0; float z = 0; + bool isVpu = false; }; class Vector4 { public: - Vector4() - { - - } + Vector4(); + Vector4(float x, float y, float z, float w); - Vector4(float x, float y, float z, float w) - { - this->x = x; - this->y = y; - this->z = z; - this->w = w; - } - - void read(DataStream& file) - { - file >> x; - file >> y; - file >> z; - file >> w; - } + void read(DataStream& stream); float getX() { return x; } float getY() { return y; } @@ -84,32 +48,3 @@ class Vector4 float z = 0; float w = 0; }; - -// In-game districts -// Not needed yet -//enum class District -//{ -// oceanView, -// westAcres, -// twinBridges, -// bigSurfBeach, -// easternShore, -// hillsidePass, -// heartbreakHills, -// rockridgeCliffs, -// southBay, -// parkVale, -// paradiseWharf, -// crystalSummit, -// lonePeaks, -// sunsetValley, -// downtown, -// riverCity, -// motorCity, -// waterfront, -// paradiseKeysBridge, -// northBeach, -// midTown, -// southCoast, -// perrensPoint -//}; diff --git a/src/binary-io/data-stream.cpp b/src/binary-io/data-stream.cpp index 216260a..78c43f9 100644 --- a/src/binary-io/data-stream.cpp +++ b/src/binary-io/data-stream.cpp @@ -41,10 +41,10 @@ void DataStream::writeString(QString string, quint64 length) // offset in the other stream. By default, this offset is the current offset of this stream. // This is most useful for storing unknown data and padding to prevent data loss // TODO: Come up with a more accurate name for this -void DataStream::readRawData(DataStream& stream, quint32 length, qint64 position) +void DataStream::readRawData(DataStream& other, quint32 length, qint64 position) { - position != -1 ? stream.seek(position) : stream.seek(pos()); - stream.device()->write(device()->read(length)); + position != -1 ? other.seek(position) : other.seek(pos()); + other.device()->write(device()->read(length)); } // Get the current offset the device is reading/writing from diff --git a/src/converter.cpp b/src/converter.cpp index 7ee1973..be685a0 100644 --- a/src/converter.cpp +++ b/src/converter.cpp @@ -11,8 +11,11 @@ #include +using namespace BrnTrigger; +using namespace tinygltf; + Converter::Converter(int argc, char* argv[]) - : triggerData(new BrnTrigger::TriggerData) + : triggerData(new TriggerData) { result = getArgs(argc, argv); if (result != 0) @@ -67,7 +70,7 @@ int Converter::getArgs(int argc, char* argv[]) int Converter::checkArgs(int argc, char* argv[]) { // Ensure minimum argument count is reached - if (argc < 3) + if (argc < minArgCount) { showUsage(); return 1; @@ -96,7 +99,7 @@ int Converter::checkArgs(int argc, char* argv[]) void Converter::showUsage() { - std::cout << "Usage: TriggersToGLTF [-p PLATFORM] \n\n" + std::cout << "Usage: TriggersToGLTF [-p PLATFORM] \n\n" << "Options:\n -p File platform. PS3, X360, PC, PS4, or NX. Default: PC"; } @@ -107,12 +110,6 @@ void Converter::readTriggerData() inStream.close(); } -// -------------------- -// GLTF stuff -// -------------------- - -using namespace tinygltf; - // Creates a file with the box regions converted to triangles // Saved as Matrix 3x3 (MAT3) Buffer Converter::createGLTFBuffer() @@ -240,13 +237,6 @@ void Converter::convertTriggersToGLTF() model->meshes[0].primitives[0].attributes["POSITION"] = 1; model->meshes[0].name = "Mesh"; - // TODO: Separate functions to have nodes for: - // Landmark, Blackspot, VFXBoxRegion (all TriggerRegion derived) - // SignatureStunt, Killzone (all containing GenericRegion arrays) - // Remaining GenericRegion triggers (checked against SignatureStunts and Killzones to avoid duplication) - // Remaining TriggerRegion triggers (checked against all of the above) - // Add starting grids, roaming locations, and spawn locations afterward - // Create nodes // TriggerRegion derived nodes int currentNodeCount = 0; @@ -383,7 +373,7 @@ void Converter::convertTriggersToGLTF() model->asset.generator = "tinygltf"; // Save it to a file - tinygltf::TinyGLTF gltf; + TinyGLTF gltf; gltf.WriteGltfSceneToFile(model.data(), outFileName, true, // embedImages true, // embedBuffers @@ -391,7 +381,7 @@ void Converter::convertTriggersToGLTF() false); // write binary } -bool Converter::triggerRegionExists(BrnTrigger::TriggerRegion region, bool checkGenericRegions) +bool Converter::triggerRegionExists(TriggerRegion region, bool checkGenericRegions) { int32_t id = region.getId(); for (int i = 0; i < triggerData->getLandmarkCount(); ++i) @@ -437,7 +427,7 @@ bool Converter::triggerRegionExists(BrnTrigger::TriggerRegion region, bool check return false; } -void Converter::addTriggerRegionFields(BrnTrigger::TriggerRegion region, Value::Object& extras) +void Converter::addTriggerRegionFields(TriggerRegion region, Value::Object& extras) { extras["TriggerRegion ID"] = Value(region.getId()); extras["TriggerRegion region index"] = Value(region.getRegionIndex()); @@ -445,7 +435,7 @@ void Converter::addTriggerRegionFields(BrnTrigger::TriggerRegion region, Value:: extras["TriggerRegion unknown 0"] = Value(region.getUnk0()); } -void Converter::convertLandmark(BrnTrigger::Landmark landmark, Node& node, int index) +void Converter::convertLandmark(Landmark landmark, Node& node, int index) { addBoxRegionTransform(landmark, node); @@ -459,13 +449,13 @@ void Converter::convertLandmark(BrnTrigger::Landmark landmark, Node& node, int i node.name = "Landmark " + std::to_string(index) + " (" + std::to_string(landmark.getId()) + ")"; } -void Converter::convertStartingGrid(BrnTrigger::StartingGrid grid, Node& node, int index) +void Converter::convertStartingGrid(StartingGrid grid, Node& node, int index) { for (int i = 0; i < 8; ++i) addPointTransform(grid.getStartingPosition(i), grid.getStartingDirection(i), node); } -void Converter::convertBlackspot(BrnTrigger::Blackspot blackspot, Node& node, int index) +void Converter::convertBlackspot(Blackspot blackspot, Node& node, int index) { addBoxRegionTransform(blackspot, node); @@ -478,14 +468,14 @@ void Converter::convertBlackspot(BrnTrigger::Blackspot blackspot, Node& node, in node.name = "Blackspot " + std::to_string(index) + " (" + std::to_string(blackspot.getId()) + ")"; } -void Converter::convertVfxBoxRegion(BrnTrigger::VFXBoxRegion vfxBoxRegion, Node& node, int index) +void Converter::convertVfxBoxRegion(VFXBoxRegion vfxBoxRegion, Node& node, int index) { addBoxRegionTransform(vfxBoxRegion, node); node.name = "VFXBoxRegion " + std::to_string(index) + " (" + std::to_string(vfxBoxRegion.getId()) + ")"; } -void Converter::convertSignatureStunt(BrnTrigger::SignatureStunt signatureStunt, Node& node, int index) +void Converter::convertSignatureStunt(SignatureStunt signatureStunt, Node& node, int index) { Value::Object extras; extras["ID"] = Value((int)signatureStunt.getId()); @@ -495,7 +485,7 @@ void Converter::convertSignatureStunt(BrnTrigger::SignatureStunt signatureStunt, node.name = "SignatureStunt " + std::to_string(index) + " (" + std::to_string(signatureStunt.getId()) + ")"; } -void Converter::convertKillzone(BrnTrigger::Killzone killzone, Node& node, int index) +void Converter::convertKillzone(Killzone killzone, Node& node, int index) { Value::Array regionIds; for (int i = 0; i < killzone.getRegionIdCount(); ++i) @@ -508,7 +498,7 @@ void Converter::convertKillzone(BrnTrigger::Killzone killzone, Node& node, int i node.name = "Killzone " + std::to_string(index); } -void Converter::convertGenericRegion(BrnTrigger::GenericRegion region, Node& node, int index) +void Converter::convertGenericRegion(GenericRegion region, Node& node, int index) { addBoxRegionTransform(region, node); @@ -529,14 +519,14 @@ void Converter::convertGenericRegion(BrnTrigger::GenericRegion region, Node& nod node.name = "GenericRegion " + std::to_string(index) + " (" + std::to_string(id) + ")"; } -void Converter::convertTriggerRegion(BrnTrigger::TriggerRegion triggerRegion, Node& node, int index) +void Converter::convertTriggerRegion(TriggerRegion triggerRegion, Node& node, int index) { addBoxRegionTransform(triggerRegion, node); node.name = "TriggerRegion " + std::to_string(index) + " (" + std::to_string(triggerRegion.getId()) + ")"; } -void Converter::convertRoamingLocation(BrnTrigger::RoamingLocation location, Node& node, int index) +void Converter::convertRoamingLocation(RoamingLocation location, Node& node, int index) { addPointTransform(location.getPosition(), node); @@ -547,7 +537,7 @@ void Converter::convertRoamingLocation(BrnTrigger::RoamingLocation location, Nod node.name = "RoamingLocation " + std::to_string(index); } -void Converter::convertSpawnLocation(BrnTrigger::SpawnLocation location, Node& node, int index) +void Converter::convertSpawnLocation(SpawnLocation location, Node& node, int index) { addPointTransform(location.getPosition(), location.getDirection(), node); diff --git a/src/trigger-data.cpp b/src/trigger-data.cpp index ed552d0..7b69c74 100644 --- a/src/trigger-data.cpp +++ b/src/trigger-data.cpp @@ -7,8 +7,8 @@ void TriggerData::read(DataStream& file) file >> versionNumber; file >> size; file.skip(0x8); - playerStartPosition.readVPU(file); - playerStartDirection.readVPU(file); + playerStartPosition.read(file); + playerStartDirection.read(file); file >> landmarks; file >> landmarkCount; file >> onlineLandmarkCount; @@ -51,66 +51,6 @@ void TriggerData::read(DataStream& file) file.cAllocAndCustomRead(regions[i], 1); } -Landmark TriggerData::getLandmark(int index) -{ - return landmarks[index]; -} - -SignatureStunt TriggerData::getSignatureStunt(int index) -{ - return signatureStunts[index]; -} - -GenericRegion TriggerData::getGenericRegion(int index) -{ - return genericRegions[index]; -} - -Killzone TriggerData::getKillzone(int index) -{ - return killzones[index]; -} - -Blackspot TriggerData::getBlackspot(int index) -{ - return blackspots[index]; -} - -VFXBoxRegion TriggerData::getVfxBoxRegion(int index) -{ - return vfxBoxRegions[index]; -} - -RoamingLocation TriggerData::getRoamingLocation(int index) -{ - return roamingLocations[index]; -} - -SpawnLocation TriggerData::getSpawnLocation(int index) -{ - return spawnLocations[index]; -} - -TriggerRegion TriggerData::getTriggerRegion(int index) -{ - return regions[index][0]; -} - -// Returns the number of box regions -int32_t TriggerData::getTotalRegionCount() -{ - int signatureStuntRegionCount = 0; - for (int i = 0; i < signatureStuntCount; ++i) - signatureStuntRegionCount += signatureStunts[i].getStuntElementCount(); - - int killzoneRegionCount = 0; - for (int i = 0; i < killzoneCount; ++i) - killzoneRegionCount += killzones[i].getTriggerCount(); - - return landmarkCount + signatureStuntRegionCount + genericRegionCount - + killzoneRegionCount + blackspotCount + vfxBoxRegionCount + regionCount; -} - void BoxRegion::read(DataStream& file) { file >> positionX; @@ -152,17 +92,21 @@ void Landmark::read(DataStream& file) file.seek(nextLandmark); } -StartingGrid Landmark::getStartingGrid(int index) +StartingGrid::StartingGrid() { - return startingGrids[index]; + for (int i = 0; i < 8; ++i) + { + startingPositions[i] = Vector3(true); + startingDirections[i] = Vector3(true); + } } void StartingGrid::read(DataStream& file) { for (int i = 0; i < 8; ++i) - startingPositions[i].readVPU(file); + startingPositions[i].read(file); for (int i = 0; i < 8; ++i) - startingDirections[i].readVPU(file); + startingDirections[i].read(file); } void SignatureStunt::read(DataStream& file) @@ -182,11 +126,6 @@ void SignatureStunt::read(DataStream& file) file.seek(nextSignatureStunt); } -GenericRegion SignatureStunt::getStuntElement(int index) -{ - return stuntElements[index][0]; -} - void GenericRegion::read(DataStream& file) { TriggerRegion::read(file); @@ -233,15 +172,15 @@ void VFXBoxRegion::read(DataStream& file) void RoamingLocation::read(DataStream& file) { - position.readVPU(file); + position.read(file); file >> districtIndex; file.skip(0xF); } void SpawnLocation::read(DataStream& file) { - position.readVPU(file); - direction.readVPU(file); + position.read(file); + direction.read(file); file >> junkyardId; file >> type; file.skip(0x7); diff --git a/src/types.cpp b/src/types.cpp new file mode 100644 index 0000000..602cfbe --- /dev/null +++ b/src/types.cpp @@ -0,0 +1,41 @@ +#include + +Vector3::Vector3(bool isVpu) + : isVpu(isVpu) +{ + +} + +Vector3::Vector3(float x, float y, float z, bool isVpu) + : x(x), y(y), z(z), isVpu(isVpu) +{ + +} + +void Vector3::read(DataStream& stream) +{ + stream >> x; + stream >> y; + stream >> z; + if (isVpu) + stream.skip(0x4); +} + +Vector4::Vector4() +{ + +} + +Vector4::Vector4(float x, float y, float z, float w) + : x(x), y(y), z(z), w(w) +{ + +} + +void Vector4::read(DataStream& stream) +{ + stream >> x; + stream >> y; + stream >> z; + stream >> w; +} From 6d477fbfad8ced480daf833ce17e29f537ff3322 Mon Sep 17 00:00:00 2001 From: burninrubber0 Date: Wed, 1 Mar 2023 14:17:45 -0500 Subject: [PATCH 2/6] Remove most getters Remove most getters, add setters to complement the remaining getters, change trigger and vector classes to structs, and remove unnecessary access specifiers. The getters and setters that remain are for pointers to pointers. --- include/converter.h | 52 ++++++------ include/trigger-data.h | 188 ++++++++++------------------------------- include/types.h | 21 ++--- src/converter.cpp | 172 ++++++++++++++++++------------------- src/types.cpp | 17 ++++ 5 files changed, 182 insertions(+), 268 deletions(-) diff --git a/include/converter.h b/include/converter.h index 936a491..ff325e8 100644 --- a/include/converter.h +++ b/include/converter.h @@ -57,54 +57,54 @@ class Converter void addBoxRegionTransform(T entry, Node& node) { node.translation = { - entry.getBoxRegion().getPosX(), - entry.getBoxRegion().getPosY(), - entry.getBoxRegion().getPosZ() + entry.boxRegion.positionX, + entry.boxRegion.positionY, + entry.boxRegion.positionZ }; Vector4 rotation = EulerToQuatRot({ - entry.getBoxRegion().getRotX(), - entry.getBoxRegion().getRotY(), - entry.getBoxRegion().getRotZ() + entry.boxRegion.rotationX, + entry.boxRegion.rotationY, + entry.boxRegion.rotationZ }); node.rotation = { - rotation.getX(), - rotation.getY(), - rotation.getZ(), - rotation.getW() + rotation.x, + rotation.y, + rotation.z, + rotation.w }; node.scale = { - entry.getBoxRegion().getDimX(), - entry.getBoxRegion().getDimY(), - entry.getBoxRegion().getDimZ() + entry.boxRegion.dimensionX, + entry.boxRegion.dimensionY, + entry.boxRegion.dimensionZ }; } void addPointTransform(Vector3 pos, Vector3 rot, Node& node) { node.translation = { - pos.getX(), - pos.getY(), - pos.getZ() + pos.x, + pos.y, + pos.z }; Vector4 rotation = EulerToQuatRot({ - rot.getX(), - rot.getY(), - rot.getZ() + rot.x, + rot.y, + rot.z }); node.rotation = { - rotation.getX(), - rotation.getY(), - rotation.getZ(), - rotation.getW() + rotation.x, + rotation.y, + rotation.z, + rotation.w }; } void addPointTransform(Vector3 pos, Node& node) { node.translation = { - pos.getX(), - pos.getY(), - pos.getZ() + pos.x, + pos.y, + pos.z }; } }; diff --git a/include/trigger-data.h b/include/trigger-data.h index 24fbce6..8fc6a0d 100644 --- a/include/trigger-data.h +++ b/include/trigger-data.h @@ -4,23 +4,13 @@ namespace BrnTrigger { - // Box trigger type. Sphere and line types are not supported. - class BoxRegion + // Transform for box triggers. + // Sphere and line types are not supported. + struct BoxRegion { - public: - void read(DataStream& file); + void read(DataStream& in); + void write(DataStream& out); - float getPosX() { return positionX; } - float getPosY() { return positionY; } - float getPosZ() { return positionZ; } - float getRotX() { return rotationX; } - float getRotY() { return rotationY; } - float getRotZ() { return rotationZ; } - float getDimX() { return dimensionX; } - float getDimY() { return dimensionY; } - float getDimZ() { return dimensionZ; } - - private: float32_t positionX = 0; float32_t positionY = 0; float32_t positionZ = 0; @@ -32,22 +22,9 @@ namespace BrnTrigger float32_t dimensionZ = 0; }; - // The actual data for the trigger. Used on nearly all types. - class TriggerRegion + // General container for box triggers. + struct TriggerRegion { - enum class Type : uint8_t; - - public: - void read(DataStream& file); - - BoxRegion getBoxRegion() { return boxRegion; } - int32_t getId() { return id; } - int16_t getRegionIndex() { return regionIndex; } - Type getType() { return type; } - uint8_t getUnk0() { return unk0; } - - private: - // The type of trigger region. enum class Type : uint8_t { landmark, @@ -56,6 +33,9 @@ namespace BrnTrigger vfxBoxRegion }; + void read(DataStream& file); + void write(DataStream& file); + BoxRegion boxRegion; int32_t id = 0; int16_t regionIndex = 0; @@ -64,44 +44,30 @@ namespace BrnTrigger }; // Starting grid for race events. Unused in retail. - class StartingGrid + struct StartingGrid { public: StartingGrid(); void read(DataStream& file); + void write(DataStream& file); - Vector3 getStartingPosition(int index) { return startingPositions[index]; } - Vector3 getStartingDirection(int index) { return startingDirections[index]; } - - private: Vector3 startingPositions[8]; Vector3 startingDirections[8]; }; - // Used for finish lines and event starts. + // Used for finish lines and checkpoints (but not event starts). // Big Surf Island has an overabundance of Landmarks. - class Landmark : public TriggerRegion + struct Landmark : public TriggerRegion { - enum class Flags : uint8_t; - - public: - void read(DataStream& file); - - StartingGrid getStartingGrid(int index) { return startingGrids[index]; } - int8_t getStartingGridCount() { return startingGridCount; } - uint8_t getDesignIndex() { return designIndex; } - uint8_t getDistrict() { return district; } - Flags getFlags() { return flags; } - bool getIsOnline() { return ((uint8_t)flags & (uint8_t)Flags::isOnline) != 0; }; - - private: - // The flags field in the Landmark structure. enum class Flags : uint8_t { isOnline = 1 << 0 }; + void read(DataStream& file); + void write(DataStream& file); + StartingGrid* startingGrids; int8_t startingGridCount = 0; uint8_t designIndex = 0; // Landmark-only index @@ -109,25 +75,9 @@ namespace BrnTrigger Flags flags = (Flags)0; }; - // Generic box trigger. The main trigger type used. Used for many things. - class GenericRegion : public TriggerRegion + // Generic box trigger. This is the main trigger type used by the game. + struct GenericRegion : public TriggerRegion { - enum class StuntCameraType : int8_t; - enum class Type : uint8_t; - - public: - void read(DataStream& file); - - int32_t getGroupId() { return groupId; } - int16_t getCameraCut1() { return cameraCut1; } - int16_t getCameraCut2() { return cameraCut2; } - StuntCameraType getcameraType1() { return cameraType1; } - StuntCameraType getcameraType2() { return cameraType2; } - Type getType() { return type; } - int8_t getIsOneWay() { return isOneWay; } - - private: - // Camera type used on GenericRegion stunts. enum class StuntCameraType : int8_t { noCuts, @@ -135,8 +85,6 @@ namespace BrnTrigger normal }; - // The type of generic region. Uses include audio, drivethru, and camera - // triggers, among others. enum class Type : uint8_t { junkyard, @@ -173,6 +121,9 @@ namespace BrnTrigger ramp }; + void read(DataStream& file); + void write(DataStream& file); + int32_t groupId = 0; // GameDB ID int16_t cameraCut1 = 0; int16_t cameraCut2 = 0; @@ -183,47 +134,37 @@ namespace BrnTrigger }; // Accident blackspot (crash mode). Unused in retail. - class Blackspot : public TriggerRegion + struct Blackspot : public TriggerRegion { - enum class ScoreType : uint8_t; - - public: - void read(DataStream& file); - - ScoreType getScoreType() { return scoreType; } - int32_t getScoreAmount() { return scoreAmount; } - - private: - // The Blackspot scoring system. Note that both are used in Showtime. enum class ScoreType : uint8_t { distance, carCount }; + void read(DataStream& file); + void write(DataStream& file); + ScoreType scoreType = (ScoreType)0; int32_t scoreAmount = 0; }; // VFX region. Unused in retail. - class VFXBoxRegion : public TriggerRegion + struct VFXBoxRegion : public TriggerRegion { - public: void read(DataStream& file); + void write(DataStream& file); }; // TODO: Description - class SignatureStunt + struct SignatureStunt { - public: void read(DataStream& file); + void write(DataStream& file); - CgsID getId() { return id; } - int64_t getCamera() { return camera; } GenericRegion getStuntElement(int index) { return stuntElements[index][0]; } - int32_t getStuntElementCount() { return stuntElementCount; } + void setStuntElement(GenericRegion region, int index) { stuntElements[index][0] = region; } - private: CgsID id = 0; int64_t camera = 0; GenericRegion** stuntElements = nullptr; @@ -231,17 +172,14 @@ namespace BrnTrigger }; // TODO: Description - class Killzone + struct Killzone { - public: void read(DataStream& file); + void write(DataStream& file); GenericRegion getTrigger(int index) { return triggers[index][0]; } - int32_t getTriggerCount() { return triggerCount; } - CgsID getRegionId(int index) { return regionIds[index]; } - int32_t getRegionIdCount() { return regionIdCount; } + void setTrigger(GenericRegion region, int index) { triggers[index][0] = region; } - private: GenericRegion** triggers = nullptr; int32_t triggerCount = 0; CgsID* regionIds = nullptr; // GameDB IDs @@ -249,34 +187,18 @@ namespace BrnTrigger }; // Spawn locations for roaming rivals (shutdown cars) - class RoamingLocation + struct RoamingLocation { - public: void read(DataStream& file); + void write(DataStream& file); - Vector3 getPosition() { return position; } - uint8_t getDistrictIndex() { return districtIndex; } - - private: Vector3 position = Vector3(true); uint8_t districtIndex = 0; }; // Vehicle spawn locations in and outside each Junkyard - class SpawnLocation + struct SpawnLocation { - enum class Type : uint8_t; - - public: - void read(DataStream& file); - - Vector3 getPosition() { return position; } - Vector3 getDirection() { return direction; } - CgsID getJunkyardId() { return junkyardId; } - Type getType() { return type; } - - private: - // The type of spawn at a spawn location. enum class Type : uint8_t { playerSpawn, @@ -285,6 +207,9 @@ namespace BrnTrigger carUnlock }; + void read(DataStream& file); + void write(DataStream& file); + Vector3 position = Vector3(true); Vector3 direction = Vector3(true); CgsID junkyardId = 0; // GameDB ID @@ -293,36 +218,14 @@ namespace BrnTrigger // The header for the TriggerData resource. // Lists all relevant offsets and counts. - class TriggerData + struct TriggerData { - public: void read(DataStream& file); + void write(DataStream& file); + + TriggerRegion getRegion(int index) { return regions[index][0]; } + void setRegion(TriggerRegion region, int index) { regions[index][0] = region; } - int32_t getVersionNumber() { return versionNumber; } - uint32_t getSize() { return size; } - Vector3 getPlayerStartPosition() { return playerStartPosition; } - Vector3 getPlayerStartDirection() { return playerStartDirection; } - Landmark getLandmark(int index) { return landmarks[index]; } - int32_t getLandmarkCount() { return landmarkCount; } - int32_t getOnlineLandmarkCount() { return onlineLandmarkCount; } - SignatureStunt getSignatureStunt(int index) { return signatureStunts[index]; } - int32_t getSignatureStuntCount() { return signatureStuntCount; } - GenericRegion getGenericRegion(int index) { return genericRegions[index]; } - int32_t getGenericRegionCount() { return genericRegionCount; } - Killzone getKillzone(int index) { return killzones[index]; } - int32_t getKillzoneCount() { return killzoneCount; } - Blackspot getBlackspot(int index) { return blackspots[index]; } - int32_t getBlackspotCount() { return blackspotCount; } - VFXBoxRegion getVfxBoxRegion(int index) { return vfxBoxRegions[index]; } - int32_t getVfxBoxRegionCount() { return vfxBoxRegionCount; } - RoamingLocation getRoamingLocation(int index) { return roamingLocations[index]; } - int32_t getRoamingLocationCount() { return roamingLocationCount; } - SpawnLocation getSpawnLocation(int index) { return spawnLocations[index]; } - int32_t getSpawnLocationCount() { return spawnLocationCount; } - TriggerRegion getTriggerRegion(int index) { return regions[index][0]; } - int32_t getRegionCount() { return regionCount; } - - private: int32_t versionNumber = 0; uint32_t size = 0; Vector3 playerStartPosition = Vector3(true); @@ -336,7 +239,6 @@ namespace BrnTrigger int32_t genericRegionCount = 0; Killzone* killzones = nullptr; int32_t killzoneCount = 0; - Blackspot* fileBlackspots = nullptr; Blackspot* blackspots = nullptr; int32_t blackspotCount = 0; VFXBoxRegion* vfxBoxRegions = nullptr; diff --git a/include/types.h b/include/types.h index 21d1bb1..5795b8c 100644 --- a/include/types.h +++ b/include/types.h @@ -9,40 +9,35 @@ typedef float float32_t; typedef uint64_t CgsID; -class Vector3 +struct Vector3 { -public: Vector3(bool isVpu = false); Vector3(float x, float y, float z, bool vpu = false); void read(DataStream& stream); + void write(DataStream& stream); - float getX() { return x; } - float getY() { return y; } - float getZ() { return z; } bool getIsVpu() { return isVpu; } -private: + void setIsVpu(bool val) { isVpu = val; } + float x = 0; float y = 0; float z = 0; + +private: bool isVpu = false; }; -class Vector4 +struct Vector4 { public: Vector4(); Vector4(float x, float y, float z, float w); void read(DataStream& stream); + void write(DataStream& stream); - float getX() { return x; } - float getY() { return y; } - float getZ() { return z; } - float getW() { return w; } - -private: float x = 0; float y = 0; float z = 0; diff --git a/src/converter.cpp b/src/converter.cpp index be685a0..80c8ce8 100644 --- a/src/converter.cpp +++ b/src/converter.cpp @@ -166,12 +166,12 @@ void Converter::writeBoxRegion(DataStream& stream) // Modified from https://stackoverflow.com/a/70462919 Vector4 Converter::EulerToQuatRot(Vector3 euler) { - float cy = (float)qCos(euler.getZ() * 0.5); - float sy = (float)qSin(euler.getZ() * 0.5); - float cp = (float)qCos(euler.getY() * 0.5); - float sp = (float)qSin(euler.getY() * 0.5); - float cr = (float)qCos(euler.getX() * 0.5); - float sr = (float)qSin(euler.getX() * 0.5); + float cy = (float)qCos(euler.z * 0.5); + float sy = (float)qSin(euler.z * 0.5); + float cp = (float)qCos(euler.y * 0.5); + float sp = (float)qSin(euler.y * 0.5); + float cr = (float)qCos(euler.x * 0.5); + float sr = (float)qSin(euler.x * 0.5); return Vector4( sr * cp * cy + cr * sp * sy, @@ -242,38 +242,38 @@ void Converter::convertTriggersToGLTF() int currentNodeCount = 0; int landmarkNodeIndex = currentNodeCount; int landmarkChildCount = 0; - for (int i = 0; i < triggerData->getLandmarkCount(); ++i) + for (int i = 0; i < triggerData->landmarkCount; ++i) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; - for (int j = 0; j < triggerData->getLandmark(i).getStartingGridCount(); ++j) + for (int j = 0; j < triggerData->landmarks[i].startingGridCount; ++j) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; model->nodes[landmarkNodeIndex + i + landmarkChildCount].children.push_back(landmarkNodeIndex + i + landmarkChildCount + j + 1); - convertStartingGrid(triggerData->getLandmark(i).getStartingGrid(j), model->nodes[landmarkNodeIndex + i + landmarkChildCount + j + 1], j); + convertStartingGrid(triggerData->landmarks[i].startingGrids[j], model->nodes[landmarkNodeIndex + i + landmarkChildCount + j + 1], j); currentNodeCount++; } - convertLandmark(triggerData->getLandmark(i), model->nodes[i + landmarkNodeIndex], i); + convertLandmark(triggerData->landmarks[i], model->nodes[i + landmarkNodeIndex], i); currentNodeCount++; - landmarkChildCount += triggerData->getLandmark(i).getStartingGridCount(); - model->scenes[0].nodes.push_back(landmarkNodeIndex + i + landmarkChildCount - triggerData->getLandmark(i).getStartingGridCount()); + landmarkChildCount += triggerData->landmarks[i].startingGridCount; + model->scenes[0].nodes.push_back(landmarkNodeIndex + i + landmarkChildCount - triggerData->landmarks[i].startingGridCount); } int blackspotNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->getBlackspotCount(); ++i) + for (int i = 0; i < triggerData->blackspotCount; ++i) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; - convertBlackspot(triggerData->getBlackspot(i), model->nodes[blackspotNodeIndex + i], i); + convertBlackspot(triggerData->blackspots[i], model->nodes[blackspotNodeIndex + i], i); currentNodeCount++; model->scenes[0].nodes.push_back(blackspotNodeIndex + i); } int vfxBoxRegionNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->getVfxBoxRegionCount(); ++i) + for (int i = 0; i < triggerData->vfxBoxRegionCount; ++i) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; - convertVfxBoxRegion(triggerData->getVfxBoxRegion(i), model->nodes[vfxBoxRegionNodeIndex + i], i); + convertVfxBoxRegion(triggerData->vfxBoxRegions[i], model->nodes[vfxBoxRegionNodeIndex + i], i); currentNodeCount++; model->scenes[0].nodes.push_back(vfxBoxRegionNodeIndex + i); } @@ -281,51 +281,51 @@ void Converter::convertTriggersToGLTF() // Nodes with GenericRegion arrays int signatureStuntNodeIndex = currentNodeCount; int signatureStuntChildCount = 0; - for (int i = 0; i < triggerData->getSignatureStuntCount(); ++i) + for (int i = 0; i < triggerData->signatureStuntCount; ++i) { model->nodes.push_back(Node()); - for (int j = 0; j < triggerData->getSignatureStunt(i).getStuntElementCount(); ++j) + for (int j = 0; j < triggerData->signatureStunts[i].stuntElementCount; ++j) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount].children.push_back(signatureStuntNodeIndex + i + signatureStuntChildCount + j + 1); - convertGenericRegion(triggerData->getSignatureStunt(i).getStuntElement(j), model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount + j + 1], j); + convertGenericRegion(triggerData->signatureStunts[i].getStuntElement(j), model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount + j + 1], j); currentNodeCount++; } - convertSignatureStunt(triggerData->getSignatureStunt(i), model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount], i); + convertSignatureStunt(triggerData->signatureStunts[i], model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount], i); currentNodeCount++; - signatureStuntChildCount += triggerData->getSignatureStunt(i).getStuntElementCount(); - model->scenes[0].nodes.push_back(signatureStuntNodeIndex + i + signatureStuntChildCount - triggerData->getSignatureStunt(i).getStuntElementCount()); + signatureStuntChildCount += triggerData->signatureStunts[i].stuntElementCount; + model->scenes[0].nodes.push_back(signatureStuntNodeIndex + i + signatureStuntChildCount - triggerData->signatureStunts[i].stuntElementCount); } int killzoneNodeIndex = currentNodeCount; int killzoneChildCount = 0; - for (int i = 0; i < triggerData->getKillzoneCount(); ++i) + for (int i = 0; i < triggerData->killzoneCount; ++i) { model->nodes.push_back(Node()); - for (int j = 0; j < triggerData->getKillzone(i).getTriggerCount(); ++j) + for (int j = 0; j < triggerData->killzones[i].triggerCount; ++j) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; model->nodes[killzoneNodeIndex + i + killzoneChildCount].children.push_back(killzoneNodeIndex + i + killzoneChildCount + j + 1); - convertGenericRegion(triggerData->getKillzone(i).getTrigger(j), model->nodes[killzoneNodeIndex + i + killzoneChildCount + j + 1], j); + convertGenericRegion(triggerData->killzones[i].getTrigger(j), model->nodes[killzoneNodeIndex + i + killzoneChildCount + j + 1], j); currentNodeCount++; } - convertKillzone(triggerData->getKillzone(i), model->nodes[killzoneNodeIndex + i + killzoneChildCount], i); + convertKillzone(triggerData->killzones[i], model->nodes[killzoneNodeIndex + i + killzoneChildCount], i); currentNodeCount++; - killzoneChildCount += triggerData->getKillzone(i).getTriggerCount(); - model->scenes[0].nodes.push_back(killzoneNodeIndex + i + killzoneChildCount - triggerData->getKillzone(i).getTriggerCount()); + killzoneChildCount += triggerData->killzones[i].triggerCount; + model->scenes[0].nodes.push_back(killzoneNodeIndex + i + killzoneChildCount - triggerData->killzones[i].triggerCount); } // Remaining GenericRegion nodes int genericRegionNodeIndex = currentNodeCount; int currentGenericRegionNode = 0; - for (int i = 0; i < triggerData->getGenericRegionCount(); ++i) + for (int i = 0; i < triggerData->genericRegionCount; ++i) { - if (!triggerRegionExists(triggerData->getGenericRegion(i), false)) + if (!triggerRegionExists(triggerData->genericRegions[i], false)) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; - convertGenericRegion(triggerData->getGenericRegion(i), model->nodes[genericRegionNodeIndex + currentGenericRegionNode], i); + convertGenericRegion(triggerData->genericRegions[i], model->nodes[genericRegionNodeIndex + currentGenericRegionNode], i); model->scenes[0].nodes.push_back(genericRegionNodeIndex + currentGenericRegionNode); currentGenericRegionNode++; currentNodeCount++; @@ -335,13 +335,13 @@ void Converter::convertTriggersToGLTF() // Remaining TriggerRegion nodes int triggerRegionNodeIndex = currentNodeCount; int currentTriggerRegionNode = 0; - for (int i = 0; i < triggerData->getRegionCount(); ++i) + for (int i = 0; i < triggerData->regionCount; ++i) { - if (!triggerRegionExists(triggerData->getTriggerRegion(i))) + if (!triggerRegionExists(triggerData->getRegion(i))) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; - convertTriggerRegion(triggerData->getTriggerRegion(i), model->nodes[triggerRegionNodeIndex + currentTriggerRegionNode], i); + convertTriggerRegion(triggerData->getRegion(i), model->nodes[triggerRegionNodeIndex + currentTriggerRegionNode], i); model->scenes[0].nodes.push_back(triggerRegionNodeIndex + currentTriggerRegionNode); currentTriggerRegionNode++; currentNodeCount++; @@ -350,20 +350,20 @@ void Converter::convertTriggersToGLTF() // Point triggers int roamingLocationNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->getRoamingLocationCount(); ++i) + for (int i = 0; i < triggerData->roamingLocationCount; ++i) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; - convertRoamingLocation(triggerData->getRoamingLocation(i), model->nodes[roamingLocationNodeIndex + i], i); + convertRoamingLocation(triggerData->roamingLocations[i], model->nodes[roamingLocationNodeIndex + i], i); currentNodeCount++; model->scenes[0].nodes.push_back(roamingLocationNodeIndex + i); } int spawnLocationNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->getSpawnLocationCount(); ++i) + for (int i = 0; i < triggerData->spawnLocationCount; ++i) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; - convertSpawnLocation(triggerData->getSpawnLocation(i), model->nodes[spawnLocationNodeIndex + i], i); + convertSpawnLocation(triggerData->spawnLocations[i], model->nodes[spawnLocationNodeIndex + i], i); currentNodeCount++; model->scenes[0].nodes.push_back(spawnLocationNodeIndex + i); } @@ -383,44 +383,44 @@ void Converter::convertTriggersToGLTF() bool Converter::triggerRegionExists(TriggerRegion region, bool checkGenericRegions) { - int32_t id = region.getId(); - for (int i = 0; i < triggerData->getLandmarkCount(); ++i) + int32_t id = region.id; + for (int i = 0; i < triggerData->landmarkCount; ++i) { - if (id == triggerData->getLandmark(i).getId()) + if (id == triggerData->landmarks[i].id) return true; } - for (int i = 0; i < triggerData->getBlackspotCount(); ++i) + for (int i = 0; i < triggerData->blackspotCount; ++i) { - if (id == triggerData->getBlackspot(i).getId()) + if (id == triggerData->blackspots[i].id) return true; } - for (int i = 0; i < triggerData->getVfxBoxRegionCount(); ++i) + for (int i = 0; i < triggerData->vfxBoxRegionCount; ++i) { - if (id == triggerData->getVfxBoxRegion(i).getId()) + if (id == triggerData->vfxBoxRegions[i].id) return true; } if (checkGenericRegions) { - for (int i = 0; i < triggerData->getGenericRegionCount(); ++i) + for (int i = 0; i < triggerData->genericRegionCount; ++i) { - if (id == triggerData->getGenericRegion(i).getId()) + if (id == triggerData->genericRegions[i].id) return true; } return false; } - for (int i = 0; i < triggerData->getSignatureStuntCount(); ++i) + for (int i = 0; i < triggerData->signatureStuntCount; ++i) { - for (int j = 0; j < triggerData->getSignatureStunt(i).getStuntElementCount(); ++j) + for (int j = 0; j < triggerData->signatureStunts[i].stuntElementCount; ++j) { - if (id == triggerData->getSignatureStunt(i).getStuntElement(j).getId()) + if (id == triggerData->signatureStunts[i].getStuntElement(j).id) return true; } } - for (int i = 0; i < triggerData->getKillzoneCount(); ++i) + for (int i = 0; i < triggerData->killzoneCount; ++i) { - for (int j = 0; j < triggerData->getKillzone(i).getTriggerCount(); ++j) + for (int j = 0; j < triggerData->killzones[i].triggerCount; ++j) { - if (id == triggerData->getKillzone(i).getTrigger(j).getId()) + if (id == triggerData->killzones[i].getTrigger(j).id) return true; } } @@ -429,10 +429,10 @@ bool Converter::triggerRegionExists(TriggerRegion region, bool checkGenericRegio void Converter::addTriggerRegionFields(TriggerRegion region, Value::Object& extras) { - extras["TriggerRegion ID"] = Value(region.getId()); - extras["TriggerRegion region index"] = Value(region.getRegionIndex()); - extras["TriggerRegion type"] = Value((uint8_t)region.getType()); - extras["TriggerRegion unknown 0"] = Value(region.getUnk0()); + extras["TriggerRegion ID"] = Value(region.id); + extras["TriggerRegion region index"] = Value(region.regionIndex); + extras["TriggerRegion type"] = Value((uint8_t)region.type); + extras["TriggerRegion unknown 0"] = Value(region.unk0); } void Converter::convertLandmark(Landmark landmark, Node& node, int index) @@ -441,18 +441,18 @@ void Converter::convertLandmark(Landmark landmark, Node& node, int index) Value::Object extras; addTriggerRegionFields(landmark, extras); - extras["Design index"] = Value(landmark.getDesignIndex()); - extras["District"] = Value(landmark.getDistrict()); - extras["Is online"] = Value(landmark.getIsOnline()); + extras["Design index"] = Value(landmark.designIndex); + extras["District"] = Value(landmark.district); + extras["Is online"] = Value((bool)(((uint8_t)landmark.flags & (uint8_t)Landmark::Flags::isOnline) != 0)); node.extras = Value(extras); - node.name = "Landmark " + std::to_string(index) + " (" + std::to_string(landmark.getId()) + ")"; + node.name = "Landmark " + std::to_string(index) + " (" + std::to_string(landmark.id) + ")"; } void Converter::convertStartingGrid(StartingGrid grid, Node& node, int index) { for (int i = 0; i < 8; ++i) - addPointTransform(grid.getStartingPosition(i), grid.getStartingDirection(i), node); + addPointTransform(grid.startingPositions[i], grid.startingDirections[i], node); } void Converter::convertBlackspot(Blackspot blackspot, Node& node, int index) @@ -461,35 +461,35 @@ void Converter::convertBlackspot(Blackspot blackspot, Node& node, int index) Value::Object extras; addTriggerRegionFields(blackspot, extras); - extras["Score type"] = Value((uint8_t)blackspot.getScoreType()); - extras["Score amount"] = Value(blackspot.getScoreAmount()); + extras["Score type"] = Value((uint8_t)blackspot.scoreType); + extras["Score amount"] = Value(blackspot.scoreAmount); node.extras = Value(extras); - node.name = "Blackspot " + std::to_string(index) + " (" + std::to_string(blackspot.getId()) + ")"; + node.name = "Blackspot " + std::to_string(index) + " (" + std::to_string(blackspot.id) + ")"; } void Converter::convertVfxBoxRegion(VFXBoxRegion vfxBoxRegion, Node& node, int index) { addBoxRegionTransform(vfxBoxRegion, node); - node.name = "VFXBoxRegion " + std::to_string(index) + " (" + std::to_string(vfxBoxRegion.getId()) + ")"; + node.name = "VFXBoxRegion " + std::to_string(index) + " (" + std::to_string(vfxBoxRegion.id) + ")"; } void Converter::convertSignatureStunt(SignatureStunt signatureStunt, Node& node, int index) { Value::Object extras; - extras["ID"] = Value((int)signatureStunt.getId()); - extras["Camera"] = Value((int)signatureStunt.getCamera()); + extras["ID"] = Value((int)signatureStunt.id); + extras["Camera"] = Value((int)signatureStunt.camera); node.extras = Value(extras); - node.name = "SignatureStunt " + std::to_string(index) + " (" + std::to_string(signatureStunt.getId()) + ")"; + node.name = "SignatureStunt " + std::to_string(index) + " (" + std::to_string(signatureStunt.id) + ")"; } void Converter::convertKillzone(Killzone killzone, Node& node, int index) { Value::Array regionIds; - for (int i = 0; i < killzone.getRegionIdCount(); ++i) - regionIds.push_back(Value((int)killzone.getRegionId(i))); + for (int i = 0; i < killzone.regionIdCount; ++i) + regionIds.push_back(Value((int)killzone.regionIds[i])); Value::Object extras; extras["Region IDs"] = Value(regionIds); @@ -504,18 +504,18 @@ void Converter::convertGenericRegion(GenericRegion region, Node& node, int index Value::Object extras; addTriggerRegionFields(region, extras); - extras["Group ID"] = Value(region.getGroupId()); - extras["Camera cut 1"] = Value(region.getCameraCut1()); - extras["Camera cut 2"] = Value(region.getCameraCut2()); - extras["Camera type 1"] = Value((int16_t)region.getcameraType1()); - extras["Camera type 2"] = Value((int16_t)region.getcameraType2()); - extras["Type"] = Value((uint8_t)region.getType()); - extras["Is one way"] = Value((bool)region.getIsOneWay()); + extras["Group ID"] = Value(region.groupId); + extras["Camera cut 1"] = Value(region.cameraCut1); + extras["Camera cut 2"] = Value(region.cameraCut2); + extras["Camera type 1"] = Value((int16_t)region.cameraType1); + extras["Camera type 2"] = Value((int16_t)region.cameraType2); + extras["Type"] = Value((uint8_t)region.type); + extras["Is one way"] = Value((bool)region.isOneWay); node.extras = Value(extras); - uint64_t id = region.getGroupId(); + uint64_t id = region.groupId; if (id == 0) - id = region.getId(); + id = region.id; node.name = "GenericRegion " + std::to_string(index) + " (" + std::to_string(id) + ")"; } @@ -523,15 +523,15 @@ void Converter::convertTriggerRegion(TriggerRegion triggerRegion, Node& node, in { addBoxRegionTransform(triggerRegion, node); - node.name = "TriggerRegion " + std::to_string(index) + " (" + std::to_string(triggerRegion.getId()) + ")"; + node.name = "TriggerRegion " + std::to_string(index) + " (" + std::to_string(triggerRegion.id) + ")"; } void Converter::convertRoamingLocation(RoamingLocation location, Node& node, int index) { - addPointTransform(location.getPosition(), node); + addPointTransform(location.position, node); Value::Object extras; - extras["District index"] = Value(location.getDistrictIndex()); + extras["District index"] = Value(location.districtIndex); node.extras = Value(extras); node.name = "RoamingLocation " + std::to_string(index); @@ -539,11 +539,11 @@ void Converter::convertRoamingLocation(RoamingLocation location, Node& node, int void Converter::convertSpawnLocation(SpawnLocation location, Node& node, int index) { - addPointTransform(location.getPosition(), location.getDirection(), node); + addPointTransform(location.position, location.direction, node); Value::Object extras; - extras["Junkyard ID"] = Value((int)location.getJunkyardId()); - extras["Type"] = Value((uint8_t)location.getType()); + extras["Junkyard ID"] = Value((int)location.junkyardId); + extras["Type"] = Value((uint8_t)location.type); node.extras = Value(extras); node.name = "SpawnLocation " + std::to_string(index); diff --git a/src/types.cpp b/src/types.cpp index 602cfbe..c7687a3 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -21,6 +21,15 @@ void Vector3::read(DataStream& stream) stream.skip(0x4); } +void Vector3::write(DataStream& stream) +{ + stream << x; + stream << y; + stream << z; + if (isVpu) + stream.skip(0x4); +} + Vector4::Vector4() { @@ -39,3 +48,11 @@ void Vector4::read(DataStream& stream) stream >> z; stream >> w; } + +void Vector4::write(DataStream& stream) +{ + stream << x; + stream << y; + stream << z; + stream << w; +} From 1e17c038f31790f512b0aab2b1581dde34583dd9 Mon Sep 17 00:00:00 2001 From: burninrubber0 Date: Wed, 2 Aug 2023 19:48:42 -0400 Subject: [PATCH 3/6] Force filtering --- include/converter.h | 1 + src/converter.cpp | 127 +++++--------------------------------------- 2 files changed, 13 insertions(+), 115 deletions(-) diff --git a/include/converter.h b/include/converter.h index ff325e8..ec8e66f 100644 --- a/include/converter.h +++ b/include/converter.h @@ -25,6 +25,7 @@ class Converter DataStream inStream; std::string inFileName; std::string outFileName; + uint8_t typeFilter = -1; TriggerData* triggerData = nullptr; diff --git a/src/converter.cpp b/src/converter.cpp index 80c8ce8..f348c28 100644 --- a/src/converter.cpp +++ b/src/converter.cpp @@ -53,6 +53,13 @@ int Converter::getArgs(int argc, char* argv[]) inStream.setIs64Bit(true); i++; } + else if (strcmp(argv[i], "-f") == 0) + { + uint8_t filter = atoi(argv[i + 1]); + if (filter >= 0) + typeFilter = filter; + i++; + } else { std::cerr << "Invalid option specified: " << argv[i]; @@ -99,8 +106,9 @@ int Converter::checkArgs(int argc, char* argv[]) void Converter::showUsage() { - std::cout << "Usage: TriggersToGLTF [-p PLATFORM] \n\n" - << "Options:\n -p File platform. PS3, X360, PC, PS4, or NX. Default: PC"; + std::cout << "Usage: TriggersToGLTF [options] \n\n" + << "Options:\n -p File platform. PS3, X360, PC, PS4, or NX. Default: PC\n" + << " -f GenericRegion type filter (an integer number). By default, all are converted."; } void Converter::readTriggerData() @@ -240,88 +248,13 @@ void Converter::convertTriggersToGLTF() // Create nodes // TriggerRegion derived nodes int currentNodeCount = 0; - int landmarkNodeIndex = currentNodeCount; - int landmarkChildCount = 0; - for (int i = 0; i < triggerData->landmarkCount; ++i) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - for (int j = 0; j < triggerData->landmarks[i].startingGridCount; ++j) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - model->nodes[landmarkNodeIndex + i + landmarkChildCount].children.push_back(landmarkNodeIndex + i + landmarkChildCount + j + 1); - convertStartingGrid(triggerData->landmarks[i].startingGrids[j], model->nodes[landmarkNodeIndex + i + landmarkChildCount + j + 1], j); - currentNodeCount++; - } - convertLandmark(triggerData->landmarks[i], model->nodes[i + landmarkNodeIndex], i); - currentNodeCount++; - landmarkChildCount += triggerData->landmarks[i].startingGridCount; - model->scenes[0].nodes.push_back(landmarkNodeIndex + i + landmarkChildCount - triggerData->landmarks[i].startingGridCount); - } - int blackspotNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->blackspotCount; ++i) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - convertBlackspot(triggerData->blackspots[i], model->nodes[blackspotNodeIndex + i], i); - currentNodeCount++; - model->scenes[0].nodes.push_back(blackspotNodeIndex + i); - } - int vfxBoxRegionNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->vfxBoxRegionCount; ++i) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - convertVfxBoxRegion(triggerData->vfxBoxRegions[i], model->nodes[vfxBoxRegionNodeIndex + i], i); - currentNodeCount++; - model->scenes[0].nodes.push_back(vfxBoxRegionNodeIndex + i); - } - - // Nodes with GenericRegion arrays - int signatureStuntNodeIndex = currentNodeCount; - int signatureStuntChildCount = 0; - for (int i = 0; i < triggerData->signatureStuntCount; ++i) - { - model->nodes.push_back(Node()); - for (int j = 0; j < triggerData->signatureStunts[i].stuntElementCount; ++j) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount].children.push_back(signatureStuntNodeIndex + i + signatureStuntChildCount + j + 1); - convertGenericRegion(triggerData->signatureStunts[i].getStuntElement(j), model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount + j + 1], j); - currentNodeCount++; - } - convertSignatureStunt(triggerData->signatureStunts[i], model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount], i); - currentNodeCount++; - signatureStuntChildCount += triggerData->signatureStunts[i].stuntElementCount; - model->scenes[0].nodes.push_back(signatureStuntNodeIndex + i + signatureStuntChildCount - triggerData->signatureStunts[i].stuntElementCount); - } - int killzoneNodeIndex = currentNodeCount; - int killzoneChildCount = 0; - for (int i = 0; i < triggerData->killzoneCount; ++i) - { - model->nodes.push_back(Node()); - for (int j = 0; j < triggerData->killzones[i].triggerCount; ++j) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - model->nodes[killzoneNodeIndex + i + killzoneChildCount].children.push_back(killzoneNodeIndex + i + killzoneChildCount + j + 1); - convertGenericRegion(triggerData->killzones[i].getTrigger(j), model->nodes[killzoneNodeIndex + i + killzoneChildCount + j + 1], j); - currentNodeCount++; - } - convertKillzone(triggerData->killzones[i], model->nodes[killzoneNodeIndex + i + killzoneChildCount], i); - currentNodeCount++; - killzoneChildCount += triggerData->killzones[i].triggerCount; - model->scenes[0].nodes.push_back(killzoneNodeIndex + i + killzoneChildCount - triggerData->killzones[i].triggerCount); - } - + // Remaining GenericRegion nodes int genericRegionNodeIndex = currentNodeCount; int currentGenericRegionNode = 0; for (int i = 0; i < triggerData->genericRegionCount; ++i) { - if (!triggerRegionExists(triggerData->genericRegions[i], false)) + if ((uint8_t)triggerData->genericRegions[i].type == typeFilter) { model->nodes.push_back(Node()); model->nodes.back().mesh = 0; @@ -332,42 +265,6 @@ void Converter::convertTriggersToGLTF() } } - // Remaining TriggerRegion nodes - int triggerRegionNodeIndex = currentNodeCount; - int currentTriggerRegionNode = 0; - for (int i = 0; i < triggerData->regionCount; ++i) - { - if (!triggerRegionExists(triggerData->getRegion(i))) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - convertTriggerRegion(triggerData->getRegion(i), model->nodes[triggerRegionNodeIndex + currentTriggerRegionNode], i); - model->scenes[0].nodes.push_back(triggerRegionNodeIndex + currentTriggerRegionNode); - currentTriggerRegionNode++; - currentNodeCount++; - } - } - - // Point triggers - int roamingLocationNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->roamingLocationCount; ++i) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - convertRoamingLocation(triggerData->roamingLocations[i], model->nodes[roamingLocationNodeIndex + i], i); - currentNodeCount++; - model->scenes[0].nodes.push_back(roamingLocationNodeIndex + i); - } - int spawnLocationNodeIndex = currentNodeCount; - for (int i = 0; i < triggerData->spawnLocationCount; ++i) - { - model->nodes.push_back(Node()); - model->nodes.back().mesh = 0; - convertSpawnLocation(triggerData->spawnLocations[i], model->nodes[spawnLocationNodeIndex + i], i); - currentNodeCount++; - model->scenes[0].nodes.push_back(spawnLocationNodeIndex + i); - } - // Set up asset model->asset.version = "2.0"; model->asset.generator = "tinygltf"; From be42fb5fed7fb658deb147a3ff9b9c028ea002e1 Mon Sep 17 00:00:00 2001 From: burninrubber0 Date: Mon, 16 Oct 2023 19:04:41 -0400 Subject: [PATCH 4/6] Only save triggers not in savegame --- include/converter.h | 3 ++ src/converter.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/include/converter.h b/include/converter.h index ec8e66f..57b328b 100644 --- a/include/converter.h +++ b/include/converter.h @@ -26,8 +26,10 @@ class Converter std::string inFileName; std::string outFileName; uint8_t typeFilter = -1; + std::string profileFileName; TriggerData* triggerData = nullptr; + QList hitTriggerIds; const int minArgCount = 3; int getArgs(int argc, char* argv[]); @@ -35,6 +37,7 @@ class Converter void showUsage(); void readTriggerData(); + void readProfileTriggers(); Buffer createGLTFBuffer(); void writeBoxRegion(DataStream& stream); Vector4 EulerToQuatRot(Vector3 euler); diff --git a/src/converter.cpp b/src/converter.cpp index f348c28..6585b3a 100644 --- a/src/converter.cpp +++ b/src/converter.cpp @@ -22,6 +22,8 @@ Converter::Converter(int argc, char* argv[]) return; readTriggerData(); + if (!profileFileName.empty()) + readProfileTriggers(); convertTriggersToGLTF(); } @@ -60,6 +62,12 @@ int Converter::getArgs(int argc, char* argv[]) typeFilter = filter; i++; } + else if (strcmp(argv[i], "-s") == 0) + { + profileFileName = argv[i + 1]; + // TODO: Check profile validity + i++; + } else { std::cerr << "Invalid option specified: " << argv[i]; @@ -118,6 +126,88 @@ void Converter::readTriggerData() inStream.close(); } +void Converter::readProfileTriggers() +{ + DataStream profile; + profile.setDevice(new QFile(QString::fromStdString(profileFileName))); + profile.open(QIODevice::ReadOnly); + + // BPR PC support only for now. No checks + int base = 0x1D246; // Profile start offset + int stunts = base + 0x75E8; // Stunt elements offset + int alloc = 512; // Number of stunt elements allocated per type + int jumpCount = 0; + int smashCount = 0; + int billboardCount = 0; + profile.seek(stunts + alloc * 8); + profile >> jumpCount; + profile.seek(stunts + alloc * 8 * 2 + 8); + profile >> smashCount; + profile.seek(stunts + alloc * 8 * 3 + 8 * 2); + profile >> billboardCount; + uint64_t tmpId = 0; + profile.seek(stunts); // Jumps + for (int i = 0; i < jumpCount; ++i) + { + profile >> tmpId; + hitTriggerIds.append(tmpId); + } + profile.seek(stunts + alloc * 8 + 8); // Smashes + for (int i = 0; i < smashCount; ++i) + { + profile >> tmpId; + hitTriggerIds.append(tmpId); + } + profile.seek(stunts + alloc * 8 * 2 + 8 * 2); // Billboards + for (int i = 0; i < billboardCount; ++i) + { + profile >> tmpId; + hitTriggerIds.append(tmpId); + } + + // Island collectibles + int bsi = base + 0x79040; + int bsiBillboards = bsi + 0x31C; + int bsiSmashes = bsi + 0x488; + int bsiJumps = bsi + 0x6E4; + int bsiBillboardAlloc = 45; + int bsiSmashAlloc = 75; + int bsiJumpAlloc = 15; + int bsiBillboardCount = 0; + int bsiSmashCount = 0; + int bsiJumpCount = 0; + profile.seek(bsiBillboards + bsiBillboardAlloc * 8); + profile >> bsiBillboardCount; + profile.seek(bsiSmashes + bsiSmashAlloc + 8); + profile >> bsiSmashCount; + profile.seek(bsiJumps + bsiJumpAlloc * 8); + profile >> bsiJumpCount; + uint32_t tmpBsiId = 0; + profile.seek(bsiBillboards); // Island billboards + for (int i = 0; i < bsiBillboardCount; ++i) + { + profile >> tmpBsiId; + profile.skip(4); + hitTriggerIds.append((uint64_t)tmpBsiId); + } + profile.seek(bsiSmashes); + for (int i = 0; i < bsiSmashCount; ++i) + { + profile >> tmpBsiId; + profile.skip(4); + hitTriggerIds.append((uint64_t)tmpBsiId); + } + profile.seek(bsiJumps); + for (int i = 0; i < bsiJumpCount; ++i) + { + profile >> tmpBsiId; + profile.skip(4); + hitTriggerIds.append((uint64_t)tmpBsiId); + } + + profile.close(); +} + // Creates a file with the box regions converted to triangles // Saved as Matrix 3x3 (MAT3) Buffer Converter::createGLTFBuffer() @@ -256,6 +346,11 @@ void Converter::convertTriggersToGLTF() { if ((uint8_t)triggerData->genericRegions[i].type == typeFilter) { + // Skip gathered collectibles + if (hitTriggerIds.contains((uint64_t)triggerData->genericRegions[i].id) + || hitTriggerIds.contains((uint64_t)triggerData->genericRegions[i].groupId)) + continue; + model->nodes.push_back(Node()); model->nodes.back().mesh = 0; convertGenericRegion(triggerData->genericRegions[i], model->nodes[genericRegionNodeIndex + currentGenericRegionNode], i); From 13d2f5034aa6fbad20d81ec782a48988b58f0557 Mon Sep 17 00:00:00 2001 From: burninrubber0 Date: Mon, 16 Oct 2023 23:51:46 -0400 Subject: [PATCH 5/6] Support other save platforms --- include/converter.h | 11 ++++ src/converter.cpp | 140 +++++++++++++++++++++++++++++--------------- 2 files changed, 103 insertions(+), 48 deletions(-) diff --git a/include/converter.h b/include/converter.h index 57b328b..6cbf046 100644 --- a/include/converter.h +++ b/include/converter.h @@ -21,6 +21,15 @@ class Converter int result = 0; private: + enum class Platform + { + PS3, + X360, + PC, + PS4, + NX + } platform = Platform::PC; + // For file reading DataStream inStream; std::string inFileName; @@ -38,6 +47,8 @@ class Converter void readTriggerData(); void readProfileTriggers(); + void readStuntElements(DataStream& stream, int offset, int count); + void readIslandStuntElements(DataStream& stream, int offset, int count); Buffer createGLTFBuffer(); void writeBoxRegion(DataStream& stream); Vector4 EulerToQuatRot(Vector3 euler); diff --git a/src/converter.cpp b/src/converter.cpp index 6585b3a..f617647 100644 --- a/src/converter.cpp +++ b/src/converter.cpp @@ -48,11 +48,23 @@ int Converter::getArgs(int argc, char* argv[]) { QString platform = argv[i + 1]; if (platform == "PC") + this->platform = Platform::PC; + else if (platform == "PS3") + this->platform = Platform::PS3; + else if (platform == "PS4") + this->platform = Platform::PS4; + else if (platform == "X360") + this->platform = Platform::X360; + else if (platform == "NX") + this->platform = Platform::NX; + + if (this->platform == Platform::PC) return 0; - else if (platform == "PS3" || platform == "X360") + else if (this->platform == Platform::PS3 || this->platform == Platform::X360) inStream.setByteOrder(QDataStream::BigEndian); - else if (platform == "PS4" || platform == "NX") + else if (this->platform == Platform::PS4 || this->platform == Platform::NX) inStream.setIs64Bit(true); + i++; } else if (strcmp(argv[i], "-f") == 0) @@ -65,7 +77,6 @@ int Converter::getArgs(int argc, char* argv[]) else if (strcmp(argv[i], "-s") == 0) { profileFileName = argv[i + 1]; - // TODO: Check profile validity i++; } else @@ -115,8 +126,11 @@ int Converter::checkArgs(int argc, char* argv[]) void Converter::showUsage() { std::cout << "Usage: TriggersToGLTF [options] \n\n" - << "Options:\n -p File platform. PS3, X360, PC, PS4, or NX. Default: PC\n" - << " -f GenericRegion type filter (an integer number). By default, all are converted."; + << "Options:\n" + << " -p File platform. PS3, X360, PC, PS4, or NX. Default: PC\n" + << " -f GenericRegion type filter (an integer number). By default, all are converted.\n" + << " -s Export only triggers not present in the provided savegame.\n" + << " Should be used with filters 8, 9, or 13 (collectibles)."; } void Converter::readTriggerData() @@ -132,10 +146,16 @@ void Converter::readProfileTriggers() profile.setDevice(new QFile(QString::fromStdString(profileFileName))); profile.open(QIODevice::ReadOnly); - // BPR PC support only for now. No checks - int base = 0x1D246; // Profile start offset + // Set offsets based on platform + int base = 0; // Profile start offset + if (platform == Platform::X360) + base = 0x1C; + else if (platform == Platform::PC) + base = 0x1D246; int stunts = base + 0x75E8; // Stunt elements offset - int alloc = 512; // Number of stunt elements allocated per type + const int alloc = 512; // Number of stunt elements allocated per type + + // Get stunt element counts int jumpCount = 0; int smashCount = 0; int billboardCount = 0; @@ -145,34 +165,52 @@ void Converter::readProfileTriggers() profile >> smashCount; profile.seek(stunts + alloc * 8 * 3 + 8 * 2); profile >> billboardCount; - uint64_t tmpId = 0; - profile.seek(stunts); // Jumps - for (int i = 0; i < jumpCount; ++i) - { - profile >> tmpId; - hitTriggerIds.append(tmpId); - } - profile.seek(stunts + alloc * 8 + 8); // Smashes - for (int i = 0; i < smashCount; ++i) + + // Read triggers + readStuntElements(profile, stunts, jumpCount); // Jumps + readStuntElements(profile, stunts + alloc * 8 + 8, smashCount); // Smashes + readStuntElements(profile, stunts + alloc * 8 * 2 + 8 * 2, smashCount); // Billboards + + // Make sure this is not the original PC game, + // because that version does not have the island + if (platform == Platform::PC) { - profile >> tmpId; - hitTriggerIds.append(tmpId); + QFileInfo info(QString::fromStdString(profileFileName)); + if (info.size() == 0x5D246) + { + profile.close(); + return; + } } - profile.seek(stunts + alloc * 8 * 2 + 8 * 2); // Billboards - for (int i = 0; i < billboardCount; ++i) + + // Island offsets + int bsi = 0; + switch (platform) { - profile >> tmpId; - hitTriggerIds.append(tmpId); + case Platform::PS3: + bsi = 0x30648; + break; + case Platform::X360: + bsi = 0x2F4E0; + break; + case Platform::PS4: + bsi = 0x79B78; + break; + case Platform::PC: + bsi = 79040; + break; + case Platform::NX: + bsi = 0x7AE68; + break; } - // Island collectibles - int bsi = base + 0x79040; + // Get stunt element details int bsiBillboards = bsi + 0x31C; int bsiSmashes = bsi + 0x488; int bsiJumps = bsi + 0x6E4; - int bsiBillboardAlloc = 45; - int bsiSmashAlloc = 75; - int bsiJumpAlloc = 15; + const int bsiBillboardAlloc = 45; + const int bsiSmashAlloc = 75; + const int bsiJumpAlloc = 15; int bsiBillboardCount = 0; int bsiSmashCount = 0; int bsiJumpCount = 0; @@ -182,30 +220,36 @@ void Converter::readProfileTriggers() profile >> bsiSmashCount; profile.seek(bsiJumps + bsiJumpAlloc * 8); profile >> bsiJumpCount; - uint32_t tmpBsiId = 0; - profile.seek(bsiBillboards); // Island billboards - for (int i = 0; i < bsiBillboardCount; ++i) - { - profile >> tmpBsiId; - profile.skip(4); - hitTriggerIds.append((uint64_t)tmpBsiId); - } - profile.seek(bsiSmashes); - for (int i = 0; i < bsiSmashCount; ++i) + + // Read island triggers + readIslandStuntElements(profile, bsiBillboards, bsiBillboardCount); // Island billboards + readIslandStuntElements(profile, bsiSmashes, bsiSmashCount); // Island smashes + readIslandStuntElements(profile, bsiJumps, bsiJumpCount); // Island jumps + + profile.close(); +} + +void Converter::readStuntElements(DataStream& stream, int offset, int count) +{ + uint64_t tmpId = 0; + stream.seek(offset); + for (int i = 0; i < count; ++i) { - profile >> tmpBsiId; - profile.skip(4); - hitTriggerIds.append((uint64_t)tmpBsiId); + stream >> tmpId; + hitTriggerIds.append(tmpId); } - profile.seek(bsiJumps); - for (int i = 0; i < bsiJumpCount; ++i) +} + +void Converter::readIslandStuntElements(DataStream& stream, int offset, int count) +{ + uint32_t tmpId = 0; + stream.seek(offset); + for (int i = 0; i < count; ++i) { - profile >> tmpBsiId; - profile.skip(4); - hitTriggerIds.append((uint64_t)tmpBsiId); + stream >> tmpId; + stream.skip(4); + hitTriggerIds.append((uint64_t)tmpId); } - - profile.close(); } // Creates a file with the box regions converted to triangles From 8ed712390aca30ddc74c610eda5b2628adc4def0 Mon Sep 17 00:00:00 2001 From: burninrubber0 Date: Tue, 17 Oct 2023 00:20:08 -0400 Subject: [PATCH 6/6] Reintroduce full conversion and fix a couple bugs --- include/converter.h | 2 +- src/converter.cpp | 129 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 125 insertions(+), 6 deletions(-) diff --git a/include/converter.h b/include/converter.h index 6cbf046..824de45 100644 --- a/include/converter.h +++ b/include/converter.h @@ -34,7 +34,7 @@ class Converter DataStream inStream; std::string inFileName; std::string outFileName; - uint8_t typeFilter = -1; + int8_t typeFilter = -1; std::string profileFileName; TriggerData* triggerData = nullptr; diff --git a/src/converter.cpp b/src/converter.cpp index f617647..c8312b9 100644 --- a/src/converter.cpp +++ b/src/converter.cpp @@ -130,7 +130,7 @@ void Converter::showUsage() << " -p File platform. PS3, X360, PC, PS4, or NX. Default: PC\n" << " -f GenericRegion type filter (an integer number). By default, all are converted.\n" << " -s Export only triggers not present in the provided savegame.\n" - << " Should be used with filters 8, 9, or 13 (collectibles)."; + << " Ignored if not used with filters 8, 9, or 13 (collectibles)."; } void Converter::readTriggerData() @@ -197,7 +197,7 @@ void Converter::readProfileTriggers() bsi = 0x79B78; break; case Platform::PC: - bsi = 79040; + bsi = 0x79040; break; case Platform::NX: bsi = 0x7AE68; @@ -382,17 +382,97 @@ void Converter::convertTriggersToGLTF() // Create nodes // TriggerRegion derived nodes int currentNodeCount = 0; + if (typeFilter == -1) + { + int landmarkNodeIndex = currentNodeCount; + int landmarkChildCount = 0; + for (int i = 0; i < triggerData->landmarkCount; ++i) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + for (int j = 0; j < triggerData->landmarks[i].startingGridCount; ++j) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + model->nodes[landmarkNodeIndex + i + landmarkChildCount].children.push_back(landmarkNodeIndex + i + landmarkChildCount + j + 1); + convertStartingGrid(triggerData->landmarks[i].startingGrids[j], model->nodes[landmarkNodeIndex + i + landmarkChildCount + j + 1], j); + currentNodeCount++; + } + convertLandmark(triggerData->landmarks[i], model->nodes[i + landmarkNodeIndex], i); + currentNodeCount++; + landmarkChildCount += triggerData->landmarks[i].startingGridCount; + model->scenes[0].nodes.push_back(landmarkNodeIndex + i + landmarkChildCount - triggerData->landmarks[i].startingGridCount); + } + int blackspotNodeIndex = currentNodeCount; + for (int i = 0; i < triggerData->blackspotCount; ++i) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + convertBlackspot(triggerData->blackspots[i], model->nodes[blackspotNodeIndex + i], i); + currentNodeCount++; + model->scenes[0].nodes.push_back(blackspotNodeIndex + i); + } + int vfxBoxRegionNodeIndex = currentNodeCount; + for (int i = 0; i < triggerData->vfxBoxRegionCount; ++i) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + convertVfxBoxRegion(triggerData->vfxBoxRegions[i], model->nodes[vfxBoxRegionNodeIndex + i], i); + currentNodeCount++; + model->scenes[0].nodes.push_back(vfxBoxRegionNodeIndex + i); + } + + // Nodes with GenericRegion arrays + int signatureStuntNodeIndex = currentNodeCount; + int signatureStuntChildCount = 0; + for (int i = 0; i < triggerData->signatureStuntCount; ++i) + { + model->nodes.push_back(Node()); + for (int j = 0; j < triggerData->signatureStunts[i].stuntElementCount; ++j) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount].children.push_back(signatureStuntNodeIndex + i + signatureStuntChildCount + j + 1); + convertGenericRegion(triggerData->signatureStunts[i].getStuntElement(j), model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount + j + 1], j); + currentNodeCount++; + } + convertSignatureStunt(triggerData->signatureStunts[i], model->nodes[signatureStuntNodeIndex + i + signatureStuntChildCount], i); + currentNodeCount++; + signatureStuntChildCount += triggerData->signatureStunts[i].stuntElementCount; + model->scenes[0].nodes.push_back(signatureStuntNodeIndex + i + signatureStuntChildCount - triggerData->signatureStunts[i].stuntElementCount); + } + int killzoneNodeIndex = currentNodeCount; + int killzoneChildCount = 0; + for (int i = 0; i < triggerData->killzoneCount; ++i) + { + model->nodes.push_back(Node()); + for (int j = 0; j < triggerData->killzones[i].triggerCount; ++j) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + model->nodes[killzoneNodeIndex + i + killzoneChildCount].children.push_back(killzoneNodeIndex + i + killzoneChildCount + j + 1); + convertGenericRegion(triggerData->killzones[i].getTrigger(j), model->nodes[killzoneNodeIndex + i + killzoneChildCount + j + 1], j); + currentNodeCount++; + } + convertKillzone(triggerData->killzones[i], model->nodes[killzoneNodeIndex + i + killzoneChildCount], i); + currentNodeCount++; + killzoneChildCount += triggerData->killzones[i].triggerCount; + model->scenes[0].nodes.push_back(killzoneNodeIndex + i + killzoneChildCount - triggerData->killzones[i].triggerCount); + } + } // Remaining GenericRegion nodes int genericRegionNodeIndex = currentNodeCount; int currentGenericRegionNode = 0; for (int i = 0; i < triggerData->genericRegionCount; ++i) { - if ((uint8_t)triggerData->genericRegions[i].type == typeFilter) + if ((typeFilter == -1 && !triggerRegionExists(triggerData->genericRegions[i], false)) + || (int8_t)triggerData->genericRegions[i].type == typeFilter) { // Skip gathered collectibles - if (hitTriggerIds.contains((uint64_t)triggerData->genericRegions[i].id) - || hitTriggerIds.contains((uint64_t)triggerData->genericRegions[i].groupId)) + if ((typeFilter == 8 || typeFilter == 9 || typeFilter == 13) + && (hitTriggerIds.contains((uint64_t)triggerData->genericRegions[i].id) + || hitTriggerIds.contains((uint64_t)triggerData->genericRegions[i].groupId))) continue; model->nodes.push_back(Node()); @@ -404,6 +484,45 @@ void Converter::convertTriggersToGLTF() } } + if (typeFilter == -1) + { + // Remaining TriggerRegion nodes + int triggerRegionNodeIndex = currentNodeCount; + int currentTriggerRegionNode = 0; + for (int i = 0; i < triggerData->regionCount; ++i) + { + if (!triggerRegionExists(triggerData->getRegion(i))) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + convertTriggerRegion(triggerData->getRegion(i), model->nodes[triggerRegionNodeIndex + currentTriggerRegionNode], i); + model->scenes[0].nodes.push_back(triggerRegionNodeIndex + currentTriggerRegionNode); + currentTriggerRegionNode++; + currentNodeCount++; + } + } + + // Point triggers + int roamingLocationNodeIndex = currentNodeCount; + for (int i = 0; i < triggerData->roamingLocationCount; ++i) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + convertRoamingLocation(triggerData->roamingLocations[i], model->nodes[roamingLocationNodeIndex + i], i); + currentNodeCount++; + model->scenes[0].nodes.push_back(roamingLocationNodeIndex + i); + } + int spawnLocationNodeIndex = currentNodeCount; + for (int i = 0; i < triggerData->spawnLocationCount; ++i) + { + model->nodes.push_back(Node()); + model->nodes.back().mesh = 0; + convertSpawnLocation(triggerData->spawnLocations[i], model->nodes[spawnLocationNodeIndex + i], i); + currentNodeCount++; + model->scenes[0].nodes.push_back(spawnLocationNodeIndex + i); + } + } + // Set up asset model->asset.version = "2.0"; model->asset.generator = "tinygltf";