home *** CD-ROM | disk | FTP | other *** search
/ Superpower (Alt) / SUPERPOWER.iso / q / source / render.m < prev    next >
Encoding:
Text File  |  1996-08-08  |  12.3 KB  |  749 lines

  1.  
  2. #import "qedefs.h"
  3.  
  4.  
  5. //define    NOLIGHT
  6.  
  7. vec3_t        r_origin, r_matrix[3];
  8.  
  9. int            t_width, t_height;
  10. unsigned    *t_data;
  11. int            t_widthmask, t_heightmask, t_widthshift;
  12. float        t_widthadd, t_heightadd;
  13.  
  14. int            r_width, r_height;
  15. float        *r_zbuffer;
  16. unsigned    *r_picbuffer;
  17.  
  18. vec5_t        rightside, leftside, rightstep,leftstep;
  19.  
  20. face_t        *r_face;
  21.  
  22. BOOL        r_drawflat;
  23.  
  24. pixel32_t    r_flatcolor;
  25.  
  26. int    sy[20];
  27.  
  28. /*
  29. ====================
  30. REN_ClearBuffers
  31. ====================
  32. */
  33. void REN_ClearBuffers (void)
  34. {
  35.     int        size;
  36.         
  37.     size = r_width * r_height*4;
  38.  
  39.     memset (r_zbuffer, 0, size);
  40.     memset (r_picbuffer, 0, size);    
  41. }
  42.  
  43.  
  44. /*
  45. ====================
  46. REN_SetTexture
  47. ====================
  48. */
  49.  
  50. void REN_SetTexture (face_t *face)
  51. {
  52.     int        i;
  53.     int        t_heightshift;
  54.     qtexture_t    *q;
  55.  
  56.     if (!face->qtexture)
  57.         face->qtexture = TEX_ForName (face->texture.texture);    // try to load
  58.     q = face->qtexture;
  59.     
  60.     t_width = q->width;
  61.     t_height = q->height;
  62.     t_data = q->data;
  63.     r_flatcolor = q->flatcolor;
  64.  
  65.     r_flatcolor.chan[0] *= r_face->light;
  66.     r_flatcolor.chan[1] *= r_face->light;
  67.     r_flatcolor.chan[2] *= r_face->light;
  68.     
  69.     t_widthadd = t_width*1024;
  70.     t_heightadd = t_height*1024;
  71.     
  72.     t_widthmask = t_width-1;
  73.     t_heightmask = t_height-1;
  74.     
  75.     t_widthshift = 0;
  76.     i = t_width;
  77.     while (i >= 2)
  78.     {
  79.         t_widthshift++;
  80.         i>>=1;
  81.     }
  82.     
  83.     t_heightshift = 0;
  84.     i = t_width;
  85.     while (i >= 2)
  86.     {
  87.         t_heightshift++;
  88.         i>>=1;
  89.     }
  90.     
  91.     if ( (1<<t_widthshift) != t_width || (1<<t_heightshift) != t_height)
  92.         t_widthshift = t_heightshift = 0;    // non power of two
  93. }
  94.  
  95. /*
  96. ==================
  97. REN_DrawSpan
  98. ==================
  99. */
  100. void REN_DrawSpan (int y)
  101. {
  102.     int            x, count;
  103.     int            ofs;
  104.     int            tx, ty;
  105.     int            x1, x2;
  106.     float        ufrac, vfrac, zfrac, lightfrac, ustep, vstep, zstep;
  107.     pixel32_t    *in, *out;
  108.     float        scale;
  109.         
  110.     if (y<0 || y >= r_height)
  111.         return;
  112.         
  113.     x1 = (leftside[0]);
  114.     x2 = (rightside[0]);
  115.  
  116.     count = x2 - x1;
  117.     if (count < 0)
  118.         return;
  119.     
  120.     zfrac = leftside[2];
  121.     ufrac = leftside[3];
  122.     vfrac = leftside[4];
  123.     lightfrac = r_face->light;
  124.     
  125.     if (!count)
  126.         scale = 1;
  127.     else
  128.         scale = 1.0/count;
  129.         
  130.     zstep = (rightside[2] - zfrac)*scale;
  131.     ustep = (rightside[3] - ufrac)*scale;
  132.     vstep = (rightside[4] - vfrac)*scale;
  133.     
  134.     if (x1 < 0)
  135.     {
  136.         ufrac -= x1*ustep;
  137.         vfrac -= x1*vstep;
  138.         zfrac -= x1*zstep;
  139.         x1 = 0;
  140.     }
  141.     
  142.     if (x2 > r_width)
  143.         x2 = r_width;
  144.  
  145.     ofs = y*r_width+x1;
  146.     
  147. // this should be specialized for 1.0 / 0.5 / 0.75 light levels
  148.     for (x=x1 ; x < x2 ; x++)
  149.     {
  150.         if (r_zbuffer[ofs] <= zfrac)
  151.         {
  152.             scale = 1/zfrac;
  153.  
  154.             r_zbuffer[ofs] = zfrac;
  155.  
  156.             if (t_widthshift)
  157.             {
  158.                 tx = (int)((ufrac*scale)) & t_widthmask;
  159.                 ty = (int)((vfrac*scale)) & t_heightmask;
  160.                 in = (pixel32_t *)&t_data [(ty<<t_widthshift)+tx];
  161.             }
  162.             else
  163.             {
  164.                 tx = (int)((ufrac*scale)+t_widthadd) % t_width;
  165.                 ty = (int)((vfrac*scale)+t_heightadd) % t_height;
  166.                 in = (pixel32_t *)&t_data [ty*t_width+tx];
  167.             }
  168.                 
  169.             out = (pixel32_t *)&r_picbuffer[ofs];
  170. #ifdef NOLIGHT
  171.             *out = *in;
  172. #else
  173.             out->chan[0] = in->chan[0]*lightfrac;
  174.             out->chan[1] = in->chan[1]*lightfrac;
  175.             out->chan[2] = in->chan[2]*lightfrac;
  176.             out->chan[3] = 0xff;
  177. #endif
  178.         }
  179.         ufrac += ustep;
  180.         vfrac += vstep;
  181.         zfrac += zstep;
  182.         ofs++;
  183.     }
  184.  
  185. }
  186.  
  187. /*
  188. ==================
  189. REN_DrawFlatSpan
  190. ==================
  191. */
  192. void REN_DrawFlatSpan (int y)
  193. {
  194.     int            x, count;
  195.     int            ofs;
  196.     int            x1, x2;
  197.     float        zfrac, zstep;
  198.     pixel32_t    *out;
  199.         
  200.     if (y<0 || y >= r_height)
  201.         return;
  202.         
  203.     x1 = (leftside[0]);
  204.     x2 = (rightside[0]);
  205.  
  206.     count = x2 - x1;
  207.     if (count < 0)
  208.         return;
  209.     
  210.     zfrac = leftside[2];
  211.     
  212.     zstep = (rightside[2] - zfrac)/count;
  213.     
  214.     if (x1 < 0)
  215.     {
  216.         zfrac -= x1*zstep;
  217.         x1 = 0;
  218.     }
  219.     
  220.     if (x2 > r_width)
  221.         x2 = r_width;
  222.  
  223.     ofs = y*r_width+x1;
  224.     
  225. // this should be specialized for 1.0 / 0.5 / 0.75 light levels
  226.     for (x=x1 ; x < x2 ; x++)
  227.     {
  228.         if (r_zbuffer[ofs] <= zfrac)
  229.         {
  230.             r_zbuffer[ofs] = zfrac;
  231.             out = (pixel32_t *)&r_picbuffer[ofs];
  232.             *out = r_flatcolor.p;
  233.         }
  234.         zfrac += zstep;
  235.         ofs++;
  236.     }
  237.  
  238. }
  239.  
  240. /*
  241. =====================
  242. REN_RasterizeFace
  243.  
  244. =====================
  245. */
  246. void REN_RasterizeFace (winding_t *w)
  247. {
  248.     int            y;
  249.     int            i;
  250.     int            top, bot;
  251.     int            leftv, rightv;
  252.     int            count;
  253.     int         numvertex;
  254.  
  255. //
  256. // find top vertex
  257. //
  258.     numvertex = w->numpoints;
  259.     top = 0x7fffffff;
  260.     bot = 0x80000000;
  261.     leftv = 0;
  262.     
  263.     for (i=0 ; i<numvertex ; i++)
  264.     {
  265.         w->points[i][3] *= w->points[i][2];
  266.         w->points[i][4] *= w->points[i][2];
  267.  
  268.         sy[i] = (int)w->points[i][1];
  269.         
  270.         if (sy[i] < top)
  271.         {
  272.             top = sy[i];
  273.             leftv = i;
  274.         }
  275.         if (sy[i] > bot)
  276.             bot = sy[i];
  277.     }
  278.     rightv = leftv;    
  279.     
  280.     if (top < 0 || bot > r_height || top > bot)
  281.         return;        // shouldn't have to have this...
  282.         
  283. //
  284. // render a trapezoid
  285. //
  286.     y = top;
  287.     
  288.     while (y < bot)
  289.     {
  290.         if (y >= sy[leftv])
  291.         {
  292.             do
  293.             {
  294.                 for (i=0 ; i<5 ; i++)
  295.                     leftside[i] = w->points[leftv][i];
  296.                 leftv--;
  297.                 if (leftv == -1)
  298.                     leftv = numvertex-1;
  299.             } while (sy[leftv] <= y);
  300.             count = sy[leftv]-y;
  301.             for (i=0 ; i<5 ; i++)
  302.                 leftstep[i] = (w->points[leftv][i] - leftside[i])/count;
  303.         }
  304.         if (y >= sy[rightv])
  305.         {
  306.             do
  307.             {
  308.                 for (i=0 ; i<5 ; i++)
  309.                     rightside[i] = w->points[rightv][i];
  310.                 rightv++;
  311.                 if (rightv == numvertex)
  312.                     rightv = 0;
  313.             } while (sy[rightv] <= y);
  314.             count = sy[rightv]-y;
  315.             for (i=0 ; i<5 ; i++)
  316.                 rightstep[i] = (w->points[rightv][i] - rightside[i])/count;
  317.         }
  318.         
  319.         if (r_drawflat)
  320.             REN_DrawFlatSpan (y);
  321.         else
  322.             REN_DrawSpan (y);
  323.         
  324.         for (i=0 ; i<5 ; i++)
  325.         {
  326.             leftside[i] += leftstep[i];
  327.             rightside[i] += rightstep[i];
  328.         }
  329.             
  330.         y++;
  331.     }
  332. }
  333.  
  334. //=============================================================================
  335.  
  336. /*
  337. ==================
  338. REN_DrawSpanLinear
  339. ==================
  340. */
  341. void REN_DrawSpanLinear (int y)
  342. {
  343.     int            x, count;
  344.     int            ofs;
  345.     int            tx, ty;
  346.     int            x1, x2;
  347.     float        ufrac, vfrac, zfrac, ustep, vstep, zstep;
  348.     pixel32_t    *in, *out;
  349.     float        scale;
  350.             
  351.     if (y<0 || y >= r_height)
  352.         return;
  353.         
  354.     x1 = (leftside[0]);
  355.     x2 = (rightside[0]);
  356.  
  357.     count = x2 - x1;
  358.     if (count < 0)
  359.         return;
  360.         
  361.     zfrac = leftside[2];
  362.     ufrac = leftside[3];
  363.     vfrac = leftside[4];
  364.     
  365.     if (!count)
  366.         scale = 1;
  367.     else
  368.         scale = 1.0/count;
  369.         
  370.     zstep = (rightside[2] - zfrac)*scale;
  371.     ustep = (rightside[3] - ufrac)*scale;
  372.     vstep = (rightside[4] - vfrac)*scale;
  373.  
  374.     
  375.     if (x1 < 0)
  376.     {
  377.         ufrac -= x1*ustep;
  378.         vfrac -= x1*vstep;
  379.         zfrac -= x1*zstep;
  380.         x1 = 0;
  381.     }
  382.     
  383.     if (x2 > r_width)
  384.         x2 = r_width;
  385.  
  386.     ofs = y*r_width+x1;
  387.         
  388.     for (x=x1 ; x < x2 ; x++)
  389.     {
  390.         if (r_zbuffer[ofs] <= zfrac)
  391.         {
  392.             r_zbuffer[ofs] = zfrac;
  393.  
  394.             if (t_widthshift)
  395.             {
  396.                 tx = (int)ufrac & t_widthmask;
  397.                 ty = (int)vfrac & t_heightmask;
  398.                 in = (pixel32_t *)&t_data [(ty<<t_widthshift)+tx];
  399.             }
  400.             else
  401.             {
  402.                 tx = (int)(ufrac+t_widthadd) % t_width;
  403.                 ty = (int)(vfrac+t_heightadd) % t_height;
  404.                 in = (pixel32_t *)&t_data [ty*t_width+tx];
  405.             }
  406.     
  407.             out = (pixel32_t *)&r_picbuffer[ofs];
  408.             *out = *in;
  409.         }
  410.         ufrac += ustep;
  411.         vfrac += vstep;
  412.         zfrac += zstep;
  413.         ofs++;
  414.     }
  415.  
  416. }
  417.  
  418. /*
  419. =====================
  420. REN_RasterizeFaceLinear
  421.  
  422. =====================
  423. */
  424. void REN_RasterizeFaceLinear (winding_t *w)
  425. {
  426.     int            y;
  427.     int            i;
  428.     int            top, bot;
  429.     int            leftv, rightv;
  430.     int            count;
  431.     int            numvertex;
  432.     
  433. //
  434. // find top vertex
  435. //
  436.     numvertex = w->numpoints;
  437.     top = 0x7fffffff;
  438.     bot = 0x80000000;
  439.  
  440.     leftv = 0;
  441.     for (i=0 ; i<numvertex ; i++)
  442.     {
  443.         sy[i] = (int)w->points[i][1];
  444.         
  445.         if (sy[i] < top)
  446.         {
  447.             top = sy[i];
  448.             leftv = i;
  449.         }
  450.         if (sy[i] > bot)
  451.             bot = sy[i];
  452.     }
  453.     rightv = leftv;    
  454.     
  455.     if (top < 0 || bot > r_height || top > bot)
  456.         return;        // shouldn't have to have this...
  457.         
  458. //
  459. // render a trapezoid
  460. //
  461.     y = top;
  462.     
  463.     while (y < bot)
  464.     {
  465.         if (y >= sy[leftv])
  466.         {
  467.             do
  468.             {
  469.                 for (i=0 ; i<5 ; i++)
  470.                     leftside[i] = w->points[leftv][i];
  471.                 leftv--;
  472.                 if (leftv == -1)
  473.                     leftv = numvertex-1;
  474.             } while (sy[leftv] <= y);
  475.             count = sy[leftv]-y;
  476.             for (i=0 ; i<5 ; i++)
  477.                 leftstep[i] = (w->points[leftv][i] - leftside[i])/count;
  478.         }
  479.         if (y >= sy[rightv])
  480.         {
  481.             do
  482.             {
  483.                 for (i=0 ; i<5 ; i++)
  484.                     rightside[i] = w->points[rightv][i];
  485.                 rightv++;
  486.                 if (rightv == numvertex)
  487.                     rightv = 0;
  488.             } while (sy[rightv] <= y);
  489.             count = sy[rightv]-y;
  490.             for (i=0 ; i<5 ; i++)
  491.                 rightstep[i] = (w->points[rightv][i] - rightside[i])/count;
  492.         }
  493.         
  494.         REN_DrawSpanLinear (y);
  495.         
  496.         for (i=0 ; i<5 ; i++)
  497.         {
  498.             leftside[i] += leftstep[i];
  499.             rightside[i] += rightstep[i];
  500.         }
  501.             
  502.         y++;
  503.     }
  504. }
  505.  
  506. //============================================================================
  507.  
  508. /*
  509. ==================
  510. REN_BeginCamera
  511. ===================
  512. */
  513. float    r_width_2, r_height_3;
  514. plane_t    frustum[5];
  515.  
  516. void REN_BeginCamera (void)
  517. {
  518.     r_width_2 = (float)r_width / 2;
  519.     r_height_3 = (float)r_height / 3;
  520.     
  521.     
  522. // clip to right side
  523.     frustum[0].normal[0] = -1;
  524.     frustum[0].normal[1] = 0;
  525.     frustum[0].normal[2] = 1;
  526.     frustum[0].dist = 0;
  527.  
  528. // clip to left side
  529.     frustum[1].normal[0] = 1;
  530.     frustum[1].normal[1] = 0;
  531.     frustum[1].normal[2] = 1;
  532.     frustum[1].dist = 0;
  533.  
  534. // clip to top side
  535.     frustum[2].normal[0] = 0;
  536.     frustum[2].normal[1] = -1;
  537.     frustum[2].normal[2] = r_height_3 / r_width_2;
  538.     frustum[2].dist = 0;
  539.  
  540. // clip to bottom side
  541.     frustum[3].normal[0] = 0;
  542.     frustum[3].normal[1] = 1;
  543.     frustum[3].normal[2] = 2*r_height_3 / r_width_2;    
  544.     frustum[3].dist = 0;
  545.  
  546. // near Z
  547.     frustum[4].normal[0] = 0;
  548.     frustum[4].normal[1] = 0;
  549.     frustum[4].normal[2] = 1;
  550.     frustum[4].dist = 1;
  551. }
  552.  
  553.  
  554. void REN_BeginXY (void)
  555. {
  556.     frustum[0].normal[0] = 1;
  557.     frustum[0].normal[1] = 0;
  558.     frustum[0].normal[2] = 0;
  559.     frustum[0].dist = 0;
  560.         
  561.     frustum[1].normal[0] = -1;
  562.     frustum[1].normal[1] = 0;
  563.     frustum[1].normal[2] = 0;
  564.     frustum[1].dist = -r_width;
  565.  
  566.     frustum[2].normal[0] = 0;
  567.     frustum[2].normal[1] = 1;
  568.     frustum[2].normal[2] = 0;
  569.     frustum[2].dist = 0;
  570.  
  571.     frustum[3].normal[0] = 0;
  572.     frustum[3].normal[1] = -1;
  573.     frustum[3].normal[2] = 0;
  574.     frustum[3].dist = -r_height;
  575. }
  576.  
  577. /*
  578. =====================
  579. REN_DrawCameraFace
  580. =====================
  581. */
  582. void REN_DrawCameraFace (face_t *idpol)
  583. {
  584.     int        i;
  585.     float        scale;    
  586.     int            numvertex;
  587.     winding_t    *w, *in;
  588.     vec3_t        temp;
  589.     
  590.     if (!idpol->w)
  591.         return;    // overconstrained plane
  592.         
  593.     r_face = idpol;
  594.  
  595. //
  596. // back face cull
  597. //
  598.     if (DotProduct (r_origin, idpol->plane.normal) <= idpol->plane.dist)
  599.         return;
  600.  
  601. //
  602. // transform in 3D (FIXME: clip first, then transform)
  603. //
  604.     in = idpol->w;
  605.     numvertex = in->numpoints;
  606.  
  607.     w = NewWinding (numvertex);
  608.     w->numpoints = numvertex;
  609.     for (i=0 ; i<numvertex ; i++)
  610.     {
  611.         VectorSubtract (in->points[i], r_origin, temp);
  612.     
  613.         w->points[i][0] = DotProduct(temp,r_matrix[0]);
  614.         w->points[i][1] = DotProduct(temp,r_matrix[1]);
  615.         w->points[i][2] = DotProduct(temp,r_matrix[2]);
  616.  
  617.         w->points[i][3] = in->points[i][3];
  618.         w->points[i][4] = in->points[i][4];
  619.     }
  620.     
  621. //
  622. // 3D clip
  623. //
  624.     for (i=0 ; i<4 ; i++)
  625.     {
  626.         w = ClipWinding (w, &frustum[i]);
  627.         if (!w)
  628.             return;
  629.     }
  630.         
  631. //
  632. // project to 2D
  633. //
  634.     for (i=0 ; i<w->numpoints ; i++)
  635.     {
  636.         scale = r_width_2 / w->points[i][2];
  637.         w->points[i][0] = r_width_2 + scale*w->points[i][0];
  638.         w->points[i][1] = r_height_3 - scale*w->points[i][1];
  639.         w->points[i][2] = scale;
  640.     }
  641.     
  642.     
  643. //
  644. // draw it
  645. //
  646.     REN_SetTexture (idpol);
  647.     
  648.     REN_RasterizeFace (w);
  649.     free (w);
  650. }
  651.  
  652.  
  653. /*
  654. =====================
  655. REN_DrawXYFace
  656. =====================
  657. */
  658. void REN_DrawXYFace (face_t *idpol)
  659. {
  660.     int            i, j, numvertex;
  661.     winding_t    *w, *in;
  662.     float        *dest, *source;
  663.     float        temp;
  664.     
  665.     if (!idpol->w)
  666.         return;    // overconstrained plane
  667.     w = idpol->w;
  668.         
  669.     r_face = idpol;
  670.     
  671. //
  672. // back (and side) face cull
  673. //
  674.     if (DotProduct (idpol->plane.normal, xy_viewnormal) > -VECTOR_EPSILON)
  675.         return;
  676.  
  677. //
  678. // transform
  679. //
  680.     in = idpol->w;
  681.     numvertex = in->numpoints;
  682.  
  683.     w = NewWinding (numvertex);
  684.     w->numpoints = numvertex;
  685.  
  686.     for (i=0 ; i<numvertex ; i++)
  687.     {
  688.     // using Z as a scale for the 2D projection
  689.         w->points[i][0] = (in->points[i][0] - r_origin[0])*r_origin[2];
  690.         w->points[i][1] = r_height - (in->points[i][1] - r_origin[1])*r_origin[2];
  691.         w->points[i][2] = in->points[i][2] + 3000;
  692.         w->points[i][3] = in->points[i][3];
  693.         w->points[i][4] = in->points[i][4];
  694.     }
  695.     
  696. //
  697. // clip
  698. //
  699.     for (i=0 ; i<4 ; i++)
  700.     {
  701.         w = ClipWinding (w, &frustum[i]);
  702.         if (!w)
  703.             return;
  704.     }
  705.         
  706. //
  707. // project to 2D
  708. //
  709.     for (i=0 ; i<w->numpoints ; i++)
  710.     {
  711.         dest = w->points[i];
  712.         if (dest[0] < 0)
  713.             dest[0] = 0;
  714.         if (dest[0] > r_width)
  715.             dest[0] = r_width;
  716.         if (dest[1] < 0)
  717.             dest[1] = 0;
  718.         if (dest[1] > r_height)
  719.             dest[1] = r_height;
  720.         if (xy_viewnormal[2] > 0)
  721.             dest[2] = 4096-dest[2];
  722.     }
  723.  
  724.     if (xy_viewnormal[2] > 0)
  725.     {    // flip order when upside down
  726.         for (i=0 ; i<w->numpoints/2 ; i++)
  727.         {
  728.             dest = w->points[i];
  729.             source = w->points[w->numpoints-1-i];
  730.             for (j=0 ; j<5 ; j++)
  731.             {
  732.                 temp = dest[j];
  733.                 dest[j] = source[j];
  734.                 source[j] = temp;
  735.             }
  736.         }
  737.     }
  738.     
  739.     REN_SetTexture (idpol);
  740.     
  741.     
  742. //
  743. // draw it
  744. //
  745.     REN_RasterizeFaceLinear (w);
  746.     free (w);
  747. }
  748.  
  749.