From b40458ee82fe9c2b1ec232644ddef1c2f069146d Mon Sep 17 00:00:00 2001 From: Lukas Cone Date: Thu, 8 Feb 2024 19:02:31 +0100 Subject: [PATCH] added bunch of new stuff to mod --- database/data/re6.ini | 2 +- include/revil/mod.hpp | 21 +- src/mtf_mod/common.cpp | 1270 ++++++++++++++++++++------- src/mtf_mod/common.hpp | 11 +- src/mtf_mod/header.hpp | 18 +- src/mtf_mod/material.cpp | 2 + src/mtf_mod/material.hpp | 7 + src/mtf_mod/mesh.hpp | 25 +- src/mtf_mod/serialize.cpp | 284 +++++- src/mtf_mod/traits.hpp | 31 +- toolset/mod_to_gltf/mod_to_gltf.cpp | 5 + 11 files changed, 1297 insertions(+), 379 deletions(-) diff --git a/database/data/re6.ini b/database/data/re6.ini index 16582aa..abc511f 100644 --- a/database/data/re6.ini +++ b/database/data/re6.ini @@ -1,6 +1,6 @@ Titles = re6, resident_evil_6, biohazard_6 [MOD:Win32] -Version = 0x2C +Version = 0xD3 [MOD:PS3] Version = 0xFF2C [TEX] diff --git a/include/revil/mod.hpp b/include/revil/mod.hpp index 00467a9..aef7e2e 100644 --- a/include/revil/mod.hpp +++ b/include/revil/mod.hpp @@ -16,8 +16,8 @@ */ #pragma once -#include "spike/io/bincore_fwd.hpp" #include "revil/platform.hpp" +#include "spike/io/bincore_fwd.hpp" #include #include @@ -28,16 +28,21 @@ class MODImpl; enum MODVersion : uint16 { X05 = 0x05, X06 = 0x06, - X70 = 0x70, // DR X360 - X170 = 0x170, // DR PC - X99 = 0x99, // MTF1 generic - XD3 = 0xD3, // RE6 PC + X70 = 0x70, // DR X360 + X170 = 0x170, // DR PC + X99 = 0x99, // MTF1 generic + X19C = 0x19c, // RE5 PC XD2 = 0xD2, - X2CFF = 0x2CFF, // RE6 PS3 - XC5 = 0xC5, // LP2 PC + XD3 = 0xD3, // RE6 PC + XD4 = 0xD4, + XD6 = 0xD6, + XFF2C = 0xFF2C, // RE6 PS3 XC3 = 0xC3, // LP2 PS3 - XE5 = 0xE6, + XC5 = 0xC5, // LP2 PC + XE5 = 0xE5, XE6 = 0xE6, + XE7 = 0xE7, + X21 = 0x21, }; struct alignas(8) MODMaker { diff --git a/src/mtf_mod/common.cpp b/src/mtf_mod/common.cpp index 8cbbfcd..3270d39 100644 --- a/src/mtf_mod/common.cpp +++ b/src/mtf_mod/common.cpp @@ -62,343 +62,508 @@ inline size_t convertLod(es::Flags vis) { return index; } -static const auto makeV1 = [](auto &self, auto &main, bool swap, - bool laterFormat) { - auto &mat = main.materials.storage[self.materialIndex].main; - using material_type = typename std::remove_reference::type; - auto useSkin = mat.vshData.template Get(); - bool skin8 = laterFormat ? useSkin == 4 : useSkin == 2; +MODVertices::MODVertices(std::initializer_list list) { + descs.storage.insert(descs.storage.end(), list); - size_t offset = 0; - size_t stride = self.buffer0Stride; - MODPrimitiveProxyV1 retval; - retval.lodIndex = convertLod(self.visibleLOD); - retval.materialIndex = self.materialIndex; - // retval.name = "group_" + std::to_string(self.unk); + for (auto &d : descs.storage) { + vertexStride += d.typeSize; + } +} - char *mainBuffer = - main.buffer.data() + (self.vertexStart * self.buffer0Stride) + - self.vertexStreamOffset + (self.indexValueOffset * self.buffer0Stride); - auto curBuffer = mainBuffer; +template ... T> +MODVertices BuildVertices(T... items) { + size_t offset = 0; + static constexpr size_t fmtStrides[]{0, 128, 96, 64, 64, 48, 32, 32, 32, + 32, 32, 32, 24, 16, 16, 16, 16, 8}; + uint8 indices[0x10]{}; - MODVertices vtArray; - vtArray.numVertices = self.numVertices; - - auto newDesc = [&](uni::FormatDescr type, size_t size) { - MODVertexDescriptor desc; - desc.stride = stride; - desc.offset = offset; - desc.type = type; - offset += size; - desc.buffer = curBuffer + desc.offset; - return desc; + auto NewDesc = [&](MODVertexDescriptor item) { + item.offset = offset; + item.index = indices[uint8(item.usage)]++; + item.typeSize = fmtStrides[uint8(item.type.compType)] / 8; + offset += item.typeSize; + return item; }; - auto makeBones = [&](size_t index) { - MODVertexDescriptor boneIdx( - newDesc({uni::FormatType::UINT, uni::DataType::R8G8B8A8}, 4)); - boneIdx.usage = uni::PrimitiveDescriptor::Usage_e::BoneIndices; - boneIdx.index = index; - vtArray.descs.storage.emplace_back(boneIdx); - }; + return MODVertices{NewDesc(items)...}; +} - auto makeWeights = [&](size_t index) { - MODVertexDescriptor boneWt( - newDesc({uni::FormatType::UNORM, uni::DataType::R8G8B8A8}, 4)); - boneWt.usage = uni::PrimitiveDescriptor::Usage_e::BoneWeights; - boneWt.index = index; - vtArray.descs.storage.emplace_back(boneWt); - }; +void RebuildVertices(MODVertices &items) { + size_t offset = 0; + static constexpr size_t fmtStrides[]{0, 128, 96, 64, 64, 48, 32, 32, 32, + 32, 32, 32, 24, 16, 16, 16, 16, 8}; + uint8 indices[0x10]{}; - auto makeNormals = [&](auto type) { - MODVertexDescriptor norms(newDesc({uni::FormatType::NORM, type}, 4)); + for (auto &item : items.descs.storage) { + item.offset = offset; + item.index = indices[uint8(item.usage)]++; + item.typeSize = fmtStrides[uint8(item.type.compType)] / 8; + offset += item.typeSize; + } +} - if (laterFormat) { - norms.type.compType = uni::DataType::R8G8B8A8; - norms.type.outType = uni::FormatType::UNORM; - norms.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; - norms.unpackData.max = Vector4A16(-1.f); - norms.unpackData.min = Vector4A16(2.f); - } +using F = uni::FormatType; +using D = uni::DataType; +using U = uni::PrimitiveDescriptor::Usage_e; +using V = MODVertexDescriptor; - norms.usage = uni::PrimitiveDescriptor::Usage_e::Normal; - vtArray.descs.storage.emplace_back(norms); +static const MODVertexDescriptor VertexNormal = [] { + V retVal{F::UNORM, D::R8G8B8A8, U::Normal}; + retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; + retVal.unpackData.min = Vector4A16{2}; + retVal.unpackData.max = Vector4A16{-1}; + return retVal; +}(); - if (!swap || laterFormat) { - return; - } +static const MODVertexDescriptor VertexNormal3 = [] { + V retVal{F::UNORM, D::R8G8B8, U::Normal}; + retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; + retVal.unpackData.min = Vector4A16{2}; + retVal.unpackData.max = Vector4A16{-1}; + return retVal; +}(); - auto normBuff = const_cast(norms.buffer); +static const MODVertexDescriptor VertexTangent = [] { + V retVal{F::UNORM, D::R8G8B8A8, U::Tangent}; + retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; + retVal.unpackData.min = Vector4A16{2}; + retVal.unpackData.max = Vector4A16{-1}; + return retVal; +}(); - for (size_t i = 0; i < self.numVertices; i++) { - FByteswapper(reinterpret_cast(*normBuff)); - normBuff += self.buffer0Stride; - } - }; +static const MODVertexDescriptor VertexTangent3 = [] { + V retVal{F::UNORM, D::R8G8B8, U::Tangent}; + retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; + retVal.unpackData.min = Vector4A16{2}; + retVal.unpackData.max = Vector4A16{-1}; + return retVal; +}(); - auto makeTangents = [&] { - MODVertexDescriptor tangs( - newDesc({uni::FormatType::NORM, uni::DataType::R10G10B10A2}, 4)); - tangs.usage = uni::PrimitiveDescriptor::Usage_e::Tangent; - vtArray.descs.storage.emplace_back(tangs); +static const MODVertexDescriptor TexCoordPhone = [] { + V retVal{F::UNORM, D::R16G16, U::TextureCoordiante}; + retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Mul; + retVal.unpackData.min = Vector4A16{64}; + return retVal; +}(); - if (!swap) { - return; - } +MODVertexDescriptor Packed(MODVertexDescriptor in) { + in.packed = true; + return in; +} - auto tangBuff = const_cast(tangs.buffer); +// clang-format off - for (size_t i = 0; i < self.numVertices; i++) { - FByteswapper(reinterpret_cast(*tangBuff)); - tangBuff += tangs.stride; - } - }; +static const MODVertexDescriptor TexCoord{F::FLOAT, D::R16G16, U::TextureCoordiante}; - auto makeUV = [&](size_t index) { - MODVertexDescriptor uvset( - newDesc({uni::FormatType::FLOAT, uni::DataType::R16G16}, 4)); - uvset.usage = uni::PrimitiveDescriptor::Usage_e::TextureCoordiante; - uvset.index = index; - vtArray.descs.storage.emplace_back(uvset); +static const MODVertexDescriptor VertexQPosition{F::NORM, D::R16G16B16, U::Position}; + +static const MODVertexDescriptor VertexPosition{F::FLOAT, D::R32G32B32, U::Position}; - if (!swap) { - return; +static const MODVertexDescriptor VertexBoneIndices{F::UINT, D::R8G8B8A8, U::BoneIndices}; + +static const MODVertexDescriptor VertexColor{F::UNORM, D::R8G8B8A8, U::VertexColor}; + +static const MODVertexDescriptor VertexNormalSigned{F::NORM, D::R8G8B8A8, U::Normal}; + +static const MODVertexDescriptor VertexTangentSigned{F::NORM, D::R8G8B8A8, U::Tangent}; + +// clang-format on + +static const auto swapBuffers = [](MODVertexDescriptor &d, size_t numVertices) { + char *curBuffer = d.buffer; + + switch (d.type.compType) { + case uni::DataType::R16: { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); } + break; + } - auto uvBuff = const_cast(uvset.buffer); + case uni::DataType::R16G16: { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); + } + break; + } - for (size_t i = 0; i < self.numVertices; i++) { - FByteswapper(reinterpret_cast(*uvBuff)); - uvBuff += uvset.stride; + case uni::DataType::R16G16B16: { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); } - }; + break; + } - auto makeColor = [&](size_t index) { - MODVertexDescriptor color( - newDesc({uni::FormatType::UNORM, uni::DataType::R8G8B8A8}, 4)); - color.usage = uni::PrimitiveDescriptor::Usage_e::VertexColor; - color.index = index; - vtArray.descs.storage.emplace_back(color); + case uni::DataType::R16G16B16A16: { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); + } + break; + } - if (!swap) { - return; + case uni::DataType::R32: + case uni::DataType::R10G10B10A2: { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); } + break; + } - auto colorBuff = const_cast(color.buffer); + case uni::DataType::R8G8B8A8: + if (d.packed) { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); + } + } + break; - for (size_t i = 0; i < self.numVertices; i++) { - auto &v = reinterpret_cast(*colorBuff); - FByteswapper(v); - colorBuff += color.stride; + case uni::DataType::R32G32: { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); } - }; + break; + } + + case uni::DataType::R32G32B32: { + for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { + FByteswapper(*reinterpret_cast(curBuffer)); + } + break; + } + + default: + break; + } +}; + +static const auto makeVertices0X70 = [](uint8 useSkin, bool v1stride4, + auto &main) { + MODVertices vtArray; + const bool skin8 = useSkin == 2; if (useSkin) { - MODVertexDescriptor pos( - newDesc({laterFormat ? uni::FormatType::NORM : uni::FormatType::UNORM, - uni::DataType::R16G16B16A16}, - 8)); - pos.usage = uni::PrimitiveDescriptor::Usage_e::Position; + MODVertexDescriptor pos{F::UNORM, D::R16G16B16A16, U::Position}; pos.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; pos.unpackData.max = main.bounds.bboxMin; pos.unpackData.min = main.bounds.bboxMax - main.bounds.bboxMin; - vtArray.descs.storage.emplace_back(pos); - if (swap) { - auto posBuff = const_cast(pos.buffer); + if (skin8) { + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(F::NORM, D::R10G10B10A2, U::Normal); + vtArray.descs.storage.emplace_back(TexCoord); + } else { + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(F::NORM, D::R10G10B10A2, U::Normal); + vtArray.descs.storage.emplace_back(F::NORM, D::R10G10B10A2, U::Tangent); + vtArray.descs.storage.emplace_back(TexCoord); + } + } else { + vtArray.descs.storage.emplace_back(VertexPosition); + vtArray.descs.storage.emplace_back(Packed(VertexNormalSigned)); + + if (v1stride4) { + vtArray.descs.storage.emplace_back(Packed(VertexTangentSigned)); + vtArray.descs.storage.emplace_back(TexCoord); + vtArray.descs.storage.emplace_back(TexCoord); + // null or swapped with tangent + vtArray.descs.storage.emplace_back(F::UINT, D::R32, U::Undefined); + } else { + // always null? + vtArray.descs.storage.emplace_back(F::UINT, D::R32, U::Undefined); + vtArray.descs.storage.emplace_back(TexCoord); + vtArray.descs.storage.emplace_back(TexCoord); + vtArray.descs.storage.emplace_back(Packed(VertexTangentSigned)); + } + } + + return vtArray; +}; - for (size_t i = 0; i < self.numVertices; i++) { - FByteswapper(reinterpret_cast(*posBuff)); - posBuff += self.buffer0Stride; - } +static const auto makeVertices1X70 = [](uint8 useSkin, bool v1stride4) { + MODVertices vtArray; + const bool skin8 = useSkin == 2; + + if (skin8) { + vtArray.descs.storage.emplace_back(F::NORM, D::R10G10B10A2, U::Tangent); + vtArray.descs.storage.emplace_back(TexCoord); + } else { + vtArray.descs.storage.emplace_back(VertexColor); + + if (!v1stride4) { + vtArray.descs.storage.emplace_back(VertexColor); } + } + return vtArray; +}; + +static const auto makeVertices0X99 = [](uint8 useSkin, bool v1stride4, + auto &main) { + MODVertices vtArray; + const bool skin8 = useSkin == 4; + + if (useSkin) { + MODVertexDescriptor pos{F::NORM, D::R16G16B16A16, U::Position}; + pos.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; + pos.unpackData.max = main.bounds.bboxMin; + pos.unpackData.min = main.bounds.bboxMax - main.bounds.bboxMin; + vtArray.descs.storage.emplace_back(pos); if (skin8) { - makeBones(0); - makeBones(1); - makeWeights(0); - makeWeights(1); - makeNormals(uni::DataType::R10G10B10A2); - makeUV(0); + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(VertexNormal); + vtArray.descs.storage.emplace_back(TexCoord); } else { - makeBones(0); - makeWeights(0); - makeNormals(uni::DataType::R10G10B10A2); - makeTangents(); - makeUV(0); - makeUV(1); + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(VertexNormal); + vtArray.descs.storage.emplace_back(VertexTangent); + vtArray.descs.storage.emplace_back(TexCoord); } } else { - MODVertexDescriptor pos( - newDesc({uni::FormatType::FLOAT, uni::DataType::R32G32B32}, 12)); - pos.usage = uni::PrimitiveDescriptor::Usage_e::Position; - vtArray.descs.storage.emplace_back(pos); + vtArray.descs.storage.emplace_back(VertexPosition); + vtArray.descs.storage.emplace_back(VertexNormal); + + if (v1stride4) { + vtArray.descs.storage.emplace_back(VertexTangent); + vtArray.descs.storage.emplace_back(TexCoord); + vtArray.descs.storage.emplace_back(TexCoord); + // null or swapped with tangent + vtArray.descs.storage.emplace_back(F::UINT, D::R32, U::Undefined); + } else { + // always null? + vtArray.descs.storage.emplace_back(F::UINT, D::R32, U::Undefined); + vtArray.descs.storage.emplace_back(TexCoord); + vtArray.descs.storage.emplace_back(TexCoord); + vtArray.descs.storage.emplace_back(VertexTangent); + } + } - if (swap) { - auto posBuff = const_cast(pos.buffer); + return vtArray; +}; - for (size_t i = 0; i < self.numVertices; i++) { - auto &vec = reinterpret_cast(*posBuff); - FByteswapper(vec); - posBuff += self.buffer0Stride; - } +static const auto makeVertices1X99 = [](uint8 useSkin, bool v1stride4) { + MODVertices vtArray; + const bool skin8 = useSkin == 4; + + if (skin8) { + vtArray.descs.storage.emplace_back(VertexTangent); + vtArray.descs.storage.emplace_back(TexCoord); + } else { + vtArray.descs.storage.emplace_back(VertexColor); + + if (!v1stride4) { + vtArray.descs.storage.emplace_back(VertexColor); } + } + return vtArray; +}; - makeNormals(uni::DataType::R8G8B8A8); +static const auto makeVertices0X170 = [](uint8 useSkin, bool, auto &main) { + MODVertices vtArray; + const bool skin8 = useSkin == 2; + + if (useSkin) { + MODVertexDescriptor pos{F::NORM, D::R16G16B16A16, U::Position}; + pos.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; + pos.unpackData.max = main.bounds.bboxMin; + pos.unpackData.min = main.bounds.bboxMax - main.bounds.bboxMin; + vtArray.descs.storage.emplace_back(pos); - if (self.buffer1Stride != 8) { - makeTangents(); - makeUV(0); - makeUV(1); - // makeColor(0); // null or swapped with tangent + if (skin8) { + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(VertexNormal); + vtArray.descs.storage.emplace_back(TexCoord); } else { - offset += 4; // makeColor(0); // always null? - makeUV(0); - makeUV(1); - makeTangents(); + vtArray.descs.storage.emplace_back(VertexBoneIndices); + vtArray.descs.storage.emplace_back(F::UNORM, D::R8G8B8A8, U::BoneWeights); + vtArray.descs.storage.emplace_back(F::NORM, D::R16G16B16A16, U::Normal); + vtArray.descs.storage.emplace_back(TexCoord); } + } else { + vtArray.descs.storage.emplace_back(VertexPosition); + vtArray.descs.storage.emplace_back(F::NORM, D::R16G16B16A16, U::Normal); + vtArray.descs.storage.emplace_back(F::FLOAT, D::R32G32, + U::TextureCoordiante); } - if (skin8 && self.buffer1Stride != 8) { + return vtArray; +}; + +static const auto makeVertices1X170 = [](uint8 useSkin, bool) { + MODVertices vtArray; + const bool skin8 = useSkin == 2; + + if (useSkin) { + vtArray.descs.storage.emplace_back(F::NORM, D::R16G16B16A16, U::Tangent); + vtArray.descs.storage.emplace_back(TexCoord); + } else if (skin8) { + vtArray.descs.storage.emplace_back(VertexTangent); + vtArray.descs.storage.emplace_back(TexCoord); + } else { + vtArray.descs.storage.emplace_back(F::NORM, D::R16G16B16A16, U::Tangent); + vtArray.descs.storage.emplace_back(F::FLOAT, D::R32G32, + U::TextureCoordiante); + vtArray.descs.storage.emplace_back(VertexColor); + vtArray.descs.storage.emplace_back(VertexColor); + vtArray.descs.storage.emplace_back(VertexColor); + } + return vtArray; +}; + +static const auto makeV1 = [](auto &self, auto &main, auto v0Maker, + auto v1Maker, auto &&fd) { + auto &mat = main.materials.storage[self.materialIndex].main; + using material_type = typename std::remove_reference::type; + auto useSkin = mat.vshData.template Get(); + + MODPrimitiveProxy retval; + retval.lodIndex = convertLod(self.visibleLOD); + retval.materialIndex = self.materialIndex; + // retval.name = "group_" + std::to_string(self.unk); + retval.indexType = uni::Primitive::IndexType_e::Strip; + retval.name = std::to_string(self.unk); + retval.vertexIndex = main.vertices.Size(); + + MODVertices vt0Array = v0Maker(useSkin, self.buffer1Stride != 8, main); + vt0Array.numVertices = self.numVertices; + RebuildVertices(vt0Array); + + char *mainBuffer = + main.buffer.data() + (self.vertexStart * self.buffer0Stride) + + self.vertexStreamOffset + (self.indexValueOffset * self.buffer0Stride); + + for (auto &d : vt0Array.descs.storage) { + d.buffer = mainBuffer + d.offset; + d.stride = self.buffer0Stride; + fd(d); + } + + main.vertices.storage.emplace_back(std::move(vt0Array)); + + /*if (skin8 && self.buffer1Stride != 8) { throw std::runtime_error("Expected secondary buffer of 8 bytes!"); } if (!skin8 && useSkin && self.buffer1Stride) { throw std::runtime_error("Unexpected secondary buffer for skin!"); - } + }*/ if (self.buffer1Stride) { - retval.additionalBuffer = main.buffer.data() + main.vertexBufferSize; - retval.additionalBuffer += self.vertexStream2Offset; - offset = 0; - stride = self.buffer1Stride; - curBuffer = retval.additionalBuffer; + char *additionalBuffer = + main.buffer.data() + main.vertexBufferSize + self.vertexStream2Offset; - if (skin8) { - makeTangents(); - makeUV(1); - } else { - makeColor(0); + MODVertices vt1Array = v1Maker(useSkin, self.buffer1Stride != 8); + vt1Array.numVertices = self.numVertices; + RebuildVertices(vt1Array); - if (offset < self.buffer1Stride) { - makeColor(1); - } + for (auto &d : vt1Array.descs.storage) { + d.buffer = additionalBuffer + d.offset; + d.stride = self.buffer1Stride; + fd(d); } + + main.vertices.storage.emplace_back(std::move(vt1Array)); } uint16 *indexBuffer = reinterpret_cast(&main.buffer[0] + main.vertexBufferSize + main.unkBufferSize + (self.indexStart * 2)); retval.indexIndex = main.indices.Size(); - retval.vertexIndex = main.vertices.Size(); MODIndices idArray; idArray.indexData = reinterpret_cast(indexBuffer); idArray.numIndices = self.numIndices; for (size_t i = 0; i < self.numIndices; i++) { - if (swap) { - FByteswapper(indexBuffer[i]); - } if (indexBuffer[i] != 0xffff) { indexBuffer[i] -= self.vertexStart; } } main.indices.storage.emplace_back(idArray); - main.vertices.storage.emplace_back(std::move(vtArray)); - retval.indexType = uni::Primitive::IndexType_e::Strip; - retval.name = std::to_string(self.unk); return retval; }; -MODPrimitiveProxyV1 MODMeshX70::ReflectBE(revil::MODImpl &main_) { - auto &main = static_cast &>(main_); - return makeV1(*this, main, true, false); -} - -MODPrimitiveProxyV1 MODMeshX99::ReflectLE(revil::MODImpl &main_) { - auto &main = static_cast &>(main_); - auto retval = makeV1(*this, main, false, true); - retval.skinIndex = skinInfo.boneRemapIndex; - return retval; -} - -MODPrimitiveProxyV1 MODMeshX99::ReflectBE(revil::MODImpl &main_) { - auto &main = static_cast &>(main_); - auto retval = makeV1(*this, main, true, true); - retval.skinIndex = skinInfo.boneRemapIndex; - return retval; +MODPrimitiveProxy MODMeshX70::ReflectLE(revil::MODImpl &main_) { + auto &main = static_cast &>(main_); + return makeV1(*this, main, makeVertices0X170, makeVertices1X170, + [&](MODVertexDescriptor &) {}); } -MODVertices::MODVertices(std::initializer_list list) { - descs.storage.insert(descs.storage.end(), list); -} - -template ... T> -MODVertices BuildVertices(T... items) { - size_t offset = 0; - static constexpr size_t fmtStrides[]{0, 128, 96, 64, 64, 48, 32, 32, 32, - 32, 32, 32, 24, 16, 16, 16, 16, 8}; - uint8 indices[0x10]{}; - - auto NewDesc = [&](MODVertexDescriptor item) { - item.offset = offset; - item.index = indices[uint8(item.usage)]++; - offset += fmtStrides[uint8(item.type.compType)] / 8; - return item; - }; - - return MODVertices{NewDesc(items)...}; -} - -using F = uni::FormatType; -using D = uni::DataType; -using U = uni::PrimitiveDescriptor::Usage_e; -using V = MODVertexDescriptor; - -static const MODVertexDescriptor VertexNormal = [] { - V retVal{F::UNORM, D::R8G8B8A8, U::Normal}; - retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; - retVal.unpackData.min = Vector4A16{2}; - retVal.unpackData.max = Vector4A16{-1}; - return retVal; -}(); - -static const MODVertexDescriptor VertexTangent = [] { - V retVal{F::UNORM, D::R8G8B8A8, U::Tangent}; - retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Madd; - retVal.unpackData.min = Vector4A16{2}; - retVal.unpackData.max = Vector4A16{-1}; - return retVal; -}(); - -static const MODVertexDescriptor TexCoordPhone = [] { - V retVal{F::UNORM, D::R16G16, U::TextureCoordiante}; - retVal.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Mul; - retVal.unpackData.min = Vector4A16{64}; - return retVal; -}(); - -// clang-format off - -static const MODVertexDescriptor TexCoord{F::FLOAT, D::R16G16, U::TextureCoordiante}; - -static const MODVertexDescriptor VertexQPosition{F::NORM, D::R16G16B16, U::Position}; - -static const MODVertexDescriptor VertexPosition{F::FLOAT, D::R32G32B32, U::Position}; +MODPrimitiveProxy MODMeshX70::ReflectBE(revil::MODImpl &main_) { + auto &main = static_cast &>(main_); + return makeV1(*this, main, makeVertices0X70, makeVertices1X70, + [&](MODVertexDescriptor &d) { swapBuffers(d, numVertices); }); +} -static const MODVertexDescriptor VertexBoneIndices{F::UINT, D::R8G8B8A8, U::BoneIndices}; +MODPrimitiveProxy MODMeshX99::ReflectLE(revil::MODImpl &main_) { + auto &main = static_cast &>(main_); + auto retval = makeV1(*this, main, makeVertices0X99, makeVertices1X99, + [&](MODVertexDescriptor &) {}); + retval.skinIndex = skinInfo.boneRemapIndex; + return retval; +} -static const MODVertexDescriptor VertexColor{F::UNORM, D::R8G8B8A8, U::VertexColor}; +MODPrimitiveProxy MODMeshX99::ReflectBE(revil::MODImpl &main_) { + auto &main = static_cast &>(main_); + auto retval = + makeV1(*this, main, makeVertices0X99, makeVertices1X99, + [&](MODVertexDescriptor &d) { swapBuffers(d, numVertices); }); + retval.skinIndex = skinInfo.boneRemapIndex; + return retval; +} -static const MODVertexDescriptor VertexNormalSigned{F::NORM, D::R8G8B8A8, U::Normal}; +// clang-format off -static const MODVertexDescriptor VertexTangentSigned{F::NORM, D::R8G8B8A8, U::Tangent}; +std::map fallbackFormats{ + { + // xc3 + 0xc31f2014, // P3s_W1s_N3c_B1c_T3c_B1c_U2h + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal3, + V{F::UINT, D::R8, U::BoneIndices}, + VertexTangent3, + V{F::UINT, D::R8, U::BoneIndices}, + TexCoord), + }, + { + // xd2 be, this might be correct after all + 0xd8297028, // P3f_N4c_T4c_U2h + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + VertexColor), + }, +}; std::map formats{ + { + 0x64593022, // P3s_W1s_N4c_T4c_B4c_U2h_W2h_unk_U2h_unk + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + V{F::UINT, D::R32, U::Undefined}), + }, { 0x64593023, // P3s_W1s_N4c_T4c_B4c_U2h_W2h_unk_U2h_unk BuildVertices(VertexQPosition, @@ -412,6 +577,19 @@ std::map formats{ TexCoord, V{F::UINT, D::R32, U::Undefined}), }, + { + 0x64593025, // P3s_W1s_N4c_T4c_B4c_U2h_W2h_unk_U2h_unk + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + V{F::UINT, D::R32, U::Undefined}), + }, { 0x14d40020, // P3s_W1s_N4c_T4c_B4c_U2h_W2h BuildVertices(VertexQPosition, @@ -422,6 +600,16 @@ std::map formats{ TexCoord, V{F::FLOAT, D::R16G16, U::BoneWeights}), }, + { + 0x14d40022, // P3s_W1s_N4c_T4c_B4c_U2h_W2h + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}), + }, { 0x14d40019, // P3s_W1s_N4c_T4c_B4c_U2h_W2h BuildVertices(VertexQPosition, @@ -431,6 +619,16 @@ std::map formats{ VertexBoneIndices, TexCoord, V{F::FLOAT, D::R16G16, U::BoneWeights}), + }, + { + 0x14d4001f, // P3s_W1s_N4c_T4c_B4c_U2h_W2h + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}), }, { 0x14d40021, // P3s_W1s_N4c_T4c_B4c_U2h_W2h @@ -463,6 +661,28 @@ std::map formats{ V{F::FLOAT, D::R16G16, U::BoneWeights}, VertexColor), }, + { + 0x77d87021, // P3s_W1s_N4c_T4c_B4c_U2h_W2h_VC4c + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexColor), + }, + { + 0x77d87024, // P3s_W1s_N4c_T4c_B4c_U2h_W2h_VC4c + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexColor), + }, { 0x77d87022, // P3s_W1s_N4c_T4c_B4c_U2h_W2h_VC4c BuildVertices(VertexQPosition, @@ -485,6 +705,20 @@ std::map formats{ V{F::FLOAT, D::R16G16, U::BoneWeights}, VertexColor), }, + { + 0x207d6036, // P3f_N4c_U2h_VC4c + BuildVertices(VertexPosition, + V{F::UINT, D::R32, U::Undefined},// polar ts? + TexCoord, + VertexColor), + }, + { + 0x207d603b, // P3f_N4c_U2h_VC4c + BuildVertices(VertexPosition, + V{F::UINT, D::R32, U::Undefined},// polar ts? + TexCoord, + VertexColor), + }, { 0x207d6037, // P3f_N4c_U2h_VC4c BuildVertices(VertexPosition, @@ -519,6 +753,22 @@ std::map formats{ V{F::UINT, D::R32G32B32A32, U::Undefined}, V{F::UINT, D::R32G32B32A32, U::Undefined}), }, + { + 0x49b4f028, // P3f_N4c_T4c_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + VertexColor), + }, + { + 0x49b4f02d, // P3f_N4c_T4c_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + VertexColor), + }, { 0x49b4f029, // P3f_N4c_T4c_U2h_VC4c BuildVertices(VertexPosition, @@ -527,6 +777,14 @@ std::map formats{ TexCoord, VertexColor), }, + { + 0x49b4f00e, // P3f_N4c_T4c_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormalSigned, + VertexTangentSigned, + TexCoord, + VertexColor), + }, { 0x49b4f022, // P3f_N4c_T4c_U2h_VC4c BuildVertices(VertexPosition, @@ -543,6 +801,14 @@ std::map formats{ TexCoord, VertexColor), }, + { + 0x49b4f015, // P3f_N4c_T4c_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormalSigned, + VertexTangentSigned, + TexCoord, + VertexColor), + }, { 0x5e7f202c, // P3f_N4c_T4c_U2h_U2h BuildVertices(VertexPosition, @@ -559,6 +825,14 @@ std::map formats{ TexCoord, TexCoord), }, + { + 0x5e7f2030, // P3f_N4c_T4c_U2h_U2h + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + TexCoord), + }, { 0x747d1031, // P3f_N4c_T4c_U2h_U2h_U2h BuildVertices(VertexPosition, @@ -581,6 +855,24 @@ std::map formats{ VertexTangent, TexCoord), }, + { + 0x926fd02d, // P3f_N4c_T4c_U2h_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + TexCoord, + VertexColor), + }, + { + 0x926fd032, // P3f_N4c_T4c_U2h_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + TexCoord, + VertexColor), + }, { 0x926fd02e, // P3f_N4c_T4c_U2h_U2h_VC4c BuildVertices(VertexPosition, @@ -599,6 +891,36 @@ std::map formats{ TexCoord, VertexColor), }, + { + 0xCBCF7026, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c_unk1i_U2h_unk1i + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, + VertexBoneIndices, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexTangent, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + V{F::UINT, D::R32, U::Undefined}), + }, + { + 0xCBCF702A, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c_unk1i_U2h_unk1i + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, + VertexBoneIndices, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexTangent, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + V{F::UINT, D::R32, U::Undefined}), + }, { 0xCBCF7027, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c_unk1i_U2h_unk1i BuildVertices(VertexQPosition, @@ -614,6 +936,30 @@ std::map formats{ TexCoord, V{F::UINT, D::R32, U::Undefined}), }, + { + 0xbb424023, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, + VertexBoneIndices, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexTangent), + }, + { + 0xbb424027, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, + VertexBoneIndices, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexTangent), + }, { 0xbb424024, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c BuildVertices(VertexQPosition, @@ -643,56 +989,108 @@ std::map formats{ BuildVertices(VertexQPosition, V{F::NORM, D::R16, U::BoneWeights}, VertexNormal, - V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, - VertexBoneIndices, + V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, + VertexBoneIndices, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexTangent), + }, + { + 0xbb424025, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormalSigned, + V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, + VertexBoneIndices, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + VertexTangentSigned), + }, + { + 0xb392101f, // P3s_W1s_N4c_T4c_B2h_U2h_U2h_unk2i + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + V{F::FLOAT, D::R16G16, U::BoneIndices}, + TexCoord, + TexCoord, + V{F::UINT, D::R32G32, U::Undefined}), + }, + { + 0xb3921020, // P3s_W1s_N4c_T4c_B2h_U2h_U2h_unk2i + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + V{F::FLOAT, D::R16G16, U::BoneIndices}, + TexCoord, + TexCoord, + V{F::UINT, D::R32G32, U::Undefined}), + }, + { + 0xda55a020, // P3s_W1s_N4c_T4c_B4c_U2h_W2s_U2h + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + TexCoord), + }, + { + 0xda55a021, // P3s_W1s_N4c_T4c_B4c_U2h_W2s_U2h + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, VertexBoneIndices, TexCoord, V{F::FLOAT, D::R16G16, U::BoneWeights}, - VertexTangent), + TexCoord), }, { - 0xbb424025, // P3s_W1s_N4c_W4c_B8c_U2h_W2h_T4c + 0xda55a023, // P3s_W1s_N4c_T4c_B4c_U2h_W2s_U2h BuildVertices(VertexQPosition, V{F::NORM, D::R16, U::BoneWeights}, - VertexNormalSigned, - V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, - VertexBoneIndices, + VertexNormal, + VertexTangent, VertexBoneIndices, TexCoord, V{F::FLOAT, D::R16G16, U::BoneWeights}, - VertexTangentSigned), + TexCoord), }, { - 0xb392101f, // P3s_W1s_N4c_T4c_B2h_U2h_U2h_unk2i + 0xd9e801d, // P3s_W1s_N4c_T4c_U2h_B2h_U2h BuildVertices(VertexQPosition, V{F::NORM, D::R16, U::BoneWeights}, VertexNormal, VertexTangent, - V{F::FLOAT, D::R16G16, U::BoneIndices}, - TexCoord, TexCoord, - V{F::UINT, D::R32G32, U::Undefined}), + V{F::FLOAT, D::R16G16, U::BoneIndices}, + TexCoord), }, { - 0xda55a021, // P3s_W1s_N4c_T4c_B4c_U2h_W2s_U2h + 0xd9e801e, // P3s_W1s_N4c_T4c_U2h_B2h_U2h BuildVertices(VertexQPosition, V{F::NORM, D::R16, U::BoneWeights}, VertexNormal, VertexTangent, - VertexBoneIndices, TexCoord, - V{F::FLOAT, D::R16G16, U::BoneWeights}, + V{F::FLOAT, D::R16G16, U::BoneIndices}, TexCoord), }, { - 0xd9e801d, // P3s_W1s_N4c_T4c_U2h_B2h_U2h + 0xc31f201b, // P3s_W1s_N4c_T4c_U2h_B2h BuildVertices(VertexQPosition, V{F::NORM, D::R16, U::BoneWeights}, VertexNormal, VertexTangent, TexCoord, - V{F::FLOAT, D::R16G16, U::BoneIndices}, - TexCoord), + V{F::FLOAT, D::R16G16, U::BoneIndices}), }, { 0xc31f201c, // P3s_W1s_N4c_T4c_U2h_B2h @@ -730,6 +1128,16 @@ std::map formats{ TexCoord, V{F::FLOAT, D::R16G16, U::BoneIndices}), }, + { + 0xa013501d, // P3s_W1s_N4c_T4c_U2h_B2h_VC4c + BuildVertices(VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneIndices}, + VertexColor), + }, { 0xa013501e, // P3s_W1s_N4c_T4c_U2h_B2h_VC4c BuildVertices(VertexQPosition, @@ -750,6 +1158,17 @@ std::map formats{ V{F::FLOAT, D::R16G16, U::BoneIndices}, VertexColor), }, + { + 0xd877801a, // P3s_B1s_N4c_T4c_U2h_unk1i_U2h_unk1i + BuildVertices(VertexQPosition, + V{F::INT, D::R16, U::BoneIndices}, + VertexNormal, + VertexTangent, + TexCoord, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + V{F::UINT, D::R32, U::Undefined}), + }, { 0xd877801b, // P3s_B1s_N4c_T4c_U2h_unk1i_U2h_unk1i BuildVertices(VertexQPosition, @@ -761,6 +1180,15 @@ std::map formats{ TexCoord, V{F::UINT, D::R32, U::Undefined}), }, + { + 0xcbf6c019, // P3s_unk1s_T4c_N4c_U2h_VC4c + BuildVertices(VertexQPosition, + V{F::UINT, D::R16, U::Undefined}, // bone? + VertexNormal, + VertexTangent, + TexCoord, + VertexColor), + }, { 0xcbf6c01a, // P3s_unk1s_T4c_N4c_U2h_VC4c BuildVertices(VertexQPosition, @@ -779,6 +1207,16 @@ std::map formats{ TexCoord, VertexColor), }, + { + 0xcbf6c00e, // P3s_unk1s_T4c_N4c_U2h_VC4c + BuildVertices(VertexQPosition, + V{F::UINT, D::R16, U::Undefined}, + VertexNormalSigned, + TexCoord, + TexCoord, + VertexColor, + VertexTangentSigned), + }, { 0x37a4e035, // P3s_N4c_T4c_U2h_U2h_U2h_U2h BuildVertices(VertexPosition, @@ -806,6 +1244,28 @@ std::map formats{ TexCoord, TexCoord), }, + { + 0xafa63031, // P3f_N4c_T4c_U2h_U2h + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + TexCoord), + }, + { + 0xd8297027, // P3f_N4c_T4c_U2h + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord), + }, + { + 0xd829702c, // P3f_N4c_T4c_U2h + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord), + }, { 0xd8297028, // P3f_N4c_T4c_U2h BuildVertices(VertexPosition, @@ -842,6 +1302,13 @@ std::map formats{ TexCoord, TexCoord), }, + { + 0xc66fa03e, // P3f_N4c_U2h_U2h + BuildVertices(VertexPosition, + VertexNormal, + TexCoord, + TexCoord), + }, { 0xd1a47038, // P3f_N4c_U2h_U2h BuildVertices(VertexPosition, @@ -849,12 +1316,31 @@ std::map formats{ TexCoord, TexCoord), }, + { + 0xd1a4703c, // P3f_N4c_U2h_U2h + BuildVertices(VertexPosition, + VertexNormal, + TexCoord, + TexCoord), + }, + { + 0xa7d7d035, // P3f_N4c_U2h + BuildVertices(VertexPosition, + V{F::UINT, D::R32, U::Undefined},// polar ts? + TexCoord), + }, { 0xa7d7d036, // P3f_N4c_U2h BuildVertices(VertexPosition, VertexNormal, TexCoord), }, + { + 0xa7d7d03a, // P3f_N4c_U2h + BuildVertices(VertexPosition, + V{F::UINT, D::R32, U::Undefined},// polar ts? + TexCoord), + }, { 0xa7d7d02f, // P3f_N4c_U2h BuildVertices(VertexPosition, @@ -875,6 +1361,14 @@ std::map formats{ TexCoord, VertexColor), }, + { + 0xa14e0040, // P3f_N4c_U2h_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormal, + TexCoord, + TexCoord, + VertexColor), + }, { 0x9399c033, // P3f_N4c_T4c_U2h_U2h_VC4c BuildVertices(VertexPosition, @@ -884,6 +1378,15 @@ std::map formats{ TexCoord, VertexColor), }, + { + 0x9399c037, // P3f_N4c_T4c_U2h_U2h_VC4c + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + TexCoord, + VertexColor), + }, { 0x4325a03e, // P3f_N4c_T4c_U2h_U2h_unk3h_unk1s_unki7 BuildVertices(VertexPosition, @@ -905,6 +1408,16 @@ std::map formats{ VertexColor, TexCoord), }, + { + 0xb6681038, // P3f_N4c_T4c_U2h_U2h_VC4c_U2h + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + TexCoord, + VertexColor, + TexCoord), + }, { 0x63b6c02f, // P3f_N4c_T4c_U2h_U2h_U2h_unk1i BuildVertices(VertexPosition, @@ -915,6 +1428,24 @@ std::map formats{ TexCoord, V{F::UINT, D::R32, U::Undefined}), }, + { + 0x63b6c033, // P3f_N4c_T4c_U2h_U2h_U2h_unk1i + BuildVertices(VertexPosition, + VertexNormal, + VertexTangent, + TexCoord, + TexCoord, + TexCoord, + V{F::UINT, D::R32, U::Undefined}), + }, + { + 0xa8fab017, // P3f_1s_N4c_T4c_U2h + BuildVertices(VertexQPosition, + V{F::INT, D::R16, U::BoneIndices}, + VertexNormal, + VertexTangent, + TexCoord), + }, { 0xa8fab018, // P3f_1s_N4c_T4c_U2h BuildVertices(VertexQPosition, @@ -1001,6 +1532,15 @@ std::map formats{ V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, TexCoordPhone), }, + { + 0x667B1018, // P3s_unk1s_N4c_VC4c_U2h_T4c + BuildVertices(VertexQPosition, + V{F::UINT, D::R16, U::Undefined}, + VertexNormal, + VertexColor, + TexCoord, + VertexTangent), + }, { 0x667B1019, // P3s_unk1s_N4c_VC4c_U2h_T4c BuildVertices(VertexQPosition, @@ -1113,29 +1653,138 @@ std::map formats{ V{F::FLOAT, D::R32G32, U::TextureCoordiante} ), }, + { + 0x6180300A, + BuildVertices( + VertexPosition, + VertexNormalSigned, + V{F::FLOAT, D::R32G32, U::TextureCoordiante}, + VertexColor, + VertexTangentSigned + ), + }, + { + 0x3F78800C, + BuildVertices( + VertexPosition, + VertexNormalSigned, + V{F::FLOAT, D::R32G32, U::TextureCoordiante}, + VertexColor, + VertexTangentSigned + ), + }, + { + 0xEDF6F03C, + BuildVertices( + VertexPosition, + VertexNormal, + VertexTangent, + VertexBoneIndices, + V{F::UNORM, D::R8G8B8A8, U::BoneWeights}, + TexCoord + ), + }, + { + 0x3339D03A, + BuildVertices( + VertexPosition, + VertexNormal3, + V{F::UINT, D::R8, U::BoneIndices}, + TexCoord + ), + }, + { + 0xFD35504D, + BuildVertices( + VertexPosition, + VertexNormal, + Packed(VertexColor), + TexCoord, + TexCoord + ), + }, + { + 0x682EF04C, + BuildVertices( + VertexPosition, + VertexNormal, + Packed(VertexColor), + TexCoord + ), + }, + { + 0x707FB01C, + BuildVertices( + VertexQPosition, + V{F::UINT, D::R16, U::Undefined}, // bone id? + VertexNormal, + VertexTangent, + TexCoord, + V{F::UINT, D::R32, U::Undefined}, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + VertexColor + ), + }, + { + 0xCC510026, + BuildVertices( + VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + VertexBoneIndices, + TexCoord, + V{F::FLOAT, D::R16G16, U::BoneWeights}, + V{F::UINT, D::R32, U::Undefined}, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + V{F::UINT, D::R32, U::Undefined} + ), + }, + { + 0x1B9A2021, + BuildVertices( + VertexQPosition, + V{F::NORM, D::R16, U::BoneWeights}, + VertexNormal, + VertexTangent, + V{F::FLOAT, D::R16G16, U::BoneIndices}, + TexCoord, + V{F::UINT, D::R32, U::Undefined}, + V{F::UINT, D::R32, U::Undefined}, + TexCoord, + V{F::UINT, D::R32, U::Undefined} + ), + } }; // clang-format on static const std::set edgeModels{ 0xdb7da014, + 0xdb7da013, // P3s_unk1s_B4c_W4c_N4c 0x0CB68015, + 0x0CB68014, // P3s_B1s_N4c 0xB0983013, // P3s_unk1s_B8c_W8c_N4c + 0xA320C015, 0xA320C016, + 0xB0983014, + 0xB0983012, }; -static const auto makeV2 = [](auto &self, revil::MODImpl &main, bool swap, - auto &&fd) { +static const auto makeV2 = [](auto &self, revil::MODImpl &main, auto &&fd) { MODPrimitiveProxy retval; uint8 visibleLOD = self.data0.template Get(); retval.lodIndex = convertLod(reinterpret_cast &>(visibleLOD)); retval.materialIndex = self.data0.template Get(); const MODMeshXC5::PrimitiveType_e primitiveType = MODMeshXC5::PrimitiveType_e( - self.data1.template Get()); + self.data1.template Get< + typename std::decay_t::PrimitiveType>()); switch (primitiveType) { case MODMeshXC5::PrimitiveType_e::Triangles: @@ -1164,8 +1813,17 @@ static const auto makeV2 = [](auto &self, revil::MODImpl &main, bool swap, auto foundFormat = formats.find(self.vertexFormat); if (!es::IsEnd(formats, foundFormat)) { + if (foundFormat->second.vertexStride != vertexStride) { + foundFormat = fallbackFormats.find(self.vertexFormat); + if (es::IsEnd(fallbackFormats, foundFormat)) { + throw std::runtime_error("Cannot find fallback vertex format: " + + std::to_string(self.vertexFormat)); + } + } + MODVertices tmpl = foundFormat->second; tmpl.numVertices = self.numVertices; + for (auto &d : tmpl.descs.storage) { d.buffer = mainBuffer + d.offset; d.stride = vertexStride; @@ -1188,18 +1846,9 @@ static const auto makeV2 = [](auto &self, revil::MODImpl &main, bool swap, idArray.indexData = reinterpret_cast(indexBuffer); idArray.numIndices = self.numIndices; - if (swap) { - for (size_t i = 0; i < self.numIndices; i++) { - if (indexBuffer[i] != 0xffff) { - FByteswapper(indexBuffer[i]); - indexBuffer[i] -= self.vertexStart; - } - } - } else { - for (size_t i = 0; i < self.numIndices; i++) { - if (indexBuffer[i] != 0xffff) { - indexBuffer[i] -= self.vertexStart; - } + for (size_t i = 0; i < self.numIndices; i++) { + if (indexBuffer[i] != 0xffff) { + indexBuffer[i] -= self.vertexStart; } } @@ -1208,46 +1857,9 @@ static const auto makeV2 = [](auto &self, revil::MODImpl &main, bool swap, return retval; }; -static const auto swapBuffers = [](MODVertexDescriptor &d, size_t numVertices) { - char *curBuffer = d.buffer; - - switch (d.type.compType) { - case uni::DataType::R16: { - for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { - FByteswapper(*reinterpret_cast(curBuffer)); - } - break; - } - - case uni::DataType::R16G16: { - for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { - FByteswapper(*reinterpret_cast(curBuffer)); - } - break; - } - - case uni::DataType::R16G16B16: { - for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { - FByteswapper(*reinterpret_cast(curBuffer)); - } - break; - } - - case uni::DataType::R32G32B32: { - for (size_t v = 0; v < numVertices; v++, curBuffer += d.stride) { - FByteswapper(*reinterpret_cast(curBuffer)); - } - break; - } - - default: - break; - } -}; - MODPrimitiveProxy MODMeshXD2::ReflectLE(revil::MODImpl &main_) { - auto &main = static_cast &>(main_); - return makeV2(*this, main, false, [&](MODVertexDescriptor &d) { + auto &main = static_cast &>(main_); + return makeV2(*this, main, [&](MODVertexDescriptor &d) { if (d.usage == uni::PrimitiveDescriptor::Usage_e::BoneIndices && skinBoneBegin) { d.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Add; @@ -1258,7 +1870,7 @@ MODPrimitiveProxy MODMeshXD2::ReflectLE(revil::MODImpl &main_) { MODPrimitiveProxy MODMeshXD2::ReflectBE(revil::MODImpl &main_) { auto &main = static_cast &>(main_); - return makeV2(*this, main, true, [&](MODVertexDescriptor &d) { + return makeV2(*this, main, [&](MODVertexDescriptor &d) { if (d.usage == uni::PrimitiveDescriptor::Usage_e::BoneIndices && skinBoneBegin < main.bones.size()) { d.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Add; @@ -1271,7 +1883,7 @@ MODPrimitiveProxy MODMeshXD2::ReflectBE(revil::MODImpl &main_) { MODPrimitiveProxy MODMeshXD3PS4::ReflectLE(revil::MODImpl &main_) { auto &main = static_cast &>(main_); - return makeV2(*this, main, false, [&](MODVertexDescriptor &d) { + return makeV2(*this, main, [&](MODVertexDescriptor &d) { if (d.usage == uni::PrimitiveDescriptor::Usage_e::BoneIndices && skinBoneBegin) { d.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Add; @@ -1288,7 +1900,7 @@ MODPrimitiveProxy MODMeshXD3PS4::ReflectLE(revil::MODImpl &main_) { MODPrimitiveProxy MODMeshXD3::ReflectLE(revil::MODImpl &main_) { auto &main = static_cast &>(main_); - return makeV2(*this, main, false, [&](MODVertexDescriptor &d) { + return makeV2(*this, main, [&](MODVertexDescriptor &d) { if (d.usage == uni::PrimitiveDescriptor::Usage_e::BoneIndices && skinBoneBegin) { d.unpackType = uni::PrimitiveDescriptor::UnpackDataType_e::Add; @@ -1299,12 +1911,18 @@ MODPrimitiveProxy MODMeshXD3::ReflectLE(revil::MODImpl &main_) { MODPrimitiveProxy MODMeshXC5::ReflectLE(revil::MODImpl &main_) { auto &main = static_cast &>(main_); - return makeV2(*this, main, false, [&](MODVertexDescriptor &) {}); + return makeV2(*this, main, [&](MODVertexDescriptor &) {}); +} + +MODPrimitiveProxy MODMeshXC5::ReflectBE(revil::MODImpl &main_) { + auto &main = static_cast &>(main_); + return makeV2(*this, main, + [&](MODVertexDescriptor &d) { swapBuffers(d, numVertices); }); } MODPrimitiveProxy MODMeshX06::ReflectLE(revil::MODImpl &main_) { - auto &main = static_cast &>(main_); - auto retval = makeV2(*this, main, false, [&](MODVertexDescriptor &) {}); + auto &main = static_cast &>(main_); + auto retval = makeV2(*this, main, [&](MODVertexDescriptor &) {}); retval.skinIndex = skinBoneBegin; /*auto idxArray = main.Indices()->At(retval.indexIndex); @@ -1356,7 +1974,7 @@ MODPrimitiveProxy MODMeshX06::ReflectLE(revil::MODImpl &main_) { MODPrimitiveProxy MODMeshXE5::ReflectBE(revil::MODImpl &main_) { auto &main = static_cast &>(main_); - auto retval = makeV2(*this, main, true, [&](MODVertexDescriptor &d) { + auto retval = makeV2(*this, main, [&](MODVertexDescriptor &d) { swapBuffers(d, numVertices); }); retval.skinIndex = numEnvelopes; @@ -1366,7 +1984,7 @@ MODPrimitiveProxy MODMeshXE5::ReflectBE(revil::MODImpl &main_) { MODPrimitiveProxy MODMeshXE5::ReflectLE(revil::MODImpl &main_) { auto &main = static_cast &>(main_); - auto retval = makeV2(*this, main, false, [&](MODVertexDescriptor &) {}); + auto retval = makeV2(*this, main, [&](MODVertexDescriptor &) {}); retval.skinIndex = numEnvelopes; return retval; diff --git a/src/mtf_mod/common.hpp b/src/mtf_mod/common.hpp index 68184ab..2ee88f4 100644 --- a/src/mtf_mod/common.hpp +++ b/src/mtf_mod/common.hpp @@ -115,10 +115,6 @@ struct MODPrimitiveProxy : uni::Primitive { } }; -struct MODPrimitiveProxyV1 : MODPrimitiveProxy { - char *additionalBuffer; -}; - struct MODIndices : uni::IndexArray { const char *indexData; size_t numIndices; @@ -140,6 +136,8 @@ struct MODVertexDescriptor : uni::PrimitiveDescriptor { uni::FormatDescr type; uni::BBOX unpackData; UnpackDataType_e unpackType = UnpackDataType_e::None; + uint32 typeSize = 0; + bool packed = false; MODVertexDescriptor() = default; MODVertexDescriptor(uni::FormatType fmtType, uni::DataType dtType, @@ -162,7 +160,8 @@ struct MODVertexDescriptor : uni::PrimitiveDescriptor { struct MODVertices : uni::VertexArray { uni::VectorList descs; - size_t numVertices = 0; + uint32 numVertices = 0; + uint32 vertexStride = 0; MODVertices(MODVertices &&) = default; MODVertices(const MODVertices &) = default; @@ -246,7 +245,7 @@ template class MODMaterialProxy : public uni::Material { }; template struct MODInner : revil::MODImpl { - uni::VectorList primitives; + uni::VectorList primitives; uni::VectorList skins; uni::VectorList paths; uni::VectorList> diff --git a/src/mtf_mod/header.hpp b/src/mtf_mod/header.hpp index fa3116f..1c4b820 100644 --- a/src/mtf_mod/header.hpp +++ b/src/mtf_mod/header.hpp @@ -81,7 +81,7 @@ struct MODHeaderX170 : MODHeaderCommon { uint64 indices; }; -struct MODHeaderXD2 : MODHeaderCommon { +struct MODHeaderXDx32 : MODHeaderCommon { uint32 vertexBufferSize; uint32 numTextures; uint32 numGroups; @@ -94,7 +94,7 @@ struct MODHeaderXD2 : MODHeaderCommon { uint32 dataEnd; }; -struct MODHeaderXD3X64 : MODHeaderCommon { +struct MODHeaderXDx64 : MODHeaderCommon { uint32 vertexBufferSize; uint32 numTextures; uint32 numGroups; @@ -136,3 +136,17 @@ struct MODHeaderXE5 : MODHeaderCommon { uint32 vertexBuffer; uint32 indices; }; + +struct MODHeaderX21 : MODHeaderCommon { + uint32 vertexBufferSize; + uint32 numGroups; + uint32 numSkins; + uint32 bones; + uint32 groups; + uint32 materials; + uint32 meshes; + uint32 vertexBuffer; + uint32 indices; + uint32 unkSize; + uint32 unkData; +}; diff --git a/src/mtf_mod/material.cpp b/src/mtf_mod/material.cpp index b1ba007..d57e504 100644 --- a/src/mtf_mod/material.cpp +++ b/src/mtf_mod/material.cpp @@ -68,6 +68,8 @@ REFLECT(CLASS(MODMaterialHash), MEMBER(hash)); REFLECT(CLASS(MODMaterialName), MEMBER(name)); +REFLECT(CLASS(MODMaterialX21), MEMBER(name)); + std::string MODMaterialX70::Name() const { char buffer[0x10]{}; std::to_chars(std::begin(buffer), std::end(buffer), hash, 0x10); diff --git a/src/mtf_mod/material.hpp b/src/mtf_mod/material.hpp index 106a517..7424201 100644 --- a/src/mtf_mod/material.hpp +++ b/src/mtf_mod/material.hpp @@ -70,6 +70,7 @@ struct MODMaterialX70 { struct MODMaterialX170 { static constexpr size_t Version() { return 1; } + using SkinType = MODMaterialX70::SkinType; uint32 pshData; MODMaterialX70::VSHData vshData; @@ -177,3 +178,9 @@ struct MODMaterialName { std::string Name() const; void NoSwap(); }; + +struct MODMaterialX21 { + std::string name; + static constexpr size_t Version() { return 1; } + std::string Name() const { return name; } +}; diff --git a/src/mtf_mod/mesh.hpp b/src/mtf_mod/mesh.hpp index d3b9239..022204c 100644 --- a/src/mtf_mod/mesh.hpp +++ b/src/mtf_mod/mesh.hpp @@ -20,7 +20,6 @@ #include "spike/type/flags.hpp" #include "spike/type/vectors_simd.hpp" -struct MODPrimitiveProxyV1; namespace revil { class MODImpl; } @@ -54,8 +53,8 @@ struct MODMeshX99 { MODMeshSkinInfo skinInfo; uint32 firstEnvelope; // assigned at runtime - MODPrimitiveProxyV1 ReflectLE(revil::MODImpl &); - MODPrimitiveProxyV1 ReflectBE(revil::MODImpl &); + MODPrimitiveProxy ReflectLE(revil::MODImpl &); + MODPrimitiveProxy ReflectBE(revil::MODImpl &); }; struct MODMeshX70 { @@ -77,8 +76,8 @@ struct MODMeshX70 { Vector4A16 bboxMin; Vector4A16 bboxMax; - MODPrimitiveProxyV1 ReflectBE(revil::MODImpl &); - MODPrimitiveProxyV1 ReflectLE(revil::MODImpl &) { return {}; } + MODPrimitiveProxy ReflectBE(revil::MODImpl &); + MODPrimitiveProxy ReflectLE(revil::MODImpl &); }; struct MODMeshXC5 { @@ -93,10 +92,9 @@ struct MODMeshXC5 { using Unk00 = BitMemberDecl<3, 5>; using Unk01 = BitMemberDecl<4, 8>; using VertexBufferStride = BitMemberDecl<5, 8>; - using PrimitiveType = BitMemberDecl<6, 6>; - using Unk02 = BitMemberDecl<7, 2>; + using PrimitiveType = BitMemberDecl<6, 8>; using BitField01 = BitFieldType; + VertexBufferStride, PrimitiveType>; enum class PrimitiveType_e : uint8 { Points, @@ -123,14 +121,21 @@ struct MODMeshXC5 { uint32 hash; MODPrimitiveProxy ReflectLE(revil::MODImpl &); - MODPrimitiveProxy ReflectBE(const revil::MODImpl &) const { return {}; } + MODPrimitiveProxy ReflectBE(revil::MODImpl &); }; struct MODMeshXD2 { + using PrimitiveType = BitMemberDecl<6, 6>; + using Unk02 = BitMemberDecl<7, 2>; + using BitField01 = + BitFieldType; + int16 unk; // somehow essential, must be an odd number uint16 numVertices; MODMeshXC5::BitField00 data0; - MODMeshXC5::BitField01 data1; + BitField01 data1; uint32 vertexStart; uint32 vertexStreamOffset; uint32 vertexFormat; diff --git a/src/mtf_mod/serialize.cpp b/src/mtf_mod/serialize.cpp index 07a809f..1292fb2 100644 --- a/src/mtf_mod/serialize.cpp +++ b/src/mtf_mod/serialize.cpp @@ -16,6 +16,8 @@ */ #include "header.hpp" +#include "pugixml.hpp" +#include "revil/xfs.hpp" #include "spike/io/binreader.hpp" #include "spike/io/binwritter.hpp" #include "spike/util/endian.hpp" @@ -26,6 +28,7 @@ using namespace revil; static constexpr uint32 MODID = CompileFourCC("MOD"); static constexpr uint32 DOMID = CompileFourCC("\0DOM"); +static constexpr uint32 RMDID = CompileFourCC("\0DMR"); template void MODInner::Reflect(bool swap) { this->boneData.storage.reserve(bones.size()); @@ -243,7 +246,7 @@ template <> void FByteswapper(MODHeaderXC5 &self, bool) { FByteswapper(self.indices); } -template <> void FByteswapper(MODHeaderXD2 &self, bool) { +template <> void FByteswapper(MODHeaderXDx32 &self, bool) { FByteswapper(static_cast(self)); FByteswapper(self.vertexBufferSize); FByteswapper(self.numTextures); @@ -297,6 +300,21 @@ template <> void FByteswapper(MODHeaderX170 &self, bool) { FByteswapper(self.indices); } +template <> void FByteswapper(MODHeaderX21 &self, bool) { + FByteswapper(static_cast(self)); + FByteswapper(self.vertexBufferSize); + FByteswapper(self.numGroups); + FByteswapper(self.numSkins); + FByteswapper(self.bones); + FByteswapper(self.groups); + FByteswapper(self.materials); + FByteswapper(self.meshes); + FByteswapper(self.vertexBuffer); + FByteswapper(self.indices); + FByteswapper(self.unkSize); + FByteswapper(self.unkData); +} + template <> void FByteswapper(MODMaterialX70 &self, bool way) { FByteswapper(self.pshData); FByteswapper(self.vshData, way); @@ -648,6 +666,14 @@ MODImpl::ptr LoadMODX70(BinReaderRef_e rd) { rd.ReadBuffer(&main.buffer[header.vertexBufferSize + header.unkBufferSize], main.indexBufferSize); + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast( + main.buffer.data() + header.vertexBufferSize + header.unkBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + return std::make_unique(std::move(main)); } @@ -748,6 +774,14 @@ MODImpl::ptr LoadMODXC3(BinReaderRef_e rd) { rd.Seek(header.indices); rd.ReadBuffer(&main.buffer[header.vertexBufferSize], main.indexBufferSize); + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast(main.buffer.data() + + header.vertexBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + return std::make_unique(std::move(main)); } @@ -806,18 +840,26 @@ template MODImpl::ptr LoadMODX99(BinReaderRef_e rd) { rd.ReadBuffer(&main.buffer[header.vertexBufferSize + header.unkBufferSize], main.indexBufferSize); + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast( + main.buffer.data() + header.vertexBufferSize + header.unkBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + return std::make_unique(std::move(main)); } template MODImpl::ptr LoadMODXD2x32(BinReaderRef_e rd) { - MODHeaderXD2 header; + MODHeaderXDx32 header; MODInner main; rd.Read(header); rd.ApplyPadding(); rd.Read(main.bounds); rd.Read(main.metadata); - if (header.bones <= 0x80) { + if (header.bones > 0 && header.bones <= 0x80) { // UMVC3 PS3 uses unique model throw std::runtime_error("Unsupported model format"); } @@ -861,13 +903,69 @@ template MODImpl::ptr LoadMODXD2x32(BinReaderRef_e rd) { rd.Seek(header.indices); rd.ReadBuffer(&main.buffer[header.vertexBufferSize], main.indexBufferSize); + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast(main.buffer.data() + + header.vertexBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + return std::make_unique(std::move(main)); } -template MODImpl::ptr LoadMODXD3x64(BinReaderRef_e rdn) { - MODHeaderXD3X64 header; +template MODImpl::ptr LoadMODXDxLEx32(BinReaderRef_e rdn) { + BinReaderRef rd(rdn); + MODHeaderXDx32 header; MODInner main; + rd.Read(header); + rd.ApplyPadding(); + rd.Read(main.bounds); + rd.Read(main.metadata); + + if (header.numBones) { + rd.Seek(header.bones); + rd.ReadContainer(main.bones, header.numBones); + rd.ReadContainer(main.refPoses, header.numBones); + rd.ReadContainer(main.transforms, header.numBones); + rd.Read(main.remaps); + } + + if (header.numGroups) { + rd.Seek(header.groups); + rd.ReadContainer(main.groups, header.numGroups); + } + + rdn.ReadContainer(main.materials.storage, header.numMaterials); + + rd.Seek(header.meshes); + rd.ReadContainer(main.meshes, header.numMeshes); + + if constexpr (std::is_same_v) { + rd.ReadContainer(main.envelopes, main.metadata.numEnvelopes); + } else { + rd.ReadContainer(main.envelopes); + } + + main.vertexBufferSize = header.vertexBufferSize; + main.indexBufferSize = header.numIndices * sizeof(uint16); + + main.buffer.resize(main.vertexBufferSize + main.indexBufferSize); + + rd.Seek(header.vertexBuffer); + rd.ReadBuffer(&main.buffer[0], header.vertexBufferSize); + + rd.Seek(header.indices); + rd.ReadBuffer(&main.buffer[header.vertexBufferSize], main.indexBufferSize); + + return std::make_unique(std::move(main)); +} + +template +MODImpl::ptr LoadMODXDxLE(BinReaderRef_e rdn) { BinReaderRef rd(rdn); + MODHeaderXDx64 header; + MODInner main; rd.Push(); rd.Read(header); rd.ApplyPadding(); @@ -881,7 +979,7 @@ template MODImpl::ptr LoadMODXD3x64(BinReaderRef_e rdn) { if (maxPtr > fileSize) { rd.Pop(); - return LoadMODXD2x32(rdn); + return LoadMODXDxLEx32(rd); } } @@ -967,6 +1065,14 @@ MODImpl::ptr LoadMODX06(BinReaderRef_e rdn) { rd.Seek(header.indices); rd.ReadBuffer(&main.buffer[header.vertexBufferSize], main.indexBufferSize); + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast(main.buffer.data() + + header.vertexBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + return std::make_unique(std::move(main)); } @@ -1010,6 +1116,141 @@ MODImpl::ptr LoadMODXE5(BinReaderRef_e rd) { rd.Seek(header.indices); rd.ReadBuffer(&main.buffer[header.vertexBufferSize], main.indexBufferSize); + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast(main.buffer.data() + + header.vertexBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + + return std::make_unique(std::move(main)); +} + +MODImpl::ptr LoadMODXFF2C(BinReaderRef_e rd) { + MODHeaderXE5 header; + MODInner main; + rd.Push(); + rd.Read(header); + rd.ApplyPadding(); + rd.Read(main.bounds); + rd.Read(main.metadata); + + if (header.numBones) { + rd.Seek(header.bones); + rd.ReadContainer(main.bones, header.numBones); + rd.ReadContainer(main.refPoses, header.numBones); + rd.ReadContainer(main.transforms, header.numBones); + rd.Read(main.remaps); + } + + if (header.numGroups) { + rd.Seek(header.groups); + rd.ReadContainer(main.groups, header.numGroups); + } + + rd.ReadContainer(main.materials.storage, header.numMaterials); + + rd.Seek(header.meshes); + rd.ReadContainerLambda(main.meshes, header.numMeshes, + [](BinReaderRef_e rd, auto &m) { + rd.Read(m); + rd.Skip(8); + }); + rd.ReadContainer(main.envelopes); + + main.vertexBufferSize = header.vertexBufferSize; + main.indexBufferSize = header.numIndices * sizeof(uint16); + + main.buffer.resize(main.vertexBufferSize + main.indexBufferSize); + + rd.Seek(header.vertexBuffer); + rd.ReadBuffer(&main.buffer[0], header.vertexBufferSize); + + rd.Seek(header.indices); + rd.ReadBuffer(&main.buffer[header.vertexBufferSize], main.indexBufferSize); + + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast(main.buffer.data() + + header.vertexBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + + return std::make_unique(std::move(main)); +} + +std::vector> +XFSToMaterials(const revil::XFS &main) { + pugi::xml_document root; + main.ToXML(root); + std::vector> retval; + auto mtArr = root.child("class").child("array"); + retval.resize(mtArr.attribute("count").as_int()); + + for (uint32 curMat = 0; auto &c : mtArr.children()) { + auto &mat = retval.at(curMat++).main; + mat.name = "Material_"; + mat.name.append(c.find_child_by_attribute("name", "mTagID") + .attribute("value") + .as_string()); + } + + return retval; +} + +MODImpl::ptr LoadMODX21(BinReaderRef_e rd) { + MODHeaderX21 header; + MODInner main; + rd.Push(); + rd.Read(header); + rd.ApplyPadding(); + rd.Read(main.bounds); + rd.Read(main.metadata); + + if (header.numBones) { + rd.Seek(header.bones); + rd.ReadContainer(main.bones, header.numBones); + rd.ReadContainer(main.refPoses, header.numBones); + rd.ReadContainer(main.transforms, header.numBones); + rd.Read(main.remaps); + // skins?? + } + + if (header.numGroups) { + rd.Seek(header.groups); + rd.ReadContainer(main.groups, header.numGroups); + } + + rd.Seek(header.materials); + revil::XFS materials; + materials.Load(rd, true); + main.materials.storage = XFSToMaterials(materials); + + rd.Seek(header.meshes); + rd.ReadContainer(main.meshes, header.numMeshes); + rd.ReadContainer(main.envelopes); + + main.vertexBufferSize = header.vertexBufferSize; + main.indexBufferSize = header.numIndices * sizeof(uint16); + + main.buffer.resize(main.vertexBufferSize + main.indexBufferSize); + + rd.Seek(header.vertexBuffer); + rd.ReadBuffer(&main.buffer[0], header.vertexBufferSize); + + rd.Seek(header.indices); + rd.ReadBuffer(&main.buffer[header.vertexBufferSize], main.indexBufferSize); + + if (rd.SwappedEndian()) { + uint16 *curIndex = reinterpret_cast(main.buffer.data() + + header.vertexBufferSize); + for (uint32 i = 0; i < header.numIndices; i++) { + FByteswapper(curIndex[i]); + } + } + return std::make_unique(std::move(main)); } @@ -1022,22 +1263,31 @@ bool MODMaker::operator<(const MODMaker &i0) const { static const std::map modLoaders{ {{MODVersion::X70, true}, LoadMODX70}, - //{{0x170, false}, LoadMODX70}, - {{MODVersion::X99, false}, LoadMODX99}, + {{MODVersion::X170}, LoadMODX70}, + {{MODVersion::X99}, LoadMODX99}, + {{MODVersion::X19C}, LoadMODX99}, {{MODVersion::X99, true}, LoadMODX99}, {{MODVersion::XC3, true}, LoadMODXC3}, - {{MODVersion::XC5, false}, LoadMODXC5}, + {{MODVersion::XC5}, LoadMODXC5}, + {{MODVersion::XD2}, LoadMODXDxLEx32}, + {{MODVersion::XD3}, LoadMODXDxLE}, + {{MODVersion::XD6}, + LoadMODXDxLE}, // unused fallback + {{MODVersion::XD4}, + LoadMODXDxLEx32}, // todo normals (different traits) + {{MODVersion::XD2, true}, LoadMODXD2x32}, {{MODVersion::XD3, true}, LoadMODXD2x32}, - {{MODVersion::XD3, false, false, Platform::PS4}, - LoadMODXD3x64}, - {{MODVersion::XD3, false}, LoadMODXD3x64}, - {{MODVersion::X05, false}, LoadMODX06}, - {{MODVersion::X06, false}, LoadMODX06}, + {{MODVersion::XD4, true}, LoadMODXD2x32}, + {{MODVersion::X05}, LoadMODX06}, + {{MODVersion::X06}, LoadMODX06}, {{MODVersion::XE5, true}, LoadMODXE5}, - {{MODVersion::XE5, false}, LoadMODXE5}, + {{MODVersion::XE5}, LoadMODXE5}, {{MODVersion::XE6, true}, LoadMODXE5}, - {{MODVersion::XE6, false}, LoadMODXE5}, + {{MODVersion::XE6}, LoadMODXE5}, + {{MODVersion::XE7}, LoadMODXE5}, + {{MODVersion::XFF2C, true}, LoadMODXFF2C}, + {{MODVersion::X21, true}, LoadMODX21}, }; template MODImpl::ptr makeMod() { @@ -1069,7 +1319,7 @@ void MOD::Load(BinReaderRef_e rd) { rd.Read(header); rd.Pop(); - if (header.id == DOMID) { + if (header.id == DOMID || header.id == RMDID) { rd.SwapEndian(true); FByteswapper(header); } else if (header.id != MODID) { diff --git a/src/mtf_mod/traits.hpp b/src/mtf_mod/traits.hpp index f06b570..10a3780 100644 --- a/src/mtf_mod/traits.hpp +++ b/src/mtf_mod/traits.hpp @@ -25,7 +25,6 @@ struct MODTraitsX70 { static constexpr size_t numSkinRemaps = 1; static constexpr size_t numRemaps = 1; static constexpr size_t pathSize = 64; - using primitive = MODPrimitiveProxyV1; using bone = MODBoneV1_5; using material = MODMaterialX70; using mesh = MODMeshX70; @@ -40,7 +39,6 @@ struct MODTraitsX99LE { static constexpr size_t numSkinRemaps = 32; static constexpr size_t numRemaps = 0x100; static constexpr size_t pathSize = 64; - using primitive = MODPrimitiveProxyV1; using bone = MODBoneV1_5; using material = MODMaterialX70; using mesh = MODMeshX99; @@ -55,29 +53,26 @@ struct MODTraitsXC5 { static constexpr size_t numSkinRemaps = 1; static constexpr size_t numRemaps = 0x100; static constexpr size_t pathSize = 64; - using primitive = MODPrimitiveProxy; using bone = MODBoneV1_5; using material = MODMaterialXC5; using mesh = MODMeshXC5; using metadata = MODMetaDataV1; }; -struct MODTraitsXD3 { +struct MODTraitsXD3LE { static constexpr size_t numSkinRemaps = 1; static constexpr size_t numRemaps = 0x100; static constexpr size_t pathSize = 1; - using primitive = MODPrimitiveProxy; using bone = MODBoneV1_5; using material = MODMaterialHash; using mesh = MODMeshXD2; - using metadata = MODMetaDataV2; + using metadata = MODMetaDataV1; }; struct MODTraitsXD2 { static constexpr size_t numSkinRemaps = 1; static constexpr size_t numRemaps = 0x100; static constexpr size_t pathSize = 1; - using primitive = MODPrimitiveProxy; using bone = MODBoneV1_5; using material = MODMaterialName; using mesh = MODMeshXD2; @@ -92,11 +87,20 @@ struct MODTraitsXD3x64 : MODTraitsXD2 { using mesh = MODMeshXD3; }; +struct MODTraitsXD6 { + static constexpr size_t numSkinRemaps = 1; + static constexpr size_t numRemaps = 0x200; + static constexpr size_t pathSize = 1; + using bone = MODBoneV2; + using material = MODMaterialName; + using mesh = MODMeshXD3PS4; + using metadata = MODMetaDataV2; +}; + struct MODTraitsX06 { static constexpr size_t numSkinRemaps = 32; static constexpr size_t numRemaps = 0x100; static constexpr size_t pathSize = 1; - using primitive = MODPrimitiveProxy; using bone = MODBoneV1_5; using material = MODMaterialName; using mesh = MODMeshX06; @@ -107,9 +111,18 @@ struct MODTraitsXE5 { static constexpr size_t numSkinRemaps = 24; static constexpr size_t numRemaps = 0x100; static constexpr size_t pathSize = 1; - using primitive = MODPrimitiveProxy; using bone = MODBoneV1_5; using material = MODMaterialName; using mesh = MODMeshXE5; using metadata = MODMetaDataV1; }; + +struct MODTraitsX21 { + static constexpr size_t numSkinRemaps = 1; + static constexpr size_t numRemaps = 0x100; + static constexpr size_t pathSize = 1; + using bone = MODBoneV1_5; + using material = MODMaterialX21; + using mesh = MODMeshXC5; + using metadata = MODMetaDataV1; +}; diff --git a/toolset/mod_to_gltf/mod_to_gltf.cpp b/toolset/mod_to_gltf/mod_to_gltf.cpp index 5f6d27c..d242950 100644 --- a/toolset/mod_to_gltf/mod_to_gltf.cpp +++ b/toolset/mod_to_gltf/mod_to_gltf.cpp @@ -407,10 +407,15 @@ std::string LODName(revil::LODIndex &lod) { } void MODGLTF::ProcessModel(const uni::Model &model) { + size_t curMaterial = 0; for (auto materials = model.Materials(); auto m : *materials) { gltf::Material gMat; gMat.name = m->Name(); + if (gMat.name.empty()) { + gMat.name = "Material_" + std::to_string(curMaterial); + } this->materials.emplace_back(std::move(gMat)); + curMaterial++; } std::map lodNodes;