diff --git a/libultraship b/libultraship index bbb565bd937..08750416e51 160000 --- a/libultraship +++ b/libultraship @@ -1 +1 @@ -Subproject commit bbb565bd9376751889bda36856a05ebb0ab9dc4b +Subproject commit 08750416e510043788dfb8ac27ef70cef084ba1d diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 32b64fc5047..cdf037b8718 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -94,6 +94,7 @@ #include "soh/resource/type/SohResourceType.h" #include "soh/resource/type/Animation.h" #include "soh/resource/type/Skeleton.h" +#include "soh/resource/type/SkinAnimatedLimbData.h" #include #include #include @@ -113,6 +114,7 @@ #include "soh/resource/importer/SkeletonLimbFactory.h" #include "soh/resource/importer/TextFactory.h" #include "soh/resource/importer/BackgroundFactory.h" +#include "soh/resource/importer/SkinAnimatedLimbDataFactory.h" #include "soh/config/ConfigUpdaters.h" #include "soh/ShipInit.hpp" @@ -912,6 +914,14 @@ void OTRGlobals::Initialize() { "Sequence", static_cast(SOH::ResourceType::SOH_AudioSequence), 0); loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_BINARY, "Background", static_cast(SOH::ResourceType::SOH_Background), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, + "SkinVert", static_cast(SOH::ResourceType::SOH_SkinVert), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, + "SkinTransform", static_cast(SOH::ResourceType::SOH_SkinTransform), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, + "SkinModif", static_cast(SOH::ResourceType::SOH_SkinModif), 0); + loader->RegisterResourceFactory(std::make_shared(), RESOURCE_FORMAT_XML, + "SkinAnimData", static_cast(SOH::ResourceType::SOH_SkinAnimData), 0); Lang::LoadLangs(); diff --git a/soh/soh/resource/importer/SkeletonLimbFactory.cpp b/soh/soh/resource/importer/SkeletonLimbFactory.cpp index 96d5c49de2d..b0fb8c89cf6 100644 --- a/soh/soh/resource/importer/SkeletonLimbFactory.cpp +++ b/soh/soh/resource/importer/SkeletonLimbFactory.cpp @@ -1,5 +1,7 @@ #include "soh/resource/importer/SkeletonLimbFactory.h" +#include "soh/resource/importer/SkinAnimatedLimbDataFactory.h" #include "soh/resource/type/SkeletonLimb.h" +#include "soh/resource/type/SkinAnimatedLimbData.h" #include #include #include @@ -204,7 +206,12 @@ ResourceFactoryXMLSkeletonLimbV0::ReadResource(std::shared_ptr file, std::string limbType = reader->Attribute("Type"); // OTRTODO - skelLimb->limbType = LimbType::LOD; + // skelLimb->limbType = LimbType::LOD; + if (limbType == "Skin") { + skelLimb->limbType = LimbType::Skin; + } else { + skelLimb->limbType = LimbType::LOD; + } // skelLimb->legTransX = reader->FloatAttribute("LegTransX"); // skelLimb->legTransY = reader->FloatAttribute("LegTransY"); @@ -224,33 +231,68 @@ ResourceFactoryXMLSkeletonLimbV0::ReadResource(std::shared_ptr file, skelLimb->childIndex = reader->IntAttribute("ChildIndex"); skelLimb->siblingIndex = reader->IntAttribute("SiblingIndex"); + skelLimb->skinSegmentType = (ZLimbSkinType)reader->IntAttribute("SegmentType"); // skelLimb->childPtr = reader->Attribute("ChildLimb"); // skelLimb->siblingPtr = reader->Attribute("SiblingLimb"); - skelLimb->dListPtr = reader->Attribute("DisplayList1"); - - if (std::string(reader->Attribute("DisplayList1")) == "gEmptyDL") { - skelLimb->dListPtr = ""; - } auto& limbData = skelLimb->limbData; - limbData.lodLimb.jointPos.x = skelLimb->transX; - limbData.lodLimb.jointPos.y = skelLimb->transY; - limbData.lodLimb.jointPos.z = skelLimb->transZ; + if (skelLimb->limbType == LimbType::LOD) { - if (skelLimb->dListPtr != "") { - skelLimb->dListPtr = "__OTR__" + skelLimb->dListPtr; - limbData.lodLimb.dLists[0] = (Gfx*)skelLimb->dListPtr.c_str(); - } else { - limbData.lodLimb.dLists[0] = nullptr; - } + skelLimb->dListPtr = reader->Attribute("DisplayList1"); + + if (std::string(reader->Attribute("DisplayList1")) == "gEmptyDL") { + skelLimb->dListPtr = ""; + } + + limbData.lodLimb.jointPos.x = skelLimb->transX; + limbData.lodLimb.jointPos.y = skelLimb->transY; + limbData.lodLimb.jointPos.z = skelLimb->transZ; + + if (skelLimb->dListPtr != "") { + skelLimb->dListPtr = "__OTR__" + skelLimb->dListPtr; + limbData.lodLimb.dLists[0] = (Gfx*)skelLimb->dListPtr.c_str(); + } else { + limbData.lodLimb.dLists[0] = nullptr; + } - limbData.lodLimb.dLists[1] = nullptr; + limbData.lodLimb.dLists[1] = nullptr; - limbData.lodLimb.child = skelLimb->childIndex; - limbData.lodLimb.sibling = skelLimb->siblingIndex; + limbData.lodLimb.child = skelLimb->childIndex; + limbData.lodLimb.sibling = skelLimb->siblingIndex; - // skelLimb->dList2Ptr = reader->Attribute("DisplayList2"); + limbData.lodLimb.child = skelLimb->childIndex; + limbData.lodLimb.sibling = skelLimb->siblingIndex; + } else if (skelLimb->limbType == LimbType::Skin) { + + skelLimb->skinDList = std::string(reader->Attribute("Segment")); + + limbData.skinLimb.jointPos.x = skelLimb->transX; + limbData.skinLimb.jointPos.y = skelLimb->transY; + limbData.skinLimb.jointPos.z = skelLimb->transZ; + limbData.skinLimb.child = skelLimb->childIndex; + limbData.skinLimb.sibling = skelLimb->siblingIndex; + + skelLimb->limbData.skinLimb.segmentType = static_cast(skelLimb->skinSegmentType); + + if (skelLimb->skinDList != "gEmptyDL") { + skelLimb->skinDList = "__OTR__" + skelLimb->skinDList; + skelLimb->limbData.skinLimb.segment = (Gfx*)skelLimb->skinDList.c_str(); + } else { + skelLimb->skinDList = ""; + skelLimb->limbData.skinLimb.segment = nullptr; + } + + if (skelLimb->skinSegmentType == ZLimbSkinType::SkinType_4) { + + auto skinAnimatedData = std::static_pointer_cast( + Ship::Context::GetRawInstance()->GetResourceManager()->LoadResourceProcess( + skelLimb->skinDList.c_str())); + + skelLimb->skinAnimLimbData = skinAnimatedData->data; + skelLimb->limbData.skinLimb.segment = &skelLimb->skinAnimLimbData; + } + } return skelLimb; } diff --git a/soh/soh/resource/importer/SkinAnimatedLimbDataFactory.cpp b/soh/soh/resource/importer/SkinAnimatedLimbDataFactory.cpp new file mode 100644 index 00000000000..3db77246a1c --- /dev/null +++ b/soh/soh/resource/importer/SkinAnimatedLimbDataFactory.cpp @@ -0,0 +1,152 @@ +#include "soh/resource/importer/SkinAnimatedLimbDataFactory.h" +#include "soh/resource/type/SkinAnimatedLimbData.h" +#include "spdlog/spdlog.h" +#include +#include "libultraship/libultraship.h" + +namespace SOH { +std::shared_ptr +ResourceFactoryXMLSkinVertV0::ReadResource(std::shared_ptr file, + std::shared_ptr initData) { + if (!FileHasValidFormatAndReader(file, initData)) { + return nullptr; + } + + auto skinVert = std::make_shared(initData); + + auto child = + std::get>(file->Reader)->FirstChildElement()->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "SkinVertex") { + SkinVertex data; + data.index = child->IntAttribute("Index"); + data.s = child->IntAttribute("S"); + data.t = child->IntAttribute("T"); + data.normX = child->IntAttribute("NormX"); + data.normY = child->IntAttribute("NormY"); + data.normZ = child->IntAttribute("NormZ"); + data.alpha = child->IntAttribute("Alpha"); + + skinVert->skinVertexList.push_back(data); + } + + child = child->NextSiblingElement(); + } + + return skinVert; +} + +std::shared_ptr +ResourceFactoryXMLSkinTransformV0::ReadResource(std::shared_ptr file, + std::shared_ptr initData) { + if (!FileHasValidFormatAndReader(file, initData)) { + return nullptr; + } + + auto skinTransform = std::make_shared(initData); + + auto child = + std::get>(file->Reader)->FirstChildElement()->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "SkinTransformation") { + SkinTransformation data; + data.limbIndex = child->IntAttribute("LimbIndex"); + data.x = child->IntAttribute("X"); + data.y = child->IntAttribute("Y"); + data.z = child->IntAttribute("Z"); + data.scale = child->IntAttribute("Scale"); + + skinTransform->skinTransformationList.push_back(data); + + } + + child = child->NextSiblingElement(); + } + + return skinTransform; +} + +std::shared_ptr +ResourceFactoryXMLSkinModifV0::ReadResource(std::shared_ptr file, + std::shared_ptr initData) { + if (!FileHasValidFormatAndReader(file, initData)) { + return nullptr; + } + + auto skinModif = std::make_shared(initData); + + auto child = + std::get>(file->Reader)->FirstChildElement()->FirstChildElement(); + + while (child != nullptr) { + std::string childName = child->Name(); + if (childName == "SkinLimbModif") { + SkinLimbModif data; + data.vtxCount = child->IntAttribute("VtxCount"); + data.transformCount = child->IntAttribute("TransformCount"); + data.unk_4 = child->IntAttribute("Unk_4"); + + std::string skinVerticesPath = child->Attribute("SkinVertices"); + auto skinVerts = std::static_pointer_cast( + Ship::Context::GetRawInstance()->GetResourceManager()->LoadResourceProcess(skinVerticesPath.c_str())); + skinModif->skinVerticesArrays.push_back(std::move(skinVerts->skinVertexList)); + data.skinVertices = skinModif->skinVerticesArrays.back().data(); + + std::string transformsPath = child->Attribute("LimbTransformations"); + auto skinTransforms = std::static_pointer_cast( + Ship::Context::GetRawInstance()->GetResourceManager()->LoadResourceProcess(transformsPath.c_str())); + skinModif->skinTransformationsArrays.push_back(std::move(skinTransforms->skinTransformationList)); + data.limbTransformations = skinModif->skinTransformationsArrays.back().data(); + + skinModif->skinLimbModifArray.push_back(data); + } + + child = child->NextSiblingElement(); + } + return skinModif; +} + +std::shared_ptr +ResourceFactoryXMLSkinAnimDataV0::ReadResource(std::shared_ptr file, + std::shared_ptr initData) { + if (!FileHasValidFormatAndReader(file, initData)) { + return nullptr; + } + + auto skinAnimatedData = std::make_shared(initData); + auto reader = std::get>(file->Reader)->FirstChildElement(); + + + skinAnimatedData->data.totalVtxCount = reader->IntAttribute("TotalVtxCount"); + skinAnimatedData->data.limbModifCount = reader->IntAttribute("LimbModifCount"); + skinAnimatedData->skinLimbModifArray.reserve(skinAnimatedData->data.limbModifCount); + // skinAnimatedData->skinLimbModifVertexArrays.reserve(skinAnimatedData->data.limbModifCount); + // skinAnimatedData->skinLimbModifTransformationArrays.reserve(skinAnimatedData->data.limbModifCount); + + std::string modifsPath = reader->Attribute("LimbModifications"); + + auto skinModifs = std::static_pointer_cast( + Ship::Context::GetRawInstance()->GetResourceManager()->LoadResourceProcess(modifsPath.c_str())); + skinAnimatedData->skinLimbModifArray = std::move(skinModifs->skinLimbModifArray); + skinAnimatedData->data.limbModifications = skinAnimatedData->skinLimbModifArray.data(); + + skinAnimatedData->dListPtr = reader->Attribute("DList"); + + if (std::string(reader->Attribute("DList")) == "gEmptyDL") { + skinAnimatedData->dListPtr = ""; + } + + if (skinAnimatedData->dListPtr != "") { + skinAnimatedData->dListPtr = "__OTR__" + skinAnimatedData->dListPtr; + skinAnimatedData->data.dlist = (Gfx*)skinAnimatedData->dListPtr.c_str(); + } else { + skinAnimatedData->data.dlist = nullptr; + } + + return skinAnimatedData; +} +}// namespace SOH diff --git a/soh/soh/resource/importer/SkinAnimatedLimbDataFactory.h b/soh/soh/resource/importer/SkinAnimatedLimbDataFactory.h new file mode 100644 index 00000000000..194bc0c90b8 --- /dev/null +++ b/soh/soh/resource/importer/SkinAnimatedLimbDataFactory.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +namespace SOH { + +class ResourceFactoryXMLSkinVertV0 final : public Ship::ResourceFactoryXML { + public: + std::shared_ptr ReadResource(std::shared_ptr file, + std::shared_ptr initData) override; +}; + +class ResourceFactoryXMLSkinTransformV0 final : public Ship::ResourceFactoryXML { + public: + std::shared_ptr ReadResource(std::shared_ptr file, + std::shared_ptr initData) override; +}; + +class ResourceFactoryXMLSkinModifV0 final : public Ship::ResourceFactoryXML { + public: + std::shared_ptr ReadResource(std::shared_ptr file, + std::shared_ptr initData) override; +}; + +class ResourceFactoryXMLSkinAnimDataV0 final : public Ship::ResourceFactoryXML { + public: + std::shared_ptr ReadResource(std::shared_ptr file, + std::shared_ptr initData) override; +}; +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/SkeletonLimb.h b/soh/soh/resource/type/SkeletonLimb.h index 84acd774157..2ce90592a34 100644 --- a/soh/soh/resource/type/SkeletonLimb.h +++ b/soh/soh/resource/type/SkeletonLimb.h @@ -1,5 +1,6 @@ #pragma once +#include "SkinAnimatedLimbData.h" #include #include "libultraship/libultra.h" #include "z64math.h" @@ -21,39 +22,6 @@ enum class ZLimbSkinType { SkinType_DList = 11, // Segment = DList address }; -/** - * Holds a compact version of a vertex used in the Skin system - * It is used to initialise the Vtx used by an animated limb - */ -typedef struct { - /* 0x00 */ u16 index; - /* 0x02 */ s16 s; // s and t are texture coordinates (also known as u and v) - /* 0x04 */ s16 t; - /* 0x06 */ s8 normX; - /* 0x07 */ s8 normY; - /* 0x08 */ s8 normZ; - /* 0x09 */ u8 alpha; -} SkinVertex; // size = 0xA - -/** - * Describes a position displacement and a scale to be applied to a limb at index `limbIndex` - */ -typedef struct { - /* 0x00 */ u8 limbIndex; - /* 0x02 */ s16 x; - /* 0x04 */ s16 y; - /* 0x06 */ s16 z; - /* 0x08 */ u8 scale; -} SkinTransformation; // size = 0xA - -typedef struct { - /* 0x00 */ u16 vtxCount; // number of vertices in this modif entry - /* 0x02 */ u16 transformCount; - /* 0x04 */ u16 unk_4; // index of limbTransformations? - /* 0x08 */ SkinVertex* skinVertices; - /* 0x0C */ SkinTransformation* limbTransformations; -} SkinLimbModif; // size = 0x10 - typedef struct { /* 0x00 */ Vec3s jointPos; // Root is position in model space, children are relative to parent /* 0x06 */ u8 child; @@ -83,13 +51,6 @@ typedef struct { // SKIN_LIMB_TYPE_ANIMATED, NULL otherwise } SkinLimb; // size = 0x10 -typedef struct { - /* 0x00 */ u16 totalVtxCount; // total vertex count for all modif entries - /* 0x02 */ u16 limbModifCount; - /* 0x04 */ SkinLimbModif* limbModifications; - /* 0x08 */ Gfx* dlist; -} SkinAnimatedLimbData; // size = 0xC - union SkeletonLimbData { LodLimb lodLimb; StandardLimb standardLimb; diff --git a/soh/soh/resource/type/SkinAnimatedLimbData.cpp b/soh/soh/resource/type/SkinAnimatedLimbData.cpp new file mode 100644 index 00000000000..47dd4effadc --- /dev/null +++ b/soh/soh/resource/type/SkinAnimatedLimbData.cpp @@ -0,0 +1,35 @@ +#include "SkinAnimatedLimbData.h" + +namespace SOH { + +SkinVertex* SkinVert::GetPointer() { + return skinVertexList.data(); +} + +size_t SkinVert::GetPointerSize() { + return skinVertexList.size() * sizeof(SkinVertex); +} + +SkinTransformation* SkinTransform::GetPointer() { + return skinTransformationList.data(); +} + +size_t SkinTransform::GetPointerSize() { + return skinTransformationList.size() * sizeof(SkinTransformation); +} + +SkinLimbModif* SkinModif::GetPointer() { + return skinLimbModifArray.data(); +} + +size_t SkinModif::GetPointerSize() { + return skinLimbModifArray.size() * sizeof(SkinLimbModif); +} + +SkinAnimatedLimbData* SkinAnimData::GetPointer() { + return &data; +} +size_t SkinAnimData::GetPointerSize() { + return sizeof(SkinAnimatedLimbData); +} +} \ No newline at end of file diff --git a/soh/soh/resource/type/SkinAnimatedLimbData.h b/soh/soh/resource/type/SkinAnimatedLimbData.h new file mode 100644 index 00000000000..989d5ca1530 --- /dev/null +++ b/soh/soh/resource/type/SkinAnimatedLimbData.h @@ -0,0 +1,109 @@ +#pragma once + +#include +#include "libultraship/libultra.h" +#include "z64math.h" + +namespace SOH { + +/** + * Holds a compact version of a vertex used in the Skin system + * It is used to initialise the Vtx used by an animated limb + */ +typedef struct { + /* 0x00 */ u16 index; + /* 0x02 */ s16 s; // s and t are texture coordinates (also known as u and v) + /* 0x04 */ s16 t; + /* 0x06 */ s8 normX; + /* 0x07 */ s8 normY; + /* 0x08 */ s8 normZ; + /* 0x09 */ u8 alpha; +} SkinVertex; // size = 0xA + +class SkinVert : public Ship::Resource { + public: + using Resource::Resource; + + SkinVert() : Resource(std::shared_ptr()) { + } + + SkinVertex* GetPointer() override; + size_t GetPointerSize() override; + + std::vector skinVertexList; + +}; + +/** + * Describes a position displacement and a scale to be applied to a limb at index `limbIndex` + */ +typedef struct { + /* 0x00 */ u8 limbIndex; + /* 0x02 */ s16 x; + /* 0x04 */ s16 y; + /* 0x06 */ s16 z; + /* 0x08 */ u8 scale; +} SkinTransformation; // size = 0xA + +class SkinTransform : public Ship::Resource { + public: + using Resource::Resource; + + SkinTransform() : Resource(std::shared_ptr()) { + } + + SkinTransformation* GetPointer() override; + size_t GetPointerSize() override; + + std::vector skinTransformationList; + +}; + +typedef struct { + /* 0x00 */ u16 vtxCount; // number of vertices in this modif entry + /* 0x02 */ u16 transformCount; + /* 0x04 */ u16 unk_4; // index of limbTransformations? + /* 0x08 */ SkinVertex* skinVertices; + /* 0x0C */ SkinTransformation* limbTransformations; +} SkinLimbModif; // size = 0x10 + +class SkinModif : public Ship::Resource { + public: + using Resource::Resource; + + SkinModif() : Resource(std::shared_ptr()) { + } + + SkinLimbModif* GetPointer() override; + size_t GetPointerSize() override; + + std::vector skinLimbModifArray; + std::vector> skinVerticesArrays; + std::vector> skinTransformationsArrays; +}; + +typedef struct { + /* 0x00 */ u16 totalVtxCount; // total vertex count for all modif entries + /* 0x02 */ u16 limbModifCount; + /* 0x04 */ SkinLimbModif* limbModifications; + /* 0x08 */ Gfx* dlist; +} SkinAnimatedLimbData; // size = 0xC + +class SkinAnimData : public Ship::Resource { + public: + using Resource::Resource; + + SkinAnimData() : Resource(std::shared_ptr()) { + } + + SkinAnimatedLimbData* GetPointer() override; + size_t GetPointerSize() override; + + SkinAnimatedLimbData data; + + uint16_t totalVtxCount; + uint32_t limbModifCount; + std::string dListPtr; + std::vector skinLimbModifArray; +}; +} // namespace SOH \ No newline at end of file diff --git a/soh/soh/resource/type/SohResourceType.h b/soh/soh/resource/type/SohResourceType.h index 6455c28c7e0..f60aae49d5d 100644 --- a/soh/soh/resource/type/SohResourceType.h +++ b/soh/soh/resource/type/SohResourceType.h @@ -18,5 +18,9 @@ enum class ResourceType { SOH_AudioSequence = 0x4F534551, // OSEQ SOH_Background = 0x4F424749, // OBGI SOH_SceneCommand = 0x4F52434D, // ORCM + SOH_SkinVert = 0x4f525356, // ORSV + SOH_SkinTransform = 0x4F525354, // ORST + SOH_SkinModif = 0x4F52534D, // ORSM + SOH_SkinAnimData = 0x4F534144, // OSAD }; } // namespace SOH