Exemple #1
0
        /*
         * ===========
         * R_AddEfrags
         * ===========
         */
        public static void R_AddEfrags(entity_t ent)
        {
            model.model_t entmodel;
            int           i;

            if (ent.model == null)
            {
                return;
            }

            if (ent == client.cl_entities[0])
            {
                return;         // never add the world
            }
            r_addent = ent;

            lastlink        = null;
            r_pefragtopnode = null;

            entmodel = ent.model;

            for (i = 0; i < 3; i++)
            {
                r_emins[i] = ent.origin[i] + entmodel.mins[i];
                r_emaxs[i] = ent.origin[i] + entmodel.maxs[i];
            }

            R_SplitEntityOnNode(client.cl.worldmodel.nodes[0]);

            ent.topnode = r_pefragtopnode;
        }
Exemple #2
0
        /*
        ===========
        R_AddEfrags
        ===========
        */
        public static void R_AddEfrags(entity_t ent)
        {
            model.model_t entmodel;
            int i;

            if (ent.model == null)
                return;

            if (ent == client.cl_entities[0])
                return;		// never add the world

            r_addent = ent;

            lastlink = null;
            r_pefragtopnode = null;

            entmodel = ent.model;

            for (i = 0; i < 3; i++)
            {
                r_emins[i] = ent.origin[i] + entmodel.mins[i];
                r_emaxs[i] = ent.origin[i] + entmodel.maxs[i];
            }

            R_SplitEntityOnNode(client.cl.worldmodel.nodes[0]);

            ent.topnode = r_pefragtopnode;
        }
Exemple #3
0
        /*
         * =============================================================================
         *
         * DYNAMIC LIGHTS
         *
         * =============================================================================
         */

        /*
         * =============
         * R_MarkLights
         * =============
         */
        static void R_MarkLights(client.dlight_t light, int bit, model.node_or_leaf_t _node)
        {
            model.mplane_t splitplane;
            double         dist;

            model.msurface_t surf;
            int i;

            if (_node.contents < 0)
            {
                return;
            }

            model.mnode_t node = (model.mnode_t)_node;
            splitplane = node.plane;
            dist       = mathlib.DotProduct(light.origin, splitplane.normal) - splitplane.dist;

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

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

            R_MarkLights(light, bit, node.children[0]);
            R_MarkLights(light, bit, node.children[1]);
        }
Exemple #4
0
        /*
         * ===================
         * R_SplitEntityOnNode2
         * ===================
         */
        static void R_SplitEntityOnNode2(model.node_or_leaf_t node)
        {
            model.mplane_t splitplane;
            int            sides;

            if (node.visframe != r_visframecount)
            {
                return;
            }

            if (node.contents < 0)
            {
                if (node.contents != bspfile.CONTENTS_SOLID)
                {
                    r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
                }
                //  visible and not BSP clipped
                return;
            }

            model.mnode_t _node = (model.mnode_t)node;
            splitplane = _node.plane;
            sides      = mathlib.BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);

            if (sides == 3)
            {
                // remember first splitter
                r_pefragtopnode = node;
                return;
            }

            // not split yet; recurse down the contacted side
            if ((sides & 1) != 0)
            {
                R_SplitEntityOnNode2(_node.children[0]);
            }
            else
            {
                R_SplitEntityOnNode2(_node.children[1]);
            }
        }
Exemple #5
0
        /*
        ===================
        R_SplitEntityOnNode2
        ===================
        */
        static void R_SplitEntityOnNode2(model.node_or_leaf_t node)
        {
            model.mplane_t splitplane;
            int sides;

            if (node.visframe != r_visframecount)
                return;

            if (node.contents < 0)
            {
                if (node.contents != bspfile.CONTENTS_SOLID)
                    r_pefragtopnode = node; // we've reached a non-solid leaf, so it's
                //  visible and not BSP clipped
                return;
            }

            model.mnode_t _node = (model.mnode_t)node;
            splitplane = _node.plane;
            sides = mathlib.BOX_ON_PLANE_SIDE(r_emins, r_emaxs, splitplane);

            if (sides == 3)
            {
                // remember first splitter
                r_pefragtopnode = node;
                return;
            }

            // not split yet; recurse down the contacted side
            if ((sides & 1) != 0)
                R_SplitEntityOnNode2(_node.children[0]);
            else
                R_SplitEntityOnNode2(_node.children[1]);
        }
Exemple #6
0
        /*
        ===================
        R_SplitEntityOnNode
        ===================
        */
        static void R_SplitEntityOnNode(model.node_or_leaf_t node)
        {
            efrag_t         ef;
            model.mplane_t  splitplane;
            model.mleaf_t   leaf;
            int             sides;

            if (node.contents == bspfile.CONTENTS_SOLID)
            {
                return;
            }

            // add an efrag if the node is a leaf

            if (node.contents < 0)
            {
                if (r_pefragtopnode == null)
                    r_pefragtopnode = node;

                leaf = (model.mleaf_t)node;

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

                ef.entity = r_addent;

                // add the entity link
                if (lastlink == null)
                    r_addent.efrag = ef;
                else
                    lastlink.entnext = ef;
                lastlink = ef;
                ef.entnext = null;

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

                return;
            }

            // NODE_MIXED
            model.mnode_t _node = (model.mnode_t)node;
            splitplane = _node.plane;
            sides = mathlib.BOX_ON_PLANE_SIDE(r_emins, 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 = node;
            }

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

            if ((sides & 2) != 0)
                R_SplitEntityOnNode(_node.children[1]);
        }
Exemple #7
0
        /*
         * =============================================================================
         *
         * LIGHT SAMPLING
         *
         * =============================================================================
         */

        static int RecursiveLightPoint(model.node_or_leaf_t _node, double[] start, double[] end)
        {
            int    r;
            double front, back, frac;
            bool   side;

            model.mplane_t   plane;
            double[]         mid = new double[3];
            model.msurface_t surf;
            int s, t, ds, dt;
            int i;

            model.mtexinfo_t tex;
            int  lightmap;
            uint scale;
            int  maps;

            if (_node.contents < 0)
            {
                return(-1);                     // didn't hit anything
            }
            model.mnode_t node = (model.mnode_t)_node;
            // calculate mid point

            // FIXME: optimize for axial
            plane = node.plane;
            front = mathlib.DotProduct(start, plane.normal) - plane.dist;
            back  = mathlib.DotProduct(end, plane.normal) - plane.dist;
            side  = (front < 0);

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

            frac   = front / (front - back);
            mid[0] = start[0] + (end[0] - start[0]) * frac;
            mid[1] = start[1] + (end[1] - start[1]) * frac;
            mid[2] = start[2] + (end[2] - start[2]) * frac;

            // go down front side
            r = RecursiveLightPoint(node.children[side ? 1 : 0], start, mid);
            if (r >= 0)
            {
                return(r);                      // hit something
            }
            if ((back < 0) == side)
            {
                return(-1);                     // didn't hit anuthing
            }
            // check for impact on this node

            for (i = 0; i < node.numsurfaces; i++)
            {
                surf = client.cl.worldmodel.surfaces[node.firstsurface + i];
                if ((surf.flags & model.SURF_DRAWTILED) != 0)
                {
                    continue;                   // no lightmaps
                }
                tex = surf.texinfo;

                s = (int)(mathlib.DotProduct(mid, tex.vecs[0]) + tex.vecs[0][3]);
                t = (int)(mathlib.DotProduct(mid, tex.vecs[1]) + tex.vecs[1][3]);

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

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

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

                if (surf.samples == null)
                {
                    return(0);
                }

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

                lightmap = surf.samples.ofs;
                r        = 0;
                if (surf.samples != null)
                {
                    lightmap += dt * ((surf.extents[0] >> 4) + 1) + ds;

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

                    r >>= 8;
                }

                return(r);
            }

            // go down back side
            return(RecursiveLightPoint(node.children[!side ? 1 : 0], mid, end));
        }
Exemple #8
0
        /*
         * ================
         * R_RecursiveWorldNode
         * ================
         */
        static void R_RecursiveWorldNode(model.node_or_leaf_t node, int clipflags)
        {
            int i, c, side, pindex;

            double[]         acceptpt = new double[3], rejectpt = new double[3];
            model.mplane_t   plane;
            model.msurface_t surf, mark;
            model.mleaf_t    pleaf;
            double           d, dot;
            int surfofs;

            if (node.contents == bspfile.CONTENTS_SOLID)
            {
                return;                 // solid
            }
            if (node.visframe != r_visframecount)
            {
                return;
            }

            // cull the clipping planes if not trivial accept
            // FIXME: the compiler is doing a lousy job of optimizing here; it could be
            //  twice as fast in ASM
            if (clipflags != 0)
            {
                for (i = 0; i < 4; i++)
                {
                    if ((clipflags & (1 << i)) == 0)
                    {
                        continue;                       // don't need to clip against it
                    }
                    // generate accept and reject points
                    // FIXME: do with fast look-ups or integer tests based on the sign bit
                    // of the floating point values

                    pindex = pfrustum_indexes[i];

                    rejectpt[0] = (double)node.minmaxs[r_frustum_indexes[pindex + 0]];
                    rejectpt[1] = (double)node.minmaxs[r_frustum_indexes[pindex + 1]];
                    rejectpt[2] = (double)node.minmaxs[r_frustum_indexes[pindex + 2]];

                    d  = mathlib.DotProduct(rejectpt, view_clipplanes[i].normal);
                    d -= view_clipplanes[i].dist;

                    if (d <= 0)
                    {
                        return;
                    }

                    acceptpt[0] = (double)node.minmaxs[r_frustum_indexes[pindex + 3 + 0]];
                    acceptpt[1] = (double)node.minmaxs[r_frustum_indexes[pindex + 3 + 1]];
                    acceptpt[2] = (double)node.minmaxs[r_frustum_indexes[pindex + 3 + 2]];

                    d  = mathlib.DotProduct(acceptpt, view_clipplanes[i].normal);
                    d -= view_clipplanes[i].dist;

                    if (d >= 0)
                    {
                        clipflags &= ~(1 << i);                 // node is entirely on screen
                    }
                }
            }

            // if a leaf node, draw stuff
            if (node.contents < 0)
            {
                pleaf = (model.mleaf_t)node;

                helper.ObjectBuffer _mark = pleaf.firstmarksurface;
                int ofs = _mark.ofs;
                mark = (model.msurface_t)_mark.buffer[ofs];
                c    = pleaf.nummarksurfaces;

                if (c != 0)
                {
                    do
                    {
                        mark.visframe = r_framecount;
                        mark          = (model.msurface_t)_mark.buffer[++ofs];
                    } while (--c != 0);
                }

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

                pleaf.key = r_currentkey;
                r_currentkey++;                 // all bmodels in a leaf share the same key
            }
            else
            {
                model.mnode_t _node = (model.mnode_t)node;
                // node is just a decision point, so go down the apropriate sides

                // find which side of the node we are on
                plane = _node.plane;

                switch (plane.type)
                {
                case bspfile.PLANE_X:
                    dot = modelorg[0] - plane.dist;
                    break;

                case bspfile.PLANE_Y:
                    dot = modelorg[1] - plane.dist;
                    break;

                case bspfile.PLANE_Z:
                    dot = modelorg[2] - plane.dist;
                    break;

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

                if (dot >= 0)
                {
                    side = 0;
                }
                else
                {
                    side = 1;
                }

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

                // draw stuff
                c = _node.numsurfaces;

                if (c != 0)
                {
                    surf    = client.cl.worldmodel.surfaces[_node.firstsurface];
                    surfofs = _node.firstsurface;

                    if (dot < -BACKFACE_EPSILON)
                    {
                        do
                        {
                            if ((surf.flags & model.SURF_PLANEBACK) != 0 &&
                                (surf.visframe == r_framecount))
                            {
                                if (r_drawpolys)
                                {
                                    if (r_worldpolysbacktofront)
                                    {
                                        if (numbtofpolys < MAX_BTOFPOLYS)
                                        {
                                            pbtofpolys[numbtofpolys].clipflags =
                                                clipflags;
                                            pbtofpolys[numbtofpolys].psurf = surf;
                                            numbtofpolys++;
                                        }
                                    }
                                    else
                                    {
                                        R_RenderPoly(surf, clipflags);
                                    }
                                }
                                else
                                {
                                    R_RenderFace(surf, clipflags);
                                }
                            }

                            surf = client.cl.worldmodel.surfaces[++surfofs];
                        } while (--c != 0);
                    }
                    else if (dot > BACKFACE_EPSILON)
                    {
                        do
                        {
                            if ((surf.flags & model.SURF_PLANEBACK) == 0 &&
                                (surf.visframe == r_framecount))
                            {
                                if (r_drawpolys)
                                {
                                    if (r_worldpolysbacktofront)
                                    {
                                        if (numbtofpolys < MAX_BTOFPOLYS)
                                        {
                                            pbtofpolys[numbtofpolys].clipflags =
                                                clipflags;
                                            pbtofpolys[numbtofpolys].psurf = surf;
                                            numbtofpolys++;
                                        }
                                    }
                                    else
                                    {
                                        R_RenderPoly(surf, clipflags);
                                    }
                                }
                                else
                                {
                                    R_RenderFace(surf, clipflags);
                                }
                            }

                            surf = client.cl.worldmodel.surfaces[++surfofs];
                        } while (--c != 0);
                    }

                    // all surfaces on the same node share the same sequence number
                    r_currentkey++;
                }

                // recurse down the back side
                R_RecursiveWorldNode(_node.children[side == 0 ? 1 : 0], clipflags);
            }
        }
Exemple #9
0
        /*
         * ===================
         * R_SplitEntityOnNode
         * ===================
         */
        static void R_SplitEntityOnNode(model.node_or_leaf_t node)
        {
            efrag_t ef;

            model.mplane_t splitplane;
            model.mleaf_t  leaf;
            int            sides;

            if (node.contents == bspfile.CONTENTS_SOLID)
            {
                return;
            }

            // add an efrag if the node is a leaf

            if (node.contents < 0)
            {
                if (r_pefragtopnode == null)
                {
                    r_pefragtopnode = node;
                }

                leaf = (model.mleaf_t)node;

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

                ef.entity = r_addent;

                // add the entity link
                if (lastlink == null)
                {
                    r_addent.efrag = ef;
                }
                else
                {
                    lastlink.entnext = ef;
                }
                lastlink   = ef;
                ef.entnext = null;

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

                return;
            }

            // NODE_MIXED
            model.mnode_t _node = (model.mnode_t)node;
            splitplane = _node.plane;
            sides      = mathlib.BOX_ON_PLANE_SIDE(r_emins, 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 = node;
                }
            }

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

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