Advertisement
Guest User

code/graphics/2d.cpp x-style-mouse

a guest
Apr 5th, 2015
244
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 49.00 KB | None | 0 0
  1. /*
  2.  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
  3.  *
  4.  * All source code herein is the property of Volition, Inc. You may not sell
  5.  * or otherwise commercially exploit the source or things you created based on the
  6.  * source.
  7.  *
  8. */
  9.  
  10.  
  11.  
  12. #ifdef _WIN32
  13. #include <windows.h>
  14. #include <windowsx.h>
  15. #endif
  16.  
  17. #include <limits.h>
  18.  
  19. #include "globalincs/pstypes.h"
  20. #include "osapi/osapi.h"
  21. #include "graphics/2d.h"
  22. #include "graphics/grstub.h"
  23. #include "render/3d.h"
  24. #include "bmpman/bmpman.h"
  25. #include "palman/palman.h"
  26. #include "graphics/font.h"
  27. #include "graphics/grinternal.h"
  28. #include "globalincs/systemvars.h"
  29. #include "cmdline/cmdline.h"
  30. #include "graphics/grbatch.h"
  31. #include "parse/scripting.h"
  32. #include "gamesequence/gamesequence.h"  //WMC - for scripting hooks in gr_flip()
  33. #include "io/keycontrol.h" // m!m
  34. #include "debugconsole/console.h"
  35. #include "debugconsole/console.h"
  36.  
  37.  
  38. #if defined(SCP_UNIX) && !defined(__APPLE__)
  39. #if ( SDL_VERSION_ATLEAST(1, 2, 7) )
  40. #include "SDL_cpuinfo.h"
  41. #endif
  42. #endif // SCP_UNIX && !__APPLE__
  43.  
  44. // Includes for different rendering systems
  45. #include "graphics/gropengl.h"
  46.  
  47. const char *Resolution_prefixes[GR_NUM_RESOLUTIONS] = { "", "2_" };
  48.  
  49. screen gr_screen;
  50.  
  51. color_gun Gr_red, Gr_green, Gr_blue, Gr_alpha;
  52. color_gun Gr_t_red, Gr_t_green, Gr_t_blue, Gr_t_alpha;
  53. color_gun Gr_ta_red, Gr_ta_green, Gr_ta_blue, Gr_ta_alpha;
  54. color_gun *Gr_current_red, *Gr_current_green, *Gr_current_blue, *Gr_current_alpha;
  55.  
  56.  
  57. ubyte Gr_original_palette[768];     // The palette
  58. ubyte Gr_current_palette[768];
  59. char Gr_current_palette_name[128] = NOX("none");
  60.  
  61. // cursor stuff
  62. int Gr_cursor = -1;
  63. #ifndef __hanzo_mouseJoy_disable__
  64. int Gr_crosshair = -1;      // hanzo@150402 : crosshair for the mouse control. using 23x23 cursor with centered(11,11) Hot-spot
  65. #endif
  66. int Web_cursor_bitmap = -1;
  67. int Gr_cursor_size = 32;    // default w/h
  68.  
  69. int Gr_inited = 0;
  70.  
  71. uint Gr_signature = 0;
  72.  
  73. float Gr_gamma = 1.8f;
  74. int Gr_gamma_int = 180;
  75.  
  76. // z-buffer stuff
  77. int gr_zbuffering = 0;
  78. int gr_zbuffering_mode = 0;
  79. int gr_global_zbuffering = 0;
  80.  
  81. // stencil buffer stuff
  82. int gr_stencil_mode = 0;
  83.  
  84. // alpha mask stuff
  85. int gr_alpha_test = 0;
  86.  
  87. // Default clipping distances
  88. const float Default_min_draw_distance = 1.0f;
  89. const float Default_max_draw_distance = 1e10;
  90. float Min_draw_distance = Default_min_draw_distance;
  91. float Max_draw_distance = Default_max_draw_distance;
  92.  
  93. static int GL_cursor_nframes = 0;
  94.  
  95. // Pre-computed screen resize vars
  96. static float Gr_full_resize_X = 1.0f, Gr_full_resize_Y = 1.0f;
  97. static float Gr_resize_X = 1.0f, Gr_resize_Y = 1.0f;
  98. static float Gr_menu_offset_X = 0.0f, Gr_menu_offset_Y = 0.0f;
  99. static float Gr_menu_zoomed_offset_X = 0.0f, Gr_menu_zoomed_offset_Y = 0.0f;
  100.  
  101. float Gr_save_full_resize_X = 1.0f, Gr_save_full_resize_Y = 1.0f;
  102. float Gr_save_resize_X = 1.0f, Gr_save_resize_Y = 1.0f;
  103. float Gr_save_menu_offset_X = 0.0f, Gr_save_menu_offset_Y = 0.0f;
  104. float Gr_save_menu_zoomed_offset_X = 0.0f, Gr_save_menu_zoomed_offset_Y = 0.0f;
  105.  
  106. bool Save_custom_screen_size;
  107.  
  108. void gr_set_screen_scale(int w, int h, int zoom_w, int zoom_h, int max_w, int max_h, bool force_stretch)
  109. {
  110.     bool do_zoom = zoom_w > 0 && zoom_h > 0 && (zoom_w != w || zoom_h != h);
  111.  
  112.     Gr_full_resize_X = (float)max_w / (float)w;
  113.     Gr_full_resize_Y = (float)max_h / (float)h;
  114.  
  115.     if (do_zoom) {
  116.         float aspect_quotient = ((float)max_w / (float)max_h) / ((float)zoom_w / (float)zoom_h);
  117.  
  118.         Gr_resize_X = (float)max_w / (float)zoom_w / ((aspect_quotient > 1.0f) ? aspect_quotient : 1.0f);
  119.         Gr_resize_Y = (float)max_h / (float)zoom_h * ((aspect_quotient < 1.0f) ? aspect_quotient : 1.0f);
  120.  
  121.         Gr_menu_offset_X = (max_w - w * Gr_resize_X) / 2.0f;
  122.         Gr_menu_offset_Y = (max_h - h * Gr_resize_Y) / 2.0f;
  123.  
  124.         Gr_menu_zoomed_offset_X = (Gr_menu_offset_X >= 0.0f) ? Gr_menu_offset_X : 0.0f;
  125.         Gr_menu_zoomed_offset_Y = (Gr_menu_offset_Y >= 0.0f) ? Gr_menu_offset_Y : 0.0f;
  126.  
  127.         if (force_stretch || Cmdline_stretch_menu) {
  128.             if (Gr_menu_offset_X > 0.0f) {
  129.                 Gr_resize_X = Gr_full_resize_X;
  130.                 Gr_menu_offset_X = Gr_menu_zoomed_offset_X = 0.0f;
  131.             }
  132.             if (Gr_menu_offset_Y > 0.0f) {
  133.                 Gr_resize_Y = Gr_full_resize_Y;
  134.                 Gr_menu_offset_Y = Gr_menu_zoomed_offset_Y = 0.0f;
  135.             }
  136.         }
  137.     } else {
  138.         if (force_stretch || Cmdline_stretch_menu) {
  139.             Gr_resize_X = Gr_full_resize_X;
  140.             Gr_resize_Y = Gr_full_resize_Y;
  141.  
  142.             Gr_menu_offset_X = Gr_menu_zoomed_offset_X = 0.0f;
  143.             Gr_menu_offset_Y = Gr_menu_zoomed_offset_Y = 0.0f;
  144.         } else {
  145.             float aspect_quotient = ((float)max_w / (float)max_h) / ((float)w / (float)h);
  146.  
  147.             Gr_resize_X = Gr_full_resize_X / ((aspect_quotient > 1.0f) ? aspect_quotient : 1.0f);
  148.             Gr_resize_Y = Gr_full_resize_Y * ((aspect_quotient < 1.0f) ? aspect_quotient : 1.0f);
  149.  
  150.             Gr_menu_offset_X = Gr_menu_zoomed_offset_X = (aspect_quotient > 1.0f) ? ((max_w - w * Gr_resize_X) / 2.0f) : 0.0f;
  151.             Gr_menu_offset_Y = Gr_menu_zoomed_offset_Y = (aspect_quotient < 1.0f) ? ((max_h - h * Gr_resize_Y) / 2.0f) : 0.0f;
  152.         }
  153.     }
  154.  
  155.     gr_screen.custom_size = (w != max_w || h != max_h);
  156.  
  157.     if (gr_screen.rendering_to_texture == -1) {
  158.         gr_screen.max_w_unscaled = w;
  159.         gr_screen.max_h_unscaled = h;
  160.  
  161.         if (do_zoom) {
  162.             gr_screen.max_w_unscaled_zoomed = gr_screen.max_w_unscaled + fl2i(Gr_menu_offset_X * 2.0f / Gr_resize_X);
  163.             gr_screen.max_h_unscaled_zoomed = gr_screen.max_h_unscaled + fl2i(Gr_menu_offset_Y * 2.0f / Gr_resize_Y);
  164.             if (gr_screen.max_w_unscaled_zoomed > gr_screen.max_w_unscaled) {
  165.                 gr_screen.max_w_unscaled_zoomed = gr_screen.max_w_unscaled;
  166.             }
  167.             if (gr_screen.max_h_unscaled_zoomed > gr_screen.max_h_unscaled) {
  168.                 gr_screen.max_h_unscaled_zoomed = gr_screen.max_h_unscaled;
  169.             }
  170.         } else {
  171.             gr_screen.max_w_unscaled_zoomed = gr_screen.max_w_unscaled;
  172.             gr_screen.max_h_unscaled_zoomed = gr_screen.max_h_unscaled;
  173.         }
  174.     }
  175. }
  176.  
  177. void gr_reset_screen_scale()
  178. {
  179.     Gr_full_resize_X = Gr_save_full_resize_X;
  180.     Gr_full_resize_Y = Gr_save_full_resize_Y;
  181.  
  182.     Gr_resize_X = Gr_save_resize_X;
  183.     Gr_resize_Y = Gr_save_resize_Y;
  184.  
  185.     Gr_menu_offset_X = Gr_save_menu_offset_X;
  186.     Gr_menu_offset_Y = Gr_save_menu_offset_Y;
  187.  
  188.     Gr_menu_zoomed_offset_X = Gr_save_menu_zoomed_offset_X;
  189.     Gr_menu_zoomed_offset_Y = Gr_save_menu_zoomed_offset_Y;
  190.  
  191.     gr_screen.custom_size = Save_custom_screen_size;
  192.  
  193.     if (gr_screen.rendering_to_texture == -1) {
  194.         gr_screen.max_w_unscaled = gr_screen.max_w_unscaled_zoomed = (gr_screen.res == GR_1024) ? 1024 : 640;
  195.         gr_screen.max_h_unscaled = gr_screen.max_h_unscaled_zoomed = (gr_screen.res == GR_1024) ?  768 : 480;
  196.     }
  197. }
  198.  
  199. /**
  200.  * This function is to be called if you wish to scale GR_1024 or GR_640 x and y positions or
  201.  * lengths in order to keep the correctly scaled to nonstandard resolutions
  202.  *
  203.  * @param x X value, can be NULL
  204.  * @param y Y value, can be NULL
  205.  * @param w width, can be NULL
  206.  * @param h height, can be NULL
  207.  * @param resize_mode
  208.  * @return always true unless error
  209.  */
  210. bool gr_resize_screen_pos(int *x, int *y, int *w, int *h, int resize_mode)
  211. {
  212.     if ( resize_mode == GR_RESIZE_NONE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
  213.         return false;
  214.     }
  215.  
  216.     float xy_tmp = 0.0f;
  217.  
  218.     if ( x ) {
  219.         switch (resize_mode) {
  220.         case GR_RESIZE_FULL:
  221.             xy_tmp = (*x) * Gr_full_resize_X;
  222.             break;
  223.  
  224.         case GR_RESIZE_MENU:
  225.             xy_tmp = (*x) * Gr_resize_X + Gr_menu_offset_X;
  226.             break;
  227.  
  228.         case GR_RESIZE_MENU_ZOOMED:
  229.             xy_tmp = (*x) * Gr_resize_X + Gr_menu_zoomed_offset_X;
  230.             break;
  231.  
  232.         case GR_RESIZE_MENU_NO_OFFSET:
  233.             xy_tmp = (*x) * Gr_resize_X;
  234.             break;
  235.         }
  236.         (*x) = fl2ir(xy_tmp);
  237.     }
  238.  
  239.     if ( y ) {
  240.         switch (resize_mode) {
  241.         case GR_RESIZE_FULL:
  242.             xy_tmp = (*y) * Gr_full_resize_Y;
  243.             break;
  244.  
  245.         case GR_RESIZE_MENU:
  246.             xy_tmp = (*y) * Gr_resize_Y + Gr_menu_offset_Y;
  247.             break;
  248.  
  249.         case GR_RESIZE_MENU_ZOOMED:
  250.             xy_tmp = (*y) * Gr_resize_Y + Gr_menu_zoomed_offset_Y;
  251.             break;
  252.  
  253.         case GR_RESIZE_MENU_NO_OFFSET:
  254.             xy_tmp = (*y) * Gr_resize_Y;
  255.             break;
  256.         }
  257.         (*y) = fl2ir(xy_tmp);
  258.     }
  259.  
  260.     if ( w ) {
  261.         xy_tmp = (*w) * ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_X : Gr_resize_X);
  262.         (*w) = fl2ir(xy_tmp);
  263.     }
  264.  
  265.     if ( h ) {
  266.         xy_tmp = (*h) * ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_Y : Gr_resize_Y);
  267.         (*h) = fl2ir(xy_tmp);
  268.     }
  269.  
  270.     return true;
  271. }
  272.  
  273. /**
  274.  *
  275.  * @param x X value, can be NULL
  276.  * @param y Y value, can be NULL
  277.  * @param w width, can be NULL
  278.  * @param h height, can be NULL
  279.  * @param resize_mode
  280.  * @return always true unless error
  281.  */
  282. bool gr_unsize_screen_pos(int *x, int *y, int *w, int *h, int resize_mode)
  283. {
  284.     if ( resize_mode == GR_RESIZE_NONE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
  285.         return false;
  286.     }
  287.  
  288.     float xy_tmp = 0.0f;
  289.  
  290.     if ( x ) {
  291.         switch (resize_mode) {
  292.         case GR_RESIZE_FULL:
  293.             xy_tmp = (*x) / Gr_full_resize_X;
  294.             break;
  295.  
  296.         case GR_RESIZE_MENU:
  297.             xy_tmp = ((*x) - Gr_menu_offset_X) / Gr_resize_X;
  298.             break;
  299.  
  300.         case GR_RESIZE_MENU_ZOOMED:
  301.             xy_tmp = ((*x) - Gr_menu_zoomed_offset_X) / Gr_resize_X;
  302.             break;
  303.  
  304.         case GR_RESIZE_MENU_NO_OFFSET:
  305.             xy_tmp = (*x) / Gr_resize_X;
  306.             break;
  307.         }
  308.         (*x) = fl2ir(xy_tmp);
  309.     }
  310.  
  311.     if ( y ) {
  312.         switch (resize_mode) {
  313.         case GR_RESIZE_FULL:
  314.             xy_tmp = (*y) / Gr_full_resize_Y;
  315.             break;
  316.  
  317.         case GR_RESIZE_MENU:
  318.             xy_tmp = ((*y) - Gr_menu_offset_Y) / Gr_resize_Y;
  319.             break;
  320.  
  321.         case GR_RESIZE_MENU_ZOOMED:
  322.             xy_tmp = ((*y) - Gr_menu_zoomed_offset_Y) / Gr_resize_Y;
  323.             break;
  324.  
  325.         case GR_RESIZE_MENU_NO_OFFSET:
  326.             xy_tmp = (*y) / Gr_resize_Y;
  327.             break;
  328.         }
  329.         (*y) = fl2ir(xy_tmp);
  330.     }
  331.  
  332.     if ( w ) {
  333.         xy_tmp = (*w) / ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_X : Gr_resize_X);
  334.         (*w) = fl2ir(xy_tmp);
  335.     }
  336.  
  337.     if ( h ) {
  338.         xy_tmp = (*h) / ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_Y : Gr_resize_Y);
  339.         (*h) = fl2ir(xy_tmp);
  340.     }
  341.  
  342.     return true;
  343. }
  344.  
  345. /**
  346.  * This function is to be called if you wish to scale GR_1024 or GR_640 x and y positions or
  347.  * lengths in order to keep the correctly scaled to nonstandard resolutions
  348.  *
  349.  * @param x X value, can be NULL
  350.  * @param y Y value, can be NULL
  351.  * @param w width, can be NULL
  352.  * @param h height, can be NULL
  353.  * @param resize_mode
  354.  * @return always true unless error
  355.  */
  356. bool gr_resize_screen_posf(float *x, float *y, float *w, float *h, int resize_mode)
  357. {
  358.     if ( resize_mode == GR_RESIZE_NONE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
  359.         return false;
  360.     }
  361.  
  362.     float xy_tmp = 0.0f;
  363.  
  364.     if ( x ) {
  365.         switch (resize_mode) {
  366.         case GR_RESIZE_FULL:
  367.             xy_tmp = (*x) * Gr_full_resize_X;
  368.             break;
  369.  
  370.         case GR_RESIZE_MENU:
  371.             xy_tmp = (*x) * Gr_resize_X + Gr_menu_offset_X;
  372.             break;
  373.  
  374.         case GR_RESIZE_MENU_ZOOMED:
  375.             xy_tmp = (*x) * Gr_resize_X + Gr_menu_zoomed_offset_X;
  376.             break;
  377.  
  378.         case GR_RESIZE_MENU_NO_OFFSET:
  379.             xy_tmp = (*x) * Gr_resize_X;
  380.             break;
  381.         }
  382.         (*x) = xy_tmp;
  383.     }
  384.  
  385.     if ( y ) {
  386.         switch (resize_mode) {
  387.         case GR_RESIZE_FULL:
  388.             xy_tmp = (*y) * Gr_full_resize_Y;
  389.             break;
  390.  
  391.         case GR_RESIZE_MENU:
  392.             xy_tmp = (*y) * Gr_resize_Y + Gr_menu_offset_Y;
  393.             break;
  394.  
  395.         case GR_RESIZE_MENU_ZOOMED:
  396.             xy_tmp = (*y) * Gr_resize_Y + Gr_menu_zoomed_offset_Y;
  397.             break;
  398.  
  399.         case GR_RESIZE_MENU_NO_OFFSET:
  400.             xy_tmp = (*y) * Gr_resize_Y;
  401.             break;
  402.         }
  403.         (*y) = xy_tmp;
  404.     }
  405.  
  406.     if ( w ) {
  407.         xy_tmp = (*w) * ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_X : Gr_resize_X);
  408.         (*w) = xy_tmp;
  409.     }
  410.  
  411.     if ( h ) {
  412.         xy_tmp = (*h) * ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_Y : Gr_resize_Y);
  413.         (*h) = xy_tmp;
  414.     }
  415.  
  416.     return true;
  417. }
  418.  
  419. /**
  420.  *
  421.  * @param x X value, can be NULL
  422.  * @param y Y value, can be NULL
  423.  * @param w width, can be NULL
  424.  * @param h height, can be NULL
  425.  * @param resize_mode
  426.  * @return always true unless error
  427.  */
  428. bool gr_unsize_screen_posf(float *x, float *y, float *w, float *h, int resize_mode)
  429. {
  430.     if ( resize_mode == GR_RESIZE_NONE || (!gr_screen.custom_size && (gr_screen.rendering_to_texture == -1)) ) {
  431.         return false;
  432.     }
  433.  
  434.     float xy_tmp = 0.0f;
  435.  
  436.     if ( x ) {
  437.         switch (resize_mode) {
  438.         case GR_RESIZE_FULL:
  439.             xy_tmp = (*x) / Gr_full_resize_X;
  440.             break;
  441.  
  442.         case GR_RESIZE_MENU:
  443.             xy_tmp = ((*x) - Gr_menu_offset_X) / Gr_resize_X;
  444.             break;
  445.  
  446.         case GR_RESIZE_MENU_ZOOMED:
  447.             xy_tmp = ((*x) - Gr_menu_zoomed_offset_X) / Gr_resize_X;
  448.             break;
  449.  
  450.         case GR_RESIZE_MENU_NO_OFFSET:
  451.             xy_tmp = (*x) / Gr_resize_X;
  452.             break;
  453.         }
  454.         (*x) = xy_tmp;
  455.     }
  456.  
  457.     if ( y ) {
  458.         switch (resize_mode) {
  459.         case GR_RESIZE_FULL:
  460.             xy_tmp = (*y) / Gr_full_resize_Y;
  461.             break;
  462.  
  463.         case GR_RESIZE_MENU:
  464.             xy_tmp = ((*y) - Gr_menu_offset_Y) / Gr_resize_Y;
  465.             break;
  466.  
  467.         case GR_RESIZE_MENU_ZOOMED:
  468.             xy_tmp = ((*y) - Gr_menu_zoomed_offset_Y) / Gr_resize_Y;
  469.             break;
  470.  
  471.         case GR_RESIZE_MENU_NO_OFFSET:
  472.             xy_tmp = (*y) / Gr_resize_Y;
  473.             break;
  474.         }
  475.         (*y) = xy_tmp;
  476.     }
  477.  
  478.     if ( w ) {
  479.         xy_tmp = (*w) / ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_X : Gr_resize_X);
  480.         (*w) = xy_tmp;
  481.     }
  482.  
  483.     if ( h ) {
  484.         xy_tmp = (*h) / ((resize_mode == GR_RESIZE_FULL) ? Gr_full_resize_Y : Gr_resize_Y);
  485.         (*h) = xy_tmp;
  486.     }
  487.  
  488.     return true;
  489. }
  490.  
  491. void gr_close()
  492. {
  493.     if ( !Gr_inited ) {
  494.         return;
  495.     }
  496.  
  497.     palette_flush();
  498.  
  499.     switch (gr_screen.mode) {
  500.         case GR_OPENGL:
  501.             gr_opengl_cleanup();
  502.             break;
  503.    
  504.         case GR_STUB:
  505.             break;
  506.    
  507.         default:
  508.             Int3();     // Invalid graphics mode
  509.     }
  510.  
  511.     gr_font_close();
  512.  
  513.     Gr_inited = 0;
  514. }
  515.  
  516.  
  517. /**
  518.  * Set screen clear color
  519.  */
  520. DCF(clear_color, "set clear color r, g, b")
  521. {
  522.     ubyte r, g, b;
  523.  
  524.     dc_stuff_ubyte(&r);
  525.     dc_stuff_ubyte(&g);
  526.     dc_stuff_ubyte(&b);
  527.  
  528.     // set the color
  529.     gr_set_clear_color(r, g, b);
  530. }
  531.  
  532. void gr_set_palette_internal( const char *name, ubyte * palette, int restrict_font_to_128 )
  533. {
  534.     if ( palette == NULL ) {
  535.         // Create a default palette
  536.         int r,g,b,i;
  537.         i = 0;
  538.  
  539.         for (r=0; r<6; r++ )
  540.             for (g=0; g<6; g++ )
  541.                 for (b=0; b<6; b++ ) {
  542.                     Gr_current_palette[i*3+0] = (unsigned char)(r*51);
  543.                     Gr_current_palette[i*3+1] = (unsigned char)(g*51);
  544.                     Gr_current_palette[i*3+2] = (unsigned char)(b*51);
  545.                     i++;
  546.                 }
  547.         for ( i=216;i<256; i++ ) {
  548.             Gr_current_palette[i*3+0] = (unsigned char)((i-216)*6);
  549.             Gr_current_palette[i*3+1] = (unsigned char)((i-216)*6);
  550.             Gr_current_palette[i*3+2] = (unsigned char)((i-216)*6);
  551.         }
  552.         memmove( Gr_original_palette, Gr_current_palette, 768 );
  553.     } else {
  554.         memmove( Gr_original_palette, palette, 768 );
  555.         memmove( Gr_current_palette, palette, 768 );
  556.     }
  557.  
  558.     if ( Gr_inited ) {
  559.         if (gr_screen.gf_set_palette) {
  560.             (*gr_screen.gf_set_palette)(Gr_current_palette, restrict_font_to_128 );
  561.  
  562.             // Since the palette set code might shuffle the palette,
  563.             // reload it into the source palette
  564.             if ( palette ) {
  565.                 memmove( palette, Gr_current_palette, 768 );
  566.             }
  567.         }
  568.  
  569.         // Update Palette Manager tables
  570.         memmove( gr_palette, Gr_current_palette, 768 );
  571.         palette_update(name, restrict_font_to_128);
  572.     }
  573. }
  574.  
  575.  
  576. void gr_set_palette( const char *name, ubyte * palette, int restrict_font_to_128 )
  577. {
  578.     char *p;
  579.     palette_flush();
  580.     strcpy_s( Gr_current_palette_name, name );
  581.     p = strchr( Gr_current_palette_name, '.' );
  582.     if ( p ) *p = 0;
  583.     gr_screen.signature = Gr_signature++;
  584.     gr_set_palette_internal( name, palette, restrict_font_to_128 );
  585. }
  586.  
  587. void gr_screen_resize(int width, int height)
  588. {
  589.     // this should only be called from FRED!!
  590.     if ( !Fred_running ) {
  591.         Int3();
  592.         return;
  593.     }
  594.  
  595.     gr_screen.save_max_w = gr_screen.max_w = gr_screen.max_w_unscaled = gr_screen.max_w_unscaled_zoomed = width;
  596.     gr_screen.save_max_h = gr_screen.max_h = gr_screen.max_h_unscaled = gr_screen.max_h_unscaled_zoomed = height;
  597.  
  598.     gr_screen.offset_x = gr_screen.offset_x_unscaled = 0;
  599.     gr_screen.offset_y = gr_screen.offset_y_unscaled = 0;
  600.  
  601.     gr_screen.clip_left = gr_screen.clip_left_unscaled = 0;
  602.     gr_screen.clip_top = gr_screen.clip_top_unscaled = 0;
  603.     gr_screen.clip_right = gr_screen.clip_right_unscaled = gr_screen.max_w - 1;
  604.     gr_screen.clip_bottom = gr_screen.clip_bottom_unscaled = gr_screen.max_h - 1;
  605.     gr_screen.clip_width = gr_screen.clip_width_unscaled = gr_screen.max_w;
  606.     gr_screen.clip_height = gr_screen.clip_height_unscaled = gr_screen.max_h;
  607.     gr_screen.clip_aspect = i2fl(gr_screen.clip_width) / i2fl(gr_screen.clip_height);
  608.  
  609.     if (gr_screen.custom_size) {
  610.         gr_unsize_screen_pos( &gr_screen.max_w_unscaled, &gr_screen.max_h_unscaled );
  611.         gr_unsize_screen_pos( &gr_screen.max_w_unscaled_zoomed, &gr_screen.max_h_unscaled_zoomed );
  612.         gr_unsize_screen_pos( &gr_screen.clip_right_unscaled, &gr_screen.clip_bottom_unscaled );
  613.         gr_unsize_screen_pos( &gr_screen.clip_width_unscaled, &gr_screen.clip_height_unscaled );
  614.     }
  615.  
  616.     gr_screen.save_max_w_unscaled = gr_screen.max_w_unscaled;
  617.     gr_screen.save_max_h_unscaled = gr_screen.max_h_unscaled;
  618.     gr_screen.save_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed;
  619.     gr_screen.save_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed;
  620.  
  621.     if (gr_screen.mode == GR_OPENGL) {
  622.         extern void opengl_setup_viewport();
  623.         opengl_setup_viewport();
  624.     }
  625. }
  626.  
  627. static bool gr_init_sub(int mode, int width, int height, int depth)
  628. {
  629.     int res = GR_1024;
  630.     bool rc = false;
  631.  
  632.     memset( &gr_screen, 0, sizeof(screen) );
  633.  
  634.     if ( ((width == 640) && (height == 480)) || ((width == 1024) && (height == 768)) ) {
  635.         gr_screen.custom_size = false;
  636.     } else {
  637.         gr_screen.custom_size = true;
  638.     }
  639.  
  640.     if ( (width >= GR_1024_THRESHOLD_WIDTH) && (height >= GR_1024_THRESHOLD_HEIGHT) ) {
  641.         res = GR_1024;
  642.     } else {
  643.         res = GR_640;
  644.     }
  645.  
  646.     if (Fred_running) {
  647.         gr_screen.custom_size = false;
  648.         res = GR_640;
  649.         mode = GR_OPENGL;
  650.     }
  651.  
  652.     Save_custom_screen_size = gr_screen.custom_size;
  653.  
  654.     Gr_save_full_resize_X = Gr_full_resize_X = (float)width / ((res == GR_1024) ? 1024.0f : 640.0f);
  655.     Gr_save_full_resize_Y = Gr_full_resize_Y = (float)height / ((res == GR_1024) ?  768.0f : 480.0f);
  656.  
  657.     if (gr_screen.custom_size && !Cmdline_stretch_menu) {
  658.         float aspect_quotient = ((float)width / (float)height) / (4.0f / 3.0f);
  659.  
  660.         Gr_save_resize_X = Gr_resize_X = Gr_full_resize_X / ((aspect_quotient > 1.0f) ? aspect_quotient : 1.0f);
  661.         Gr_save_resize_Y = Gr_resize_Y = Gr_full_resize_Y * ((aspect_quotient < 1.0f) ? aspect_quotient : 1.0f);
  662.  
  663.         Gr_save_menu_offset_X = Gr_menu_offset_X = (aspect_quotient > 1.0f) ? ((width - width / aspect_quotient) / 2.0f) : 0.0f;
  664.         Gr_save_menu_offset_Y = Gr_menu_offset_Y = (aspect_quotient < 1.0f) ? ((height - height * aspect_quotient) / 2.0f) : 0.0f;
  665.     } else {
  666.         Gr_save_resize_X = Gr_resize_X = Gr_full_resize_X;
  667.         Gr_save_resize_Y = Gr_resize_Y = Gr_full_resize_Y;
  668.  
  669.         Gr_save_menu_offset_X = Gr_menu_offset_X = 0.0f;
  670.         Gr_save_menu_offset_Y = Gr_menu_offset_Y = 0.0f;
  671.     }
  672.  
  673.     Gr_save_menu_zoomed_offset_X = Gr_menu_zoomed_offset_X = Gr_menu_offset_X;
  674.     Gr_save_menu_zoomed_offset_Y = Gr_menu_zoomed_offset_Y = Gr_menu_offset_Y;
  675.    
  676.  
  677.     gr_screen.signature = Gr_signature++;
  678.     gr_screen.bits_per_pixel = depth;
  679.     gr_screen.bytes_per_pixel= depth / 8;
  680.     gr_screen.rendering_to_texture = -1;
  681.     gr_screen.recording_state_block = false;
  682.     gr_screen.envmap_render_target = -1;
  683.     gr_screen.mode = mode;
  684.     gr_screen.res = res;
  685.     gr_screen.aspect = 1.0f;            // Normal PC screen
  686.  
  687.     gr_screen.save_max_w = gr_screen.max_w = gr_screen.max_w_unscaled = gr_screen.max_w_unscaled_zoomed = width;
  688.     gr_screen.save_max_h = gr_screen.max_h = gr_screen.max_h_unscaled = gr_screen.max_h_unscaled_zoomed = height;
  689.  
  690.     gr_screen.offset_x = gr_screen.offset_x_unscaled = 0;
  691.     gr_screen.offset_y = gr_screen.offset_y_unscaled = 0;
  692.  
  693.     gr_screen.clip_left = gr_screen.clip_left_unscaled = 0;
  694.     gr_screen.clip_top = gr_screen.clip_top_unscaled = 0;
  695.     gr_screen.clip_right = gr_screen.clip_right_unscaled = gr_screen.max_w - 1;
  696.     gr_screen.clip_bottom = gr_screen.clip_bottom_unscaled = gr_screen.max_h - 1;
  697.     gr_screen.clip_width = gr_screen.clip_width_unscaled = gr_screen.max_w;
  698.     gr_screen.clip_height = gr_screen.clip_height_unscaled = gr_screen.max_h;
  699.     gr_screen.clip_aspect = i2fl(gr_screen.clip_width) / i2fl(gr_screen.clip_height);
  700.     gr_screen.clip_center_x = (gr_screen.clip_left + gr_screen.clip_right) * 0.5f;
  701.     gr_screen.clip_center_y = (gr_screen.clip_top + gr_screen.clip_bottom) * 0.5f;
  702.  
  703.     if (gr_screen.custom_size) {
  704.         gr_unsize_screen_pos( &gr_screen.max_w_unscaled, &gr_screen.max_h_unscaled );
  705.         gr_unsize_screen_pos( &gr_screen.max_w_unscaled_zoomed, &gr_screen.max_h_unscaled_zoomed );
  706.         gr_unsize_screen_pos( &gr_screen.clip_right_unscaled, &gr_screen.clip_bottom_unscaled );
  707.         gr_unsize_screen_pos( &gr_screen.clip_width_unscaled, &gr_screen.clip_height_unscaled );
  708.     }
  709.  
  710.     gr_screen.save_max_w_unscaled = gr_screen.max_w_unscaled;
  711.     gr_screen.save_max_h_unscaled = gr_screen.max_h_unscaled;
  712.     gr_screen.save_max_w_unscaled_zoomed = gr_screen.max_w_unscaled_zoomed;
  713.     gr_screen.save_max_h_unscaled_zoomed = gr_screen.max_h_unscaled_zoomed;
  714.  
  715. #ifdef WIN32
  716.     // FRED doesn't need this
  717.     if ( !Fred_running && !Is_standalone ) {
  718.         // for Windows, we need to do this just before the *_init() calls
  719.         extern void win32_create_window(int width, int height);
  720.         win32_create_window( width, height );
  721.     }
  722. #endif
  723.  
  724.     switch (mode) {
  725.         case GR_OPENGL:
  726.             rc = gr_opengl_init();
  727.             break;
  728.         case GR_STUB:
  729.             rc = gr_stub_init();
  730.             break;
  731.         default:
  732.             Int3();     // Invalid graphics mode
  733.     }
  734.  
  735.     if ( !rc ) {
  736.         return false;
  737.     }
  738.  
  739.     return true;
  740. }
  741.  
  742. bool gr_init(int d_mode, int d_width, int d_height, int d_depth)
  743. {
  744.     int width = 1024, height = 768, depth = 32, mode = GR_OPENGL;
  745.     const char *ptr = NULL;
  746.     const char *Default_video_settings = "OGL -(1024x768)x32 bit";
  747.  
  748.     if ( !Gr_inited ) {
  749.         atexit(gr_close);
  750.     }
  751.  
  752.     // If already inited, shutdown the previous graphics
  753.     if (Gr_inited) {
  754.         switch (gr_screen.mode) {
  755.             case GR_OPENGL:
  756.                 gr_opengl_cleanup();
  757.                 break;
  758.            
  759.             case GR_STUB:
  760.                 break;
  761.    
  762.             default:
  763.                 Int3();     // Invalid graphics mode
  764.         }
  765.     }
  766.  
  767.     // We cannot continue without this, quit, but try to help the user out first
  768.     ptr = os_config_read_string(NULL, NOX("VideocardFs2open"), NULL);
  769.  
  770.     // if we don't have a config string then construct one, using OpenGL 1024x768 32-bit as the default
  771.     if (ptr == NULL) {
  772.         ptr = Default_video_settings;
  773.     }
  774.  
  775.     Assert( ptr != NULL );
  776.  
  777.     // NOTE: The "ptr+5" is to skip over the initial "????-" in the video string.
  778.     //       If the format of that string changes you'll have to change this too!!!
  779.     if ( sscanf(ptr+5, "(%dx%d)x%d ", &width, &height, &depth) != 3 ) {
  780.         Error(LOCATION, "Can't understand 'VideocardFs2open' config entry!");
  781.     }
  782.  
  783.     if (Cmdline_res != NULL) {
  784.         int tmp_width = 0;
  785.         int tmp_height = 0;
  786.  
  787.         if ( sscanf(Cmdline_res, "%dx%d", &tmp_width, &tmp_height) == 2 ) {
  788.             width = tmp_width;
  789.             height = tmp_height;
  790.         }
  791.     }
  792.  
  793.     if (d_mode == GR_DEFAULT) {
  794.         // OpenGL should be default
  795.         mode = GR_OPENGL;
  796.     } else {
  797.         mode = d_mode;
  798.     }
  799.  
  800.     // see if we passed good values, and use those instead of the config settings
  801.     if ( (d_width != GR_DEFAULT) && (d_height != GR_DEFAULT) ) {
  802.         width = d_width;
  803.         height = d_height;
  804.     }
  805.  
  806.     if (d_depth != GR_DEFAULT) {
  807.         depth = d_depth;
  808.     }
  809.  
  810.     // check for hi-res interface files so that we can verify our width/height is correct
  811.     bool has_sparky_hi = (cf_exists_full("2_ChoosePilot-m.pcx", CF_TYPE_ANY) && cf_exists_full("2_TechShipData-m.pcx", CF_TYPE_ANY));
  812.  
  813.     // if we don't have it then fall back to 640x480 mode instead
  814.     if ( !has_sparky_hi ) {
  815.         if ( (width == 1024) && (height == 768) ) {
  816.             width = 640;
  817.             height = 480;
  818.         } else {
  819.             width = 800;
  820.             height = 600;
  821.         }
  822.     }
  823.  
  824.     // if we are in standalone mode then just use special defaults
  825.     if (Is_standalone) {
  826.         mode = GR_STUB;
  827.         width = 640;
  828.         height = 480;
  829.         depth = 16;
  830.     }
  831.  
  832. // These compiler macros will force windowed mode at the specified resolution if
  833. // built in debug mode.  This helps if you run with the debugger active as the
  834. // game won't be switching from fullscreen to minimized every time you hit a breakpoint or
  835. // warning message.
  836. #ifdef _DEBUG
  837. #ifdef _FORCE_DEBUG_WIDESCREEN
  838.     width = 1280;
  839.     height = 800;
  840.     depth = 32;
  841.     Cmdline_window = 1;
  842. #elif defined(_FORCE_DEBUG_1024)
  843.     width = 1024;
  844.     height = 768;
  845.     depth = 32;
  846.     Cmdline_window = 1;
  847. #elif defined(_FORCE_DEBUG_640)
  848.     width = 640;
  849.     height = 480;
  850.     depth = 32;
  851.     Cmdline_window = 1;
  852. #endif
  853. #endif
  854.  
  855.     // now try to actually init everything...
  856.     if ( gr_init_sub(mode, width, height, depth) == false ) {
  857.         return false;
  858.     }
  859.  
  860.     gr_set_palette_internal(Gr_current_palette_name, NULL, 0);
  861.  
  862.     bm_init();
  863.  
  864.     if (Gr_cursor < 0) {
  865.         int w, h;
  866.  
  867. //=======================####### BLOCK BEGIN  by hanzo@150402
  868. #ifndef __hanzo_mouseJoy_disable__
  869.     {
  870. // implemented in playercontrol.cpp
  871. extern float g_fMjoyMaxRad__;
  872. extern float g_fMjoyDeadZn__;
  873. extern float g_fMjoyFactor__;
  874. extern float g_fMjoyCriArea_;
  875.       float fMaxRadLim = (float)( (width>height) ? height : width );
  876.       char sztmp[512];
  877.  
  878.         fMaxRadLim = floor( (fMaxRadLim*0.975f) / 2.0f );
  879.  
  880.         ptr = os_config_read_string( NOX("MjoyCfg"), NOX("MaxRad") );
  881.         if( ptr ) { g_fMjoyMaxRad__ = (float)atof( ptr ); if( (g_fMjoyMaxRad__ > fMaxRadLim) || (g_fMjoyMaxRad__ < 150.0f ) ) { ptr = NULL; } }  // 150 <= maxRad <= fMaxRadLim
  882.         if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("MaxRad"), itoa((int)fMaxRadLim, sztmp, 10 ) ); g_fMjoyMaxRad__ = fMaxRadLim; }
  883.  
  884.         ptr = os_config_read_string( NOX("MjoyCfg"), NOX("DeadZone") );
  885.         if( ptr ) { g_fMjoyDeadZn__ = (float)atof( ptr ); if( (g_fMjoyDeadZn__ >= (g_fMjoyMaxRad__/2.0f)) || (g_fMjoyDeadZn__ < 30.0f) ) { ptr = NULL; } } // 30.0f <= deadZone < (maxRad/2)
  886.         if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("DeadZone"), "56.0" ); g_fMjoyDeadZn__ = 56.0f; }
  887.  
  888.         ptr = os_config_read_string( NOX("MjoyCfg"), NOX("SensitivityFactor") );
  889.         if( ptr ) { g_fMjoyFactor__ = (float)atof( ptr ); if( (g_fMjoyFactor__ >= 1.0f) || (g_fMjoyFactor__ < 0.02f) ) { ptr = NULL; } } // 0.02 <= Factor < 1.0
  890.         if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("SensitivityFactor"), "0.075" ); g_fMjoyFactor__ = 0.075f; }
  891.  
  892.         ptr = os_config_read_string( NOX("MjoyCfg"), NOX("CriticalArea") );
  893.         if( ptr ) { g_fMjoyCriArea_ = (float)atof( ptr ); if( (g_fMjoyCriArea_ >= 0.98f) || (g_fMjoyCriArea_ < 0.7f) ) { ptr = NULL; } } // 0.7 <= CritArea < 0.98
  894.         if( !ptr ) { os_config_write_string( NOX("MjoyCfg"), NOX("CriticalArea"), "0.925" ); g_fMjoyCriArea_ = 0.925f; }
  895.  
  896.         Gr_crosshair = bm_load( "xhair23" ); // hanzo@150402 : crosshair for the mouse control
  897.     }
  898. #endif
  899. //=======================####### BLOCK END
  900.  
  901.         Gr_cursor = bm_load( "cursor" );
  902.  
  903.         if (Gr_cursor >= 0) {
  904.             // get cursor size, so that we can be sure to account for the full thing
  905.             // in later cursor hiding code
  906.             bm_get_info(Gr_cursor, &w, &h);
  907.             Gr_cursor_size = MAX(w, h);
  908.  
  909.             if (Gr_cursor_size <= 0) {
  910.                 Int3();
  911.                 Gr_cursor_size = 32;
  912.             }
  913.         }
  914.     }
  915.  
  916.     // load the web pointer cursor bitmap
  917.     if (Web_cursor_bitmap < 0) {
  918.         //if it still hasn't loaded then this usually means that the executable isn't in the same directory as the main fs2 install
  919.         if ( (Web_cursor_bitmap = bm_load_animation("cursorweb")) < 0 ) {
  920.             Error(LOCATION, "\nWeb cursor bitmap not found.  This is most likely due to one of three reasons:\n"
  921.                 "\t1) You're running FreeSpace Open from somewhere other than your FreeSpace 2 folder;\n"
  922.                 "\t2) You've somehow corrupted your FreeSpace 2 installation, e.g. by modifying or removing the retail VP files;\n"
  923.                 "\t3) You haven't installed FreeSpace 2 at all.  (Note that installing FreeSpace Open does NOT remove the need for a FreeSpace 2 installation.)\n"
  924.                 "Number 1 can be fixed by simply moving the FreeSpace Open executable file to the FreeSpace 2 folder.  Numbers 2 and 3 can be fixed by installing or reinstalling FreeSpace 2.\n");
  925.         }
  926.     }
  927.  
  928.     mprintf(("GRAPHICS: Initializing default colors...\n"));
  929.  
  930.     gr_set_color(0,0,0);
  931.     gr_set_clear_color(0, 0, 0);
  932.  
  933.     gr_set_shader(NULL);
  934.  
  935.     os_set_title(Osreg_title);
  936.  
  937.     Gr_inited = 1;
  938.  
  939.     return true;
  940. }
  941.  
  942. void gr_force_windowed()
  943. {
  944.     if ( !Gr_inited ) {
  945.         return;
  946.     }
  947.  
  948.     switch( gr_screen.mode ) {
  949.         case GR_OPENGL:
  950.             break;
  951.         case GR_STUB:
  952.             break;
  953.         default:
  954.             Int3();     // Invalid graphics mode
  955.     }
  956.  
  957.     if ( Os_debugger_running ) {
  958.         Sleep(1000);
  959.     }
  960. }
  961.  
  962. int gr_activated = 0;
  963. void gr_activate(int active)
  964. {
  965.  
  966.     if (gr_activated == active) {
  967.         return;
  968.     }
  969.     gr_activated = active;
  970.  
  971.     if ( !Gr_inited ) {
  972.         return;
  973.     }
  974.  
  975.     switch( gr_screen.mode ) {
  976.         case GR_OPENGL:
  977.             extern void gr_opengl_activate(int active);
  978.             gr_opengl_activate(active);
  979.             break;
  980.         case GR_STUB:
  981.             break;
  982.         default:
  983.             Int3();     // Invalid graphics mode
  984.     }
  985.  
  986. }
  987.  
  988. // color stuff
  989. void gr_get_color( int *r, int *g, int *b )
  990. {
  991.     if (r) *r = gr_screen.current_color.red;
  992.     if (g) *g = gr_screen.current_color.green;
  993.     if (b) *b = gr_screen.current_color.blue;
  994. }
  995.  
  996. void gr_init_color(color *c, int r, int g, int b)
  997. {
  998.     CAP(r, 0, 255);
  999.     CAP(g, 0, 255);
  1000.     CAP(b, 0, 255);
  1001.  
  1002.     c->screen_sig = gr_screen.signature;
  1003.     c->red = (ubyte)r;
  1004.     c->green = (ubyte)g;
  1005.     c->blue = (ubyte)b;
  1006.     c->alpha = 255;
  1007.     c->ac_type = AC_TYPE_NONE;
  1008.     c->alphacolor = -1;
  1009.     c->is_alphacolor = 0;
  1010.     c->magic = 0xAC01;
  1011.     c->raw8 = 0;
  1012. }
  1013.  
  1014. void gr_init_alphacolor( color *clr, int r, int g, int b, int alpha, int type )
  1015. {
  1016.     CAP(r, 0, 255);
  1017.     CAP(g, 0, 255);
  1018.     CAP(b, 0, 255);
  1019.     CAP(alpha, 0, 255);
  1020.  
  1021.     gr_init_color( clr, r, g, b );
  1022.  
  1023.     clr->alpha = (ubyte)alpha;
  1024.     clr->ac_type = (ubyte)type;
  1025.     clr->alphacolor = -1;
  1026.     clr->is_alphacolor = 1;
  1027. }
  1028.  
  1029. void gr_set_color( int r, int g, int b )
  1030. {
  1031.     Assert((r >= 0) && (r < 256));
  1032.     Assert((g >= 0) && (g < 256));
  1033.     Assert((b >= 0) && (b < 256));
  1034.  
  1035.     gr_init_color( &gr_screen.current_color, r, g, b );
  1036. }
  1037.  
  1038. void gr_set_color_fast(color *dst)
  1039. {
  1040.     if ( dst->screen_sig != gr_screen.signature ) {
  1041.         if (dst->is_alphacolor) {
  1042.             gr_init_alphacolor( dst, dst->red, dst->green, dst->blue, dst->alpha, dst->ac_type );
  1043.         } else {
  1044.             gr_init_color( dst, dst->red, dst->green, dst->blue );
  1045.         }
  1046.     }
  1047.  
  1048.     gr_screen.current_color = *dst;
  1049. }
  1050.  
  1051. // shader functions
  1052. void gr_create_shader(shader *shade, ubyte r, ubyte g, ubyte b, ubyte c )
  1053. {
  1054.     shade->screen_sig = gr_screen.signature;
  1055.     shade->r = r;
  1056.     shade->g = g;
  1057.     shade->b = b;
  1058.     shade->c = c;
  1059. }
  1060.  
  1061. void gr_set_shader(shader *shade)
  1062. {
  1063.     if (shade) {
  1064.         if (shade->screen_sig != gr_screen.signature) {
  1065.             gr_create_shader( shade, shade->r, shade->g, shade->b, shade->c );
  1066.         }
  1067.         gr_screen.current_shader = *shade;
  1068.     } else {
  1069.         gr_create_shader( &gr_screen.current_shader, 0, 0, 0, 0 );
  1070.     }
  1071. }
  1072.  
  1073. /**
  1074.  * Set the bitmap for the mouse pointer.  This is called by the animating mouse
  1075.  * pointer code.
  1076.  *
  1077.  * The lock parameter just locks basically disables the next call of this function that doesn't
  1078.  * have an unlock feature.  If adding in more cursor-changing situations, be aware of
  1079.  * unexpected results. You have been warned.
  1080.  *
  1081.  * @todo investigate memory leak of original Gr_cursor bitmap when this is called
  1082.  */
  1083. void gr_set_cursor_bitmap(int n, int lock)
  1084. {
  1085.     int w, h;
  1086.     static int locked = 0;
  1087.  
  1088.     if ( !locked || (lock == GR_CURSOR_UNLOCK) ) {
  1089.         // if we are changing the cursor to something different
  1090.         // then unload the previous cursor's data - taylor
  1091.         if ( (Gr_cursor >= 0) && (Gr_cursor != n) ) {
  1092.             // be sure to avoid changing a cursor which is simply another frame
  1093.             if ( (GL_cursor_nframes < 2) || ((n - Gr_cursor) >= GL_cursor_nframes) ) {
  1094.                 gr_unset_cursor_bitmap(Gr_cursor);
  1095.             }
  1096.         }
  1097.  
  1098.         if (n != Gr_cursor) {
  1099.             // get cursor size, so that we can be sure to account for the full thing
  1100.             // in later cursor hiding code
  1101.             bm_get_info(n, &w, &h, NULL, &GL_cursor_nframes);
  1102.             Assert( GL_cursor_nframes > 0 );
  1103.  
  1104.             Gr_cursor_size = MAX(w, h);
  1105.  
  1106.             if (Gr_cursor_size <= 0) {
  1107.                 Int3();
  1108.                 Gr_cursor_size = 32;
  1109.             }
  1110.         }
  1111.  
  1112.         Gr_cursor = n;
  1113.     } else {
  1114.         locked = 0;
  1115.     }
  1116.  
  1117.     if (lock == GR_CURSOR_LOCK) {
  1118.         locked = 1;
  1119.     }
  1120. }
  1121.  
  1122. void gr_unset_cursor_bitmap(int n)
  1123. {
  1124.     if (n < 0) {
  1125.         return;
  1126.     }
  1127.  
  1128.     if (Gr_cursor == n) {
  1129.         bm_unload(Gr_cursor);
  1130.         Gr_cursor = -1;
  1131.     }
  1132. }
  1133.  
  1134. /**
  1135.  * Retrieves the current bitmap
  1136.  * Used in UI_GADGET to save/restore current cursor state
  1137.  */
  1138. int gr_get_cursor_bitmap()
  1139. {
  1140.     return Gr_cursor;
  1141. }
  1142.  
  1143. // new bitmap functions
  1144. void gr_bitmap(int _x, int _y, int resize_mode)
  1145. {
  1146.     int _w, _h;
  1147.     float x, y, w, h;
  1148.     vertex verts[4];
  1149.  
  1150.     if (gr_screen.mode == GR_STUB) {
  1151.         return;
  1152.     }
  1153.  
  1154.     bm_get_info(gr_screen.current_bitmap, &_w, &_h, NULL, NULL, NULL);
  1155.  
  1156.     x = i2fl(_x);
  1157.     y = i2fl(_y);
  1158.     w = i2fl(_w);
  1159.     h = i2fl(_h);
  1160.  
  1161.     // I will tidy this up later - RT
  1162.     if ( resize_mode != GR_RESIZE_NONE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)) ) {
  1163.         gr_resize_screen_posf(&x, &y, &w, &h, resize_mode);
  1164.     }
  1165.  
  1166.     memset(verts, 0, sizeof(verts));
  1167.  
  1168.     verts[0].screen.xyw.x = x;
  1169.     verts[0].screen.xyw.y = y;
  1170.     verts[0].texture_position.u = 0.0f;
  1171.     verts[0].texture_position.v = 0.0f;
  1172.  
  1173.     verts[1].screen.xyw.x = x + w;
  1174.     verts[1].screen.xyw.y = y;
  1175.     verts[1].texture_position.u = 1.0f;
  1176.     verts[1].texture_position.v = 0.0f;
  1177.  
  1178.     verts[2].screen.xyw.x = x + w;
  1179.     verts[2].screen.xyw.y = y + h;
  1180.     verts[2].texture_position.u = 1.0f;
  1181.     verts[2].texture_position.v = 1.0f;
  1182.  
  1183.     verts[3].screen.xyw.x = x;
  1184.     verts[3].screen.xyw.y = y + h;
  1185.     verts[3].texture_position.u = 0.0f;
  1186.     verts[3].texture_position.v = 1.0f;
  1187.  
  1188.     // turn off zbuffering
  1189.     int saved_zbuffer_mode = gr_zbuffer_get();
  1190.     gr_zbuffer_set(GR_ZBUFF_NONE);
  1191.  
  1192.     gr_render(4, verts, TMAP_FLAG_TEXTURED | TMAP_FLAG_INTERFACE);
  1193.  
  1194.     gr_zbuffer_set(saved_zbuffer_mode);
  1195. }
  1196.  
  1197. void gr_bitmap_uv(int _x, int _y, int _w, int _h, float _u0, float _v0, float _u1, float _v1, int resize_mode)
  1198. {
  1199.     float x, y, w, h;
  1200.     vertex verts[4];
  1201.  
  1202.     if (gr_screen.mode == GR_STUB) {
  1203.         return;
  1204.     }
  1205.  
  1206.     x = i2fl(_x);
  1207.     y = i2fl(_y);
  1208.     w = i2fl(_w);
  1209.     h = i2fl(_h);
  1210.  
  1211.     // I will tidy this up later - RT
  1212.     if ( resize_mode != GR_RESIZE_NONE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)) ) {
  1213.         gr_resize_screen_posf(&x, &y, &w, &h, resize_mode);
  1214.     }
  1215.  
  1216.     memset(verts, 0, sizeof(verts));
  1217.  
  1218.     verts[0].screen.xyw.x = x;
  1219.     verts[0].screen.xyw.y = y;
  1220.     verts[0].texture_position.u = _u0;
  1221.     verts[0].texture_position.v = _v0;
  1222.  
  1223.     verts[1].screen.xyw.x = x + w;
  1224.     verts[1].screen.xyw.y = y;
  1225.     verts[1].texture_position.u = _u1;
  1226.     verts[1].texture_position.v = _v0;
  1227.  
  1228.     verts[2].screen.xyw.x = x + w;
  1229.     verts[2].screen.xyw.y = y + h;
  1230.     verts[2].texture_position.u = _u1;
  1231.     verts[2].texture_position.v = _v1;
  1232.  
  1233.     verts[3].screen.xyw.x = x;
  1234.     verts[3].screen.xyw.y = y + h;
  1235.     verts[3].texture_position.u = _u0;
  1236.     verts[3].texture_position.v = _v1;
  1237.  
  1238.     // turn off zbuffering
  1239.     int saved_zbuffer_mode = gr_zbuffer_get();
  1240.     gr_zbuffer_set(GR_ZBUFF_NONE);
  1241.  
  1242.     gr_render(4, verts, TMAP_FLAG_TEXTURED | TMAP_FLAG_INTERFACE);
  1243.  
  1244.     gr_zbuffer_set(saved_zbuffer_mode);
  1245. }
  1246.  
  1247. // NEW new bitmap functions -Bobboau
  1248. void gr_bitmap_list(bitmap_2d_list* list, int n_bm, int resize_mode)
  1249. {
  1250.     for (int i = 0; i < n_bm; i++) {
  1251.         bitmap_2d_list *l = &list[i];
  1252.  
  1253.         bm_get_info(gr_screen.current_bitmap, &l->w, &l->h, NULL, NULL, NULL);
  1254.  
  1255.         if ( resize_mode != GR_RESIZE_NONE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)) ) {
  1256.             gr_resize_screen_pos(&l->x, &l->y, &l->w, &l->h, resize_mode);
  1257.         }
  1258.     }
  1259.  
  1260.     g3_draw_2d_poly_bitmap_list(list, n_bm, TMAP_FLAG_INTERFACE);
  1261. }
  1262.  
  1263. // _->NEW<-_ NEW new bitmap functions -Bobboau
  1264. //takes a list of rectangles that have assosiated rectangles in a texture
  1265. void gr_bitmap_list(bitmap_rect_list* list, int n_bm, int resize_mode)
  1266. {
  1267.     for(int i = 0; i < n_bm; i++) {
  1268.         bitmap_2d_list *l = &list[i].screen_rect;
  1269.  
  1270.         // if no valid hight or width values were given get some from the bitmap
  1271.         if ( (l->w <= 0) || (l->h <= 0) ) {
  1272.             bm_get_info(gr_screen.current_bitmap, &l->w, &l->h, NULL, NULL, NULL);
  1273.         }
  1274.  
  1275.         if ( resize_mode != GR_RESIZE_NONE && (gr_screen.custom_size || (gr_screen.rendering_to_texture != -1)) ) {
  1276.             gr_resize_screen_pos(&l->x, &l->y, &l->w, &l->h, resize_mode);
  1277.         }
  1278.     }
  1279.  
  1280.     g3_draw_2d_poly_bitmap_rect_list(list, n_bm, TMAP_FLAG_INTERFACE);
  1281. }
  1282.  
  1283.  
  1284. /**
  1285.  * Given endpoints, and thickness, calculate coords of the endpoint
  1286.  */
  1287. void gr_pline_helper(vec3d *out, vec3d *in1, vec3d *in2, int thickness)
  1288. {
  1289.     vec3d slope;
  1290.  
  1291.     // slope of the line
  1292.     if(vm_vec_same(in1, in2)) {
  1293.         slope = vmd_zero_vector;
  1294.     } else {
  1295.         vm_vec_sub(&slope, in2, in1);
  1296.         float temp = -slope.xyz.x;
  1297.         slope.xyz.x = slope.xyz.y;
  1298.         slope.xyz.y = temp;
  1299.         vm_vec_normalize(&slope);
  1300.     }
  1301.     // get the points
  1302.     vm_vec_scale_add(out, in1, &slope, (float)thickness);
  1303. }
  1304.  
  1305. /**
  1306.  * Special function for drawing polylines.
  1307.  *
  1308.  * This function is specifically intended for polylines where each section
  1309.  * is no more than 90 degrees away from a previous section.
  1310.  * Moreover, it is _really_ intended for use with 45 degree angles.
  1311.  */
  1312. void gr_pline_special(SCP_vector<vec3d> *pts, int thickness,int resize_mode)
  1313. {
  1314.     vec3d s1, s2, e1, e2, dir;
  1315.     vec3d last_e1, last_e2;
  1316.     vertex v[4];
  1317.     vertex *verts[4] = {&v[0], &v[1], &v[2], &v[3]};
  1318.     int saved_zbuffer_mode, idx;
  1319.     int started_frame = 0;
  1320.  
  1321.     int num_pts = pts->size();
  1322.  
  1323.     // if we have less than 2 pts, bail
  1324.     if(num_pts < 2) {
  1325.         return;
  1326.     }
  1327.  
  1328.     extern int G3_count;
  1329.     if(G3_count == 0) {
  1330.         g3_start_frame(1);
  1331.         started_frame = 1;
  1332.     }
  1333.  
  1334.     // turn off zbuffering
  1335.     saved_zbuffer_mode = gr_zbuffer_get();
  1336.     gr_zbuffer_set(GR_ZBUFF_NONE);
  1337.  
  1338.     // turn off culling
  1339.     int cull = gr_set_cull(0);
  1340.  
  1341.     // draw each section
  1342.     last_e1 = vmd_zero_vector;
  1343.     last_e2 = vmd_zero_vector;
  1344.     int j;
  1345.     for(idx=0; idx<num_pts-1; idx++) {
  1346.         // get the start and endpoints
  1347.         s1 = pts->at(idx);                                                  // start 1 (on the line)
  1348.         e1 = pts->at(idx+1);                                                // end 1 (on the line)
  1349.         gr_pline_helper(&s2, &s1, &e1, thickness);  // start 2
  1350.         vm_vec_sub(&dir, &e1, &s1);
  1351.         vm_vec_add(&e2, &s2, &dir);                                         // end 2
  1352.        
  1353.         // stuff coords
  1354.         v[0].screen.xyw.x = (float)ceil(s1.xyz.x);
  1355.         v[0].screen.xyw.y = (float)ceil(s1.xyz.y);
  1356.         v[0].screen.xyw.w = 0.0f;
  1357.         v[0].texture_position.u = 0.5f;
  1358.         v[0].texture_position.v = 0.5f;
  1359.         v[0].flags = PF_PROJECTED;
  1360.         v[0].codes = 0;
  1361.         v[0].r = gr_screen.current_color.red;
  1362.         v[0].g = gr_screen.current_color.green;
  1363.         v[0].b = gr_screen.current_color.blue;
  1364.  
  1365.         v[1].screen.xyw.x = (float)ceil(s2.xyz.x);
  1366.         v[1].screen.xyw.y = (float)ceil(s2.xyz.y);
  1367.         v[1].screen.xyw.w = 0.0f;
  1368.         v[1].texture_position.u = 0.5f;
  1369.         v[1].texture_position.v = 0.5f;
  1370.         v[1].flags = PF_PROJECTED;
  1371.         v[1].codes = 0;
  1372.         v[1].r = gr_screen.current_color.red;
  1373.         v[1].g = gr_screen.current_color.green;
  1374.         v[1].b = gr_screen.current_color.blue;
  1375.  
  1376.         v[2].screen.xyw.x = (float)ceil(e2.xyz.x);
  1377.         v[2].screen.xyw.y = (float)ceil(e2.xyz.y);
  1378.         v[2].screen.xyw.w = 0.0f;
  1379.         v[2].texture_position.u = 0.5f;
  1380.         v[2].texture_position.v = 0.5f;
  1381.         v[2].flags = PF_PROJECTED;
  1382.         v[2].codes = 0;
  1383.         v[2].r = gr_screen.current_color.red;
  1384.         v[2].g = gr_screen.current_color.green;
  1385.         v[2].b = gr_screen.current_color.blue;
  1386.  
  1387.         v[3].screen.xyw.x = (float)ceil(e1.xyz.x);
  1388.         v[3].screen.xyw.y = (float)ceil(e1.xyz.y);
  1389.         v[3].screen.xyw.w = 0.0f;
  1390.         v[3].texture_position.u = 0.5f;
  1391.         v[3].texture_position.v = 0.5f;
  1392.         v[3].flags = PF_PROJECTED;
  1393.         v[3].codes = 0;
  1394.         v[3].r = gr_screen.current_color.red;
  1395.         v[3].g = gr_screen.current_color.green;
  1396.         v[3].b = gr_screen.current_color.blue;
  1397.  
  1398.         //We could really do this better...but oh well. _WMC
  1399.         if(resize_mode != GR_RESIZE_NONE) {
  1400.             for(j=0;j<4;j++) {
  1401.                 gr_resize_screen_posf(&v[j].screen.xyw.x,&v[j].screen.xyw.y,NULL,NULL,resize_mode);
  1402.             }
  1403.         }
  1404.  
  1405.         // draw the polys
  1406.         g3_draw_poly_constant_sw(4, verts, TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB, 0.1f);
  1407.  
  1408.         // if we're past the first section, draw a "patch" triangle to fill any gaps
  1409.         if(idx > 0) {
  1410.             // stuff coords
  1411.             v[0].screen.xyw.x = (float)ceil(s1.xyz.x);
  1412.             v[0].screen.xyw.y = (float)ceil(s1.xyz.y);
  1413.             v[0].screen.xyw.w = 0.0f;
  1414.             v[0].texture_position.u = 0.5f;
  1415.             v[0].texture_position.v = 0.5f;
  1416.             v[0].flags = PF_PROJECTED;
  1417.             v[0].codes = 0;
  1418.             v[0].r = gr_screen.current_color.red;
  1419.             v[0].g = gr_screen.current_color.green;
  1420.             v[0].b = gr_screen.current_color.blue;
  1421.  
  1422.             v[1].screen.xyw.x = (float)ceil(s2.xyz.x);
  1423.             v[1].screen.xyw.y = (float)ceil(s2.xyz.y);
  1424.             v[1].screen.xyw.w = 0.0f;
  1425.             v[1].texture_position.u = 0.5f;
  1426.             v[1].texture_position.v = 0.5f;
  1427.             v[1].flags = PF_PROJECTED;
  1428.             v[1].codes = 0;
  1429.             v[1].r = gr_screen.current_color.red;
  1430.             v[1].g = gr_screen.current_color.green;
  1431.             v[1].b = gr_screen.current_color.blue;
  1432.  
  1433.  
  1434.             v[2].screen.xyw.x = (float)ceil(last_e2.xyz.x);
  1435.             v[2].screen.xyw.y = (float)ceil(last_e2.xyz.y);
  1436.             v[2].screen.xyw.w = 0.0f;
  1437.             v[2].texture_position.u = 0.5f;
  1438.             v[2].texture_position.v = 0.5f;
  1439.             v[2].flags = PF_PROJECTED;
  1440.             v[2].codes = 0;
  1441.             v[2].r = gr_screen.current_color.red;
  1442.             v[2].g = gr_screen.current_color.green;
  1443.             v[2].b = gr_screen.current_color.blue;
  1444.  
  1445.             //Inefficiency or flexibility? you be the judge -WMC
  1446.             if(resize_mode != GR_RESIZE_NONE) {
  1447.                 for(j=0;j<3;j++) {
  1448.                     gr_resize_screen_posf(&v[j].screen.xyw.x,&v[j].screen.xyw.y,NULL,NULL,resize_mode);
  1449.                 }
  1450.             }
  1451.  
  1452.             g3_draw_poly_constant_sw(3, verts, TMAP_FLAG_GOURAUD | TMAP_FLAG_RGB, 0.1f);
  1453.         }
  1454.  
  1455.         // store our endpoints
  1456.         last_e1 = e1;
  1457.         last_e2 = e2;
  1458.     }
  1459.  
  1460.     if(started_frame) {
  1461.         g3_end_frame();
  1462.     }
  1463.  
  1464.     // restore zbuffer mode
  1465.     gr_zbuffer_set(saved_zbuffer_mode);
  1466.  
  1467.     // restore culling
  1468.     gr_set_cull(cull);
  1469. }
  1470.  
  1471. int poly_list::find_first_vertex(int idx)
  1472. {
  1473.     vec3d *o_norm = &norm[idx];
  1474.     vertex *o_vert = &vert[idx];
  1475.     vec3d *p_norm = &norm[0];
  1476.     vertex *p_vert = &vert[0];
  1477.  
  1478.     // we should always equal ourselves, so just use that as the stopping point
  1479.     for (int i = 0; i < idx; i++) {
  1480.         if ( (*p_norm == *o_norm)
  1481.             && (p_vert->world == o_vert->world)
  1482.             && (p_vert->texture_position == o_vert->texture_position) )
  1483.         {
  1484.             return i;
  1485.         }
  1486.  
  1487.         ++p_norm;
  1488.         ++p_vert;
  1489.     }
  1490.  
  1491.     return idx;
  1492. }
  1493.  
  1494. /**
  1495.  * Given a list (plist) find the index within the indexed list that the vert at position idx within list is at
  1496.  */
  1497. int poly_list::find_index(poly_list *plist, int idx)
  1498. {
  1499.     vec3d *o_norm = &plist->norm[idx];
  1500.     vertex *o_vert = &plist->vert[idx];
  1501.     vec3d *p_norm = &norm[0];
  1502.     vertex *p_vert = &vert[0];
  1503.  
  1504.     for (int i = 0; i < n_verts; i++) {
  1505.         if ( (*p_norm == *o_norm)
  1506.             && (p_vert->world == o_vert->world)
  1507.             && (p_vert->texture_position == o_vert->texture_position))
  1508.         {
  1509.             return i;
  1510.         }
  1511.  
  1512.         ++p_vert;
  1513.         ++p_norm;
  1514.     }
  1515.  
  1516.     return -1;
  1517. }
  1518.  
  1519.  
  1520. void poly_list::allocate(int _verts)
  1521. {
  1522.     if (_verts <= currently_allocated)
  1523.         return;
  1524.  
  1525.     if (vert != NULL) {
  1526.         vm_free(vert);
  1527.         vert = NULL;
  1528.     }
  1529.  
  1530.     if (norm != NULL) {
  1531.         vm_free(norm);
  1532.         norm = NULL;
  1533.     }
  1534.  
  1535.     if (tsb != NULL) {
  1536.         vm_free(tsb);
  1537.         tsb = NULL;
  1538.     }
  1539.  
  1540.     if (_verts) {
  1541.         vert = (vertex*)vm_malloc(sizeof(vertex) * _verts);
  1542.         norm = (vec3d*)vm_malloc(sizeof(vec3d) * _verts);
  1543.  
  1544.         if (Cmdline_normal) {
  1545.             tsb = (tsb_t*)vm_malloc(sizeof(tsb_t) * _verts);
  1546.         }
  1547.     }
  1548.  
  1549.     n_verts = 0;
  1550.     currently_allocated = _verts;
  1551. }
  1552.  
  1553. poly_list::~poly_list()
  1554. {
  1555.     if (vert != NULL) {
  1556.         vm_free(vert);
  1557.         vert = NULL;
  1558.     }
  1559.  
  1560.     if (norm != NULL) {
  1561.         vm_free(norm);
  1562.         norm = NULL;
  1563.     }
  1564.  
  1565.     if (tsb != NULL) {
  1566.         vm_free(tsb);
  1567.         tsb = NULL;
  1568.     }
  1569. }
  1570.  
  1571. void poly_list::calculate_tangent()
  1572. {
  1573.     vertex *v0, *v1, *v2;
  1574.     vec3d *t0, *t1, *t2;
  1575.     vec3d side0, side1;
  1576.     vec3d vt0, vt1;
  1577.     float deltaU0, deltaV0, deltaU1, deltaV1;
  1578.     vec3d tangent, binormal, cross;
  1579.     float magg, scale;
  1580.  
  1581.     if ( !Cmdline_normal ) {
  1582.         return;
  1583.     }
  1584.  
  1585.     Assert( !(n_verts % 3) );
  1586.  
  1587.     for (int i = 0; i < n_verts; i += 3) {
  1588.         // vertex (reading)
  1589.         v0 = &vert[i];
  1590.         v1 = &vert[i+1];
  1591.         v2 = &vert[i+2];
  1592.         // tangents (writing)
  1593.         t0 = &tsb[i].tangent;
  1594.         t1 = &tsb[i+1].tangent;
  1595.         t2 = &tsb[i+2].tangent;
  1596.  
  1597.  
  1598.         deltaU0 = v1->texture_position.u - v0->texture_position.u;
  1599.         deltaV0 = v1->texture_position.v - v0->texture_position.v;
  1600.  
  1601.         deltaU1 = v2->texture_position.u - v0->texture_position.u;
  1602.         deltaV1 = v2->texture_position.v - v0->texture_position.v;
  1603.  
  1604.         // quick short circuit for NULL case
  1605.         float n = (deltaU0 * deltaV1) - (deltaU1 * deltaV0);
  1606.  
  1607.         if (n == 0.0f) {
  1608.             // hit NULL, so just set identity
  1609.             tangent  = vmd_x_vector;
  1610.             binormal = vmd_y_vector;
  1611.         } else {
  1612.             float blah = 1.0f / n;
  1613.  
  1614.             vm_vec_sub(&side0, &v1->world, &v0->world);
  1615.             vm_vec_sub(&side1, &v2->world, &v0->world);
  1616.  
  1617.             // tangent
  1618.             vm_vec_copy_scale(&vt0, &side0, deltaV1);
  1619.             vm_vec_copy_scale(&vt1, &side1, deltaV0);
  1620.             vm_vec_sub(&tangent, &vt0, &vt1);
  1621.             vm_vec_scale(&tangent, blah);
  1622.  
  1623.             // binormal
  1624.             vm_vec_copy_scale(&vt0, &side0, deltaU1);
  1625.             vm_vec_copy_scale(&vt1, &side1, deltaU0);
  1626.             vm_vec_sub(&binormal, &vt0, &vt1);
  1627.             vm_vec_scale(&binormal, blah);
  1628.         }
  1629.  
  1630.         // orthogonalize tangent (for all 3 verts)
  1631.         magg = vm_vec_dot(&norm[i], &tangent);
  1632.         vm_vec_scale_sub(t0, &tangent, &norm[i], magg);
  1633.         vm_vec_normalize_safe(t0);
  1634.  
  1635.         magg = vm_vec_dot(&norm[i+1], &tangent);
  1636.         vm_vec_scale_sub(t1, &tangent, &norm[i+1], magg);
  1637.         vm_vec_normalize_safe(t1);
  1638.  
  1639.         magg = vm_vec_dot(&norm[i+2], &tangent);
  1640.         vm_vec_scale_sub(t2, &tangent, &norm[i+2], magg);
  1641.         vm_vec_normalize_safe(t2);
  1642.  
  1643.         // compute handedness (for all 3 verts)
  1644.         vm_vec_crossprod(&cross, &norm[i], &tangent);
  1645.         scale = vm_vec_dot(&cross, &binormal);
  1646.         tsb[i].scaler = (scale < 0.0f) ? -1.0f : 1.0f;
  1647.  
  1648.         vm_vec_crossprod(&cross, &norm[i+1], &tangent);
  1649.         scale = vm_vec_dot(&cross, &binormal);
  1650.         tsb[i+1].scaler = (scale < 0.0f) ? -1.0f : 1.0f;
  1651.  
  1652.         vm_vec_crossprod(&cross, &norm[i+2], &tangent);
  1653.         scale = vm_vec_dot(&cross, &binormal);
  1654.         tsb[i+2].scaler = (scale < 0.0f) ? -1.0f : 1.0f;
  1655.     }
  1656. }
  1657.  
  1658. static poly_list buffer_list_internal;
  1659.  
  1660. void poly_list::make_index_buffer(SCP_vector<int> &vertex_list)
  1661. {
  1662.     int nverts = 0;
  1663.     int j, z = 0;
  1664.     ubyte *nverts_good = NULL;
  1665.  
  1666.     // calculate tangent space data (must be done early)
  1667.     calculate_tangent();
  1668.  
  1669.     // using vm_malloc() here rather than 'new' so we get the extra out-of-memory check
  1670.     nverts_good = (ubyte *) vm_malloc(n_verts);
  1671.  
  1672.     Assert( nverts_good != NULL );
  1673.     if ( nverts_good == NULL )
  1674.         return;
  1675.    
  1676.     memset( nverts_good, 0, n_verts );
  1677.  
  1678.     vertex_list.reserve(n_verts);
  1679.  
  1680.     for (j = 0; j < n_verts; j++) {
  1681.         if (find_first_vertex(j) == j) {
  1682.             nverts++;
  1683.             nverts_good[j] = 1;
  1684.             vertex_list.push_back(j);
  1685.         }
  1686.     }
  1687.  
  1688.     // if there is nothig to change then bail
  1689.     if (n_verts == nverts) {
  1690.         if (nverts_good != NULL) {
  1691.             vm_free(nverts_good);
  1692.         }
  1693.  
  1694.         return;
  1695.     }
  1696.  
  1697.     buffer_list_internal.n_verts = 0;
  1698.     buffer_list_internal.allocate(nverts);
  1699.  
  1700.     for (j = 0; j < n_verts; j++) {
  1701.         if ( !nverts_good[j] ) {
  1702.             continue;
  1703.         }
  1704.  
  1705.         buffer_list_internal.vert[z] = vert[j];
  1706.         buffer_list_internal.norm[z] = norm[j];
  1707.  
  1708.         if (Cmdline_normal) {
  1709.             buffer_list_internal.tsb[z] = tsb[j];
  1710.         }
  1711.  
  1712.         buffer_list_internal.n_verts++;
  1713.         z++;
  1714.     }
  1715.  
  1716.     Assert(nverts == buffer_list_internal.n_verts);
  1717.  
  1718.     if (nverts_good != NULL) {
  1719.         vm_free(nverts_good);
  1720.     }
  1721.  
  1722.     (*this) = buffer_list_internal;
  1723. }
  1724.  
  1725. poly_list& poly_list::operator = (poly_list &other_list)
  1726. {
  1727.     allocate(other_list.n_verts);
  1728.  
  1729.     memcpy(norm, other_list.norm, sizeof(vec3d) * other_list.n_verts);
  1730.     memcpy(vert, other_list.vert, sizeof(vertex) * other_list.n_verts);
  1731.  
  1732.     if (Cmdline_normal) {
  1733.         memcpy(tsb, other_list.tsb, sizeof(tsb_t) * other_list.n_verts);
  1734.     }
  1735.  
  1736.     n_verts = other_list.n_verts;
  1737.  
  1738.     return *this;
  1739. }
  1740.  
  1741. void gr_shield_icon(coord2d coords[6], int resize_mode)
  1742. {
  1743.     if (gr_screen.mode == GR_STUB) {
  1744.         return;
  1745.     }
  1746.  
  1747.     if (resize_mode != GR_RESIZE_NONE) {
  1748.         gr_resize_screen_pos(&coords[0].x, &coords[0].y, NULL, NULL, resize_mode);
  1749.         gr_resize_screen_pos(&coords[1].x, &coords[1].y, NULL, NULL, resize_mode);
  1750.         gr_resize_screen_pos(&coords[2].x, &coords[2].y, NULL, NULL, resize_mode);
  1751.         gr_resize_screen_pos(&coords[3].x, &coords[3].y, NULL, NULL, resize_mode);
  1752.         gr_resize_screen_pos(&coords[4].x, &coords[4].y, NULL, NULL, resize_mode);
  1753.         gr_resize_screen_pos(&coords[5].x, &coords[5].y, NULL, NULL, resize_mode);
  1754.     }
  1755.  
  1756.     g3_draw_2d_shield_icon(coords,
  1757.         gr_screen.current_color.red,
  1758.         gr_screen.current_color.green,
  1759.         gr_screen.current_color.blue,
  1760.         gr_screen.current_color.alpha);
  1761. }
  1762.  
  1763. void gr_rect(int x, int y, int w, int h, int resize_mode)
  1764. {
  1765.     if (gr_screen.mode == GR_STUB) {
  1766.         return;
  1767.     }
  1768.  
  1769.     if (resize_mode != GR_RESIZE_NONE) {
  1770.         gr_resize_screen_pos(&x, &y, &w, &h, resize_mode);
  1771.     }
  1772.  
  1773.     g3_draw_2d_rect(x, y, w, h,
  1774.         gr_screen.current_color.red,
  1775.         gr_screen.current_color.green,
  1776.         gr_screen.current_color.blue,
  1777.         gr_screen.current_color.alpha);
  1778. }
  1779.  
  1780. void gr_shade(int x, int y, int w, int h, int resize_mode)
  1781. {
  1782.     int r, g, b, a;
  1783.  
  1784.     if (gr_screen.mode == GR_STUB) {
  1785.         return;
  1786.     }
  1787.  
  1788.     if (resize_mode != GR_RESIZE_NONE) {
  1789.         gr_resize_screen_pos(&x, &y, &w, &h, resize_mode);
  1790.     }
  1791.  
  1792.     r = (int)gr_screen.current_shader.r;
  1793.     g = (int)gr_screen.current_shader.g;
  1794.     b = (int)gr_screen.current_shader.b;
  1795.     a = (int)gr_screen.current_shader.c;
  1796.  
  1797.     g3_draw_2d_rect(x, y, w, h, r, g, b, a);
  1798. }
  1799.  
  1800. void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
  1801. {
  1802.     gr_screen.current_alpha = alpha;
  1803.     gr_screen.current_alphablend_mode = alphablend_mode;
  1804.     gr_screen.current_bitblt_mode = bitblt_mode;
  1805.     gr_screen.current_bitmap = bitmap_num;
  1806. }
  1807.  
  1808. void gr_flip()
  1809. {
  1810.     // m!m avoid running CHA_ONFRAME when the "Quit mission" popup is shown. See mantis 2446 for reference
  1811.     if (!quit_mission_popup_shown)
  1812.     {
  1813.         //WMC - Evaluate global hook if not override.
  1814.         Script_system.RunBytecode(Script_globalhook);
  1815.         //WMC - Do conditional hooks. Yippee!
  1816.         Script_system.RunCondition(CHA_ONFRAME);
  1817.         //WMC - Do scripting reset stuff
  1818.         Script_system.EndFrame();
  1819.     }
  1820.  
  1821.     gr_screen.gf_flip();
  1822. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement