Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
504f2a2a4This 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.Collections;
using System.Linq;
using BYTES = System.Memory<byte>;
using ENCODING = SharpGLTF.Schema2.EncodingType;
namespace SharpGLTF.Memory
{
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an array of strided <see cref="Single"/> values.
/// </summary>
readonly struct FloatingAccessor
{
private const string ERR_UNSUPPORTEDENCODING = "Unsupported encoding.";
#region constructors
public FloatingAccessor(BYTES source, int byteOffset, int itemsCount, int byteStride, int dimensions, ENCODING encoding, Boolean normalized)
{
var enclen = encoding.ByteLength();
this._Data = source.Slice(byteOffset);
this._Getter = null;
this._Setter = null;
this._ByteStride = Math.Max(byteStride, enclen * dimensions);
this._EncodedLen = enclen;
this._ItemCount = this._Data.Length / this._ByteStride;
// strided buffers require 4 byte word padding.
if ((_Data.Length % _ByteStride) >= enclen * dimensions) ++_ItemCount;
_ItemCount = Math.Min(itemsCount, _ItemCount);
if (encoding == ENCODING.FLOAT)
{
this._Setter = this._SetValue<Single>;
this._Getter = this._GetValue<Single>;
return;
}
if (normalized)
{
switch (encoding)
{
case ENCODING.BYTE:
{
this._Setter = this._SetNormalizedS8;
this._Getter = this._GetNormalizedS8;
break;
}
case ENCODING.UNSIGNED_BYTE:
{
this._Setter = this._SetNormalizedU8;
this._Getter = this._GetNormalizedU8;
break;
}
case ENCODING.SHORT:
{
this._Setter = this._SetNormalizedS16;
this._Getter = this._GetNormalizedS16;
break;
}
case ENCODING.UNSIGNED_SHORT:
{
this._Setter = this._SetNormalizedU16;
this._Getter = this._GetNormalizedU16;
break;
}
default: throw new ArgumentException(ERR_UNSUPPORTEDENCODING, nameof(encoding));
}
}
else
{
switch (encoding)
{
case ENCODING.BYTE:
{
this._Setter = this._SetValueS8;
this._Getter = this._GetValueS8;
break;
}
case ENCODING.UNSIGNED_BYTE:
{
this._Setter = this._SetValueU8;
this._Getter = this._GetValueU8;
break;
}
case ENCODING.SHORT:
{
this._Setter = this._SetValueS16;
this._Getter = this._GetValueS16;
break;
}
case ENCODING.UNSIGNED_SHORT:
{
this._Setter = this._SetValueU16;
this._Getter = this._GetValueU16;
break;
}
case ENCODING.UNSIGNED_INT:
{
this._Setter = this._SetValueU32;
this._Getter = this._GetValueU32;
break;
}
case ENCODING.FLOAT:
break;
default: throw new ArgumentException("Unsupported encoding.", nameof(encoding));
}
}
}
#endregion
#region encoding / decoding
private Single _GetValueU8(int byteOffset) { return _GetValue<Byte>(byteOffset); }
private void _SetValueU8(int byteOffset, Single value) { _SetValue<Byte>(byteOffset, (Byte)value); }
private Single _GetValueS8(int byteOffset) { return _GetValue<SByte>(byteOffset); }
private void _SetValueS8(int byteOffset, Single value) { _SetValue<SByte>(byteOffset, (SByte)value); }
private Single _GetValueU16(int byteOffset) { return _GetValue<UInt16>(byteOffset); }
private void _SetValueU16(int byteOffset, Single value) { _SetValue<UInt16>(byteOffset, (UInt16)value); }
private Single _GetValueS16(int byteOffset) { return _GetValue<Int16>(byteOffset); }
private void _SetValueS16(int byteOffset, Single value) { _SetValue<Int16>(byteOffset, (Int16)value); }
private Single _GetValueU32(int byteOffset) { return _GetValue<UInt32>(byteOffset); }
private void _SetValueU32(int byteOffset, Single value) { _SetValue<UInt32>(byteOffset, (UInt32)value); }
private Single _GetNormalizedU8(int byteOffset) { return _GetValueU8(byteOffset) / 255.0f; }
private void _SetNormalizedU8(int byteOffset, Single value) { _SetValueU8(byteOffset, value * 255.0f); }
private Single _GetNormalizedS8(int byteOffset) { return Math.Max(_GetValueS8(byteOffset) / 127.0f, -1); }
private void _SetNormalizedS8(int byteOffset, Single value) { _SetValueS8(byteOffset, (Single)Math.Round(value * 127.0f)); }
private Single _GetNormalizedU16(int byteOffset) { return _GetValueU16(byteOffset) / 65535.0f; }
private void _SetNormalizedU16(int byteOffset, Single value) { _SetValueU16(byteOffset, value * 65535.0f); }
private Single _GetNormalizedS16(int byteOffset) { return Math.Max(_GetValueS16(byteOffset) / 32767.0f, -1); }
private void _SetNormalizedS16(int byteOffset, Single value) { _SetValueS16(byteOffset, (Single)Math.Round(value * 32767.0f)); }
private T _GetValue<T>(int byteOffset)
where T : unmanaged
{
return System.Runtime.InteropServices.MemoryMarshal.Read<T>(_Data.Span.Slice(byteOffset));
}
private void _SetValue<T>(int byteOffset, T value)
where T : unmanaged
{
System.Runtime.InteropServices.MemoryMarshal.Write<T>(_Data.Span.Slice(byteOffset), ref value);
}
#endregion
#region data
delegate Single _GetterCallback(int byteOffset);
delegate void _SetterCallback(int byteOffset, Single value);
private readonly BYTES _Data;
private readonly int _ByteStride;
private readonly int _EncodedLen;
private readonly int _ItemCount;
private readonly _GetterCallback _Getter;
private readonly _SetterCallback _Setter;
#endregion
#region API
public int ByteLength => _Data.Length;
public int Count => _ItemCount;
public Single this[int index]
{
get => _Getter(index * _ByteStride);
set
{
if (!value._IsFinite()) throw new NotFiniteNumberException(nameof(value), value);
_Setter(index * _ByteStride, value);
}
}
public Single this[int rowIndex, int subIndex]
{
get => _Getter((rowIndex * _ByteStride) + (subIndex * _EncodedLen));
set
{
if (!value._IsFinite()) throw new NotFiniteNumberException(nameof(value), value);
_Setter((rowIndex * _ByteStride) + (subIndex * _EncodedLen), value);
}
}
#endregion
}
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an <see cref="IList{single}"/>.
/// </summary>
[System.Diagnostics.DebuggerDisplay("Float[{Count}]")]
public readonly struct ScalarArray : IList<Single>, IReadOnlyList<Single>
{
#region constructors
/// <summary>
/// Initializes a new instance of the <see cref="ScalarArray"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public ScalarArray(BYTES source, int byteStride = 0, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
: this(source, 0, int.MaxValue, byteStride, encoding, normalized) { }
/// <summary>
/// Initializes a new instance of the <see cref="ScalarArray"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteOffset">The zero-based index of the first <see cref="Byte"/> in <paramref name="source"/>.</param>
/// <param name="itemsCount">The number of <see cref="Single"/> items in <paramref name="source"/>.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public ScalarArray(BYTES source, int byteOffset, int itemsCount, int byteStride, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
{
_Accessor = new FloatingAccessor(source, byteOffset, itemsCount, byteStride, 1, encoding, normalized);
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly FloatingAccessor _Accessor;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private Single[] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _Accessor.Count;
bool ICollection<Single>.IsReadOnly => false;
public Single this[int index]
{
get => _Accessor[index, 0];
set => _Accessor[index, 0] = value;
}
public IEnumerator<Single> GetEnumerator() { return new EncodedArrayEnumerator<Single>(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Single>(this); }
public bool Contains(Single item) { return IndexOf(item) >= 0; }
public int IndexOf(Single item) { return this._FirstIndexOf(item); }
public void CopyTo(Single[] array, int arrayIndex)
{
Guard.NotNull(array, nameof(array));
this._CopyTo(array, arrayIndex);
}
public void Fill(IEnumerable<Single> values, int dstStart = 0)
{
Guard.NotNull(values, nameof(values));
values._CopyTo(this, dstStart);
}
void IList<Single>.Insert(int index, Single item) { throw new NotSupportedException(); }
void IList<Single>.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection<Single>.Add(Single item) { throw new NotSupportedException(); }
void ICollection<Single>.Clear() { throw new NotSupportedException(); }
bool ICollection<Single>.Remove(Single item) { throw new NotSupportedException(); }
#endregion
}
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an <see cref="IList{Vector2}"/>.
/// </summary>
[System.Diagnostics.DebuggerDisplay("Vector2[{Count}]")]
public readonly struct Vector2Array : IList<Vector2>, IReadOnlyList<Vector2>
{
#region constructors
/// <summary>
/// Initializes a new instance of the <see cref="Vector2Array"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public Vector2Array(BYTES source, int byteStride = 0, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
: this(source, 0, int.MaxValue, byteStride, encoding, normalized) { }
/// <summary>
/// Initializes a new instance of the <see cref="Vector2Array"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteOffset">The zero-based index of the first <see cref="Byte"/> in <paramref name="source"/>.</param>
/// <param name="itemsCount">>The number of <see cref="Vector2"/> items in <paramref name="source"/>.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public Vector2Array(BYTES source, int byteOffset, int itemsCount, int byteStride, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
{
_Accessor = new FloatingAccessor(source, byteOffset, itemsCount, byteStride, 2, encoding, normalized);
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly FloatingAccessor _Accessor;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private Vector2[] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _Accessor.Count;
bool ICollection<Vector2>.IsReadOnly => false;
public Vector2 this[int index]
{
get
{
return new Vector2(_Accessor[index, 0], _Accessor[index, 1]);
}
set
{
_Accessor[index, 0] = value.X;
_Accessor[index, 1] = value.Y;
}
}
public IEnumerator<Vector2> GetEnumerator() { return new EncodedArrayEnumerator<Vector2>(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Vector2>(this); }
public bool Contains(Vector2 item) { return IndexOf(item) >= 0; }
public int IndexOf(Vector2 item) { return this._FirstIndexOf(item); }
public void CopyTo(Vector2[] array, int arrayIndex)
{
Guard.NotNull(array, nameof(array));
this._CopyTo(array, arrayIndex);
}
public void Fill(IEnumerable<Vector2> values, int dstStart = 0)
{
Guard.NotNull(values, nameof(values));
values._CopyTo(this, dstStart);
}
void IList<Vector2>.Insert(int index, Vector2 item) { throw new NotSupportedException(); }
void IList<Vector2>.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection<Vector2>.Add(Vector2 item) { throw new NotSupportedException(); }
void ICollection<Vector2>.Clear() { throw new NotSupportedException(); }
bool ICollection<Vector2>.Remove(Vector2 item) { throw new NotSupportedException(); }
#endregion
}
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an <see cref="IList{Vector3}"/>.
/// </summary>
[System.Diagnostics.DebuggerDisplay("Vector3[{Count}]")]
public readonly struct Vector3Array : IList<Vector3>, IReadOnlyList<Vector3>
{
#region constructors
/// <summary>
/// Initializes a new instance of the <see cref="Vector3Array"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public Vector3Array(BYTES source, int byteStride = 0, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
: this(source, 0, int.MaxValue, byteStride, encoding, normalized) { }
/// <summary>
/// Initializes a new instance of the <see cref="Vector3Array"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteOffset">The zero-based index of the first <see cref="Byte"/> in <paramref name="source"/>.</param>
/// <param name="itemsCount">The number of <see cref="Vector3"/> items in <paramref name="source"/>.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public Vector3Array(BYTES source, int byteOffset, int itemsCount, int byteStride, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
{
_Accessor = new FloatingAccessor(source, byteOffset, itemsCount, byteStride, 3, encoding, normalized);
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly FloatingAccessor _Accessor;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private Vector3[] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _Accessor.Count;
bool ICollection<Vector3>.IsReadOnly => false;
public Vector3 this[int index]
{
get
{
return new Vector3(_Accessor[index, 0], _Accessor[index, 1], _Accessor[index, 2]);
}
set
{
_Accessor[index, 0] = value.X;
_Accessor[index, 1] = value.Y;
_Accessor[index, 2] = value.Z;
}
}
public IEnumerator<Vector3> GetEnumerator() { return new EncodedArrayEnumerator<Vector3>(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Vector3>(this); }
public bool Contains(Vector3 item) { return IndexOf(item) >= 0; }
public int IndexOf(Vector3 item) { return this._FirstIndexOf(item); }
public void CopyTo(Vector3[] array, int arrayIndex)
{
Guard.NotNull(array, nameof(array));
this._CopyTo(array, arrayIndex);
}
public void Fill(IEnumerable<Vector3> values, int dstStart = 0)
{
Guard.NotNull(values, nameof(values));
values._CopyTo(this, dstStart);
}
void IList<Vector3>.Insert(int index, Vector3 item) { throw new NotSupportedException(); }
void IList<Vector3>.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection<Vector3>.Add(Vector3 item) { throw new NotSupportedException(); }
void ICollection<Vector3>.Clear() { throw new NotSupportedException(); }
bool ICollection<Vector3>.Remove(Vector3 item) { throw new NotSupportedException(); }
#endregion
}
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an <see cref="IList{Vector4}"/>.
/// </summary>
[System.Diagnostics.DebuggerDisplay("Vector4[{Count}]")]
public readonly struct Vector4Array : IList<Vector4>, IReadOnlyList<Vector4>
{
#region constructors
/// <summary>
/// Initializes a new instance of the <see cref="Vector4Array"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public Vector4Array(BYTES source, int byteStride = 0, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
: this(source, 0, int.MaxValue, byteStride, encoding, normalized) { }
/// <summary>
/// Initializes a new instance of the <see cref="Vector4Array"/> struct.
/// </summary>
/// <param name="source">The array range to wrap.</param>
/// <param name="byteOffset">The zero-based index of the first <see cref="Byte"/> in <paramref name="source"/>.</param>
/// <param name="itemsCount">The number of <see cref="Vector3"/> items in <paramref name="source"/>.</param>
/// <param name="byteStride">
/// The byte stride between elements.
/// If the value is zero, the size of the item is used instead.
/// </param>
/// <param name="encoding">A value of <see cref="ENCODING"/>.</param>
/// <param name="normalized">True if values are normalized.</param>
public Vector4Array(BYTES source, int byteOffset, int itemsCount, int byteStride, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
{
_Accessor = new FloatingAccessor(source, byteOffset, itemsCount, byteStride, 4, encoding, normalized);
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly FloatingAccessor _Accessor;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private Vector4[] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _Accessor.Count;
bool ICollection<Vector4>.IsReadOnly => false;
public Vector4 this[int index]
{
get
{
return new Vector4(_Accessor[index, 0], _Accessor[index, 1], _Accessor[index, 2], _Accessor[index, 3]);
}
set
{
_Accessor[index, 0] = value.X;
_Accessor[index, 1] = value.Y;
_Accessor[index, 2] = value.Z;
_Accessor[index, 3] = value.W;
}
}
public IEnumerator<Vector4> GetEnumerator() { return new EncodedArrayEnumerator<Vector4>(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Vector4>(this); }
public bool Contains(Vector4 item) { return IndexOf(item) >= 0; }
public int IndexOf(Vector4 item) { return this._FirstIndexOf(item); }
public void CopyTo(Vector4[] array, int arrayIndex)
{
Guard.NotNull(array, nameof(array));
this._CopyTo(array, arrayIndex);
}
public void Fill(IEnumerable<Vector4> values, int dstStart = 0)
{
Guard.NotNull(values, nameof(values));
values._CopyTo(this, dstStart);
}
void IList<Vector4>.Insert(int index, Vector4 item) { throw new NotSupportedException(); }
void IList<Vector4>.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection<Vector4>.Add(Vector4 item) { throw new NotSupportedException(); }
void ICollection<Vector4>.Clear() { throw new NotSupportedException(); }
bool ICollection<Vector4>.Remove(Vector4 item) { throw new NotSupportedException(); }
#endregion
}
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an <see cref="IList{Quaternion}"/>.
/// </summary>
[System.Diagnostics.DebuggerDisplay("Quaternion[{Count}]")]
public readonly struct QuaternionArray : IList<Quaternion>, IReadOnlyList<Quaternion>
{
#region constructors
public QuaternionArray(BYTES source, int byteStride = 0, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
: this(source, 0, int.MaxValue, byteStride, encoding, normalized) { }
public QuaternionArray(BYTES source, int byteOffset, int itemsCount, int byteStride, ENCODING encoding, Boolean normalized)
{
_Accessor = new FloatingAccessor(source, byteOffset, itemsCount, byteStride, 4, encoding, normalized);
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly FloatingAccessor _Accessor;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private Quaternion[] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _Accessor.Count;
bool ICollection<Quaternion>.IsReadOnly => false;
public Quaternion this[int index]
{
get
{
return new Quaternion(_Accessor[index, 0], _Accessor[index, 1], _Accessor[index, 2], _Accessor[index, 3]);
}
set
{
_Accessor[index, 0] = value.X;
_Accessor[index, 1] = value.Y;
_Accessor[index, 2] = value.Z;
_Accessor[index, 3] = value.W;
}
}
public IEnumerator<Quaternion> GetEnumerator() { return new EncodedArrayEnumerator<Quaternion>(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Quaternion>(this); }
public bool Contains(Quaternion item) { return IndexOf(item) >= 0; }
public int IndexOf(Quaternion item) { return this._FirstIndexOf(item); }
public void CopyTo(Quaternion[] array, int arrayIndex)
{
Guard.NotNull(array, nameof(array));
this._CopyTo(array, arrayIndex);
}
public void Fill(IEnumerable<Quaternion> values, int dstStart = 0)
{
Guard.NotNull(values, nameof(values));
values._CopyTo(this, dstStart);
}
void IList<Quaternion>.Insert(int index, Quaternion item) { throw new NotSupportedException(); }
void IList<Quaternion>.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection<Quaternion>.Add(Quaternion item) { throw new NotSupportedException(); }
void ICollection<Quaternion>.Clear() { throw new NotSupportedException(); }
bool ICollection<Quaternion>.Remove(Quaternion item) { throw new NotSupportedException(); }
#endregion
}
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an <see cref="IList{Matrix4x4}"/>.
/// </summary>
[System.Diagnostics.DebuggerDisplay("Matrix4x4[{Count}]")]
public readonly struct Matrix4x4Array : IList<Matrix4x4>, IReadOnlyList<Matrix4x4>
{
#region constructors
public Matrix4x4Array(BYTES source, int byteStride = 0, ENCODING encoding = ENCODING.FLOAT, Boolean normalized = false)
: this(source, 0, int.MaxValue, byteStride, encoding, normalized) { }
public Matrix4x4Array(BYTES source, int byteOffset, int itemsCount, int byteStride, ENCODING encoding, Boolean normalized)
{
_Accessor = new FloatingAccessor(source, byteOffset, itemsCount, byteStride, 16, encoding, normalized);
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly FloatingAccessor _Accessor;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private Matrix4x4[] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _Accessor.Count;
bool ICollection<Matrix4x4>.IsReadOnly => false;
public Matrix4x4 this[int index]
{
get
{
return new Matrix4x4
(
_Accessor[index, 0], _Accessor[index, 1], _Accessor[index, 2], _Accessor[index, 3],
_Accessor[index, 4], _Accessor[index, 5], _Accessor[index, 6], _Accessor[index, 7],
_Accessor[index, 8], _Accessor[index, 9], _Accessor[index, 10], _Accessor[index, 11],
_Accessor[index, 12], _Accessor[index, 13], _Accessor[index, 14], _Accessor[index, 15]
);
}
set
{
_Accessor[index, 0] = value.M11;
_Accessor[index, 1] = value.M12;
_Accessor[index, 2] = value.M13;
_Accessor[index, 3] = value.M14;
_Accessor[index, 4] = value.M21;
_Accessor[index, 5] = value.M22;
_Accessor[index, 6] = value.M23;
_Accessor[index, 7] = value.M24;
_Accessor[index, 8] = value.M31;
_Accessor[index, 9] = value.M32;
_Accessor[index, 10] = value.M33;
_Accessor[index, 11] = value.M34;
_Accessor[index, 12] = value.M41;
_Accessor[index, 13] = value.M42;
_Accessor[index, 14] = value.M43;
_Accessor[index, 15] = value.M44;
}
}
public IEnumerator<Matrix4x4> GetEnumerator() { return new EncodedArrayEnumerator<Matrix4x4>(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Matrix4x4>(this); }
public bool Contains(Matrix4x4 item) { return IndexOf(item) >= 0; }
public int IndexOf(Matrix4x4 item) { return this._FirstIndexOf(item); }
public void CopyTo(Matrix4x4[] array, int arrayIndex)
{
Guard.NotNull(array, nameof(array));
this._CopyTo(array, arrayIndex);
}
public void Fill(IEnumerable<Matrix4x4> values, int dstStart = 0)
{
Guard.NotNull(values, nameof(values));
values._CopyTo(this, dstStart);
}
void IList<Matrix4x4>.Insert(int index, Matrix4x4 item) { throw new NotSupportedException(); }
void IList<Matrix4x4>.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection<Matrix4x4>.Add(Matrix4x4 item) { throw new NotSupportedException(); }
void ICollection<Matrix4x4>.Clear() { throw new NotSupportedException(); }
bool ICollection<Matrix4x4>.Remove(Matrix4x4 item) { throw new NotSupportedException(); }
#endregion
}
/// <summary>
/// Wraps an encoded <see cref="BYTES"/> and exposes it as an IList{Single[]}/>.
/// </summary>
[System.Diagnostics.DebuggerDisplay("Float[][{Count}]")]
public readonly struct MultiArray : IList<Single[]>, IReadOnlyList<Single[]>
{
#region constructors
public MultiArray(BYTES source, int byteOffset, int itemsCount, int byteStride, int dimensions, ENCODING encoding, Boolean normalized)
{
_Dimensions = dimensions;
_Accessor = new FloatingAccessor(source, byteOffset, itemsCount, byteStride, dimensions, encoding, normalized);
}
#endregion
#region data
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly int _Dimensions;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
private readonly FloatingAccessor _Accessor;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
private Single[][] _DebugItems => this.ToArray();
#endregion
#region API
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Count => _Accessor.Count;
[System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
public int Dimensions => _Dimensions;
bool ICollection<Single[]>.IsReadOnly => false;
#pragma warning disable CA1819 // Properties should not return arrays
public Single[] this[int index]
#pragma warning restore CA1819 // Properties should not return arrays
{
get
{
var val = new Single[_Dimensions];
CopyItemTo(index, val);
return val;
}
set
{
Guard.NotNull(value, nameof(value));
Guard.IsTrue(value.Length == _Dimensions, nameof(value));
for (int i = 0; i < _Dimensions; ++i)
{
_Accessor[index, i] = value[i];
}
}
}
public void CopyItemTo(int index, Single[] dstItem)
{
Guard.NotNull(dstItem, nameof(dstItem));
var count = _Dimensions;
for (int i = 0; i < count; ++i) dstItem[i] = _Accessor[index, i];
}
public IEnumerator<Single[]> GetEnumerator() { return new EncodedArrayEnumerator<Single[]>(this); }
IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Single[]>(this); }
public bool Contains(Single[] item) { return IndexOf(item) >= 0; }
public int IndexOf(Single[] item) { return this._FirstIndexOf(item); }
public void CopyTo(Single[][] array, int arrayIndex)
{
Guard.NotNull(array, nameof(array));
this._CopyTo(array, arrayIndex);
}
public void Fill(IEnumerable<Single[]> values, int dstStart = 0)
{
Guard.NotNull(values, nameof(values));
values._CopyTo(this, dstStart);
}
void IList<Single[]>.Insert(int index, Single[] item) { throw new NotSupportedException(); }
void IList<Single[]>.RemoveAt(int index) { throw new NotSupportedException(); }
void ICollection<Single[]>.Add(Single[] item) { throw new NotSupportedException(); }
void ICollection<Single[]>.Clear() { throw new NotSupportedException(); }
bool ICollection<Single[]>.Remove(Single[] item) { throw new NotSupportedException(); }
#endregion
}
}