Merge pull request #259 from Laupetin/feature/check-xmodel-conversion-limits

feat: check for xmodel limits when converting
This commit is contained in:
Jan 2024-09-08 23:22:02 +02:00 committed by GitHub
commit f9a653b7f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -484,7 +484,7 @@ namespace
static void
CreateVertex(GfxPackedVertex& vertex, const XModelVertex& commonVertex, const std::array<float, 3>& tangent, const std::array<float, 3>& binormal)
{
float tangent_[]{tangent[0], tangent[1], tangent[2]};
const float tangentPlainArray[]{tangent[0], tangent[1], tangent[2]};
vertex.xyz.x = commonVertex.coordinates[0];
vertex.xyz.y = commonVertex.coordinates[1];
@ -493,7 +493,7 @@ namespace
vertex.color = Common::Vec4PackGfxColor(commonVertex.color);
vertex.texCoord = Common::Vec2PackTexCoords(commonVertex.uv);
vertex.normal = Common::Vec3PackUnitVec(commonVertex.normal);
vertex.tangent = Common::Vec3PackUnitVec(tangent_);
vertex.tangent = Common::Vec3PackUnitVec(tangentPlainArray);
}
static size_t GetRigidBoneForVertex(const size_t vertexIndex, const XModelCommon& common)
@ -557,7 +557,7 @@ namespace
surface.partBits[partBitsIndex] |= 1 << shiftValue;
}
void CreateVertListData(XSurface& surface, const std::vector<size_t>& vertexIndices, const XModelCommon& common)
void CreateVertListData(XSurface& surface, const std::vector<size_t>& vertexIndices, const XModelCommon& common) const
{
ReorderRigidTrisByBoneIndex(vertexIndices, surface, common);
const auto rigidBoneIndexForTri = GetRigidBoneIndicesForTris(vertexIndices, surface, common);
@ -663,6 +663,13 @@ namespace
std::vector<size_t> xmodelToCommonVertexIndexLookup;
std::unordered_map<size_t, size_t> usedVertices;
constexpr auto maxTriCount = std::numeric_limits<decltype(XSurface::triCount)>::max();
if (commonObject.m_faces.size() > maxTriCount)
{
std::cerr << std::format("Surface cannot have more than {} faces\n", maxTriCount);
return false;
}
surface.triCount = static_cast<uint16_t>(commonObject.m_faces.size());
surface.triIndices = m_memory.Alloc<XSurfaceTri>(surface.triCount);
@ -690,6 +697,13 @@ namespace
ReorderVerticesByWeightCount(xmodelToCommonVertexIndexLookup, surface, common);
constexpr auto maxVertices = std::numeric_limits<decltype(XSurface::vertCount)>::max();
if (vertexOffset + xmodelToCommonVertexIndexLookup.size() > maxVertices)
{
std::cerr << std::format("Lod exceeds limit of {} vertices\n", maxVertices);
return false;
}
surface.baseVertIndex = static_cast<uint16_t>(vertexOffset);
surface.vertCount = static_cast<uint16_t>(xmodelToCommonVertexIndexLookup.size());
surface.verts0 = m_memory.Alloc<GfxPackedVertex>(surface.vertCount);
@ -756,6 +770,14 @@ namespace
auto& lodInfo = xmodel.lodInfo[lodNumber];
lodInfo.dist = jLod.distance;
constexpr auto maxSurfaces = std::numeric_limits<decltype(XModelLodInfo::numsurfs)>::max();
if (common->m_objects.size() > maxSurfaces)
{
PrintError(xmodel, std::format("Lod {} cannot have more than {} surfaces", lodNumber, maxSurfaces));
return false;
}
lodInfo.surfIndex = static_cast<uint16_t>(m_surfaces.size());
lodInfo.numsurfs = static_cast<uint16_t>(common->m_objects.size());
@ -835,13 +857,27 @@ namespace
bool CreateXModelFromJson(const JsonXModel& jXModel, XModel& xmodel)
{
constexpr auto maxLods = std::extent_v<decltype(XModel::lodInfo)>;
if (jXModel.lods.size() > maxLods)
{
PrintError(xmodel, std::format("Model cannot have more than {} lods", maxLods));
return false;
}
auto lodNumber = 0u;
xmodel.numLods = static_cast<uint16_t>(jXModel.lods.size());
for (const auto& jLod : jXModel.lods)
{
if (!LoadLod(jLod, xmodel, lodNumber++))
return false;
}
xmodel.numLods = static_cast<uint16_t>(jXModel.lods.size());
constexpr auto maxSurfaces = std::numeric_limits<decltype(XModel::numsurfs)>::max();
if (m_surfaces.size() > maxSurfaces)
{
PrintError(xmodel, std::format("Model cannot have more than {} surfaces across all lods", maxSurfaces));
return false;
}
xmodel.numsurfs = static_cast<unsigned char>(m_surfaces.size());
xmodel.surfs = m_memory.Alloc<XSurface>(xmodel.numsurfs);