FloatingArrays.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Numerics;
  5. using System.Collections;
  6. using System.Linq;
  7. namespace glTF2Sharp.Memory
  8. {
  9. using BYTES = ArraySegment<Byte>;
  10. using ENCODING = Schema2.ComponentType;
  11. /// <summary>
  12. /// Helper structure to access any Byte array as an array of floating Singles/>
  13. /// </summary>
  14. struct FloatingAccessor
  15. {
  16. #region constructors
  17. public FloatingAccessor(Byte[] data, ENCODING encoding, Boolean normalized)
  18. : this(new BYTES(data), encoding, normalized) { }
  19. public FloatingAccessor(BYTES data, ENCODING encoding, Boolean normalized)
  20. {
  21. this._Data = data;
  22. this._Getter = null;
  23. this._Setter = null;
  24. if (encoding == ENCODING.FLOAT)
  25. {
  26. this._Setter = this._SetValue<Single>;
  27. this._Getter = this._GetValue<Single>;
  28. }
  29. else
  30. {
  31. if (normalized)
  32. {
  33. switch (encoding)
  34. {
  35. case ENCODING.BYTE:
  36. {
  37. this._Setter = this._SetNormalizedS8;
  38. this._Getter = this._GetNormalizedS8;
  39. break;
  40. }
  41. case ENCODING.UNSIGNED_BYTE:
  42. {
  43. this._Setter = this._SetNormalizedU8;
  44. this._Getter = this._GetNormalizedU8;
  45. break;
  46. }
  47. case ENCODING.SHORT:
  48. {
  49. this._Setter = this._SetNormalizedS16;
  50. this._Getter = this._GetNormalizedS16;
  51. break;
  52. }
  53. case ENCODING.UNSIGNED_SHORT:
  54. {
  55. this._Setter = this._SetNormalizedU16;
  56. this._Getter = this._GetNormalizedU16;
  57. break;
  58. }
  59. default: throw new ArgumentException(nameof(encoding));
  60. }
  61. }
  62. else
  63. {
  64. switch (encoding)
  65. {
  66. case ENCODING.BYTE:
  67. {
  68. this._Setter = this._SetValueS8;
  69. this._Getter = this._GetValueS8;
  70. break;
  71. }
  72. case ENCODING.UNSIGNED_BYTE:
  73. {
  74. this._Setter = this._SetValueU8;
  75. this._Getter = this._GetValueU8;
  76. break;
  77. }
  78. case ENCODING.SHORT:
  79. {
  80. this._Setter = this._SetValueS16;
  81. this._Getter = this._GetValueS16;
  82. break;
  83. }
  84. case ENCODING.UNSIGNED_SHORT:
  85. {
  86. this._Setter = this._SetValueU16;
  87. this._Getter = this._GetValueU16;
  88. break;
  89. }
  90. case ENCODING.UNSIGNED_INT:
  91. {
  92. this._Setter = this._SetValueU32;
  93. this._Getter = this._GetValueU32;
  94. break;
  95. }
  96. case ENCODING.FLOAT:
  97. break;
  98. default: throw new ArgumentException(nameof(encoding));
  99. }
  100. }
  101. }
  102. }
  103. private Single _GetValueU8(int byteOffset, int index) { return _GetValue<Byte>(byteOffset, index); }
  104. private void _SetValueU8(int byteOffset, int index, Single value) { _SetValue<Byte>(byteOffset, index, (Byte)value); }
  105. private Single _GetValueS8(int byteOffset, int index) { return _GetValue<SByte>(byteOffset, index); }
  106. private void _SetValueS8(int byteOffset, int index, Single value) { _SetValue<SByte>(byteOffset, index, (SByte)value); }
  107. private Single _GetValueU16(int byteOffset, int index) { return _GetValue<UInt16>(byteOffset, index); }
  108. private void _SetValueU16(int byteOffset, int index, Single value) { _SetValue<UInt16>(byteOffset, index, (UInt16)value); }
  109. private Single _GetValueS16(int byteOffset, int index) { return _GetValue<Int16>(byteOffset, index); }
  110. private void _SetValueS16(int byteOffset, int index, Single value) { _SetValue<Int16>(byteOffset, index, (Int16)value); }
  111. private Single _GetValueU32(int byteOffset, int index) { return _GetValue<UInt32>(byteOffset, index); }
  112. private void _SetValueU32(int byteOffset, int index, Single value) { _SetValue<UInt32>(byteOffset, index, (UInt32)value); }
  113. private Single _GetNormalizedU8(int byteOffset, int index) { return _GetValueU8(byteOffset, index) / 255.0f; }
  114. private void _SetNormalizedU8(int byteOffset, int index, Single value) { _SetValueU8(byteOffset, index, value * 255.0f); }
  115. private Single _GetNormalizedS8(int byteOffset, int index) { return Math.Max(_GetValueS8(byteOffset, index) / 127.0f, -1); }
  116. private void _SetNormalizedS8(int byteOffset, int index, Single value) { _SetValueS8(byteOffset, index, (Single)Math.Round(value * 127.0f)); }
  117. private Single _GetNormalizedU16(int byteOffset, int index) { return _GetValueU16(byteOffset, index) / 65535.0f; }
  118. private void _SetNormalizedU16(int byteOffset, int index, Single value) { _SetValueU16(byteOffset, index, value * 65535.0f); }
  119. private Single _GetNormalizedS16(int byteOffset, int index) { return Math.Max(_GetValueS16(byteOffset, index) / 32767.0f, -1); }
  120. private void _SetNormalizedS16(int byteOffset, int index, Single value) { _SetValueS16(byteOffset, index, (Single)Math.Round(value * 32767.0f)); }
  121. private T _GetValue<T>(int byteOffset, int index) where T : unmanaged
  122. {
  123. return System.Runtime.InteropServices.MemoryMarshal.Cast<Byte, T>(_Data.AsSpan(byteOffset))[index];
  124. }
  125. private void _SetValue<T>(int byteOffset, int index, T value) where T : unmanaged
  126. {
  127. System.Runtime.InteropServices.MemoryMarshal.Cast<Byte, T>(_Data.AsSpan(byteOffset))[index] = value;
  128. }
  129. #endregion
  130. #region data
  131. delegate Single _GetterCallback(int byteOffset, int index);
  132. delegate void _SetterCallback(int byteOffset, int index, Single value);
  133. private readonly BYTES _Data;
  134. private readonly _GetterCallback _Getter;
  135. private readonly _SetterCallback _Setter;
  136. #endregion
  137. #region API
  138. public int ByteLength => _Data.Count;
  139. public Single this[int index]
  140. {
  141. get => _Getter(0, index);
  142. set => _Setter(0, index, value);
  143. }
  144. public Single this[int byteOffset, int index]
  145. {
  146. get => _Getter(byteOffset, index);
  147. set => _Setter(byteOffset, index, value);
  148. }
  149. #endregion
  150. }
  151. /// <summary>
  152. /// Wraps an encoded byte array and exposes it as a collection of Single Scalar values
  153. /// </summary>
  154. [System.Diagnostics.DebuggerDisplay("Scalar Accessor {Count}")]
  155. public struct ScalarArray : IEncodedArray<Single>
  156. {
  157. #region constructors
  158. public ScalarArray(Byte[] data, int byteStride, ENCODING encoding, Boolean normalized)
  159. : this(new BYTES(data), byteStride, encoding, normalized) { }
  160. public ScalarArray(BYTES data, int byteStride, ENCODING encoding, Boolean normalized)
  161. {
  162. var len = encoding.ByteLength() * 1;
  163. _Accesor = new FloatingAccessor(data, encoding, normalized);
  164. _ByteStride = Math.Max(len, byteStride);
  165. _ItemCount = _Accesor.ByteLength / _ByteStride;
  166. if ((_Accesor.ByteLength % _ByteStride) >= len) ++_ItemCount;
  167. }
  168. #endregion
  169. #region data
  170. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  171. private FloatingAccessor _Accesor;
  172. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  173. private readonly int _ByteStride;
  174. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  175. private readonly int _ItemCount;
  176. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
  177. private Single[] _DebugItems => this.ToArray();
  178. #endregion
  179. #region API
  180. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  181. public int Count => _ItemCount;
  182. public Single this[int index]
  183. {
  184. get => _Accesor[index * _ByteStride, 0];
  185. set => _Accesor[index * _ByteStride, 0] = value;
  186. }
  187. public void CopyTo(ArraySegment<Single> dst) { EncodedArrayUtils.Copy<Single>(this, dst); }
  188. public IEnumerator<Single> GetEnumerator() { return new EncodedArrayEnumerator<Single>(this); }
  189. IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Single>(this); }
  190. public (Single, Single) GetBounds() { return EncodedArrayUtils.GetBounds(this); }
  191. public IEncodedArray<Vector4> AsVector4() { return new _MapScalarToVector4(this); }
  192. #endregion
  193. }
  194. /// <summary>
  195. /// Wraps an encoded byte array and exposes it as a collection of Vector2 values
  196. /// </summary>
  197. [System.Diagnostics.DebuggerDisplay("Vector2 Accessor {Count}")]
  198. public struct Vector2Array : IEncodedArray<Vector2>
  199. {
  200. #region constructors
  201. public Vector2Array(Byte[] data, int byteStride, ENCODING encoding, Boolean normalized)
  202. : this(new BYTES(data),byteStride,encoding,normalized) { }
  203. public Vector2Array(BYTES data, int byteStride, ENCODING encoding, Boolean normalized)
  204. {
  205. var len = encoding.ByteLength() * 2;
  206. _Accesor = new FloatingAccessor(data, encoding, normalized);
  207. _ByteStride = Math.Max(len, byteStride);
  208. _ItemCount = _Accesor.ByteLength / _ByteStride;
  209. if ((_Accesor.ByteLength % _ByteStride) >= len) ++_ItemCount;
  210. }
  211. #endregion
  212. #region data
  213. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  214. private FloatingAccessor _Accesor;
  215. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  216. private readonly int _ByteStride;
  217. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  218. private readonly int _ItemCount;
  219. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
  220. private Vector2[] _DebugItems => this.ToArray();
  221. #endregion
  222. #region API
  223. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  224. public int Count => _ItemCount;
  225. public Vector2 this[int index]
  226. {
  227. get
  228. {
  229. index *= _ByteStride;
  230. return new Vector2(_Accesor[index, 0], _Accesor[index, 1]);
  231. }
  232. set
  233. {
  234. index *= _ByteStride;
  235. _Accesor[index, 0] = value.X;
  236. _Accesor[index, 1] = value.Y;
  237. }
  238. }
  239. public void CopyTo(ArraySegment<Vector2> dst) { EncodedArrayUtils.Copy<Vector2>(this, dst); }
  240. public IEnumerator<Vector2> GetEnumerator() { return new EncodedArrayEnumerator<Vector2>(this); }
  241. IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Vector2>(this); }
  242. public (Vector2, Vector2) GetBounds() { return EncodedArrayUtils.GetBounds(this); }
  243. public IEncodedArray<Vector4> AsVector4() { return new _MapVector2ToVector4(this); }
  244. #endregion
  245. }
  246. /// <summary>
  247. /// Wraps an encoded byte array and exposes it as a collection of Vector3 values
  248. /// </summary>
  249. [System.Diagnostics.DebuggerDisplay("Vector3 Accessor {Count}")]
  250. public struct Vector3Array: IEncodedArray<Vector3>
  251. {
  252. #region constructors
  253. public Vector3Array(Byte[] data, int byteStride, ENCODING encoding, Boolean normalized)
  254. : this(new BYTES(data), byteStride, encoding, normalized) { }
  255. public Vector3Array(BYTES data, int byteStride, ENCODING encoding, Boolean normalized)
  256. {
  257. var len = encoding.ByteLength() * 3;
  258. _Accesor = new FloatingAccessor(data, encoding, normalized);
  259. _ByteStride = Math.Max(len, byteStride);
  260. _ItemCount = _Accesor.ByteLength / _ByteStride;
  261. if ((_Accesor.ByteLength % _ByteStride) >= len) ++_ItemCount;
  262. }
  263. #endregion
  264. #region data
  265. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  266. private FloatingAccessor _Accesor;
  267. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  268. private readonly int _ByteStride;
  269. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  270. private readonly int _ItemCount;
  271. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
  272. private Vector3[] _DebugItems => this.ToArray();
  273. #endregion
  274. #region API
  275. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  276. public int Count => _ItemCount;
  277. public Vector3 this[int index]
  278. {
  279. get
  280. {
  281. index *= _ByteStride;
  282. return new Vector3(_Accesor[index, 0], _Accesor[index, 1], _Accesor[index, 2]);
  283. }
  284. set
  285. {
  286. index *= _ByteStride;
  287. _Accesor[index, 0] = value.X;
  288. _Accesor[index, 1] = value.Y;
  289. _Accesor[index, 2] = value.Z;
  290. }
  291. }
  292. public void CopyTo(ArraySegment<Vector3> dst) { EncodedArrayUtils.Copy<Vector3>(this, dst); }
  293. public IEnumerator<Vector3> GetEnumerator() { return new EncodedArrayEnumerator<Vector3>(this); }
  294. IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Vector3>(this); }
  295. public (Vector3, Vector3) GetBounds() { return EncodedArrayUtils.GetBounds(this); }
  296. public IEncodedArray<Vector4> AsVector4() { return new _MapVector3ToVector4(this); }
  297. #endregion
  298. }
  299. /// <summary>
  300. /// Wraps an encoded byte array and exposes it as a collection of Vector4 values
  301. /// </summary>
  302. [System.Diagnostics.DebuggerDisplay("Vector4 Accessor {Count}")]
  303. public struct Vector4Array: IEncodedArray<Vector4>
  304. {
  305. #region constructors
  306. public Vector4Array(Byte[] data, int byteStride, ENCODING encoding, Boolean normalized)
  307. : this(new BYTES(data), byteStride, encoding, normalized) { }
  308. public Vector4Array(BYTES data, int byteStride, ENCODING encoding, Boolean normalized)
  309. {
  310. var len = encoding.ByteLength() * 4;
  311. _Accesor = new FloatingAccessor(data, encoding, normalized);
  312. _ByteStride = Math.Max(len, byteStride);
  313. _ItemCount = _Accesor.ByteLength / _ByteStride;
  314. if ((_Accesor.ByteLength % _ByteStride) >= len) ++_ItemCount;
  315. }
  316. #endregion
  317. #region data
  318. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  319. private FloatingAccessor _Accesor;
  320. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  321. private readonly int _ByteStride;
  322. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  323. private readonly int _ItemCount;
  324. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
  325. private Vector4[] _DebugItems => this.ToArray();
  326. #endregion
  327. #region API
  328. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  329. public int Count => _ItemCount;
  330. public Vector4 this[int index]
  331. {
  332. get
  333. {
  334. index *= _ByteStride;
  335. return new Vector4(_Accesor[index, 0], _Accesor[index, 1], _Accesor[index, 2], _Accesor[index, 3]);
  336. }
  337. set
  338. {
  339. index *= _ByteStride;
  340. _Accesor[index, 0] = value.X;
  341. _Accesor[index, 1] = value.Y;
  342. _Accesor[index, 2] = value.Z;
  343. _Accesor[index, 3] = value.W;
  344. }
  345. }
  346. public void CopyTo(ArraySegment<Vector4> dst) { EncodedArrayUtils.Copy<Vector4>(this, dst); }
  347. public IEnumerator<Vector4> GetEnumerator() { return new EncodedArrayEnumerator<Vector4>(this); }
  348. IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Vector4>(this); }
  349. public (Vector4, Vector4) GetBounds() { return EncodedArrayUtils.GetBounds(this); }
  350. public IEncodedArray<Vector4> AsVector4() { return this; }
  351. #endregion
  352. }
  353. /// <summary>
  354. /// Wraps an encoded byte array and exposes it as a collection of Quaternion values
  355. /// </summary>
  356. [System.Diagnostics.DebuggerDisplay("Quaternion Accessor {Count}")]
  357. public struct QuaternionArray : IEncodedArray<Quaternion>
  358. {
  359. #region constructors
  360. public QuaternionArray(Byte[] data, int byteStride, ENCODING encoding, Boolean normalized)
  361. : this(new BYTES(data), byteStride, encoding, normalized) { }
  362. public QuaternionArray(BYTES data, int byteStride, ENCODING encoding, Boolean normalized)
  363. {
  364. var len = encoding.ByteLength() * 4;
  365. _Accesor = new FloatingAccessor(data, encoding, normalized);
  366. _ByteStride = Math.Max(len, byteStride);
  367. _ItemCount = _Accesor.ByteLength / _ByteStride;
  368. if ((_Accesor.ByteLength % _ByteStride) >= len) ++_ItemCount;
  369. }
  370. #endregion
  371. #region data
  372. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  373. private FloatingAccessor _Accesor;
  374. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  375. private readonly int _ByteStride;
  376. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  377. private readonly int _ItemCount;
  378. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
  379. private Quaternion[] _DebugItems => this.ToArray();
  380. #endregion
  381. #region API
  382. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  383. public int Count => _ItemCount;
  384. public Quaternion this[int index]
  385. {
  386. get
  387. {
  388. index *= _ByteStride;
  389. return new Quaternion(_Accesor[index, 0], _Accesor[index, 1], _Accesor[index, 2], _Accesor[index, 3]);
  390. }
  391. set
  392. {
  393. index *= _ByteStride;
  394. _Accesor[index, 0] = value.X;
  395. _Accesor[index, 1] = value.Y;
  396. _Accesor[index, 2] = value.Z;
  397. _Accesor[index, 3] = value.W;
  398. }
  399. }
  400. public void CopyTo(ArraySegment<Quaternion> dst) { EncodedArrayUtils.Copy<Quaternion>(this, dst); }
  401. public IEnumerator<Quaternion> GetEnumerator() { return new EncodedArrayEnumerator<Quaternion>(this); }
  402. IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Quaternion>(this); }
  403. public (Quaternion, Quaternion) GetBounds() { throw new NotImplementedException(); }
  404. public IEncodedArray<Vector4> AsVector4() { return new _MapQuaternionToVector4(this); }
  405. #endregion
  406. }
  407. /// <summary>
  408. /// Wraps an encoded byte array and exposes it as a collection of Matrix4x4 values
  409. /// </summary>
  410. [System.Diagnostics.DebuggerDisplay("MAtrix4x4 Accessor {Count}")]
  411. public struct Matrix4x4Array : IEncodedArray<Matrix4x4>
  412. {
  413. #region constructors
  414. public Matrix4x4Array(Byte[] data, int byteStride, ENCODING encoding, Boolean normalized)
  415. : this(new BYTES(data), byteStride, encoding, normalized) { }
  416. public Matrix4x4Array(BYTES data, int byteStride, ENCODING encoding, Boolean normalized)
  417. {
  418. var len = encoding.ByteLength() * 16;
  419. _Accesor = new FloatingAccessor(data, encoding, normalized);
  420. _ByteStride = Math.Max(len, byteStride);
  421. _ItemCount = _Accesor.ByteLength / _ByteStride;
  422. if ((_Accesor.ByteLength % _ByteStride) >= len) ++_ItemCount;
  423. }
  424. #endregion
  425. #region data
  426. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  427. private FloatingAccessor _Accesor;
  428. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  429. private readonly int _ByteStride;
  430. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  431. private readonly int _ItemCount;
  432. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.RootHidden)]
  433. private Matrix4x4[] _DebugItems => this.ToArray();
  434. #endregion
  435. #region API
  436. [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
  437. public int Count => _ItemCount;
  438. public Matrix4x4 this[int index]
  439. {
  440. get
  441. {
  442. index *= _ByteStride;
  443. return new Matrix4x4
  444. (
  445. _Accesor[index, 0], _Accesor[index, 1], _Accesor[index, 2], _Accesor[index, 3],
  446. _Accesor[index, 4], _Accesor[index, 5], _Accesor[index, 6], _Accesor[index, 7],
  447. _Accesor[index, 8], _Accesor[index, 9], _Accesor[index, 10], _Accesor[index, 11],
  448. _Accesor[index, 12], _Accesor[index, 13], _Accesor[index, 14], _Accesor[index, 15]
  449. );
  450. }
  451. set
  452. {
  453. index *= _ByteStride;
  454. _Accesor[index, 0] = value.M11;
  455. _Accesor[index, 1] = value.M12;
  456. _Accesor[index, 2] = value.M13;
  457. _Accesor[index, 3] = value.M14;
  458. _Accesor[index, 4] = value.M21;
  459. _Accesor[index, 5] = value.M22;
  460. _Accesor[index, 6] = value.M23;
  461. _Accesor[index, 7] = value.M24;
  462. _Accesor[index, 8] = value.M31;
  463. _Accesor[index, 9] = value.M32;
  464. _Accesor[index, 10] = value.M33;
  465. _Accesor[index, 11] = value.M34;
  466. _Accesor[index, 12] = value.M41;
  467. _Accesor[index, 13] = value.M42;
  468. _Accesor[index, 14] = value.M43;
  469. _Accesor[index, 15] = value.M44;
  470. }
  471. }
  472. public void CopyTo(ArraySegment<Matrix4x4> dst) { EncodedArrayUtils.Copy<Matrix4x4>(this, dst); }
  473. public IEnumerator<Matrix4x4> GetEnumerator() { return new EncodedArrayEnumerator<Matrix4x4>(this); }
  474. IEnumerator IEnumerable.GetEnumerator() { return new EncodedArrayEnumerator<Matrix4x4>(this); }
  475. public (Matrix4x4, Matrix4x4) GetBounds() { throw new NotImplementedException(); }
  476. #endregion
  477. }
  478. }