Cameras.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. using Microsoft.Xna.Framework;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.IO;
  7. namespace OpenVIII.Fields
  8. {
  9. /// <summary>
  10. /// Cameras
  11. /// </summary>
  12. /// <see cref="http://wiki.ffrtt.ru/index.php?title=FF7/Field/Camera_Matrix"/>
  13. /// <seealso cref="https://github.com/myst6re/deling/blob/master/files/CaFile.cpp"/>
  14. /// <seealso cref="https://github.com/myst6re/deling/blob/master/files/CaFile.h"/>
  15. /// <seealso cref="https://github.com/myst6re/deling/blob/master/WalkmeshGLWidget.cpp"/>
  16. /// <seealso cref="https://github.com/myst6re/deling/blob/master/WalkmeshGLWidget.h"/>
  17. public class Cameras : IList<Cameras.Camera>
  18. {
  19. #region Fields
  20. private const int altsizeofCamera = 0x26;
  21. private const int sizeofCamera = 0x28;
  22. private List<Camera> cameras;
  23. #endregion Fields
  24. #region Constructors
  25. public Cameras() => this.cameras = new List<Camera>(1);
  26. #endregion Constructors
  27. #region Properties
  28. public int Count => ((IList<Camera>)cameras).Count;
  29. public bool IsReadOnly => ((IList<Camera>)cameras).IsReadOnly;
  30. #endregion Properties
  31. #region Indexers
  32. public Camera this[int index] { get => ((IList<Camera>)cameras)[index]; set => ((IList<Camera>)cameras)[index] = value; }
  33. #endregion Indexers
  34. #region Methods
  35. public static Cameras Load(byte[] idb)
  36. {
  37. Cameras r = new Cameras();
  38. int _sizeofCamera = Cameras.sizeofCamera;
  39. int count = 0;
  40. if (idb.Length / sizeofCamera > idb.Length / altsizeofCamera)
  41. count = idb.Length / sizeofCamera;
  42. else
  43. {
  44. _sizeofCamera = altsizeofCamera;
  45. count = idb.Length / _sizeofCamera;
  46. }
  47. Debug.Assert(count >= 1);
  48. for (long offset = 0; offset < count * _sizeofCamera; offset += _sizeofCamera)
  49. r.Add(Camera.Load(idb, offset));
  50. return r;
  51. }
  52. public void Add(Camera item) => ((IList<Camera>)cameras).Add(item);
  53. public void Clear() => ((IList<Camera>)cameras).Clear();
  54. public bool Contains(Camera item) => ((IList<Camera>)cameras).Contains(item);
  55. public void CopyTo(Camera[] array, int arrayIndex) => ((IList<Camera>)cameras).CopyTo(array, arrayIndex);
  56. public IEnumerator<Camera> GetEnumerator() => ((IList<Camera>)cameras).GetEnumerator();
  57. IEnumerator IEnumerable.GetEnumerator() => ((IList<Camera>)cameras).GetEnumerator();
  58. public int IndexOf(Camera item) => ((IList<Camera>)cameras).IndexOf(item);
  59. public void Insert(int index, Camera item) => ((IList<Camera>)cameras).Insert(index, item);
  60. public bool Remove(Camera item) => ((IList<Camera>)cameras).Remove(item);
  61. public void RemoveAt(int index) => ((IList<Camera>)cameras).RemoveAt(index);
  62. #endregion Methods
  63. #region Classes
  64. /// <summary>
  65. /// Camera
  66. /// </summary>
  67. public class Camera
  68. {
  69. #region Fields
  70. private Vector3 _position;
  71. private Vector3 space;
  72. private Vector3[] xyz;
  73. #endregion Fields
  74. #region Constructors
  75. public Camera() => xyz = new Vector3[3];
  76. #endregion Constructors
  77. #region Properties
  78. private uint Blank { get; set; }
  79. public Vector3 Position { get => _position; private set => _position = value; }
  80. public Matrix RotationMatrix => new Matrix { Left = xyz[0], Down = xyz[1], Backward = xyz[2] };
  81. public Vector3[] XYZ { get => xyz; private set => xyz = value; }
  82. private short Z { get; set; }
  83. public float Zoom { get; private set; }
  84. private float Zoom2 { get; set; }
  85. public Vector3 Space { get => space; private set => space = value; }
  86. #endregion Properties
  87. #region Methods
  88. public static Camera Load(byte[] idb, long offset)
  89. {
  90. Camera r = new Camera();
  91. r.ReadData(idb, offset);
  92. return r;
  93. }
  94. public Matrix CreateLookAt() => Matrix.CreateLookAt(Position - xyz[2] * 2, xyz[2] + Position, xyz[1]);
  95. public Matrix CreateWorld() => Matrix.CreateWorld(Position, xyz[2], xyz[1]);
  96. private void ReadData(byte[] cab, long offset)
  97. {
  98. using (BinaryReader br = new BinaryReader(new MemoryStream(cab)))
  99. {
  100. br.BaseStream.Seek(offset, SeekOrigin.Begin);
  101. const float multipleconstant = 4096f;
  102. for (int i = 0; i < 3; i++)
  103. {
  104. xyz[i].X = br.ReadInt16() / multipleconstant;
  105. xyz[i].Y = br.ReadInt16() / multipleconstant;
  106. xyz[i].Z = br.ReadInt16() / multipleconstant;
  107. }
  108. Z = br.ReadInt16();
  109. space.X = br.ReadInt32();
  110. space.Y = br.ReadInt32();
  111. space.Z = br.ReadInt32();
  112. Blank = br.ReadUInt16();
  113. Zoom = br.ReadUInt16();
  114. Zoom2 = br.ReadUInt16();
  115. Zoom = Zoom2 = Math.Max(Zoom, Zoom2);
  116. var r = RotationMatrix;
  117. space /= 4096f;
  118. _position = -(space * xyz[0] + space * xyz[1] + space * xyz[2]);
  119. //_position = -(space * r.Right + space * r.Up + space * r.Backward);
  120. //_position = Vector3.Transform(space/4096f, r);
  121. //_position = new Vector3
  122. //{
  123. // X = -(space.X * xyz[0].X + space.X * xyz[1].X + space.X * xyz[2].X),
  124. // Y = -(space.Y * xyz[0].Y + space.Y * xyz[1].Y + space.Y * xyz[2].Y),
  125. // Z = -(space.Z * xyz[0].Z + space.Z * xyz[1].Z + space.Z * xyz[2].Z),
  126. //};
  127. }
  128. }
  129. #endregion Methods
  130. }
  131. #endregion Classes
  132. }
  133. }