public static void VectorSubtract(ref v3f a, ref v3f b, out v3f c) { c.x = a.x - b.x; c.y = a.y - b.y; c.z = a.z - b.z; }
public static void Clamp(ref v3f src, ref Vector3 min, ref Vector3 max, out v3f dest) { dest.x = Math.Max(Math.Min(src.x, max.X), min.X); dest.y = Math.Max(Math.Min(src.y, max.Y), min.Y); dest.z = Math.Max(Math.Min(src.z, max.Z), min.Z); }
public static void VectorScale(ref v3f a, float scale, out v3f b) { b.x = a.x * scale; b.y = a.y * scale; b.z = a.z * scale; }
public static void VectorAdd(ref v3f a, ref v3f b, out v3f c) { c.x = a.x + b.x; c.y = a.y + b.y; c.z = a.z + b.z; }
public static float LengthXY(ref v3f v) { return((float)Math.Sqrt(v.x * v.x + v.y * v.y)); }
public static void VectorMA(ref v3f a, float scale, ref v3f b, out v3f c) { c.x = a.x + b.x * scale; c.y = a.y + b.y * scale; c.z = a.z + b.z * scale; }
public static void Copy(ref v3f src, out Vector3 dest) { dest.X = src.x; dest.Y = src.y; dest.Z = src.z; }
public static bool SV_movestep(edict_t ent, ref v3f move, bool relink) { trace_t trace; // try the move v3f oldorg = ent.v.origin; v3f neworg; Mathlib.VectorAdd(ref ent.v.origin, ref move, out neworg); // flying monsters don't step up if (((int)ent.v.flags & (q_shared.FL_SWIM | q_shared.FL_FLY)) != 0) { // try one move with vertical motion, then one without for (int i = 0; i < 2; i++) { Mathlib.VectorAdd(ref ent.v.origin, ref move, out neworg); edict_t enemy = PROG_TO_EDICT(ent.v.enemy); if (i == 0 && enemy != sv.edicts[0]) { float dz = ent.v.origin.z - enemy.v.origin.z; if (dz > 40) { neworg.z -= 8; } if (dz < 30) { neworg.z += 8; } } trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref neworg, 0, ent); if (trace.fraction == 1) { if (((int)ent.v.flags & q_shared.FL_SWIM) != 0 && SV_PointContents(ref trace.endpos) == q_shared.CONTENTS_EMPTY) { return(false); // swim monster left water } Mathlib.Copy(ref trace.endpos, out ent.v.origin); if (relink) { SV_LinkEdict(ent, true); } return(true); } if (enemy == sv.edicts[0]) { break; } } return(false); } // push down from a step height above the wished position neworg.z += q_shared.STEPSIZE; v3f end = neworg; end.z -= q_shared.STEPSIZE * 2; trace = Move(ref neworg, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent); if (trace.allsolid) { return(false); } if (trace.startsolid) { neworg.z -= q_shared.STEPSIZE; trace = Move(ref neworg, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent); if (trace.allsolid || trace.startsolid) { return(false); } } if (trace.fraction == 1) { // if monster had the ground pulled out, go ahead and fall if (((int)ent.v.flags & q_shared.FL_PARTIALGROUND) != 0) { Mathlib.VectorAdd(ref ent.v.origin, ref move, out ent.v.origin); if (relink) { SV_LinkEdict(ent, true); } ent.v.flags = (int)ent.v.flags & ~q_shared.FL_ONGROUND; return(true); } return(false); // walked off an edge } // check point traces down for dangling corners Mathlib.Copy(ref trace.endpos, out ent.v.origin); if (!SV_CheckBottom(ent)) { if (((int)ent.v.flags & q_shared.FL_PARTIALGROUND) != 0) { // entity had floor mostly pulled out from underneath it // and is trying to correct if (relink) { SV_LinkEdict(ent, true); } return(true); } ent.v.origin = oldorg; return(false); } if (((int)ent.v.flags & q_shared.FL_PARTIALGROUND) != 0) { ent.v.flags = (int)ent.v.flags & ~q_shared.FL_PARTIALGROUND; } ent.v.groundentity = EDICT_TO_PROG(trace.ent); // the move is ok if (relink) { SV_LinkEdict(ent, true); } return(true); }
public static void SV_PushMove(edict_t pusher, float movetime) { if (pusher.v.velocity.IsEmpty) { pusher.v.ltime += movetime; return; } v3f move, mins, maxs; Mathlib.VectorScale(ref pusher.v.velocity, movetime, out move); Mathlib.VectorAdd(ref pusher.v.absmin, ref move, out mins); Mathlib.VectorAdd(ref pusher.v.absmax, ref move, out maxs); v3f pushorig = pusher.v.origin; edict_t[] moved_edict = new edict_t[q_shared.MAX_EDICTS]; v3f[] moved_from = new v3f[q_shared.MAX_EDICTS]; // move the pusher to it's final position Mathlib.VectorAdd(ref pusher.v.origin, ref move, out pusher.v.origin); pusher.v.ltime += movetime; SV_LinkEdict(pusher, false); // see if any solid entities are inside the final position int num_moved = 0; for (int e = 1; e < sv.num_edicts; e++) { edict_t check = sv.edicts[e]; if (check.free) { continue; } if (check.v.movetype == q_shared.MOVETYPE_PUSH || check.v.movetype == q_shared.MOVETYPE_NONE || check.v.movetype == q_shared.MOVETYPE_NOCLIP) { continue; } // if the entity is standing on the pusher, it will definately be moved if (!(((int)check.v.flags & q_shared.FL_ONGROUND) != 0 && PROG_TO_EDICT(check.v.groundentity) == pusher)) { if (check.v.absmin.x >= maxs.x || check.v.absmin.y >= maxs.y || check.v.absmin.z >= maxs.z || check.v.absmax.x <= mins.x || check.v.absmax.y <= mins.y || check.v.absmax.z <= mins.z) { continue; } // see if the ent's bbox is inside the pusher's final position if (SV_TestEntityPosition(check) == null) { continue; } } // remove the onground flag for non-players if (check.v.movetype != q_shared.MOVETYPE_WALK) { check.v.flags = (int)check.v.flags & ~q_shared.FL_ONGROUND; } v3f entorig = check.v.origin; moved_from[num_moved] = entorig; moved_edict[num_moved] = check; num_moved++; // try moving the contacted entity pusher.v.solid = q_shared.SOLID_NOT; PushEntity(check, ref move); pusher.v.solid = q_shared.SOLID_BSP; // if it is still inside the pusher, block edict_t block = SV_TestEntityPosition(check); if (block != null) { // fail the move if (check.v.mins.x == check.v.maxs.x) { continue; } if (check.v.solid == q_shared.SOLID_NOT || check.v.solid == q_shared.SOLID_TRIGGER) { // corpse check.v.mins.x = check.v.mins.y = 0; check.v.maxs = check.v.mins; continue; } check.v.origin = entorig; SV_LinkEdict(check, true); pusher.v.origin = pushorig; SV_LinkEdict(pusher, false); pusher.v.ltime -= movetime; // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (pusher.v.blocked != 0) { pr_global_struct.self = EDICT_TO_PROG(pusher); pr_global_struct.other = EDICT_TO_PROG(check); PR_ExecuteProgram(pusher.v.blocked); } // move back any entities we already moved for (int i = 0; i < num_moved; i++) { moved_edict[i].v.origin = moved_from[i]; SV_LinkEdict(moved_edict[i], false); } return; } } }
public static float DotProduct(ref v3f a, ref v3f b) { return(a.x * b.x + a.y * b.y + a.z * b.z); }
public static int SV_FlyMove(edict_t ent, float time, trace_t steptrace) { v3f original_velocity = ent.v.velocity; v3f primal_velocity = ent.v.velocity; int numbumps = 4; int blocked = 0; Vector3[] planes = new Vector3[q_shared.MAX_CLIP_PLANES]; int numplanes = 0; float time_left = time; for (int bumpcount = 0; bumpcount < numbumps; bumpcount++) { if (ent.v.velocity.IsEmpty) { break; } v3f end; Mathlib.VectorMA(ref ent.v.origin, time_left, ref ent.v.velocity, out end); trace_t trace = Move(ref ent.v.origin, ref ent.v.mins, ref ent.v.maxs, ref end, 0, ent); if (trace.allsolid) { // entity is trapped in another solid ent.v.velocity = default(v3f); return(3); } if (trace.fraction > 0) { // actually covered some distance Mathlib.Copy(ref trace.endpos, out ent.v.origin); original_velocity = ent.v.velocity; numplanes = 0; } if (trace.fraction == 1) { break; // moved the entire distance } if (trace.ent == null) { Sys_Error("SV_FlyMove: !trace.ent"); } if (trace.plane.normal.Z > 0.7) { blocked |= 1; // floor if (trace.ent.v.solid == q_shared.SOLID_BSP) { ent.v.flags = (int)ent.v.flags | q_shared.FL_ONGROUND; ent.v.groundentity = EDICT_TO_PROG(trace.ent); } } if (trace.plane.normal.Z == 0) { blocked |= 2; // step if (steptrace != null) { steptrace.CopyFrom(trace); // save for player extrafriction } } // // run the impact function // SV_Impact(ent, trace.ent); if (ent.free) { break; // removed by the impact function } time_left -= time_left * trace.fraction; // cliped to another plane if (numplanes >= q_shared.MAX_CLIP_PLANES) { // this shouldn't really happen ent.v.velocity = default(v3f); return(3); } planes[numplanes] = trace.plane.normal; numplanes++; // // modify original_velocity so it parallels all of the clip planes // v3f new_velocity = default(v3f); int i, j; for (i = 0; i < numplanes; i++) { ClipVelocity(ref original_velocity, ref planes[i], out new_velocity, 1); for (j = 0; j < numplanes; j++) { if (j != i) { float dot = new_velocity.x * planes[j].X + new_velocity.y * planes[j].Y + new_velocity.z * planes[j].Z; if (dot < 0) { break; // not ok } } } if (j == numplanes) { break; } } if (i != numplanes) { // go along this plane ent.v.velocity = new_velocity; } else { // go along the crease if (numplanes != 2) { ent.v.velocity = default(v3f); return(7); } Vector3 dir = Vector3.Cross(planes[0], planes[1]); float d = dir.X * ent.v.velocity.x + dir.Y * ent.v.velocity.y + dir.Z * ent.v.velocity.z; Mathlib.Copy(ref dir, out ent.v.velocity); Mathlib.VectorScale(ref ent.v.velocity, d, out ent.v.velocity); } // // if original velocity is against the original velocity, stop dead // to avoid tiny occilations in sloping corners // if (Mathlib.DotProduct(ref ent.v.velocity, ref primal_velocity) <= 0) { ent.v.velocity = default(v3f); return(blocked); } } return(blocked); }
public static void SV_WalkMove(edict_t ent) { // // do a regular slide move unless it looks like you ran into a step // int oldonground = (int)ent.v.flags & q_shared.FL_ONGROUND; ent.v.flags = (int)ent.v.flags & ~q_shared.FL_ONGROUND; v3f oldorg = ent.v.origin; v3f oldvel = ent.v.velocity; trace_t steptrace = new trace_t(); int clip = SV_FlyMove(ent, (float)host_framtime, steptrace); if ((clip & 2) == 0) { return; // move didn't block on a step } if (oldonground == 0 && ent.v.waterlevel == 0) { return; // don't stair up while jumping } if (ent.v.movetype != q_shared.MOVETYPE_WALK) { return; // gibbed by a trigger } if (sv_nostep.value != 0) { return; } if (((int)sv_player.v.flags & q_shared.FL_WATERJUMP) != 0) { return; } v3f nosteporg = ent.v.origin; v3f nostepvel = ent.v.velocity; // // try moving up and forward to go up a step // ent.v.origin = oldorg; // back to start pos v3f upmove = q_shared.ZeroVector3f; v3f downmove = upmove; upmove.z = q_shared.STEPSIZE; downmove.z = (float)(-q_shared.STEPSIZE + oldvel.z * host_framtime); // move up PushEntity(ent, ref upmove); // FIXME: don't link? // move forward ent.v.velocity.x = oldvel.x; ent.v.velocity.y = oldvel.y; ent.v.velocity.z = 0; clip = SV_FlyMove(ent, (float)host_framtime, steptrace); // check for stuckness, possibly due to the limited precision of floats // in the clipping hulls if (clip != 0) { if (Math.Abs(oldorg.y - ent.v.origin.y) < 0.03125 && Math.Abs(oldorg.x - ent.v.origin.x) < 0.03125) { // stepping up didn't make any progress clip = SV_TryUnstick(ent, ref oldvel); } } // extra friction based on view angle if ((clip & 2) != 0) { SV_WallFriction(ent, steptrace); } // move down trace_t downtrace = PushEntity(ent, ref downmove); // FIXME: don't link? if (downtrace.plane.normal.Z > 0.7) { if (ent.v.solid == q_shared.SOLID_BSP) { ent.v.flags = (int)ent.v.flags | q_shared.FL_ONGROUND; ent.v.groundentity = EDICT_TO_PROG(downtrace.ent); } } else { // if the push down didn't end up on good ground, use the move without // the step up. This happens near wall / slope combinations, and can // cause the player to hop up higher on a slope too steep to climb ent.v.origin = nosteporg; ent.v.velocity = nostepvel; } }
private void ParseClustersPacket(BinaryReader br) { ClusterMsg msg = new ClusterMsg(); // read the header byte packetType = br.ReadByte(); if (packetType != CLUSTER_PACKET_TYPE) { Debug.WriteLine("ERROR: cluster parser got packet starting with " + packetType.ToString()); return; } UInt16 packetNum = br.ReadUInt16(); UInt16 tsSeconds = br.ReadUInt16(); UInt32 tsTicks = br.ReadUInt32(); UInt16 numPts = br.ReadUInt16(); UInt16 numClusters = br.ReadUInt16(); msg.timestamp = (double)tsSeconds + (double)tsTicks / 10000.0; // now for the red meat.. v3f[] pts = new v3f[numPts]; for (int i = 0; i < numPts; i++) { pts[i].x = (float)(br.ReadInt16()) / 100.0f; pts[i].y = (float)(br.ReadInt16()) / 100.0f; pts[i].z = (float)(br.ReadInt16()) / 100.0f; } msg.clusters = new List <LidarCluster>(); for (int i = 0; i < numClusters; i++) { LidarCluster lc = new LidarCluster(); UInt16 firstPtIndex, lastPtIndex; byte flags; firstPtIndex = br.ReadUInt16(); lastPtIndex = br.ReadUInt16(); flags = br.ReadByte(); lc.pts = new v3f[lastPtIndex - firstPtIndex + 1]; lc.stable = (flags & 0x01) == 0; lc.leftOccluded = (flags & 0x02) != 0; lc.rightOccluded = (flags & 0x04) != 0; lc.highObstacle = (flags & 0x08) != 0; lc.bb_low.x = lc.bb_high.x = pts[firstPtIndex].x; lc.bb_low.y = lc.bb_high.y = pts[firstPtIndex].y; lc.bb_low.z = lc.bb_high.z = pts[firstPtIndex].z; for (int j = firstPtIndex; j <= lastPtIndex; j++) { lc.pts[j - firstPtIndex] = pts[j]; lc.bb_low.x = Math.Min(lc.bb_low.x, pts[j].x); lc.bb_low.y = Math.Min(lc.bb_low.y, pts[j].y); lc.bb_low.z = Math.Min(lc.bb_low.z, pts[j].z); lc.bb_high.x = Math.Max(lc.bb_high.x, pts[j].x); lc.bb_high.y = Math.Max(lc.bb_high.y, pts[j].y); lc.bb_high.z = Math.Max(lc.bb_high.z, pts[j].z); } msg.clusters.Add(lc); } if (ClustersReceived != null) { ClustersReceived(this, new ClusterRXEventArgs(msg)); } }
public static Vector3 ToVector(ref v3f v) { return(new Vector3(v.x, v.y, v.z)); }
public static void Copy(ref Vector3 src, out v3f dest) { dest.x = src.X; dest.y = src.Y; dest.z = src.Z; }
static unsafe void Copy(float *src, ref v3f dest) { dest.x = src[0]; dest.y = src[1]; dest.z = src[2]; }
public static void SV_SetIdealPitch() { if (((int)sv_player.v.flags & q_shared.FL_ONGROUND) == 0) { return; } double angleval = sv_player.v.angles.y * Math.PI * 2 / 360; double sinval = Math.Sin(angleval); double cosval = Math.Cos(angleval); float[] z = new float[q_shared.MAX_FORWARD]; for (int i = 0; i < q_shared.MAX_FORWARD; i++) { v3f top = sv_player.v.origin; top.x += (float)(cosval * (i + 3) * 12); top.y += (float)(sinval * (i + 3) * 12); top.z += sv_player.v.view_ofs.z; v3f bottom = top; bottom.z -= 160; trace_t tr = Move(ref top, ref q_shared.ZeroVector3f, ref q_shared.ZeroVector3f, ref bottom, 1, sv_player); if (tr.allsolid) { return; // looking at a wall, leave ideal the way is was } if (tr.fraction == 1) { return; // near a dropoff } z[i] = top.z + tr.fraction * (bottom.z - top.z); } float dir = 0; // Uze: int in original code??? int steps = 0; for (int j = 1; j < q_shared.MAX_FORWARD; j++) { float step = z[j] - z[j - 1]; // Uze: int in original code??? if (step > -q_shared.ON_EPSILON && step < q_shared.ON_EPSILON) // Uze: comparing int with ON_EPSILON (0.1)??? { continue; } if (dir != 0 && (step - dir > q_shared.ON_EPSILON || step - dir < -q_shared.ON_EPSILON)) { return; // mixed changes } steps++; dir = step; } if (dir == 0) { sv_player.v.idealpitch = 0; return; } if (steps < 2) { return; } sv_player.v.idealpitch = -dir * sv_idealpitchscale.value; }