Guest User

Raytrace.cpp

a guest
Jan 8th, 2014
60
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // include Simple Direct-media Layer
  2. #include <SDL/SDL.h>
  3. #pragma comment( lib, "SDL.lib" )
  4.  
  5. #include <math.h>
  6.  
  7. // setup some basic data types
  8. typedef   signed long long s64;
  9. typedef unsigned long long u64;
  10. typedef unsigned int       u32;
  11. typedef   signed int       s32;
  12. typedef   signed short     s16;
  13. typedef unsigned char      byte;
  14. typedef   signed long long fp64;
  15.  
  16. // ---- ----- ---- ---- ---- ---- ---- ---- FRAMEWORK SPECIFICS
  17. namespace framework
  18. {
  19.     // the title name for this application
  20.     const char *app_name    = "Raytrace Demo";
  21.  
  22.     // size of the video buffer
  23.     const int vidSize       = 512;
  24.  
  25.     // pixel size
  26.     const int vidScale      = 1;
  27.  
  28.     // video buffer
  29.     u32 *video              = NULL;
  30.      
  31.     // number of pixels in the video buffer
  32.     const int nPixels       = vidSize * vidSize;
  33.  
  34.     // calculated real SDL video buffer size
  35.     const int scrRes        = vidSize * vidScale;
  36.  
  37.     // the real SDL video buffer
  38.     SDL_Surface *screen     = NULL;
  39.  
  40.     // rate onTick is called in FPS
  41.     const int tickFPS       = 45;
  42.  
  43.     // mouse position
  44.     int mousex              = 0;
  45.     int mousey              = 0;
  46.  
  47. }; // namespace framework
  48. using namespace framework;
  49.  
  50. // ---- ----- ---- ---- ---- ---- ---- ---- MATH HELPER FUNCTIONS
  51. namespace mathHelper
  52. {
  53.     static u32 randSeed = 0xBABEFACE;
  54.  
  55.     static s64 absi( s64 a )
  56.     {
  57.         if ( a < 0 ) return -a;
  58.         else         return  a;
  59.     }
  60.  
  61.     static s64 maxi( s64 a, s64 b )
  62.     {
  63.         if ( a > b ) return a;
  64.         else         return b;
  65.     }
  66.  
  67.     static s64 mini( s64 a, s64 b )
  68.     {
  69.         if ( a < b ) return a;
  70.         else         return b;
  71.     }
  72.  
  73.     inline u32 randi( void )
  74.     {
  75.         randSeed *= 1103515245;
  76.         randSeed += 12345;
  77.         return (randSeed >> 15) & 0xFFFF;
  78.     }
  79.  
  80.     inline u32 scale( u32 a, byte scale )
  81.     {
  82.         return (a * scale) >> 8;
  83.     }
  84.  
  85. }; // namespace mathHelper
  86. using namespace mathHelper;
  87.  
  88. // ---- ----- ---- ---- ---- ---- ---- ---- FIXED POINT HELPER FUNCTIONS
  89. namespace fixedPointHelper
  90. {
  91.     const fp64 fp_1 = 0x10000;
  92.  
  93.     fp64 fp_mul( fp64 a, fp64 b )
  94.     {
  95.         return (a * b) >> 16;
  96.     }
  97.  
  98.     fp64 fp_div( fp64 a, fp64 b )
  99.     {
  100.         return (a << 16) / b;
  101.     }
  102.  
  103.     fp64 fp_ceil( fp64 a )
  104.     {
  105.         return (a | 0xFFFF) + 1;
  106.     }
  107.  
  108.     fp64 fp_floor( fp64 a )
  109.     {
  110.         return a & (~0xFFFF);
  111.     }
  112.  
  113.     fp64 fp_fract( fp64 a )
  114.     {
  115.         return a & 0xFFFF;
  116.     }
  117.  
  118.     fp64 fp_ifract( fp64 a )
  119.     {
  120.         return 0xFFFF - (a & 0xFFFF);
  121.     }
  122.  
  123.     int fp_to_int( fp64 a )
  124.     {
  125.         return (int) (a >> 16);
  126.     }
  127.  
  128.     fp64 int_to_fp( int a )
  129.     {
  130.         return (a << 16);
  131.     }
  132.  
  133.     fp64 fp_rand( int max )
  134.     {
  135.         return ((randi() % max) << 16) | (randi() & 0xFFFF);
  136.     }
  137.  
  138. }; // namespace fixedPointHelper
  139. using namespace fixedPointHelper;
  140.  
  141. // ---- ----- ---- ---- ---- ---- ---- ---- DRAWING HELPER FUNCTIONS
  142. namespace videoHelper
  143. {
  144.     static u32 drawColour = 0xFFFFFF;
  145.  
  146.     inline void plot( int x, int y )
  147.     {
  148.         bool out  = x < 0;
  149.              out |= y < 0;
  150.              out |= x >= vidSize;
  151.              out |= y >= vidSize;
  152.         if ( out ) return;
  153.         video[ x + y * vidSize ] = drawColour;
  154.     }
  155.    
  156.     inline u32 readPixel( int x, int y )
  157.     {
  158.         bool out  = x < 0;
  159.              out |= y < 0;
  160.              out |= x >= vidSize;
  161.              out |= y >= vidSize;
  162.         if ( out ) return 0;
  163.         return video[ x + y * vidSize ];
  164.     }
  165.  
  166.     void circle( s32 x0, s32 y0, s32 radius )
  167.     {
  168.         s32 error  =  1 - radius;
  169.         s32 errorY =  1;
  170.         s32 errorX = -2 * radius;
  171.  
  172.         s32 x = radius, y = 0;
  173.  
  174.         plot(x0, y0 + radius);
  175.         plot(x0, y0 - radius);
  176.         plot(x0 + radius, y0);
  177.         plot(x0 - radius, y0);
  178.  
  179.         while(y < x)
  180.         {
  181.             if (error > 0)
  182.                 { x--; errorX += 2; error += errorX; }
  183.                 { y++; errorY += 2; error += errorY; }
  184.  
  185.             plot(x0 + x, y0 + y);
  186.             plot(x0 - x, y0 + y);
  187.             plot(x0 + x, y0 - y);
  188.             plot(x0 - x, y0 - y);
  189.             plot(x0 + y, y0 + x);
  190.             plot(x0 - y, y0 + x);
  191.             plot(x0 + y, y0 - x);
  192.             plot(x0 - y, y0 - x);
  193.         }
  194.     }
  195.  
  196.     void line( s32 X0, s32 Y0, s32 X1, s32 Y1 )
  197.     {
  198.         s32  incrementVal = 0;
  199.         s32  shortLen     = Y1 - Y0;
  200.         s32  longLen      = X1 - X0;
  201.         bool yLonger      = false;
  202.         s32  decInc       = 0;
  203.         s32  endVal       = 0;
  204.         s32  j            = 0;
  205.  
  206.         if ( absi( shortLen ) > absi( longLen ) )
  207.         {
  208.             int swap = shortLen;
  209.             shortLen = longLen;
  210.             longLen  = swap;
  211.             yLonger  = true;
  212.         }
  213.  
  214.         endVal = longLen;
  215.  
  216.         if ( longLen < 0 )
  217.         {
  218.             incrementVal = -1;
  219.             longLen      = -longLen;
  220.         }
  221.         else
  222.             incrementVal = 1;
  223.  
  224.         if ( longLen == 0 )
  225.             decInc = 0;
  226.         else
  227.             decInc = (shortLen << 16) / longLen;
  228.  
  229.         if ( yLonger )
  230.         {
  231.             for ( s32 i=0; i!=endVal; i+=incrementVal )
  232.             {
  233.                 plot( X0 + (j >> 16), Y0 + i );
  234.                 j += decInc;
  235.             }
  236.         }
  237.         else
  238.         {
  239.             for ( s32 i=0; i!=endVal; i+=incrementVal )
  240.             {
  241.                 plot( X0 + i, Y0 + (j >> 16) );
  242.                 j += decInc;
  243.             }
  244.         }
  245.     }
  246.  
  247. }; // namesapce videoHelper
  248. using namespace videoHelper;
  249.  
  250. // ---- ----- ---- ---- ---- ---- ---- ---- DEMO CODE ( the good stuff )
  251. namespace demo
  252. {  
  253.     struct vec3
  254.     {
  255.         float x, y, z;
  256.  
  257.         vec3( )
  258.             : x( 0 ), y( 0 ), z( 0 )
  259.         {
  260.         }
  261.  
  262.         vec3( float _tx, float _ty, float _tz )
  263.             : x( _tx ), y( _ty ), z( _tz )
  264.         {
  265.         }
  266.  
  267.         void normalize( void )
  268.         {
  269.             float d = 1.0f / sqrtf( x*x + y*y + z*z );
  270.             x *= d;
  271.             y *= d;
  272.             z *= d;
  273.         }
  274.  
  275.         vec3 operator - ( const vec3 &a )
  276.         {
  277.             return vec3( x - a.x, y - a.y, z - a.z );
  278.         }
  279.  
  280.         vec3 operator + ( const vec3 &a )
  281.         {
  282.             return vec3( x + a.x, y + a.y, z + a.z );
  283.         }
  284.  
  285.         float operator * ( const vec3 &a )
  286.         {
  287.             return x*a.x + y*a.y + z*a.z;
  288.         }
  289.  
  290.         vec3 operator * ( const float s )
  291.         {
  292.             return vec3( x*s, y*s, z*s );
  293.         }
  294.  
  295.         float lengthSqr( void )
  296.         {
  297.             return x*x + y*y + z*z;
  298.         }
  299.  
  300.     };
  301.  
  302.     struct sSphere
  303.     {
  304.         sSphere( )
  305.             : origin( 0, 0, 0 ), radius( 0 )
  306.         {
  307.         }
  308.  
  309.         sSphere( float x, float y, float z, float r )
  310.             : origin( x, y, z ), radius( r )
  311.         {
  312.         }
  313.  
  314.         sSphere( float x, float y, float z, float r, u32 c )
  315.             : origin( x, y, z ), radius( r ), colour( c )
  316.         {
  317.         }
  318.  
  319.         vec3   origin;
  320.         float radius;
  321.         u32    colour;
  322.     };
  323.  
  324.     struct sRay
  325.     {  
  326.         vec3 origin;
  327.         vec3 normal;
  328.     };
  329.  
  330.     u32 randColour( void )
  331.     {
  332.         return ((randi()&0xFF) << 16 ) | ((randi()&0xFF) << 8 ) | ((randi()&0xFF) );
  333.     }
  334.  
  335.     bool intersect( sRay &ray, sSphere &sphere, vec3 &ipoint )
  336.     {
  337.         vec3  EO    = sphere.origin - ray.origin;
  338.         float v     = EO * ray.normal;
  339.         float disc  = sphere.radius * sphere.radius;
  340.               disc -= (EO*EO) - (v*v);
  341.  
  342.         if ( disc < 0.0 )
  343.             return false;
  344.  
  345.         float d = sqrtf( disc );
  346.         ipoint = ray.origin + ray.normal * (v-d);
  347.  
  348.         return true;
  349.     }
  350.  
  351.     const int nSpheres = 3;
  352.  
  353.     sSphere spheres[ nSpheres ] =
  354.     {
  355.         sSphere(    0,  32, 315, 96, randColour( ) ),
  356.         sSphere( -128, -32, 512, 48, randColour( ) ),
  357.         sSphere(    0, -64, 256, 64, randColour( ) )
  358.     };
  359.  
  360.     void onInit( void )
  361.     {
  362.     /*
  363.         for ( int i=0; i<nSpheres; i++ )
  364.         {
  365.             sSphere &s = spheres[i];
  366.  
  367.             s.origin.x = (float) ( randi() % 256) - 128;
  368.             s.origin.y = (float) ( randi() % 256) - 128;
  369.             s.origin.z = (float) ( randi() % 256) + 128;
  370.             s.radius   = (float) ( randi() % 5) + 8;
  371.             s.colour   = randColour( );
  372.         }
  373.     */
  374.     }
  375.  
  376.     void onKeyHit( SDLKey key )
  377.     {
  378.         switch ( key )
  379.         {
  380.         case ( SDLK_SPACE ):
  381.             onInit( );
  382.         }
  383.     }
  384.    
  385.     u32 rayShoot( sRay &ray )
  386.     {
  387.         //
  388.         float min = -1.0f;
  389.         u32 colour = 0;
  390.         //
  391.         for ( int i=0; i<nSpheres; i++ )
  392.         {
  393.             vec3 ipoint( 0, 0, 0 );
  394.             if ( intersect( ray, spheres[i], ipoint ) )
  395.             {
  396.                 float dst = ipoint.lengthSqr( );
  397.  
  398.                 if ( dst < min || min < 0.0f )
  399.                 {
  400.                     min = dst;
  401.                     vec3 normal = (ipoint - spheres[i].origin);
  402.  
  403.                     float irad = 1.0f / spheres[i].radius;
  404.                     normal.x *= irad;
  405.                     normal.y *= irad;
  406.                     normal.z *= irad;
  407.  
  408.                     int r = (int)(127.0 + 127.0 * normal.x);
  409.                     int g = (int)(127.0 + 127.0 * normal.y);
  410.                     int b = (int)(127.0 - 127.0 * normal.z);
  411.  
  412. //                  colour = spheres[i].colour;
  413.                     colour = (r<<16) | (g<<8) | b;
  414.                 }
  415.             }
  416.         }
  417.         return colour;
  418.     }
  419.  
  420.     void incWrap( float &x, float y )
  421.     {
  422.         const float _2PI = 6.28318530718f;
  423.         if ( (x+=y) > _2PI ) x -= _2PI;
  424.     }
  425.  
  426.     float t = 0.0;
  427.  
  428.     void onTick( void )
  429.     {
  430.         float hvs = vidSize / 2.0;
  431.  
  432.         for ( int y=0; y<vidSize; y++ )
  433.         {
  434.             for ( int x=0; x<vidSize; x++ )
  435.             {
  436.                 sRay ray = { vec3( ), vec3( x-hvs, y-hvs, hvs*2 ) };
  437.                 ray.normal.normalize( );
  438.                 drawColour = rayShoot( ray );
  439.                 plot( x, y );
  440.             }
  441.         }
  442.  
  443.         incWrap( t, 0.01f );
  444.  
  445.         spheres[0].origin.x = sin( (float)t ) * 256.0f;
  446.  
  447.     }
  448.  
  449. }; // namespace demo
  450. using namespace demo;
  451.  
  452. // ---- ----- ---- ---- ---- ---- ---- ---- FRAMEWORK FUNCIONS
  453. namespace framework
  454. {
  455.     static bool app_init( void )
  456.     {
  457.         if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
  458.             return false;
  459.  
  460.         SDL_WM_SetCaption( app_name, NULL );
  461.  
  462.         screen = SDL_SetVideoMode( scrRes, scrRes, 32, 0 );
  463.         if ( screen == NULL )
  464.             return false;
  465.  
  466.         if ( vidScale == 1 )    video = (u32*)screen->pixels;
  467.         else                    video = new u32[ nPixels ];
  468.  
  469.         return true;
  470.     }
  471.  
  472.     static void blit_2x( void )
  473.     {
  474.         //
  475.         const int stride = screen->w;
  476.  
  477.         u32 *dst = (u32*) screen->pixels;
  478.  
  479.         int a = 0;
  480.  
  481.         for ( int i=0; i<nPixels; i++ )
  482.         {
  483.             u32 colour = video[ i ];
  484.            
  485.             // x4 pixel write
  486.             dst[0       ] = colour;
  487.             dst[1       ] = colour;
  488.             dst[  stride] = colour;
  489.             dst[1+stride] = colour;
  490.  
  491.             dst += 2;
  492.             if ( a++ >= vidSize )
  493.             {
  494.                 a = 0;
  495.                 // add on ONE stride not two since one length
  496.                 // has already been walked
  497.                 dst += stride;
  498.             }
  499.         }
  500.     }
  501.  
  502.     static void app_draw( void )
  503.     {
  504.         if ( vidScale <= 1 )
  505.             return;
  506.  
  507.         if ( vidScale == 2 )
  508.         {
  509.             blit_2x( );
  510.             return;
  511.         }
  512.  
  513.         for ( int i=0; i<nPixels; i++ )
  514.         {
  515.             SDL_Rect rect =
  516.             {
  517.                 (i % vidSize) * vidScale,
  518.                 (i / vidSize) * vidScale,
  519.                                 vidScale,
  520.                                 vidScale
  521.             };
  522.             SDL_FillRect( screen, &rect, video[ i ] );
  523.         }
  524.     }
  525.  
  526.     static bool app_tick( void )
  527.     {
  528.         static bool active = true;
  529.  
  530.         SDL_Event event;
  531.         while ( SDL_PollEvent( &event ) )
  532.         {
  533.             switch ( event.type )
  534.             {
  535.             case ( SDL_QUIT ):
  536.                 active = false;
  537.                 break;
  538.             case ( SDL_KEYUP ):
  539.                 {
  540.                     if ( event.key.keysym.sym == SDLK_ESCAPE )
  541.                         active = false;
  542.                     else
  543.                         onKeyHit( event.key.keysym.sym );
  544.                 }
  545.                 break;
  546.             }
  547.         }
  548.         return active;
  549.     }
  550.  
  551.     static void app_quit( void )
  552.     {
  553.         //
  554.         if ( video != NULL )
  555.             if ( video != screen->pixels )
  556.                 delete [] video;
  557.         video = NULL;
  558.         //
  559.         if ( screen != NULL )
  560.             SDL_FreeSurface( screen );
  561.         //
  562.         SDL_Quit( );
  563.     }
  564.  
  565. }; // namespace framework
  566.  
  567. // windows entry point
  568. int __stdcall WinMain( int, int, int, int )
  569. {
  570.     // start up SDL
  571.     atexit( app_quit );
  572.     if (! app_init( ) )
  573.         return 1;
  574.     // get keyboard access
  575.     u32 keyCount = 0;
  576.     byte *keys = SDL_GetKeyState( (int*) &keyCount );
  577.     // seed the random
  578.     randSeed ^= SDL_GetTicks( );
  579.     // call the on initialize function 
  580.     onInit( );
  581.     //
  582.     int oldTicks = SDL_GetTicks( );
  583.     // work out the tick threshold in milliseconds
  584.     const int tickThresh = 1000 / tickFPS;
  585.     //
  586.     while ( app_tick( ) )
  587.     {
  588.         int diff = SDL_GetTicks() - oldTicks;
  589.  
  590.         if ( diff < 10  )
  591.             SDL_Delay( 10 );
  592.  
  593.         if ( diff > 500 )
  594.         {
  595.             oldTicks += diff;
  596.             continue;
  597.         }
  598.  
  599.         while ( diff > tickThresh )
  600.         {
  601.             // grab the mouse state
  602.             SDL_GetMouseState( &mousex, &mousey );
  603.             // tick the application
  604.             onTick( );
  605.             app_draw( );
  606.             SDL_Flip( screen );
  607.             // progress the tick count
  608.             oldTicks += tickThresh;
  609.             diff     -= tickThresh;
  610.         }
  611.     }
  612.     return 0;
  613. }
RAW Paste Data