Add Collision Header XML parser (#3396)

* Add Collision Header XML parser

* Update CollisionHeaderFactory.cpp

* Remove "Num" attributes

* Fix crashes

Prevent crash when the camera setting is negative
Change some IntAttributes to UnsignedAttributes
This commit is contained in:
Pepe20129 2024-01-15 16:33:21 +01:00 committed by GitHub
parent ecdf74161b
commit db2ccd95b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 141 additions and 1 deletions

View File

@ -24,6 +24,27 @@ CollisionHeaderFactory::ReadResource(std::shared_ptr<ResourceInitData> initData,
return resource; return resource;
} }
std::shared_ptr<IResource>
CollisionHeaderFactory::ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) {
auto resource = std::make_shared<CollisionHeader>(initData);
std::shared_ptr<ResourceVersionFactory> factory = nullptr;
switch (resource->GetInitData()->ResourceVersion) {
case 0:
factory = std::make_shared<CollisionHeaderFactoryV0>();
break;
}
if (factory == nullptr) {
SPDLOG_ERROR("Failed to load Collision Header with version {}", resource->GetInitData()->ResourceVersion);
return nullptr;
}
factory->ParseFileXML(reader, resource);
return resource;
}
void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader, void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader> reader,
std::shared_ptr<IResource> resource) std::shared_ptr<IResource> resource)
{ {
@ -139,4 +160,119 @@ void LUS::CollisionHeaderFactoryV0::ParseFileBinary(std::shared_ptr<BinaryReader
} }
collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data(); collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data();
} }
void LUS::CollisionHeaderFactoryV0::ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) {
std::shared_ptr<CollisionHeader> collisionHeader = std::static_pointer_cast<CollisionHeader>(resource);
collisionHeader->collisionHeaderData.minBounds.x = reader->IntAttribute("MinBoundsX");
collisionHeader->collisionHeaderData.minBounds.y = reader->IntAttribute("MinBoundsY");
collisionHeader->collisionHeaderData.minBounds.z = reader->IntAttribute("MinBoundsZ");
collisionHeader->collisionHeaderData.maxBounds.x = reader->IntAttribute("MaxBoundsX");
collisionHeader->collisionHeaderData.maxBounds.y = reader->IntAttribute("MaxBoundsY");
collisionHeader->collisionHeaderData.maxBounds.z = reader->IntAttribute("MaxBoundsZ");
Vec3s zero;
zero.x = 0;
zero.y = 0;
zero.z = 0;
collisionHeader->camPosDataZero = zero;
auto child = reader->FirstChildElement();
while (child != nullptr) {
std::string childName = child->Name();
if (childName == "Vertex") {
Vec3s vtx;
vtx.x = child->IntAttribute("X");
vtx.y = child->IntAttribute("Y");
vtx.z = child->IntAttribute("Z");
collisionHeader->vertices.push_back(vtx);
} else if (childName == "Polygon") {
CollisionPoly polygon;
polygon.type = child->UnsignedAttribute("Type");
polygon.flags_vIA = child->UnsignedAttribute("VertexA");
polygon.flags_vIB = child->UnsignedAttribute("VertexB");
polygon.vIC = child->UnsignedAttribute("VertexC");
polygon.normal.x = child->IntAttribute("NormalX");
polygon.normal.y = child->IntAttribute("NormalY");
polygon.normal.z = child->IntAttribute("NormalZ");
polygon.dist = child->IntAttribute("Dist");
collisionHeader->polygons.push_back(polygon);
} else if (childName == "PolygonType") {
SurfaceType surfaceType;
surfaceType.data[0] = child->UnsignedAttribute("Data1");
surfaceType.data[1] = child->UnsignedAttribute("Data2");
collisionHeader->surfaceTypes.push_back(surfaceType);
} else if (childName == "CameraData") {
CamData camDataEntry;
camDataEntry.cameraSType = child->UnsignedAttribute("SType");
camDataEntry.numCameras = child->IntAttribute("NumData");
collisionHeader->camData.push_back(camDataEntry);
int32_t camPosDataIdx = child->IntAttribute("CameraPosDataSeg");
collisionHeader->camPosDataIndices.push_back(camPosDataIdx);
} else if (childName == "CameraPositionData") {
//each camera position data is made up of 3 Vec3s
Vec3s pos;
pos.x = child->IntAttribute("PosX");
pos.y = child->IntAttribute("PosY");
pos.z = child->IntAttribute("PosZ");
collisionHeader->camPosData.push_back(pos);
Vec3s rot;
rot.x = child->IntAttribute("RotX");
rot.y = child->IntAttribute("RotY");
rot.z = child->IntAttribute("RotZ");
collisionHeader->camPosData.push_back(rot);
Vec3s other;
other.x = child->IntAttribute("FOV");
other.y = child->IntAttribute("JfifID");
other.z = child->IntAttribute("Unknown");
collisionHeader->camPosData.push_back(other);
} else if (childName == "WaterBox") {
WaterBox waterBox;
waterBox.xMin = child->IntAttribute("XMin");
waterBox.ySurface = child->IntAttribute("Ysurface");
waterBox.zMin = child->IntAttribute("ZMin");
waterBox.xLength = child->IntAttribute("XLength");
waterBox.zLength = child->IntAttribute("ZLength");
waterBox.properties = child->IntAttribute("Properties");
collisionHeader->waterBoxes.push_back(waterBox);
}
child = child->NextSiblingElement();
}
for (size_t i = 0; i < collisionHeader->camData.size(); i++) {
int32_t idx = collisionHeader->camPosDataIndices[i];
if (collisionHeader->camPosData.size() > 0) {
collisionHeader->camData[i].camPosData = &collisionHeader->camPosData[idx];
} else {
collisionHeader->camData[i].camPosData = &collisionHeader->camPosDataZero;
}
}
collisionHeader->collisionHeaderData.numVertices = collisionHeader->vertices.size();
collisionHeader->collisionHeaderData.numPolygons = collisionHeader->polygons.size();
collisionHeader->surfaceTypesCount = collisionHeader->surfaceTypes.size();
collisionHeader->camDataCount = collisionHeader->camData.size();
collisionHeader->camPosCount = collisionHeader->camPosData.size();
collisionHeader->collisionHeaderData.numWaterBoxes = collisionHeader->waterBoxes.size();
collisionHeader->collisionHeaderData.vtxList = collisionHeader->vertices.data();
collisionHeader->collisionHeaderData.polyList = collisionHeader->polygons.data();
collisionHeader->collisionHeaderData.surfaceTypeList = collisionHeader->surfaceTypes.data();
collisionHeader->collisionHeaderData.cameraDataList = collisionHeader->camData.data();
collisionHeader->collisionHeaderData.cameraDataListLen = collisionHeader->camDataCount;
collisionHeader->collisionHeaderData.waterBoxes = collisionHeader->waterBoxes.data();
}
} }

View File

@ -8,10 +8,13 @@ class CollisionHeaderFactory : public ResourceFactory {
public: public:
std::shared_ptr<IResource> std::shared_ptr<IResource>
ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override; ReadResource(std::shared_ptr<ResourceInitData> initData, std::shared_ptr<BinaryReader> reader) override;
std::shared_ptr<IResource>
ReadResourceXML(std::shared_ptr<ResourceInitData> initData, tinyxml2::XMLElement *reader) override;
}; };
class CollisionHeaderFactoryV0 : public ResourceVersionFactory { class CollisionHeaderFactoryV0 : public ResourceVersionFactory {
public: public:
void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override; void ParseFileBinary(std::shared_ptr<BinaryReader> reader, std::shared_ptr<IResource> resource) override;
void ParseFileXML(tinyxml2::XMLElement* reader, std::shared_ptr<IResource> resource) override;
}; };
}; // namespace LUS }; // namespace LUS

View File

@ -7933,7 +7933,8 @@ s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags) {
return -5; return -5;
} }
if (setting == CAM_SET_NONE || setting >= CAM_SET_MAX) { //modified from "==" to "<=" to not crash when "setting" is a negative value
if (setting <= CAM_SET_NONE || setting >= CAM_SET_MAX) {
osSyncPrintf(VT_COL(RED, WHITE) "camera: error: illegal camera set (%d) !!!!\n" VT_RST, setting); osSyncPrintf(VT_COL(RED, WHITE) "camera: error: illegal camera set (%d) !!!!\n" VT_RST, setting);
return -99; return -99;
} }