home *** CD-ROM | disk | FTP | other *** search
/ Chip 2011 November / CHIP_2011_11.iso / Programy / Inne / Gry / Atomic_Tanks / Atomic-Tanks-5.1.exe / src / sky.cpp < prev    next >
C/C++ Source or Header  |  2009-09-07  |  14KB  |  432 lines

  1. /*
  2.  * atanks - obliterate each other with oversize weapons
  3.  * Copyright (C) 2003  Thomas Hudson
  4.  *
  5.  * This program is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU General Public License
  7.  * as published by the Free Software Foundation; either version 2
  8.  * of the License, or (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  * */
  19.  
  20. /*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
  21. sky.cc
  22.  
  23. Code for generating sky backgrounds, including moons.
  24. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
  25.  
  26. /*
  27. TODO
  28.  + Improve documentation
  29.  + Add clouds?
  30. */
  31.  
  32. #include "globaldata.h"
  33. #include "main.h"
  34. #include <vector>
  35. #include "environment.h"
  36. #include "sky.h"
  37. #include "files.h"
  38.  
  39.  
  40. /* Here's a function that could move nicely out of atanks.cc :) */
  41. int gradientColorPoint (const gradient *grad, double length, double line);
  42.  
  43.  
  44. /*============================================================================
  45. struct moon
  46.  
  47. A simple data structure to store the parameters of a moon for easy passing.
  48. ============================================================================*/
  49. struct moon
  50.   {
  51.     int radius;
  52.     int x;
  53.     int y;
  54.     double lambda;
  55.     int octaves;
  56.     double smoothness;
  57.     double xoffset;
  58.     double yoffset;
  59.     int col1;
  60.     int col2;
  61.   };
  62.  
  63.  
  64. /*############################################################################
  65. ZBuffer
  66.  
  67. Acts a a simple, 1bpp zbuffer.  For each pixel location, the ZBuffer can
  68. remember if something is (char *)"popping up" at that location.
  69. ############################################################################*/
  70. class ZBuffer
  71.   {
  72.   private:
  73.     // empty ctor, copy-ctor and assign operator are private, so the compiler won't create implicit ones!
  74.     inline ZBuffer () { }
  75.     inline ZBuffer (ZBuffer &sourceZBuf _UNUSED)_UNUSED;
  76.     inline const ZBuffer& operator= (const ZBuffer &sourceZBuf) { return(sourceZBuf); }
  77.  
  78.     std::vector< bool >    z;
  79.     int shiftamt;
  80.  
  81.   public:
  82.     /*************************************************************************
  83.     ctor
  84.  
  85.     Construct a ZBuffer object capable of storing (char *)"popup" values for a
  86.     w by h grid.  All cells in the ZBuffer start out lowered.
  87.     *************************************************************************/
  88.     ZBuffer( int w, int h )
  89.     {
  90.       shiftamt = 0;
  91.       while ( w )
  92.         {
  93.           w >>= 1;
  94.           ++shiftamt;
  95.         }
  96.       z.resize( h << shiftamt );
  97.     }
  98.  
  99.     /*************************************************************************
  100.     test
  101.  
  102.     Returns true iff the cell at location (x,y) is raised.  Behavior is
  103.     undefined if x does not fall in the range [0,w) or if y does not fall in
  104.     the range [0,h); w and h being the parameters to the ctor.
  105.     *************************************************************************/
  106.     bool test( int x, int y ) const
  107.       {
  108.         return z[ (y<<shiftamt) | x ];
  109.       }
  110.  
  111.  
  112.     /*************************************************************************
  113.     set
  114.  
  115.     Causes a cell in the ZBuffer to become raised.  Follows the same
  116.     conditions on x and y as the test function does.
  117.     *************************************************************************/
  118.     void set( int x, int y )
  119.     {
  120.       z[ (y<<shiftamt) | x ] = true ;
  121.     }
  122.   };
  123.  
  124.  
  125. /*****************************************************************************
  126. central_rand
  127.  
  128. Return a random double in the range [0,u] where non-extreme values
  129. are preferred.
  130.  
  131. Basic on a simple cubic function.
  132. *****************************************************************************/
  133. static double central_rand( double u )
  134. {
  135.   const double x = ( (double)rand( ) / RAND_MAX ) - 0.5;    // [-.5,+.5]
  136.   return u * (0.5 - (x*x*x)*4.0) ;
  137. }
  138.  
  139.  
  140. /*****************************************************************************
  141. clamped_int
  142.  
  143. Clamps an integer value, m, into a range specified by [a,z].  Returns the
  144. clamped value.
  145. *****************************************************************************/
  146. static int clamped_int( int m, int a, int z )
  147. {
  148.   return (m<a) ? a : ( (m>z) ? z : m );
  149. }
  150.  
  151.  
  152. /*****************************************************************************
  153. generate_moon
  154.  
  155. Returns a moon structure with appropriately randomized variables.
  156. *****************************************************************************/
  157. static moon generate_moon( int scrnw, int scrnh )
  158. {
  159.   moon m;
  160.  
  161.   m.smoothness = (rand () % 20) + 3;
  162.   m.octaves = rand () % 4 + 6;
  163.   m.lambda = (rand () % 60 + 30) * (1.00/100);
  164.  
  165.   //m.radius = (int)((rand () % 100 / 200.0) * (rand () % 100 / 200.0) * scrnw);
  166.   m.radius = (int)central_rand( scrnw/8 ) ;
  167.   m.x = rand () % scrnw;
  168.   m.y = rand () % scrnh;
  169.  
  170.   m.xoffset = rand ();
  171.   m.yoffset = rand ();
  172.  
  173.   m.col1 = makecol (rand () % 255, rand () % 255, rand () % 255);
  174.   m.col2 = makecol (rand () % 255, rand () % 255, rand () % 255);
  175.  
  176.   return m;
  177. }
  178.  
  179.  
  180. /*****************************************************************************
  181. coverage
  182.  
  183. Compute the percent coverage of a pixel by a sphere given the pixel's
  184. distance from the center and the sphere's radius.
  185. *****************************************************************************/
  186. static double coverage( double distance, double fradius )
  187. {
  188.   if ( distance <= fradius )
  189.     return 1.0 ;
  190.   return 1 - (distance - fradius);
  191. }
  192.  
  193.  
  194. /*****************************************************************************
  195. fract_clamp - unused
  196.  
  197. Clamp a fraction down to the range [0.0,1.0]
  198. *****************************************************************************/
  199. /*static double fract_clamp( double x ) {
  200.     return (x < 0.0) ? 0.0 : ( (x>1.0) ? 1.0 : x );
  201. }*/
  202.  
  203.  
  204.  
  205. /*****************************************************************************
  206. paint_moonpix
  207.  
  208. Paint a pixel onto the screen for a particular part of a moon.
  209.  
  210. Parameters:
  211. * bmp, x, y
  212.     The bitmap on which to paint.  Paints onto the pixel at (x,y)
  213. * mn, xval, yval
  214.     The moon to paint.  The val's give the percentage along the moon.
  215.     Percentages must fall within [0,1].
  216. * blend
  217.     Controls how much (char *)"paint" is used.  Must be in the range [0,1].  Higher
  218.     values cause stronger painting.  Used for anti-aliasing.
  219.  
  220. *****************************************************************************/
  221. static void paint_moonpix( BITMAP* bmp, int x, int y,
  222.                            const moon& mn, double xval, double yval,
  223.                            double blend )
  224. {
  225.   const double thetax = asin (xval) * 180 / PI;
  226.   const double thetay = acos (yval) * 180 / PI;
  227.  
  228.   const double offset = (perlin2DPoint (1.0, mn.smoothness,
  229.                                         mn.xoffset + mn.x + thetax,
  230.                                         mn.yoffset + mn.y + thetay,
  231.                                         mn.lambda, mn.octaves) + 1) / 2;
  232.   const double percentVal = (perlin2DPoint (1.0, mn.smoothness,
  233.                              mn.xoffset + mn.x * 1000 + thetax,
  234.                              mn.yoffset + mn.y * 1000 + thetay,
  235.                              mn.lambda, mn.octaves) + 1) / 2;
  236.  
  237.   set_add_blender (0, 0, 0, (int)(blend * xval * percentVal * offset * 255));
  238. #ifdef THREADS
  239.   drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
  240. #endif
  241.   putpixel (bmp, x, y, mn.col1);
  242.   set_add_blender (0, 0, 0, (int)(blend * xval * (1 - percentVal) * offset * 255));
  243.   putpixel (bmp, x, y, mn.col2);
  244. #ifdef THREADS
  245.   solid_mode();
  246. #endif
  247. }
  248.  
  249.  
  250.  
  251. /*****************************************************************************
  252. draw_amoon
  253.  
  254. Renders a single moon onto a bitmap.  Assumes transparent drawing is enabled.
  255. Abeys the given bounding box, which may be smaller than the moon itself.
  256. Uses the darkside parameter to decide which side of the moon should be
  257. dark.  Obeys and updates the z-buffer.
  258.  
  259. The current implementation of this function is beggins for some
  260. simplifications.  And again, what about thoes [xy]offset variables?
  261. *****************************************************************************/
  262. static void draw_amoon( BITMAP* bmp,
  263.                         const moon& mn, int x0, int y0, int x1, int y1,
  264.                         bool darkside, ZBuffer& zbuffer )
  265. {
  266.   for ( int y = y0; y != y1; ++y )
  267.     {
  268.       bool hityet = false;
  269.  
  270.       for ( int x = x0; x != x1; ++x )
  271.         {
  272.           /* Occupied? */
  273.           if ( zbuffer.test(x,y) )
  274.             continue ;
  275.  
  276.           /* Find distance from this moon */
  277.           int xdist = mn.x - x;
  278.           int ydist = mn.y - y;
  279.  
  280.           /* Compute some other nice circle values */
  281.           const double fradius = (double) mn.radius ;
  282.           double xval = (double)xdist / fradius;
  283.           double yval = (double)ydist / fradius;
  284.           double distance2 = (xdist * xdist) + (ydist * ydist);
  285.           double distance = sqrt (distance2);
  286.  
  287.           /* A bound check -> are we in the circle? */
  288.           if ( distance > fradius + 1 )
  289.             {
  290.               if ( hityet )    /* If we've already been inside at this y... */
  291.                 break;        /* then skip ahead to the next y */
  292.               else            /* Otherwise... */
  293.                 continue ;    /* Stay at this y, and skip to the next x */
  294.             }
  295.  
  296.           /* Edges use lighter blending */
  297.           const double edgeval = coverage( distance, fradius );
  298.  
  299.           /* Now, should we paint this side of the moon? */
  300.           if ( xval && ((xval<0) == darkside) )
  301.             {
  302.               paint_moonpix(
  303.                 bmp, x, y,
  304.                 mn, fabs(xval), yval,
  305.                 //fract_clamp( fabs(xval) ),
  306.                 //fract_clamp( fabs(yval) ),
  307.                 edgeval ) ;
  308.             }
  309.  
  310.           /* Mark this pixel as occupied */
  311.           zbuffer.set(x,y);
  312.           hityet = true ;
  313.         }
  314.     }
  315. }
  316.  
  317.  
  318.  
  319. /*****************************************************************************
  320. draw_moons
  321.  
  322. Renders a set of moons over a given bitmap.  The bitmap to draw of and the
  323. appropriate dimensions must be given.
  324. *****************************************************************************/
  325. void draw_moons (BITMAP* bmp, int width, int height)
  326. {
  327.   const bool darkside = rand() > (RAND_MAX/2+1) ;
  328.   ZBuffer    zbuffer( width, height ) ;
  329.  
  330.   drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
  331.   for ( int numMoons = (int)central_rand( 14.0 );
  332.         numMoons; --numMoons )
  333.     {
  334.       int x0, y0, x1, y1;
  335.  
  336.       /* Make up a moon */
  337.       const moon mn = generate_moon( width, height );
  338.  
  339.       /* Where is it? */
  340.       x0 = clamped_int( mn.x - mn.radius -1, 0, width ) ;
  341.       y0 = clamped_int( mn.y - mn.radius -1, 0, height ) ;
  342.       x1 = clamped_int( mn.x + mn.radius +1, 0, width ) ;
  343.       y1 = clamped_int( mn.y + mn.radius +1, 0, height ) ;
  344.  
  345.       /* Draw it */
  346.       draw_amoon( bmp, mn, x0, y0, x1, y1, darkside, zbuffer );
  347.     }
  348.   solid_mode ();
  349. }
  350.  
  351.  
  352.  
  353. /*****************************************************************************
  354. generate_sky
  355.  
  356. Given some input parameters, renders a sky (with moons) onto a bitmap.
  357. *****************************************************************************/
  358. void generate_sky (GLOBALDATA *global, BITMAP* bmp, const gradient* grad, int flags )
  359. {
  360.   double messiness = (rand () % 100 / 1000.0 + 0.05);
  361.   const int xoffset = rand( );    /* For perlin, random starting x */
  362.   const int yoffset = rand( );    /* For perlin, random starting y */
  363.  
  364.   for (int x = 0; x < global->screenWidth; x++)
  365.     {
  366.       for (int y = 0; y < global->screenHeight - MENUHEIGHT; y++)
  367.         {
  368.           double offset = 0;
  369.  
  370.           if ( flags & GENSKY_DETAILED )
  371.             offset += perlin2DPoint (1.0, 200, xoffset + x, yoffset + y, 0.3, 6) * ((global->screenHeight - MENUHEIGHT) * messiness);
  372.  
  373.           if ( flags & GENSKY_DITHERGRAD )
  374.             offset += rand () % 10 - 5;
  375.  
  376.           while (y + offset < 0)
  377.             offset /= 2;
  378.           while (y + offset + 1 > (global->screenHeight - MENUHEIGHT))
  379.             offset /= 2;
  380.  
  381.           #ifdef THREADS
  382.           solid_mode();
  383.           #endif
  384.           putpixel (bmp, x, y,
  385.                     gradientColorPoint (grad, global->screenHeight - MENUHEIGHT, y + offset));
  386.           #ifdef THREADS
  387.           drawing_mode(global->env->current_drawing_mode, NULL, 0, 0);
  388.           #endif
  389.  
  390.         }
  391.     }
  392.   draw_moons (bmp, global->screenWidth, global->screenHeight);
  393. }
  394.  
  395.  
  396.  
  397. // This function should be a seperate thread which constantly generates
  398. // skies in the background so as to not to hang the game after the
  399. // buying screen.
  400. void *Generate_Sky_In_Background(void *new_env)
  401. {
  402.    ENVIRONMENT *env = (ENVIRONMENT *) new_env;
  403.    GLOBALDATA *my_global = env->Get_Globaldata();
  404.    BITMAP *sky_in_progress = NULL;
  405.  
  406.    // do this constantly
  407.    while ( my_global->command != GLOBAL_COMMAND_QUIT )
  408.    {
  409.       // create a bitmap in waiting, if none exists
  410.       if (! env->waiting_sky)
  411.       {
  412.          sky_in_progress = create_bitmap( my_global->screenWidth, my_global->screenHeight - MENUHEIGHT);
  413.          generate_sky (my_global, sky_in_progress, env->my_sky_gradients[my_global->cursky],
  414.                    (my_global->ditherGradients ? GENSKY_DITHERGRAD : 0 ) |
  415.                    (my_global->detailedSky ? GENSKY_DETAILED : 0 )  );
  416.  
  417.          env->waiting_sky = sky_in_progress;
  418.          sky_in_progress = NULL;
  419.       }
  420.  
  421.       LINUX_SLEEP;
  422.    }
  423.  
  424.    #ifdef THREADS
  425.    pthread_exit(NULL);
  426.    return NULL;         // we never hit this, but it keeps the compiler from complaining
  427.    #else
  428.    return NULL;
  429.    #endif
  430. }
  431.  
  432.