Example #1
0
        /// <summary>
        /// SV_HullPointContents
        /// </summary>
        static int 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);
        }
Example #2
0
        /// <summary>
        /// SV_ClipMoveToEntity
        /// Handles selection or creation of a clipping hull, and offseting (and
        /// eventually rotation) of the end points
        /// </summary>
        static trace_t ClipMoveToEntity(edict_t ent, ref Vector3 start, ref Vector3 mins, ref Vector3 maxs, ref Vector3 end)
        {
            trace_t trace = new trace_t();

            // fill in a default trace
            trace.fraction = 1;
            trace.allsolid = true;
            trace.endpos   = end;

            // get the clipping hull
            Vector3 offset;
            hull_t  hull = HullForEntity(ent, ref mins, ref maxs, out offset);

            Vector3 start_l = start - offset;
            Vector3 end_l   = end - offset;

            // trace a line through the apropriate clipping hull
            RecursiveHullCheck(hull, hull.firstclipnode, 0, 1, ref start_l, ref end_l, trace);

            // fix trace up by the offset
            if (trace.fraction != 1)
            {
                trace.endpos += offset;
            }

            // did we clip the move?
            if (trace.fraction < 1 || trace.startsolid)
            {
                trace.ent = ent;
            }

            return(trace);
        }
Example #3
0
 public void CopyFrom(hull_t src)
 {
     this.clipnodes     = src.clipnodes;
     this.planes        = src.planes;
     this.firstclipnode = src.firstclipnode;
     this.lastclipnode  = src.lastclipnode;
     this.clip_mins     = src.clip_mins;
     this.clip_maxs     = src.clip_maxs;
 }
Example #4
0
        /// <summary>
        /// SV_HullForEntity
        /// Returns a hull that can be used for testing or clipping an object of mins/maxs size.
        /// Offset is filled in to contain the adjustment that must be added to the
        /// testing object's origin to get a point to use with the returned hull.
        /// </summary>
        static hull_t HullForEntity(edict_t ent, ref Vector3 mins, ref Vector3 maxs, out Vector3 offset)
        {
            hull_t hull = null;

            // decide which clipping hull to use, based on the size
            if (ent.v.solid == Solids.SOLID_BSP)
            {   // explicit hulls in the BSP model
                if (ent.v.movetype != Movetypes.MOVETYPE_PUSH)
                {
                    Sys.Error("SOLID_BSP without MOVETYPE_PUSH");
                }

                model_t model = sv.models[(int)ent.v.modelindex];

                if (model == null || model.type != modtype_t.mod_brush)
                {
                    Sys.Error("MOVETYPE_PUSH with a non bsp model");
                }

                Vector3 size = maxs - mins;
                if (size.X < 3)
                {
                    hull = model.hulls[0];
                }
                else if (size.X <= 32)
                {
                    hull = model.hulls[1];
                }
                else
                {
                    hull = model.hulls[2];
                }

                // calculate an offset value to center the origin
                offset  = hull.clip_mins - mins;
                offset += Common.ToVector(ref ent.v.origin);
            }
            else
            {
                // create a temp hull from bounding box sizes
                Vector3 hullmins = Common.ToVector(ref ent.v.mins) - maxs;
                Vector3 hullmaxs = Common.ToVector(ref ent.v.maxs) - mins;
                hull = HullForBox(ref hullmins, ref hullmaxs);

                offset = Common.ToVector(ref ent.v.origin);
            }

            return(hull);
        }
Example #5
0
        /// <summary>
        /// SV_RecursiveHullCheck
        /// </summary>
        public static bool 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 != Contents.CONTENTS_SOLID)
                {
                    trace.allsolid = false;
                    if (num == Contents.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(RecursiveHullCheck(hull, node_children[0], p1f, p2f, ref p1, ref p2, trace));
            }
            if (t1 < 0 && t2 < 0)
            {
                return(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 + DIST_EPSILON) / (t1 - t2);
            }
            else
            {
                frac = (t1 - 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 (!RecursiveHullCheck(hull, node_children[side], p1f, midf, ref p1, ref mid, trace))
            {
                return(false);
            }

            if (HullPointContents(hull, node_children[side ^ 1], ref mid) != Contents.CONTENTS_SOLID)
            {
                // go past the node
                return(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 (HullPointContents(hull, hull.firstclipnode, ref mid) == Contents.CONTENTS_SOLID)
            {
                // shouldn't really happen, but does occasionally
                frac -= 0.1f;
                if (frac < 0)
                {
                    trace.fraction = midf;
                    trace.endpos   = mid;
                    Con.DPrint("backup past 0\n");
                    return(false);
                }
                midf = p1f + (p2f - p1f) * frac;
                mid  = p1 + (p2 - p1) * frac;
            }

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

            return(false);
        }