Annotation of quakeworld/client/r_draw.c, revision 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.