public static void R_SetupFrame() { // don't allow cheats in multiplayer if (cl.maxclients > 1) { Cvar.Cvar_Set("r_fullbright", "0"); } R_AnimateLight(); r_framecount++; // build the transformation matrix for the given view angles r_origin = r_refdef.vieworg; Mathlib.AngleVectors(ref r_refdef.viewangles, out vpn, out vright, out vup); // current viewleaf r_oldviewleaf = r_viewleaf; r_viewleaf = Mod_PointInLeaf(ref r_origin, cl.worldmodel); game_engine.V_SetContentsColor(r_viewleaf.contents); game_engine.V_CalcBlend(); r_cache_thrash = false; c_brush_polys = 0; c_alias_polys = 0; }
public static void Chase_Update() { // if can't see player, reset Vector3 forward, up, right; Mathlib.AngleVectors(ref cl.viewangles, out forward, out right, out up); // calc exact destination chase_dest = r_refdef.vieworg - forward * chase_back.value - right * chase_right.value; chase_dest.Z = r_refdef.vieworg.Z + chase_up.value; // find the spot the player is looking at Vector3 dest = r_refdef.vieworg + forward * 4096; Vector3 stop; TraceLine(ref r_refdef.vieworg, ref dest, out stop); // calculate pitch to look at the same spot from camera stop -= r_refdef.vieworg; float dist; Vector3.Dot(ref stop, ref forward, out dist); if (dist < 1) { dist = 1; } r_refdef.viewangles.X = (float)(-Math.Atan(stop.Z / dist) / Math.PI * 180.0); //r_refdef.viewangles[PITCH] = -atan(stop[2] / dist) / M_PI * 180; // move towards destination r_refdef.vieworg = chase_dest; //VectorCopy(chase_dest, r_refdef.vieworg); }
static unsafe void PF_makevectors() { float * av = G_VECTOR(q_shared.OFS_PARM0); Vector3 a = new Vector3(av[0], av[1], av[2]); Vector3 fw, right, up; Mathlib.AngleVectors(ref a, out fw, out right, out up); Mathlib.Copy(ref fw, out pr_global_struct.v_forward); Mathlib.Copy(ref right, out pr_global_struct.v_right); Mathlib.Copy(ref up, out pr_global_struct.v_up); }
public static void R_DrawSpriteModel(entity_t e) { // don't even bother culling, because it's just a single // polygon without a surface cache mspriteframe_t frame = R_GetSpriteFrame(e); msprite_t psprite = (msprite_t)e.model.cache.data; Vector3 v_forward, right, up; if (psprite.type == q_shared.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 = vup; // vup; right = vright; // vright; } GL.Color3(1f, 1, 1); GL_DisableMultitexture(); GL_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); }
public static void SV_AirMove() { Vector3 pangles = ToVector(ref sv_player.v.angles); Mathlib.AngleVectors(ref pangles, out forward, out right, out up); float fmove = cmd.forwardmove; float smove = cmd.sidemove; // hack to not let you back into teleporter if (sv.time < sv_player.v.teleport_time && fmove < 0) { fmove = 0; } Vector3 wishvel = forward * fmove + right * smove; if ((int)sv_player.v.movetype != q_shared.MOVETYPE_WALK) { wishvel.Z = cmd.upmove; } else { wishvel.Z = 0; } wishdir = wishvel; wishspeed = Mathlib.Normalize(ref wishdir); if (wishspeed > sv_maxspeed.value) { wishvel *= sv_maxspeed.value / wishspeed; wishspeed = sv_maxspeed.value; } if (sv_player.v.movetype == q_shared.MOVETYPE_NOCLIP) { // noclip Mathlib.Copy(ref wishvel, out sv_player.v.velocity); } else if (onground) { SV_UserFriction(); SV_Accelerate(); } else { // not on ground, so little effect on velocity SV_AirAccelerate(wishvel); } }
public static float V_CalcRoll(ref Vector3 angles, ref Vector3 velocity) { Mathlib.AngleVectors(ref angles, out forward, out right, out up); float side = Vector3.Dot(velocity, right); float sign = side < 0 ? -1 : 1; side = Math.Abs(side); float value = cl_rollangle.value; if (side < cl_rollspeed.value) { side = side * value / cl_rollspeed.value; } else { side = value; } return(side * sign); }
public static void SV_WallFriction(edict_t ent, trace_t trace) { Vector3 forward, right, up, vangle = ToVector(ref ent.v.v_angle); Mathlib.AngleVectors(ref vangle, out forward, out right, out up); float d = Vector3.Dot(trace.plane.normal, forward); d += 0.5f; if (d >= 0) { return; } // cut the tangential velocity Vector3 vel = ToVector(ref ent.v.velocity); float i = Vector3.Dot(trace.plane.normal, vel); Vector3 into = trace.plane.normal * i; Vector3 side = vel - into; ent.v.velocity.x = side.X * (1 + d); ent.v.velocity.y = side.Y * (1 + d); }
public static void V_ParseDamage() { int armor = Reader.MSG_ReadByte(); int blood = Reader.MSG_ReadByte(); Vector3 from = Reader.ReadCoords(); float count = blood * 0.5f + armor * 0.5f; if (count < 10) { count = 10; } cl.faceanimtime = (float)cl.time + 0.2f; // put sbar face into pain frame cl.cshifts[q_shared.CSHIFT_DAMAGE].percent += (int)(3 * count); if (cl.cshifts[q_shared.CSHIFT_DAMAGE].percent < 0) { cl.cshifts[q_shared.CSHIFT_DAMAGE].percent = 0; } if (cl.cshifts[q_shared.CSHIFT_DAMAGE].percent > 150) { cl.cshifts[q_shared.CSHIFT_DAMAGE].percent = 150; } if (armor > blood) { cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[0] = 200; cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[1] = 100; cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[2] = 100; } else if (armor != 0) { cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[0] = 220; cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[1] = 50; cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[2] = 50; } else { cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[0] = 255; cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[1] = 0; cl.cshifts[q_shared.CSHIFT_DAMAGE].destcolor[2] = 0; } // // calculate view angle kicks // entity_t ent = cl_entities[cl.viewentity]; from -= ent.origin; // VectorSubtract (from, ent->origin, from); Mathlib.Normalize(ref from); Vector3 forward, right, up; Mathlib.AngleVectors(ref ent.angles, out forward, out right, out up); float side = Vector3.Dot(from, right); v_dmg_roll = count * side * v_kickroll.value; side = Vector3.Dot(from, forward); v_dmg_pitch = count * side * v_kickpitch.value; v_dmg_time = v_kicktime.value; }
static void V_CalcRefdef() { V_DriftPitch(); // ent is the player model (visible when out of body) entity_t ent = cl_entities[cl.viewentity]; // view is the weapon model (only visible from inside body) entity_t view = cl.viewent; // transform the view offset by the model's matrix to get the offset from // model origin for the view ent.angles.Y = cl.viewangles.Y; // the model should face the view dir ent.angles.X = -cl.viewangles.X; // the model should face the view dir float bob = V_CalcBob(); refdef_t rdef = r_refdef; // refresh position rdef.vieworg = ent.origin; rdef.vieworg.Z += cl.viewheight + bob; // never let it sit exactly on a node line, because a water plane can // dissapear when viewed with the eye exactly on it. // the server protocol only specifies to 1/16 pixel, so add 1/32 in each axis rdef.vieworg += q_shared.SmallOffset; rdef.viewangles = cl.viewangles; V_CalcViewRoll(); V_AddIdle(v_idlescale.value); // offsets Vector3 angles = ent.angles; angles.X = -angles.X; // because entity pitches are actually backward Vector3 forward, right, up; Mathlib.AngleVectors(ref angles, out forward, out right, out up); rdef.vieworg += forward * scr_ofsx.value + right * scr_ofsy.value + up * scr_ofsz.value; V_BoundOffsets(); // set up gun position view.angles = cl.viewangles; CalcGunAngle(); view.origin = ent.origin; view.origin.Z += cl.viewheight; view.origin += forward * bob * 0.4f; view.origin.Z += bob; // fudge position around to keep amount of weapon visible // roughly equal with different FOV float viewSize = scr_viewsize.value; // scr_viewsize if (viewSize == 110) { view.origin.Z += 1; } else if (viewSize == 100) { view.origin.Z += 2; } else if (viewSize == 90) { view.origin.Z += 1; } else if (viewSize == 80) { view.origin.Z += 0.5f; } view.model = cl.model_precache[cl.stats[q_shared.STAT_WEAPON]]; view.frame = cl.stats[q_shared.STAT_WEAPONFRAME]; view.colormap = vid.colormap; // set up the refresh position rdef.viewangles += cl.punchangle; // smooth out stair step ups if (cl.onground && ent.origin.Z - _OldZ > 0) { float steptime = (float)(cl.time - cl.oldtime); if (steptime < 0) { steptime = 0; } _OldZ += steptime * 80; if (_OldZ > ent.origin.Z) { _OldZ = ent.origin.Z; } if (ent.origin.Z - _OldZ > 12) { _OldZ = ent.origin.Z - 12; } rdef.vieworg.Z += _OldZ - ent.origin.Z; view.origin.Z += _OldZ - ent.origin.Z; } else { _OldZ = ent.origin.Z; } if (chase_active.value != 0) { Chase_Update(); } }
public static void R_DrawBrushModel(entity_t e) { currententity = e; 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 (R_CullBox(ref mins, ref maxs)) { return; } GL.Color3(1f, 1, 1); Array.Clear(lightmap_polys, 0, lightmap_polys.Length); modelorg = r_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 && gl_flashblend.value == 0) { for (int k = 0; k < q_shared.MAX_DLIGHTS; k++) { if ((cl_dlights[k].die < cl.time) || (cl_dlights[k].radius == 0)) { continue; } R_MarkLights(cl_dlights[k], 1 << k, clmodel.nodes[clmodel.hulls[0].firstclipnode]); } } GL.PushMatrix(); e.angles.X = -e.angles.X; // stupid quake bug R_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 & q_shared.SURF_PLANEBACK) != 0; if ((planeBack && (dot < -q_shared.BACKFACE_EPSILON)) || (!planeBack && (dot > q_shared.BACKFACE_EPSILON))) { if (gl_texsort.value != 0) { R_RenderBrushPoly(psurf[surfOffset]); } else { R_DrawSequentialPoly(psurf[surfOffset]); } } } R_BlendLightmaps(); GL.PopMatrix(); }
public static void SV_WaterMove() { // // user intentions // Vector3 pangle = ToVector(ref sv_player.v.v_angle); Mathlib.AngleVectors(ref pangle, out forward, out right, out up); Vector3 wishvel = forward * cmd.forwardmove + right * cmd.sidemove; if (cmd.forwardmove == 0 && cmd.sidemove == 0 && cmd.upmove == 0) { wishvel.Z -= 60; // drift towards bottom } else { wishvel.Z += cmd.upmove; } float wishspeed = wishvel.Length; if (wishspeed > sv_maxspeed.value) { wishvel *= sv_maxspeed.value / wishspeed; wishspeed = sv_maxspeed.value; } wishspeed *= 0.7f; // // water friction // float newspeed, speed = Mathlib.Length(ref sv_player.v.velocity); if (speed != 0) { newspeed = (float)(speed - host_framtime * speed * sv_friction.value); if (newspeed < 0) { newspeed = 0; } Mathlib.VectorScale(ref sv_player.v.velocity, newspeed / speed, out sv_player.v.velocity); } else { newspeed = 0; } // // water acceleration // if (wishspeed == 0) { return; } float addspeed = wishspeed - newspeed; if (addspeed <= 0) { return; } Mathlib.Normalize(ref wishvel); float accelspeed = (float)(sv_accelerate.value * wishspeed * host_framtime); if (accelspeed > addspeed) { accelspeed = addspeed; } wishvel *= accelspeed; sv_player.v.velocity.x += wishvel.X; sv_player.v.velocity.y += wishvel.Y; sv_player.v.velocity.z += wishvel.Z; }
public static void CL_RelinkEntities() { // determine partial update time float frac = CL_LerpPoint(); cl_numvisedicts = 0; // // interpolate player info // cl.velocity = cl.mvelocity[1] + frac * (cl.mvelocity[0] - cl.mvelocity[1]); if (cls.demoplayback) { // interpolate the angles Vector3 angleDelta = cl.mviewangles[0] - cl.mviewangles[1]; Mathlib.CorrectAngles180(ref angleDelta); cl.viewangles = cl.mviewangles[1] + frac * angleDelta; } float bobjrotate = Mathlib.anglemod(100 * cl.time); // start on the entity after the world for (int i = 1; i < cl.num_entities; i++) { entity_t ent = cl_entities[i]; if (ent.model == null) { // empty slot if (ent.forcelink) { R_RemoveEfrags(ent); // just became empty } continue; } // if the object wasn't included in the last packet, remove it if (ent.msgtime != cl.mtime[0]) { ent.model = null; continue; } Vector3 oldorg = ent.origin; if (ent.forcelink) { // the entity was not updated in the last message // so move to the final spot ent.origin = ent.msg_origins[0]; ent.angles = ent.msg_angles[0]; } else { // if the delta is large, assume a teleport and don't lerp float f = frac; Vector3 delta = ent.msg_origins[0] - ent.msg_origins[1]; if (Math.Abs(delta.X) > 100 || Math.Abs(delta.Y) > 100 || Math.Abs(delta.Z) > 100) { f = 1; // assume a teleportation, not a motion } // interpolate the origin and angles ent.origin = ent.msg_origins[1] + f * delta; Vector3 angleDelta = ent.msg_angles[0] - ent.msg_angles[1]; Mathlib.CorrectAngles180(ref angleDelta); ent.angles = ent.msg_angles[1] + f * angleDelta; } // rotate binary objects locally if ((ent.model.flags & q_shared.EF_ROTATE) != 0) { ent.angles.Y = bobjrotate; } if ((ent.effects & q_shared.EF_BRIGHTFIELD) != 0) { R_EntityParticles(ent); } if ((ent.effects & q_shared.EF_MUZZLEFLASH) != 0) { dlight_t dl = CL_AllocDlight(i); dl.origin = ent.origin; dl.origin.Z += 16; Vector3 fv, rv, uv; Mathlib.AngleVectors(ref ent.angles, out fv, out rv, out uv); dl.origin += fv * 18; dl.radius = 200 + (Random() & 31); dl.minlight = 32; dl.die = (float)cl.time + 0.1f; } if ((ent.effects & q_shared.EF_BRIGHTLIGHT) != 0) { dlight_t dl = CL_AllocDlight(i); dl.origin = ent.origin; dl.origin.Z += 16; dl.radius = 400 + (Random() & 31); dl.die = (float)cl.time + 0.001f; } if ((ent.effects & q_shared.EF_DIMLIGHT) != 0) { dlight_t dl = CL_AllocDlight(i); dl.origin = ent.origin; dl.radius = 200 + (Random() & 31); dl.die = (float)cl.time + 0.001f; } if ((ent.model.flags & q_shared.EF_GIB) != 0) { R_RocketTrail(ref oldorg, ref ent.origin, 2); } else if ((ent.model.flags & q_shared.EF_ZOMGIB) != 0) { R_RocketTrail(ref oldorg, ref ent.origin, 4); } else if ((ent.model.flags & q_shared.EF_TRACER) != 0) { R_RocketTrail(ref oldorg, ref ent.origin, 3); } else if ((ent.model.flags & q_shared.EF_TRACER2) != 0) { R_RocketTrail(ref oldorg, ref ent.origin, 5); } else if ((ent.model.flags & q_shared.EF_ROCKET) != 0) { R_RocketTrail(ref oldorg, ref ent.origin, 0); dlight_t dl = CL_AllocDlight(i); dl.origin = ent.origin; dl.radius = 200; dl.die = (float)cl.time + 0.01f; } else if ((ent.model.flags & q_shared.EF_GRENADE) != 0) { R_RocketTrail(ref oldorg, ref ent.origin, 1); } else if ((ent.model.flags & q_shared.EF_TRACER3) != 0) { R_RocketTrail(ref oldorg, ref ent.origin, 6); } ent.forcelink = false; if (i == cl.viewentity && chase_active.value == 0) { continue; } if (cl_numvisedicts < q_shared.MAX_VISEDICTS) { cl_visedicts[cl_numvisedicts] = ent; cl_numvisedicts++; } } }