module_world_debug.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. using Microsoft.Xna.Framework;
  2. using Microsoft.Xna.Framework.Graphics;
  3. using Microsoft.Xna.Framework.Input;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Runtime.InteropServices;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace FF8
  12. {
  13. class Module_world_debug
  14. {
  15. private static Matrix projectionMatrix, viewMatrix, worldMatrix;
  16. private static float degrees, Yshift;
  17. private static readonly float camDistance = 10.0f;
  18. private static readonly float renderCamDistance = 1200.0f;
  19. private static Vector3 camPosition, camTarget;
  20. public static BasicEffect effect;
  21. public static AlphaTestEffect ate;
  22. private enum _worldState
  23. {
  24. _0init,
  25. _1debugFly
  26. }
  27. private enum MiniMapState
  28. {
  29. noMinimap,
  30. planet,
  31. rectangle,
  32. fullscreen
  33. }
  34. //DEBUG
  35. private const float WORLD_SCALE_MODEL = 16f;
  36. private static List<Texture2D[]> textures;
  37. private static List<Texture2D[]> wm38textures;
  38. private static List<Texture2D[]> wm39textures;
  39. private static List<Texture2D[]> charaOneTextures;
  40. private static readonly int renderDistance = 4;
  41. private static readonly float FOV = 60;
  42. private static Vector2 segmentPosition;
  43. private static Debug_MCH[] mchEntities;
  44. private static byte[] wmx;
  45. static float DEBUGshit = FOV;
  46. private static int GetSegment(int segID) => segID * 0x9000;
  47. private static Segment[] segments;
  48. private struct Segment
  49. {
  50. public int segmentId;
  51. public SegHeader headerData;
  52. public Block[] block;
  53. }
  54. private struct Block
  55. {
  56. public byte polyCount;
  57. public byte vertCount;
  58. public byte normalCount;
  59. public byte unkPadd;
  60. public Polygon[] polygons;
  61. public Vertex[] vertices;
  62. public Normal[] normals;
  63. public int unkPadd2;
  64. }
  65. [StructLayout(LayoutKind.Sequential, Size = 68, Pack = 1)]
  66. private struct SegHeader
  67. {
  68. public uint groupId;
  69. [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
  70. public uint[] blockOffsets;
  71. }
  72. private struct Polygon
  73. {
  74. public byte F1, F2, F3, N1, N2, N3, U1, V1, U2, V2, U3, V3, TPage_clut, groundtype, TextureSwitch, unk2;
  75. public byte TPage { get => (byte)((TPage_clut >> 4) & 0x0F); }
  76. public byte Clut { get => (byte)(TPage_clut & 0x0F); }
  77. //public byte TPage_clut1 { set => TPage_clut = value; }
  78. }
  79. private struct Vertex
  80. {
  81. public short X;
  82. private short Z;
  83. public short Y;
  84. private short W;
  85. public short Z1 { get => (short)(Z * -1); set => Z = value; }
  86. }
  87. private struct Normal /*: Vertex we can't inherit struct in C#*/
  88. {
  89. public short X;
  90. private short Z;
  91. private short Y;
  92. private short W;
  93. public short Z1 { get => (short)(Z * -1); set => Z = value; }
  94. }
  95. private static _worldState worldState;
  96. private static MiniMapState MapState = MiniMapState.rectangle;
  97. public static void Update()
  98. {
  99. switch (worldState)
  100. {
  101. case _worldState._0init:
  102. InitWorld();
  103. break;
  104. case _worldState._1debugFly:
  105. FPSCamera();
  106. break;
  107. }
  108. }
  109. private static void InitWorld()
  110. {
  111. Input.OverrideLockMouse = true;
  112. Input.CurrentMode = Input.MouseLockMode.Center;
  113. //init renderer
  114. effect = new BasicEffect(Memory.graphics.GraphicsDevice);
  115. effect.EnableDefaultLighting();
  116. camTarget = new Vector3(0, 0f, 0f);
  117. camPosition = new Vector3(-9166f, 112f, -4570f);
  118. projectionMatrix = Matrix.CreatePerspectiveFieldOfView(
  119. MathHelper.ToRadians(60),
  120. Memory.graphics.GraphicsDevice.DisplayMode.AspectRatio,
  121. 1f, 1000f);
  122. viewMatrix = Matrix.CreateLookAt(camPosition, camTarget,
  123. new Vector3(0f, 1f, 0f));// Y up
  124. worldMatrix = Matrix.CreateWorld(camTarget, Vector3.
  125. Forward, Vector3.Up);
  126. //temporarily disabling this, because I'm getting more and more tired of this music playing over and over when debugging
  127. //Memory.musicIndex = 30;
  128. //init_debugger_Audio.PlayMusic();
  129. ate = new AlphaTestEffect(Memory.graphics.GraphicsDevice)
  130. {
  131. Projection = projectionMatrix,
  132. View = viewMatrix,
  133. World = worldMatrix,
  134. FogEnabled = true,
  135. FogColor = Color.CornflowerBlue.ToVector3(),
  136. FogStart = 9.75f,
  137. FogEnd = 1000.00f
  138. };
  139. ReadWMX();
  140. worldState++;
  141. return;
  142. }
  143. private static void ReadWMX()
  144. {
  145. ArchiveWorker aw = new ArchiveWorker(Memory.Archives.A_WORLD);
  146. string wmxPath = aw.GetListOfFiles().Where(x => x.ToLower().Contains("wmx.obj")).Select(x => x).First();
  147. string texlPath = aw.GetListOfFiles().Where(x => x.ToLower().Contains("texl.obj")).Select(x => x).First();
  148. string wmPath = aw.GetListOfFiles().Where(x => x.ToLower().Contains("wmsetus.obj")).Select(x => x).First();
  149. string charaOne = aw.GetListOfFiles().Where(x => x.ToLower().Contains("chara.one")).Select(x => x).First();
  150. wmx = ArchiveWorker.GetBinaryFile(Memory.Archives.A_WORLD, wmxPath);
  151. byte[] texl = ArchiveWorker.GetBinaryFile(Memory.Archives.A_WORLD, texlPath);
  152. byte[] charaOneB = ArchiveWorker.GetBinaryFile(Memory.Archives.A_WORLD, charaOne);
  153. ReadCharaOne(charaOneB);
  154. charaOneB = null; //GC
  155. ReadWmSet(ArchiveWorker.GetBinaryFile(Memory.Archives.A_WORLD, wmPath));
  156. ReadTextures(texl);
  157. texl = null; //GC
  158. segments = new Segment[835];
  159. using (MemoryStream ms = new MemoryStream(wmx))
  160. using (BinaryReader br = new BinaryReader(ms))
  161. for (int i = 0; i < segments.Length; i++)
  162. {
  163. ms.Seek(GetSegment(i), SeekOrigin.Begin);
  164. segments[i] = new Segment { segmentId = i, headerData = MakiExtended.ByteArrayToStructure<SegHeader>(br.ReadBytes(68)), block = new Block[16] };
  165. ms.Seek(GetSegment(i), SeekOrigin.Begin);
  166. for (int n = 0; n < segments[i].block.Length; n++)
  167. {
  168. ms.Seek(segments[i].headerData.blockOffsets[n] + GetSegment(i), SeekOrigin.Begin);
  169. segments[i].block[n] = new Block { polyCount = br.ReadByte(), vertCount = br.ReadByte(), normalCount = br.ReadByte(), unkPadd = br.ReadByte() };
  170. segments[i].block[n].polygons = new Polygon[segments[i].block[n].polyCount];
  171. segments[i].block[n].vertices = new Vertex[segments[i].block[n].vertCount];
  172. segments[i].block[n].normals = new Normal[segments[i].block[n].normalCount];
  173. for (int k = 0; k < segments[i].block[n].polyCount; k++)
  174. segments[i].block[n].polygons[k] = MakiExtended.ByteArrayToStructure<Polygon>(br.ReadBytes(16));
  175. for (int k = 0; k < segments[i].block[n].vertCount; k++)
  176. segments[i].block[n].vertices[k] = MakiExtended.ByteArrayToStructure<Vertex>(br.ReadBytes(8));
  177. for (int k = 0; k < segments[i].block[n].normalCount; k++)
  178. segments[i].block[n].normals[k] = MakiExtended.ByteArrayToStructure<Normal>(br.ReadBytes(8));
  179. segments[i].block[n].unkPadd2 = br.ReadInt32();
  180. }
  181. }
  182. }
  183. //TODO - so parsing is done
  184. private static void ReadCharaOne(byte[] charaOneB)
  185. {
  186. List<Debug_MCH> mchs = new List<Debug_MCH>();
  187. using (MemoryStream ms = new MemoryStream(charaOneB))
  188. using (BinaryReader br = new BinaryReader(ms))
  189. {
  190. uint eof = br.ReadUInt32();
  191. TIM2 tim;
  192. while (ms.CanRead)
  193. if (ms.Position > ms.Length)
  194. break;
  195. else if (BitConverter.ToUInt16(charaOneB, (int)ms.Position) == 0)
  196. ms.Seek(2, SeekOrigin.Current);
  197. else if (br.ReadUInt64() == 0x0000000800000010)
  198. {
  199. ms.Seek(-8, SeekOrigin.Current);
  200. tim = new TIM2(charaOneB, (uint)ms.Position);
  201. ms.Seek(tim.GetHeight * tim.GetWidth / 2 + 64, SeekOrigin.Current); //i.e. 64*20=1280/2=640 + 64= 704 + eof
  202. if (charaOneTextures == null)
  203. charaOneTextures = new List<Texture2D[]>();
  204. Texture2D[] _2d = { new Texture2D(Memory.graphics.GraphicsDevice, tim.GetWidth, tim.GetHeight, false, SurfaceFormat.Color) };
  205. _2d[0].SetData(tim.CreateImageBuffer(tim.GetClutColors(0), true));
  206. charaOneTextures.Add(_2d);
  207. }
  208. else //is geometry structure
  209. {
  210. ms.Seek(-8, SeekOrigin.Current);
  211. mchs.Add(new Debug_MCH(ms, br));
  212. }
  213. }
  214. mchEntities = mchs.ToArray();
  215. }
  216. #region wmset
  217. private static void ReadWmSet(byte[] v)
  218. {
  219. int[] sections = new int[48];
  220. using (MemoryStream ms = new MemoryStream(v))
  221. using (BinaryReader br = new BinaryReader(ms))
  222. {
  223. for (int i = 0; i < sections.Length; i++)
  224. sections[i] = br.ReadInt32();
  225. Wm_s38(ms, br, sections, v);
  226. Wm_s39(ms, br, sections, v);
  227. }
  228. }
  229. private static void Wm_s39(MemoryStream ms, BinaryReader br, int[] sec, byte[] v)
  230. {
  231. ms.Seek(sec[39 - 1], SeekOrigin.Begin);
  232. List<int> wm39sections = new List<int>();
  233. int eof = -1;
  234. while ((eof = br.ReadInt32()) != 0)
  235. wm39sections.Add(eof);
  236. wm39textures = new List<Texture2D[]>();
  237. for (int i = 0; i < wm39sections.Count; i++)
  238. {
  239. TIM2 tim = new TIM2(v, (uint)(sec[39 - 1] + wm39sections[i]));
  240. wm39textures.Add(new Texture2D[tim.GetClutCount]);
  241. for (ushort k = 0; k < wm39textures[i].Length; k++)
  242. {
  243. wm39textures[i][k] = new Texture2D(Memory.graphics.GraphicsDevice, tim.GetWidth, tim.GetHeight, false, SurfaceFormat.Color);
  244. wm39textures[i][k].SetData(tim.CreateImageBuffer(tim.GetClutColors(k), true));
  245. }
  246. }
  247. }
  248. private static void Wm_s38(MemoryStream ms, BinaryReader br, int[] sec, byte[] v)
  249. {
  250. ms.Seek(sec[38 - 1], SeekOrigin.Begin);
  251. List<int> wm38sections = new List<int>();
  252. int eof = -1;
  253. while ((eof = br.ReadInt32()) != 0)
  254. wm38sections.Add(eof);
  255. wm38textures = new List<Texture2D[]>();
  256. for (int i = 0; i < wm38sections.Count; i++)
  257. {
  258. TIM2 tim = new TIM2(v, (uint)(sec[38 - 1] + wm38sections[i]));
  259. wm38textures.Add(new Texture2D[tim.GetClutCount]);
  260. for (ushort k = 0; k < wm38textures[i].Length; k++)
  261. {
  262. wm38textures[i][k] = new Texture2D(Memory.graphics.GraphicsDevice, tim.GetWidth, tim.GetHeight, false, SurfaceFormat.Color);
  263. wm38textures[i][k].SetData(tim.CreateImageBuffer(tim.GetClutColors(k), true));
  264. }
  265. }
  266. }
  267. #endregion
  268. private static void ReadTextures(byte[] texl)
  269. {
  270. MemoryStream ms = new MemoryStream(texl);
  271. BinaryReader br = new BinaryReader(ms);
  272. textures = new List<Texture2D[]>(); //20
  273. for (int i = 0; i < 20; i++)
  274. {
  275. int timOffset = i * 0x12800;
  276. TIM2 tim = new TIM2(texl, (uint)timOffset);
  277. textures.Add(new Texture2D[tim.GetClutCount]);
  278. for (ushort k = 0; k < textures[i].Length; k++)
  279. {
  280. textures[i][k] = new Texture2D(Memory.graphics.GraphicsDevice, tim.GetWidth, tim.GetHeight, false, SurfaceFormat.Color);
  281. textures[i][k].SetData(tim.CreateImageBuffer(tim.GetClutColors(k), true));
  282. }
  283. }
  284. br.Close();
  285. ms.Close();
  286. br.Dispose();
  287. ms.Dispose();
  288. }
  289. const float defaultmaxMoveSpeed = 1f;
  290. const float MoveSpeedChange = 1f;
  291. static float maxMoveSpeed = defaultmaxMoveSpeed;
  292. const float maxLookSpeed = 0.25f;
  293. public static void FPSCamera()
  294. {
  295. #region FPScamera
  296. float x_shift = 0.0f, y_shift = 0.0f, leftdistX = 0.0f, leftdistY = 0.0f;
  297. //speedcontrols
  298. //+ to increase
  299. //- to decrease
  300. //* to reset
  301. if (Input.Button(Keys.OemPlus) || Input.Button(Keys.Add))
  302. {
  303. maxMoveSpeed += MoveSpeedChange;
  304. }
  305. if (Input.Button(Keys.OemMinus) || Input.Button(Keys.Subtract))
  306. {
  307. maxMoveSpeed -= MoveSpeedChange;
  308. if (maxMoveSpeed < defaultmaxMoveSpeed) maxMoveSpeed = defaultmaxMoveSpeed;
  309. }
  310. if (Input.Button(Keys.Multiply)) maxMoveSpeed = defaultmaxMoveSpeed;
  311. //speed is effected by the milliseconds between frames. so alittle goes a long way. :P
  312. x_shift = Input.Distance(Buttons.MouseXjoy, maxLookSpeed);
  313. y_shift = Input.Distance(Buttons.MouseYjoy, maxLookSpeed);
  314. leftdistX = Math.Abs(Input.Distance(Buttons.LeftStickX, maxMoveSpeed));
  315. leftdistY = Math.Abs(Input.Distance(Buttons.LeftStickY, maxMoveSpeed));
  316. x_shift += Input.Distance(Buttons.RightStickX, maxLookSpeed);
  317. y_shift += Input.Distance(Buttons.RightStickY, maxLookSpeed);
  318. Yshift -= y_shift;
  319. degrees = (degrees + (int)x_shift) % 360;
  320. Yshift = MathHelper.Clamp(Yshift, -80, 80);
  321. if (leftdistY == 0)
  322. {
  323. leftdistY = Input.Distance(maxMoveSpeed);
  324. }
  325. if (leftdistX == 0)
  326. {
  327. leftdistX = Input.Distance(maxMoveSpeed);
  328. }
  329. if (Input.Button(Buttons.Up))//(Keyboard.GetState().IsKeyDown(Keys.W) || GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.Y > 0.0f)
  330. {
  331. camPosition.X += (float)Math.Cos(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  332. camPosition.Z += (float)Math.Sin(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  333. camPosition.Y -= Yshift / 50;
  334. }
  335. if (Input.Button(Buttons.Down))//(Keyboard.GetState().IsKeyDown(Keys.S) || GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.Y < 0.0f)
  336. {
  337. camPosition.X -= (float)Math.Cos(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  338. camPosition.Z -= (float)Math.Sin(MathHelper.ToRadians(degrees)) * leftdistY / 10;
  339. camPosition.Y += Yshift / 50;
  340. }
  341. if (Input.Button(Buttons.Left))//(Keyboard.GetState().IsKeyDown(Keys.A) || GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.X < 0.0f)
  342. {
  343. camPosition.X += (float)Math.Cos(MathHelper.ToRadians(degrees - 90)) * leftdistX / 10;
  344. camPosition.Z += (float)Math.Sin(MathHelper.ToRadians(degrees - 90)) * leftdistX / 10;
  345. }
  346. if (Input.Button(Buttons.Right))//(Keyboard.GetState().IsKeyDown(Keys.D) || GamePad.GetState(PlayerIndex.One).ThumbSticks.Left.X > 0.0f)
  347. {
  348. camPosition.X += (float)Math.Cos(MathHelper.ToRadians(degrees + 90)) * leftdistX / 10;
  349. camPosition.Z += (float)Math.Sin(MathHelper.ToRadians(degrees + 90)) * leftdistX / 10;
  350. }
  351. camTarget.X = camPosition.X + (float)Math.Cos(MathHelper.ToRadians(degrees)) * camDistance;
  352. camTarget.Z = camPosition.Z + (float)Math.Sin(MathHelper.ToRadians(degrees)) * camDistance;
  353. camTarget.Y = camPosition.Y - Yshift / 5;
  354. viewMatrix = Matrix.CreateLookAt(camPosition, camTarget,
  355. Vector3.Up);
  356. #endregion
  357. }
  358. public static void Draw()
  359. {
  360. Memory.spriteBatch.GraphicsDevice.Clear(Color.CornflowerBlue);
  361. Memory.spriteBatch.Begin(SpriteSortMode.BackToFront, BlendState.AlphaBlend);
  362. Memory.spriteBatch.Draw(wm38textures[10][0], new Rectangle(0, 0, (int)(Memory.graphics.GraphicsDevice.Viewport.Width / 2.8f), (int)(Memory.graphics.GraphicsDevice.Viewport.Height / 2.8f)), Color.White * .1f);
  363. Memory.spriteBatch.End();
  364. Memory.graphics.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
  365. Memory.graphics.GraphicsDevice.BlendState = BlendState.NonPremultiplied;
  366. Memory.graphics.GraphicsDevice.DepthStencilState = DepthStencilState.Default;
  367. Memory.graphics.GraphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
  368. ate.Projection = projectionMatrix;
  369. ate.View = viewMatrix;
  370. ate.World = worldMatrix;
  371. //334 debug
  372. for (int i = 0; i < 768; i++)
  373. DrawSegment(i);
  374. if (true)
  375. {
  376. var collectionDebug = mchEntities[0].GetVertexPositions(-500, 100, -500);
  377. ate.Texture = charaOneTextures[1][0];
  378. foreach (var pass in ate.CurrentTechnique.Passes)
  379. {
  380. pass.Apply();
  381. Memory.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, collectionDebug.Item1, 0, collectionDebug.Item1.Length / 3);
  382. }
  383. }
  384. if (Input.GetInputDelayed(Keys.J))
  385. MapState = MapState >= MiniMapState.fullscreen ? MapState = 0 : MapState + 1;
  386. //if (Input.GetInputDelayed(Keys.F1))
  387. // ;
  388. switch (MapState)
  389. {
  390. case MiniMapState.noMinimap:
  391. break;
  392. case MiniMapState.planet:
  393. break;
  394. case MiniMapState.rectangle:
  395. DrawRectangleMiniMap();
  396. break;
  397. case MiniMapState.fullscreen:
  398. break;
  399. }
  400. Memory.SpriteBatchStartAlpha();
  401. Memory.font.RenderBasicText(Font.CipherDirty($"World map MapState: {MapState}"), 0, 0, 1, 1, 0, 1);
  402. Memory.font.RenderBasicText(Font.CipherDirty($"World Map Camera: X={camPosition}"), 0, 30, 1, 1, 0, 1);
  403. Memory.font.RenderBasicText(Font.CipherDirty($"Segment Position: ={segmentPosition}"), 0, 30 * 2, 1, 1, 0, 1);
  404. Memory.font.RenderBasicText(Font.CipherDirty($"FPS camera deegress: ={degrees}"), 0, 30 * 3, 1, 1, 0, 1);
  405. Memory.font.RenderBasicText(Font.CipherDirty($"var1: ={FOV}"), 0, 30 * 4, 1, 1, 0, 1);
  406. Memory.SpriteBatchEnd();
  407. }
  408. private static void DrawRectangleMiniMap()
  409. {
  410. Memory.spriteBatch.Begin(SpriteSortMode.BackToFront, Memory.blendState_BasicAdd);
  411. Memory.spriteBatch.Draw(wm38textures[11][1], new Rectangle((int)(Memory.graphics.GraphicsDevice.Viewport.Width * 0.60f), (int)(Memory.graphics.GraphicsDevice.Viewport.Height * 0.60f), (int)(Memory.graphics.GraphicsDevice.Viewport.Width / 2.8f), (int)(Memory.graphics.GraphicsDevice.Viewport.Height / 2.8f)), Color.White * .7f);
  412. Memory.spriteBatch.End();
  413. //cursor is wm38[24][0] and -16384 is max X, where 12288 is max Y
  414. float topX = Memory.graphics.GraphicsDevice.Viewport.Width * .6f; //6
  415. float topY = Memory.graphics.GraphicsDevice.Viewport.Height * .6f;
  416. float bc = Math.Abs(camPosition.X / 16384.0f);
  417. topX += Memory.graphics.GraphicsDevice.Viewport.Width / 2.8f * bc;
  418. bc = Math.Abs(camPosition.Z / 12288f);
  419. topY += Memory.graphics.GraphicsDevice.Viewport.Height / 2.8f * bc;
  420. Memory.SpriteBatchStartAlpha();
  421. Memory.spriteBatch.Draw(wm38textures[24][0], new Rectangle((int)topX, (int)topY, (int)(Memory.graphics.GraphicsDevice.Viewport.Width / 32.0f), (int)(Memory.graphics.GraphicsDevice.Viewport.Height / 32.0f)), null, Color.White * 1f, degrees * 6.3f / 360f + 2.5f, Vector2.Zero, SpriteEffects.None, 1f);
  422. Memory.SpriteBatchEnd();
  423. }
  424. private static bool ShouldDrawSegment(float baseX, float baseY, int seg)
  425. {
  426. segmentPosition = new Vector2((int)(camPosition.X / 512) * -1, (int)(camPosition.Z / 512) * -1);
  427. if (camPosition.X > 0)
  428. camPosition.X = 32 * 512 * -1;
  429. if (camPosition.X < 32 * 512 * -1)
  430. camPosition.X = 0;
  431. if (camPosition.Z > 0)
  432. camPosition.Z = 24 * 512 * -1;
  433. if (camPosition.Z < 24 * 512 * -1)
  434. camPosition.Z = 0;
  435. int ySegment = seg / 32; //2
  436. int xSegment = seg - ySegment * 32;
  437. Vector2 currentSegment = new Vector2(xSegment, ySegment);
  438. for (int i = -1 - renderDistance; i < renderDistance; i++)
  439. for (int k = 0 - renderDistance; k < renderDistance; k++)
  440. if (segmentPosition + new Vector2(i, k) == currentSegment)
  441. return true;
  442. return false;
  443. }
  444. private static void DrawSegment(int _i)
  445. {
  446. float baseX, baseY;
  447. //TODO http://forums.qhimm.com/index.php?topic=16230.msg230004#msg230004
  448. baseX = 2048f / 4 * (_i % 32);
  449. baseY = -(2048f / 4) * (_i / 32); //explicit int cast
  450. if (!ShouldDrawSegment(baseX, baseY, _i))
  451. return;
  452. #region Interchangable zones
  453. //esthar
  454. if (MakiExtended.In(_i, 373, 380))
  455. _i += 395;
  456. if (MakiExtended.In(_i, 405, 412))
  457. _i += 371;
  458. if (MakiExtended.In(_i, 437, 444))
  459. _i += 785 - 438;
  460. if (MakiExtended.In(_i, 469, 476))
  461. _i += 793 - 470;
  462. if (MakiExtended.In(_i, 501, 508))
  463. _i += 801 - 502;
  464. if (MakiExtended.In(_i, 533, 540))
  465. _i += 809 - 534;
  466. if (MakiExtended.In(_i, 565, 572))
  467. _i += 817 - 566;
  468. //trabia
  469. if (MakiExtended.In(_i, 149, 150))
  470. _i += 825 - 150;
  471. //galbadia
  472. if (MakiExtended.In(_i, 267, 267))
  473. _i = 826;
  474. ////balamb
  475. if (MakiExtended.In(_i, 274, 275))
  476. _i += 828 - 275;
  477. ////base
  478. if (MakiExtended.In(_i, 327, 327))
  479. _i += 830 - 328;
  480. ////trabia
  481. if (MakiExtended.In(_i, 214, 215))
  482. _i += 831 - 215;
  483. if (MakiExtended.In(_i, 246, 247))
  484. _i += 833 - 247;
  485. ////prison
  486. if (MakiExtended.In(_i, 361, 361))
  487. _i += 835 - 362;
  488. #endregion
  489. effect.TextureEnabled = true;
  490. Segment seg = segments[_i];
  491. float localX = 0;//_i * 2048;
  492. for (int i = 0; i < seg.block.Length; i++)
  493. {
  494. localX = 2048 * (i % 4);
  495. float localZ = -2048 * (i / 4);
  496. VertexPositionTexture[] vpc = new VertexPositionTexture[seg.block[i].polygons.Length * 3];
  497. for (int k = 0; k < seg.block[i].polyCount * 3; k += 3)
  498. {
  499. vpc[k] = new VertexPositionTexture(
  500. new Vector3(((seg.block[i].vertices[seg.block[i].polygons[k / 3].F1].X + localX) / WORLD_SCALE_MODEL + baseX) * -1f,
  501. seg.block[i].vertices[seg.block[i].polygons[k / 3].F1].Z1 / WORLD_SCALE_MODEL,
  502. (seg.block[i].vertices[seg.block[i].polygons[k / 3].F1].Y + localZ) / WORLD_SCALE_MODEL + baseY),
  503. new Vector2(seg.block[i].polygons[k / 3].U1 / 256.0f, seg.block[i].polygons[k / 3].V1 / 256.0f));
  504. vpc[k + 1] = new VertexPositionTexture(
  505. new Vector3(((seg.block[i].vertices[seg.block[i].polygons[k / 3].F2].X + localX) / WORLD_SCALE_MODEL + baseX) * -1f,
  506. seg.block[i].vertices[seg.block[i].polygons[k / 3].F2].Z1 / WORLD_SCALE_MODEL,
  507. (seg.block[i].vertices[seg.block[i].polygons[k / 3].F2].Y + localZ) / WORLD_SCALE_MODEL + baseY),
  508. new Vector2(seg.block[i].polygons[k / 3].U2 / 256.0f, seg.block[i].polygons[k / 3].V2 / 256.0f));
  509. vpc[k + 2] = new VertexPositionTexture(
  510. new Vector3(((seg.block[i].vertices[seg.block[i].polygons[k / 3].F3].X + localX) / WORLD_SCALE_MODEL + baseX) * -1f,
  511. seg.block[i].vertices[seg.block[i].polygons[k / 3].F3].Z1 / WORLD_SCALE_MODEL,
  512. (seg.block[i].vertices[seg.block[i].polygons[k / 3].F3].Y + localZ) / WORLD_SCALE_MODEL + baseY),
  513. new Vector2(seg.block[i].polygons[k / 3].U3 / 256.0f, seg.block[i].polygons[k / 3].V3 / 256.0f));
  514. if (MakiExtended.Distance3D(camPosition, vpc[k].Position) > renderCamDistance)
  515. continue;
  516. float ax, ay, px, py, d1, d2, d3;
  517. px = vpc[k].Position.X;
  518. py = vpc[k].Position.Z;
  519. ax = camPosition.X + (float)Math.Cos(MathHelper.ToRadians(degrees)) * -50f;
  520. ay = camPosition.Z + (float)Math.Sin(MathHelper.ToRadians(degrees)) * -50f;
  521. Vector3 left=Vector3.Zero,right = Vector3.Zero;
  522. left.X = camPosition.X + (float)Math.Cos(MathHelper.ToRadians(MakiExtended.ClampOverload(degrees-FOV, 0, 359))) * renderCamDistance*2;
  523. left.Z = camPosition.Z + (float)Math.Sin(MathHelper.ToRadians(MakiExtended.ClampOverload(degrees-FOV, 0, 359))) * renderCamDistance*2;
  524. right.X = camPosition.X + (float)Math.Cos(MathHelper.ToRadians(MakiExtended.ClampOverload(degrees + FOV, 0, 359))) * renderCamDistance*2;
  525. right.Z = camPosition.Z + (float)Math.Sin(MathHelper.ToRadians(MakiExtended.ClampOverload(degrees + FOV, 0, 359))) * renderCamDistance*2;
  526. d1 = px * (ay - left.Z) + py * (left.X - ax) + (ax * left.Z - ay * left.X);
  527. d2 = px * (left.Z - right.Z) + py * (right.X - left.X) + (left.X * right.Z - left.Z * right.X);
  528. d3 = px * (right.Z - ay) + py * (ax - right.X) + (right.X * ay - right.Z * ax);
  529. if ((d1 > 0 || d2 > 0 || d3 > 0) && (d1 < 0 || d2 < 0 || d3 < 0))
  530. continue;
  531. if (seg.block[i].polygons[k / 3].TextureSwitch == 0x40 ||
  532. seg.block[i].polygons[k / 3].TextureSwitch == 0xC0)
  533. {
  534. ate.Texture = wm38textures[16][0];
  535. }
  536. else switch (seg.block[i].polygons[k / 3].TextureSwitch)
  537. {
  538. case 0x60:
  539. ate.Texture = wm39textures[0][0];
  540. break;
  541. case 0xE0:
  542. ate.Texture = wm39textures[5][0];
  543. break;
  544. default:
  545. ate.Texture = textures[seg.block[i].polygons[k / 3].TPage][seg.block[i].polygons[k / 3].Clut]; //there are two texs, worth looking at other parameters; to reverse!
  546. break;
  547. } //there are two texs, worth looking at other parameters; to reverse!
  548. foreach (var pass in ate.CurrentTechnique.Passes)
  549. {
  550. pass.Apply();
  551. Memory.graphics.GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleList, vpc, k, 1);
  552. }
  553. }
  554. }
  555. }
  556. }
  557. }