using System;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace SharpQuake
{
	internal static class render
	{
		public static refdef_t RefDef
		{
			get
			{
				return render._RefDef;
			}
		}

		public static bool CacheTrash
		{
			get
			{
				return render._CacheThrash;
			}
		}

		public static texture_t NoTextureMip
		{
			get
			{
				return render._NoTextureMip;
			}
		}

		public static void Init()
		{
			for (int i = 0; i < render._Frustum.Length; i++)
			{
				render._Frustum[i] = new mplane_t();
			}
			cmd.Add("timerefresh", new xcommand_t(render.TimeRefresh_f));
			if (render._NoRefresh == null)
			{
				render._NoRefresh = new cvar("r_norefresh", "0");
				render._DrawEntities = new cvar("r_drawentities", "1");
				render._DrawViewModel = new cvar("r_drawviewmodel", "1");
				render._Speeds = new cvar("r_speeds", "0");
				render._FullBright = new cvar("r_fullbright", "0");
				render._LightMap = new cvar("r_lightmap", "0");
				render._Shadows = new cvar("r_shadows", "0");
				render._MirrorAlpha = new cvar("r_mirroralpha", "1");
				render._WaterAlpha = new cvar("r_wateralpha", "1");
				render._Dynamic = new cvar("r_dynamic", "1");
				render._NoVis = new cvar("r_novis", "0");
				render._glFinish = new cvar("gl_finish", "0");
				render._glClear = new cvar("gl_clear", "0");
				render._glCull = new cvar("gl_cull", "1");
				render._glTexSort = new cvar("gl_texsort", "1");
				render._glSmoothModels = new cvar("gl_smoothmodels", "1");
				render._glAffineModels = new cvar("gl_affinemodels", "0");
				render._glPolyBlend = new cvar("gl_polyblend", "1");
				render._glFlashBlend = new cvar("gl_flashblend", "1");
				render._glPlayerMip = new cvar("gl_playermip", "0");
				render._glNoColors = new cvar("gl_nocolors", "0");
				render._glKeepTJunctions = new cvar("gl_keeptjunctions", "0");
				render._glReportTJunctions = new cvar("gl_reporttjunctions", "0");
				render._glDoubleEyes = new cvar("gl_doubleeys", "1");
			}
			if (vid.glMTexable)
			{
				cvar.Set("gl_texsort", 0f);
			}
			render.InitParticles();
			render.InitParticleTexture();
			render._PlayerTextures = Drawer.GenerateTextureNumberRange(16);
		}

		public static void InitTextures()
		{
			render._NoTextureMip = new texture_t();
			render._NoTextureMip.pixels = new byte[340];
			render._NoTextureMip.width = (render._NoTextureMip.height = 16u);
			int num = 0;
			render._NoTextureMip.offsets[0] = num;
			num += 256;
			render._NoTextureMip.offsets[1] = num;
			num += 64;
			render._NoTextureMip.offsets[2] = num;
			num += 16;
			render._NoTextureMip.offsets[3] = num;
			byte[] pixels = render._NoTextureMip.pixels;
			for (int i = 0; i < 4; i++)
			{
				num = render._NoTextureMip.offsets[i];
				for (int j = 0; j < 16 >> i; j++)
				{
					for (int k = 0; k < 16 >> i; k++)
					{
						if (j < 8 >> i ^ k < 8 >> i)
						{
							pixels[num] = 0;
						}
						else
						{
							pixels[num] = byte.MaxValue;
						}
						num++;
					}
				}
			}
		}

		public static void RenderView()
		{
			if (render._NoRefresh.Value != 0f)
			{
				return;
			}
			if (render._WorldEntity.model == null || client.cl.worldmodel == null)
			{
				sys.Error("R_RenderView: NULL worldmodel", Array.Empty<object>());
			}
			double num = 0.0;
			if (render._Speeds.Value != 0f)
			{
				GL.Finish();
				num = sys.GetFloatTime();
				render._BrushPolys = 0;
				render._AliasPolys = 0;
			}
			render._IsMirror = false;
			if (render._glFinish.Value != 0f)
			{
				GL.Finish();
			}
			render.Clear();
			render.RenderScene();
			render.DrawViewModel();
			render.DrawWaterSurfaces();
			render.Mirror();
			render.PolyBlend();
			if (render._Speeds.Value != 0f)
			{
				double floatTime = sys.GetFloatTime();
				Con.Print("{0,3} ms  {1,4} wpoly {2,4} epoly\n", new object[]
				{
					(int)((floatTime - num) * 1000.0),
					render._BrushPolys,
					render._AliasPolys
				});
			}
		}

		public static void RemoveEfrags(entity_t ent)
		{
			efrag_t efrag_t = ent.efrag;
			while (efrag_t != null)
			{
				mleaf_t mleaf_t = efrag_t.leaf;
				for (;;)
				{
					efrag_t efrags = mleaf_t.efrags;
					if (efrags == null)
					{
						break;
					}
					if (efrags == efrag_t)
					{
						goto Block_2;
					}
					mleaf_t = (mleaf_t)efrags.leafnext;
				}
				IL_3A:
				efrag_t efrag_t2 = efrag_t;
				efrag_t = efrag_t.entnext;
				efrag_t2.entnext = client.cl.free_efrags;
				client.cl.free_efrags = efrag_t2;
				continue;
				Block_2:
				mleaf_t.efrags = efrag_t.leafnext;
				goto IL_3A;
			}
			ent.efrag = null;
		}

		public static void TranslatePlayerSkin(int playernum)
		{
			render.DisableMultitexture();
			int num = client.cl.scores[playernum].colors & 240;
			int num2 = (client.cl.scores[playernum].colors & 15) << 4;
			byte[] array = new byte[256];
			for (int i = 0; i < 256; i++)
			{
				array[i] = (byte)i;
			}
			for (int j = 0; j < 16; j++)
			{
				if (num < 128)
				{
					array[16 + j] = (byte)(num + j);
				}
				else
				{
					array[16 + j] = (byte)(num + 15 - j);
				}
				if (num2 < 128)
				{
					array[96 + j] = (byte)(num2 + j);
				}
				else
				{
					array[96 + j] = (byte)(num2 + 15 - j);
				}
			}
			render._CurrentEntity = client.Entities[1 + playernum];
			model_t model = render._CurrentEntity.model;
			if (model == null)
			{
				return;
			}
			if (model.type != modtype_t.mod_alias)
			{
				return;
			}
			aliashdr_t extraData = Mod.GetExtraData(model);
			if ((extraData.skinwidth * extraData.skinheight & 3) != 0)
			{
				sys.Error("R_TranslateSkin: s&3", Array.Empty<object>());
			}
			byte[] array2;
			if (render._CurrentEntity.skinnum < 0 || render._CurrentEntity.skinnum >= extraData.numskins)
			{
				Con.Print("({0}): Invalid player skin #{1}\n", new object[]
				{
					playernum,
					render._CurrentEntity.skinnum
				});
				array2 = (byte[])extraData.texels[0];
			}
			else
			{
				array2 = (byte[])extraData.texels[render._CurrentEntity.skinnum];
			}
			int skinwidth = extraData.skinwidth;
			int skinheight = extraData.skinheight;
			Drawer.Bind(render._PlayerTextures + playernum);
			int num3 = (int)((Drawer.glMaxSize < 512f) ? Drawer.glMaxSize : 512f);
			int num4 = (int)((Drawer.glMaxSize < 256f) ? Drawer.glMaxSize : 256f);
			num3 >>= (int)render._glPlayerMip.Value;
			num4 >>= (int)render._glPlayerMip.Value;
			uint[] array3 = new uint[256];
			for (int k = 0; k < 256; k++)
			{
				array3[k] = vid.Table8to24[(int)array[k]];
			}
			uint[] array4 = new uint[131072];
			int num5 = 0;
			uint num6 = (uint)(skinwidth * 65536 / num3);
			int l = 0;
			while (l < num4)
			{
				int num7 = skinwidth * (l * skinheight / num4);
				uint num8 = num6 >> 1;
				for (int m = 0; m < num3; m += 4)
				{
					array4[num5 + m] = array3[(int)array2[(int)(checked((IntPtr)(unchecked((long)num7 + (long)((ulong)(num8 >> 16))))))]];
					num8 += num6;
					array4[num5 + m + 1] = array3[(int)array2[(int)(checked((IntPtr)(unchecked((long)num7 + (long)((ulong)(num8 >> 16))))))]];
					num8 += num6;
					array4[num5 + m + 2] = array3[(int)array2[(int)(checked((IntPtr)(unchecked((long)num7 + (long)((ulong)(num8 >> 16))))))]];
					num8 += num6;
					array4[num5 + m + 3] = array3[(int)array2[(int)(checked((IntPtr)(unchecked((long)num7 + (long)((ulong)(num8 >> 16))))))]];
					num8 += num6;
				}
				l++;
				num5 += num3;
			}
			GCHandle gchandle = GCHandle.Alloc(array4, GCHandleType.Pinned);
			try
			{
				GL.TexImage2D(TextureTarget.Texture2D, 0, Drawer.SolidFormat, num3, num4, 0, PixelFormat.Rgba, PixelType.UnsignedByte, gchandle.AddrOfPinnedObject());
			}
			finally
			{
				gchandle.Free();
			}
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 8448);
			Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear);
		}

		public static void DisableMultitexture()
		{
			if (render._MTexEnabled)
			{
				GL.Disable(EnableCap.Texture2D);
				Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS);
				render._MTexEnabled = false;
			}
		}

		public static void EnableMultitexture()
		{
			if (vid.glMTexable)
			{
				Drawer.SelectTexture(MTexTarget.TEXTURE1_SGIS);
				GL.Enable(EnableCap.Texture2D);
				render._MTexEnabled = true;
			}
		}

		public static void NewMap()
		{
			for (int i = 0; i < 256; i++)
			{
				render._LightStyleValue[i] = 264;
			}
			render._WorldEntity.Clear();
			render._WorldEntity.model = client.cl.worldmodel;
			for (int j = 0; j < client.cl.worldmodel.numleafs; j++)
			{
				client.cl.worldmodel.leafs[j].efrags = null;
			}
			render._ViewLeaf = null;
			render.ClearParticles();
			render.BuildLightMaps();
			render._SkyTextureNum = -1;
			render._MirrorTextureNum = -1;
			model_t worldmodel = client.cl.worldmodel;
			for (int k = 0; k < worldmodel.numtextures; k++)
			{
				if (worldmodel.textures[k] != null)
				{
					if (worldmodel.textures[k].name != null)
					{
						if (worldmodel.textures[k].name.StartsWith("sky"))
						{
							render._SkyTextureNum = k;
						}
						if (worldmodel.textures[k].name.StartsWith("window02_1"))
						{
							render._MirrorTextureNum = k;
						}
					}
					worldmodel.textures[k].texturechain = null;
				}
			}
		}

		private static void PolyBlend()
		{
			if (render._glPolyBlend.Value == 0f)
			{
				return;
			}
			if (view.Blend.A == 0f)
			{
				return;
			}
			render.DisableMultitexture();
			GL.Disable(EnableCap.AlphaTest);
			GL.Enable(EnableCap.Blend);
			GL.Disable(EnableCap.DepthTest);
			GL.Disable(EnableCap.Texture2D);
			GL.LoadIdentity();
			GL.Rotate(-90f, 1f, 0f, 0f);
			GL.Rotate(90f, 0f, 0f, 1f);
			GL.Color4(view.Blend);
			GL.Begin(PrimitiveType.Quads);
			GL.Vertex3(10f, 100f, 100f);
			GL.Vertex3(10f, -100f, 100f);
			GL.Vertex3(10f, -100f, -100f);
			GL.Vertex3(10f, 100f, -100f);
			GL.End();
			GL.Disable(EnableCap.Blend);
			GL.Enable(EnableCap.Texture2D);
			GL.Enable(EnableCap.AlphaTest);
		}

		private static void Mirror()
		{
			if (!render._IsMirror)
			{
				return;
			}
			render._BaseWorldMatrix = render._WorldMatrix;
			float scale = Vector3.Dot(render._RefDef.vieworg, render._MirrorPlane.normal) - render._MirrorPlane.dist;
			render._RefDef.vieworg += render._MirrorPlane.normal * -2f * scale;
			scale = Vector3.Dot(render.ViewPn, render._MirrorPlane.normal);
			render.ViewPn += render._MirrorPlane.normal * -2f * scale;
			render._RefDef.viewangles = new Vector3((float)(Math.Asin((double)render.ViewPn.Z) / 3.1415926535897931 * 180.0), (float)(Math.Atan2((double)render.ViewPn.Y, (double)render.ViewPn.X) / 3.1415926535897931 * 180.0), -render._RefDef.viewangles.Z);
			entity_t viewEntity = client.ViewEntity;
			if (client.NumVisEdicts < 256)
			{
				client.VisEdicts[client.NumVisEdicts] = viewEntity;
				client.NumVisEdicts++;
			}
			render._glDepthMin = 0.5f;
			render._glDepthMax = 1f;
			GL.DepthRange(render._glDepthMin, render._glDepthMax);
			GL.DepthFunc(DepthFunction.Lequal);
			render.RenderScene();
			render.DrawWaterSurfaces();
			render._glDepthMin = 0f;
			render._glDepthMax = 0.5f;
			GL.DepthRange(render._glDepthMin, render._glDepthMax);
			GL.DepthFunc(DepthFunction.Lequal);
			GL.Enable(EnableCap.Blend);
			GL.MatrixMode(MatrixMode.Projection);
			if (render._MirrorPlane.normal.Z != 0f)
			{
				GL.Scale(1f, -1f, 1f);
			}
			else
			{
				GL.Scale(-1f, 1f, 1f);
			}
			GL.CullFace(CullFaceMode.Front);
			GL.MatrixMode(MatrixMode.Modelview);
			GL.LoadMatrix(ref render._BaseWorldMatrix);
			GL.Color4(1f, 1f, 1f, render._MirrorAlpha.Value);
			for (msurface_t texturechain = client.cl.worldmodel.textures[render._MirrorTextureNum].texturechain; texturechain != null; texturechain = texturechain.texturechain)
			{
				render.RenderBrushPoly(texturechain);
			}
			client.cl.worldmodel.textures[render._MirrorTextureNum].texturechain = null;
			GL.Disable(EnableCap.Blend);
			GL.Color4(1f, 1f, 1f, 1f);
		}

		private static void DrawViewModel()
		{
			if (render._DrawViewModel.Value == 0f)
			{
				return;
			}
			if (chase.IsActive)
			{
				return;
			}
			if (render._IsEnvMap)
			{
				return;
			}
			if (render._DrawEntities.Value == 0f)
			{
				return;
			}
			if (client.cl.HasItems(QItems.IT_INVISIBILITY))
			{
				return;
			}
			if (client.cl.stats[QStats.STAT_HEALTH] <= 0)
			{
				return;
			}
			render._CurrentEntity = client.ViewEnt;
			if (render._CurrentEntity.model == null)
			{
				return;
			}
			int num = render.LightPoint(ref render._CurrentEntity.origin);
			if (num < 24)
			{
				num = 24;
			}
			render._AmbientLight = (float)num;
			render._ShadeLight = (float)num;
			for (int i = 0; i < 32; i++)
			{
				dlight_t dlight_t = client.DLights[i];
				if (dlight_t.radius != 0f && (double)dlight_t.die >= client.cl.time)
				{
					Vector3 vector = render._CurrentEntity.origin - dlight_t.origin;
					float num2 = dlight_t.radius - vector.Length;
					if (num2 > 0f)
					{
						render._AmbientLight += num2;
					}
				}
			}
			GL.DepthRange(render._glDepthMin, render._glDepthMin + 0.3f * (render._glDepthMax - render._glDepthMin));
			render.DrawAliasModel(render._CurrentEntity);
			GL.DepthRange(render._glDepthMin, render._glDepthMax);
		}

		private static void RenderScene()
		{
			render.SetupFrame();
			render.SetFrustum();
			render.SetupGL();
			render.MarkLeaves();
			render.DrawWorld();
			snd.ExtraUpdate();
			render.DrawEntitiesOnList();
			render.DisableMultitexture();
			render.RenderDlights();
			render.DrawParticles();
		}

		private static void DrawEntitiesOnList()
		{
			if (render._DrawEntities.Value == 0f)
			{
				return;
			}
			for (int i = 0; i < client.NumVisEdicts; i++)
			{
				render._CurrentEntity = client.VisEdicts[i];
				modtype_t type = render._CurrentEntity.model.type;
				if (type != modtype_t.mod_brush)
				{
					if (type == modtype_t.mod_alias)
					{
						render.DrawAliasModel(render._CurrentEntity);
					}
				}
				else
				{
					render.DrawBrushModel(render._CurrentEntity);
				}
			}
			for (int j = 0; j < client.NumVisEdicts; j++)
			{
				render._CurrentEntity = client.VisEdicts[j];
				if (render._CurrentEntity.model.type == modtype_t.mod_sprite)
				{
					render.DrawSpriteModel(render._CurrentEntity);
				}
			}
		}

		private static void DrawSpriteModel(entity_t e)
		{
			mspriteframe_t spriteFrame = render.GetSpriteFrame(e);
			Vector3 viewRight;
			Vector3 viewUp;
			if (((msprite_t)e.model.cache.data).type == 3)
			{
				Vector3 vector;
				mathlib.AngleVectors(ref e.angles, out vector, out viewRight, out viewUp);
			}
			else
			{
				viewUp = render.ViewUp;
				viewRight = render.ViewRight;
			}
			GL.Color3(1f, 1f, 1f);
			render.DisableMultitexture();
			Drawer.Bind(spriteFrame.gl_texturenum);
			GL.Enable(EnableCap.AlphaTest);
			GL.Begin(PrimitiveType.Quads);
			GL.TexCoord2(0f, 1f);
			GL.Vertex3(e.origin + viewUp * spriteFrame.down + viewRight * spriteFrame.left);
			GL.TexCoord2(0f, 0f);
			GL.Vertex3(e.origin + viewUp * spriteFrame.up + viewRight * spriteFrame.left);
			GL.TexCoord2(1f, 0f);
			GL.Vertex3(e.origin + viewUp * spriteFrame.up + viewRight * spriteFrame.right);
			GL.TexCoord2(1f, 1f);
			GL.Vertex3(e.origin + viewUp * spriteFrame.down + viewRight * spriteFrame.right);
			GL.End();
			GL.Disable(EnableCap.AlphaTest);
		}

		private static mspriteframe_t GetSpriteFrame(entity_t currententity)
		{
			msprite_t msprite_t = (msprite_t)currententity.model.cache.data;
			int num = currententity.frame;
			if (num >= msprite_t.numframes || num < 0)
			{
				Con.Print("R_DrawSprite: no such frame {0}\n", new object[]
				{
					num
				});
				num = 0;
			}
			mspriteframe_t result;
			if (msprite_t.frames[num].type == spriteframetype_t.SPR_SINGLE)
			{
				result = (mspriteframe_t)msprite_t.frames[num].frameptr;
			}
			else
			{
				mspritegroup_t mspritegroup_t = (mspritegroup_t)msprite_t.frames[num].frameptr;
				float[] intervals = mspritegroup_t.intervals;
				int numframes = mspritegroup_t.numframes;
				float num2 = intervals[numframes - 1];
				float num3 = (float)client.cl.time + currententity.syncbase;
				float num4 = num3 - (float)((int)(num3 / num2)) * num2;
				int num5 = 0;
				while (num5 < numframes - 1 && intervals[num5] <= num4)
				{
					num5++;
				}
				result = mspritegroup_t.frames[num5];
			}
			return result;
		}

		private static void DrawAliasModel(entity_t e)
		{
			model_t model = render._CurrentEntity.model;
			Vector3 vector = render._CurrentEntity.origin + model.mins;
			Vector3 vector2 = render._CurrentEntity.origin + model.maxs;
			if (render.CullBox(ref vector, ref vector2))
			{
				return;
			}
			render._EntOrigin = render._CurrentEntity.origin;
			render._ModelOrg = render.Origin - render._EntOrigin;
			render._AmbientLight = (render._ShadeLight = (float)render.LightPoint(ref render._CurrentEntity.origin));
			if (e == client.cl.viewent && render._AmbientLight < 24f)
			{
				render._AmbientLight = (render._ShadeLight = 24f);
			}
			for (int i = 0; i < 32; i++)
			{
				if ((double)client.DLights[i].die >= client.cl.time)
				{
					Vector3 vector3 = render._CurrentEntity.origin - client.DLights[i].origin;
					float num = client.DLights[i].radius - vector3.Length;
					if (num > 0f)
					{
						render._AmbientLight += num;
						render._ShadeLight += num;
					}
				}
			}
			if (render._AmbientLight > 128f)
			{
				render._AmbientLight = 128f;
			}
			if (render._AmbientLight + render._ShadeLight > 192f)
			{
				render._ShadeLight = 192f - render._AmbientLight;
			}
			int num2 = Array.IndexOf<entity_t>(client.Entities, render._CurrentEntity, 0, client.cl.maxclients);
			if (num2 >= 1 && render._AmbientLight < 8f)
			{
				render._AmbientLight = (render._ShadeLight = 8f);
			}
			if (model.name == "progs/flame2.mdl" || model.name == "progs/flame.mdl")
			{
				render._AmbientLight = (render._ShadeLight = 256f);
			}
			render._ShadeDots = anorm_dots.Values[(int)((double)e.angles.Y * 0.044444444444444446) & 15];
			render._ShadeLight /= 200f;
			double num3 = (double)e.angles.Y / 180.0 * 3.1415926535897931;
			render._ShadeVector.X = (float)Math.Cos(-num3);
			render._ShadeVector.Y = (float)Math.Sin(-num3);
			render._ShadeVector.Z = 1f;
			mathlib.Normalize(ref render._ShadeVector);
			aliashdr_t extraData = Mod.GetExtraData(render._CurrentEntity.model);
			render._AliasPolys += extraData.numtris;
			render.DisableMultitexture();
			GL.PushMatrix();
			render.RotateForEntity(e);
			if (model.name == "progs/eyes.mdl" && render._glDoubleEyes.Value != 0f)
			{
				Vector3 scale_origin = extraData.scale_origin;
				scale_origin.Z -= 30f;
				GL.Translate(scale_origin);
				GL.Scale(extraData.scale * 2f);
			}
			else
			{
				GL.Translate(extraData.scale_origin);
				GL.Scale(extraData.scale);
			}
			int num4 = (int)(client.cl.time * 10.0) & 3;
			Drawer.Bind(extraData.gl_texturenum[render._CurrentEntity.skinnum, num4]);
			if (render._CurrentEntity.colormap != Scr.vid.colormap && render._glNoColors.Value == 0f && num2 >= 1)
			{
				Drawer.Bind(render._PlayerTextures - 1 + num2);
			}
			if (render._glSmoothModels.Value != 0f)
			{
				GL.ShadeModel(ShadingModel.Smooth);
			}
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 8448);
			if (render._glAffineModels.Value != 0f)
			{
				GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Fastest);
			}
			render.SetupAliasFrame(render._CurrentEntity.frame, extraData);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 7681);
			GL.ShadeModel(ShadingModel.Flat);
			if (render._glAffineModels.Value != 0f)
			{
				GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
			}
			GL.PopMatrix();
			if (render._Shadows.Value != 0f)
			{
				GL.PushMatrix();
				render.RotateForEntity(e);
				GL.Disable(EnableCap.Texture2D);
				GL.Enable(EnableCap.Blend);
				GL.Color4(0f, 0f, 0f, 0.5f);
				render.DrawAliasShadow(extraData, render._LastPoseNum);
				GL.Enable(EnableCap.Texture2D);
				GL.Disable(EnableCap.Blend);
				GL.Color4(1f, 1f, 1f, 1f);
				GL.PopMatrix();
			}
		}

		private static void DrawAliasShadow(aliashdr_t paliashdr, int posenum)
		{
			float num = render._CurrentEntity.origin.Z - render._LightSpot.Z;
			trivertx_t[] posedata = paliashdr.posedata;
			int num2 = posenum * paliashdr.poseverts;
			int[] commands = paliashdr.commands;
			float z = -num + 1f;
			int num3 = 0;
			for (;;)
			{
				int num4 = commands[num3++];
				if (num4 == 0)
				{
					break;
				}
				if (num4 < 0)
				{
					num4 = -num4;
					GL.Begin(PrimitiveType.TriangleFan);
				}
				else
				{
					GL.Begin(PrimitiveType.TriangleStrip);
				}
				do
				{
					num3 += 2;
					Vector3 vector = new Vector3((float)posedata[num2].v[0] * paliashdr.scale.X + paliashdr.scale_origin.X, (float)posedata[num2].v[1] * paliashdr.scale.Y + paliashdr.scale_origin.Y, (float)posedata[num2].v[2] * paliashdr.scale.Z + paliashdr.scale_origin.Z);
					vector.X -= render._ShadeVector.X * (vector.Z + num);
					vector.Y -= render._ShadeVector.Y * (vector.Z + num);
					vector.Z = z;
					GL.Vertex3(vector);
					num2++;
				}
				while (--num4 > 0);
				GL.End();
			}
		}

		private static void SetupAliasFrame(int frame, aliashdr_t paliashdr)
		{
			if (frame >= paliashdr.numframes || frame < 0)
			{
				Con.DPrint("R_AliasSetupFrame: no such frame {0}\n", new object[]
				{
					frame
				});
				frame = 0;
			}
			int num = paliashdr.frames[frame].firstpose;
			int numposes = paliashdr.frames[frame].numposes;
			if (numposes > 1)
			{
				float interval = paliashdr.frames[frame].interval;
				num += (int)(client.cl.time / (double)interval) % numposes;
			}
			render.DrawAliasFrame(paliashdr, num);
		}

		private static void DrawAliasFrame(aliashdr_t paliashdr, int posenum)
		{
			render._LastPoseNum = posenum;
			trivertx_t[] posedata = paliashdr.posedata;
			int num = posenum * paliashdr.poseverts;
			int[] commands = paliashdr.commands;
			int num2 = 0;
			for (;;)
			{
				int num3 = commands[num2++];
				if (num3 == 0)
				{
					break;
				}
				if (num3 < 0)
				{
					num3 = -num3;
					GL.Begin(PrimitiveType.TriangleFan);
				}
				else
				{
					GL.Begin(PrimitiveType.TriangleStrip);
				}
				Union4b empty = Union4b.Empty;
				Union4b empty2 = Union4b.Empty;
				do
				{
					empty.i0 = commands[num2];
					empty2.i0 = commands[num2 + 1];
					num2 += 2;
					GL.TexCoord2(empty.f0, empty2.f0);
					float num4 = render._ShadeDots[(int)posedata[num].lightnormalindex] * render._ShadeLight;
					GL.Color3(num4, num4, num4);
					GL.Vertex3((float)posedata[num].v[0], (float)posedata[num].v[1], (float)posedata[num].v[2]);
					num++;
				}
				while (--num3 > 0);
				GL.End();
			}
		}

		private static void RotateForEntity(entity_t e)
		{
			GL.Translate(e.origin);
			GL.Rotate(e.angles.Y, 0f, 0f, 1f);
			GL.Rotate(-e.angles.X, 0f, 1f, 0f);
			GL.Rotate(e.angles.Z, 1f, 0f, 0f);
		}

		private static void SetupGL()
		{
			GL.MatrixMode(MatrixMode.Projection);
			GL.LoadIdentity();
			int num = render._RefDef.vrect.x * Scr.glWidth / Scr.vid.width;
			int num2 = (render._RefDef.vrect.x + render._RefDef.vrect.width) * Scr.glWidth / Scr.vid.width;
			int num3 = (Scr.vid.height - render._RefDef.vrect.y) * Scr.glHeight / Scr.vid.height;
			int num4 = (Scr.vid.height - (render._RefDef.vrect.y + render._RefDef.vrect.height)) * Scr.glHeight / Scr.vid.height;
			if (num > 0)
			{
				num--;
			}
			if (num2 < Scr.glWidth)
			{
				num2++;
			}
			if (num4 < 0)
			{
				num4--;
			}
			if (num3 < Scr.glHeight)
			{
				num3++;
			}
			int width = num2 - num;
			int height = num3 - num4;
			if (render._IsEnvMap)
			{
				num4 = (num = 0);
				height = (width = 256);
			}
			GL.Viewport(Scr.glX + num, Scr.glY + num4, width, height);
			float num5 = (float)render._RefDef.vrect.width / (float)render._RefDef.vrect.height;
			render.MYgluPerspective((double)render._RefDef.fov_y, (double)num5, 4.0, 4096.0);
			if (render._IsMirror)
			{
				if (render._MirrorPlane.normal.Z != 0f)
				{
					GL.Scale(1f, -1f, 1f);
				}
				else
				{
					GL.Scale(-1f, 1f, 1f);
				}
				GL.CullFace(CullFaceMode.Back);
			}
			else
			{
				GL.CullFace(CullFaceMode.Front);
			}
			GL.MatrixMode(MatrixMode.Modelview);
			GL.LoadIdentity();
			GL.Rotate(-90f, 1f, 0f, 0f);
			GL.Rotate(90f, 0f, 0f, 1f);
			GL.Rotate(-render._RefDef.viewangles.Z, 1f, 0f, 0f);
			GL.Rotate(-render._RefDef.viewangles.X, 0f, 1f, 0f);
			GL.Rotate(-render._RefDef.viewangles.Y, 0f, 0f, 1f);
			GL.Translate(-render._RefDef.vieworg.X, -render._RefDef.vieworg.Y, -render._RefDef.vieworg.Z);
			GL.GetFloat(GetPName.Modelview0MatrixExt, out render._WorldMatrix);
			if (render._glCull.Value != 0f)
			{
				GL.Enable(EnableCap.CullFace);
			}
			else
			{
				GL.Disable(EnableCap.CullFace);
			}
			GL.Disable(EnableCap.Blend);
			GL.Disable(EnableCap.AlphaTest);
			GL.Enable(EnableCap.DepthTest);
		}

		private static void MYgluPerspective(double fovy, double aspect, double zNear, double zFar)
		{
			double num = zNear * Math.Tan(fovy * 3.1415926535897931 / 360.0);
			double num2 = -num;
			double left = num2 * aspect;
			double right = num * aspect;
			GL.Frustum(left, right, num2, num, zNear, zFar);
		}

		private static void SetFrustum()
		{
			if (render._RefDef.fov_x == 90f)
			{
				render._Frustum[0].normal = render.ViewPn + render.ViewRight;
				render._Frustum[1].normal = render.ViewPn - render.ViewRight;
				render._Frustum[2].normal = render.ViewPn + render.ViewUp;
				render._Frustum[3].normal = render.ViewPn - render.ViewUp;
			}
			else
			{
				mathlib.RotatePointAroundVector(out render._Frustum[0].normal, ref render.ViewUp, ref render.ViewPn, -(90f - render._RefDef.fov_x / 2f));
				mathlib.RotatePointAroundVector(out render._Frustum[1].normal, ref render.ViewUp, ref render.ViewPn, 90f - render._RefDef.fov_x / 2f);
				mathlib.RotatePointAroundVector(out render._Frustum[2].normal, ref render.ViewRight, ref render.ViewPn, 90f - render._RefDef.fov_y / 2f);
				mathlib.RotatePointAroundVector(out render._Frustum[3].normal, ref render.ViewRight, ref render.ViewPn, -(90f - render._RefDef.fov_y / 2f));
			}
			for (int i = 0; i < 4; i++)
			{
				render._Frustum[i].type = 5;
				render._Frustum[i].dist = Vector3.Dot(render.Origin, render._Frustum[i].normal);
				render._Frustum[i].signbits = (byte)render.SignbitsForPlane(render._Frustum[i]);
			}
		}

		private static int SignbitsForPlane(mplane_t p)
		{
			int num = 0;
			if (p.normal.X < 0f)
			{
				num |= 1;
			}
			if (p.normal.Y < 0f)
			{
				num |= 2;
			}
			if (p.normal.Z < 0f)
			{
				num |= 4;
			}
			return num;
		}

		private static void SetupFrame()
		{
			if (client.cl.maxclients > 1)
			{
				cvar.Set("r_fullbright", "0");
			}
			render.AnimateLight();
			render._FrameCount++;
			render.Origin = render._RefDef.vieworg;
			mathlib.AngleVectors(ref render._RefDef.viewangles, out render.ViewPn, out render.ViewRight, out render.ViewUp);
			render._OldViewLeaf = render._ViewLeaf;
			render._ViewLeaf = Mod.PointInLeaf(ref render.Origin, client.cl.worldmodel);
			view.SetContentsColor(render._ViewLeaf.contents);
			view.CalcBlend();
			render._CacheThrash = false;
			render._BrushPolys = 0;
			render._AliasPolys = 0;
		}

		private static void Clear()
		{
			if ((double)render._MirrorAlpha.Value != 1.0)
			{
				if (render._glClear.Value != 0f)
				{
					GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
				}
				else
				{
					GL.Clear(ClearBufferMask.DepthBufferBit);
				}
				render._glDepthMin = 0f;
				render._glDepthMax = 0.5f;
				GL.DepthFunc(DepthFunction.Lequal);
			}
			else if (vid.glZTrick)
			{
				if (render._glClear.Value != 0f)
				{
					GL.Clear(ClearBufferMask.ColorBufferBit);
				}
				render._TrickFrame++;
				if ((render._TrickFrame & 1) != 0)
				{
					render._glDepthMin = 0f;
					render._glDepthMax = 0.49999f;
					GL.DepthFunc(DepthFunction.Lequal);
				}
				else
				{
					render._glDepthMin = 1f;
					render._glDepthMax = 0.5f;
					GL.DepthFunc(DepthFunction.Gequal);
				}
			}
			else
			{
				if (render._glClear.Value != 0f)
				{
					GL.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit);
					sbar.Changed();
				}
				else
				{
					GL.Clear(ClearBufferMask.DepthBufferBit);
				}
				render._glDepthMin = 0f;
				render._glDepthMax = 1f;
				GL.DepthFunc(DepthFunction.Lequal);
			}
			GL.DepthRange(render._glDepthMin, render._glDepthMax);
		}

		private static void TimeRefresh_f()
		{
			GL.Finish();
			double floatTime = sys.GetFloatTime();
			for (int i = 0; i < 128; i++)
			{
				render._RefDef.viewangles.Y = (float)((double)i / 128.0 * 360.0);
				render.RenderView();
				mainwindow.Instance.SwapBuffers();
			}
			GL.Finish();
			double num = sys.GetFloatTime() - floatTime;
			Con.Print("{0:F} seconds ({1:F1} fps)\n", new object[]
			{
				num,
				128.0 / num
			});
			Scr.EndRendering();
		}

		private static bool CullBox(ref Vector3 mins, ref Vector3 maxs)
		{
			for (int i = 0; i < 4; i++)
			{
				if (mathlib.BoxOnPlaneSide(ref mins, ref maxs, render._Frustum[i]) == 2)
				{
					return true;
				}
			}
			return false;
		}

		public static void AddEfrags(entity_t ent)
		{
			if (ent.model == null)
			{
				return;
			}
			render._AddEnt = ent;
			render._LastObj = ent;
			render._EfragTopNode = null;
			model_t model = ent.model;
			render._EMins = ent.origin + model.mins;
			render._EMaxs = ent.origin + model.maxs;
			render.SplitEntityOnNode(client.cl.worldmodel.nodes[0]);
			ent.topnode = render._EfragTopNode;
		}

		private static void SplitEntityOnNode(mnodebase_t node)
		{
			if (node.contents == -2)
			{
				return;
			}
			if (node.contents < 0)
			{
				if (render._EfragTopNode == null)
				{
					render._EfragTopNode = (node as mnode_t);
				}
				mleaf_t mleaf_t = (mleaf_t)node;
				efrag_t free_efrags = client.cl.free_efrags;
				if (free_efrags == null)
				{
					Con.Print("Too many efrags!\n", Array.Empty<object>());
					return;
				}
				client.cl.free_efrags = client.cl.free_efrags.entnext;
				free_efrags.entity = render._AddEnt;
				if (render._LastObj is entity_t)
				{
					((entity_t)render._LastObj).efrag = free_efrags;
				}
				else
				{
					((efrag_t)render._LastObj).entnext = free_efrags;
				}
				render._LastObj = free_efrags;
				free_efrags.entnext = null;
				free_efrags.leaf = mleaf_t;
				free_efrags.leafnext = mleaf_t.efrags;
				mleaf_t.efrags = free_efrags;
				return;
			}
			else
			{
				mnode_t mnode_t = node as mnode_t;
				if (mnode_t == null)
				{
					return;
				}
				mplane_t plane = mnode_t.plane;
				int num = mathlib.BoxOnPlaneSide(ref render._EMins, ref render._EMaxs, plane);
				if (num == 3 && render._EfragTopNode == null)
				{
					render._EfragTopNode = mnode_t;
				}
				if ((num & 1) != 0)
				{
					render.SplitEntityOnNode(mnode_t.children[0]);
				}
				if ((num & 2) != 0)
				{
					render.SplitEntityOnNode(mnode_t.children[1]);
				}
				return;
			}
		}

		private static void StoreEfrags(efrag_t ef)
		{
			while (ef != null)
			{
				entity_t entity = ef.entity;
				model_t model = entity.model;
				modtype_t type = model.type;
				if (type <= modtype_t.mod_alias)
				{
					if (entity.visframe != render._FrameCount && client.NumVisEdicts < 256)
					{
						client.VisEdicts[client.NumVisEdicts++] = entity;
						entity.visframe = render._FrameCount;
					}
					ef = ef.leafnext;
				}
				else
				{
					sys.Error("R_StoreEfrags: Bad entity type {0}\n", new object[]
					{
						model.type
					});
				}
			}
		}

		public static void PushDlights()
		{
			if (render._glFlashBlend.Value != 0f)
			{
				return;
			}
			render._DlightFrameCount = render._FrameCount + 1;
			for (int i = 0; i < 32; i++)
			{
				dlight_t dlight_t = client.DLights[i];
				if ((double)dlight_t.die >= client.cl.time && dlight_t.radius != 0f)
				{
					render.MarkLights(dlight_t, 1 << i, client.cl.worldmodel.nodes[0]);
				}
			}
		}

		private static void MarkLights(dlight_t light, int bit, mnodebase_t node)
		{
			if (node.contents < 0)
			{
				return;
			}
			mnode_t mnode_t = (mnode_t)node;
			mplane_t plane = mnode_t.plane;
			float num = Vector3.Dot(light.origin, plane.normal) - plane.dist;
			if (num > light.radius)
			{
				render.MarkLights(light, bit, mnode_t.children[0]);
				return;
			}
			if (num < -light.radius)
			{
				render.MarkLights(light, bit, mnode_t.children[1]);
				return;
			}
			for (int i = 0; i < (int)mnode_t.numsurfaces; i++)
			{
				msurface_t msurface_t = client.cl.worldmodel.surfaces[(int)mnode_t.firstsurface + i];
				if (msurface_t.dlightframe != render._DlightFrameCount)
				{
					msurface_t.dlightbits = 0;
					msurface_t.dlightframe = render._DlightFrameCount;
				}
				msurface_t.dlightbits |= bit;
			}
			render.MarkLights(light, bit, mnode_t.children[0]);
			render.MarkLights(light, bit, mnode_t.children[1]);
		}

		private static void RenderDlights()
		{
			if (render._glFlashBlend.Value == 0f)
			{
				return;
			}
			render._DlightFrameCount = render._FrameCount + 1;
			GL.DepthMask(false);
			GL.Disable(EnableCap.Texture2D);
			GL.ShadeModel(ShadingModel.Smooth);
			GL.Enable(EnableCap.Blend);
			GL.BlendFunc(BlendingFactor.One, BlendingFactor.One);
			for (int i = 0; i < 32; i++)
			{
				dlight_t dlight_t = client.DLights[i];
				if ((double)dlight_t.die >= client.cl.time && dlight_t.radius != 0f)
				{
					render.RenderDlight(dlight_t);
				}
			}
			GL.Color3(1f, 1f, 1f);
			GL.Disable(EnableCap.Blend);
			GL.Enable(EnableCap.Texture2D);
			GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
			GL.DepthMask(true);
		}

		private static void AnimateLight()
		{
			int num = (int)(client.cl.time * 10.0);
			for (int i = 0; i < 64; i++)
			{
				if (string.IsNullOrEmpty(client.LightStyle[i].map))
				{
					render._LightStyleValue[i] = 256;
				}
				else
				{
					string map = client.LightStyle[i].map;
					int num2 = num % map.Length;
					num2 = (int)(map[num2] - 'a');
					num2 *= 22;
					render._LightStyleValue[i] = num2;
				}
			}
		}

		private static int LightPoint(ref Vector3 p)
		{
			if (client.cl.worldmodel.lightdata == null)
			{
				return 255;
			}
			Vector3 vector = p;
			vector.Z -= 2048f;
			int num = render.RecursiveLightPoint(client.cl.worldmodel.nodes[0], ref p, ref vector);
			if (num == -1)
			{
				num = 0;
			}
			return num;
		}

		private static int RecursiveLightPoint(mnodebase_t node, ref Vector3 start, ref Vector3 end)
		{
			if (node.contents < 0)
			{
				return -1;
			}
			mnode_t mnode_t = (mnode_t)node;
			mplane_t plane = mnode_t.plane;
			float num = Vector3.Dot(start, plane.normal) - plane.dist;
			float num2 = Vector3.Dot(end, plane.normal) - plane.dist;
			int num3 = (num < 0f) ? 1 : 0;
			if (((num2 < 0f) ? 1 : 0) == num3)
			{
				return render.RecursiveLightPoint(mnode_t.children[num3], ref start, ref end);
			}
			float scale = num / (num - num2);
			Vector3 vector = start + (end - start) * scale;
			int num4 = render.RecursiveLightPoint(mnode_t.children[num3], ref start, ref vector);
			if (num4 >= 0)
			{
				return num4;
			}
			if (((num2 < 0f) ? 1 : 0) == num3)
			{
				return -1;
			}
			render._LightSpot = vector;
			render._LightPlane = plane;
			msurface_t[] surfaces = client.cl.worldmodel.surfaces;
			int num5 = (int)mnode_t.firstsurface;
			int i = 0;
			while (i < (int)mnode_t.numsurfaces)
			{
				if ((surfaces[num5].flags & 32) == 0)
				{
					mtexinfo_t texinfo = surfaces[num5].texinfo;
					int num6 = (int)(Vector3.Dot(vector, texinfo.vecs[0].Xyz) + texinfo.vecs[0].W);
					int num7 = (int)(Vector3.Dot(vector, texinfo.vecs[1].Xyz) + texinfo.vecs[1].W);
					if (num6 >= (int)surfaces[num5].texturemins[0] && num7 >= (int)surfaces[num5].texturemins[1])
					{
						int num8 = num6 - (int)surfaces[num5].texturemins[0];
						int num9 = num7 - (int)surfaces[num5].texturemins[1];
						if (num8 <= (int)surfaces[num5].extents[0] && num9 <= (int)surfaces[num5].extents[1])
						{
							if (surfaces[num5].sample_base == null)
							{
								return 0;
							}
							num8 >>= 4;
							num9 >>= 4;
							byte[] sample_base = surfaces[num5].sample_base;
							int num10 = surfaces[num5].sampleofs;
							short[] extents = surfaces[num5].extents;
							num4 = 0;
							if (sample_base != null)
							{
								num10 += num9 * ((extents[0] >> 4) + 1) + num8;
								int num11 = 0;
								while (num11 < 4 && surfaces[num5].styles[num11] != 255)
								{
									int num12 = render._LightStyleValue[(int)surfaces[num5].styles[num11]];
									num4 += (int)sample_base[num10] * num12;
									num10 += ((extents[0] >> 4) + 1) * ((extents[1] >> 4) + 1);
									num11++;
								}
								num4 >>= 8;
							}
							return num4;
						}
					}
				}
				i++;
				num5++;
			}
			return render.RecursiveLightPoint(mnode_t.children[(num3 == 0) ? 1 : 0], ref vector, ref end);
		}

		private static void RenderDlight(dlight_t light)
		{
			float num = light.radius * 0.35f;
			if ((light.origin - render.Origin).Length < num)
			{
				render.AddLightBlend(1f, 0.5f, 0f, light.radius * 0.0003f);
				return;
			}
			GL.Begin(PrimitiveType.TriangleFan);
			GL.Color3(0.2f, 0.1f, 0f);
			Vector3 v = light.origin - render.ViewPn * num;
			GL.Vertex3(v);
			GL.Color3(0, 0, 0);
			for (int i = 16; i >= 0; i--)
			{
				double num2 = (double)i / 16.0 * 3.1415926535897931 * 2.0;
				v = light.origin + render.ViewRight * (float)Math.Cos(num2) * num + render.ViewUp * (float)Math.Sin(num2) * num;
				GL.Vertex3(v);
			}
			GL.End();
		}

		private static void AddLightBlend(float r, float g, float b, float a2)
		{
			view.Blend.A = view.Blend.A + a2 * (1f - view.Blend.A);
			float a3 = view.Blend.A;
			a2 /= a3;
			view.Blend.R = view.Blend.R * (1f - a2) + r * a2;
			view.Blend.G = view.Blend.G * (1f - a2) + g * a2;
			view.Blend.B = view.Blend.B * (1f - a2) + b * a2;
		}

		public static void RocketTrail(ref Vector3 start, ref Vector3 end, int type)
		{
			Vector3 vector = end - start;
			float num = mathlib.Normalize(ref vector);
			int num2;
			if (type < 128)
			{
				num2 = 3;
			}
			else
			{
				num2 = 1;
				type -= 128;
			}
			while (num > 0f)
			{
				num -= (float)num2;
				render.particle_t particle_t = render.AllocParticle();
				if (particle_t == null)
				{
					return;
				}
				particle_t.vel = Vector3.Zero;
				particle_t.die = (float)client.cl.time + 2f;
				switch (type)
				{
				case 0:
					particle_t.ramp = (float)(sys.Random() & 3);
					particle_t.color = (float)render._Ramp3[(int)particle_t.ramp];
					particle_t.type = render.ptype_t.pt_fire;
					particle_t.org = new Vector3(start.X + (float)(sys.Random() % 6 - 3), start.Y + (float)(sys.Random() % 6 - 3), start.Z + (float)(sys.Random() % 6 - 3));
					break;
				case 1:
					particle_t.ramp = (float)((sys.Random() & 3) + 2);
					particle_t.color = (float)render._Ramp3[(int)particle_t.ramp];
					particle_t.type = render.ptype_t.pt_fire;
					particle_t.org = new Vector3(start.X + (float)(sys.Random() % 6 - 3), start.Y + (float)(sys.Random() % 6 - 3), start.Z + (float)(sys.Random() % 6 - 3));
					break;
				case 2:
					particle_t.type = render.ptype_t.pt_grav;
					particle_t.color = (float)(67 + (sys.Random() & 3));
					particle_t.org = new Vector3(start.X + (float)(sys.Random() % 6 - 3), start.Y + (float)(sys.Random() % 6 - 3), start.Z + (float)(sys.Random() % 6 - 3));
					break;
				case 3:
				case 5:
					particle_t.die = (float)client.cl.time + 0.5f;
					particle_t.type = render.ptype_t.pt_static;
					if (type == 3)
					{
						particle_t.color = (float)(52 + ((render._TracerCount & 4) << 1));
					}
					else
					{
						particle_t.color = (float)(230 + ((render._TracerCount & 4) << 1));
					}
					render._TracerCount++;
					particle_t.org = start;
					if ((render._TracerCount & 1) != 0)
					{
						particle_t.vel.X = 30f * vector.Y;
						particle_t.vel.Y = 30f * -vector.X;
					}
					else
					{
						particle_t.vel.X = 30f * -vector.Y;
						particle_t.vel.Y = 30f * vector.X;
					}
					break;
				case 4:
					particle_t.type = render.ptype_t.pt_grav;
					particle_t.color = (float)(67 + (sys.Random() & 3));
					particle_t.org = new Vector3(start.X + (float)(sys.Random() % 6 - 3), start.Y + (float)(sys.Random() % 6 - 3), start.Z + (float)(sys.Random() % 6 - 3));
					num -= 3f;
					break;
				case 6:
					particle_t.color = (float)(152 + (sys.Random() & 3));
					particle_t.type = render.ptype_t.pt_static;
					particle_t.die = (float)client.cl.time + 0.3f;
					particle_t.org = new Vector3(start.X + (float)(sys.Random() % 15 - 8), start.Y + (float)(sys.Random() % 15 - 8), start.Z + (float)(sys.Random() % 15 - 8));
					break;
				}
				start += vector;
			}
		}

		public static void ParticleExplosion(ref Vector3 org)
		{
			for (int i = 0; i < 1024; i++)
			{
				render.particle_t particle_t = render.AllocParticle();
				if (particle_t == null)
				{
					return;
				}
				particle_t.die = (float)client.cl.time + 5f;
				particle_t.color = (float)render._Ramp1[0];
				particle_t.ramp = (float)(sys.Random() & 3);
				if ((i & 1) != 0)
				{
					particle_t.type = render.ptype_t.pt_explode;
				}
				else
				{
					particle_t.type = render.ptype_t.pt_explode2;
				}
				particle_t.org = org + new Vector3((float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16));
				particle_t.vel = new Vector3((float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256));
			}
		}

		public static void RunParticleEffect(ref Vector3 org, ref Vector3 dir, int color, int count)
		{
			for (int i = 0; i < count; i++)
			{
				render.particle_t particle_t = render.AllocParticle();
				if (particle_t == null)
				{
					return;
				}
				if (count == 1024)
				{
					particle_t.die = (float)client.cl.time + 5f;
					particle_t.color = (float)render._Ramp1[0];
					particle_t.ramp = (float)(sys.Random() & 3);
					if ((i & 1) != 0)
					{
						particle_t.type = render.ptype_t.pt_explode;
					}
					else
					{
						particle_t.type = render.ptype_t.pt_explode2;
					}
					particle_t.org = org + new Vector3((float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16));
					particle_t.vel = new Vector3((float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256));
				}
				else
				{
					particle_t.die = (float)client.cl.time + 0.1f * (float)(sys.Random() % 5);
					particle_t.color = (float)((color & -8) + (sys.Random() & 7));
					particle_t.type = render.ptype_t.pt_slowgrav;
					particle_t.org = org + new Vector3((float)((sys.Random() & 15) - 8), (float)((sys.Random() & 15) - 8), (float)((sys.Random() & 15) - 8));
					particle_t.vel = dir * 15f;
				}
			}
		}

		public static void ParseParticleEffect()
		{
			Vector3 vector = net.Reader.ReadCoords();
			Vector3 vector2 = new Vector3((float)net.Reader.ReadChar() * 0.0625f, (float)net.Reader.ReadChar() * 0.0625f, (float)net.Reader.ReadChar() * 0.0625f);
			int num = net.Reader.ReadByte();
			int color = net.Reader.ReadByte();
			if (num == 255)
			{
				num = 1024;
			}
			render.RunParticleEffect(ref vector, ref vector2, color, num);
		}

		public static void TeleportSplash(ref Vector3 org)
		{
			for (int i = -16; i < 16; i += 4)
			{
				for (int j = -16; j < 16; j += 4)
				{
					for (int k = -24; k < 32; k += 4)
					{
						render.particle_t particle_t = render.AllocParticle();
						if (particle_t == null)
						{
							return;
						}
						particle_t.die = (float)(client.cl.time + 0.2 + (double)(sys.Random() & 7) * 0.02);
						particle_t.color = (float)(7 + (sys.Random() & 7));
						particle_t.type = render.ptype_t.pt_slowgrav;
						Vector3 vec = new Vector3((float)(j * 8), (float)(i * 8), (float)(k * 8));
						particle_t.org = org + new Vector3((float)(i + (sys.Random() & 3)), (float)(j + (sys.Random() & 3)), (float)(k + (sys.Random() & 3)));
						mathlib.Normalize(ref vec);
						float scale = (float)(50 + (sys.Random() & 63));
						particle_t.vel = vec * scale;
					}
				}
			}
		}

		public static void LavaSplash(ref Vector3 org)
		{
			for (int i = -16; i < 16; i++)
			{
				for (int j = -16; j < 16; j++)
				{
					for (int k = 0; k < 1; k++)
					{
						render.particle_t particle_t = render.AllocParticle();
						if (particle_t == null)
						{
							return;
						}
						particle_t.die = (float)(client.cl.time + 2.0 + (double)(sys.Random() & 31) * 0.02);
						particle_t.color = (float)(224 + (sys.Random() & 7));
						particle_t.type = render.ptype_t.pt_slowgrav;
						Vector3 vector;
						vector.X = (float)(j * 8 + (sys.Random() & 7));
						vector.Y = (float)(i * 8 + (sys.Random() & 7));
						vector.Z = 256f;
						particle_t.org = org + vector;
						render.particle_t particle_t2 = particle_t;
						particle_t2.org.Z = particle_t2.org.Z + (float)(sys.Random() & 63);
						mathlib.Normalize(ref vector);
						float scale = (float)(50 + (sys.Random() & 63));
						particle_t.vel = vector * scale;
					}
				}
			}
		}

		public static void ParticleExplosion(ref Vector3 org, int colorStart, int colorLength)
		{
			int num = 0;
			for (int i = 0; i < 512; i++)
			{
				render.particle_t particle_t = render.AllocParticle();
				if (particle_t == null)
				{
					return;
				}
				particle_t.die = (float)(client.cl.time + 0.3);
				particle_t.color = (float)(colorStart + num % colorLength);
				num++;
				particle_t.type = render.ptype_t.pt_blob;
				particle_t.org = org + new Vector3((float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16));
				particle_t.vel = new Vector3((float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256));
			}
		}

		public static void BlobExplosion(ref Vector3 org)
		{
			for (int i = 0; i < 1024; i++)
			{
				render.particle_t particle_t = render.AllocParticle();
				if (particle_t == null)
				{
					return;
				}
				particle_t.die = (float)(client.cl.time + 1.0 + (double)(sys.Random() & 8) * 0.05);
				if ((i & 1) != 0)
				{
					particle_t.type = render.ptype_t.pt_blob;
					particle_t.color = (float)(66 + sys.Random() % 6);
				}
				else
				{
					particle_t.type = render.ptype_t.pt_blob2;
					particle_t.color = (float)(150 + sys.Random() % 6);
				}
				particle_t.org = org + new Vector3((float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16), (float)(sys.Random() % 32 - 16));
				particle_t.vel = new Vector3((float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256), (float)(sys.Random() % 512 - 256));
			}
		}

		public static void EntityParticles(entity_t ent)
		{
			float scale = 64f;
			if (render._AVelocities[0].X == 0f)
			{
				for (int i = 0; i < 162; i++)
				{
					render._AVelocities[i].X = (float)(sys.Random() & 255) * 0.01f;
					render._AVelocities[i].Y = (float)(sys.Random() & 255) * 0.01f;
					render._AVelocities[i].Z = (float)(sys.Random() & 255) * 0.01f;
				}
			}
			for (int j = 0; j < 162; j++)
			{
				double num = client.cl.time * (double)render._AVelocities[j].X;
				double num2 = Math.Sin(num);
				double num3 = Math.Cos(num);
				double num4 = client.cl.time * (double)render._AVelocities[j].Y;
				double num5 = Math.Sin(num4);
				double num6 = Math.Cos(num4);
				double num7 = client.cl.time * (double)render._AVelocities[j].Z;
				Math.Sin(num7);
				Math.Cos(num7);
				Vector3 vec = new Vector3((float)(num6 * num3), (float)(num6 * num2), (float)(-(float)num5));
				render.particle_t particle_t = render.AllocParticle();
				if (particle_t == null)
				{
					return;
				}
				particle_t.die = (float)(client.cl.time + 0.01);
				particle_t.color = 111f;
				particle_t.type = render.ptype_t.pt_explode;
				particle_t.org = ent.origin + anorms.Values[j] * scale + vec * render._BeamLength;
			}
		}

		private static void InitParticles()
		{
			int i = common.CheckParm("-particles");
			if (i > 0 && i < common.Argc - 1)
			{
				render._NumParticles = int.Parse(common.Argv(i + 1));
				if (render._NumParticles < 512)
				{
					render._NumParticles = 512;
				}
			}
			else
			{
				render._NumParticles = 2048;
			}
			render._Particles = new render.particle_t[render._NumParticles];
			for (i = 0; i < render._NumParticles; i++)
			{
				render._Particles[i] = new render.particle_t();
			}
		}

		private static void InitParticleTexture()
		{
			render._ParticleTexture = Drawer.GenerateTextureNumber();
			Drawer.Bind(render._ParticleTexture);
			byte[,,] array = new byte[8, 8, 4];
			for (int i = 0; i < 8; i++)
			{
				for (int j = 0; j < 8; j++)
				{
					array[j, i, 0] = byte.MaxValue;
					array[j, i, 1] = byte.MaxValue;
					array[j, i, 2] = byte.MaxValue;
					array[j, i, 3] = render._DotTexture[i, j] * byte.MaxValue;
				}
			}
			GL.TexImage2D<byte>(TextureTarget.Texture2D, 0, Drawer.AlphaFormat, 8, 8, 0, PixelFormat.Rgba, PixelType.UnsignedByte, array);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 8448);
			Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear);
		}

		private static void ClearParticles()
		{
			render._FreeParticles = render._Particles[0];
			render._ActiveParticles = null;
			for (int i = 0; i < render._NumParticles - 1; i++)
			{
				render._Particles[i].next = render._Particles[i + 1];
			}
			render._Particles[render._NumParticles - 1].next = null;
		}

		private static void DrawParticles()
		{
			Drawer.Bind(render._ParticleTexture);
			GL.Enable(EnableCap.Blend);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 8448);
			GL.Begin(PrimitiveType.Triangles);
			Vector3 vec = render.ViewUp * 1.5f;
			Vector3 vec2 = render.ViewRight * 1.5f;
			float num = (float)(client.cl.time - client.cl.oldtime);
			float num2 = num * 15f;
			float num3 = num * 10f;
			float num4 = num * 5f;
			float num5 = num * server.Gravity * 0.05f;
			float scale = 4f * num;
			for (;;)
			{
				render.particle_t activeParticles = render._ActiveParticles;
				if (activeParticles == null || (double)activeParticles.die >= client.cl.time)
				{
					break;
				}
				render._ActiveParticles = activeParticles.next;
				activeParticles.next = render._FreeParticles;
				render._FreeParticles = activeParticles;
			}
			for (render.particle_t particle_t = render._ActiveParticles; particle_t != null; particle_t = particle_t.next)
			{
				for (;;)
				{
					render.particle_t next = particle_t.next;
					if (next == null || (double)next.die >= client.cl.time)
					{
						break;
					}
					particle_t.next = next.next;
					next.next = render._FreeParticles;
					render._FreeParticles = next;
				}
				float num6 = Vector3.Dot(particle_t.org - render.Origin, render.ViewPn);
				if (num6 < 20f)
				{
					num6 = 1f;
				}
				else
				{
					num6 = 1f + num6 * 0.004f;
				}
				uint num7 = vid.Table8to24[(int)((byte)particle_t.color)];
				GL.Color4((byte)(num7 & 255u), (byte)(num7 >> 8 & 255u), (byte)(num7 >> 16 & 255u), (byte)(num7 >> 24 & 255u));
				GL.TexCoord2(0f, 0f);
				GL.Vertex3(particle_t.org);
				GL.TexCoord2(1f, 0f);
				GL.Vertex3(particle_t.org + vec * num6);
				GL.TexCoord2(0f, 1f);
				GL.Vertex3(particle_t.org + vec2 * num6);
				particle_t.org += particle_t.vel * num;
				switch (particle_t.type)
				{
				case render.ptype_t.pt_grav:
				case render.ptype_t.pt_slowgrav:
				{
					render.particle_t particle_t2 = particle_t;
					particle_t2.vel.Z = particle_t2.vel.Z - num5;
					break;
				}
				case render.ptype_t.pt_fire:
				{
					particle_t.ramp += num4;
					if (particle_t.ramp >= 6f)
					{
						particle_t.die = -1f;
					}
					else
					{
						particle_t.color = (float)render._Ramp3[(int)particle_t.ramp];
					}
					render.particle_t particle_t3 = particle_t;
					particle_t3.vel.Z = particle_t3.vel.Z + num5;
					break;
				}
				case render.ptype_t.pt_explode:
				{
					particle_t.ramp += num3;
					if (particle_t.ramp >= 8f)
					{
						particle_t.die = -1f;
					}
					else
					{
						particle_t.color = (float)render._Ramp1[(int)particle_t.ramp];
					}
					particle_t.vel += particle_t.vel * scale;
					render.particle_t particle_t4 = particle_t;
					particle_t4.vel.Z = particle_t4.vel.Z - num5;
					break;
				}
				case render.ptype_t.pt_explode2:
				{
					particle_t.ramp += num2;
					if (particle_t.ramp >= 8f)
					{
						particle_t.die = -1f;
					}
					else
					{
						particle_t.color = (float)render._Ramp2[(int)particle_t.ramp];
					}
					particle_t.vel -= particle_t.vel * num;
					render.particle_t particle_t5 = particle_t;
					particle_t5.vel.Z = particle_t5.vel.Z - num5;
					break;
				}
				case render.ptype_t.pt_blob:
				{
					particle_t.vel += particle_t.vel * scale;
					render.particle_t particle_t6 = particle_t;
					particle_t6.vel.Z = particle_t6.vel.Z - num5;
					break;
				}
				case render.ptype_t.pt_blob2:
				{
					particle_t.vel -= particle_t.vel * scale;
					render.particle_t particle_t7 = particle_t;
					particle_t7.vel.Z = particle_t7.vel.Z - num5;
					break;
				}
				}
			}
			GL.End();
			GL.Disable(EnableCap.Blend);
			GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 7681);
		}

		private static render.particle_t AllocParticle()
		{
			if (render._FreeParticles == null)
			{
				return null;
			}
			render.particle_t freeParticles = render._FreeParticles;
			render._FreeParticles = freeParticles.next;
			freeParticles.next = render._ActiveParticles;
			render._ActiveParticles = freeParticles;
			return freeParticles;
		}

		private static void BuildLightMaps()
		{
			Array.Clear(render._Allocated, 0, render._Allocated.Length);
			render._FrameCount = 1;
			if (render._LightMapTextures == 0)
			{
				render._LightMapTextures = Drawer.GenerateTextureNumberRange(64);
			}
			Drawer.LightMapFormat = PixelFormat.Luminance;
			if (Scr.IsPermedia)
			{
				Drawer.LightMapFormat = PixelFormat.Rgba;
			}
			if (common.HasParam("-lm_1"))
			{
				Drawer.LightMapFormat = PixelFormat.Luminance;
			}
			if (common.HasParam("-lm_a"))
			{
				Drawer.LightMapFormat = PixelFormat.Alpha;
			}
			if (common.HasParam("-lm_4"))
			{
				Drawer.LightMapFormat = PixelFormat.Rgba;
			}
			switch (Drawer.LightMapFormat)
			{
			case PixelFormat.Alpha:
			case PixelFormat.Luminance:
				render._LightMapBytes = 1;
				break;
			case PixelFormat.Rgba:
				render._LightMapBytes = 4;
				break;
			}
			for (int i = 1; i < 256; i++)
			{
				model_t model_t = client.cl.model_precache[i];
				if (model_t == null)
				{
					break;
				}
				if (model_t.name == null || !model_t.name.StartsWith("*"))
				{
					render._CurrentVertBase = model_t.vertexes;
					render._CurrentModel = model_t;
					for (int j = 0; j < model_t.numsurfaces; j++)
					{
						render.CreateSurfaceLightmap(model_t.surfaces[j]);
						if ((model_t.surfaces[j].flags & 16) == 0 && (model_t.surfaces[j].flags & 4) == 0)
						{
							render.BuildSurfaceDisplayList(model_t.surfaces[j]);
						}
					}
				}
			}
			if (render._glTexSort.Value == 0f)
			{
				Drawer.SelectTexture(MTexTarget.TEXTURE1_SGIS);
			}
			GCHandle gchandle = GCHandle.Alloc(render._LightMaps, GCHandleType.Pinned);
			try
			{
				long num = gchandle.AddrOfPinnedObject().ToInt64();
				for (int k = 0; k < 64; k++)
				{
					if (render._Allocated[k, 0] == 0)
					{
						break;
					}
					render._LightMapModified[k] = false;
					render._LightMapRectChange[k].l = 128;
					render._LightMapRectChange[k].t = 128;
					render._LightMapRectChange[k].w = 0;
					render._LightMapRectChange[k].h = 0;
					Drawer.Bind(render._LightMapTextures + k);
					Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear);
					long value = num + (long)(k * 128 * 128 * render._LightMapBytes);
					GL.TexImage2D(TextureTarget.Texture2D, 0, (PixelInternalFormat)render._LightMapBytes, 128, 128, 0, Drawer.LightMapFormat, PixelType.UnsignedByte, new IntPtr(value));
				}
			}
			finally
			{
				gchandle.Free();
			}
			if (render._glTexSort.Value == 0f)
			{
				Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS);
			}
		}

		private static void CreateSurfaceLightmap(msurface_t surf)
		{
			if ((surf.flags & 20) != 0)
			{
				return;
			}
			int w = (surf.extents[0] >> 4) + 1;
			int h = (surf.extents[1] >> 4) + 1;
			surf.lightmaptexturenum = render.AllocBlock(w, h, ref surf.light_s, ref surf.light_t);
			int num = surf.lightmaptexturenum * render._LightMapBytes * 128 * 128;
			num += (surf.light_t * 128 + surf.light_s) * render._LightMapBytes;
			render.BuildLightMap(surf, new ByteArraySegment(render._LightMaps, num), 128 * render._LightMapBytes);
		}

		private static void BuildSurfaceDisplayList(msurface_t fa)
		{
			medge_t[] edges = render._CurrentModel.edges;
			int num = fa.numedges;
			glpoly_t glpoly_t = new glpoly_t();
			glpoly_t.AllocVerts(num);
			glpoly_t.next = fa.polys;
			glpoly_t.flags = fa.flags;
			fa.polys = glpoly_t;
			for (int i = 0; i < num; i++)
			{
				int num2 = render._CurrentModel.surfedges[fa.firstedge + i];
				Vector3 position;
				if (num2 > 0)
				{
					ushort[] v = edges[num2].v;
					position = render._CurrentVertBase[(int)v[0]].position;
				}
				else
				{
					ushort[] v = edges[-num2].v;
					position = render._CurrentVertBase[(int)v[1]].position;
				}
				float num3 = mathlib.DotProduct(ref position, ref fa.texinfo.vecs[0]) + fa.texinfo.vecs[0].W;
				num3 /= fa.texinfo.texture.width;
				float num4 = mathlib.DotProduct(ref position, ref fa.texinfo.vecs[1]) + fa.texinfo.vecs[1].W;
				num4 /= fa.texinfo.texture.height;
				glpoly_t.verts[i][0] = position.X;
				glpoly_t.verts[i][1] = position.Y;
				glpoly_t.verts[i][2] = position.Z;
				glpoly_t.verts[i][3] = num3;
				glpoly_t.verts[i][4] = num4;
				num3 = mathlib.DotProduct(ref position, ref fa.texinfo.vecs[0]) + fa.texinfo.vecs[0].W;
				num3 -= (float)fa.texturemins[0];
				num3 += (float)(fa.light_s * 16);
				num3 += 8f;
				num3 /= 2048f;
				num4 = mathlib.DotProduct(ref position, ref fa.texinfo.vecs[1]) + fa.texinfo.vecs[1].W;
				num4 -= (float)fa.texturemins[1];
				num4 += (float)(fa.light_t * 16);
				num4 += 8f;
				num4 /= 2048f;
				glpoly_t.verts[i][5] = num3;
				glpoly_t.verts[i][6] = num4;
			}
			if (render._glKeepTJunctions.Value == 0f && (fa.flags & 128) == 0)
			{
				for (int j = 0; j < num; j++)
				{
					if (render.IsCollinear(glpoly_t.verts[(j + num - 1) % num], glpoly_t.verts[j], glpoly_t.verts[(j + 1) % num]))
					{
						for (int k = j + 1; k < num; k++)
						{
							for (int l = 0; l < 7; l++)
							{
								glpoly_t.verts[k - 1][l] = glpoly_t.verts[k][l];
							}
						}
						num--;
						render._ColinElim++;
						j--;
					}
				}
			}
			glpoly_t.numverts = num;
		}

		private static bool IsCollinear(float[] prev, float[] cur, float[] next)
		{
			Vector3 vector = new Vector3(cur[0] - prev[0], cur[1] - prev[1], cur[2] - prev[2]);
			mathlib.Normalize(ref vector);
			Vector3 right = new Vector3(next[0] - prev[0], next[1] - prev[1], next[2] - prev[2]);
			mathlib.Normalize(ref right);
			vector -= right;
			return (double)Math.Abs(vector.X) <= 0.001 && (double)Math.Abs(vector.Y) <= 0.001 && (double)Math.Abs(vector.Z) <= 0.001;
		}

		private static int AllocBlock(int w, int h, ref int x, ref int y)
		{
			for (int i = 0; i < 64; i++)
			{
				int num = 128;
				for (int j = 0; j < 128 - w; j++)
				{
					int num2 = 0;
					int num3 = 0;
					while (num3 < w && render._Allocated[i, j + num3] < num)
					{
						if (render._Allocated[i, j + num3] > num2)
						{
							num2 = render._Allocated[i, j + num3];
						}
						num3++;
					}
					if (num3 == w)
					{
						x = j;
						num = (y = num2);
					}
				}
				if (num + h <= 128)
				{
					for (int k = 0; k < w; k++)
					{
						render._Allocated[i, x + k] = num + h;
					}
					return i;
				}
			}
			sys.Error("AllocBlock: full", Array.Empty<object>());
			return 0;
		}

		private static void BuildLightMap(msurface_t surf, ByteArraySegment dest, int stride)
		{
			surf.cached_dlight = (surf.dlightframe == render._FrameCount);
			int num = (surf.extents[0] >> 4) + 1;
			int num2 = (surf.extents[1] >> 4) + 1;
			int num3 = num * num2;
			int num4 = surf.sampleofs;
			byte[] sample_base = surf.sample_base;
			if (render._FullBright.Value != 0f || client.cl.worldmodel.lightdata == null)
			{
				for (int i = 0; i < num3; i++)
				{
					render._BlockLights[i] = 65280u;
				}
			}
			else
			{
				for (int j = 0; j < num3; j++)
				{
					render._BlockLights[j] = 0u;
				}
				if (sample_base != null)
				{
					int num5 = 0;
					while (num5 < 4 && surf.styles[num5] != 255)
					{
						int num6 = render._LightStyleValue[(int)surf.styles[num5]];
						surf.cached_light[num5] = num6;
						for (int k = 0; k < num3; k++)
						{
							render._BlockLights[k] += (uint)((int)sample_base[num4 + k] * num6);
						}
						num4 += num3;
						num5++;
					}
				}
				if (surf.dlightframe == render._FrameCount)
				{
					render.AddDynamicLights(surf);
				}
			}
			int num7 = 0;
			int num8 = dest.StartIndex;
			byte[] data = dest.Data;
			switch (Drawer.LightMapFormat)
			{
			case PixelFormat.Alpha:
			case PixelFormat.Luminance:
			{
				int l = 0;
				while (l < num2)
				{
					for (int m = 0; m < num; m++)
					{
						uint num9 = render._BlockLights[num7++];
						num9 >>= 7;
						if (num9 > 255u)
						{
							num9 = 255u;
						}
						data[num8 + m] = (byte)(255u - num9);
					}
					l++;
					num8 += stride;
				}
				return;
			}
			case PixelFormat.Rgba:
			{
				stride -= num << 2;
				int n = 0;
				while (n < num2)
				{
					for (int num10 = 0; num10 < num; num10++)
					{
						uint num11 = render._BlockLights[num7++];
						num11 >>= 7;
						if (num11 > 255u)
						{
							num11 = 255u;
						}
						data[num8 + 3] = (byte)(255u - num11);
						num8 += 4;
					}
					n++;
					num8 += stride;
				}
				return;
			}
			}
			sys.Error("Bad lightmap format", Array.Empty<object>());
		}

		private static void AddDynamicLights(msurface_t surf)
		{
			int num = (surf.extents[0] >> 4) + 1;
			int num2 = (surf.extents[1] >> 4) + 1;
			mtexinfo_t texinfo = surf.texinfo;
			dlight_t[] dlights = client.DLights;
			for (int i = 0; i < 32; i++)
			{
				if ((surf.dlightbits & 1 << i) != 0)
				{
					float num3 = dlights[i].radius;
					float num4 = Vector3.Dot(dlights[i].origin, surf.plane.normal) - surf.plane.dist;
					num3 -= Math.Abs(num4);
					float num5 = dlights[i].minlight;
					if (num3 >= num5)
					{
						num5 = num3 - num5;
						Vector3 left = dlights[i].origin - surf.plane.normal * num4;
						float num6 = Vector3.Dot(left, texinfo.vecs[0].Xyz) + texinfo.vecs[0].W;
						float num7 = Vector3.Dot(left, texinfo.vecs[1].Xyz) + texinfo.vecs[1].W;
						num6 -= (float)surf.texturemins[0];
						num7 -= (float)surf.texturemins[1];
						for (int j = 0; j < num2; j++)
						{
							int num8 = (int)(num7 - (float)(j * 16));
							if (num8 < 0)
							{
								num8 = -num8;
							}
							for (int k = 0; k < num; k++)
							{
								int num9 = (int)(num6 - (float)(k * 16));
								if (num9 < 0)
								{
									num9 = -num9;
								}
								if (num9 > num8)
								{
									num4 = (float)(num9 + (num8 >> 1));
								}
								else
								{
									num4 = (float)(num8 + (num9 >> 1));
								}
								if (num4 < num5)
								{
									render._BlockLights[j * num + k] += (uint)((num3 - num4) * 256f);
								}
							}
						}
					}
				}
			}
		}

		private static void DrawWaterSurfaces()
		{
			if (render._WaterAlpha.Value == 1f && render._glTexSort.Value != 0f)
			{
				return;
			}
			GL.LoadMatrix(ref render._WorldMatrix);
			if ((double)render._WaterAlpha.Value < 1.0)
			{
				GL.Enable(EnableCap.Blend);
				GL.Color4(1f, 1f, 1f, render._WaterAlpha.Value);
				GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 8448);
			}
			if (render._glTexSort.Value == 0f)
			{
				if (render._WaterChain == null)
				{
					return;
				}
				for (msurface_t msurface_t = render._WaterChain; msurface_t != null; msurface_t = msurface_t.texturechain)
				{
					Drawer.Bind(msurface_t.texinfo.texture.gl_texturenum);
					render.EmitWaterPolys(msurface_t);
				}
				render._WaterChain = null;
			}
			else
			{
				for (int i = 0; i < client.cl.worldmodel.numtextures; i++)
				{
					texture_t texture_t = client.cl.worldmodel.textures[i];
					if (texture_t != null)
					{
						msurface_t texturechain = texture_t.texturechain;
						if (texturechain != null && (texturechain.flags & 16) != 0)
						{
							Drawer.Bind(texture_t.gl_texturenum);
							while (texturechain != null)
							{
								render.EmitWaterPolys(texturechain);
								texturechain = texturechain.texturechain;
							}
							texture_t.texturechain = null;
						}
					}
				}
			}
			if ((double)render._WaterAlpha.Value < 1.0)
			{
				GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 7681);
				GL.Color4(1f, 1f, 1f, 1f);
				GL.Disable(EnableCap.Blend);
			}
		}

		private static void MarkLeaves()
		{
			if (render._OldViewLeaf == render._ViewLeaf && render._NoVis.Value == 0f)
			{
				return;
			}
			if (render._IsMirror)
			{
				return;
			}
			render._VisFrameCount++;
			render._OldViewLeaf = render._ViewLeaf;
			byte[] array;
			if (render._NoVis.Value != 0f)
			{
				array = new byte[4096];
				common.FillArray<byte>(array, byte.MaxValue);
			}
			else
			{
				array = Mod.LeafPVS(render._ViewLeaf, client.cl.worldmodel);
			}
			model_t worldmodel = client.cl.worldmodel;
			for (int i = 0; i < worldmodel.numleafs; i++)
			{
				if (array[i >> 3] > 0 & 1 << (i & 7) != 0)
				{
					mnodebase_t mnodebase_t = worldmodel.leafs[i + 1];
					while (mnodebase_t.visframe != render._VisFrameCount)
					{
						mnodebase_t.visframe = render._VisFrameCount;
						mnodebase_t = mnodebase_t.parent;
						if (mnodebase_t == null)
						{
							break;
						}
					}
				}
			}
		}

		private static void DrawWorld()
		{
			render._TempEnt.Clear();
			render._TempEnt.model = client.cl.worldmodel;
			render._ModelOrg = render._RefDef.vieworg;
			render._CurrentEntity = render._TempEnt;
			Drawer.CurrentTexture = -1;
			GL.Color3(1f, 1f, 1f);
			Array.Clear(render._LightMapPolys, 0, render._LightMapPolys.Length);
			render.RecursiveWorldNode(render._TempEnt.model.nodes[0]);
			render.DrawTextureChains();
			render.BlendLightmaps();
		}

		private static void BlendLightmaps()
		{
			if (render._FullBright.Value != 0f)
			{
				return;
			}
			if (render._glTexSort.Value == 0f)
			{
				return;
			}
			GL.DepthMask(false);
			if (Drawer.LightMapFormat == PixelFormat.Luminance)
			{
				GL.BlendFunc(BlendingFactor.Zero, BlendingFactor.OneMinusSrcColor);
			}
			if (render._LightMap.Value == 0f)
			{
				GL.Enable(EnableCap.Blend);
			}
			for (int i = 0; i < 64; i++)
			{
				glpoly_t glpoly_t = render._LightMapPolys[i];
				if (glpoly_t != null)
				{
					Drawer.Bind(render._LightMapTextures + i);
					if (render._LightMapModified[i])
					{
						render.CommitLightmap(i);
					}
					while (glpoly_t != null)
					{
						if ((glpoly_t.flags & 128) != 0)
						{
							render.DrawGLWaterPolyLightmap(glpoly_t);
						}
						else
						{
							GL.Begin(PrimitiveType.Polygon);
							for (int j = 0; j < glpoly_t.numverts; j++)
							{
								float[] array = glpoly_t.verts[j];
								GL.TexCoord2(array[5], array[6]);
								GL.Vertex3(array);
							}
							GL.End();
						}
						glpoly_t = glpoly_t.chain;
					}
				}
			}
			GL.Disable(EnableCap.Blend);
			if (Drawer.LightMapFormat == PixelFormat.Luminance)
			{
				GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
			}
			GL.DepthMask(true);
		}

		private static void DrawTextureChains()
		{
			if (render._glTexSort.Value == 0f)
			{
				render.DisableMultitexture();
				if (render._SkyChain != null)
				{
					render.DrawSkyChain(render._SkyChain);
					render._SkyChain = null;
				}
				return;
			}
			model_t worldmodel = client.cl.worldmodel;
			for (int i = 0; i < worldmodel.numtextures; i++)
			{
				texture_t texture_t = worldmodel.textures[i];
				if (texture_t != null)
				{
					msurface_t texturechain = texture_t.texturechain;
					if (texturechain != null)
					{
						if (i == render._SkyTextureNum)
						{
							render.DrawSkyChain(texturechain);
						}
						else
						{
							if (i == render._MirrorTextureNum && render._MirrorAlpha.Value != 1f)
							{
								render.MirrorChain(texturechain);
								goto IL_BC;
							}
							if ((texturechain.flags & 16) != 0 && render._WaterAlpha.Value != 1f)
							{
								goto IL_BC;
							}
							while (texturechain != null)
							{
								render.RenderBrushPoly(texturechain);
								texturechain = texturechain.texturechain;
							}
						}
						texture_t.texturechain = null;
					}
				}
				IL_BC:;
			}
		}

		private static void RenderBrushPoly(msurface_t fa)
		{
			render._BrushPolys++;
			if ((fa.flags & 4) != 0)
			{
				render.EmitBothSkyLayers(fa);
				return;
			}
			Drawer.Bind(render.TextureAnimation(fa.texinfo.texture).gl_texturenum);
			if ((fa.flags & 16) != 0)
			{
				render.EmitWaterPolys(fa);
				return;
			}
			if ((fa.flags & 128) != 0)
			{
				render.DrawGLWaterPoly(fa.polys);
			}
			else
			{
				render.DrawGLPoly(fa.polys);
			}
			fa.polys.chain = render._LightMapPolys[fa.lightmaptexturenum];
			render._LightMapPolys[fa.lightmaptexturenum] = fa.polys;
			bool flag = false;
			int num = 0;
			while (num < 4 && fa.styles[num] != 255)
			{
				if (render._LightStyleValue[(int)fa.styles[num]] != fa.cached_light[num])
				{
					flag = true;
					break;
				}
				num++;
			}
			if ((flag || fa.dlightframe == render._FrameCount || fa.cached_dlight) && render._Dynamic.Value != 0f)
			{
				render._LightMapModified[fa.lightmaptexturenum] = true;
				render.UpdateRect(fa, ref render._LightMapRectChange[fa.lightmaptexturenum]);
				int num2 = fa.lightmaptexturenum * render._LightMapBytes * 128 * 128;
				num2 += fa.light_t * 128 * render._LightMapBytes + fa.light_s * render._LightMapBytes;
				render.BuildLightMap(fa, new ByteArraySegment(render._LightMaps, num2), 128 * render._LightMapBytes);
			}
		}

		private static void UpdateRect(msurface_t fa, ref glRect_t theRect)
		{
			if (fa.light_t < (int)theRect.t)
			{
				if (theRect.h != 0)
				{
					theRect.h += (byte)((int)theRect.t - fa.light_t);
				}
				theRect.t = (byte)fa.light_t;
			}
			if (fa.light_s < (int)theRect.l)
			{
				if (theRect.w != 0)
				{
					theRect.w += (byte)((int)theRect.l - fa.light_s);
				}
				theRect.l = (byte)fa.light_s;
			}
			int num = (fa.extents[0] >> 4) + 1;
			int num2 = (fa.extents[1] >> 4) + 1;
			if ((int)(theRect.w + theRect.l) < fa.light_s + num)
			{
				theRect.w = (byte)(fa.light_s - (int)theRect.l + num);
			}
			if ((int)(theRect.h + theRect.t) < fa.light_t + num2)
			{
				theRect.h = (byte)(fa.light_t - (int)theRect.t + num2);
			}
		}

		private static void DrawGLPoly(glpoly_t p)
		{
			GL.Begin(PrimitiveType.Polygon);
			for (int i = 0; i < p.numverts; i++)
			{
				float[] array = p.verts[i];
				GL.TexCoord2(array[3], array[4]);
				GL.Vertex3(array);
			}
			GL.End();
		}

		private static void MirrorChain(msurface_t s)
		{
			if (render._IsMirror)
			{
				return;
			}
			render._IsMirror = true;
			render._MirrorPlane = s.plane;
		}

		private static void RecursiveWorldNode(mnodebase_t node)
		{
			if (node.contents == -2)
			{
				return;
			}
			if (node.visframe != render._VisFrameCount)
			{
				return;
			}
			if (render.CullBox(ref node.mins, ref node.maxs))
			{
				return;
			}
			int num2;
			if (node.contents < 0)
			{
				mleaf_t mleaf_t = (mleaf_t)node;
				msurface_t[] marksurfaces = mleaf_t.marksurfaces;
				int num = mleaf_t.firstmarksurface;
				num2 = mleaf_t.nummarksurfaces;
				if (num2 != 0)
				{
					do
					{
						marksurfaces[num].visframe = render._FrameCount;
						num++;
					}
					while (--num2 != 0);
				}
				if (mleaf_t.efrags != null)
				{
					render.StoreEfrags(mleaf_t.efrags);
				}
				return;
			}
			mnode_t mnode_t = (mnode_t)node;
			mplane_t plane = mnode_t.plane;
			double num3;
			switch (plane.type)
			{
			case 0:
				num3 = (double)(render._ModelOrg.X - plane.dist);
				break;
			case 1:
				num3 = (double)(render._ModelOrg.Y - plane.dist);
				break;
			case 2:
				num3 = (double)(render._ModelOrg.Z - plane.dist);
				break;
			default:
				num3 = (double)(Vector3.Dot(render._ModelOrg, plane.normal) - plane.dist);
				break;
			}
			int num4 = (num3 >= 0.0) ? 0 : 1;
			render.RecursiveWorldNode(mnode_t.children[num4]);
			num2 = (int)mnode_t.numsurfaces;
			if (num2 != 0)
			{
				msurface_t[] surfaces = client.cl.worldmodel.surfaces;
				int num5 = (int)mnode_t.firstsurface;
				if (num3 < -0.01)
				{
					num4 = 2;
				}
				else if (num3 > 0.01)
				{
					num4 = 0;
				}
				while (num2 != 0)
				{
					if (surfaces[num5].visframe == render._FrameCount && ((surfaces[num5].flags & 128) != 0 || !(num3 < 0.0 ^ (surfaces[num5].flags & 2) != 0)))
					{
						if (render._glTexSort.Value != 0f)
						{
							if (!render._IsMirror || surfaces[num5].texinfo.texture != client.cl.worldmodel.textures[render._MirrorTextureNum])
							{
								surfaces[num5].texturechain = surfaces[num5].texinfo.texture.texturechain;
								surfaces[num5].texinfo.texture.texturechain = surfaces[num5];
							}
						}
						else if ((surfaces[num5].flags & 4) != 0)
						{
							surfaces[num5].texturechain = render._SkyChain;
							render._SkyChain = surfaces[num5];
						}
						else if ((surfaces[num5].flags & 16) != 0)
						{
							surfaces[num5].texturechain = render._WaterChain;
							render._WaterChain = surfaces[num5];
						}
						else
						{
							render.DrawSequentialPoly(surfaces[num5]);
						}
					}
					num2--;
					num5++;
				}
			}
			render.RecursiveWorldNode(mnode_t.children[(num4 == 0) ? 1 : 0]);
		}

		private static void DrawSequentialPoly(msurface_t s)
		{
			if ((s.flags & 148) == 0)
			{
				render.RenderDynamicLightmaps(s);
				glpoly_t polys = s.polys;
				texture_t texture_t = render.TextureAnimation(s.texinfo.texture);
				if (vid.glMTexable)
				{
					Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS);
					Drawer.Bind(texture_t.gl_texturenum);
					GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 7681);
					render.EnableMultitexture();
					Drawer.Bind(render._LightMapTextures + s.lightmaptexturenum);
					int i = s.lightmaptexturenum;
					if (render._LightMapModified[i])
					{
						render.CommitLightmap(i);
					}
					GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 3042);
					GL.Begin(PrimitiveType.Polygon);
					for (i = 0; i < polys.numverts; i++)
					{
						float[] array = polys.verts[i];
						GL.MultiTexCoord2(TextureUnit.Texture0, array[3], array[4]);
						GL.MultiTexCoord2(TextureUnit.Texture1, array[5], array[6]);
						GL.Vertex3(array);
					}
					GL.End();
					return;
				}
				Drawer.Bind(texture_t.gl_texturenum);
				GL.Begin(PrimitiveType.Polygon);
				for (int j = 0; j < polys.numverts; j++)
				{
					float[] array2 = polys.verts[j];
					GL.TexCoord2(array2[3], array2[4]);
					GL.Vertex3(array2);
				}
				GL.End();
				Drawer.Bind(render._LightMapTextures + s.lightmaptexturenum);
				GL.Enable(EnableCap.Blend);
				GL.Begin(PrimitiveType.Polygon);
				for (int k = 0; k < polys.numverts; k++)
				{
					float[] array3 = polys.verts[k];
					GL.TexCoord2(array3[5], array3[6]);
					GL.Vertex3(array3);
				}
				GL.End();
				GL.Disable(EnableCap.Blend);
				return;
			}
			else
			{
				if ((s.flags & 16) != 0)
				{
					render.DisableMultitexture();
					Drawer.Bind(s.texinfo.texture.gl_texturenum);
					render.EmitWaterPolys(s);
					return;
				}
				if ((s.flags & 4) != 0)
				{
					render.DisableMultitexture();
					Drawer.Bind(render._SolidSkyTexture);
					render._SpeedScale = (float)host.RealTime * 8f;
					render._SpeedScale -= (float)((int)render._SpeedScale & -128);
					render.EmitSkyPolys(s);
					GL.Enable(EnableCap.Blend);
					Drawer.Bind(render._AlphaSkyTexture);
					render._SpeedScale = (float)host.RealTime * 16f;
					render._SpeedScale -= (float)((int)render._SpeedScale & -128);
					render.EmitSkyPolys(s);
					GL.Disable(EnableCap.Blend);
					return;
				}
				render.RenderDynamicLightmaps(s);
				if (vid.glMTexable)
				{
					texture_t texture_t2 = render.TextureAnimation(s.texinfo.texture);
					Drawer.SelectTexture(MTexTarget.TEXTURE0_SGIS);
					Drawer.Bind(texture_t2.gl_texturenum);
					GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 7681);
					render.EnableMultitexture();
					Drawer.Bind(render._LightMapTextures + s.lightmaptexturenum);
					int l = s.lightmaptexturenum;
					if (render._LightMapModified[l])
					{
						render.CommitLightmap(l);
					}
					GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, 3042);
					GL.Begin(PrimitiveType.TriangleFan);
					glpoly_t polys2 = s.polys;
					float[] array4 = new float[3];
					for (l = 0; l < polys2.numverts; l++)
					{
						float[] array5 = polys2.verts[l];
						GL.MultiTexCoord2(TextureUnit.Texture0, array5[3], array5[4]);
						GL.MultiTexCoord2(TextureUnit.Texture1, array5[5], array5[6]);
						array4[0] = (float)((double)array5[0] + 8.0 * Math.Sin((double)array5[1] * 0.05 + host.RealTime) * Math.Sin((double)array5[2] * 0.05 + host.RealTime));
						array4[1] = (float)((double)array5[1] + 8.0 * Math.Sin((double)array5[0] * 0.05 + host.RealTime) * Math.Sin((double)array5[2] * 0.05 + host.RealTime));
						array4[2] = array5[2];
						GL.Vertex3(array4);
					}
					GL.End();
					return;
				}
				glpoly_t polys3 = s.polys;
				Drawer.Bind(render.TextureAnimation(s.texinfo.texture).gl_texturenum);
				render.DrawGLWaterPoly(polys3);
				Drawer.Bind(render._LightMapTextures + s.lightmaptexturenum);
				GL.Enable(EnableCap.Blend);
				render.DrawGLWaterPolyLightmap(polys3);
				GL.Disable(EnableCap.Blend);
				return;
			}
		}

		private static void DrawGLWaterPolyLightmap(glpoly_t p)
		{
			render.DisableMultitexture();
			float[] array = new float[3];
			GL.Begin(PrimitiveType.TriangleFan);
			for (int i = 0; i < p.numverts; i++)
			{
				float[] array2 = p.verts[i];
				GL.TexCoord2(array2[5], array2[6]);
				array[0] = (float)((double)array2[0] + 8.0 * Math.Sin((double)array2[1] * 0.05 + host.RealTime) * Math.Sin((double)array2[2] * 0.05 + host.RealTime));
				array[1] = (float)((double)array2[1] + 8.0 * Math.Sin((double)array2[0] * 0.05 + host.RealTime) * Math.Sin((double)array2[2] * 0.05 + host.RealTime));
				array[2] = array2[2];
				GL.Vertex3(array);
			}
			GL.End();
		}

		private static void DrawGLWaterPoly(glpoly_t p)
		{
			render.DisableMultitexture();
			float[] array = new float[3];
			GL.Begin(PrimitiveType.TriangleFan);
			for (int i = 0; i < p.numverts; i++)
			{
				float[] array2 = p.verts[i];
				GL.TexCoord2(array2[3], array2[4]);
				array[0] = (float)((double)array2[0] + 8.0 * Math.Sin((double)array2[1] * 0.05 + host.RealTime) * Math.Sin((double)array2[2] * 0.05 + host.RealTime));
				array[1] = (float)((double)array2[1] + 8.0 * Math.Sin((double)array2[0] * 0.05 + host.RealTime) * Math.Sin((double)array2[2] * 0.05 + host.RealTime));
				array[2] = array2[2];
				GL.Vertex3(array);
			}
			GL.End();
		}

		private static void CommitLightmap(int i)
		{
			render._LightMapModified[i] = false;
			glRect_t glRect_t = render._LightMapRectChange[i];
			GCHandle gchandle = GCHandle.Alloc(render._LightMaps, GCHandleType.Pinned);
			try
			{
				long value = gchandle.AddrOfPinnedObject().ToInt64() + (long)((i * 128 + (int)glRect_t.t) * 128 * render._LightMapBytes);
				GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, (int)glRect_t.t, 128, (int)glRect_t.h, Drawer.LightMapFormat, PixelType.UnsignedByte, new IntPtr(value));
			}
			finally
			{
				gchandle.Free();
			}
			glRect_t.l = 128;
			glRect_t.t = 128;
			glRect_t.h = 0;
			glRect_t.w = 0;
			render._LightMapRectChange[i] = glRect_t;
		}

		private static texture_t TextureAnimation(texture_t t)
		{
			if (render._CurrentEntity.frame != 0 && t.alternate_anims != null)
			{
				t = t.alternate_anims;
			}
			if (t.anim_total == 0)
			{
				return t;
			}
			int num = (int)(client.cl.time * 10.0) % t.anim_total;
			int num2 = 0;
			while (t.anim_min > num || t.anim_max <= num)
			{
				t = t.anim_next;
				if (t == null)
				{
					sys.Error("R_TextureAnimation: broken cycle", Array.Empty<object>());
				}
				if (++num2 > 100)
				{
					sys.Error("R_TextureAnimation: infinite cycle", Array.Empty<object>());
				}
			}
			return t;
		}

		private static void RenderDynamicLightmaps(msurface_t fa)
		{
			render._BrushPolys++;
			if ((fa.flags & 20) != 0)
			{
				return;
			}
			fa.polys.chain = render._LightMapPolys[fa.lightmaptexturenum];
			render._LightMapPolys[fa.lightmaptexturenum] = fa.polys;
			bool flag = false;
			int num = 0;
			while (num < 4 && fa.styles[num] != 255)
			{
				if (render._LightStyleValue[(int)fa.styles[num]] != fa.cached_light[num])
				{
					flag = true;
					break;
				}
				num++;
			}
			if ((flag || fa.dlightframe == render._FrameCount || fa.cached_dlight) && render._Dynamic.Value != 0f)
			{
				render._LightMapModified[fa.lightmaptexturenum] = true;
				render.UpdateRect(fa, ref render._LightMapRectChange[fa.lightmaptexturenum]);
				int startIndex = fa.lightmaptexturenum * render._LightMapBytes * 128 * 128 + fa.light_t * 128 * render._LightMapBytes + fa.light_s * render._LightMapBytes;
				render.BuildLightMap(fa, new ByteArraySegment(render._LightMaps, startIndex), 128 * render._LightMapBytes);
			}
		}

		private static void DrawBrushModel(entity_t e)
		{
			render._CurrentEntity = e;
			Drawer.CurrentTexture = -1;
			model_t model = e.model;
			bool flag = false;
			Vector3 vector;
			Vector3 vector2;
			if (e.angles.X != 0f || e.angles.Y != 0f || e.angles.Z != 0f)
			{
				flag = true;
				vector = e.origin;
				vector.X -= model.radius;
				vector.Y -= model.radius;
				vector.Z -= model.radius;
				vector2 = e.origin;
				vector2.X += model.radius;
				vector2.Y += model.radius;
				vector2.Z += model.radius;
			}
			else
			{
				vector = e.origin + model.mins;
				vector2 = e.origin + model.maxs;
			}
			if (render.CullBox(ref vector, ref vector2))
			{
				return;
			}
			GL.Color3(1f, 1f, 1f);
			Array.Clear(render._LightMapPolys, 0, render._LightMapPolys.Length);
			render._ModelOrg = render._RefDef.vieworg - e.origin;
			if (flag)
			{
				Vector3 modelOrg = render._ModelOrg;
				Vector3 right;
				Vector3 right2;
				Vector3 right3;
				mathlib.AngleVectors(ref e.angles, out right, out right2, out right3);
				render._ModelOrg.X = Vector3.Dot(modelOrg, right);
				render._ModelOrg.Y = -Vector3.Dot(modelOrg, right2);
				render._ModelOrg.Z = Vector3.Dot(modelOrg, right3);
			}
			if (model.firstmodelsurface != 0 && render._glFlashBlend.Value == 0f)
			{
				for (int i = 0; i < 32; i++)
				{
					if ((double)client.DLights[i].die >= client.cl.time && client.DLights[i].radius != 0f)
					{
						render.MarkLights(client.DLights[i], 1 << i, model.nodes[model.hulls[0].firstclipnode]);
					}
				}
			}
			GL.PushMatrix();
			e.angles.X = -e.angles.X;
			render.RotateForEntity(e);
			e.angles.X = -e.angles.X;
			int num = model.firstmodelsurface;
			msurface_t[] surfaces = model.surfaces;
			int j = 0;
			while (j < model.nummodelsurfaces)
			{
				mplane_t plane = surfaces[num].plane;
				float num2 = Vector3.Dot(render._ModelOrg, plane.normal) - plane.dist;
				bool flag2 = (surfaces[num].flags & 2) != 0;
				if ((flag2 && (double)num2 < -0.01) || (!flag2 && (double)num2 > 0.01))
				{
					if (render._glTexSort.Value != 0f)
					{
						render.RenderBrushPoly(surfaces[num]);
					}
					else
					{
						render.DrawSequentialPoly(surfaces[num]);
					}
				}
				j++;
				num++;
			}
			render.BlendLightmaps();
			GL.PopMatrix();
		}

		public static void InitSky(texture_t mt)
		{
			byte[] pixels = mt.pixels;
			int num = mt.offsets[0];
			uint[] array = new uint[16384];
			uint[] table8to = vid.Table8to24;
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			Union4b empty = Union4b.Empty;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					int num5 = (int)pixels[num + i * 256 + j + 128];
					empty.ui0 = table8to[num5];
					array[i * 128 + j] = empty.ui0;
					num2 += (int)empty.b0;
					num3 += (int)empty.b1;
					num4 += (int)empty.b2;
				}
			}
			empty.b0 = (byte)(num2 / 16384);
			empty.b1 = (byte)(num3 / 16384);
			empty.b2 = (byte)(num4 / 16384);
			empty.b3 = 0;
			uint ui = empty.ui0;
			if (render._SolidSkyTexture == 0)
			{
				render._SolidSkyTexture = Drawer.GenerateTextureNumber();
			}
			Drawer.Bind(render._SolidSkyTexture);
			GL.TexImage2D<uint>(TextureTarget.Texture2D, 0, Drawer.SolidFormat, 128, 128, 0, PixelFormat.Rgba, PixelType.UnsignedByte, array);
			Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear);
			for (int k = 0; k < 128; k++)
			{
				for (int l = 0; l < 128; l++)
				{
					int num6 = (int)pixels[num + k * 256 + l];
					if (num6 == 0)
					{
						array[k * 128 + l] = ui;
					}
					else
					{
						array[k * 128 + l] = table8to[num6];
					}
				}
			}
			if (render._AlphaSkyTexture == 0)
			{
				render._AlphaSkyTexture = Drawer.GenerateTextureNumber();
			}
			Drawer.Bind(render._AlphaSkyTexture);
			GL.TexImage2D<uint>(TextureTarget.Texture2D, 0, Drawer.AlphaFormat, 128, 128, 0, PixelFormat.Rgba, PixelType.UnsignedByte, array);
			Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear);
		}

		public static void SubdivideSurface(msurface_t fa)
		{
			render._WarpFace = fa;
			int num = 0;
			Vector3[] array = new Vector3[fa.numedges + 1];
			model_t model = Mod.Model;
			for (int i = 0; i < fa.numedges; i++)
			{
				int num2 = model.surfedges[fa.firstedge + i];
				if (num2 > 0)
				{
					array[num] = model.vertexes[(int)model.edges[num2].v[0]].position;
				}
				else
				{
					array[num] = model.vertexes[(int)model.edges[-num2].v[1]].position;
				}
				num++;
			}
			render.SubdividePolygon(num, array);
		}

		private static void SubdividePolygon(int numverts, Vector3[] verts)
		{
			if (numverts > 60)
			{
				sys.Error("numverts = {0}", new object[]
				{
					numverts
				});
			}
			Vector3 vector;
			Vector3 vector2;
			render.BoundPoly(numverts, verts, out vector, out vector2);
			float[] array = new float[64];
			for (int i = 0; i < 3; i++)
			{
				double num = (double)(mathlib.Comp(ref vector, i) + mathlib.Comp(ref vector2, i)) * 0.5;
				num = (double)Mod.SubdivideSize * Math.Floor(num / (double)Mod.SubdivideSize + 0.5);
				if ((double)mathlib.Comp(ref vector2, i) - num >= 8.0 && num - (double)mathlib.Comp(ref vector, i) >= 8.0)
				{
					for (int j = 0; j < numverts; j++)
					{
						array[j] = (float)((double)mathlib.Comp(ref verts[j], i) - num);
					}
					Vector3[] array2 = new Vector3[64];
					Vector3[] array3 = new Vector3[64];
					array[numverts] = array[0];
					verts[numverts] = verts[0];
					int num2 = 0;
					int num3 = 0;
					for (int k = 0; k < numverts; k++)
					{
						if (array[k] >= 0f)
						{
							array2[num2] = verts[k];
							num2++;
						}
						if (array[k] <= 0f)
						{
							array3[num3] = verts[k];
							num3++;
						}
						if (array[k] != 0f && array[k + 1] != 0f && array[k] > 0f != array[k + 1] > 0f)
						{
							float scale = array[k] / (array[k] - array[k + 1]);
							array2[num2] = (array3[num3] = verts[k] + (verts[k + 1] - verts[k]) * scale);
							num2++;
							num3++;
						}
					}
					render.SubdividePolygon(num2, array2);
					render.SubdividePolygon(num3, array3);
					return;
				}
			}
			glpoly_t glpoly_t = new glpoly_t();
			glpoly_t.next = render._WarpFace.polys;
			render._WarpFace.polys = glpoly_t;
			glpoly_t.AllocVerts(numverts);
			for (int l = 0; l < numverts; l++)
			{
				common.Copy(ref verts[l], glpoly_t.verts[l]);
				float num4 = Vector3.Dot(verts[l], render._WarpFace.texinfo.vecs[0].Xyz);
				float num5 = Vector3.Dot(verts[l], render._WarpFace.texinfo.vecs[1].Xyz);
				glpoly_t.verts[l][3] = num4;
				glpoly_t.verts[l][4] = num5;
			}
		}

		private static void BoundPoly(int numverts, Vector3[] verts, out Vector3 mins, out Vector3 maxs)
		{
			mins = Vector3.One * 9999f;
			maxs = Vector3.One * -9999f;
			for (int i = 0; i < numverts; i++)
			{
				Vector3.ComponentMin(ref verts[i], ref mins, out mins);
				Vector3.ComponentMax(ref verts[i], ref maxs, out maxs);
			}
		}

		private static void EmitWaterPolys(msurface_t fa)
		{
			for (glpoly_t glpoly_t = fa.polys; glpoly_t != null; glpoly_t = glpoly_t.next)
			{
				GL.Begin(PrimitiveType.Polygon);
				for (int i = 0; i < glpoly_t.numverts; i++)
				{
					float[] array = glpoly_t.verts[i];
					float num = array[3];
					float num2 = array[4];
					float s = (num + render._TurbSin[(int)(((double)num2 * 0.125 + host.RealTime) * 40.743665431525208) & 255]) * 0.015625f;
					float num3 = num2 + render._TurbSin[(int)(((double)num * 0.125 + host.RealTime) * 40.743665431525208) & 255];
					num3 *= 0.015625f;
					GL.TexCoord2(s, num3);
					GL.Vertex3(array);
				}
				GL.End();
			}
		}

		private static void EmitSkyPolys(msurface_t fa)
		{
			for (glpoly_t glpoly_t = fa.polys; glpoly_t != null; glpoly_t = glpoly_t.next)
			{
				GL.Begin(PrimitiveType.Polygon);
				for (int i = 0; i < glpoly_t.numverts; i++)
				{
					float[] array = glpoly_t.verts[i];
					Vector3 vector = new Vector3(array[0] - render.Origin.X, array[1] - render.Origin.Y, array[2] - render.Origin.Z);
					vector.Z *= 3f;
					vector.Normalize();
					vector *= 378f;
					float s = (render._SpeedScale + vector.X) / 128f;
					float t = (render._SpeedScale + vector.Y) / 128f;
					GL.TexCoord2(s, t);
					GL.Vertex3(array);
				}
				GL.End();
			}
		}

		private static void DrawSkyChain(msurface_t s)
		{
			render.DisableMultitexture();
			Drawer.Bind(render._SolidSkyTexture);
			render._SpeedScale = (float)host.RealTime * 8f;
			render._SpeedScale -= (float)((int)render._SpeedScale & -128);
			for (msurface_t msurface_t = s; msurface_t != null; msurface_t = msurface_t.texturechain)
			{
				render.EmitSkyPolys(msurface_t);
			}
			GL.Enable(EnableCap.Blend);
			Drawer.Bind(render._AlphaSkyTexture);
			render._SpeedScale = (float)host.RealTime * 16f;
			render._SpeedScale -= (float)((int)render._SpeedScale & -128);
			for (msurface_t msurface_t2 = s; msurface_t2 != null; msurface_t2 = msurface_t2.texturechain)
			{
				render.EmitSkyPolys(msurface_t2);
			}
			GL.Disable(EnableCap.Blend);
		}

		private static void EmitBothSkyLayers(msurface_t fa)
		{
			render.DisableMultitexture();
			Drawer.Bind(render._SolidSkyTexture);
			render._SpeedScale = (float)host.RealTime * 8f;
			render._SpeedScale -= (float)((int)render._SpeedScale & -128);
			render.EmitSkyPolys(fa);
			GL.Enable(EnableCap.Blend);
			Drawer.Bind(render._AlphaSkyTexture);
			render._SpeedScale = (float)host.RealTime * 16f;
			render._SpeedScale -= (float)((int)render._SpeedScale & -128);
			render.EmitSkyPolys(fa);
			GL.Disable(EnableCap.Blend);
		}

		public const int MAXCLIPPLANES = 11;

		public const int TOP_RANGE = 16;

		public const int BOTTOM_RANGE = 96;

		public static Vector3 ViewUp;

		public static Vector3 ViewPn;

		public static Vector3 ViewRight;

		public static Vector3 Origin;

		private const float ONE_OVER_16 = 0.0625f;

		private const int MAX_LIGHTMAPS = 64;

		private const int BLOCK_WIDTH = 128;

		private const int BLOCK_HEIGHT = 128;

		private static refdef_t _RefDef = new refdef_t();

		private static texture_t _NoTextureMip;

		private static cvar _NoRefresh;

		private static cvar _DrawEntities;

		private static cvar _DrawViewModel;

		private static cvar _Speeds;

		private static cvar _FullBright;

		private static cvar _LightMap;

		private static cvar _Shadows;

		private static cvar _MirrorAlpha;

		private static cvar _WaterAlpha;

		private static cvar _Dynamic;

		private static cvar _NoVis;

		private static cvar _glFinish;

		private static cvar _glClear;

		private static cvar _glCull;

		private static cvar _glTexSort;

		private static cvar _glSmoothModels;

		private static cvar _glAffineModels;

		private static cvar _glPolyBlend;

		private static cvar _glFlashBlend;

		private static cvar _glPlayerMip;

		private static cvar _glNoColors;

		private static cvar _glKeepTJunctions;

		private static cvar _glReportTJunctions;

		private static cvar _glDoubleEyes;

		private static int _PlayerTextures;

		private static bool _CacheThrash;

		private static int[] _LightStyleValue = new int[256];

		private static entity_t _WorldEntity = new entity_t();

		private static entity_t _CurrentEntity;

		private static mleaf_t _ViewLeaf;

		private static mleaf_t _OldViewLeaf;

		private static int _SkyTextureNum;

		private static int _MirrorTextureNum;

		private static int[,] _Allocated = new int[64, 128];

		private static int _VisFrameCount;

		private static int _FrameCount;

		private static bool _MTexEnabled;

		private static int _BrushPolys;

		private static int _AliasPolys;

		private static bool _IsMirror;

		private static mplane_t _MirrorPlane;

		private static float _glDepthMin;

		private static float _glDepthMax;

		private static int _TrickFrame;

		private static mplane_t[] _Frustum = new mplane_t[4];

		private static bool _IsEnvMap = false;

		private static Matrix4 _WorldMatrix;

		private static Matrix4 _BaseWorldMatrix;

		private static Vector3 _ModelOrg;

		private static Vector3 _EntOrigin;

		private static float _SpeedScale;

		private static float _ShadeLight;

		private static float _AmbientLight;

		private static float[] _ShadeDots = anorm_dots.Values[0];

		private static Vector3 _ShadeVector;

		private static int _LastPoseNum;

		private static Vector3 _LightSpot;

		private static entity_t _AddEnt;

		private static mnode_t _EfragTopNode;

		private static Vector3 _EMins;

		private static Vector3 _EMaxs;

		private static object _LastObj;

		private static int _DlightFrameCount;

		private static mplane_t _LightPlane;

		private const int MAX_PARTICLES = 2048;

		private const int ABSOLUTE_MIN_PARTICLES = 512;

		private const int NUMVERTEXNORMALS = 162;

		private static int[] _Ramp1 = new int[]
		{
			111,
			109,
			107,
			105,
			103,
			101,
			99,
			97
		};

		private static int[] _Ramp2 = new int[]
		{
			111,
			110,
			109,
			108,
			107,
			106,
			104,
			102
		};

		private static int[] _Ramp3 = new int[]
		{
			109,
			107,
			6,
			5,
			4,
			3
		};

		private static byte[,] _DotTexture = new byte[,]
		{
			{
				0,
				1,
				1,
				0,
				0,
				0,
				0,
				0
			},
			{
				1,
				1,
				1,
				1,
				0,
				0,
				0,
				0
			},
			{
				1,
				1,
				1,
				1,
				0,
				0,
				0,
				0
			},
			{
				0,
				1,
				1,
				0,
				0,
				0,
				0,
				0
			},
			{
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0
			},
			{
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0
			},
			{
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0
			},
			{
				0,
				0,
				0,
				0,
				0,
				0,
				0,
				0
			}
		};

		private static int _NumParticles;

		private static render.particle_t[] _Particles;

		private static int _ParticleTexture;

		private static render.particle_t _ActiveParticles;

		private static render.particle_t _FreeParticles;

		private static int _TracerCount;

		private static Vector3[] _AVelocities = new Vector3[162];

		private static float _BeamLength = 16f;

		private const double COLINEAR_EPSILON = 0.001;

		private static int _LightMapTextures;

		private static int _LightMapBytes;

		private static mvertex_t[] _CurrentVertBase;

		private static model_t _CurrentModel;

		private static bool[] _LightMapModified = new bool[64];

		private static glpoly_t[] _LightMapPolys = new glpoly_t[64];

		private static glRect_t[] _LightMapRectChange = new glRect_t[64];

		private static uint[] _BlockLights = new uint[324];

		private static int _ColinElim;

		private static msurface_t _SkyChain;

		private static msurface_t _WaterChain;

		private static entity_t _TempEnt = new entity_t();

		private static byte[] _LightMaps = new byte[4194304];

		private const double TURBSCALE = 40.743665431525208;

		private static float[] _TurbSin = new float[]
		{
			0f,
			0.19633f,
			0.392541f,
			0.588517f,
			0.784137f,
			0.979285f,
			1.17384f,
			1.3677f,
			1.56072f,
			1.75281f,
			1.94384f,
			2.1337f,
			2.32228f,
			2.50945f,
			2.69512f,
			2.87916f,
			3.06147f,
			3.24193f,
			3.42044f,
			3.59689f,
			3.77117f,
			3.94319f,
			4.11282f,
			4.27998f,
			4.44456f,
			4.60647f,
			4.76559f,
			4.92185f,
			5.07515f,
			5.22538f,
			5.37247f,
			5.51632f,
			5.65685f,
			5.79398f,
			5.92761f,
			6.05767f,
			6.18408f,
			6.30677f,
			6.42566f,
			6.54068f,
			6.65176f,
			6.75883f,
			6.86183f,
			6.9607f,
			7.05537f,
			7.14579f,
			7.23191f,
			7.31368f,
			7.39104f,
			7.46394f,
			7.53235f,
			7.59623f,
			7.65552f,
			7.71021f,
			7.76025f,
			7.80562f,
			7.84628f,
			7.88222f,
			7.91341f,
			7.93984f,
			7.96148f,
			7.97832f,
			7.99036f,
			7.99759f,
			8f,
			7.99759f,
			7.99036f,
			7.97832f,
			7.96148f,
			7.93984f,
			7.91341f,
			7.88222f,
			7.84628f,
			7.80562f,
			7.76025f,
			7.71021f,
			7.65552f,
			7.59623f,
			7.53235f,
			7.46394f,
			7.39104f,
			7.31368f,
			7.23191f,
			7.14579f,
			7.05537f,
			6.9607f,
			6.86183f,
			6.75883f,
			6.65176f,
			6.54068f,
			6.42566f,
			6.30677f,
			6.18408f,
			6.05767f,
			5.92761f,
			5.79398f,
			5.65685f,
			5.51632f,
			5.37247f,
			5.22538f,
			5.07515f,
			4.92185f,
			4.76559f,
			4.60647f,
			4.44456f,
			4.27998f,
			4.11282f,
			3.94319f,
			3.77117f,
			3.59689f,
			3.42044f,
			3.24193f,
			3.06147f,
			2.87916f,
			2.69512f,
			2.50945f,
			2.32228f,
			2.1337f,
			1.94384f,
			1.75281f,
			1.56072f,
			1.3677f,
			1.17384f,
			0.979285f,
			0.784137f,
			0.588517f,
			0.392541f,
			0.19633f,
			9.79717E-16f,
			-0.19633f,
			-0.392541f,
			-0.588517f,
			-0.784137f,
			-0.979285f,
			-1.17384f,
			-1.3677f,
			-1.56072f,
			-1.75281f,
			-1.94384f,
			-2.1337f,
			-2.32228f,
			-2.50945f,
			-2.69512f,
			-2.87916f,
			-3.06147f,
			-3.24193f,
			-3.42044f,
			-3.59689f,
			-3.77117f,
			-3.94319f,
			-4.11282f,
			-4.27998f,
			-4.44456f,
			-4.60647f,
			-4.76559f,
			-4.92185f,
			-5.07515f,
			-5.22538f,
			-5.37247f,
			-5.51632f,
			-5.65685f,
			-5.79398f,
			-5.92761f,
			-6.05767f,
			-6.18408f,
			-6.30677f,
			-6.42566f,
			-6.54068f,
			-6.65176f,
			-6.75883f,
			-6.86183f,
			-6.9607f,
			-7.05537f,
			-7.14579f,
			-7.23191f,
			-7.31368f,
			-7.39104f,
			-7.46394f,
			-7.53235f,
			-7.59623f,
			-7.65552f,
			-7.71021f,
			-7.76025f,
			-7.80562f,
			-7.84628f,
			-7.88222f,
			-7.91341f,
			-7.93984f,
			-7.96148f,
			-7.97832f,
			-7.99036f,
			-7.99759f,
			-8f,
			-7.99759f,
			-7.99036f,
			-7.97832f,
			-7.96148f,
			-7.93984f,
			-7.91341f,
			-7.88222f,
			-7.84628f,
			-7.80562f,
			-7.76025f,
			-7.71021f,
			-7.65552f,
			-7.59623f,
			-7.53235f,
			-7.46394f,
			-7.39104f,
			-7.31368f,
			-7.23191f,
			-7.14579f,
			-7.05537f,
			-6.9607f,
			-6.86183f,
			-6.75883f,
			-6.65176f,
			-6.54068f,
			-6.42566f,
			-6.30677f,
			-6.18408f,
			-6.05767f,
			-5.92761f,
			-5.79398f,
			-5.65685f,
			-5.51632f,
			-5.37247f,
			-5.22538f,
			-5.07515f,
			-4.92185f,
			-4.76559f,
			-4.60647f,
			-4.44456f,
			-4.27998f,
			-4.11282f,
			-3.94319f,
			-3.77117f,
			-3.59689f,
			-3.42044f,
			-3.24193f,
			-3.06147f,
			-2.87916f,
			-2.69512f,
			-2.50945f,
			-2.32228f,
			-2.1337f,
			-1.94384f,
			-1.75281f,
			-1.56072f,
			-1.3677f,
			-1.17384f,
			-0.979285f,
			-0.784137f,
			-0.588517f,
			-0.392541f,
			-0.19633f
		};

		private static int _SolidSkyTexture;

		private static int _AlphaSkyTexture;

		private static msurface_t _WarpFace;

		private enum ptype_t
		{
			pt_static,
			pt_grav,
			pt_slowgrav,
			pt_fire,
			pt_explode,
			pt_explode2,
			pt_blob,
			pt_blob2
		}

		private class particle_t
		{
			public Vector3 org;

			public float color;

			public render.particle_t next;

			public Vector3 vel;

			public float ramp;

			public float die;

			public render.ptype_t type;
		}
	}
}
