home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / texmap / tmapv.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  16KB  |  553 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/texmap/rcs/tmapv.c $
  15.  * $Revision: 1.5 $
  16.  * $Author: mike $
  17.  * $Date: 1994/11/28 13:34:30 $
  18.  * 
  19.  * Vertical scanning in inner loop analogue to tmap.c
  20.  * 
  21.  * $Log: tmapv.c $
  22.  * Revision 1.5  1994/11/28  13:34:30  mike
  23.  * optimizations.
  24.  * 
  25.  * Revision 1.4  1994/05/24  17:31:01  mike
  26.  * Vertical scanning texture mapper, hyperbolic in outer loop, linear in inner.
  27.  * 
  28.  * Revision 1.3  1994/05/24  11:02:54  mike
  29.  * Fix bugs in vertically scanning texture mapper, hack in Do_vertical_scan.
  30.  * 
  31.  * Revision 1.2  1994/01/31  15:42:02  mike
  32.  * Vertical scanning version of texture mapper.
  33.  * 
  34.  * Revision 1.1  1994/01/30  13:56:44  mike
  35.  * Initial revision
  36.  * 
  37.  * 
  38.  */
  39.  
  40.  
  41. #pragma off (unreferenced)
  42. static char rcsid[] = "$Id: tmapv.c 1.5 1994/11/28 13:34:30 mike Exp $";
  43. #pragma on (unreferenced)
  44.  
  45. #include <math.h>
  46. #include <limits.h>
  47. #include <stdio.h>
  48. #include <conio.h>
  49. #include <stdlib.h>
  50.  
  51. #include "mono.h"
  52. #include "fix.h"
  53. #include "3d.h"
  54. #include "gr.h"
  55. #include "error.h"
  56.  
  57. #include "texmap.h"
  58. #include "texmapl.h"
  59.  
  60. int    Is_sky_flag;
  61.  
  62. // ------------------------------------------------------------------------------------------
  63. void compute_x_bounds(g3ds_tmap *t, int *vlt, int *vlb, int *vrt, int *vrb, int *left_x_ind)
  64. {
  65.     int    i;
  66.     int    min_y,max_y;
  67.     int    min_x_ind;
  68.     int    original_vrt;
  69.     fix    min_x,max_x;
  70.  
  71.     min_y = 9999;
  72.     max_y = -9999;
  73.     min_x = 9999;
  74.     max_x = -9999;
  75.  
  76.     // Scan all vertices, set min_y_ind to vertex with smallest y coordinate.
  77.     for (i=0; i<t->nv; i++) {
  78.         if (f2i(t->verts[i].x2d) < min_x) {
  79.             min_x = f2i(t->verts[i].x2d);
  80.             min_x_ind = i;
  81.             min_y = f2i(t->verts[i].y2d);
  82.         } else if (f2i(t->verts[i].x2d) == min_x) {
  83.             if (f2i(t->verts[i].y2d) < min_y) {
  84.                 min_x_ind = i;
  85.                 min_y = f2i(t->verts[i].y2d);
  86.             }
  87.         }
  88.         if (f2i(t->verts[i].x2d) > max_x) {
  89.             max_x = f2i(t->verts[i].x2d);
  90.             *left_x_ind = i;
  91.         }
  92.     }
  93.  
  94.     // Set "vertex left top", etc. based on vertex with topmost y coordinate
  95.     *vlt = min_x_ind;
  96.     *vrt = *vlt;
  97.     *vlb = succmod(*vlt,t->nv);
  98.     *vrb = prevmod(*vrt,t->nv);
  99.  
  100.     // If right edge is vertical, then advance along polygon bound until it no longer is or until all
  101.     // vertices have been examined.
  102.     // (Left edge cannot be horizontal, because *vlt is set to leftmost point with highest y coordinate.)
  103.  
  104.     original_vrt = *vrt;
  105.  
  106.     while (f2i(t->verts[*vrt].x2d) == f2i(t->verts[*vrb].x2d)) {
  107.         if (succmod(*vrt,t->nv) == original_vrt) {
  108.             break;
  109.         }
  110.         *vrt = prevmod(*vrt,t->nv);
  111.         *vrb = prevmod(*vrt,t->nv);
  112.     }
  113. }
  114.  
  115. // -------------------------------------------------------------------------------------
  116. //    Render a texture map.
  117. // Linear in outer loop, linear in inner loop.
  118. //    Scan horizontally in outer loop, vertically in inner loop.
  119. fix compute_dy_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  120. {
  121.     int    dx;
  122.  
  123.     // compute delta x with respect to y for any edge
  124.     dx = f2i(t->verts[bottom_vertex].x2d - t->verts[top_vertex].x2d) + 1;
  125.     if (dx)
  126.         return (t->verts[bottom_vertex].y2d - t->verts[top_vertex].y2d) / dx;
  127.     else
  128.         return 0;
  129.  
  130. }
  131.  
  132. fix compute_dy_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  133. {
  134.     int    dx;
  135.  
  136.     // compute delta y with respect to y for any edge
  137.     dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  138.     if (dx)
  139.         return (t->verts[bottom_vertex].y2d - t->verts[top_vertex].y2d) / dx;
  140.     else
  141.         return 0;
  142.  
  143. }
  144.  
  145. fix compute_du_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  146. {
  147.     int    dx;
  148.  
  149.     // compute delta u with respect to y for any edge
  150.     dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  151.     if (dx)
  152.         return (fixmul(t->verts[bottom_vertex].u,t->verts[bottom_vertex].z) - fixmul(t->verts[top_vertex].u,t->verts[top_vertex].z)) / dx;
  153.     else
  154.         return 0;
  155.  
  156. }
  157.  
  158.  
  159. fix compute_dv_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  160. {
  161.     int    dx;
  162.  
  163.     // compute delta v with respect to y for any edge
  164.     dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  165.     if (dx)
  166.         return (fixmul(t->verts[bottom_vertex].v,t->verts[bottom_vertex].z) - fixmul(t->verts[top_vertex].v,t->verts[top_vertex].z)) / dx;
  167.     else
  168.         return 0;
  169.  
  170. }
  171.  
  172. fix compute_dz_dx(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  173. {
  174.     int    dx;
  175.  
  176.     // compute delta x with respect to y for the any edge
  177.     // this is used in computing the x coordinate on the next row and in
  178.     // scaling the add of Du_dx to the uleft and vleft coordinates.
  179.     dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d); // + 1;
  180.     if (dx)
  181.         return (t->verts[bottom_vertex].z - t->verts[top_vertex].z) / dx;
  182.     else
  183.         return 0;
  184.  
  185. }
  186.  
  187. fix compute_dl_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  188. {
  189.     int    dx;
  190.  
  191.     // compute delta l with respect to y for any edge
  192.     dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d) + 1;
  193.     if (dx)
  194.         return (t->verts[bottom_vertex].l - t->verts[top_vertex].l) / dx;
  195.     else
  196.         return 0;
  197.  
  198. }
  199.  
  200. fix compute_du_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  201. {
  202.     int    dx;
  203.  
  204.     // compute delta u with respect to y for any edge
  205.     dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d) + 1;
  206.     if (dx)
  207.         return (t->verts[bottom_vertex].u - t->verts[top_vertex].u) / dx;
  208.     else
  209.         return 0;
  210.  
  211. }
  212.  
  213.  
  214. fix compute_dv_dx_lin(g3ds_tmap *t, int top_vertex,int bottom_vertex)
  215. {
  216.     int    dx;
  217.  
  218.     // compute delta v with respect to y for any edge
  219.     dx = f2i(t->verts[bottom_vertex].x2d) - f2i(t->verts[top_vertex].x2d) + 1;
  220.     if (dx)
  221.         return (t->verts[bottom_vertex].v - t->verts[top_vertex].v) / dx;
  222.     else
  223.         return 0;
  224.  
  225. }
  226.  
  227. // -------------------------------------------------------------------------------------
  228. void tmap_scanline_lin_sky_v(grs_bitmap *srcb, int x, fix yleft, fix yright, fix uleft, fix uright, fix vleft, fix vright)
  229. {
  230.     fix    dy;
  231.  
  232.     dy = f2i(yright) - f2i(yleft);
  233.     if ((dy < 0) || (yright < 0) || (yleft > yright))        // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  234.         return;
  235.  
  236.     // setup to call assembler scanline renderer
  237.     fx_u = uleft;
  238.     fx_v = vleft;
  239.  
  240.     if (dy < f1_0) {
  241.         fx_du_dx = uright-uleft;
  242.         fx_dv_dx = vright-vleft;
  243.     } else {
  244.         fx_du_dx = fixdiv(uright - fx_u,dy);
  245.         fx_dv_dx = fixdiv(vright - fx_v,dy);
  246.     }
  247.  
  248.     fx_y = x;
  249.     fx_xleft = yleft;
  250.     fx_xright = yright;
  251.     pixptr = srcb->bm_data;
  252.  
  253.     if (Is_sky_flag)
  254.         asm_tmap_scanline_lin_sky_v();
  255.     else
  256.         asm_tmap_scanline_lin_v();
  257.  
  258. }
  259.  
  260. // -------------------------------------------------------------------------------------
  261. void tmap_scanline_hyp_lin_v(grs_bitmap *srcb, int x, fix yleft, fix yright, fix uleft, fix uright, fix vleft, fix vright, fix zleft, fix zright)
  262. {
  263. //    fix    dy, recip_dy, z;
  264.     int    dy;
  265.  
  266.     dy = f2i(yright) - f2i(yleft);
  267.     if ((dy < 0) || (yright < 0) || (yleft > yright))        // the (xleft > xright) term is not redundant with (dx < 0) because dx is computed using integers
  268.         return;
  269.  
  270.     // setup to call assembler scanline renderer
  271. //    if (dy < FIX_RECIP_TABLE_SIZE)
  272. //        recip_dy = fix_recip[dy];
  273. //    else
  274. //        recip_dy = F1_0/dy;
  275.  
  276.     uleft = fixdiv(uleft, zleft);
  277.     uright = fixdiv(uright, zright);
  278.     vleft = fixdiv(vleft, zleft);
  279.     vright = fixdiv(vright, zright);
  280.  
  281.     if (dy > 0) {
  282.         fx_du_dx = (uright - uleft)/dy;
  283.         fx_dv_dx = (vright - vleft)/dy;
  284.     } else {
  285.         fx_du_dx = 0;
  286.         fx_dv_dx = 0;
  287.     }
  288. //    fx_dz_dx = fixmul(zright - zleft,recip_dy);
  289.  
  290.     fx_u = uleft;
  291.     fx_v = vleft;
  292.     fx_z = zleft;
  293.     fx_y = x;
  294.     fx_xleft = yleft;
  295.     fx_xright = yright;
  296.     pixptr = srcb->bm_data;
  297.  
  298.     if (Is_sky_flag)
  299.         asm_tmap_scanline_lin_sky_v();
  300.     else
  301.         asm_tmap_scanline_lin_v();
  302.  
  303. }
  304.  
  305.  
  306. // -------------------------------------------------------------------------------------
  307. void texture_map_hyp_lin_v(grs_bitmap *srcb, g3ds_tmap *t)
  308. {
  309.     int    vlt,vrt,vlb,vrb;    // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  310.     int    topy,boty,x;
  311.     int    left_break,right_break;
  312.  
  313.     fix    dx_dy_left,dx_dy_right;
  314.     fix    du_dy_left,du_dy_right;
  315.     fix    dv_dy_left,dv_dy_right;
  316.     fix    dz_dy_left,dz_dy_right;
  317.     fix    zleft, zright;
  318.  
  319.     int    max_x_vertex;
  320.     fix    yleft,yright,uleft,vleft,uright,vright;
  321.     g3ds_vertex *v3d;
  322.  
  323. // mprintf(0, "width = %i, height = %i\n", srcb->bm_w, srcb->bm_h);
  324. Is_sky_flag = 0;
  325. if ((srcb->bm_w == 1024) && (srcb->bm_h == 128))
  326.     Is_sky_flag = 1;
  327.  
  328.     //--now called from g3_start_frame-- init_interface_vars_to_assembler();
  329.  
  330.     v3d = t->verts;
  331.  
  332.     // Determine top and bottom y coords.
  333.     compute_x_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_x_vertex);
  334.  
  335.     // Set top and bottom (of entire texture map) y coordinates.
  336.     topy = f2i(v3d[vlt].x2d);
  337.     boty = f2i(v3d[max_x_vertex].x2d);
  338.  
  339.     // Set amount to change x coordinate for each advance to next scanline.
  340.     dx_dy_left = compute_dy_dx(t,vlt,vlb);
  341.     dx_dy_right = compute_dy_dx(t,vrt,vrb);
  342.  
  343.     du_dy_left = compute_du_dx(t,vlt,vlb);
  344.     du_dy_right = compute_du_dx(t,vrt,vrb);
  345.  
  346.     dv_dy_left = compute_dv_dx(t,vlt,vlb);
  347.     dv_dy_right = compute_dv_dx(t,vrt,vrb);
  348.  
  349.     dz_dy_left = compute_dz_dx(t,vlt,vlb);
  350.     dz_dy_right = compute_dz_dx(t,vrt,vrb);
  351.  
  352.      // Set initial values for x, u, v
  353.     yleft = v3d[vlt].y2d;
  354.     yright = v3d[vrt].y2d;
  355.  
  356.     zleft = v3d[vlt].z;
  357.     zright = v3d[vrt].z;
  358.  
  359.     uleft = fixmul(v3d[vlt].u,zleft);
  360.     uright = fixmul(v3d[vrt].u,zright);
  361.     vleft = fixmul(v3d[vlt].v,zleft);
  362.     vright = fixmul(v3d[vrt].v,zright);
  363.  
  364.     // scan all rows in texture map from top through first break.
  365.     // @mk: Should we render the scanline for y==boty?  This violates Matt's spec.
  366.  
  367.     left_break = f2i(v3d[vlb].x2d);
  368.     right_break = f2i(v3d[vrb].x2d);
  369.  
  370.     for (x = topy; x < boty; x++) {
  371.  
  372.         // See if we have reached the end of the current left edge, and if so, set
  373.         // new values for dx_dy and x,u,v
  374.         if (x == left_break) {
  375.             // Handle problem of double points.  Search until y coord is different.  Cannot get
  376.             // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  377.             // because in the for loop, we don't scan all spanlines.
  378.             while (x == f2i(v3d[vlb].x2d)) {
  379.                 vlt = vlb;
  380.                 vlb = succmod(vlb,t->nv);
  381.             }
  382.             left_break = f2i(v3d[vlb].x2d);
  383.  
  384.             dx_dy_left = compute_dy_dx(t,vlt,vlb);
  385.  
  386.             yleft = v3d[vlt].y2d;
  387.             zleft = v3d[vlt].z;
  388.             uleft = fixmul(v3d[vlt].u,zleft);
  389.             vleft = fixmul(v3d[vlt].v,zleft);
  390.  
  391.             du_dy_left = compute_du_dx(t,vlt,vlb);
  392.             dv_dy_left = compute_dv_dx(t,vlt,vlb);
  393.             dz_dy_left = compute_dz_dx(t,vlt,vlb);
  394.  
  395.         }
  396.  
  397.         // See if we have reached the end of the current left edge, and if so, set
  398.         // new values for dx_dy and x.  Not necessary to set new values for u,v.
  399.         if (x == right_break) {
  400.             while (x == f2i(v3d[vrb].x2d)) {
  401.                 vrt = vrb;
  402.                 vrb = prevmod(vrb,t->nv);
  403.             }
  404.             right_break = f2i(v3d[vrb].x2d);
  405.  
  406.             dx_dy_right = compute_dy_dx(t,vrt,vrb);
  407.  
  408.             yright = v3d[vrt].y2d;
  409.             zright = v3d[vrt].z;
  410.             uright = fixmul(v3d[vrt].u,zright);
  411.             vright = fixmul(v3d[vrt].v,zright);
  412.  
  413.             du_dy_right = compute_du_dx(t,vrt,vrb);
  414.             dv_dy_right = compute_dv_dx(t,vrt,vrb);
  415.             dz_dy_right = compute_dz_dx(t,vrt,vrb);
  416.  
  417.         }
  418.  
  419.         tmap_scanline_hyp_lin_v(srcb,x,yleft,yright,uleft,uright,vleft,vright, zleft, zright);
  420.  
  421.         uleft += du_dy_left;
  422.         vleft += dv_dy_left;
  423.  
  424.         uright += du_dy_right;
  425.         vright += dv_dy_right;
  426.  
  427.         yleft += dx_dy_left;
  428.         yright += dx_dy_right;
  429.  
  430.         zleft += dz_dy_left;
  431.         zright += dz_dy_right;
  432.     }
  433.  
  434.     tmap_scanline_hyp_lin_v(srcb,x,yleft,yright,uleft,uright,vleft,vright, zleft, zright);
  435. }
  436.  
  437.  
  438. // -------------------------------------------------------------------------------------
  439. void texture_map_lin_lin_sky_v(grs_bitmap *srcb, g3ds_tmap *t)
  440. {
  441.     int    vlt,vrt,vlb,vrb;    // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  442.     int    topy,boty,x;
  443.     int    left_break,right_break;
  444.  
  445.     fix    dx_dy_left,dx_dy_right;
  446.     fix    du_dy_left,du_dy_right;
  447.     fix    dv_dy_left,dv_dy_right;
  448.  
  449.     int    max_x_vertex;
  450.     fix    yleft,yright,uleft,vleft,uright,vright;
  451.     g3ds_vertex *v3d;
  452.  
  453. // mprintf(0, "width = %i, height = %i\n", srcb->bm_w, srcb->bm_h);
  454. Is_sky_flag = 0;
  455. if ((srcb->bm_w == 1024) && (srcb->bm_h == 128))
  456.     Is_sky_flag = 1;
  457.  
  458.     //--now called from g3_start_frame-- init_interface_vars_to_assembler();
  459.  
  460.     v3d = t->verts;
  461.  
  462.     // Determine top and bottom y coords.
  463.     compute_x_bounds(t,&vlt,&vlb,&vrt,&vrb,&max_x_vertex);
  464.  
  465.     // Set top and bottom (of entire texture map) y coordinates.
  466.     topy = f2i(v3d[vlt].x2d);
  467.     boty = f2i(v3d[max_x_vertex].x2d);
  468.  
  469.     // Set amount to change x coordinate for each advance to next scanline.
  470.     dx_dy_left = compute_dy_dx_lin(t,vlt,vlb);
  471.     dx_dy_right = compute_dy_dx_lin(t,vrt,vrb);
  472.  
  473.     du_dy_left = compute_du_dx_lin(t,vlt,vlb);
  474.     du_dy_right = compute_du_dx_lin(t,vrt,vrb);
  475.  
  476.     dv_dy_left = compute_dv_dx_lin(t,vlt,vlb);
  477.     dv_dy_right = compute_dv_dx_lin(t,vrt,vrb);
  478.  
  479.      // Set initial values for x, u, v
  480.     yleft = v3d[vlt].y2d;
  481.     yright = v3d[vrt].y2d;
  482.  
  483.     uleft = v3d[vlt].u;
  484.     uright = v3d[vrt].u;
  485.     vleft = v3d[vlt].v;
  486.     vright = v3d[vrt].v;
  487.  
  488.     // scan all rows in texture map from top through first break.
  489.     // @mk: Should we render the scanline for y==boty?  This violates Matt's spec.
  490.  
  491.     left_break = f2i(v3d[vlb].x2d);
  492.     right_break = f2i(v3d[vrb].x2d);
  493.  
  494.     for (x = topy; x < boty; x++) {
  495.  
  496.         // See if we have reached the end of the current left edge, and if so, set
  497.         // new values for dx_dy and x,u,v
  498.         if (x == left_break) {
  499.             // Handle problem of double points.  Search until y coord is different.  Cannot get
  500.             // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  501.             // because in the for loop, we don't scan all spanlines.
  502.             while (x == f2i(v3d[vlb].x2d)) {
  503.                 vlt = vlb;
  504.                 vlb = succmod(vlb,t->nv);
  505.             }
  506.             left_break = f2i(v3d[vlb].x2d);
  507.  
  508.             dx_dy_left = compute_dy_dx_lin(t,vlt,vlb);
  509.  
  510.             yleft = v3d[vlt].y2d;
  511.             uleft = v3d[vlt].u;
  512.             vleft = v3d[vlt].v;
  513.  
  514.             du_dy_left = compute_du_dx_lin(t,vlt,vlb);
  515.             dv_dy_left = compute_dv_dx_lin(t,vlt,vlb);
  516.         }
  517.  
  518.         // See if we have reached the end of the current left edge, and if so, set
  519.         // new values for dx_dy and x.  Not necessary to set new values for u,v.
  520.         if (x == right_break) {
  521.             while (x == f2i(v3d[vrb].x2d)) {
  522.                 vrt = vrb;
  523.                 vrb = prevmod(vrb,t->nv);
  524.             }
  525.             right_break = f2i(v3d[vrb].x2d);
  526.  
  527.             dx_dy_right = compute_dy_dx_lin(t,vrt,vrb);
  528.  
  529.             yright = v3d[vrt].y2d;
  530.             uright = v3d[vrt].u;
  531.             vright = v3d[vrt].v;
  532.  
  533.             du_dy_right = compute_du_dx_lin(t,vrt,vrb);
  534.             dv_dy_right = compute_dv_dx_lin(t,vrt,vrb);
  535.         }
  536.  
  537.         tmap_scanline_lin_sky_v(srcb,x,yleft,yright,uleft,uright,vleft,vright);
  538.  
  539.         uleft += du_dy_left;
  540.         vleft += dv_dy_left;
  541.  
  542.         uright += du_dy_right;
  543.         vright += dv_dy_right;
  544.  
  545.         yleft += dx_dy_left;
  546.         yright += dx_dy_right;
  547.  
  548.     }
  549.     tmap_scanline_lin_sky_v(srcb,x,yleft,yright,uleft,uright,vleft,vright);
  550. }
  551.  
  552.  
  553.