Add PositionFormat and TexCoordFormat to model import option for mesh data encoding
This commit is contained in:
@@ -665,6 +665,8 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
|
||||
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 texCoordsFormat = modelData.TexCoordFormat == ModelData::TexCoordFormats::Float16 ? PixelFormat::R16G16_Float : PixelFormat::R8G8_UNorm;
|
||||
PixelFormat blendIndicesFormat = PixelFormat::R8G8B8A8_UInt;
|
||||
PixelFormat blendWeightsFormat = PixelFormat::R8G8B8A8_UNorm;
|
||||
for (const Int4& indices : mesh.BlendIndices)
|
||||
@@ -677,14 +679,13 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
|
||||
}
|
||||
{
|
||||
byte vbIndex = 0;
|
||||
// TODO: add option to quantize vertex positions (eg. 16-bit)
|
||||
// TODO: add option to quantize vertex attributes (eg. 8-bit blend weights, 8-bit texcoords)
|
||||
|
||||
// Position
|
||||
if (useSeparatePositions)
|
||||
{
|
||||
auto& vb0 = vbElements.AddOne();
|
||||
vb0.Add({ VertexElement::Types::Position, vbIndex, 0, 0, PixelFormat::R32G32B32_Float });
|
||||
vb0.Add({ VertexElement::Types::Position, vbIndex, 0, 0, positionsFormat });
|
||||
vbIndex++;
|
||||
}
|
||||
|
||||
@@ -692,13 +693,13 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
|
||||
{
|
||||
auto& vb = vbElements.AddOne();
|
||||
if (!useSeparatePositions)
|
||||
vb.Add({ VertexElement::Types::Position, vbIndex, 0, 0, PixelFormat::R32G32B32_Float });
|
||||
vb.Add({ VertexElement::Types::Position, vbIndex, 0, 0, positionsFormat });
|
||||
for (int32 channelIdx = 0; channelIdx < mesh.UVs.Count(); channelIdx++)
|
||||
{
|
||||
auto& channel = mesh.UVs.Get()[channelIdx];
|
||||
if (channel.HasItems())
|
||||
{
|
||||
vb.Add({ (VertexElement::Types)((int32)VertexElement::Types::TexCoord0 + channelIdx), vbIndex, 0, 0, PixelFormat::R16G16_Float });
|
||||
vb.Add({ (VertexElement::Types)((int32)VertexElement::Types::TexCoord0 + channelIdx), vbIndex, 0, 0, texCoordsFormat });
|
||||
}
|
||||
}
|
||||
vb.Add({ VertexElement::Types::Normal, vbIndex, 0, 0, PixelFormat::R10G10B10A2_UNorm });
|
||||
@@ -733,7 +734,7 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
|
||||
// Write vertex buffers
|
||||
for (int32 vbIndex = 0; vbIndex < vbCount; vbIndex++)
|
||||
{
|
||||
if (useSeparatePositions && vbIndex == 0)
|
||||
if (useSeparatePositions && vbIndex == 0 && positionsFormat == PixelFormat::R32G32B32_Float)
|
||||
{
|
||||
// Fast path for vertex positions of static models using the first buffer
|
||||
stream.WriteBytes(mesh.Positions.Get(), sizeof(Float3) * vertices);
|
||||
@@ -751,7 +752,15 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
|
||||
case VertexElement::Types::Position:
|
||||
{
|
||||
const Float3 position = mesh.Positions.Get()[vertex];
|
||||
stream.Write(position);
|
||||
if (positionsFormat == PixelFormat::R16G16B16A16_Float)
|
||||
{
|
||||
const Half4 positionEnc(Float4(position, 0.0f));
|
||||
stream.Write(positionEnc);
|
||||
}
|
||||
else //if (positionsFormat == PixelFormat::R32G32B32_Float)
|
||||
{
|
||||
stream.Write(position);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VertexElement::Types::Color:
|
||||
@@ -817,8 +826,16 @@ bool ModelBase::SaveLOD(WriteStream& stream, const ModelData& modelData, int32 l
|
||||
{
|
||||
const int32 channelIdx = (int32)element.Type - (int32)VertexElement::Types::TexCoord0;
|
||||
const Float2 uv = mesh.UVs.Get()[channelIdx].Get()[vertex];
|
||||
const Half2 uvEnc(uv);
|
||||
stream.Write(uvEnc);
|
||||
if (texCoordsFormat == PixelFormat::R8G8_UNorm)
|
||||
{
|
||||
stream.Write((uint8)Math::Clamp<int32>((int32)(uv.X * 255), 0, 255));
|
||||
stream.Write((uint8)Math::Clamp<int32>((int32)(uv.Y * 255), 0, 255));
|
||||
}
|
||||
else //if (texCoordsFormat == PixelFormat::R16G16_Float)
|
||||
{
|
||||
const Half2 uvEnc(uv);
|
||||
stream.Write(uvEnc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -428,6 +428,21 @@ public:
|
||||
/// </summary>
|
||||
Array<AnimationData> Animations;
|
||||
|
||||
public:
|
||||
// See ModelTool::PositionFormat
|
||||
enum class PositionFormats
|
||||
{
|
||||
Float32,
|
||||
Float16,
|
||||
} PositionFormat = PositionFormats::Float32;
|
||||
|
||||
// See ModelTool::TexCoordFormats
|
||||
enum class TexCoordFormats
|
||||
{
|
||||
Float16,
|
||||
UNorm8,
|
||||
} TexCoordFormat = TexCoordFormats::Float16;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Automatically calculates the screen size for every model LOD for a proper transitions.
|
||||
|
||||
@@ -676,6 +676,9 @@ void ModelTool::Options::Serialize(SerializeStream& stream, const void* otherObj
|
||||
SERIALIZE(CalculateBoneOffsetMatrices);
|
||||
SERIALIZE(LightmapUVsSource);
|
||||
SERIALIZE(CollisionMeshesPrefix);
|
||||
SERIALIZE(CollisionType);
|
||||
SERIALIZE(PositionFormat);
|
||||
SERIALIZE(TexCoordFormat);
|
||||
SERIALIZE(Scale);
|
||||
SERIALIZE(Rotation);
|
||||
SERIALIZE(Translation);
|
||||
@@ -727,6 +730,9 @@ void ModelTool::Options::Deserialize(DeserializeStream& stream, ISerializeModifi
|
||||
DESERIALIZE(CalculateBoneOffsetMatrices);
|
||||
DESERIALIZE(LightmapUVsSource);
|
||||
DESERIALIZE(CollisionMeshesPrefix);
|
||||
DESERIALIZE(CollisionType);
|
||||
DESERIALIZE(PositionFormat);
|
||||
DESERIALIZE(TexCoordFormat);
|
||||
DESERIALIZE(Scale);
|
||||
DESERIALIZE(Rotation);
|
||||
DESERIALIZE(Translation);
|
||||
@@ -1137,6 +1143,10 @@ bool ModelTool::ImportModel(const String& path, ModelData& data, Options& option
|
||||
if (ImportData(path, data, options, errorMsg))
|
||||
return true;
|
||||
|
||||
// Copy over data format options
|
||||
data.PositionFormat = (ModelData::PositionFormats)options.PositionFormat;
|
||||
data.TexCoordFormat = (ModelData::TexCoordFormats)options.TexCoordFormat;
|
||||
|
||||
// Validate result data
|
||||
if (EnumHasAnyFlags(options.ImportTypes, ImportDataTypes::Geometry))
|
||||
{
|
||||
|
||||
@@ -142,6 +142,28 @@ public:
|
||||
ExtractCenterOfMass = 2,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Declares the imported vertex positions data formats.
|
||||
/// </summary>
|
||||
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,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Declares the imported vertex texture coordinates data formats.
|
||||
/// </summary>
|
||||
API_ENUM(Attributes="HideInEditor") enum class TexCoordFormats
|
||||
{
|
||||
// XY channels with 16-bit precision (4 bytes per vertex).
|
||||
Float16,
|
||||
// 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,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Model import options.
|
||||
/// </summary>
|
||||
@@ -201,6 +223,14 @@ public:
|
||||
API_FIELD(Attributes="EditorOrder(105), EditorDisplay(\"Geometry\"), VisibleIf(nameof(ShowGeometry))")
|
||||
CollisionDataType CollisionType = CollisionDataType::ConvexMesh;
|
||||
|
||||
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;
|
||||
// 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;
|
||||
|
||||
public: // Transform
|
||||
|
||||
// Custom uniform import scale.
|
||||
|
||||
Reference in New Issue
Block a user