public static int BoxOnPlaneSide(Vector3 emins, Vector3 emaxs, BSPPlane plane) { Vector3[] bounds = { emins, emaxs }; Vector3 normal = plane.normal; byte signbits = plane.Signbits; int sides = 0; int i = signbits & 1; int j = (signbits >> 1) & 1; int k = (signbits >> 2) & 1; float dist1 = normal[0] * bounds[i ^ 1][0] + normal[1] * bounds[j ^ 1][1] + normal[2] * bounds[k ^ 1][2]; float dist2 = normal[0] * bounds[i][0] + normal[1] * bounds[j][1] + normal[2] * bounds[k][2]; if (dist1 >= plane.distance) { sides = 1; } if (dist2 < plane.distance) { sides |= 2; } return(sides); }
public static float PlaneDiff(Vector3 v, BSPPlane p) { return(Vector3.Dot(v, p.normal) - p.distance); }
public static void Pmove(ref PlayerMoveData pmd) { //default mins = Vector3.zero; maxs = Vector3.zero; PlayerMove.pmd = pmd; groundplane = null; origin = pmd.inOrigin * 0.125f; velocity = pmd.inVelocity * 0.125f; frametime = pmd.frametime; pmflags = pmd.flags; if (pmd.addVelocities != Vector3.zero) { velocity += pmd.addVelocities; } if (PlayerState.mode == GameMode.flying) { PM_FlyMove(); if (PlayerState.Noclip) { origin += velocity * frametime; } else { PM_StepSlideMove_(); } FinishPmove(); pmd = PlayerMove.pmd; return; } PM_CheckDuck(); if (pmd.initialSnap) { PM_InitialSnapPosition(); } PM_CategorizePosition(); PM_CheckSpecialMovement(); //drop timing counter if (timer > 0) { float msec = frametime; if (msec == 0) { //? msec = 1; } if (msec >= timer) { pmflags &= ~PMFlags.PMF_TIME_WATERJUMP; timer = 0; } else { timer -= msec; } } if (pmflags.HasFlag(PMFlags.PMF_TIME_WATERJUMP)) { velocity.y -= PlayerState.pm_gravity * frametime; if (velocity.y < 0) { //cancel waterjump when we start falling pmflags &= ~PMFlags.PMF_TIME_WATERJUMP; timer = 0; } PM_StepSlideMove(); } else { PM_CheckJump(); PM_Friction(); if (waterlevel >= 2) { PM_WaterMove(); } else { PM_AirMove(); } } PM_CategorizePosition(); FinishPmove(); pmd = PlayerMove.pmd; }
/// <summary> /// Checks if player is standing on the ground and if he is in a water body. /// </summary> private static void PM_CategorizePosition() { TraceT trace; BrushContents cont; int sample1, sample2; if (velocity.y > 180) { groundentity = false; pmflags &= ~PMFlags.PMF_ON_GROUND; } else { trace = Trace.CL_Trace(origin, mins, maxs, origin - new Vector3(0, 0.25f, 0)); groundplane = trace.plane; groundsurface = trace.surface; groundcontents = trace.contents; if (trace.plane == null || (trace.plane.normal.y < 0.7f && !trace.startsolid)) { groundentity = false; pmflags &= ~PMFlags.PMF_ON_GROUND; } else { groundentity = true; //hitting solid ground will end a waterjump if (pmflags.HasFlag(PMFlags.PMF_TIME_WATERJUMP)) { pmflags &= ~PMFlags.PMF_TIME_WATERJUMP; timer = 0; } if (!pmflags.HasFlag(PMFlags.PMF_ON_GROUND)) { //just hit the ground pmflags |= PMFlags.PMF_ON_GROUND; } } } //get waterlevel waterlevel = 0; watertype = 0; sample2 = (int)viewheight - (int)mins.y; sample1 = sample2 / 2; Vector3 point = origin; point.y = origin.y + mins.y + 1; cont = Utils.NodePointSearch(BSPFile.headnode, point).contents; if ((cont & BrushContents.MASK_WATER) != 0) { watertype = cont; waterlevel = 1; point.y = origin.y + mins.y + sample1; cont = Utils.NodePointSearch(BSPFile.headnode, point).contents; if ((cont & BrushContents.MASK_WATER) != 0) { waterlevel = 2; point.y = origin.y + mins.y + sample2; cont = Utils.NodePointSearch(BSPFile.headnode, point).contents; if ((cont & BrushContents.MASK_WATER) != 0) { waterlevel = 3; } } } }
/// <summary> /// Checks for intersection with a brush during a moving trace. /// </summary> /// <param name="p1">Trace start.</param> /// <param name="p2">Trace end.</param> /// <param name="trace">Data struct.</param> /// <param name="brush">Brush to test against.</param> private static void CM_ClipBoxToBrush(Vector3 p1, Vector3 p2, ref TraceT trace, BSPBrush brush) { int i; BSPPlane plane; BSPPlane clipplane = new BSPPlane(); //initialize this to keep c# happy... float dist; float enterfrac, leavefrac; float d1, d2; bool getout, startout; bool hasclip = false; bool haslead = false; float f; BSPBrushSide leadside = new BSPBrushSide(); //initialize this to keep c# happy... BSPBrushSide[] sides; if (brush.numsides == 0) { return; } sides = brush.Sides; enterfrac = -1; leavefrac = 1; getout = false; //gets out of the brush startout = false; //starts inside the brush for (i = 0; i < brush.numsides; i++) { plane = sides[i].Plane; //we only need plane for each side //get plane to bounds point distance if (!trace_ispoint) { //bounding box trace dist = Vector3.Dot(trace_offsets[plane.Signbits], plane.normal); dist = plane.distance - dist; } else { //point trace dist = plane.distance; } //get distances for start and end of the trace d1 = Vector3.Dot(p1, plane.normal) - dist; //start d2 = Vector3.Dot(p2, plane.normal) - dist; //end if (d2 > 0) { getout = true; //endpoint is not in solid } if (d1 > 0) { startout = true; //starts outside } //if completely in front of a face, no intersection if (d1 > 0 && d2 >= d1) { return; //a single face plane that is not crossed while tracing means that we never hit that brush } //? if (d1 <= 0 && d2 <= 0) { continue; } //crosses face if (d1 > d2) { //enter f = (d1 - DIST_EPSILON) / (d1 - d2); //fraction of the distance covered before hitting a side if (f > enterfrac) { enterfrac = f; clipplane = plane; hasclip = true; //plane clips the trace leadside = sides[i]; haslead = true; //could be combined with hasclip? writes flags for the collided face } } else { //leave f = (d1 + DIST_EPSILON) / (d1 - d2); if (f < leavefrac) { leavefrac = f; } } } //startout wasn't true for any face if (!startout) { //original point was inside brush trace.startsolid = true; if (!getout) { trace.allsolid = true; //map_allsolid_bug trace.fraction = 0; trace.contents = brush.contents; } return; } //after testing all faces we need to see which test went further if (enterfrac < leavefrac) { //only write the test if the brush was closer than any brushes hit before if (enterfrac > -1 && enterfrac < trace.fraction) { if (enterfrac < 0) { enterfrac = 0; } trace.fraction = enterfrac; if (hasclip) { trace.plane = clipplane; } if (haslead) { if (leadside.HasTexInfo) { trace.surface = leadside.TexInfo.Surface; } } trace.contents = brush.contents; } } }