Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Linq;
using SharpGLTF.Collections;
namespace SharpGLTF.Schema2
{
partial class KHR_lights_punctualglTFextension
{
internal KHR_lights_punctualglTFextension(ModelRoot root)
{
_lights = new ChildrenCollection<PunctualLight, ModelRoot>(root);
}
protected override IEnumerable<ExtraProperties> GetLogicalChildren()
{
return base.GetLogicalChildren().Concat(_lights);
}
public IReadOnlyList<PunctualLight> Lights => _lights;
public PunctualLight CreateLight(string name, PunctualLightType ltype)
{
var light = new PunctualLight(ltype);
light.Name = name;
_lights.Add(light);
return light;
}
}
/// <summary>
/// Defines all the types of <see cref="PunctualLight"/> types.
/// </summary>
public enum PunctualLightType
{
Directional,
Point,
Spot
}
/// <remarks>
/// This is part of <see href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual"/> extension.
/// </remarks>
[System.Diagnostics.DebuggerDisplay("{LightType} {Color} {Intensity} {Range}")]
public sealed partial class PunctualLight
{
#region constants
private const Double _rangeDefault = Double.PositiveInfinity;
#endregion
#region lifecycle
internal PunctualLight() { }
internal PunctualLight(PunctualLightType ltype)
{
_type = ltype.ToString().ToLowerInvariant();
if (ltype == PunctualLightType.Spot) _spot = new PunctualLightSpot();
}
/// <summary>
/// Sets the cone angles for the <see cref="PunctualLightType.Spot"/> light.
/// </summary>
/// <param name="innerConeAngle">
/// Gets the Angle, in radians, from centre of spotlight where falloff begins.
/// Must be greater than or equal to 0 and less than outerConeAngle.
/// </param>
/// <param name="outerConeAngle">
/// Gets Angle, in radians, from centre of spotlight where falloff ends.
/// Must be greater than innerConeAngle and less than or equal to PI / 2.0.
/// </param>
public void SetSpotCone(float innerConeAngle, float outerConeAngle)
{
if (_spot == null) throw new InvalidOperationException($"Expected {PunctualLightType.Spot} but found {LightType}");
if (innerConeAngle > outerConeAngle) throw new ArgumentException($"{nameof(innerConeAngle)} must be equal or smaller than {nameof(outerConeAngle)}");
_spot.InnerConeAngle = innerConeAngle;
_spot.OuterConeAngle = outerConeAngle;
}
/// <summary>
/// Defines the light color, intensity and range for the current <see cref="PunctualLight"/>.
/// </summary>
/// <param name="color">RGB value for light's color in linear space.</param>
/// <param name="intensity">
/// Brightness of light in. The units that this is defined in depend on the type of light.
/// point and spot lights use luminous intensity in candela (lm/sr) while directional
/// lights use illuminance in lux (lm/m2)
/// </param>
/// <param name="range">
/// Hint defining a distance cutoff at which the light's intensity may be considered
/// to have reached zero. Supported only for point and spot lights. Must be > 0.
/// When undefined, range is assumed to be infinite.
/// </param>
public void SetColor(Vector3 color, float intensity = 1, float range = float.PositiveInfinity)
{
this.Color = color;
this.Intensity = intensity;
this.Range = range;
}
#endregion
#region properties
/// <summary>
/// Gets the Local light direction.
/// </summary>
/// <remarks>
/// For light types that have a direction (directional and spot lights),
/// the light's direction is defined as the 3-vector (0.0, 0.0, -1.0)
/// </remarks>
public static Vector3 LocalDirection => -Vector3.UnitZ;
/// <summary>
/// Gets the type of light.
/// </summary>
public PunctualLightType LightType => string.IsNullOrEmpty(_type) ? PunctualLightType.Directional : (PunctualLightType)Enum.Parse(typeof(PunctualLightType), _type, true);
/// <summary>
/// Gets the Angle, in radians, from centre of spotlight where falloff begins.
/// Must be greater than or equal to 0 and less than outerConeAngle.
/// </summary>
public Single InnerConeAngle => this._spot == null ? 0 : (Single)this._spot.InnerConeAngle;
/// <summary>
/// Gets Angle, in radians, from centre of spotlight where falloff ends.
/// Must be greater than innerConeAngle and less than or equal to PI / 2.0.
/// </summary>
public Single OuterConeAngle => this._spot == null ? 0 : (Single)this._spot.OuterConeAngle;
/// <summary>
/// Gets or sets the RGB value for light's color in linear space.
/// </summary>
public Vector3 Color
{
get => _color.AsValue(_colorDefault);
set => _color = value.AsNullable(_colorDefault, Vector3.Zero, Vector3.One);
}
/// <summary>
/// Gets or sets the Brightness of light in. The units that this is defined in depend on the type of light.
/// point and spot lights use luminous intensity in candela (lm/sr) while directional
/// lights use illuminance in lux (lm/m2)
/// </summary>
public Single Intensity
{
get => (Single)_intensity.AsValue(_intensityDefault);
set => _intensity = ((double)value).AsNullable(_intensityDefault, _intensityMinimum, float.MaxValue);
}
/// <summary>
/// Gets or sets a Hint defining a distance cutoff at which the light's intensity may be considered
/// to have reached zero. Supported only for point and spot lights. Must be > 0.
/// When undefined, range is assumed to be infinite.
/// </summary>
public Single Range
{
get => (Single)_range.AsValue(_rangeDefault);
set
{
if (LightType == PunctualLightType.Directional) { _range = null; return; }
_range = ((double)value).AsNullable(_rangeDefault, _rangeMinimum + 2e-07, float.MaxValue);
}
}
#endregion
#region API
protected override IEnumerable<ExtraProperties> GetLogicalChildren()
{
var children = base.GetLogicalChildren();
if (_spot != null) children = children.Concat(new[] { _spot });
return children;
}
#endregion
#region Validation
protected override void OnValidateReferences(Validation.ValidationContext validate)
{
validate.IsAnyOf("Type", _type, "directional", "point", "spot");
if (LightType == PunctualLightType.Spot) validate.IsDefined("Spot", _spot);
base.OnValidateReferences(validate);
}
protected override void OnValidateContent(Validation.ValidationContext validate)
{
validate.IsDefaultOrWithin(nameof(Intensity), _intensity, _intensityMinimum, float.MaxValue);
base.OnValidateContent(validate);
}
#endregion
}
partial class PunctualLightSpot
{
public Single InnerConeAngle
{
get => (Single)_innerConeAngle.AsValue(_innerConeAngleDefault);
set => _innerConeAngle = value.AsNullable((Single)_innerConeAngleDefault, (Single)_innerConeAngleMinimum, (Single)_innerConeAngleMaximum);
}
public Single OuterConeAngle
{
get => (Single)_outerConeAngle.AsValue(_outerConeAngleDefault);
set => _outerConeAngle = value.AsNullable((Single)_outerConeAngleDefault, (Single)_outerConeAngleMinimum, (Single)_outerConeAngleMaximum);
}
protected override void OnValidateContent(Validation.ValidationContext validate)
{
validate
.IsDefaultOrWithin(nameof(InnerConeAngle), InnerConeAngle, (Single)_innerConeAngleMinimum, (Single)_innerConeAngleMaximum)
.IsDefaultOrWithin(nameof(OuterConeAngle), OuterConeAngle, (Single)_outerConeAngleMinimum, (Single)_outerConeAngleMaximum)
.IsLess(nameof(InnerConeAngle), InnerConeAngle, OuterConeAngle);
base.OnValidateContent(validate);
}
}
partial class KHR_lights_punctualnodeextension
{
#pragma warning disable CA1801 // Review unused parameters
internal KHR_lights_punctualnodeextension(Node node) { }
#pragma warning restore CA1801 // Review unused parameters
public int LightIndex
{
get => _light;
set => _light = value;
}
}
partial class Node
{
/// <summary>
/// Gets or sets the <see cref="Schema2.PunctualLight"/> of this <see cref="Node"/>.
/// </summary>
/// <remarks>
/// This is part of <see href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual"/> extension.
/// </remarks>
public PunctualLight PunctualLight
{
get
{
var ext = this.GetExtension<KHR_lights_punctualnodeextension>();
if (ext == null) return null;
return this.LogicalParent.LogicalPunctualLights[ext.LightIndex];
}
set
{
if (value == null) { this.RemoveExtensions<KHR_lights_punctualnodeextension>(); return; }
Guard.MustShareLogicalParent(this, value, nameof(value));
this.UsingExtension(typeof(KHR_lights_punctualnodeextension));
var ext = new KHR_lights_punctualnodeextension(this);
ext.LightIndex = value.LogicalIndex;
this.SetExtension(ext);
}
}
}
partial class ModelRoot
{
/// <summary>
/// Gets A collection of <see cref="PunctualLight"/> instances.
/// </summary>
/// <remarks>
/// This is part of <see href="https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual">KHR_lights_punctual</see> extension.
/// </remarks>
public IReadOnlyList<PunctualLight> LogicalPunctualLights
{
get
{
var ext = this.GetExtension<KHR_lights_punctualglTFextension>();
if (ext == null) return Array.Empty<PunctualLight>();
return ext.Lights;
}
}
/// <summary>
/// Creates a new <see cref="PunctualLight"/> instance and
/// adds it to <see cref="ModelRoot.LogicalPunctualLights"/>.
/// </summary>
/// <param name="lightType">A value of <see cref="PunctualLightType"/> describing the type of light to create.</param>
/// <returns>A <see cref="PunctualLight"/> instance.</returns>
public PunctualLight CreatePunctualLight(PunctualLightType lightType)
{
return CreatePunctualLight(null, lightType);
}
/// <summary>
/// Creates a new <see cref="PunctualLight"/> instance.
/// and adds it to <see cref="ModelRoot.LogicalPunctualLights"/>.
/// </summary>
/// <param name="name">The name of the instance.</param>
/// <param name="lightType">A value of <see cref="PunctualLightType"/> describing the type of light to create.</param>
/// <returns>A <see cref="PunctualLight"/> instance.</returns>
public PunctualLight CreatePunctualLight(string name, PunctualLightType lightType)
{
var ext = this.GetExtension<KHR_lights_punctualglTFextension>();
if (ext == null)
{
this.UsingExtension(typeof(ModelRoot), typeof(KHR_lights_punctualglTFextension));
ext = new KHR_lights_punctualglTFextension(this);
this.SetExtension(ext);
}
return ext.CreateLight(name, lightType);
}
}
}
d49ffeb42This file is pinned to the selected release. Download the original to open it in your design tool.