From 056a73ec84ffd65a1e9229ff1dff86efc10806be Mon Sep 17 00:00:00 2001 From: Bezaleel Olakunori Date: Tue, 28 May 2024 13:00:31 +0200 Subject: [PATCH] Implement KHR_materials_volume Gltf extension --- .../Gltf/Extensions/KHR_materials_volume.cs | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/ThreeDModels/Format/Gltf/Extensions/KHR_materials_volume.cs diff --git a/src/ThreeDModels/Format/Gltf/Extensions/KHR_materials_volume.cs b/src/ThreeDModels/Format/Gltf/Extensions/KHR_materials_volume.cs new file mode 100644 index 0000000..9996b75 --- /dev/null +++ b/src/ThreeDModels/Format/Gltf/Extensions/KHR_materials_volume.cs @@ -0,0 +1,113 @@ +using System.Text.Json; +using ThreeDModels.Format.Gltf.Elements; +using ThreeDModels.Format.Gltf.IO; +using static ThreeDModels.Format.Gltf.IO.Utf8JsonReaderHelpers; + +namespace ThreeDModels.Format.Gltf.Extensions; + +/// +/// Represents an object that defines the parameters for the volume of a material. +/// +public class KHR_materials_volume : IGltfProperty +{ + /// + /// The thickness of the volume beneath the surface. + /// + public float ThicknessFactor { get; set; } + /// + /// Texture that defines the thickness of the volume, stored in the G channel. + /// + public TextureInfo? ThicknessTexture { get; set; } + /// + /// Average distance that light travels in the medium before interacting with a particle. + /// + public float AttenuationDistance { get; set; } + /// + /// Color that white light turns into due to absorption when reaching the attenuation distance. + /// + public required float[] AttenuationColor { get; set; } + public Dictionary? Extensions { get; set; } + public object? Extras { get; set; } +} + +public class KhrMaterialsVolumeExtension : IGltfExtension +{ + public string Name => nameof(KHR_materials_volume); + public const float Default_ThicknessFactor = 0.0f; + public const float Default_AttenuationDistance = 0.01f; + public static readonly float[] Default_AttenuationColor = [1.0f, 1.0f, 1.0f]; + + public object? Read(ref Utf8JsonReader jsonReader, GltfReaderContext context, Type parentType) + { + if (parentType != typeof(Material)) + { + throw new InvalidDataException("KHR_materials_volume must be used in a Material."); + } + float? thicknessFactor = null; + TextureInfo? thicknessTexture = null; + float? attenuationDistance = null; + float[]? attenuationColor = null; + Dictionary? extensions = null; + object? extras = null; + if (jsonReader.TokenType == JsonTokenType.PropertyName && jsonReader.Read()) + { + } + if (jsonReader.TokenType == JsonTokenType.Null) + { + return null; + } + else if (jsonReader.TokenType != JsonTokenType.StartObject) + { + throw new InvalidDataException("Failed to find start of property."); + } + while (jsonReader.Read()) + { + if (jsonReader.TokenType == JsonTokenType.EndObject) + { + break; + } + var propertyName = jsonReader.GetString(); + if (propertyName == nameof(thicknessFactor)) + { + thicknessFactor = ReadFloat(ref jsonReader); + } + else if (propertyName == nameof(thicknessTexture)) + { + thicknessTexture = TextureInfoSerialization.Read(ref jsonReader, context); + } + else if (propertyName == nameof(attenuationDistance)) + { + attenuationDistance = ReadFloat(ref jsonReader); + } + else if (propertyName == nameof(attenuationColor)) + { + attenuationColor = ReadFloatList(ref jsonReader, context)?.ToArray(); + } + else if (propertyName == nameof(extensions)) + { + extensions = ExtensionsSerialization.Read(ref jsonReader, context); + } + else if (propertyName == nameof(extras)) + { + extras = JsonSerialization.Read(ref jsonReader, context); + } + else + { + throw new InvalidDataException($"Unknown property: {propertyName}"); + } + } + if (attenuationColor != null && attenuationColor.Length != 3) + { + throw new InvalidDataException("KHR_materials_volume.attenuationColor must have 3 elements."); + } + return new KHR_materials_volume() + { + ThicknessFactor = thicknessFactor ?? Default_ThicknessFactor, + ThicknessTexture = thicknessTexture, + AttenuationDistance = attenuationDistance ?? Default_AttenuationDistance, + AttenuationColor = attenuationColor ?? Default_AttenuationColor, + Extensions = extensions, + Extras = extras, + }; + } +}