Annotation of quakeworld/client/r_draw.c, revision 1.1.1.1

1.1       root        1: /*
                      2: Copyright (C) 1996-1997 Id Software, Inc.
                      3: 
                      4: This program is free software; you can redistribute it and/or
                      5: modify it under the terms of the GNU General Public License
                      6: as published by the Free Software Foundation; either version 2
                      7: of the License, or (at your option) any later version.
                      8: 
                      9: This program is distributed in the hope that it will be useful,
                     10: but WITHOUT ANY WARRANTY; without even the implied warranty of
                     11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
                     12: 
                     13: See the GNU General Public License for more details.
                     14: 
                     15: You should have received a copy of the GNU General Public License
                     16: along with this program; if not, write to the Free Software
                     17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
                     18: 
                     19: */
                     20: 
                     21: // r_draw.c
                     22: 
                     23: #include "quakedef.h"
                     24: #include "r_local.h"
                     25: #include "d_local.h"   // FIXME: shouldn't need to include this
                     26: 
                     27: #define MAXLEFTCLIPEDGES               100
                     28: 
                     29: // !!! if these are changed, they must be changed in asm_draw.h too !!!
                     30: #define FULLY_CLIPPED_CACHED   0x80000000
                     31: #define FRAMECOUNT_MASK                        0x7FFFFFFF
                     32: 
                     33: unsigned int   cacheoffset;
                     34: 
                     35: int                    c_faceclip;                                     // number of faces clipped
                     36: 
                     37: zpointdesc_t   r_zpointdesc;
                     38: 
                     39: polydesc_t             r_polydesc;
                     40: 
                     41: 
                     42: 
                     43: clipplane_t    *entity_clipplanes;
                     44: clipplane_t    view_clipplanes[4];
                     45: clipplane_t    world_clipplanes[16];
                     46: 
                     47: medge_t                        *r_pedge;
                     48: 
                     49: qboolean               r_leftclipped, r_rightclipped;
                     50: static qboolean        makeleftedge, makerightedge;
                     51: qboolean               r_nearzionly;
                     52: 
                     53: int            sintable[1280];
                     54: int            intsintable[1280];
                     55: 
                     56: mvertex_t      r_leftenter, r_leftexit;
                     57: mvertex_t      r_rightenter, r_rightexit;
                     58: 
                     59: typedef struct
                     60: {
                     61:        float   u,v;
                     62:        int             ceilv;
                     63: } evert_t;
                     64: 
                     65: int                            r_emitted;
                     66: float                  r_nearzi;
                     67: float                  r_u1, r_v1, r_lzi1;
                     68: int                            r_ceilv1;
                     69: 
                     70: qboolean       r_lastvertvalid;
                     71: 
                     72: 
                     73: #if    !id386
                     74: 
                     75: /*
                     76: ================
                     77: R_EmitEdge
                     78: ================
                     79: */
                     80: void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1)
                     81: {
                     82:        edge_t  *edge, *pcheck;
                     83:        int             u_check;
                     84:        float   u, u_step;
                     85:        vec3_t  local, transformed;
                     86:        float   *world;
                     87:        int             v, v2, ceilv0;
                     88:        float   scale, lzi0, u0, v0;
                     89:        int             side;
                     90: 
                     91:        if (r_lastvertvalid)
                     92:        {
                     93:                u0 = r_u1;
                     94:                v0 = r_v1;
                     95:                lzi0 = r_lzi1;
                     96:                ceilv0 = r_ceilv1;
                     97:        }
                     98:        else
                     99:        {
                    100:                world = &pv0->position[0];
                    101:        
                    102:        // transform and project
                    103:                VectorSubtract (world, modelorg, local);
                    104:                TransformVector (local, transformed);
                    105:        
                    106:                if (transformed[2] < NEAR_CLIP)
                    107:                        transformed[2] = NEAR_CLIP;
                    108:        
                    109:                lzi0 = 1.0 / transformed[2];
                    110:        
                    111:        // FIXME: build x/yscale into transform?
                    112:                scale = xscale * lzi0;
                    113:                u0 = (xcenter + scale*transformed[0]);
                    114:                if (u0 < r_refdef.fvrectx_adj)
                    115:                        u0 = r_refdef.fvrectx_adj;
                    116:                if (u0 > r_refdef.fvrectright_adj)
                    117:                        u0 = r_refdef.fvrectright_adj;
                    118:        
                    119:                scale = yscale * lzi0;
                    120:                v0 = (ycenter - scale*transformed[1]);
                    121:                if (v0 < r_refdef.fvrecty_adj)
                    122:                        v0 = r_refdef.fvrecty_adj;
                    123:                if (v0 > r_refdef.fvrectbottom_adj)
                    124:                        v0 = r_refdef.fvrectbottom_adj;
                    125:        
                    126:                ceilv0 = (int) ceil(v0);
                    127:        }
                    128: 
                    129:        world = &pv1->position[0];
                    130: 
                    131: // transform and project
                    132:        VectorSubtract (world, modelorg, local);
                    133:        TransformVector (local, transformed);
                    134: 
                    135:        if (transformed[2] < NEAR_CLIP)
                    136:                transformed[2] = NEAR_CLIP;
                    137: 
                    138:        r_lzi1 = 1.0 / transformed[2];
                    139: 
                    140:        scale = xscale * r_lzi1;
                    141:        r_u1 = (xcenter + scale*transformed[0]);
                    142:        if (r_u1 < r_refdef.fvrectx_adj)
                    143:                r_u1 = r_refdef.fvrectx_adj;
                    144:        if (r_u1 > r_refdef.fvrectright_adj)
                    145:                r_u1 = r_refdef.fvrectright_adj;
                    146: 
                    147:        scale = yscale * r_lzi1;
                    148:        r_v1 = (ycenter - scale*transformed[1]);
                    149:        if (r_v1 < r_refdef.fvrecty_adj)
                    150:                r_v1 = r_refdef.fvrecty_adj;
                    151:        if (r_v1 > r_refdef.fvrectbottom_adj)
                    152:                r_v1 = r_refdef.fvrectbottom_adj;
                    153: 
                    154:        if (r_lzi1 > lzi0)
                    155:                lzi0 = r_lzi1;
                    156: 
                    157:        if (lzi0 > r_nearzi)    // for mipmap finding
                    158:                r_nearzi = lzi0;
                    159: 
                    160: // for right edges, all we want is the effect on 1/z
                    161:        if (r_nearzionly)
                    162:                return;
                    163: 
                    164:        r_emitted = 1;
                    165: 
                    166:        r_ceilv1 = (int) ceil(r_v1);
                    167: 
                    168: 
                    169: // create the edge
                    170:        if (ceilv0 == r_ceilv1)
                    171:        {
                    172:        // we cache unclipped horizontal edges as fully clipped
                    173:                if (cacheoffset != 0x7FFFFFFF)
                    174:                {
                    175:                        cacheoffset = FULLY_CLIPPED_CACHED |
                    176:                                        (r_framecount & FRAMECOUNT_MASK);
                    177:                }
                    178: 
                    179:                return;         // horizontal edge
                    180:        }
                    181: 
                    182:        side = ceilv0 > r_ceilv1;
                    183: 
                    184:        edge = edge_p++;
                    185: 
                    186:        edge->owner = r_pedge;
                    187: 
                    188:        edge->nearzi = lzi0;
                    189: 
                    190:        if (side == 0)
                    191:        {
                    192:        // trailing edge (go from p1 to p2)
                    193:                v = ceilv0;
                    194:                v2 = r_ceilv1 - 1;
                    195: 
                    196:                edge->surfs[0] = surface_p - surfaces;
                    197:                edge->surfs[1] = 0;
                    198: 
                    199:                u_step = ((r_u1 - u0) / (r_v1 - v0));
                    200:                u = u0 + ((float)v - v0) * u_step;
                    201:        }
                    202:        else
                    203:        {
                    204:        // leading edge (go from p2 to p1)
                    205:                v2 = ceilv0 - 1;
                    206:                v = r_ceilv1;
                    207: 
                    208:                edge->surfs[0] = 0;
                    209:                edge->surfs[1] = surface_p - surfaces;
                    210: 
                    211:                u_step = ((u0 - r_u1) / (v0 - r_v1));
                    212:                u = r_u1 + ((float)v - r_v1) * u_step;
                    213:        }
                    214: 
                    215:        edge->u_step = u_step*0x100000;
                    216:        edge->u = u*0x100000 + 0xFFFFF;
                    217: 
                    218: // we need to do this to avoid stepping off the edges if a very nearly
                    219: // horizontal edge is less than epsilon above a scan, and numeric error causes
                    220: // it to incorrectly extend to the scan, and the extension of the line goes off
                    221: // the edge of the screen
                    222: // FIXME: is this actually needed?
                    223:        if (edge->u < r_refdef.vrect_x_adj_shift20)
                    224:                edge->u = r_refdef.vrect_x_adj_shift20;
                    225:        if (edge->u > r_refdef.vrectright_adj_shift20)
                    226:                edge->u = r_refdef.vrectright_adj_shift20;
                    227: 
                    228: //
                    229: // sort the edge in normally
                    230: //
                    231:        u_check = edge->u;
                    232:        if (edge->surfs[0])
                    233:                u_check++;      // sort trailers after leaders
                    234: 
                    235:        if (!newedges[v] || newedges[v]->u >= u_check)
                    236:        {
                    237:                edge->next = newedges[v];
                    238:                newedges[v] = edge;
                    239:        }
                    240:        else
                    241:        {
                    242:                pcheck = newedges[v];
                    243:                while (pcheck->next && pcheck->next->u < u_check)
                    244:                        pcheck = pcheck->next;
                    245:                edge->next = pcheck->next;
                    246:                pcheck->next = edge;
                    247:        }
                    248: 
                    249:        edge->nextremove = removeedges[v2];
                    250:        removeedges[v2] = edge;
                    251: }
                    252: 
                    253: 
                    254: /*
                    255: ================
                    256: R_ClipEdge
                    257: ================
                    258: */
                    259: void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip)
                    260: {
                    261:        float           d0, d1, f;
                    262:        mvertex_t       clipvert;
                    263: 
                    264:        if (clip)
                    265:        {
                    266:                do
                    267:                {
                    268:                        d0 = DotProduct (pv0->position, clip->normal) - clip->dist;
                    269:                        d1 = DotProduct (pv1->position, clip->normal) - clip->dist;
                    270: 
                    271:                        if (d0 >= 0)
                    272:                        {
                    273:                        // point 0 is unclipped
                    274:                                if (d1 >= 0)
                    275:                                {
                    276:                                // both points are unclipped
                    277:                                        continue;
                    278:                                }
                    279: 
                    280:                        // only point 1 is clipped
                    281: 
                    282:                        // we don't cache clipped edges
                    283:                                cacheoffset = 0x7FFFFFFF;
                    284: 
                    285:                                f = d0 / (d0 - d1);
                    286:                                clipvert.position[0] = pv0->position[0] +
                    287:                                                f * (pv1->position[0] - pv0->position[0]);
                    288:                                clipvert.position[1] = pv0->position[1] +
                    289:                                                f * (pv1->position[1] - pv0->position[1]);
                    290:                                clipvert.position[2] = pv0->position[2] +
                    291:                                                f * (pv1->position[2] - pv0->position[2]);
                    292: 
                    293:                                if (clip->leftedge)
                    294:                                {
                    295:                                        r_leftclipped = true;
                    296:                                        r_leftexit = clipvert;
                    297:                                }
                    298:                                else if (clip->rightedge)
                    299:                                {
                    300:                                        r_rightclipped = true;
                    301:                                        r_rightexit = clipvert;
                    302:                                }
                    303: 
                    304:                                R_ClipEdge (pv0, &clipvert, clip->next);
                    305:                                return;
                    306:                        }
                    307:                        else
                    308:                        {
                    309:                        // point 0 is clipped
                    310:                                if (d1 < 0)
                    311:                                {
                    312:                                // both points are clipped
                    313:                                // we do cache fully clipped edges
                    314:                                        if (!r_leftclipped)
                    315:                                                cacheoffset = FULLY_CLIPPED_CACHED |
                    316:                                                                (r_framecount & FRAMECOUNT_MASK);
                    317:                                        return;
                    318:                                }
                    319: 
                    320:                        // only point 0 is clipped
                    321:                                r_lastvertvalid = false;
                    322: 
                    323:                        // we don't cache partially clipped edges
                    324:                                cacheoffset = 0x7FFFFFFF;
                    325: 
                    326:                                f = d0 / (d0 - d1);
                    327:                                clipvert.position[0] = pv0->position[0] +
                    328:                                                f * (pv1->position[0] - pv0->position[0]);
                    329:                                clipvert.position[1] = pv0->position[1] +
                    330:                                                f * (pv1->position[1] - pv0->position[1]);
                    331:                                clipvert.position[2] = pv0->position[2] +
                    332:                                                f * (pv1->position[2] - pv0->position[2]);
                    333: 
                    334:                                if (clip->leftedge)
                    335:                                {
                    336:                                        r_leftclipped = true;
                    337:                                        r_leftenter = clipvert;
                    338:                                }
                    339:                                else if (clip->rightedge)
                    340:                                {
                    341:                                        r_rightclipped = true;
                    342:                                        r_rightenter = clipvert;
                    343:                                }
                    344: 
                    345:                                R_ClipEdge (&clipvert, pv1, clip->next);
                    346:                                return;
                    347:                        }
                    348:                } while ((clip = clip->next) != NULL);
                    349:        }
                    350: 
                    351: // add the edge
                    352:        R_EmitEdge (pv0, pv1);
                    353: }
                    354: 
                    355: #endif // !id386
                    356: 
                    357: 
                    358: /*
                    359: ================
                    360: R_EmitCachedEdge
                    361: ================
                    362: */
                    363: void R_EmitCachedEdge (void)
                    364: {
                    365:        edge_t          *pedge_t;
                    366: 
                    367:        pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset);
                    368: 
                    369:        if (!pedge_t->surfs[0])
                    370:                pedge_t->surfs[0] = surface_p - surfaces;
                    371:        else
                    372:                pedge_t->surfs[1] = surface_p - surfaces;
                    373: 
                    374:        if (pedge_t->nearzi > r_nearzi) // for mipmap finding
                    375:                r_nearzi = pedge_t->nearzi;
                    376: 
                    377:        r_emitted = 1;
                    378: }
                    379: 
                    380: 
                    381: /*
                    382: ================
                    383: R_RenderFace
                    384: ================
                    385: */
                    386: void R_RenderFace (msurface_t *fa, int clipflags)
                    387: {
                    388:        int                     i, lindex;
                    389:        unsigned        mask;
                    390:        mplane_t        *pplane;
                    391:        float           distinv;
                    392:        vec3_t          p_normal;
                    393:        medge_t         *pedges, tedge;
                    394:        clipplane_t     *pclip;
                    395: 
                    396: // skip out if no more surfs
                    397:        if ((surface_p) >= surf_max)
                    398:        {
                    399:                r_outofsurfaces++;
                    400:                return;
                    401:        }
                    402: 
                    403: // ditto if not enough edges left, or switch to auxedges if possible
                    404:        if ((edge_p + fa->numedges + 4) >= edge_max)
                    405:        {
                    406:                r_outofedges += fa->numedges;
                    407:                return;
                    408:        }
                    409: 
                    410:        c_faceclip++;
                    411: 
                    412: // set up clip planes
                    413:        pclip = NULL;
                    414: 
                    415:        for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
                    416:        {
                    417:                if (clipflags & mask)
                    418:                {
                    419:                        view_clipplanes[i].next = pclip;
                    420:                        pclip = &view_clipplanes[i];
                    421:                }
                    422:        }
                    423: 
                    424: // push the edges through
                    425:        r_emitted = 0;
                    426:        r_nearzi = 0;
                    427:        r_nearzionly = false;
                    428:        makeleftedge = makerightedge = false;
                    429:        pedges = currententity->model->edges;
                    430:        r_lastvertvalid = false;
                    431: 
                    432:        for (i=0 ; i<fa->numedges ; i++)
                    433:        {
                    434:                lindex = currententity->model->surfedges[fa->firstedge + i];
                    435: 
                    436:                if (lindex > 0)
                    437:                {
                    438:                        r_pedge = &pedges[lindex];
                    439: 
                    440:                // if the edge is cached, we can just reuse the edge
                    441:                        if (!insubmodel)
                    442:                        {
                    443:                                if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
                    444:                                {
                    445:                                        if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
                    446:                                                r_framecount)
                    447:                                        {
                    448:                                                r_lastvertvalid = false;
                    449:                                                continue;
                    450:                                        }
                    451:                                }
                    452:                                else
                    453:                                {
                    454:                                        if ((((unsigned long)edge_p - (unsigned long)r_edges) >
                    455:                                                 r_pedge->cachededgeoffset) &&
                    456:                                                (((edge_t *)((unsigned long)r_edges +
                    457:                                                 r_pedge->cachededgeoffset))->owner == r_pedge))
                    458:                                        {
                    459:                                                R_EmitCachedEdge ();
                    460:                                                r_lastvertvalid = false;
                    461:                                                continue;
                    462:                                        }
                    463:                                }
                    464:                        }
                    465: 
                    466:                // assume it's cacheable
                    467:                        cacheoffset = (byte *)edge_p - (byte *)r_edges;
                    468:                        r_leftclipped = r_rightclipped = false;
                    469:                        R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]],
                    470:                                                &r_pcurrentvertbase[r_pedge->v[1]],
                    471:                                                pclip);
                    472:                        r_pedge->cachededgeoffset = cacheoffset;
                    473: 
                    474:                        if (r_leftclipped)
                    475:                                makeleftedge = true;
                    476:                        if (r_rightclipped)
                    477:                                makerightedge = true;
                    478:                        r_lastvertvalid = true;
                    479:                }
                    480:                else
                    481:                {
                    482:                        lindex = -lindex;
                    483:                        r_pedge = &pedges[lindex];
                    484:                // if the edge is cached, we can just reuse the edge
                    485:                        if (!insubmodel)
                    486:                        {
                    487:                                if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED)
                    488:                                {
                    489:                                        if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) ==
                    490:                                                r_framecount)
                    491:                                        {
                    492:                                                r_lastvertvalid = false;
                    493:                                                continue;
                    494:                                        }
                    495:                                }
                    496:                                else
                    497:                                {
                    498:                                // it's cached if the cached edge is valid and is owned
                    499:                                // by this medge_t
                    500:                                        if ((((unsigned long)edge_p - (unsigned long)r_edges) >
                    501:                                                 r_pedge->cachededgeoffset) &&
                    502:                                                (((edge_t *)((unsigned long)r_edges +
                    503:                                                 r_pedge->cachededgeoffset))->owner == r_pedge))
                    504:                                        {
                    505:                                                R_EmitCachedEdge ();
                    506:                                                r_lastvertvalid = false;
                    507:                                                continue;
                    508:                                        }
                    509:                                }
                    510:                        }
                    511: 
                    512:                // assume it's cacheable
                    513:                        cacheoffset = (byte *)edge_p - (byte *)r_edges;
                    514:                        r_leftclipped = r_rightclipped = false;
                    515:                        R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]],
                    516:                                                &r_pcurrentvertbase[r_pedge->v[0]],
                    517:                                                pclip);
                    518:                        r_pedge->cachededgeoffset = cacheoffset;
                    519: 
                    520:                        if (r_leftclipped)
                    521:                                makeleftedge = true;
                    522:                        if (r_rightclipped)
                    523:                                makerightedge = true;
                    524:                        r_lastvertvalid = true;
                    525:                }
                    526:        }
                    527: 
                    528: // if there was a clip off the left edge, add that edge too
                    529: // FIXME: faster to do in screen space?
                    530: // FIXME: share clipped edges?
                    531:        if (makeleftedge)
                    532:        {
                    533:                r_pedge = &tedge;
                    534:                r_lastvertvalid = false;
                    535:                R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
                    536:        }
                    537: 
                    538: // if there was a clip off the right edge, get the right r_nearzi
                    539:        if (makerightedge)
                    540:        {
                    541:                r_pedge = &tedge;
                    542:                r_lastvertvalid = false;
                    543:                r_nearzionly = true;
                    544:                R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
                    545:        }
                    546: 
                    547: // if no edges made it out, return without posting the surface
                    548:        if (!r_emitted)
                    549:                return;
                    550: 
                    551:        r_polycount++;
                    552: 
                    553:        surface_p->data = (void *)fa;
                    554:        surface_p->nearzi = r_nearzi;
                    555:        surface_p->flags = fa->flags;
                    556:        surface_p->insubmodel = insubmodel;
                    557:        surface_p->spanstate = 0;
                    558:        surface_p->entity = currententity;
                    559:        surface_p->key = r_currentkey++;
                    560:        surface_p->spans = NULL;
                    561: 
                    562:        pplane = fa->plane;
                    563: // FIXME: cache this?
                    564:        TransformVector (pplane->normal, p_normal);
                    565: // FIXME: cache this?
                    566:        distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
                    567: 
                    568:        surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
                    569:        surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
                    570:        surface_p->d_ziorigin = p_normal[2] * distinv -
                    571:                        xcenter * surface_p->d_zistepu -
                    572:                        ycenter * surface_p->d_zistepv;
                    573: 
                    574: //JDC  VectorCopy (r_worldmodelorg, surface_p->modelorg);
                    575:        surface_p++;
                    576: }
                    577: 
                    578: 
                    579: /*
                    580: ================
                    581: R_RenderBmodelFace
                    582: ================
                    583: */
                    584: void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf)
                    585: {
                    586:        int                     i;
                    587:        unsigned        mask;
                    588:        mplane_t        *pplane;
                    589:        float           distinv;
                    590:        vec3_t          p_normal;
                    591:        medge_t         tedge;
                    592:        clipplane_t     *pclip;
                    593: 
                    594: // skip out if no more surfs
                    595:        if (surface_p >= surf_max)
                    596:        {
                    597:                r_outofsurfaces++;
                    598:                return;
                    599:        }
                    600: 
                    601: // ditto if not enough edges left, or switch to auxedges if possible
                    602:        if ((edge_p + psurf->numedges + 4) >= edge_max)
                    603:        {
                    604:                r_outofedges += psurf->numedges;
                    605:                return;
                    606:        }
                    607: 
                    608:        c_faceclip++;
                    609: 
                    610: // this is a dummy to give the caching mechanism someplace to write to
                    611:        r_pedge = &tedge;
                    612: 
                    613: // set up clip planes
                    614:        pclip = NULL;
                    615: 
                    616:        for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
                    617:        {
                    618:                if (r_clipflags & mask)
                    619:                {
                    620:                        view_clipplanes[i].next = pclip;
                    621:                        pclip = &view_clipplanes[i];
                    622:                }
                    623:        }
                    624: 
                    625: // push the edges through
                    626:        r_emitted = 0;
                    627:        r_nearzi = 0;
                    628:        r_nearzionly = false;
                    629:        makeleftedge = makerightedge = false;
                    630: // FIXME: keep clipped bmodel edges in clockwise order so last vertex caching
                    631: // can be used?
                    632:        r_lastvertvalid = false;
                    633: 
                    634:        for ( ; pedges ; pedges = pedges->pnext)
                    635:        {
                    636:                r_leftclipped = r_rightclipped = false;
                    637:                R_ClipEdge (pedges->v[0], pedges->v[1], pclip);
                    638: 
                    639:                if (r_leftclipped)
                    640:                        makeleftedge = true;
                    641:                if (r_rightclipped)
                    642:                        makerightedge = true;
                    643:        }
                    644: 
                    645: // if there was a clip off the left edge, add that edge too
                    646: // FIXME: faster to do in screen space?
                    647: // FIXME: share clipped edges?
                    648:        if (makeleftedge)
                    649:        {
                    650:                r_pedge = &tedge;
                    651:                R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next);
                    652:        }
                    653: 
                    654: // if there was a clip off the right edge, get the right r_nearzi
                    655:        if (makerightedge)
                    656:        {
                    657:                r_pedge = &tedge;
                    658:                r_nearzionly = true;
                    659:                R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next);
                    660:        }
                    661: 
                    662: // if no edges made it out, return without posting the surface
                    663:        if (!r_emitted)
                    664:                return;
                    665: 
                    666:        r_polycount++;
                    667: 
                    668:        surface_p->data = (void *)psurf;
                    669:        surface_p->nearzi = r_nearzi;
                    670:        surface_p->flags = psurf->flags;
                    671:        surface_p->insubmodel = true;
                    672:        surface_p->spanstate = 0;
                    673:        surface_p->entity = currententity;
                    674:        surface_p->key = r_currentbkey;
                    675:        surface_p->spans = NULL;
                    676: 
                    677:        pplane = psurf->plane;
                    678: // FIXME: cache this?
                    679:        TransformVector (pplane->normal, p_normal);
                    680: // FIXME: cache this?
                    681:        distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal));
                    682: 
                    683:        surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv;
                    684:        surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv;
                    685:        surface_p->d_ziorigin = p_normal[2] * distinv -
                    686:                        xcenter * surface_p->d_zistepu -
                    687:                        ycenter * surface_p->d_zistepv;
                    688: 
                    689: //JDC  VectorCopy (r_worldmodelorg, surface_p->modelorg);
                    690:        surface_p++;
                    691: }
                    692: 
                    693: 
                    694: /*
                    695: ================
                    696: R_RenderPoly
                    697: ================
                    698: */
                    699: void R_RenderPoly (msurface_t *fa, int clipflags)
                    700: {
                    701:        int                     i, lindex, lnumverts, s_axis, t_axis;
                    702:        float           dist, lastdist, lzi, scale, u, v, frac;
                    703:        unsigned        mask;
                    704:        vec3_t          local, transformed;
                    705:        clipplane_t     *pclip;
                    706:        medge_t         *pedges;
                    707:        mplane_t        *pplane;
                    708:        mvertex_t       verts[2][100];  //FIXME: do real number
                    709:        polyvert_t      pverts[100];    //FIXME: do real number, safely
                    710:        int                     vertpage, newverts, newpage, lastvert;
                    711:        qboolean        visible;
                    712: 
                    713: // FIXME: clean this up and make it faster
                    714: // FIXME: guard against running out of vertices
                    715: 
                    716:        s_axis = t_axis = 0;    // keep compiler happy
                    717: 
                    718: // set up clip planes
                    719:        pclip = NULL;
                    720: 
                    721:        for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1)
                    722:        {
                    723:                if (clipflags & mask)
                    724:                {
                    725:                        view_clipplanes[i].next = pclip;
                    726:                        pclip = &view_clipplanes[i];
                    727:                }
                    728:        }
                    729: 
                    730: // reconstruct the polygon
                    731: // FIXME: these should be precalculated and loaded off disk
                    732:        pedges = currententity->model->edges;
                    733:        lnumverts = fa->numedges;
                    734:        vertpage = 0;
                    735: 
                    736:        for (i=0 ; i<lnumverts ; i++)
                    737:        {
                    738:                lindex = currententity->model->surfedges[fa->firstedge + i];
                    739: 
                    740:                if (lindex > 0)
                    741:                {
                    742:                        r_pedge = &pedges[lindex];
                    743:                        verts[0][i] = r_pcurrentvertbase[r_pedge->v[0]];
                    744:                }
                    745:                else
                    746:                {
                    747:                        r_pedge = &pedges[-lindex];
                    748:                        verts[0][i] = r_pcurrentvertbase[r_pedge->v[1]];
                    749:                }
                    750:        }
                    751: 
                    752: // clip the polygon, done if not visible
                    753:        while (pclip)
                    754:        {
                    755:                lastvert = lnumverts - 1;
                    756:                lastdist = DotProduct (verts[vertpage][lastvert].position,
                    757:                                                           pclip->normal) - pclip->dist;
                    758: 
                    759:                visible = false;
                    760:                newverts = 0;
                    761:                newpage = vertpage ^ 1;
                    762: 
                    763:                for (i=0 ; i<lnumverts ; i++)
                    764:                {
                    765:                        dist = DotProduct (verts[vertpage][i].position, pclip->normal) -
                    766:                                        pclip->dist;
                    767: 
                    768:                        if ((lastdist > 0) != (dist > 0))
                    769:                        {
                    770:                                frac = dist / (dist - lastdist);
                    771:                                verts[newpage][newverts].position[0] =
                    772:                                                verts[vertpage][i].position[0] +
                    773:                                                ((verts[vertpage][lastvert].position[0] -
                    774:                                                  verts[vertpage][i].position[0]) * frac);
                    775:                                verts[newpage][newverts].position[1] =
                    776:                                                verts[vertpage][i].position[1] +
                    777:                                                ((verts[vertpage][lastvert].position[1] -
                    778:                                                  verts[vertpage][i].position[1]) * frac);
                    779:                                verts[newpage][newverts].position[2] =
                    780:                                                verts[vertpage][i].position[2] +
                    781:                                                ((verts[vertpage][lastvert].position[2] -
                    782:                                                  verts[vertpage][i].position[2]) * frac);
                    783:                                newverts++;
                    784:                        }
                    785: 
                    786:                        if (dist >= 0)
                    787:                        {
                    788:                                verts[newpage][newverts] = verts[vertpage][i];
                    789:                                newverts++;
                    790:                                visible = true;
                    791:                        }
                    792: 
                    793:                        lastvert = i;
                    794:                        lastdist = dist;
                    795:                }
                    796: 
                    797:                if (!visible || (newverts < 3))
                    798:                        return;
                    799: 
                    800:                lnumverts = newverts;
                    801:                vertpage ^= 1;
                    802:                pclip = pclip->next;
                    803:        }
                    804: 
                    805: // transform and project, remembering the z values at the vertices and
                    806: // r_nearzi, and extract the s and t coordinates at the vertices
                    807:        pplane = fa->plane;
                    808:        switch (pplane->type)
                    809:        {
                    810:        case PLANE_X:
                    811:        case PLANE_ANYX:
                    812:                s_axis = 1;
                    813:                t_axis = 2;
                    814:                break;
                    815:        case PLANE_Y:
                    816:        case PLANE_ANYY:
                    817:                s_axis = 0;
                    818:                t_axis = 2;
                    819:                break;
                    820:        case PLANE_Z:
                    821:        case PLANE_ANYZ:
                    822:                s_axis = 0;
                    823:                t_axis = 1;
                    824:                break;
                    825:        }
                    826: 
                    827:        r_nearzi = 0;
                    828: 
                    829:        for (i=0 ; i<lnumverts ; i++)
                    830:        {
                    831:        // transform and project
                    832:                VectorSubtract (verts[vertpage][i].position, modelorg, local);
                    833:                TransformVector (local, transformed);
                    834: 
                    835:                if (transformed[2] < NEAR_CLIP)
                    836:                        transformed[2] = NEAR_CLIP;
                    837: 
                    838:                lzi = 1.0 / transformed[2];
                    839: 
                    840:                if (lzi > r_nearzi)     // for mipmap finding
                    841:                        r_nearzi = lzi;
                    842: 
                    843:        // FIXME: build x/yscale into transform?
                    844:                scale = xscale * lzi;
                    845:                u = (xcenter + scale*transformed[0]);
                    846:                if (u < r_refdef.fvrectx_adj)
                    847:                        u = r_refdef.fvrectx_adj;
                    848:                if (u > r_refdef.fvrectright_adj)
                    849:                        u = r_refdef.fvrectright_adj;
                    850: 
                    851:                scale = yscale * lzi;
                    852:                v = (ycenter - scale*transformed[1]);
                    853:                if (v < r_refdef.fvrecty_adj)
                    854:                        v = r_refdef.fvrecty_adj;
                    855:                if (v > r_refdef.fvrectbottom_adj)
                    856:                        v = r_refdef.fvrectbottom_adj;
                    857: 
                    858:                pverts[i].u = u;
                    859:                pverts[i].v = v;
                    860:                pverts[i].zi = lzi;
                    861:                pverts[i].s = verts[vertpage][i].position[s_axis];
                    862:                pverts[i].t = verts[vertpage][i].position[t_axis];
                    863:        }
                    864: 
                    865: // build the polygon descriptor, including fa, r_nearzi, and u, v, s, t, and z
                    866: // for each vertex
                    867:        r_polydesc.numverts = lnumverts;
                    868:        r_polydesc.nearzi = r_nearzi;
                    869:        r_polydesc.pcurrentface = fa;
                    870:        r_polydesc.pverts = pverts;
                    871: 
                    872: // draw the polygon
                    873:        D_DrawPoly ();
                    874: }
                    875: 
                    876: 
                    877: /*
                    878: ================
                    879: R_ZDrawSubmodelPolys
                    880: ================
                    881: */
                    882: void R_ZDrawSubmodelPolys (model_t *pmodel)
                    883: {
                    884:        int                     i, numsurfaces;
                    885:        msurface_t      *psurf;
                    886:        float           dot;
                    887:        mplane_t        *pplane;
                    888: 
                    889:        psurf = &pmodel->surfaces[pmodel->firstmodelsurface];
                    890:        numsurfaces = pmodel->nummodelsurfaces;
                    891: 
                    892:        for (i=0 ; i<numsurfaces ; i++, psurf++)
                    893:        {
                    894:        // find which side of the node we are on
                    895:                pplane = psurf->plane;
                    896: 
                    897:                dot = DotProduct (modelorg, pplane->normal) - pplane->dist;
                    898: 
                    899:        // draw the polygon
                    900:                if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
                    901:                        (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON)))
                    902:                {
                    903:                // FIXME: use bounding-box-based frustum clipping info?
                    904:                        R_RenderPoly (psurf, 15);
                    905:                }
                    906:        }
                    907: }
                    908: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.