Ejemplo n.º 1
0
static inline void GL_DrawLeaf( mleaf_t *leaf ) {
    mface_t **face, **last;

    if( leaf->contents == CONTENTS_SOLID ) {
        return; // solid leaf
    }
    if( glr.fd.areabits && !Q_IsBitSet( glr.fd.areabits, leaf->area ) ) {
        return; // door blocks sight
    }

    last = leaf->firstleafface + leaf->numleaffaces;
    for( face = leaf->firstleafface; face < last; face++ ) {
        (*face)->drawframe = glr.drawframe;
    }

    c.leavesDrawn++;
}
Ejemplo n.º 2
0
/*
===============
SV_EdictIsVisible

Checks if edict is potentially visible from the given PVS row.
===============
*/
qboolean SV_EdictIsVisible(cm_t *cm, edict_t *ent, byte *mask)
{
    int i;

    if (ent->num_clusters == -1) {
        // too many leafs for individual check, go by headnode
        return CM_HeadnodeVisible(CM_NodeNum(cm, ent->headnode), mask);
    }

    // check individual leafs
    for (i = 0; i < ent->num_clusters; i++) {
        if (Q_IsBitSet(mask, ent->clusternums[i])) {
            return qtrue;
        }
    }

    return qfalse;  // not visible
}
Ejemplo n.º 3
0
Archivo: save.c Proyecto: jdolan/q2pro
void SV_AutoSaveBegin(mapcmd_t *cmd)
{
    byte        bitmap[MAX_CLIENTS / CHAR_BIT];
    edict_t     *ent;
    int         i;

    // check for clearing the current savegame
    if (cmd->endofunit) {
        wipe_save_dir(SAVE_CURRENT);
        return;
    }

    if (sv.state != ss_game)
        return;

    if (no_save_games())
        return;

    memset(bitmap, 0, sizeof(bitmap));

    // clear all the client inuse flags before saving so that
    // when the level is re-entered, the clients will spawn
    // at spawn points instead of occupying body shells
    for (i = 0; i < sv_maxclients->integer; i++) {
        ent = EDICT_NUM(i + 1);
        if (ent->inuse) {
            Q_SetBit(bitmap, i);
            ent->inuse = qfalse;
        }
    }

    // save the map just exited
    if (write_level_file())
        Com_EPrintf("Couldn't write level file.\n");

    // we must restore these for clients to transfer over correctly
    for (i = 0; i < sv_maxclients->integer; i++) {
        ent = EDICT_NUM(i + 1);
        ent->inuse = Q_IsBitSet(bitmap, i);
    }
}
Ejemplo n.º 4
0
Archivo: bsp.c Proyecto: Jenco420/q2pro
/*
================
R_RecursiveClipBPoly

Clip a bmodel poly down the world bsp tree
================
*/
static void R_RecursiveClipBPoly(bedge_t *pedges, mnode_t *pnode, mface_t *psurf)
{
    bedge_t     *psideedges[2], *pnextedge, *ptedge;
    int         i, side, lastside;
    float       dist, frac, lastdist;
    cplane_t    *splitplane, tplane;
    mvertex_t   *pvert, *plastvert, *ptvert;
    mnode_t     *pn;
    int         area;

    psideedges[0] = psideedges[1] = NULL;

    makeclippededge = qfalse;

// transform the BSP plane into model space
// FIXME: cache these?
    splitplane = pnode->plane;
    tplane.dist = -PlaneDiff(r_entorigin, splitplane);
    tplane.normal[0] = DotProduct(entity_rotation[0], splitplane->normal);
    tplane.normal[1] = DotProduct(entity_rotation[1], splitplane->normal);
    tplane.normal[2] = DotProduct(entity_rotation[2], splitplane->normal);

// clip edges to BSP plane
    for (; pedges; pedges = pnextedge) {
        pnextedge = pedges->pnext;

        // set the status for the last point as the previous point
        // FIXME: cache this stuff somehow?
        plastvert = pedges->v[0];
        lastdist = PlaneDiff(plastvert->point, &tplane);

        if (lastdist > 0)
            lastside = 0;
        else
            lastside = 1;

        pvert = pedges->v[1];
        dist = PlaneDiff(pvert->point, &tplane);

        if (dist > 0)
            side = 0;
        else
            side = 1;

        if (side != lastside) {
            // clipped
            if (numbverts >= MAX_BMODEL_VERTS)
                return;

            // generate the clipped vertex
            frac = lastdist / (lastdist - dist);
            ptvert = &pbverts[numbverts++];
            LerpVector(plastvert->point, pvert->point, frac, ptvert->point);

            // split into two edges, one on each side, and remember entering
            // and exiting points
            // FIXME: share the clip edge by having a winding direction flag?
            if (numbedges >= (MAX_BMODEL_EDGES - 1)) {
                Com_Printf("Out of edges for bmodel\n");
                return;
            }

            ptedge = &pbedges[numbedges];
            ptedge->pnext = psideedges[lastside];
            psideedges[lastside] = ptedge;
            ptedge->v[0] = plastvert;
            ptedge->v[1] = ptvert;

            ptedge = &pbedges[numbedges + 1];
            ptedge->pnext = psideedges[side];
            psideedges[side] = ptedge;
            ptedge->v[0] = ptvert;
            ptedge->v[1] = pvert;

            numbedges += 2;

            if (side == 0) {
                // entering for front, exiting for back
                pfrontenter = ptvert;
                makeclippededge = qtrue;
            } else {
                pfrontexit = ptvert;
                makeclippededge = qtrue;
            }
        } else {
            // add the edge to the appropriate side
            pedges->pnext = psideedges[side];
            psideedges[side] = pedges;
        }
    }

// if anything was clipped, reconstitute and add the edges along the clip
// plane to both sides (but in opposite directions)
    if (makeclippededge) {
        if (numbedges >= (MAX_BMODEL_EDGES - 2)) {
            Com_Error(ERR_DROP, "Out of edges for bmodel");
        }

        ptedge = &pbedges[numbedges];
        ptedge->pnext = psideedges[0];
        psideedges[0] = ptedge;
        ptedge->v[0] = pfrontexit;
        ptedge->v[1] = pfrontenter;

        ptedge = &pbedges[numbedges + 1];
        ptedge->pnext = psideedges[1];
        psideedges[1] = ptedge;
        ptedge->v[0] = pfrontenter;
        ptedge->v[1] = pfrontexit;

        numbedges += 2;
    }

// draw or recurse further
    for (i = 0; i < 2; i++) {
        if (psideedges[i]) {
            // draw if we've reached a non-solid leaf, done if all that's left is a
            // solid leaf, and continue down the tree if it's not a leaf
            pn = pnode->children[i];

            // we're done with this branch if the node or leaf isn't in the PVS
            if (pn->visframe == r_visframecount) {
                if (!pn->plane) {
                    mleaf_t *pl = (mleaf_t *)pn;
                    if (pl->contents != CONTENTS_SOLID) {
                        if (r_newrefdef.areabits) {
                            area = pl->area;
                            if (!Q_IsBitSet(r_newrefdef.areabits, area))
                                continue;       // not visible
                        }

                        r_currentbkey = pl->key;
                        R_RenderBmodelFace(psideedges[i], psurf);
                    }
                } else {
                    R_RecursiveClipBPoly(psideedges[i], pnode->children[i],
                                         psurf);
                }
            }
        }
    }
}
Ejemplo n.º 5
0
Archivo: bsp.c Proyecto: Jenco420/q2pro
/*
================
R_RecursiveWorldNode
================
*/
static void R_RecursiveWorldNode(mnode_t *node, int clipflags)
{
    int         i, c, side, *pindex;
    vec3_t      acceptpt, rejectpt;
    cplane_t    *plane;
    mface_t     *surf, **mark;
    float       d, dot;
    mleaf_t     *pleaf;

    while (node->visframe == r_visframecount) {
        // 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) {
            for (i = 0; i < 4; i++) {
                if (!(clipflags & (1 << i)))
                    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] = (float)node->minmaxs[pindex[0]];
                rejectpt[1] = (float)node->minmaxs[pindex[1]];
                rejectpt[2] = (float)node->minmaxs[pindex[2]];

                d = PlaneDiff(rejectpt, &view_clipplanes[i]);
                if (d <= 0)
                    return;

                acceptpt[0] = (float)node->minmaxs[pindex[3 + 0]];
                acceptpt[1] = (float)node->minmaxs[pindex[3 + 1]];
                acceptpt[2] = (float)node->minmaxs[pindex[3 + 2]];

                d = PlaneDiff(acceptpt, &view_clipplanes[i]);
                if (d >= 0)
                    clipflags &= ~(1 << i); // node is entirely on screen
            }
        }

        c_drawnode++;

        // if a leaf node, draw stuff
        if (!node->plane) {
            pleaf = (mleaf_t *)node;

            if (pleaf->contents == CONTENTS_SOLID)
                return;     // solid

            // check for door connected areas
            if (r_newrefdef.areabits) {
                if (! Q_IsBitSet(r_newrefdef.areabits, pleaf->area))
                    return;     // not visible
            }

            mark = pleaf->firstleafface;
            c = pleaf->numleaffaces;
            if (c) {
                do {
                    (*mark)->drawframe = r_framecount;
                    mark++;
                } while (--c);
            }

            pleaf->key = r_currentkey;
            r_currentkey++;     // all bmodels in a leaf share the same key
            return;
        }
        // node is just a decision point, so go down the apropriate sides

        // find which side of the node we are on
        plane = node->plane;

        dot = PlaneDiffFast(modelorg, plane);

        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->numfaces;
        if (c) {
            surf = node->firstface;
            if (dot < -BACKFACE_EPSILON) {
                do {
                    if ((surf->drawflags & DSURF_PLANEBACK) &&
                        (surf->drawframe == r_framecount)) {
                        R_RenderFace(surf, clipflags);
                    }
                    surf++;
                } while (--c);
            } else if (dot > BACKFACE_EPSILON) {
                do {
                    if (!(surf->drawflags & DSURF_PLANEBACK) &&
                        (surf->drawframe == r_framecount)) {
                        R_RenderFace(surf, clipflags);
                    }
                    surf++;
                } while (--c);
            }

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

        // recurse down the back side
        node = node->children[side ^ 1];
    }
}
Ejemplo n.º 6
0
/*
===================
Key_Event

Called by the system between frames for both key up and key down events
Should NOT be called during an interrupt!
===================
*/
void Key_Event(unsigned key, qboolean down, unsigned time)
{
    char    *kb;
    char    cmd[MAX_STRING_CHARS];

    if (key >= 256) {
        Com_Error(ERR_FATAL, "%s: bad key", __func__);
    }

    Com_DDDPrintf("%u: %c%s\n", time,
                  down ? '+' : '-', Key_KeynumToString(key));

    // hack for menu key binding
    if (key_wait_cb && down && !key_wait_cb(key_wait_arg, key)) {
        return;
    }

    // update key down and auto-repeat status
    if (down) {
        if (keydown[key] < 255)
            keydown[key]++;
    } else {
        keydown[key] = 0;
    }

    // console key is hardcoded, so the user can never unbind it
    if (!Key_IsDown(K_SHIFT) && (key == '`' || key == '~')) {
        if (keydown[key] == 1) {
            Con_ToggleConsole_f();
        }
        return;
    }

    // Alt+Enter is hardcoded for all systems
    if (Key_IsDown(K_ALT) && key == K_ENTER) {
        if (keydown[key] == 1) {
            VID_ToggleFullscreen();
        }
        return;
    }

    // menu key is hardcoded, so the user can never unbind it
    if (key == K_ESCAPE) {
        if (!down) {
            return;
        }

        if (cls.key_dest == KEY_GAME &&
            cl.frame.ps.stats[STAT_LAYOUTS] &&
            cls.demo.playback == qfalse) {
            if (keydown[key] == 2) {
                // force main menu if escape is held
                UI_OpenMenu(UIMENU_GAME);
            } else if (keydown[key] == 1) {
                // put away help computer / inventory
                CL_ClientCommand("putaway");
            }
            return;
        }

        // ignore autorepeats
        if (keydown[key] > 1) {
            return;
        }

        if (cls.key_dest & KEY_CONSOLE) {
            if (cls.state < ca_active && !(cls.key_dest & KEY_MENU)) {
                UI_OpenMenu(UIMENU_MAIN);
            } else {
                Con_Close(qtrue);
            }
        } else if (cls.key_dest & KEY_MENU) {
            UI_Keydown(key);
        } else if (cls.key_dest & KEY_MESSAGE) {
            Key_Message(key);
        } else if (cls.state == ca_active) {
            UI_OpenMenu(UIMENU_GAME);
        } else {
            UI_OpenMenu(UIMENU_MAIN);
        }
        return;
    }

    // track if any key is down for BUTTON_ANY
    if (down) {
        if (keydown[key] == 1)
            anykeydown++;
    } else {
        anykeydown--;
        if (anykeydown < 0)
            anykeydown = 0;
    }

    // hack for demo freelook in windowed mode
    if (cls.key_dest == KEY_GAME && cls.demo.playback && key == K_SHIFT && keydown[key] <= 1) {
        IN_Activate();
    }

//
// if not a consolekey, send to the interpreter no matter what mode is
//
    if ((cls.key_dest == KEY_GAME) ||
        ((cls.key_dest & KEY_CONSOLE) && !Q_IsBitSet(consolekeys, key)) ||
        ((cls.key_dest & KEY_MENU) && (key >= K_F1 && key <= K_F12)) ||
        (!down && Q_IsBitSet(buttondown, key))) {
//
// Key up events only generate commands if the game key binding is a button
// command (leading + sign). These will occur even in console mode, to keep the
// character from continuing an action started before a console switch. Button
// commands include the kenum as a parameter, so multiple downs can be matched
// with ups.
//
        if (!down) {
            kb = keybindings[key];
            if (kb && kb[0] == '+') {
                Q_snprintf(cmd, sizeof(cmd), "-%s %i %i\n",
                           kb + 1, key, time);
                Cbuf_AddText(&cmd_buffer, cmd);
            }
            Q_ClearBit(buttondown, key);
            return;
        }

        // ignore autorepeats
        if (keydown[key] > 1) {
            return;
        }

        // generate button up command when released
        Q_SetBit(buttondown, key);

        kb = keybindings[key];
        if (kb) {
            if (kb[0] == '+') {
                // button commands add keynum and time as a parm
                Q_snprintf(cmd, sizeof(cmd), "%s %i %i\n", kb, key, time);
                Cbuf_AddText(&cmd_buffer, cmd);
            } else {
                Cbuf_AddText(&cmd_buffer, kb);
                Cbuf_AddText(&cmd_buffer, "\n");
            }
        }
        return;
    }

    if (cls.key_dest == KEY_GAME)
        return;

    if (!down)
        return;     // other subsystems only care about key down events

    if (cls.key_dest & KEY_CONSOLE) {
        Key_Console(key);
    } else if (cls.key_dest & KEY_MENU) {
        UI_Keydown(key);
    } else if (cls.key_dest & KEY_MESSAGE) {
        Key_Message(key);
    }

    if (Key_IsDown(K_CTRL) || Key_IsDown(K_ALT)) {
        return;
    }

    switch (key) {
    case K_KP_SLASH:
        key = '/';
        break;
    case K_KP_MULTIPLY:
        key = '*';
        break;
    case K_KP_MINUS:
        key = '-';
        break;
    case K_KP_PLUS:
        key = '+';
        break;
    case K_KP_HOME:
        key = '7';
        break;
    case K_KP_UPARROW:
        key = '8';
        break;
    case K_KP_PGUP:
        key = '9';
        break;
    case K_KP_LEFTARROW:
        key = '4';
        break;
    case K_KP_5:
        key = '5';
        break;
    case K_KP_RIGHTARROW:
        key = '6';
        break;
    case K_KP_END:
        key = '1';
        break;
    case K_KP_DOWNARROW:
        key = '2';
        break;
    case K_KP_PGDN:
        key = '3';
        break;
    case K_KP_INS:
        key = '0';
        break;
    case K_KP_DEL:
        key = '.';
        break;
    }

    // if key is printable, generate char events
    if (key < 32 || key >= 127) {
        return;
    }

    if (Key_IsDown(K_SHIFT)) {
        key = keyshift[key];
    }

    if (cls.key_dest & KEY_CONSOLE) {
        Char_Console(key);
    } else if (cls.key_dest & KEY_MENU) {
        UI_CharEvent(key);
    } else if (cls.key_dest & KEY_MESSAGE) {
        Char_Message(key);
    }
}
Ejemplo n.º 7
0
static void GL_MarkLeaves( void ) {
    static int lastNodesVisible;
    byte vis1[VIS_MAX_BYTES];
    byte vis2[VIS_MAX_BYTES];
    mleaf_t *leaf;
    mnode_t *node;
    uint_fast32_t *src1, *src2;
    int cluster1, cluster2, longs;
    vec3_t tmp;
    int i;
    bsp_t *bsp = gl_static.world.cache;

    leaf = BSP_PointLeaf( bsp->nodes, glr.fd.vieworg );
    cluster1 = cluster2 = leaf->cluster;
    VectorCopy( glr.fd.vieworg, tmp );
    if( !leaf->contents ) {
        tmp[2] -= 16;   
    } else {
        tmp[2] += 16;   
    }   
    leaf = BSP_PointLeaf( bsp->nodes, tmp );
    if( !( leaf->contents & CONTENTS_SOLID ) ) {
        cluster2 = leaf->cluster;
    }
    
    if( cluster1 == glr.viewcluster1 && cluster2 == glr.viewcluster2 ) {
        goto finish;
    }
        
    if( gl_lockpvs->integer ) {
        goto finish;
    }

    glr.visframe++;
    glr.viewcluster1 = cluster1;
    glr.viewcluster2 = cluster2;

    if( !bsp->vis || gl_novis->integer || cluster1 == -1 ) {
        // mark everything visible
        for( i = 0; i < bsp->numnodes; i++ ) {
            bsp->nodes[i].visframe = glr.visframe;
        }
        for( i = 0; i < bsp->numleafs; i++ ) {
            bsp->leafs[i].visframe = glr.visframe;
        }
        lastNodesVisible = bsp->numnodes;
        goto finish;
    }

    BSP_ClusterVis( bsp, vis1, cluster1, DVIS_PVS );
    if( cluster1 != cluster2 ) {
        BSP_ClusterVis( bsp, vis2, cluster2, DVIS_PVS );
        longs = VIS_FAST_LONGS( bsp );
        src1 = ( uint_fast32_t * )vis1;
        src2 = ( uint_fast32_t * )vis2;
        while( longs-- ) {
            *src1++ |= *src2++;
        }
    }

    lastNodesVisible = 0;
    for( i = 0, leaf = bsp->leafs; i < bsp->numleafs; i++, leaf++ ) {
        cluster1 = leaf->cluster;
        if( cluster1 == -1 ) {
            continue;
        }
        if( Q_IsBitSet( vis1, cluster1 ) ) {
            node = ( mnode_t * )leaf;

            // mark parent nodes visible
            do {
                if( node->visframe == glr.visframe ) {
                    break;
                }
                node->visframe = glr.visframe;
                node = node->parent;
                lastNodesVisible++;
            } while( node );
        }
    }
    
finish:
    c.nodesVisible = lastNodesVisible;

}