示例#1
0
    public static int SV_HullPointContents(hull_t hull, int num, ref Vector3 p)
    {
        while (num >= 0)
        {
            if (num < hull.firstclipnode || num > hull.lastclipnode)
            {
                Sys_Error("SV_HullPointContents: bad node number");
            }

            short[]  node_children = hull.clipnodes[num].children;
            mplane_t plane         = hull.planes[hull.clipnodes[num].planenum];
            float    d;
            if (plane.type < 3)
            {
                d = Mathlib.Comp(ref p, plane.type) - plane.dist;
            }
            else
            {
                d = Vector3.Dot(plane.normal, p) - plane.dist;
            }
            if (d < 0)
            {
                num = node_children[1];
            }
            else
            {
                num = node_children[0];
            }
        }

        return(num);
    }
示例#2
0
    public static void SV_TouchLinks(edict_t ent, areanode_t node)
    {
        // touch linked edicts
        link_t next;

        for (link_t l = node.trigger_edicts.Next; l != node.trigger_edicts; l = next)
        {
            next = l.Next;
            edict_t touch = (edict_t)l.Owner;// EDICT_FROM_AREA(l);
            if (touch == ent)
            {
                continue;
            }
            if (touch.v.touch == 0 || touch.v.solid != q_shared.SOLID_TRIGGER)
            {
                continue;
            }
            if (ent.v.absmin.x > touch.v.absmax.x || ent.v.absmin.y > touch.v.absmax.y ||
                ent.v.absmin.z > touch.v.absmax.z || ent.v.absmax.x < touch.v.absmin.x ||
                ent.v.absmax.y < touch.v.absmin.y || ent.v.absmax.z < touch.v.absmin.z)
            {
                continue;
            }

            int old_self  = pr_global_struct.self;
            int old_other = pr_global_struct.other;

            pr_global_struct.self  = EDICT_TO_PROG(touch);
            pr_global_struct.other = EDICT_TO_PROG(ent);
            pr_global_struct.time  = (float)sv.time;
            PR_ExecuteProgram(touch.v.touch);

            pr_global_struct.self  = old_self;
            pr_global_struct.other = old_other;
        }

        // recurse down both sides
        if (node.axis == -1)
        {
            return;
        }

        if (Mathlib.Comp(ref ent.v.absmax, node.axis) > node.dist)
        {
            SV_TouchLinks(ent, node.children[0]);
        }
        if (Mathlib.Comp(ref ent.v.absmin, node.axis) < node.dist)
        {
            SV_TouchLinks(ent, node.children[1]);
        }
    }
示例#3
0
    static void PF_makestatic()
    {
        edict_t   ent = G_EDICT(q_shared.OFS_PARM0);
        MsgWriter msg = sv.signon;

        msg.MSG_WriteByte(q_shared.svc_spawnstatic);
        msg.MSG_WriteByte(SV_ModelIndex(GetString(ent.v.model)));
        msg.MSG_WriteByte((int)ent.v.frame);
        msg.MSG_WriteByte((int)ent.v.colormap);
        msg.MSG_WriteByte((int)ent.v.skin);
        for (int i = 0; i < 3; i++)
        {
            msg.MSG_WriteCoord(Mathlib.Comp(ref ent.v.origin, i));
            msg.MSG_WriteAngle(Mathlib.Comp(ref ent.v.angles, i));
        }

        // throw the entity away now
        ED_Free(ent);
    }
示例#4
0
    public static void SV_LinkEdict(edict_t ent, bool touch_triggers)
    {
        if (ent.area.Prev != null)
        {
            SV_UnlinkEdict(ent);        // unlink from old position
        }
        if (ent == sv.edicts[0])
        {
            return;             // don't add the world
        }
        if (ent.free)
        {
            return;
        }

        // set the abs box
        Mathlib.VectorAdd(ref ent.v.origin, ref ent.v.mins, out ent.v.absmin);
        Mathlib.VectorAdd(ref ent.v.origin, ref ent.v.maxs, out ent.v.absmax);

        //
        // to make items easier to pick up and allow them to be grabbed off
        // of shelves, the abs sizes are expanded
        //
        if (((int)ent.v.flags & q_shared.FL_ITEM) != 0)
        {
            ent.v.absmin.x -= 15;
            ent.v.absmin.y -= 15;
            ent.v.absmax.x += 15;
            ent.v.absmax.y += 15;
        }
        else
        {       // because movement is clipped an epsilon away from an actual edge,
            // we must fully check even when bounding boxes don't quite touch
            ent.v.absmin.x -= 1;
            ent.v.absmin.y -= 1;
            ent.v.absmin.z -= 1;
            ent.v.absmax.x += 1;
            ent.v.absmax.y += 1;
            ent.v.absmax.z += 1;
        }

        // link to PVS leafs
        ent.num_leafs = 0;
        if (ent.v.modelindex != 0)
        {
            SV_FindTouchedLeafs(ent, sv.worldmodel.nodes[0]);
        }

        if (ent.v.solid == q_shared.SOLID_NOT)
        {
            return;
        }

        // find the first node that the ent's box crosses
        areanode_t node = sv_areanodes[0];

        while (true)
        {
            if (node.axis == -1)
            {
                break;
            }
            if (Mathlib.Comp(ref ent.v.absmin, node.axis) > node.dist)
            {
                node = node.children[0];
            }
            else if (Mathlib.Comp(ref ent.v.absmax, node.axis) < node.dist)
            {
                node = node.children[1];
            }
            else
            {
                break;          // crosses the node
            }
        }

        // link it in

        if (ent.v.solid == q_shared.SOLID_TRIGGER)
        {
            ent.area.InsertBefore(node.trigger_edicts);
        }
        else
        {
            ent.area.InsertBefore(node.solid_edicts);
        }

        // if touch_triggers, touch all entities at this node and decend for more
        if (touch_triggers)
        {
            SV_TouchLinks(ent, sv_areanodes[0]);
        }
    }
示例#5
0
    public static void SV_ClipToLinks(areanode_t node, moveclip_t clip)
    {
        link_t  next;
        trace_t trace;

        // touch linked edicts
        for (link_t l = node.solid_edicts.Next; l != node.solid_edicts; l = next)
        {
            next = l.Next;
            edict_t touch = (edict_t)l.Owner;// EDICT_FROM_AREA(l);
            if (touch.v.solid == q_shared.SOLID_NOT)
            {
                continue;
            }
            if (touch == clip.passedict)
            {
                continue;
            }
            if (touch.v.solid == q_shared.SOLID_TRIGGER)
            {
                Sys_Error("Trigger in clipping list");
            }

            if (clip.type == q_shared.MOVE_NOMONSTERS && touch.v.solid != q_shared.SOLID_BSP)
            {
                continue;
            }

            if (clip.boxmins.X > touch.v.absmax.x || clip.boxmins.Y > touch.v.absmax.y ||
                clip.boxmins.Z > touch.v.absmax.z || clip.boxmaxs.X < touch.v.absmin.x ||
                clip.boxmaxs.Y < touch.v.absmin.y || clip.boxmaxs.Z < touch.v.absmin.z)
            {
                continue;
            }

            if (clip.passedict != null && clip.passedict.v.size.x != 0 && touch.v.size.x == 0)
            {
                continue;       // points never interact
            }
            // might intersect, so do an exact clip
            if (clip.trace.allsolid)
            {
                return;
            }
            if (clip.passedict != null)
            {
                if (PROG_TO_EDICT(touch.v.owner) == clip.passedict)
                {
                    continue;   // don't clip against own missiles
                }
                if (PROG_TO_EDICT(clip.passedict.v.owner) == touch)
                {
                    continue;   // don't clip against owner
                }
            }

            if (((int)touch.v.flags & q_shared.FL_MONSTER) != 0)
            {
                trace = SV_ClipMoveToEntity(touch, ref clip.start, ref clip.mins2, ref clip.maxs2, ref clip.end);
            }
            else
            {
                trace = SV_ClipMoveToEntity(touch, ref clip.start, ref clip.mins, ref clip.maxs, ref clip.end);
            }

            if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction)
            {
                trace.ent = touch;
                if (clip.trace.startsolid)
                {
                    clip.trace            = trace;
                    clip.trace.startsolid = true;
                }
                else
                {
                    clip.trace = trace;
                }
            }
            else if (trace.startsolid)
            {
                clip.trace.startsolid = true;
            }
        }

        // recurse down both sides
        if (node.axis == -1)
        {
            return;
        }

        if (Mathlib.Comp(ref clip.boxmaxs, node.axis) > node.dist)
        {
            SV_ClipToLinks(node.children[0], clip);
        }
        if (Mathlib.Comp(ref clip.boxmins, node.axis) < node.dist)
        {
            SV_ClipToLinks(node.children[1], clip);
        }
    }
示例#6
0
    public static bool SV_RecursiveHullCheck(hull_t hull, int num, float p1f, float p2f, ref Vector3 p1, ref Vector3 p2, trace_t trace)
    {
        // check for empty
        if (num < 0)
        {
            if (num != q_shared.CONTENTS_SOLID)
            {
                trace.allsolid = false;
                if (num == q_shared.CONTENTS_EMPTY)
                {
                    trace.inopen = true;
                }
                else
                {
                    trace.inwater = true;
                }
            }
            else
            {
                trace.startsolid = true;
            }
            return(true);                // empty
        }

        if (num < hull.firstclipnode || num > hull.lastclipnode)
        {
            Sys_Error("SV_RecursiveHullCheck: bad node number");
        }

        //
        // find the point distances
        //
        short[]  node_children = hull.clipnodes[num].children;
        mplane_t plane = hull.planes[hull.clipnodes[num].planenum];
        float    t1, t2;

        if (plane.type < 3)
        {
            t1 = Mathlib.Comp(ref p1, plane.type) - plane.dist;
            t2 = Mathlib.Comp(ref p2, plane.type) - plane.dist;
        }
        else
        {
            t1 = Vector3.Dot(plane.normal, p1) - plane.dist;
            t2 = Vector3.Dot(plane.normal, p2) - plane.dist;
        }

        if (t1 >= 0 && t2 >= 0)
        {
            return(SV_RecursiveHullCheck(hull, node_children[0], p1f, p2f, ref p1, ref p2, trace));
        }
        if (t1 < 0 && t2 < 0)
        {
            return(SV_RecursiveHullCheck(hull, node_children[1], p1f, p2f, ref p1, ref p2, trace));
        }

        // put the crosspoint DIST_EPSILON pixels on the near side
        float frac;

        if (t1 < 0)
        {
            frac = (t1 + q_shared.DIST_EPSILON) / (t1 - t2);
        }
        else
        {
            frac = (t1 - q_shared.DIST_EPSILON) / (t1 - t2);
        }
        if (frac < 0)
        {
            frac = 0;
        }
        if (frac > 1)
        {
            frac = 1;
        }

        float   midf = p1f + (p2f - p1f) * frac;
        Vector3 mid  = p1 + (p2 - p1) * frac;

        int side = (t1 < 0) ? 1 : 0;

        // move up to the node
        if (!SV_RecursiveHullCheck(hull, node_children[side], p1f, midf, ref p1, ref mid, trace))
        {
            return(false);
        }

        if (SV_HullPointContents(hull, node_children[side ^ 1], ref mid) != q_shared.CONTENTS_SOLID)
        {
            // go past the node
            return(SV_RecursiveHullCheck(hull, node_children[side ^ 1], midf, p2f, ref mid, ref p2, trace));
        }

        if (trace.allsolid)
        {
            return(false);               // never got out of the solid area
        }
        //==================
        // the other side of the node is solid, this is the impact point
        //==================
        if (side == 0)
        {
            trace.plane.normal = plane.normal;
            trace.plane.dist   = plane.dist;
        }
        else
        {
            trace.plane.normal = -plane.normal;
            trace.plane.dist   = -plane.dist;
        }

        while (SV_HullPointContents(hull, hull.firstclipnode, ref mid) == q_shared.CONTENTS_SOLID)
        {
            // shouldn't really happen, but does occasionally
            frac -= 0.1f;
            if (frac < 0)
            {
                trace.fraction = midf;
                trace.endpos   = mid;
                Con_DPrintf("backup past 0\n");
                return(false);
            }
            midf = p1f + (p2f - p1f) * frac;
            mid  = p1 + (p2 - p1) * frac;
        }

        trace.fraction = midf;
        trace.endpos   = mid;

        return(false);
    }
示例#7
0
    static void SubdividePolygon(int numverts, Vector3[] verts)
    {
        if (numverts > 60)
        {
            Sys_Error("numverts = {0}", numverts);
        }

        Vector3 mins, maxs;

        BoundPoly(numverts, verts, out mins, out maxs);

        float[] dist = new float[64];
        for (int i = 0; i < 3; i++)
        {
            double m = (Mathlib.Comp(ref mins, i) + Mathlib.Comp(ref maxs, i)) * 0.5;
            m = gl_subdivide_size.value * Math.Floor(m / gl_subdivide_size.value + 0.5);
            if (Mathlib.Comp(ref maxs, i) - m < 8)
            {
                continue;
            }

            if (m - Mathlib.Comp(ref mins, i) < 8)
            {
                continue;
            }

            for (int j = 0; j < numverts; j++)
            {
                dist[j] = (float)(Mathlib.Comp(ref verts[j], i) - m);
            }

            Vector3[] front = new Vector3[64];
            Vector3[] back  = new Vector3[64];

            // cut it

            // wrap cases
            dist[numverts]  = dist[0];
            verts[numverts] = verts[0]; // Uze: source array must be at least numverts + 1 elements long

            int f = 0, b = 0;
            for (int j = 0; j < numverts; j++)
            {
                if (dist[j] >= 0)
                {
                    front[f] = verts[j];
                    f++;
                }
                if (dist[j] <= 0)
                {
                    back[b] = verts[j];
                    b++;
                }
                if (dist[j] == 0 || dist[j + 1] == 0)
                {
                    continue;
                }
                if ((dist[j] > 0) != (dist[j + 1] > 0))
                {
                    // clip point
                    float frac = dist[j] / (dist[j] - dist[j + 1]);
                    front[f] = back[b] = verts[j] + (verts[j + 1] - verts[j]) * frac;
                    f++;
                    b++;
                }
            }

            SubdividePolygon(f, front);
            SubdividePolygon(b, back);
            return;
        }

        glpoly_t poly = new glpoly_t();

        poly.next       = _WarpFace.polys;
        _WarpFace.polys = poly;
        poly.AllocVerts(numverts);
        for (int i = 0; i < numverts; i++)
        {
            Copy(ref verts[i], poly.verts[i]);
            float s = Vector3.Dot(verts[i], _WarpFace.texinfo.vecs[0].Xyz);
            float t = Vector3.Dot(verts[i], _WarpFace.texinfo.vecs[1].Xyz);
            poly.verts[i][3] = s;
            poly.verts[i][4] = t;
        }
    }