Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Portions of this file are copyright Rebirth contributors and licensed as
  3.  * described in COPYING.txt.
  4.  * Portions of this file are copyright Parallax Software and licensed
  5.  * according to the Parallax license below.
  6.  * See COPYING.txt for license details.
  7.  
  8. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  9. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  10. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  11. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  12. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  13. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  14. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  15. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  16. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  17. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  18. */
  19.  
  20. /*
  21.  *
  22.  * Flat shader derived from texture mapper (a little slow)
  23.  *
  24.  */
  25.  
  26. #include "maths.h"
  27. #include "vecmat.h"
  28. #include "gr.h"
  29. #include "grdef.h"
  30. #include "texmap.h"
  31. #include "texmapl.h"
  32. #include "scanline.h"
  33.  
  34. #include "compiler-range_for.h"
  35. #include "partial_range.h"
  36.  
  37. //#include "tmapext.h"
  38.  
  39. #if !DXX_USE_OGL
  40. #include "3d.h"
  41. #include "dxxerror.h"
  42.  
  43. #include "3d.h"
  44. #include "dxxerror.h"
  45.  
  46. namespace dcx {
  47.  
  48. static void gr_upoly_tmap_ylr(grs_canvas &, uint_fast32_t nverts, const int *vert, uint8_t color);
  49.  
  50. // -------------------------------------------------------------------------------------
  51. //      Texture map current scanline.
  52. //      Uses globals Du_dx and Dv_dx to incrementally compute u,v coordinates
  53. // -------------------------------------------------------------------------------------
  54. static void tmap_scanline_flat(grs_canvas &canvas, int y, fix xleft, fix xright)
  55. {
  56.         if (xright < xleft)
  57.                 return;
  58.  
  59.         // setup to call assembler scanline renderer
  60.  
  61.         fx_y = y;
  62.         fx_xleft = xleft/F1_0;          // (xleft >> 16) != xleft/F1_0 for negative numbers, f2i caused random crashes
  63.         fx_xright = xright/F1_0;
  64.  
  65.         if (canvas.cv_fade_level >= GR_FADE_OFF)
  66.                 cur_tmap_scanline_flat();
  67.         else    {
  68.                 cur_tmap_scanline_shaded(canvas.cv_fade_level);
  69.         }      
  70. }
  71.  
  72.  
  73. //--unused-- void tmap_scanline_shaded(int y, fix xleft, fix xright)
  74. //--unused-- {
  75. //--unused--    fix     dx;
  76. //--unused--
  77. //--unused--    dx = xright - xleft;
  78. //--unused--
  79. //--unused--    // setup to call assembler scanline renderer
  80. //--unused--
  81. //--unused--    fx_y = y << 16;
  82. //--unused--    fx_xleft = xleft;
  83. //--unused--    fx_xright = xright;
  84. //--unused--
  85. //--unused--    asm_tmap_scanline_shaded();
  86. //--unused-- }
  87.  
  88.  
  89. // -------------------------------------------------------------------------------------
  90. //      Render a texture map.
  91. // Linear in outer loop, linear in inner loop.
  92. // -------------------------------------------------------------------------------------
  93. static void texture_map_flat(grs_canvas &canvas, const g3ds_tmap &t, int color)
  94. {
  95.         int     vlt,vrt,vlb,vrb;        // vertex left top, vertex right top, vertex left bottom, vertex right bottom
  96.         int     topy,boty,dy;
  97.         fix     dx_dy_left,dx_dy_right;
  98.         int     max_y_vertex;
  99.         fix     xleft,xright;
  100.         fix     recip_dy;
  101.         auto &v3d = t.verts;
  102.  
  103.         tmap_flat_color = color;
  104.  
  105.         // Determine top and bottom y coords.
  106.         compute_y_bounds(t,vlt,vlb,vrt,vrb,max_y_vertex);
  107.  
  108.         // Set top and bottom (of entire texture map) y coordinates.
  109.         topy = f2i(v3d[vlt].y2d);
  110.         boty = f2i(v3d[max_y_vertex].y2d);
  111.  
  112.         // Set amount to change x coordinate for each advance to next scanline.
  113.         dy = f2i(t.verts[vlb].y2d) - f2i(t.verts[vlt].y2d);
  114.         recip_dy = fix_recip(dy);
  115.  
  116.         dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
  117.  
  118.         dy = f2i(t.verts[vrb].y2d) - f2i(t.verts[vrt].y2d);
  119.         recip_dy = fix_recip(dy);
  120.  
  121.         dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
  122.  
  123.         // Set initial values for x, u, v
  124.         xleft = v3d[vlt].x2d;
  125.         xright = v3d[vrt].x2d;
  126.  
  127.         // scan all rows in texture map from top through first break.
  128.         // @mk: Should we render the scanline for y==boty?  This violates Matt's spec.
  129.  
  130.         for (int y = topy; y < boty; y++) {
  131.  
  132.                 // See if we have reached the end of the current left edge, and if so, set
  133.                 // new values for dx_dy and x,u,v
  134.                 if (y == f2i(v3d[vlb].y2d)) {
  135.                         // Handle problem of double points.  Search until y coord is different.  Cannot get
  136.                         // hung in an infinite loop because we know there is a vertex with a lower y coordinate
  137.                         // because in the for loop, we don't scan all spanlines.
  138.                         while (y == f2i(v3d[vlb].y2d)) {
  139.                                 vlt = vlb;
  140.                                 vlb = prevmod(vlb,t.nv);
  141.                         }
  142.                         dy = f2i(t.verts[vlb].y2d) - f2i(t.verts[vlt].y2d);
  143.                         recip_dy = fix_recip(dy);
  144.  
  145.                         dx_dy_left = compute_dx_dy(t,vlt,vlb, recip_dy);
  146.  
  147.                         xleft = v3d[vlt].x2d;
  148.                 }
  149.  
  150.                 // See if we have reached the end of the current left edge, and if so, set
  151.                 // new values for dx_dy and x.  Not necessary to set new values for u,v.
  152.                 if (y == f2i(v3d[vrb].y2d)) {
  153.                         while (y == f2i(v3d[vrb].y2d)) {
  154.                                 vrt = vrb;
  155.                                 vrb = succmod(vrb,t.nv);
  156.                         }
  157.  
  158.                         dy = f2i(t.verts[vrb].y2d) - f2i(t.verts[vrt].y2d);
  159.                         recip_dy = fix_recip(dy);
  160.  
  161.                         dx_dy_right = compute_dx_dy(t,vrt,vrb, recip_dy);
  162.  
  163.                         xright = v3d[vrt].x2d;
  164.  
  165.                 }
  166.                 tmap_scanline_flat(canvas, y, xleft, xright);
  167.  
  168.                 xleft += dx_dy_left;
  169.                 xright += dx_dy_right;
  170.  
  171.         }
  172.         tmap_scanline_flat(canvas, boty, xleft, xright);
  173. }
  174.  
  175. //      -----------------------------------------------------------------------------------------
  176. //      This is the gr_upoly-like interface to the texture mapper which uses texture-mapper compatible
  177. //      (ie, avoids cracking) edge/delta computation.
  178. void gr_upoly_tmap(grs_canvas &canvas, uint_fast32_t nverts, const std::array<fix, MAX_POINTS_IN_POLY * 2> &vert, const uint8_t color)
  179. {
  180.         gr_upoly_tmap_ylr(canvas, nverts, vert.data(), color);
  181. }
  182.  
  183. struct pnt2d {
  184.         fix x,y;
  185. };
  186.  
  187. //this takes the same partms as draw_tmap, but draws a flat-shaded polygon
  188. void draw_tmap_flat(grs_canvas &canvas, const grs_bitmap &bp, uint_fast32_t nverts, const g3s_point *const *vertbuf)
  189. {
  190.         union {
  191.                 std::array<pnt2d, MAX_TMAP_VERTS> points;
  192.                 std::array<int, MAX_TMAP_VERTS * (sizeof(pnt2d) / sizeof(int))> ipoints;
  193.         };
  194.         static_assert(sizeof(points) == sizeof(ipoints), "array size mismatch");
  195.         fix     average_light;
  196.         Assert(nverts < MAX_TMAP_VERTS);
  197.         average_light = vertbuf[0]->p3_l;
  198.         for (int i=1; i<nverts; i++)
  199.                 average_light += vertbuf[i]->p3_l;
  200.  
  201.         if (nverts == 4)
  202.                 average_light = f2i(average_light * NUM_LIGHTING_LEVELS/4);
  203.         else
  204.                 average_light = f2i(average_light * NUM_LIGHTING_LEVELS/nverts);
  205.  
  206.         if (average_light < 0)
  207.                 average_light = 0;
  208.         else if (average_light > NUM_LIGHTING_LEVELS-1)
  209.                 average_light = NUM_LIGHTING_LEVELS-1;
  210.  
  211.         color_t color = gr_fade_table[average_light][bp.avg_color];
  212.  
  213.         for (int i=0;i<nverts;i++) {
  214.                 points[i].x = vertbuf[i]->p3_sx;
  215.                 points[i].y = vertbuf[i]->p3_sy;
  216.         }
  217.         gr_upoly_tmap_ylr(canvas, nverts, ipoints.data(), color);
  218. }
  219.  
  220. //      -----------------------------------------------------------------------------------------
  221. //This is like gr_upoly_tmap() but instead of drawing, it calls the specified
  222. //function with ylr values
  223. static void gr_upoly_tmap_ylr(grs_canvas &canvas, uint_fast32_t nverts, const int *vert, const uint8_t color)
  224. {
  225.         g3ds_tmap       my_tmap;
  226.         my_tmap.nv = nverts;
  227.  
  228.         range_for (auto &i, partial_range(my_tmap.verts, nverts))
  229.         {
  230.                 i.x2d = *vert++;
  231.                 i.y2d = *vert++;
  232.         }
  233.         texture_map_flat(canvas, my_tmap, color);
  234. }
  235.  
  236. }
  237. #endif //!OGL
  238.