Add and use Max Mesh Position Error to Build Settings for automatic mesh vertex positions storage

This commit is contained in:
Wojtek Figat
2025-09-12 17:53:14 +02:00
parent b537a80031
commit f323fdb592
4 changed files with 49 additions and 9 deletions

View File

@@ -3,6 +3,7 @@
#include "ModelBase.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Transform.h"
#include "Engine/Core/Config/BuildSettings.h"
#include "Engine/Content/WeakAssetReference.h"
#include "Engine/Serialization/MemoryReadStream.h"
#include "Engine/Profiler/ProfilerMemory.h"
@@ -666,11 +667,42 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
return true;
}
// Process mesh data if need to decide vertex buffer on format dynamically
auto positionFormat = modelData.PositionFormat;
if (positionFormat == ModelData::PositionFormats::Automatic)
{
const float maxPositionError = BuildSettings::Get()->MaxMeshPositionError; // In world-units
const float maxPositionErrorSq = maxPositionError * maxPositionError;
if (maxPositionErrorSq > 0.0f)
{
positionFormat = ModelData::PositionFormats::Float16;
const Float3* positions = mesh.Positions.Get();
for (int32 i = 0; i < mesh.Positions.Count(); i++)
{
// Encode to Half3 and decode back to see the position error
Float3 position = positions[i];
Half3 encoded(position);
Float3 decoded = encoded.ToFloat3();
if (Float3::DistanceSquared(position, decoded) > maxPositionErrorSq)
{
// Cannot use lower quality so go back to full precision
positionFormat = ModelData::PositionFormats::Float32;
break;
}
}
}
else
{
// Full precision as default
positionFormat = ModelData::PositionFormats::Float32;
}
}
// Define vertex buffers layout and packing
Array<GPUVertexLayout::Elements, FixedAllocation<MODEL_MAX_VB>> vbElements;
const bool useSeparatePositions = !isSkinned;
const bool useSeparateColors = !isSkinned;
PixelFormat positionsFormat = modelData.PositionFormat == ModelData::PositionFormats::Float32 ? PixelFormat::R32G32B32_Float : PixelFormat::R16G16B16A16_Float;
PixelFormat positionsFormat = positionFormat == ModelData::PositionFormats::Float32 ? PixelFormat::R32G32B32_Float : PixelFormat::R16G16B16A16_Float;
PixelFormat texCoordsFormat = modelData.TexCoordFormat == ModelData::TexCoordFormats::Float16 ? PixelFormat::R16G16_Float : PixelFormat::R8G8_UNorm;
PixelFormat blendIndicesFormat = PixelFormat::R8G8B8A8_UInt;
PixelFormat blendWeightsFormat = PixelFormat::R8G8B8A8_UNorm;
@@ -684,7 +716,6 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
}
{
byte vbIndex = 0;
// TODO: add option to quantize vertex attributes (eg. 8-bit blend weights, 8-bit texcoords)
// Position
if (useSeparatePositions)