Exemple #1
0
    public static void R_MarkLeaves()
    {
        if (r_oldviewleaf == r_viewleaf && r_novis.value == 0)
        {
            return;
        }

        if (mirror)
        {
            return;
        }

        r_visframecount++;
        r_oldviewleaf = r_viewleaf;

        byte[] vis;
        if (r_novis.value != 0)
        {
            vis = new byte[4096];
            FillArray <Byte>(vis, 0xff); // todo: add count parameter?
            //memset(solid, 0xff, (cl.worldmodel->numleafs + 7) >> 3);
        }
        else
        {
            vis = Mod_LeafPVS(r_viewleaf, cl.worldmodel);
        }

        model_t world = cl.worldmodel;

        for (int i = 0; i < world.numleafs; i++)
        {
            if (vis[i >> 3] != 0 & (1 << (i & 7)) != 0)
            {
                mnodebase_t node = world.leafs[i + 1];
                do
                {
                    if (node.visframe == r_visframecount)
                    {
                        break;
                    }
                    node.visframe = r_visframecount;
                    node          = node.parent;
                } while (node != null);
            }
        }
    }
Exemple #2
0
    public static void SV_FindTouchedLeafs(edict_t ent, mnodebase_t node)
    {
        if (node.contents == q_shared.CONTENTS_SOLID)
        {
            return;
        }

        // add an efrag if the node is a leaf

        if (node.contents < 0)
        {
            if (ent.num_leafs == q_shared.MAX_ENT_LEAFS)
            {
                return;
            }

            mleaf_t leaf    = (mleaf_t)node;
            int     leafnum = Array.IndexOf(sv.worldmodel.leafs, leaf) - 1;

            ent.leafnums[ent.num_leafs] = (short)leafnum;
            ent.num_leafs++;
            return;
        }

        // NODE_MIXED
        mnode_t  n          = (mnode_t)node;
        mplane_t splitplane = n.plane;
        int      sides      = Mathlib.BoxOnPlaneSide(ref ent.v.absmin, ref ent.v.absmax, splitplane);

        // recurse down the contacted sides
        if ((sides & 1) != 0)
        {
            SV_FindTouchedLeafs(ent, n.children[0]);
        }

        if ((sides & 2) != 0)
        {
            SV_FindTouchedLeafs(ent, n.children[1]);
        }
    }
Exemple #3
0
    public static void R_MarkLights(dlight_t light, int bit, mnodebase_t node)
    {
        if (node.contents < 0)
        {
            return;
        }

        mnode_t  n          = (mnode_t)node;
        mplane_t splitplane = n.plane;
        float    dist       = Vector3.Dot(light.origin, splitplane.normal) - splitplane.dist;

        if (dist > light.radius)
        {
            R_MarkLights(light, bit, n.children[0]);
            return;
        }
        if (dist < -light.radius)
        {
            R_MarkLights(light, bit, n.children[1]);
            return;
        }

        // mark the polygons
        for (int i = 0; i < n.numsurfaces; i++)
        {
            msurface_t surf = cl.worldmodel.surfaces[n.firstsurface + i];
            if (surf.dlightframe != r_dlightframecount)
            {
                surf.dlightbits  = 0;
                surf.dlightframe = r_dlightframecount;
            }
            surf.dlightbits |= bit;
        }

        R_MarkLights(light, bit, n.children[0]);
        R_MarkLights(light, bit, n.children[1]);
    }
    public static void SV_AddToFatPVS(ref Vector3 org, mnodebase_t node)
    {
        while (true)
        {
            // if this is a leaf, accumulate the pvs bits
            if (node.contents < 0)
            {
                if (node.contents != q_shared.CONTENTS_SOLID)
                {
                    byte[] pvs = Mod_LeafPVS((mleaf_t)node, sv.worldmodel);
                    for (int i = 0; i < fatbytes; i++)
                    {
                        fatpvs[i] |= pvs[i];
                    }
                }
                return;
            }

            mnode_t  n     = (mnode_t)node;
            mplane_t plane = n.plane;
            float    d     = Vector3.Dot(org, plane.normal) - plane.dist;
            if (d > 8)
            {
                node = n.children[0];
            }
            else if (d < -8)
            {
                node = n.children[1];
            }
            else
            {   // go down both
                SV_AddToFatPVS(ref org, n.children[0]);
                node = n.children[1];
            }
        }
    }
Exemple #5
0
    public static int RecursiveLightPoint(mnodebase_t node, ref Vector3 start, ref Vector3 end)
    {
        if (node.contents < 0)
        {
            return(-1);          // didn't hit anything
        }
        mnode_t n = (mnode_t)node;

        // calculate mid point

        // FIXME: optimize for axial
        mplane_t plane = n.plane;
        float    front = Vector3.Dot(start, plane.normal) - plane.dist;
        float    back  = Vector3.Dot(end, plane.normal) - plane.dist;
        int      side  = front < 0 ? 1 : 0;

        if ((back < 0 ? 1 : 0) == side)
        {
            return(RecursiveLightPoint(n.children[side], ref start, ref end));
        }

        float   frac = front / (front - back);
        Vector3 mid  = start + (end - start) * frac;

        // go down front side
        int r = RecursiveLightPoint(n.children[side], ref start, ref mid);

        if (r >= 0)
        {
            return(r);           // hit something
        }
        if ((back < 0 ? 1 : 0) == side)
        {
            return(-1);          // didn't hit anuthing
        }
        // check for impact on this node
        lightspot  = mid;
        lightplane = plane;

        msurface_t[] surf   = cl.worldmodel.surfaces;
        int          offset = n.firstsurface;

        for (int i = 0; i < n.numsurfaces; i++, offset++)
        {
            if ((surf[offset].flags & q_shared.SURF_DRAWTILED) != 0)
            {
                continue;       // no lightmaps
            }
            mtexinfo_t tex = surf[offset].texinfo;

            int s = (int)(Vector3.Dot(mid, tex.vecs[0].Xyz) + tex.vecs[0].W);
            int t = (int)(Vector3.Dot(mid, tex.vecs[1].Xyz) + tex.vecs[1].W);

            if (s < surf[offset].texturemins[0] || t < surf[offset].texturemins[1])
            {
                continue;
            }

            int ds = s - surf[offset].texturemins[0];
            int dt = t - surf[offset].texturemins[1];

            if (ds > surf[offset].extents[0] || dt > surf[offset].extents[1])
            {
                continue;
            }

            if (surf[offset].sample_base == null)
            {
                return(0);
            }

            ds >>= 4;
            dt >>= 4;

            byte[]  lightmap = surf[offset].sample_base;
            int     lmOffset = surf[offset].sampleofs;
            short[] extents  = surf[offset].extents;
            r = 0;
            if (lightmap != null)
            {
                lmOffset += dt * ((extents[0] >> 4) + 1) + ds;

                for (int maps = 0; maps < q_shared.MAXLIGHTMAPS && surf[offset].styles[maps] != 255; maps++)
                {
                    int scale = d_lightstylevalue[surf[offset].styles[maps]];
                    r        += lightmap[lmOffset] * scale;
                    lmOffset += ((extents[0] >> 4) + 1) * ((extents[1] >> 4) + 1);
                }

                r >>= 8;
            }

            return(r);
        }

        // go down back side
        return(RecursiveLightPoint(n.children[side == 0 ? 1 : 0], ref mid, ref end));
    }
Exemple #6
0
    public static void R_RecursiveWorldNode(mnodebase_t node)
    {
        if (node.contents == q_shared.CONTENTS_SOLID)
        {
            return;             // solid
        }
        if (node.visframe != r_visframecount)
        {
            return;
        }
        if (R_CullBox(ref node.mins, ref node.maxs))
        {
            return;
        }

        int c;

        // if a leaf node, draw stuff
        if (node.contents < 0)
        {
            mleaf_t      pleaf = (mleaf_t)node;
            msurface_t[] marks = pleaf.marksurfaces;
            int          mark  = pleaf.firstmarksurface;
            c = pleaf.nummarksurfaces;

            if (c != 0)
            {
                do
                {
                    marks[mark].visframe = r_framecount;
                    mark++;
                } while (--c != 0);
            }

            // deal with model fragments in this leaf
            if (pleaf.efrags != null)
            {
                R_StoreEfrags(pleaf.efrags);
            }

            return;
        }

        // node is just a decision point, so go down the apropriate sides

        mnode_t n = (mnode_t)node;

        // find which side of the node we are on
        mplane_t plane = n.plane;
        double   dot;

        switch (plane.type)
        {
        case q_shared.PLANE_X:
            dot = modelorg.X - plane.dist;
            break;

        case q_shared.PLANE_Y:
            dot = modelorg.Y - plane.dist;
            break;

        case q_shared.PLANE_Z:
            dot = modelorg.Z - plane.dist;
            break;

        default:
            dot = Vector3.Dot(modelorg, plane.normal) - plane.dist;
            break;
        }

        int side = (dot >= 0 ? 0 : 1);

        // recurse down the children, front side first
        R_RecursiveWorldNode(n.children[side]);

        // draw stuff
        c = n.numsurfaces;

        if (c != 0)
        {
            msurface_t[] surf   = cl.worldmodel.surfaces;
            int          offset = n.firstsurface;

            if (dot < 0 - q_shared.BACKFACE_EPSILON)
            {
                side = q_shared.SURF_PLANEBACK;
            }
            else if (dot > q_shared.BACKFACE_EPSILON)
            {
                side = 0;
            }

            for (; c != 0; c--, offset++)
            {
                if (surf[offset].visframe != r_framecount)
                {
                    continue;
                }

                // don't backface underwater surfaces, because they warp
                if ((surf[offset].flags & q_shared.SURF_UNDERWATER) == 0 && ((dot < 0) ^ ((surf[offset].flags & q_shared.SURF_PLANEBACK) != 0)))
                {
                    continue;           // wrong side
                }
                // if sorting by texture, just store it out
                if (gl_texsort.value != 0)
                {
                    if (!mirror || surf[offset].texinfo.texture != cl.worldmodel.textures[mirrortexturenum])
                    {
                        surf[offset].texturechain = surf[offset].texinfo.texture.texturechain;
                        surf[offset].texinfo.texture.texturechain = surf[offset];
                    }
                }
                else if ((surf[offset].flags & q_shared.SURF_DRAWSKY) != 0)
                {
                    surf[offset].texturechain = skychain;
                    skychain = surf[offset];
                }
                else if ((surf[offset].flags & q_shared.SURF_DRAWTURB) != 0)
                {
                    surf[offset].texturechain = waterchain;
                    waterchain = surf[offset];
                }
                else
                {
                    R_DrawSequentialPoly(surf[offset]);
                }
            }
        }

        // recurse down the back side
        R_RecursiveWorldNode(n.children[side == 0 ? 1 : 0]);
    }
    public static void R_SplitEntityOnNode(mnodebase_t node)
    {
        if (node.contents == q_shared.CONTENTS_SOLID)
        {
            return;
        }

        // add an efrag if the node is a leaf
        if (node.contents < 0)
        {
            if (r_pefragtopnode == null)
            {
                r_pefragtopnode = node as mnode_t;
            }

            mleaf_t leaf = (mleaf_t)(object)node;

            // grab an efrag off the free list
            efrag_t ef = cl.free_efrags;
            if (ef == null)
            {
                Con_Printf("Too many efrags!\n");
                return; // no free fragments...
            }
            cl.free_efrags = cl.free_efrags.entnext;

            ef.entity = r_addent;

            // add the entity link
            // *lastlink = ef;
            if (_LastObj is entity_t)
            {
                ((entity_t)_LastObj).efrag = ef;
            }
            else
            {
                ((efrag_t)_LastObj).entnext = ef;
            }
            _LastObj   = ef; // lastlink = &ef->entnext;
            ef.entnext = null;

            // set the leaf links
            ef.leaf     = leaf;
            ef.leafnext = leaf.efrags;
            leaf.efrags = ef;

            return;
        }

        // NODE_MIXED
        mnode_t n = node as mnode_t;

        if (n == null)
        {
            return;
        }

        mplane_t splitplane = n.plane;
        int      sides      = Mathlib.BoxOnPlaneSide(ref r_emins, ref r_emaxs, splitplane);

        if (sides == 3)
        {
            // split on this plane
            // if this is the first splitter of this bmodel, remember it
            if (r_pefragtopnode == null)
            {
                r_pefragtopnode = n;
            }
        }

        // recurse down the contacted sides
        if ((sides & 1) != 0)
        {
            R_SplitEntityOnNode(n.children[0]);
        }

        if ((sides & 2) != 0)
        {
            R_SplitEntityOnNode(n.children[1]);
        }
    }