using System;
using System.IO;
using System.Text;

namespace SharpQuake
{
	internal static class mesh
	{
		public static void MakeAliasModelDisplayLists(model_t m, aliashdr_t hdr)
		{
			mesh._AliasModel = m;
			mesh._AliasHdr = hdr;
			string text = Path.ChangeExtension("glquake/" + Path.GetFileNameWithoutExtension(m.name), ".ms2");
			DisposableWrapper<BinaryReader> disposableWrapper;
			common.FOpenFile(text, out disposableWrapper);
			if (disposableWrapper != null)
			{
				using (disposableWrapper)
				{
					BinaryReader @object = disposableWrapper.Object;
					mesh._NumCommands = @object.ReadInt32();
					mesh._NumOrder = @object.ReadInt32();
					for (int i = 0; i < mesh._NumCommands; i++)
					{
						mesh._Commands[i] = @object.ReadInt32();
					}
					for (int j = 0; j < mesh._NumOrder; j++)
					{
						mesh._VertexOrder[j] = @object.ReadInt32();
					}
					goto IL_161;
				}
			}
			Con.Print("meshing {0}...\n", new object[]
			{
				m.name
			});
			mesh.BuildTris();
			Stream stream = sys.FileOpenWrite(Path.Combine(common.GameDir, text), true);
			if (stream != null)
			{
				using (BinaryWriter binaryWriter = new BinaryWriter(stream, Encoding.ASCII))
				{
					binaryWriter.Write(mesh._NumCommands);
					binaryWriter.Write(mesh._NumOrder);
					for (int k = 0; k < mesh._NumCommands; k++)
					{
						binaryWriter.Write(mesh._Commands[k]);
					}
					for (int l = 0; l < mesh._NumOrder; l++)
					{
						binaryWriter.Write(mesh._VertexOrder[l]);
					}
				}
			}
			IL_161:
			mesh._AliasHdr.poseverts = mesh._NumOrder;
			int[] array = new int[mesh._NumCommands];
			mesh._AliasHdr.commands = array;
			Buffer.BlockCopy(mesh._Commands, 0, array, 0, mesh._NumCommands * 4);
			trivertx_t[][] poseVerts = Mod.PoseVerts;
			trivertx_t[] array2 = new trivertx_t[mesh._AliasHdr.numposes * mesh._AliasHdr.poseverts];
			mesh._AliasHdr.posedata = array2;
			int num = 0;
			for (int n = 0; n < mesh._AliasHdr.numposes; n++)
			{
				for (int num2 = 0; num2 < mesh._NumOrder; num2++)
				{
					array2[num++] = poseVerts[n][mesh._VertexOrder[num2]];
				}
			}
		}

		private static void BuildTris()
		{
			int[] array = new int[1024];
			int[] array2 = new int[1024];
			stvert_t[] stverts = Mod.STVerts;
			dtriangle_t[] triangles = Mod.Triangles;
			mesh._NumOrder = 0;
			mesh._NumCommands = 0;
			Array.Clear(mesh._Used, 0, mesh._Used.Length);
			int num = 0;
			for (int i = 0; i < mesh._AliasHdr.numtris; i++)
			{
				if (mesh._Used[i] == 0)
				{
					int num2 = 0;
					for (int j = 0; j < 2; j++)
					{
						for (int k = 0; k < 3; k++)
						{
							int num3;
							if (j == 1)
							{
								num3 = mesh.StripLength(i, k);
							}
							else
							{
								num3 = mesh.FanLength(i, k);
							}
							if (num3 > num2)
							{
								num = j;
								num2 = num3;
								for (int l = 0; l < num2 + 2; l++)
								{
									array[l] = mesh._StripVerts[l];
								}
								for (int m = 0; m < num2; m++)
								{
									array2[m] = mesh._StripTris[m];
								}
							}
						}
					}
					for (int n = 0; n < num2; n++)
					{
						mesh._Used[array2[n]] = 1;
					}
					if (num == 1)
					{
						mesh._Commands[mesh._NumCommands++] = num2 + 2;
					}
					else
					{
						mesh._Commands[mesh._NumCommands++] = -(num2 + 2);
					}
					Union4b empty = Union4b.Empty;
					for (int num4 = 0; num4 < num2 + 2; num4++)
					{
						int num5 = array[num4];
						mesh._VertexOrder[mesh._NumOrder++] = num5;
						float num6 = (float)stverts[num5].s;
						float num7 = (float)stverts[num5].t;
						if (triangles[array2[0]].facesfront == 0 && stverts[num5].onseam != 0)
						{
							num6 += (float)(mesh._AliasHdr.skinwidth / 2);
						}
						num6 = (num6 + 0.5f) / (float)mesh._AliasHdr.skinwidth;
						num7 = (num7 + 0.5f) / (float)mesh._AliasHdr.skinheight;
						empty.f0 = num6;
						mesh._Commands[mesh._NumCommands++] = empty.i0;
						empty.f0 = num7;
						mesh._Commands[mesh._NumCommands++] = empty.i0;
					}
				}
			}
			mesh._Commands[mesh._NumCommands++] = 0;
			Con.DPrint("{0,3} tri {1,3} vert {2,3} cmd\n", new object[]
			{
				mesh._AliasHdr.numtris,
				mesh._NumOrder,
				mesh._NumCommands
			});
			mesh._AllVerts += mesh._NumOrder;
			mesh._AllTris += mesh._AliasHdr.numtris;
		}

		private static int StripLength(int starttri, int startv)
		{
			mesh._Used[starttri] = 2;
			dtriangle_t[] triangles = Mod.Triangles;
			int[] vertindex = triangles[starttri].vertindex;
			mesh._StripVerts[0] = vertindex[startv % 3];
			mesh._StripVerts[1] = vertindex[(startv + 1) % 3];
			mesh._StripVerts[2] = vertindex[(startv + 2) % 3];
			mesh._StripTris[0] = starttri;
			mesh._StripCount = 1;
			int num = mesh._StripVerts[2];
			int num2 = mesh._StripVerts[1];
			int facesfront = triangles[starttri].facesfront;
			for (;;)
			{
				IL_6F:
				for (int i = starttri + 1; i < mesh._AliasHdr.numtris; i++)
				{
					if (triangles[i].facesfront == facesfront)
					{
						vertindex = triangles[i].vertindex;
						int j = 0;
						while (j < 3)
						{
							if (vertindex[j] == num && vertindex[(j + 1) % 3] == num2)
							{
								if (mesh._Used[i] == 0)
								{
									if ((mesh._StripCount & 1) != 0)
									{
										num2 = vertindex[(j + 2) % 3];
									}
									else
									{
										num = vertindex[(j + 2) % 3];
									}
									mesh._StripVerts[mesh._StripCount + 2] = triangles[i].vertindex[(j + 2) % 3];
									mesh._StripTris[mesh._StripCount] = i;
									mesh._StripCount++;
									mesh._Used[i] = 2;
									goto IL_6F;
								}
								goto IL_14C;
							}
							else
							{
								j++;
							}
						}
					}
				}
				break;
			}
			IL_14C:
			for (int k = starttri + 1; k < mesh._AliasHdr.numtris; k++)
			{
				if (mesh._Used[k] == 2)
				{
					mesh._Used[k] = 0;
				}
			}
			return mesh._StripCount;
		}

		private static int FanLength(int starttri, int startv)
		{
			mesh._Used[starttri] = 2;
			dtriangle_t[] triangles = Mod.Triangles;
			int[] vertindex = triangles[starttri].vertindex;
			mesh._StripVerts[0] = vertindex[startv % 3];
			mesh._StripVerts[1] = vertindex[(startv + 1) % 3];
			mesh._StripVerts[2] = vertindex[(startv + 2) % 3];
			mesh._StripTris[0] = starttri;
			mesh._StripCount = 1;
			int num = vertindex[startv % 3];
			int num2 = vertindex[(startv + 2) % 3];
			int facesfront = triangles[starttri].facesfront;
			for (;;)
			{
				IL_6D:
				for (int i = starttri + 1; i < mesh._AliasHdr.numtris; i++)
				{
					vertindex = triangles[i].vertindex;
					if (triangles[i].facesfront == facesfront)
					{
						int j = 0;
						while (j < 3)
						{
							if (vertindex[j] == num && vertindex[(j + 1) % 3] == num2)
							{
								if (mesh._Used[i] == 0)
								{
									num2 = vertindex[(j + 2) % 3];
									mesh._StripVerts[mesh._StripCount + 2] = num2;
									mesh._StripTris[mesh._StripCount] = i;
									mesh._StripCount++;
									mesh._Used[i] = 2;
									goto IL_6D;
								}
								goto IL_117;
							}
							else
							{
								j++;
							}
						}
					}
				}
				break;
			}
			IL_117:
			for (int k = starttri + 1; k < mesh._AliasHdr.numtris; k++)
			{
				if (mesh._Used[k] == 2)
				{
					mesh._Used[k] = 0;
				}
			}
			return mesh._StripCount;
		}

		private const int MAX_COMMANDS = 8192;

		private const int MAX_STRIP = 128;

		private static model_t _AliasModel;

		private static aliashdr_t _AliasHdr;

		private static byte[] _Used = new byte[8192];

		private static int[] _Commands = new int[8192];

		private static int _NumCommands;

		private static int[] _VertexOrder = new int[8192];

		private static int _NumOrder;

		private static int _AllVerts;

		private static int _AllTris;

		private static int[] _StripVerts = new int[128];

		private static int[] _StripTris = new int[128];

		private static int _StripCount;
	}
}
