Add PackNormal/UnpackNormal and GetInt/SetInt to MeshAccessor

This commit is contained in:
Wojtek Figat
2025-01-12 21:22:35 +01:00
parent 344d342610
commit d751c6a6c6
5 changed files with 90 additions and 15 deletions

View File

@@ -304,7 +304,8 @@ namespace FlaxEditor.Viewport.Previews
for (int i = 0; i < count; i++)
{
var position = positionStream.GetFloat3(i);
var normal = normalStream.GetFloat3(i) * 2.0f - 1.0f;
var normal = normalStream.GetFloat3(i);
MeshAccessor.UnpackNormal(ref normal);
DebugDraw.DrawLine(position, position + normal * 4.0f, Color.Blue);
}
}
@@ -328,7 +329,8 @@ namespace FlaxEditor.Viewport.Previews
for (int i = 0; i < count; i++)
{
var position = positionStream.GetFloat3(i);
var tangent = tangentStream.GetFloat3(i) * 2.0f - 1.0f;
var tangent = tangentStream.GetFloat3(i);
MeshAccessor.UnpackNormal(ref tangent);
DebugDraw.DrawLine(position, position + tangent * 4.0f, Color.Red);
}
}
@@ -353,10 +355,11 @@ namespace FlaxEditor.Viewport.Previews
for (int i = 0; i < count; i++)
{
var position = positionStream.GetFloat3(i);
var normal = normalStream.GetFloat3(i) * 2.0f - 1.0f;
var normal = normalStream.GetFloat3(i);
var tangent = tangentStream.GetFloat4(i);
var bitangentSign = tangent.W > Mathf.Epsilon ? -1.0f : +1.0f;
var bitangent = Float3.Cross(normal, new Float3(tangent) * 2.0f - 1.0f) * bitangentSign;
MeshAccessor.UnpackNormal(ref normal);
MeshAccessor.UnpackNormal(ref tangent, out var bitangentSign);
var bitangent = Float3.Cross(normal, new Float3(tangent)) * bitangentSign;
DebugDraw.DrawLine(position, position + bitangent * 4.0f, Color.Green);
}
}

View File

@@ -81,7 +81,8 @@ ExportAssetResult AssetExporters::ExportModel(ExportAssetContext& context)
{
for (uint32 i = 0; i < meshData.Vertices; i++)
{
auto v = normalStream.GetFloat3(i) * 2.0f - 1.0f;
auto v = normalStream.GetFloat3(i);
MeshAccessor::UnpackNormal(v);
output->WriteText(StringAnsi::Format("vn {0} {1} {2}\n", v.X, v.Y, v.Z));
}
output->WriteChar('\n');

View File

@@ -69,6 +69,17 @@ namespace FlaxEngine
return _format == expectedFormat && _stride == PixelFormatExtensions.SizeInBytes(_format);
}
/// <summary>
/// Reads an integer value from a given item.
/// </summary>
/// <param name="index">Zero-based index of the item.</param>
/// <returns>Loaded value.</returns>
public int GetInt(int index)
{
fixed (byte* data = _data)
return (int)_sampler.Read(data + index * _stride).X;
}
/// <summary>
/// Reads a float value from a given item.
/// </summary>
@@ -113,6 +124,18 @@ namespace FlaxEngine
return _sampler.Read(data + index * _stride);
}
/// <summary>
/// Writes an integer value to a given item.
/// </summary>
/// <param name="index">Zero-based index of the item.</param>
/// <param name="value">Value to assign.</param>
public void SetInt(int index, int value)
{
var v = new Float4(value);
fixed (byte* data = _data)
_sampler.Write(data + index * _stride, ref v);
}
/// <summary>
/// Writes a float value to a given item.
/// </summary>
@@ -713,13 +736,34 @@ namespace FlaxEngine
}
}
private static void UnpackNormal(ref Float3 value)
/// <summary>
/// Unpacks normal/tangent vector from normalized range to full range.
/// </summary>
/// <param name="value">In and out value.</param>
public static void UnpackNormal(ref Float3 value)
{
// [0; 1] -> [-1; 1]
value = value * 2.0f - 1.0f;
}
private static void PackNormal(ref Float3 value)
/// <summary>
/// Unpacks normal/tangent vector from normalized range to full range.
/// </summary>
/// <param name="value">In and out value.</param>
/// <param name="sign">Encoded sign in the alpha channel.</param>
public static void UnpackNormal(ref Float4 value, out float sign)
{
sign = value.W > Mathf.Epsilon ? -1.0f : +1.0f;
// [0; 1] -> [-1; 1]
value = value * 2.0f - 1.0f;
}
/// <summary>
/// Packs normal/tangent vector to normalized range from full range.
/// </summary>
/// <param name="value">In and out value.</param>
public static void PackNormal(ref Float3 value)
{
// [-1; 1] -> [0; 1]
value = value * 0.5f + 0.5f;

View File

@@ -37,6 +37,11 @@ public:
bool IsValid() const;
bool IsLinear(PixelFormat expectedFormat) const;
FORCE_INLINE int32 GetInt(int32 index) const
{
return (int32)_sampler.Read(_data.Get() + index * _stride).X;
}
FORCE_INLINE float GetFloat(int32 index) const
{
return _sampler.Read(_data.Get() + index * _stride).X;
@@ -57,7 +62,12 @@ public:
return _sampler.Read(_data.Get() + index * _stride);
}
FORCE_INLINE void SetFloat(int32 index, const float& value)
FORCE_INLINE void SetInt(int32 index, const int32 value)
{
_sampler.Write(_data.Get() + index * _stride, Float4((float)value));
}
FORCE_INLINE void SetFloat(int32 index, const float value)
{
_sampler.Write(_data.Get() + index * _stride, Float4(value));
}
@@ -182,4 +192,17 @@ public:
{
return Attribute((VertexElement::Types)((byte)VertexElement::Types::TexCoord0 + channel));
}
public:
// Unpacks normal/tangent vector from normalized range to full range.
FORCE_INLINE static void UnpackNormal(Float3& normal)
{
normal = normal * 2.0f - 1.0f;
}
// Packs normal/tangent vector to normalized range from full range.
FORCE_INLINE static void PackNormal(Float3& normal)
{
normal = normal * 0.5f + 0.5f;
}
};

View File

@@ -653,9 +653,10 @@ void AnimatedModel::RunBlendShapeDeformer(const MeshBase* mesh, MeshDeformationD
{
const BlendShapeVertex& blendShapeVertex = q.First.Vertices[i];
Float3 normal = normalStream.GetFloat3(blendShapeVertex.VertexIndex) * 2.0f - 1.0f;
Float3 normal = normalStream.GetFloat3(blendShapeVertex.VertexIndex);
MeshAccessor::UnpackNormal(normal);
normal = normal + blendShapeVertex.NormalDelta * q.Second;
normal = normal * 0.5f + 0.5f; // TODO: optimize unpacking and packing to just apply it to the normal delta
MeshAccessor::PackNormal(normal); // TODO: optimize unpacking and packing to just apply it to the normal delta
normalStream.SetFloat3(blendShapeVertex.VertexIndex, normal);
}
}
@@ -667,18 +668,21 @@ void AnimatedModel::RunBlendShapeDeformer(const MeshBase* mesh, MeshDeformationD
auto tangentStream = accessor.Tangent();
for (uint32 vertexIndex = minVertexIndex; vertexIndex <= maxVertexIndex; vertexIndex++)
{
Float3 normal = normalStream.GetFloat3(vertexIndex) * 2.0f - 1.0f;
Float3 normal = normalStream.GetFloat3(vertexIndex);
MeshAccessor::UnpackNormal(normal);
normal.Normalize();
normal = normal * 0.5f + 0.5f;
MeshAccessor::PackNormal(normal);
normalStream.SetFloat3(vertexIndex, normal);
if (tangentStream.IsValid())
{
Float4 tangentRaw = normalStream.GetFloat4(vertexIndex);
Float3 tangent = Float3(tangentRaw) * 2.0f - 1.0f;
Float3 tangent = Float3(tangentRaw);
MeshAccessor::UnpackNormal(tangent);
tangent = tangent - ((tangent | normal) * normal);
tangent.Normalize();
tangentRaw = Float4(tangent * 0.5f + 0.5f, tangentRaw.W);
MeshAccessor::PackNormal(tangent);
tangentRaw = Float4(tangent, tangentRaw.W);
tangentStream.SetFloat4(vertexIndex, tangentRaw);
}
}