Clean up code related to deserialization of linear algebra types.

This commit is contained in:
H. Utku Maden 2025-10-12 18:01:13 +03:00
parent 8256444c76
commit 10d912d302
3 changed files with 70 additions and 134 deletions

View File

@ -1,7 +1,6 @@
using System;
using System.Drawing;
using System.Numerics;
using System.Text.Json;
using ReFuel.Gltf.Serialization;
namespace ReFuel.Gltf
{
@ -86,31 +85,7 @@ namespace ReFuel.Gltf
JsonElement child;
if (element.TryGetProperty("baseColorFactor", out child))
{
if (child.ValueKind != JsonValueKind.Array)
{
throw new Exception("Expected a value array.");
}
Vector4 color = Vector4.One;
int i = 0;
foreach (JsonElement item in child.EnumerateArray())
{
float value = item.GetSingle();
switch (i++)
{
case 0: color.X = value; break;
case 1: color.Y = value; break;
case 2: color.Z = value; break;
case 3: color.W = value; break;
default:
goto break_for;
}
continue;
break_for:
break;
}
BaseColorFactor = color;
BaseColorFactor = child.ToSingleVector(4, Vector4.One);
}
if (element.TryGetProperty("baseColorTexture", out child))
@ -277,6 +252,9 @@ namespace ReFuel.Gltf
break_for:
break;
}
EmissiveFactor = factor;
break;
case "alphaMode":
AlphaModeString = property.Value.GetString() ?? "OPAQUE";

View File

@ -2,6 +2,7 @@
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text.Json;
using ReFuel.Gltf.Serialization;
namespace ReFuel.Gltf
{
@ -177,131 +178,36 @@ namespace ReFuel.Gltf
if (element.TryGetProperty("matrix", out JsonElement matrixElement))
{
if (matrixElement.ValueKind != JsonValueKind.Array)
throw new Exception("Expected matrix to be an array.");
var enumerator = matrixElement.EnumerateArray();
transformMode = TransformMode.Matrix;
transform.Matrix = Matrix4x4.Identity;
for (int x = 0; x < 4; x++)
for (int y = 0; y < 4 && enumerator.MoveNext(); y++)
{
if (!enumerator.Current.TryGetSingle(out float v))
throw new Exception("Expected a floating point number as matrix elements.");
StoreMat(ref transform.Matrix, x, y, v);
}
transform.Matrix = matrixElement.ToSingleMatrix(4, 4, Matrix4x4.Identity);
}
else
{
transformMode = TransformMode.SRT;
transform = new TransformUnion()
{
Scale = Vector3.One,
Rotation = Quaternion.Identity,
Translation = Vector3.Zero
};
if (element.TryGetProperty("scale", out JsonElement scaleElement))
{
if (scaleElement.ValueKind != JsonValueKind.Array)
throw new Exception("Expected scale to be an array.");
transformMode = TransformMode.SRT;
Vector3 scale = default;
var enumerator = scaleElement.EnumerateArray();
for (int i = 0; i < 3 && enumerator.MoveNext(); i++)
{
if (!enumerator.Current.TryGetSingle(out float v))
throw new Exception("Expected a floating point number as scale elements.");
StoreVec(ref scale, i, v);
}
Scale = scale;
transform.Scale = scaleElement.ToSingleVector(3, Vector3.One);
}
if (element.TryGetProperty("rotation", out JsonElement rotationElement))
{
if (scaleElement.ValueKind != JsonValueKind.Array)
throw new Exception("Expected rotation to be an array.");
transformMode = TransformMode.SRT;
Quaternion rotation = Quaternion.Identity;
var enumerator = scaleElement.EnumerateArray();
for (int i = 0; i < 4 && enumerator.MoveNext(); i++)
{
if (!enumerator.Current.TryGetSingle(out float v))
throw new Exception("Expected a floating point number as rotation elements.");
StoreQuat(ref rotation, i, v);
}
Rotation = rotation;
transform.Rotation = scaleElement.ToSingleVector(4, Quaternion.Identity);
}
if (element.TryGetProperty("translation", out JsonElement translationElement))
{
if (scaleElement.ValueKind != JsonValueKind.Array)
throw new Exception("Expected translation to be an array.");
transformMode = TransformMode.SRT;
Vector3 translation = default;
var enumerator = scaleElement.EnumerateArray();
for (int i = 0; i < 3 && enumerator.MoveNext(); i++)
{
if (!enumerator.Current.TryGetSingle(out float v))
throw new Exception("Expected a floating point number as rotation elements.");
StoreVec(ref translation, i, v);
}
Translation = translation;
transform.Translation = translationElement.ToSingleVector(3, Vector3.One);
}
}
DeserializeCommon(element);
static void StoreMat(ref Matrix4x4 m, int r, int c, float x)
{
// I love System.Numerics...
switch (r, c)
{
case (0, 0): m.M11 = x; break;
case (0, 1): m.M12 = x; break;
case (0, 2): m.M13 = x; break;
case (0, 3): m.M14 = x; break;
case (1, 0): m.M21 = x; break;
case (1, 1): m.M22 = x; break;
case (1, 2): m.M23 = x; break;
case (1, 3): m.M24 = x; break;
case (2, 0): m.M31 = x; break;
case (2, 1): m.M32 = x; break;
case (2, 2): m.M33 = x; break;
case (2, 3): m.M34 = x; break;
case (3, 0): m.M41 = x; break;
case (3, 1): m.M42 = x; break;
case (3, 2): m.M43 = x; break;
case (3, 3): m.M44 = x; break;
};
}
static void StoreVec(ref Vector3 v, int r, float x)
{
switch (r)
{
case 0: v.X = x; break;
case 1: v.Y = x; break;
case 2: v.Z = x; break;
}
}
static void StoreQuat(ref Quaternion q, int r, float x)
{
switch (r)
{
case 0: q.X = x; break;
case 1: q.Y = x; break;
case 2: q.Z = x; break;
case 3: q.W = x; break;
}
}
}
internal override void Serialize(Utf8JsonWriter writer)

View File

@ -0,0 +1,52 @@
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text.Json;
namespace ReFuel.Gltf.Serialization
{
public static class SerdesUtil
{
public static T ToSingleMatrix<T>(this JsonElement element, int rows, int columns, in T identity = default) where T : unmanaged
{
if (element.ValueKind != JsonValueKind.Array)
throw new Exception("Expected matrix to be an array.");
var enumerator = element.EnumerateArray();
T m = identity;
Span<float> view = MemoryMarshal.Cast<T, float>(MemoryMarshal.CreateSpan(ref m, 1));
for (int x = 0; x < columns; x++)
for (int y = 0; y < rows && enumerator.MoveNext(); y++)
{
if (!enumerator.Current.TryGetSingle(out float v))
throw new Exception("Expected a floating point number as matrix elements.");
view[x + columns * y] = v;
}
return m;
}
public static T ToSingleVector<T>(this JsonElement element, int components, in T identity = default)
where T : unmanaged
{
if (element.ValueKind != JsonValueKind.Array)
throw new Exception("Expected vector to be an array.");
var enumerator = element.EnumerateArray();
T vec = identity;
Span<float> view = MemoryMarshal.Cast<T, float>(MemoryMarshal.CreateSpan(ref vec, 1));
for (int i = 0; i < components && enumerator.MoveNext(); i++)
{
if (!enumerator.Current.TryGetSingle(out float v))
throw new Exception("Expected a floating point number as vector elements.");
view[i] = v;
}
return vec;
}
}
}