public void Clear() { this.leaf = null; this.leafnext = null; this.entity = null; this.entnext = null; }
static entity_t[] _TempEntities = new entity_t[MAX_TEMP_ENTITIES]; // cl_temp_entities[MAX_TEMP_ENTITIES] #endregion Fields #region Methods // CL_InitTEnts static void InitTempEntities() { _SfxWizHit = Sound.PrecacheSound ("wizard/hit.wav"); _SfxKnigtHit = Sound.PrecacheSound ("hknight/hit.wav"); _SfxTink1 = Sound.PrecacheSound ("weapons/tink1.wav"); _SfxRic1 = Sound.PrecacheSound ("weapons/ric1.wav"); _SfxRic2 = Sound.PrecacheSound ("weapons/ric2.wav"); _SfxRic3 = Sound.PrecacheSound ("weapons/ric3.wav"); _SfxRExp3 = Sound.PrecacheSound ("weapons/r_exp3.wav"); for (int i = 0; i < _TempEntities.Length; i++) _TempEntities[i] = new entity_t(); for (int i = 0; i < _Beams.Length; i++) _Beams[i] = new beam_t(); }
static object _LastObj; // see comments #endregion Fields #region Methods /// <summary> /// R_AddEfrags /// </summary> public static void AddEfrags(entity_t ent) { if (ent.model == null) return; _AddEnt = ent; _LastObj = ent; // lastlink = &ent->efrag; _EfragTopNode = null; model_t entmodel = ent.model; _EMins = ent.origin + entmodel.mins; _EMaxs = ent.origin + entmodel.maxs; SplitEntityOnNode(Client.cl.worldmodel.nodes[0]); ent.topnode = _EfragTopNode; }
/// <summary> /// R_DrawBrushModel /// </summary> private static void DrawBrushModel(entity_t e) { _CurrentEntity = e; Drawer.CurrentTexture = -1; model_t clmodel = e.model; bool rotated = false; Vector3 mins, maxs; if (e.angles.X != 0 || e.angles.Y != 0 || e.angles.Z != 0) { rotated = true; mins = e.origin; mins.X -= clmodel.radius; mins.Y -= clmodel.radius; mins.Z -= clmodel.radius; maxs = e.origin; maxs.X += clmodel.radius; maxs.Y += clmodel.radius; maxs.Z += clmodel.radius; } else { mins = e.origin + clmodel.mins; maxs = e.origin + clmodel.maxs; } if (CullBox(ref mins, ref maxs)) return; GL.Color3(1f, 1, 1); Array.Clear(_LightMapPolys, 0, _LightMapPolys.Length); _ModelOrg = _RefDef.vieworg - e.origin; if (rotated) { Vector3 temp = _ModelOrg; Vector3 forward, right, up; Mathlib.AngleVectors(ref e.angles, out forward, out right, out up); _ModelOrg.X = Vector3.Dot(temp, forward); _ModelOrg.Y = -Vector3.Dot(temp, right); _ModelOrg.Z = Vector3.Dot(temp, up); } // calculate dynamic lighting for bmodel if it's not an // instanced model if (clmodel.firstmodelsurface != 0 && _glFlashBlend.Value == 0) { for (int k = 0; k < Client.MAX_DLIGHTS; k++) { if ((Client.DLights[k].die < Client.cl.time) || (Client.DLights[k].radius == 0)) continue; MarkLights(Client.DLights[k], 1 << k, clmodel.nodes[clmodel.hulls[0].firstclipnode]); } } GL.PushMatrix(); e.angles.X = -e.angles.X; // stupid quake bug RotateForEntity(e); e.angles.X = -e.angles.X; // stupid quake bug int surfOffset = clmodel.firstmodelsurface; msurface_t[] psurf = clmodel.surfaces; //[clmodel.firstmodelsurface]; // // draw texture // for (int i = 0; i < clmodel.nummodelsurfaces; i++, surfOffset++) { // find which side of the node we are on mplane_t pplane = psurf[surfOffset].plane; float dot = Vector3.Dot(_ModelOrg, pplane.normal) - pplane.dist; // draw the polygon bool planeBack = (psurf[surfOffset].flags & Surf.SURF_PLANEBACK) != 0; if ((planeBack && (dot < -QDef.BACKFACE_EPSILON)) || (!planeBack && (dot > QDef.BACKFACE_EPSILON))) { if (_glTexSort.Value != 0) RenderBrushPoly(psurf[surfOffset]); else DrawSequentialPoly(psurf[surfOffset]); } } BlendLightmaps(); GL.PopMatrix(); }
/// <summary> /// R_DrawViewModel /// </summary> static void DrawViewModel() { if (_DrawViewModel.Value == 0) return; if (Chase.IsActive) return; if (_IsEnvMap) return; if (_DrawEntities.Value == 0) return; if (Client.cl.HasItems(QItems.IT_INVISIBILITY)) return; if (Client.cl.stats[QStats.STAT_HEALTH] <= 0) return; _CurrentEntity = Client.ViewEnt; if (_CurrentEntity.model == null) return; int j = LightPoint(ref _CurrentEntity.origin); if (j < 24) j = 24; // allways give some light on gun _AmbientLight = j; _ShadeLight = j; // add dynamic lights for (int lnum = 0; lnum < Client.MAX_DLIGHTS; lnum++) { dlight_t dl = Client.DLights[lnum]; if (dl.radius == 0) continue; if (dl.die < Client.cl.time) continue; Vector3 dist = _CurrentEntity.origin - dl.origin; float add = dl.radius - dist.Length; if (add > 0) _AmbientLight += add; } // hack the depth range to prevent view model from poking into walls GL.DepthRange(_glDepthMin, _glDepthMin + 0.3f * (_glDepthMax - _glDepthMin)); DrawAliasModel(_CurrentEntity); GL.DepthRange(_glDepthMin, _glDepthMax); }
/// <summary> /// R_DrawSpriteModel /// </summary> private static void DrawSpriteModel(entity_t e) { // don't even bother culling, because it's just a single // polygon without a surface cache mspriteframe_t frame = GetSpriteFrame(e); msprite_t psprite = (msprite_t)e.model.cache.data; // Uze: changed from _CurrentEntity to e Vector3 v_forward, right, up; if (psprite.type == SPR.SPR_ORIENTED) { // bullet marks on walls Mathlib.AngleVectors(ref e.angles, out v_forward, out right, out up); // Uze: changed from _CurrentEntity to e } else { // normal sprite up = Render.ViewUp;// vup; right = Render.ViewRight;// vright; } GL.Color3(1f, 1, 1); DisableMultitexture(); Drawer.Bind(frame.gl_texturenum); GL.Enable(EnableCap.AlphaTest); GL.Begin(BeginMode.Quads); GL.TexCoord2(0f, 1); Vector3 point = e.origin + up * frame.down + right * frame.left; GL.Vertex3(point); GL.TexCoord2(0f, 0); point = e.origin + up * frame.up + right * frame.left; GL.Vertex3(point); GL.TexCoord2(1f, 0); point = e.origin + up * frame.up + right * frame.right; GL.Vertex3(point); GL.TexCoord2(1f, 1); point = e.origin + up * frame.down + right * frame.right; GL.Vertex3(point); GL.End(); GL.Disable(EnableCap.AlphaTest); }
/// <summary> /// R_DrawEntitiesOnList /// </summary> private static void DrawEntitiesOnList() { if (_DrawEntities.Value == 0) return; // draw sprites seperately, because of alpha blending for (int i = 0; i < Client.NumVisEdicts; i++) { _CurrentEntity = Client.VisEdicts[i]; switch (_CurrentEntity.model.type) { case modtype_t.mod_alias: DrawAliasModel(_CurrentEntity); break; case modtype_t.mod_brush: DrawBrushModel(_CurrentEntity); break; default: break; } } for (int i = 0; i < Client.NumVisEdicts; i++) { _CurrentEntity = Client.VisEdicts[i]; switch (_CurrentEntity.model.type) { case modtype_t.mod_sprite: DrawSpriteModel(_CurrentEntity); break; } } }
/// <summary> /// R_DrawAliasModel /// </summary> private static void DrawAliasModel(entity_t e) { model_t clmodel = _CurrentEntity.model; Vector3 mins = _CurrentEntity.origin + clmodel.mins; Vector3 maxs = _CurrentEntity.origin + clmodel.maxs; if (CullBox(ref mins, ref maxs)) return; _EntOrigin = _CurrentEntity.origin; _ModelOrg = Render.Origin - _EntOrigin; // // get lighting information // _AmbientLight = _ShadeLight = LightPoint(ref _CurrentEntity.origin); // allways give the gun some light if (e == Client.cl.viewent && _AmbientLight < 24) _AmbientLight = _ShadeLight = 24; for (int lnum = 0; lnum < Client.MAX_DLIGHTS; lnum++) { if (Client.DLights[lnum].die >= Client.cl.time) { Vector3 dist = _CurrentEntity.origin - Client.DLights[lnum].origin; float add = Client.DLights[lnum].radius - dist.Length; if (add > 0) { _AmbientLight += add; //ZOID models should be affected by dlights as well _ShadeLight += add; } } } // clamp lighting so it doesn't overbright as much if (_AmbientLight > 128) _AmbientLight = 128; if (_AmbientLight + _ShadeLight > 192) _ShadeLight = 192 - _AmbientLight; // ZOID: never allow players to go totally black int playernum = Array.IndexOf(Client.Entities, _CurrentEntity, 0, Client.cl.maxclients); if (playernum >= 1)// && i <= cl.maxclients) if (_AmbientLight < 8) _AmbientLight = _ShadeLight = 8; // HACK HACK HACK -- no fullbright colors, so make torches full light if (clmodel.name == "progs/flame2.mdl" || clmodel.name == "progs/flame.mdl") _AmbientLight = _ShadeLight = 256; _ShadeDots = AnormDots.Values[((int)(e.angles.Y * (AnormDots.SHADEDOT_QUANT / 360.0))) & (AnormDots.SHADEDOT_QUANT - 1)]; _ShadeLight = _ShadeLight / 200.0f; double an = e.angles.Y / 180.0 * Math.PI; _ShadeVector.X = (float)Math.Cos(-an); _ShadeVector.Y = (float)Math.Sin(-an); _ShadeVector.Z = 1; Mathlib.Normalize(ref _ShadeVector); // // locate the proper data // aliashdr_t paliashdr = Mod.GetExtraData(_CurrentEntity.model); _AliasPolys += paliashdr.numtris; // // draw all the triangles // DisableMultitexture(); GL.PushMatrix(); RotateForEntity(e); if (clmodel.name == "progs/eyes.mdl" && _glDoubleEyes.Value != 0) { Vector3 v = paliashdr.scale_origin; v.Z -= (22 + 8); GL.Translate(v); // double size of eyes, since they are really hard to see in gl GL.Scale(paliashdr.scale * 2.0f); } else { GL.Translate(paliashdr.scale_origin); GL.Scale(paliashdr.scale); } int anim = (int)(Client.cl.time * 10) & 3; Drawer.Bind(paliashdr.gl_texturenum[_CurrentEntity.skinnum, anim]); // we can't dynamically colormap textures, so they are cached // seperately for the players. Heads are just uncolored. if (_CurrentEntity.colormap != Scr.vid.colormap && _glNoColors.Value == 0 && playernum >= 1) { Drawer.Bind(_PlayerTextures - 1 + playernum); } if (_glSmoothModels.Value != 0) GL.ShadeModel(ShadingModel.Smooth); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate); if (_glAffineModels.Value != 0) GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Fastest); SetupAliasFrame(_CurrentEntity.frame, paliashdr); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Replace); GL.ShadeModel(ShadingModel.Flat); if (_glAffineModels.Value != 0) GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest); GL.PopMatrix(); if (_Shadows.Value != 0) { GL.PushMatrix(); RotateForEntity(e); GL.Disable(EnableCap.Texture2D); GL.Enable(EnableCap.Blend); GL.Color4(0, 0, 0, 0.5f); DrawAliasShadow(paliashdr, _LastPoseNum); GL.Enable(EnableCap.Texture2D); GL.Disable(EnableCap.Blend); GL.Color4(1f, 1, 1, 1); GL.PopMatrix(); } }
/// <summary> /// R_TranslatePlayerSkin /// Translates a skin texture by the per-player color lookup /// </summary> public static void TranslatePlayerSkin(int playernum) { DisableMultitexture(); int top = Client.cl.scores[playernum].colors & 0xf0; int bottom = (Client.cl.scores[playernum].colors & 15) << 4; byte[] translate = new byte[256]; for (int i = 0; i < 256; i++) translate[i] = (byte)i; for (int i = 0; i < 16; i++) { if (top < 128) // the artists made some backwards ranges. sigh. translate[TOP_RANGE + i] = (byte)(top + i); else translate[TOP_RANGE + i] = (byte)(top + 15 - i); if (bottom < 128) translate[BOTTOM_RANGE + i] = (byte)(bottom + i); else translate[BOTTOM_RANGE + i] = (byte)(bottom + 15 - i); } // // locate the original skin pixels // _CurrentEntity = Client.Entities[1 + playernum]; model_t model = _CurrentEntity.model; if (model == null) return; // player doesn't have a model yet if (model.type != modtype_t.mod_alias) return; // only translate skins on alias models aliashdr_t paliashdr = Mod.GetExtraData(model); int s = paliashdr.skinwidth * paliashdr.skinheight; if ((s & 3) != 0) Sys.Error("R_TranslateSkin: s&3"); byte[] original; if (_CurrentEntity.skinnum < 0 || _CurrentEntity.skinnum >= paliashdr.numskins) { Con.Print("({0}): Invalid player skin #{1}\n", playernum, _CurrentEntity.skinnum); original = (byte[])paliashdr.texels[0];// (byte *)paliashdr + paliashdr.texels[0]; } else original = (byte[])paliashdr.texels[_CurrentEntity.skinnum]; int inwidth = paliashdr.skinwidth; int inheight = paliashdr.skinheight; // because this happens during gameplay, do it fast // instead of sending it through gl_upload 8 Drawer.Bind(_PlayerTextures + playernum); int scaled_width = (int)(Drawer.glMaxSize < 512 ? Drawer.glMaxSize : 512); int scaled_height = (int)(Drawer.glMaxSize < 256 ? Drawer.glMaxSize : 256); // allow users to crunch sizes down even more if they want scaled_width >>= (int)_glPlayerMip.Value; scaled_height >>= (int)_glPlayerMip.Value; uint fracstep, frac; int destOffset; uint[] translate32 = new uint[256]; for (int i = 0; i < 256; i++) translate32[i] = Vid.Table8to24[translate[i]]; uint[] dest = new uint[512 * 256]; destOffset = 0; fracstep = (uint)(inwidth * 0x10000 / scaled_width); for (int i = 0; i < scaled_height; i++, destOffset += scaled_width) { int srcOffset = inwidth * (i * inheight / scaled_height); frac = fracstep >> 1; for (int j = 0; j < scaled_width; j += 4) { dest[destOffset + j] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; dest[destOffset + j + 1] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; dest[destOffset + j + 2] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; dest[destOffset + j + 3] = translate32[original[srcOffset + (frac >> 16)]]; frac += fracstep; } } GCHandle handle = GCHandle.Alloc(dest, GCHandleType.Pinned); try { GL.TexImage2D(TextureTarget.Texture2D, 0, Drawer.SolidFormat, scaled_width, scaled_height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, handle.AddrOfPinnedObject()); } finally { handle.Free(); } GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.TextureEnvMode, (int)TextureEnvMode.Modulate); Drawer.SetTextureFilters(TextureMinFilter.Linear, TextureMagFilter.Linear); }
/// <summary> /// R_RotateForEntity /// </summary> static void RotateForEntity(entity_t e) { GL.Translate(e.origin); GL.Rotate(e.angles.Y, 0, 0, 1); GL.Rotate(-e.angles.X, 0, 1, 0); GL.Rotate(e.angles.Z, 1, 0, 0); }
/// <summary> /// R_RemoveEfrags /// Call when removing an object from the world or moving it to another position /// </summary> public static void RemoveEfrags(entity_t ent) { efrag_t ef = ent.efrag; while (ef != null) { mleaf_t leaf = ef.leaf; while (true) { efrag_t walk = leaf.efrags; if (walk == null) break; if (walk == ef) { // remove this fragment leaf.efrags = ef.leafnext; break; } else leaf = (mleaf_t)(object)walk.leafnext; } efrag_t old = ef; ef = ef.entnext; // put it on the free list old.entnext = Client.cl.free_efrags; Client.cl.free_efrags = old; } ent.efrag = null; }
/// <summary> /// R_GetSpriteFrame /// </summary> static mspriteframe_t GetSpriteFrame(entity_t currententity) { msprite_t psprite = (msprite_t)currententity.model.cache.data; int frame = currententity.frame; if ((frame >= psprite.numframes) || (frame < 0)) { Con.Print("R_DrawSprite: no such frame {0}\n", frame); frame = 0; } mspriteframe_t pspriteframe; if (psprite.frames[frame].type == spriteframetype_t.SPR_SINGLE) { pspriteframe = (mspriteframe_t)psprite.frames[frame].frameptr; } else { mspritegroup_t pspritegroup = (mspritegroup_t)psprite.frames[frame].frameptr; float[] pintervals = pspritegroup.intervals; int numframes = pspritegroup.numframes; float fullinterval = pintervals[numframes - 1]; float time = (float)Client.cl.time + currententity.syncbase; // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values // are positive, so we don't have to worry about division by 0 float targettime = time - ((int)(time / fullinterval)) * fullinterval; int i; for (i = 0; i < (numframes - 1); i++) { if (pintervals[i] > targettime) break; } pspriteframe = pspritegroup.frames[i]; } return pspriteframe; }
/// <summary> /// CL_ParseBaseline /// </summary> /// <param name="ent"></param> static void ParseBaseline(entity_t ent) { ent.baseline.modelindex = Net.Reader.ReadByte(); ent.baseline.frame = Net.Reader.ReadByte(); ent.baseline.colormap = Net.Reader.ReadByte(); ent.baseline.skin = Net.Reader.ReadByte(); ent.baseline.origin.x = Net.Reader.ReadCoord(); ent.baseline.angles.x = Net.Reader.ReadAngle(); ent.baseline.origin.y = Net.Reader.ReadCoord(); ent.baseline.angles.y = Net.Reader.ReadAngle(); ent.baseline.origin.z = Net.Reader.ReadCoord(); ent.baseline.angles.z = Net.Reader.ReadAngle(); }
// CL_Init public static void Init() { InitInput(); InitTempEntities(); if (_Name == null) { _Name = new Cvar("_cl_name", "player", true); _Color = new Cvar("_cl_color", "0", true); _ShowNet = new Cvar("cl_shownet", "0"); // can be 0, 1, or 2 _NoLerp = new Cvar("cl_nolerp", "0"); _LookSpring = new Cvar("lookspring", "0", true); _LookStrafe = new Cvar("lookstrafe", "0", true); _Sensitivity = new Cvar("sensitivity", "3", true); _MPitch = new Cvar("m_pitch", "0.022", true); _MYaw = new Cvar("m_yaw", "0.022", true); _MForward = new Cvar("m_forward", "1", true); _MSide = new Cvar("m_side", "0.8", true); _UpSpeed = new Cvar("cl_upspeed", "200"); _ForwardSpeed = new Cvar("cl_forwardspeed", "200", true); _BackSpeed = new Cvar("cl_backspeed", "200", true); _SideSpeed = new Cvar("cl_sidespeed", "350"); _MoveSpeedKey = new Cvar("cl_movespeedkey", "2.0"); _YawSpeed = new Cvar("cl_yawspeed", "140"); _PitchSpeed = new Cvar("cl_pitchspeed", "150"); _AngleSpeedKey = new Cvar("cl_anglespeedkey", "1.5"); } for (int i = 0; i < _EFrags.Length; i++) _EFrags[i] = new efrag_t(); for (int i = 0; i < _Entities.Length; i++) _Entities[i] = new entity_t(); for (int i = 0; i < _StaticEntities.Length; i++) _StaticEntities[i] = new entity_t(); for (int i = 0; i < _DLights.Length; i++) _DLights[i] = new dlight_t(); // // register our commands // Cmd.Add("entities", PrintEntities_f); Cmd.Add("disconnect", Disconnect_f); Cmd.Add("record", Record_f); Cmd.Add("stop", Stop_f); Cmd.Add("playdemo", PlayDemo_f); Cmd.Add("timedemo", TimeDemo_f); }
public model_t worldmodel; // cl_entitites[0].model #endregion Fields #region Constructors public client_state_t() { this.stats = new int[QStats.MAX_CL_STATS]; this.item_gettime = new float[32]; // ??????????? this.cshifts = new cshift_t[ColorShift.NUM_CSHIFTS]; for (int i = 0; i < ColorShift.NUM_CSHIFTS; i++) this.cshifts[i] = new cshift_t(); this.prev_cshifts = new cshift_t[ColorShift.NUM_CSHIFTS]; for (int i = 0; i < ColorShift.NUM_CSHIFTS; i++) this.prev_cshifts[i] = new cshift_t(); this.mviewangles = new Vector3[2]; //?????? this.mvelocity = new Vector3[2]; this.mtime = new double[2]; this.model_precache = new model_t[QDef.MAX_MODELS]; this.sound_precache = new sfx_t[QDef.MAX_SOUNDS]; this.viewent = new entity_t(); }
/// <summary> /// R_EntityParticles /// </summary> public static void EntityParticles(entity_t ent) { float dist = 64; if (_AVelocities[0].X == 0) { for (int i = 0; i < NUMVERTEXNORMALS; i++) { _AVelocities[i].X = (Sys.Random() & 255) * 0.01f; _AVelocities[i].Y = (Sys.Random() & 255) * 0.01f; _AVelocities[i].Z = (Sys.Random() & 255) * 0.01f; } } for (int i = 0; i < NUMVERTEXNORMALS; i++) { double angle = Client.cl.time * _AVelocities[i].X; double sy = Math.Sin(angle); double cy = Math.Cos(angle); angle = Client.cl.time * _AVelocities[i].Y; double sp = Math.Sin(angle); double cp = Math.Cos(angle); angle = Client.cl.time * _AVelocities[i].Z; double sr = Math.Sin(angle); double cr = Math.Cos(angle); Vector3 forward = new Vector3((float)(cp * cy), (float)(cp * sy), (float)-sp); particle_t p = AllocParticle(); if (p == null) return; p.die = (float)(Client.cl.time + 0.01); p.color = 0x6f; p.type = ptype_t.pt_explode; p.org = ent.origin + Anorms.Values[i] * dist + forward * _BeamLength; } }