Add and use Max Mesh Position Error to Build Settings for automatic mesh vertex positions storage
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -89,6 +89,12 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(2100), EditorDisplay(\"Content\")")
|
||||
bool SkipDefaultFonts = false;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum acceptable mesh vertex position error (in world units) for data quantization. Use 0 to disable this feature. Affects meshes during import (or reimpport).
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(2200), EditorDisplay(\"Content\"), ValueCategory(Utils.ValueCategory.Distance)")
|
||||
float MaxMeshPositionError = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// If checked, .NET Runtime won't be packaged with a game and will be required by user to be installed on system upon running game build. Available only on supported platforms such as Windows, Linux and macOS.
|
||||
/// </summary>
|
||||
|
||||
@@ -434,7 +434,8 @@ public:
|
||||
{
|
||||
Float32,
|
||||
Float16,
|
||||
} PositionFormat = PositionFormats::Float32;
|
||||
Automatic,
|
||||
} PositionFormat = PositionFormats::Automatic;
|
||||
|
||||
// See ModelTool::TexCoordFormats
|
||||
enum class TexCoordFormats
|
||||
|
||||
@@ -148,9 +148,11 @@ public:
|
||||
API_ENUM(Attributes="HideInEditor") enum class PositionFormat
|
||||
{
|
||||
// XYZ channels with 32-bit precision (12 bytes per vertex).
|
||||
Float32,
|
||||
// XYZ(W) channels with 12-bit precision (8 bytes per vertex).
|
||||
Float16,
|
||||
Float32 = 0,
|
||||
// XYZ(W) channels with 16-bit precision (8 bytes per vertex).
|
||||
Float16 = 1,
|
||||
// Selects the most memory-efficient format that can represent positions within a max error defined in project Build Settings.
|
||||
Automatic = 2,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -159,9 +161,9 @@ public:
|
||||
API_ENUM(Attributes="HideInEditor") enum class TexCoordFormats
|
||||
{
|
||||
// XY channels with 16-bit precision (4 bytes per vertex).
|
||||
Float16,
|
||||
Float16 = 0,
|
||||
// XY channels with 8-bit precision (2 bytes per vertex). Valid only for normalized UVs within range [0; 1], scaled or negative UVs won't work.
|
||||
UNorm8,
|
||||
UNorm8 = 1,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -226,7 +228,7 @@ public:
|
||||
public:
|
||||
// The imported vertex positions data format to use by meshes. Changing this affects memory usage of the mesh data, performance and overall quality.
|
||||
API_FIELD(Attributes = "EditorOrder(200), EditorDisplay(\"Data Format\"), VisibleIf(nameof(ShowGeometry))")
|
||||
PositionFormat PositionFormat = PositionFormat::Float32;
|
||||
PositionFormat PositionFormat = PositionFormat::Automatic;
|
||||
// The imported vertex texture coordinates data format to use by meshes. Changing this affects memory usage of the mesh data, performance and overall quality.
|
||||
API_FIELD(Attributes = "EditorOrder(205), EditorDisplay(\"Data Format\"), VisibleIf(nameof(ShowGeometry))")
|
||||
TexCoordFormats TexCoordFormat = TexCoordFormats::Float16;
|
||||
|
||||
Reference in New Issue
Block a user