mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-19 15:52:53 +00:00
Merge pull request #395 from Laupetin/fix/bad-xmodel-loading
fix: bad xmodel loading
This commit is contained in:
commit
d3bb99e92c
@ -286,7 +286,7 @@ namespace
|
|||||||
|
|
||||||
common.m_vertices.emplace_back(vertex);
|
common.m_vertices.emplace_back(vertex);
|
||||||
|
|
||||||
XModelVertexBoneWeights vertexWeights{common.m_bone_weight_data.weights.size(), 0u};
|
XModelVertexBoneWeights vertexWeights{.weightOffset = common.m_bone_weight_data.weights.size(), .weightCount = 0u};
|
||||||
for (auto i = 0u; i < std::extent_v<decltype(joints)>; i++)
|
for (auto i = 0u; i < std::extent_v<decltype(joints)>; i++)
|
||||||
{
|
{
|
||||||
if (std::abs(weights[i]) < std::numeric_limits<float>::epsilon())
|
if (std::abs(weights[i]) < std::numeric_limits<float>::epsilon())
|
||||||
@ -315,12 +315,12 @@ namespace
|
|||||||
throw GltfLoadException("Requires primitives attribute POSITION");
|
throw GltfLoadException("Requires primitives attribute POSITION");
|
||||||
|
|
||||||
AccessorsForVertex accessorsForVertex{
|
AccessorsForVertex accessorsForVertex{
|
||||||
*primitives.attributes.POSITION,
|
.positionAccessor = *primitives.attributes.POSITION,
|
||||||
primitives.attributes.NORMAL,
|
.normalAccessor = primitives.attributes.NORMAL,
|
||||||
primitives.attributes.COLOR_0,
|
.colorAccessor = primitives.attributes.COLOR_0,
|
||||||
primitives.attributes.TEXCOORD_0,
|
.uvAccessor = primitives.attributes.TEXCOORD_0,
|
||||||
primitives.attributes.JOINTS_0,
|
.jointsAccessor = primitives.attributes.JOINTS_0,
|
||||||
primitives.attributes.WEIGHTS_0,
|
.weightsAccessor = primitives.attributes.WEIGHTS_0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto existingVertices = m_vertex_offset_for_accessors.find(accessorsForVertex);
|
const auto existingVertices = m_vertex_offset_for_accessors.find(accessorsForVertex);
|
||||||
@ -328,7 +328,7 @@ namespace
|
|||||||
existingVertices == m_vertex_offset_for_accessors.end() ? CreateVertices(common, accessorsForVertex) : existingVertices->second;
|
existingVertices == m_vertex_offset_for_accessors.end() ? CreateVertices(common, accessorsForVertex) : existingVertices->second;
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
auto* indexAccessor = GetAccessorForIndex(
|
const auto* indexAccessor = GetAccessorForIndex(
|
||||||
"INDICES",
|
"INDICES",
|
||||||
primitives.indices,
|
primitives.indices,
|
||||||
{JsonAccessorType::SCALAR},
|
{JsonAccessorType::SCALAR},
|
||||||
@ -552,7 +552,7 @@ namespace
|
|||||||
common.m_bones.resize(skinBoneOffset + skin.joints.size());
|
common.m_bones.resize(skinBoneOffset + skin.joints.size());
|
||||||
|
|
||||||
constexpr float defaultTranslation[3]{0.0f, 0.0f, 0.0f};
|
constexpr float defaultTranslation[3]{0.0f, 0.0f, 0.0f};
|
||||||
constexpr XModelQuaternion defaultRotation{0.0f, 0.0f, 0.0f, 1.0f};
|
constexpr XModelQuaternion defaultRotation{.x = 0.0f, .y = 0.0f, .z = 0.0f, .w = 1.0f};
|
||||||
constexpr float defaultScale[3]{1.0f, 1.0f, 1.0f};
|
constexpr float defaultScale[3]{1.0f, 1.0f, 1.0f};
|
||||||
|
|
||||||
return ConvertJoint(jRoot, skin, common, skinBoneOffset, rootNode, std::nullopt, defaultTranslation, defaultRotation, defaultScale);
|
return ConvertJoint(jRoot, skin, common, skinBoneOffset, rootNode, std::nullopt, defaultTranslation, defaultRotation, defaultScale);
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include JSON_HEADER
|
#include JSON_HEADER
|
||||||
|
|
||||||
#include "Asset/AssetRegistration.h"
|
#include "Asset/AssetRegistration.h"
|
||||||
#include "ObjLoading.h"
|
|
||||||
#include "Utils/QuatInt16.h"
|
#include "Utils/QuatInt16.h"
|
||||||
#include "Utils/StringUtils.h"
|
#include "Utils/StringUtils.h"
|
||||||
#include "XModel/Gltf/GltfBinInput.h"
|
#include "XModel/Gltf/GltfBinInput.h"
|
||||||
@ -44,7 +43,6 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <set>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace GAME;
|
using namespace GAME;
|
||||||
@ -146,17 +144,17 @@ namespace
|
|||||||
assert(common.m_vertex_bone_weights.size() == common.m_vertices.size());
|
assert(common.m_vertex_bone_weights.size() == common.m_vertices.size());
|
||||||
|
|
||||||
XModelBone rootBone{
|
XModelBone rootBone{
|
||||||
"root",
|
.name = "root",
|
||||||
std::nullopt,
|
.parentIndex = std::nullopt,
|
||||||
{1.0f, 1.0f, 1.0f},
|
.scale = {1.0f, 1.0f, 1.0f},
|
||||||
{0.0f, 0.0f, 0.0f},
|
.globalOffset = {0.0f, 0.0f, 0.0f},
|
||||||
{0.0f, 0.0f, 0.0f},
|
.localOffset = {0.0f, 0.0f, 0.0f},
|
||||||
{0.0f, 0.0f, 0.0f, 1.0f},
|
.globalRotation = {.x = 0.0f, .y = 0.0f, .z = 0.0f, .w = 1.0f},
|
||||||
{0.0f, 0.0f, 0.0f, 1.0f},
|
.localRotation = {.x = 0.0f, .y = 0.0f, .z = 0.0f, .w = 1.0f},
|
||||||
};
|
};
|
||||||
common.m_bones.emplace_back(rootBone);
|
common.m_bones.emplace_back(rootBone);
|
||||||
|
|
||||||
XModelBoneWeight rootWeight{0, 1.0f};
|
XModelBoneWeight rootWeight{.boneIndex = 0, .weight = 1.0f};
|
||||||
common.m_bone_weight_data.weights.emplace_back(rootWeight);
|
common.m_bone_weight_data.weights.emplace_back(rootWeight);
|
||||||
|
|
||||||
for (auto& vertexBoneWeights : common.m_vertex_bone_weights)
|
for (auto& vertexBoneWeights : common.m_vertex_bone_weights)
|
||||||
@ -401,7 +399,7 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::optional<size_t>>
|
static std::vector<std::optional<size_t>>
|
||||||
GetRigidBoneIndicesForTris(const std::vector<size_t>& vertexIndices, XSurface& surface, const XModelCommon& common)
|
GetRigidBoneIndicesForTris(const std::vector<size_t>& vertexIndices, const XSurface& surface, const XModelCommon& common)
|
||||||
{
|
{
|
||||||
std::vector<std::optional<size_t>> rigidBoneIndexForTri;
|
std::vector<std::optional<size_t>> rigidBoneIndexForTri;
|
||||||
rigidBoneIndexForTri.reserve(surface.triCount);
|
rigidBoneIndexForTri.reserve(surface.triCount);
|
||||||
@ -422,7 +420,7 @@ namespace
|
|||||||
return rigidBoneIndexForTri;
|
return rigidBoneIndexForTri;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReorderRigidTrisByBoneIndex(const std::vector<size_t>& vertexIndices, XSurface& surface, const XModelCommon& common)
|
static void ReorderRigidTrisByBoneIndex(const std::vector<size_t>& vertexIndices, const XSurface& surface, const XModelCommon& common)
|
||||||
{
|
{
|
||||||
const auto rigidBoneIndexForTri = GetRigidBoneIndicesForTris(vertexIndices, surface, common);
|
const auto rigidBoneIndexForTri = GetRigidBoneIndicesForTris(vertexIndices, surface, common);
|
||||||
|
|
||||||
@ -456,17 +454,17 @@ namespace
|
|||||||
surface.partBits[partBitsIndex] |= 1 << shiftValue;
|
surface.partBits[partBitsIndex] |= 1 << shiftValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateVertListData(XSurface& surface, const std::vector<size_t>& vertexIndices, const XModelCommon& common) const
|
void CreateVertListData(XSurface& surface, const std::vector<size_t>& xmodelToCommonVertexIndexLookup, const XModelCommon& common) const
|
||||||
{
|
{
|
||||||
ReorderRigidTrisByBoneIndex(vertexIndices, surface, common);
|
ReorderRigidTrisByBoneIndex(xmodelToCommonVertexIndexLookup, surface, common);
|
||||||
const auto rigidBoneIndexForTri = GetRigidBoneIndicesForTris(vertexIndices, surface, common);
|
const auto rigidBoneIndexForTri = GetRigidBoneIndicesForTris(xmodelToCommonVertexIndexLookup, surface, common);
|
||||||
|
|
||||||
std::vector<XRigidVertList> vertLists;
|
std::vector<XRigidVertList> vertLists;
|
||||||
|
|
||||||
auto currentVertexTail = 0u;
|
auto currentVertexTail = 0u;
|
||||||
auto currentTriTail = 0u;
|
auto currentTriTail = 0u;
|
||||||
|
|
||||||
const auto vertexCount = vertexIndices.size();
|
const auto vertexCount = xmodelToCommonVertexIndexLookup.size();
|
||||||
const auto triCount = static_cast<size_t>(surface.triCount);
|
const auto triCount = static_cast<size_t>(surface.triCount);
|
||||||
const auto boneCount = common.m_bones.size();
|
const auto boneCount = common.m_bones.size();
|
||||||
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
for (auto boneIndex = 0u; boneIndex < boneCount; boneIndex++)
|
||||||
@ -475,7 +473,7 @@ namespace
|
|||||||
boneVertList.boneOffset = static_cast<uint16_t>(boneIndex * sizeof(DObjSkelMat));
|
boneVertList.boneOffset = static_cast<uint16_t>(boneIndex * sizeof(DObjSkelMat));
|
||||||
|
|
||||||
auto currentVertexHead = currentVertexTail;
|
auto currentVertexHead = currentVertexTail;
|
||||||
while (currentVertexHead < vertexCount && GetRigidBoneForVertex(currentVertexHead, common) == boneIndex)
|
while (currentVertexHead < vertexCount && GetRigidBoneForVertex(xmodelToCommonVertexIndexLookup[currentVertexHead], common) == boneIndex)
|
||||||
currentVertexHead++;
|
currentVertexHead++;
|
||||||
|
|
||||||
auto currentTriHead = currentTriTail;
|
auto currentTriHead = currentTriTail;
|
||||||
@ -512,7 +510,7 @@ namespace
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReorderVerticesByWeightCount(std::vector<size_t>& vertexIndices, XSurface& surface, const XModelCommon& common)
|
static void ReorderVerticesByWeightCount(std::vector<size_t>& vertexIndices, const XSurface& surface, const XModelCommon& common)
|
||||||
{
|
{
|
||||||
if (common.m_bone_weight_data.weights.empty())
|
if (common.m_bone_weight_data.weights.empty())
|
||||||
return;
|
return;
|
||||||
@ -541,13 +539,21 @@ namespace
|
|||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
std::vector<XSurfaceTri> preSortTris(surface.triCount);
|
||||||
|
std::memcpy(preSortTris.data(), surface.triIndices, sizeof(XSurfaceTri) * surface.triCount);
|
||||||
|
|
||||||
|
std::vector<size_t> reverseLookup(reorderLookup.size());
|
||||||
|
for (auto i = 0u; i < reverseLookup.size(); i++)
|
||||||
|
reverseLookup[reorderLookup[i]] = i;
|
||||||
|
|
||||||
for (auto triIndex = 0u; triIndex < surface.triCount; triIndex++)
|
for (auto triIndex = 0u; triIndex < surface.triCount; triIndex++)
|
||||||
{
|
{
|
||||||
|
const auto& preSortTriIndices = preSortTris[triIndex];
|
||||||
auto& triIndices = surface.triIndices[triIndex];
|
auto& triIndices = surface.triIndices[triIndex];
|
||||||
|
|
||||||
triIndices.i[0] = static_cast<uint16_t>(reorderLookup[triIndices.i[0]]);
|
triIndices.i[0] = static_cast<uint16_t>(reverseLookup[preSortTriIndices.i[0]]);
|
||||||
triIndices.i[1] = static_cast<uint16_t>(reorderLookup[triIndices.i[1]]);
|
triIndices.i[1] = static_cast<uint16_t>(reverseLookup[preSortTriIndices.i[1]]);
|
||||||
triIndices.i[2] = static_cast<uint16_t>(reorderLookup[triIndices.i[2]]);
|
triIndices.i[2] = static_cast<uint16_t>(reverseLookup[preSortTriIndices.i[2]]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& entry : reorderLookup)
|
for (auto& entry : reorderLookup)
|
||||||
@ -572,6 +578,7 @@ namespace
|
|||||||
surface.triCount = static_cast<uint16_t>(commonObject.m_faces.size());
|
surface.triCount = static_cast<uint16_t>(commonObject.m_faces.size());
|
||||||
surface.triIndices = m_memory.Alloc<XSurfaceTri>(surface.triCount);
|
surface.triIndices = m_memory.Alloc<XSurfaceTri>(surface.triCount);
|
||||||
|
|
||||||
|
xmodelToCommonVertexIndexLookup.reserve(static_cast<size_t>(surface.triCount) * std::extent_v<decltype(XModelFace::vertexIndex)>);
|
||||||
for (auto faceIndex = 0u; faceIndex < surface.triCount; faceIndex++)
|
for (auto faceIndex = 0u; faceIndex < surface.triCount; faceIndex++)
|
||||||
{
|
{
|
||||||
const auto& face = commonObject.m_faces[faceIndex];
|
const auto& face = commonObject.m_faces[faceIndex];
|
||||||
@ -594,8 +601,6 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReorderVerticesByWeightCount(xmodelToCommonVertexIndexLookup, surface, common);
|
|
||||||
|
|
||||||
constexpr auto maxVertices = std::numeric_limits<decltype(XSurface::vertCount)>::max();
|
constexpr auto maxVertices = std::numeric_limits<decltype(XSurface::vertCount)>::max();
|
||||||
if (vertexOffset + xmodelToCommonVertexIndexLookup.size() > maxVertices)
|
if (vertexOffset + xmodelToCommonVertexIndexLookup.size() > maxVertices)
|
||||||
{
|
{
|
||||||
@ -603,6 +608,8 @@ namespace
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReorderVerticesByWeightCount(xmodelToCommonVertexIndexLookup, surface, common);
|
||||||
|
|
||||||
surface.baseVertIndex = static_cast<uint16_t>(vertexOffset);
|
surface.baseVertIndex = static_cast<uint16_t>(vertexOffset);
|
||||||
surface.vertCount = static_cast<uint16_t>(xmodelToCommonVertexIndexLookup.size());
|
surface.vertCount = static_cast<uint16_t>(xmodelToCommonVertexIndexLookup.size());
|
||||||
surface.verts0 = m_memory.Alloc<GfxPackedVertex>(surface.vertCount);
|
surface.verts0 = m_memory.Alloc<GfxPackedVertex>(surface.vertCount);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user