summaryrefslogtreecommitdiff
path: root/mm/2s2h/resource/importer/SkeletonLimbFactory.cpp
blob: b98a0da29bfb7bc1ecbcef42424eb1c4fc59c02f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
#include "2s2h/resource/importer/SkeletonLimbFactory.h"
#include "2s2h/resource/type/SkeletonLimb.h"
#include <tinyxml2.h>

namespace SOH {
static void BuildSkeletonLimbData(const std::shared_ptr<SkeletonLimb>& skeletonLimb) {
    if (skeletonLimb->limbType == LimbType::LOD) {
        skeletonLimb->limbData.lodLimb.jointPos.x = skeletonLimb->transX;
        skeletonLimb->limbData.lodLimb.jointPos.y = skeletonLimb->transY;
        skeletonLimb->limbData.lodLimb.jointPos.z = skeletonLimb->transZ;
        skeletonLimb->limbData.lodLimb.child = skeletonLimb->childIndex;
        skeletonLimb->limbData.lodLimb.sibling = skeletonLimb->siblingIndex;

        if (!skeletonLimb->dListPtr.empty()) {
            skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
            skeletonLimb->limbData.lodLimb.dLists[0] = (Gfx*)skeletonLimb->dListPtr.c_str();
        } else {
            skeletonLimb->limbData.lodLimb.dLists[0] = nullptr;
        }

        if (!skeletonLimb->dList2Ptr.empty()) {
            skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr;
            skeletonLimb->limbData.lodLimb.dLists[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str();
        } else {
            skeletonLimb->limbData.lodLimb.dLists[1] = nullptr;
        }
    } else if (skeletonLimb->limbType == LimbType::Standard) {
        skeletonLimb->limbData.standardLimb.jointPos.x = skeletonLimb->transX;
        skeletonLimb->limbData.standardLimb.jointPos.y = skeletonLimb->transY;
        skeletonLimb->limbData.standardLimb.jointPos.z = skeletonLimb->transZ;
        skeletonLimb->limbData.standardLimb.child = skeletonLimb->childIndex;
        skeletonLimb->limbData.standardLimb.sibling = skeletonLimb->siblingIndex;
        skeletonLimb->limbData.standardLimb.dList = nullptr;

        if (!skeletonLimb->dListPtr.empty()) {
            skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
            skeletonLimb->limbData.standardLimb.dList = (Gfx*)skeletonLimb->dListPtr.c_str();
        }
    } else if (skeletonLimb->limbType == LimbType::Curve) {
        skeletonLimb->limbData.skelCurveLimb.firstChildIdx = skeletonLimb->childIndex;
        skeletonLimb->limbData.skelCurveLimb.nextLimbIdx = skeletonLimb->siblingIndex;
        skeletonLimb->limbData.skelCurveLimb.dList[0] = nullptr;
        skeletonLimb->limbData.skelCurveLimb.dList[1] = nullptr;

        if (!skeletonLimb->dListPtr.empty()) {
            skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
            skeletonLimb->limbData.skelCurveLimb.dList[0] = (Gfx*)skeletonLimb->dListPtr.c_str();
        }

        if (!skeletonLimb->dList2Ptr.empty()) {
            skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr;
            skeletonLimb->limbData.skelCurveLimb.dList[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str();
        }
    }
}

std::shared_ptr<Ship::IResource>
ResourceFactoryBinarySkeletonLimbV0::ReadResource(std::shared_ptr<Ship::File> file,
                                                  std::shared_ptr<Ship::ResourceInitData> initData) {
    if (!FileHasValidFormatAndReader(file, initData)) {
        return nullptr;
    }

    auto skeletonLimb = std::make_shared<SkeletonLimb>(initData);
    auto reader = std::get<std::shared_ptr<Ship::BinaryReader>>(file->Reader);

    skeletonLimb->limbType = (LimbType)reader->ReadInt8();
    skeletonLimb->skinSegmentType = (ZLimbSkinType)reader->ReadInt8();
    skeletonLimb->skinDList = reader->ReadString();

    skeletonLimb->skinVtxCnt = reader->ReadUInt16();

    skeletonLimb->skinLimbModifCount = reader->ReadUInt32();
    skeletonLimb->skinLimbModifArray.reserve(skeletonLimb->skinLimbModifCount);
    skeletonLimb->skinLimbModifVertexArrays.reserve(skeletonLimb->skinLimbModifCount);
    skeletonLimb->skinLimbModifTransformationArrays.reserve(skeletonLimb->skinLimbModifCount);
    for (size_t i = 0; i < skeletonLimb->skinLimbModifCount; i++) {
        SkinLimbModif skinLimbModif;
        skinLimbModif.unk_4 = reader->ReadUInt16();
        skeletonLimb->skinLimbModifArray.push_back(skinLimbModif);

        std::vector<SkinVertex> skinVertexArray;
        int32_t skinVertexCount = reader->ReadInt32();
        skinVertexArray.reserve(skinVertexCount);
        for (int32_t k = 0; k < skinVertexCount; k++) {
            SkinVertex skinVertex;

            skinVertex.index = reader->ReadInt16();
            skinVertex.s = reader->ReadInt16();
            skinVertex.t = reader->ReadInt16();
            skinVertex.normX = reader->ReadInt8();
            skinVertex.normY = reader->ReadInt8();
            skinVertex.normZ = reader->ReadInt8();
            skinVertex.alpha = reader->ReadUByte();

            skinVertexArray.push_back(skinVertex);
        }
        skeletonLimb->skinLimbModifVertexArrays.push_back(skinVertexArray);

        std::vector<SkinTransformation> skinTransformationArray;
        int32_t skinTransformationCount = reader->ReadInt32();
        skinTransformationArray.reserve(skinTransformationCount);
        for (int32_t k = 0; k < skinTransformationCount; k++) {
            SkinTransformation skinTransformation;

            skinTransformation.limbIndex = reader->ReadUByte();
            skinTransformation.x = reader->ReadInt16();
            skinTransformation.y = reader->ReadInt16();
            skinTransformation.z = reader->ReadInt16();
            skinTransformation.scale = reader->ReadUByte();

            skinTransformationArray.push_back(skinTransformation);
        }
        skeletonLimb->skinLimbModifTransformationArrays.push_back(skinTransformationArray);
    }

    skeletonLimb->skinDList2 = reader->ReadString();

    skeletonLimb->legTransX = reader->ReadFloat();
    skeletonLimb->legTransY = reader->ReadFloat();
    skeletonLimb->legTransZ = reader->ReadFloat();

    skeletonLimb->rotX = reader->ReadUInt16();
    skeletonLimb->rotY = reader->ReadUInt16();
    skeletonLimb->rotZ = reader->ReadUInt16();

    skeletonLimb->childPtr = reader->ReadString();
    skeletonLimb->siblingPtr = reader->ReadString();
    skeletonLimb->dListPtr = reader->ReadString();
    skeletonLimb->dList2Ptr = reader->ReadString();

    skeletonLimb->transX = reader->ReadInt16();
    skeletonLimb->transY = reader->ReadInt16();
    skeletonLimb->transZ = reader->ReadInt16();

    skeletonLimb->childIndex = reader->ReadUByte();
    skeletonLimb->siblingIndex = reader->ReadUByte();

    if (skeletonLimb->limbType == LimbType::LOD) {
        skeletonLimb->limbData.lodLimb.jointPos.x = skeletonLimb->transX;
        skeletonLimb->limbData.lodLimb.jointPos.y = skeletonLimb->transY;
        skeletonLimb->limbData.lodLimb.jointPos.z = skeletonLimb->transZ;
        skeletonLimb->limbData.lodLimb.child = skeletonLimb->childIndex;
        skeletonLimb->limbData.lodLimb.sibling = skeletonLimb->siblingIndex;

        if (skeletonLimb->dListPtr != "") {
            skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
            skeletonLimb->limbData.lodLimb.dLists[0] = (Gfx*)skeletonLimb->dListPtr.c_str();
        } else {
            skeletonLimb->limbData.lodLimb.dLists[0] = nullptr;
        }

        if (skeletonLimb->dList2Ptr != "") {
            skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr;
            skeletonLimb->limbData.lodLimb.dLists[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str();
        } else {
            skeletonLimb->limbData.lodLimb.dLists[1] = nullptr;
        }
    } else if (skeletonLimb->limbType == LimbType::Standard) {
        skeletonLimb->limbData.standardLimb.jointPos.x = skeletonLimb->transX;
        skeletonLimb->limbData.standardLimb.jointPos.y = skeletonLimb->transY;
        skeletonLimb->limbData.standardLimb.jointPos.z = skeletonLimb->transZ;
        skeletonLimb->limbData.standardLimb.child = skeletonLimb->childIndex;
        skeletonLimb->limbData.standardLimb.sibling = skeletonLimb->siblingIndex;
        skeletonLimb->limbData.standardLimb.dList = nullptr;

        if (!skeletonLimb->dListPtr.empty()) {
            skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
            skeletonLimb->limbData.standardLimb.dList = (Gfx*)skeletonLimb->dListPtr.c_str();
        }
    } else if (skeletonLimb->limbType == LimbType::Curve) {
        skeletonLimb->limbData.skelCurveLimb.firstChildIdx = skeletonLimb->childIndex;
        skeletonLimb->limbData.skelCurveLimb.nextLimbIdx = skeletonLimb->siblingIndex;
        skeletonLimb->limbData.skelCurveLimb.dList[0] = nullptr;
        skeletonLimb->limbData.skelCurveLimb.dList[1] = nullptr;

        if (!skeletonLimb->dListPtr.empty()) {
            skeletonLimb->dListPtr = "__OTR__" + skeletonLimb->dListPtr;
            skeletonLimb->limbData.skelCurveLimb.dList[0] = (Gfx*)skeletonLimb->dListPtr.c_str();
        }

        if (!skeletonLimb->dList2Ptr.empty()) {
            skeletonLimb->dList2Ptr = "__OTR__" + skeletonLimb->dList2Ptr;
            skeletonLimb->limbData.skelCurveLimb.dList[1] = (Gfx*)skeletonLimb->dList2Ptr.c_str();
        }
    } else if (skeletonLimb->limbType == LimbType::Skin) {
        skeletonLimb->limbData.skinLimb.jointPos.x = skeletonLimb->transX;
        skeletonLimb->limbData.skinLimb.jointPos.y = skeletonLimb->transY;
        skeletonLimb->limbData.skinLimb.jointPos.z = skeletonLimb->transZ;
        skeletonLimb->limbData.skinLimb.child = skeletonLimb->childIndex;
        skeletonLimb->limbData.skinLimb.sibling = skeletonLimb->siblingIndex;

        if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_DList) {
            skeletonLimb->limbData.skinLimb.segmentType = static_cast<int32_t>(skeletonLimb->skinSegmentType);
        } else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_4) {
            skeletonLimb->limbData.skinLimb.segmentType = 4;
        } else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_5) {
            skeletonLimb->limbData.skinLimb.segmentType = 5;
        } else {
            skeletonLimb->limbData.skinLimb.segmentType = 0;
        }

        if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_DList) {
            if (skeletonLimb->skinDList != "") {
                skeletonLimb->skinDList = "__OTR__" + skeletonLimb->skinDList;
                skeletonLimb->limbData.skinLimb.segment = (Gfx*)skeletonLimb->skinDList.c_str();
            } else {
                skeletonLimb->limbData.skinLimb.segment = nullptr;
            }
        } else if (skeletonLimb->skinSegmentType == ZLimbSkinType::SkinType_4) {
            skeletonLimb->skinAnimLimbData.totalVtxCount = skeletonLimb->skinVtxCnt;
            skeletonLimb->skinAnimLimbData.limbModifCount = skeletonLimb->skinLimbModifCount;
            skeletonLimb->skinAnimLimbData.limbModifications = skeletonLimb->skinLimbModifArray.data();

            if (skeletonLimb->skinDList2 != "") {
                skeletonLimb->skinDList2 = "__OTR__" + skeletonLimb->skinDList2;
                skeletonLimb->skinAnimLimbData.dlist = (Gfx*)skeletonLimb->skinDList2.c_str();
            } else {
                skeletonLimb->skinAnimLimbData.dlist = nullptr;
            }

            for (size_t i = 0; i < skeletonLimb->skinLimbModifArray.size(); i++) {
                skeletonLimb->skinAnimLimbData.limbModifications[i].vtxCount =
                    skeletonLimb->skinLimbModifVertexArrays[i].size();
                skeletonLimb->skinAnimLimbData.limbModifications[i].skinVertices =
                    skeletonLimb->skinLimbModifVertexArrays[i].data();

                skeletonLimb->skinAnimLimbData.limbModifications[i].transformCount =
                    skeletonLimb->skinLimbModifTransformationArrays[i].size();
                skeletonLimb->skinAnimLimbData.limbModifications[i].limbTransformations =
                    skeletonLimb->skinLimbModifTransformationArrays[i].data();

                skeletonLimb->skinAnimLimbData.limbModifications[i].unk_4 = skeletonLimb->skinLimbModifArray[i].unk_4;
            }

            skeletonLimb->limbData.skinLimb.segment = &skeletonLimb->skinAnimLimbData;
        }
    }

    return skeletonLimb;
}

std::shared_ptr<Ship::IResource>
ResourceFactoryXMLSkeletonLimbV0::ReadResource(std::shared_ptr<Ship::File> file,
                                               std::shared_ptr<Ship::ResourceInitData> initData) {
    if (!FileHasValidFormatAndReader(file, initData)) {
        return nullptr;
    }

    auto skelLimb = std::make_shared<SkeletonLimb>(initData);
    auto reader = std::get<std::shared_ptr<tinyxml2::XMLDocument>>(file->Reader)->FirstChildElement();

    skelLimb->limbType = LimbType::LOD;

    // skelLimb->legTransX = reader->FloatAttribute("LegTransX");
    // skelLimb->legTransY = reader->FloatAttribute("LegTransY");
    // skelLimb->legTransZ = reader->FloatAttribute("LegTransZ");
    skelLimb->rotX = reader->IntAttribute("RotX");
    skelLimb->rotY = reader->IntAttribute("RotY");
    skelLimb->rotZ = reader->IntAttribute("RotZ");

    // skelLimb->transX = reader->IntAttribute("TransX");
    // skelLimb->transY = reader->IntAttribute("TransY");
    // skelLimb->transZ = reader->IntAttribute("TransZ");

    skelLimb->transX = (int)reader->FloatAttribute("LegTransX");
    skelLimb->transY = (int)reader->FloatAttribute("LegTransY");
    skelLimb->transZ = (int)reader->FloatAttribute("LegTransZ");

    skelLimb->childIndex = reader->IntAttribute("ChildIndex");
    skelLimb->siblingIndex = reader->IntAttribute("SiblingIndex");

    // skelLimb->childPtr = reader->Attribute("ChildLimb");
    // skelLimb->siblingPtr = reader->Attribute("SiblingLimb");
    if (const char* dList1 = reader->Attribute("DisplayList1")) {
        skelLimb->dListPtr = dList1;
    }
    if (const char* dList2 = reader->Attribute("DisplayList2")) {
        skelLimb->dList2Ptr = dList2;
    }

    if (skelLimb->dListPtr == "gEmptyDL") {
        skelLimb->dListPtr = "";
    }
    if (skelLimb->dList2Ptr == "gEmptyDL") {
        skelLimb->dList2Ptr = "";
    }

    BuildSkeletonLimbData(skelLimb);

    return skelLimb;
}
} // namespace SOH