From 10d912d302a20aa6f424e3726b6dd5c03169f5f7 Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Sun, 12 Oct 2025 18:01:13 +0300 Subject: [PATCH] Clean up code related to deserialization of linear algebra types. --- ReFuel.Gltf/GltfMaterial.cs | 32 +------ ReFuel.Gltf/GltfNode.cs | 120 +++--------------------- ReFuel.Gltf/Serialization/SerdesUtil.cs | 52 ++++++++++ 3 files changed, 70 insertions(+), 134 deletions(-) create mode 100644 ReFuel.Gltf/Serialization/SerdesUtil.cs diff --git a/ReFuel.Gltf/GltfMaterial.cs b/ReFuel.Gltf/GltfMaterial.cs index 8b6d15a..11af03a 100644 --- a/ReFuel.Gltf/GltfMaterial.cs +++ b/ReFuel.Gltf/GltfMaterial.cs @@ -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"; diff --git a/ReFuel.Gltf/GltfNode.cs b/ReFuel.Gltf/GltfNode.cs index 7c8a116..34f3983 100755 --- a/ReFuel.Gltf/GltfNode.cs +++ b/ReFuel.Gltf/GltfNode.cs @@ -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) diff --git a/ReFuel.Gltf/Serialization/SerdesUtil.cs b/ReFuel.Gltf/Serialization/SerdesUtil.cs new file mode 100644 index 0000000..175f2a0 --- /dev/null +++ b/ReFuel.Gltf/Serialization/SerdesUtil.cs @@ -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(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 view = MemoryMarshal.Cast(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(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 view = MemoryMarshal.Cast(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; + } + } +}