Exemple #1
0
    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);
    }
Exemple #2
0
 public static float PlaneDiff(Vector3 v, BSPPlane p)
 {
     return(Vector3.Dot(v, p.normal) - p.distance);
 }
Exemple #3
0
    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;
    }
Exemple #4
0
    /// <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;
                }
            }
        }
    }
Exemple #5
0
    /// <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;
            }
        }
    }