using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Text; namespace SharpGLTF.Memory { public interface IEncodedArray : IReadOnlyCollection where T : unmanaged { T this[int index] { get; set; } void CopyTo(ArraySegment dst); // void CopyTo(IEncodedArray dst); (T, T) GetBounds(); } struct EncodedArrayEnumerator : IEnumerator where T : unmanaged { #region lifecycle public EncodedArrayEnumerator(IEncodedArray accessor) { this._Accessor = accessor; this._Count = accessor.Count; this._Index = -1; } public void Dispose() { } #endregion #region data private readonly IEncodedArray _Accessor; private readonly int _Count; private int _Index; #endregion #region API public T Current => _Accessor[_Index]; object IEnumerator.Current => _Accessor[_Index]; public bool MoveNext() { ++_Index; return _Index < _Count; } public void Reset() { _Index = -1; } #endregion } public static class EncodedArrayUtils { public static IntegerArray IndicesRange(int start, int count) { var array = new IntegerArray( new ArraySegment(new Byte[count * 4]), Schema2.IndexType.UNSIGNED_INT); for (int i = 0; i < count; ++i) { array[i] = (UInt32)(start + i); } return array; } public static void FillFrom(this IEncodedArray dst, int dstIndex, IEnumerable src) { using (var ator = src.GetEnumerator()) { while (dstIndex < dst.Count && ator.MoveNext()) { dst[dstIndex++] = (UInt32)ator.Current; } } } public static void FillFrom(this IEncodedArray dst, int dstIndex, IEnumerable src) where T : unmanaged { using (var ator = src.GetEnumerator()) { while (dstIndex < dst.Count && ator.MoveNext()) { dst[dstIndex++] = ator.Current; } } } public static void FillFrom(this IEncodedArray dst, int dstIndex, params T[] src) where T : unmanaged { for (int i = 0; i < src.Length; ++i) { dst[dstIndex + i] = src[i]; } } public static void CopyTo(IEncodedArray src, IEncodedArray dst, int dstOffset = 0) where T : unmanaged { for (int i = 0; i < src.Count; ++i) { dst[i + dstOffset] = src[i]; } } public static void CopyTo(T[] src, IEncodedArray dst, int dstOffset = 0) where T : unmanaged { for (int i = 0; i < src.Length; ++i) { dst[i + dstOffset] = src[i]; } } public static void Copy(IEncodedArray src, T[] dst) where T : unmanaged { Copy(src, new ArraySegment(dst)); } public static void Copy(IEncodedArray src, ArraySegment dst) where T : unmanaged { var c = src.Count; for (int i = 0; i < c; ++i) dst.Array[dst.Offset + i] = src[i]; } public static (Single, Single) GetBounds(ScalarArray accesor) { var min = Single.MaxValue; var max = Single.MinValue; int c = accesor.Count; for (int i = 0; i < c; ++i) { var v = accesor[i]; min = Math.Min(min, v); max = Math.Max(max, v); } return (min, max); } public static (Vector2, Vector2) GetBounds(Vector2Array accesor) { var min = new Vector2(Single.MaxValue); var max = new Vector2(Single.MinValue); int c = accesor.Count; for (int i = 0; i < c; ++i) { var v = accesor[i]; min = Vector2.Min(min, v); max = Vector2.Max(max, v); } return (min, max); } public static (Vector3, Vector3) GetBounds(Vector3Array accesor) { var min = new Vector3(Single.MaxValue); var max = new Vector3(Single.MinValue); int c = accesor.Count; for (int i = 0; i < c; ++i) { var v = accesor[i]; min = Vector3.Min(min, v); max = Vector3.Max(max, v); } return (min, max); } public static (Vector4, Vector4) GetBounds(IEncodedArray accesor) { var min = new Vector4(Single.MaxValue); var max = new Vector4(Single.MinValue); int c = accesor.Count; for (int i = 0; i < c; ++i) { var v = accesor[i]; min = Vector4.Min(min, v); max = Vector4.Max(max, v); } return (min, max); } } /// /// Wraps a collection of Scalar values and exposes it as a collection of Vector4 values /// struct _MapScalarToVector4 : IEncodedArray { public _MapScalarToVector4(ScalarArray source) { _Accessor = source; } private ScalarArray _Accessor; public int Count => _Accessor.Count; public Vector4 this[int index] { get => new Vector4(_Accessor[index], 0, 0, 0); set => _Accessor[index] = value.X; } public void CopyTo(ArraySegment dst) { EncodedArrayUtils.Copy(this, dst); } public IEnumerator GetEnumerator() { return new EncodedArrayEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator(this); } public (Vector4, Vector4) GetBounds() { return EncodedArrayUtils.GetBounds(this); } } /// /// Wraps a collection of Vector2 values and exposes it as a collection of Vector4 values /// struct _MapVector2ToVector4 : IEncodedArray { public _MapVector2ToVector4(Vector2Array source) { _Accessor = source; } private Vector2Array _Accessor; public int Count => _Accessor.Count; public Vector4 this[int index] { get { var v = _Accessor[index]; return new Vector4(v.X, v.Y, 0, 0); } set => _Accessor[index] = new Vector2(value.X, value.Y); } public void CopyTo(ArraySegment dst) { EncodedArrayUtils.Copy(this, dst); } public IEnumerator GetEnumerator() { return new EncodedArrayEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator(this); } public (Vector4, Vector4) GetBounds() { return EncodedArrayUtils.GetBounds(this); } } /// /// Wraps a collection of Vector3 values and exposes it as a collection of Vector4 values /// struct _MapVector3ToVector4 : IEncodedArray { public _MapVector3ToVector4(Vector3Array source) { _Accessor = source; } private Vector3Array _Accessor; public int Count => _Accessor.Count; public Vector4 this[int index] { get { var v = _Accessor[index]; return new Vector4(v.X, v.Y, v.Z, 0); } set => _Accessor[index] = new Vector3(value.X, value.Y, value.Z); } public void CopyTo(ArraySegment dst) { EncodedArrayUtils.Copy(this, dst); } public IEnumerator GetEnumerator() { return new EncodedArrayEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator(this); } public (Vector4, Vector4) GetBounds() { return EncodedArrayUtils.GetBounds(this); } } /// /// Wraps a collection of Quaternion values and exposes it as a collection of Vector4 values /// struct _MapQuaternionToVector4 : IEncodedArray { public _MapQuaternionToVector4(QuaternionArray source) { _Accessor = source; } private QuaternionArray _Accessor; public int Count => _Accessor.Count; public Vector4 this[int index] { get { var v = _Accessor[index]; return new Vector4(v.X, v.Y, v.Z, v.W); } set => _Accessor[index] = new Quaternion(value.X, value.Y, value.Z, value.W); } public void CopyTo(ArraySegment dst) { EncodedArrayUtils.Copy(this, dst); } public IEnumerator GetEnumerator() { return new EncodedArrayEnumerator(this); } IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator(this); } public (Vector4, Vector4) GetBounds() { return EncodedArrayUtils.GetBounds(this); } } }