Guest User

Raytrace_2.cpp

a guest
Jan 8th, 2014
33
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.     u32 randColour( void )
  248.     {
  249.         return ((randi()&0xFF) << 16 ) | ((randi()&0xFF) << 8 ) | ((randi()&0xFF) );
  250.     }
  251.  
  252. }; // namesapce videoHelper
  253. using namespace videoHelper;
  254.  
  255. // ---- ----- ---- ---- ---- ---- ---- ---- DEMO CODE ( the good stuff )
  256. namespace demo
  257. {  
  258.     struct vec3
  259.     {
  260.         float x, y, z;
  261.  
  262.         vec3( )
  263.             : x( 0 ), y( 0 ), z( 0 )
  264.         {
  265.         }
  266.  
  267.         vec3( float _tx, float _ty, float _tz )
  268.             : x( _tx ), y( _ty ), z( _tz )
  269.         {
  270.         }
  271.  
  272.         void normalize( void )
  273.         {
  274.             float d = 1.0f / sqrtf( x*x + y*y + z*z );
  275.             x *= d;
  276.             y *= d;
  277.             z *= d;
  278.         }
  279.  
  280.         vec3 operator - ( const vec3 &a )
  281.         {
  282.             return vec3( x - a.x, y - a.y, z - a.z );
  283.         }
  284.  
  285.         vec3 operator + ( const vec3 &a )
  286.         {
  287.             return vec3( x + a.x, y + a.y, z + a.z );
  288.         }
  289.  
  290.         float operator * ( const vec3 &a )
  291.         {
  292.             return x*a.x + y*a.y + z*a.z;
  293.         }
  294.  
  295.         vec3 operator * ( const float s )
  296.         {
  297.             return vec3( x*s, y*s, z*s );
  298.         }
  299.  
  300.         float lengthSqr( void )
  301.         {
  302.             return x*x + y*y + z*z;
  303.         }
  304.  
  305.     };
  306.  
  307.     struct sSphere
  308.     {
  309.         sSphere( )
  310.             : origin( 0, 0, 0 ), radius( 0 )
  311.         {
  312.         }
  313.  
  314.         sSphere( float x, float y, float z, float r )
  315.             : origin( x, y, z ), radius( r )
  316.         {
  317.         }
  318.  
  319.         sSphere( float x, float y, float z, float r, u32 c )
  320.             : origin( x, y, z ), radius( r ), colour( c )
  321.         {
  322.         }
  323.  
  324.         vec3   origin;
  325.         float radius;
  326.         u32    colour;
  327.     };
  328.  
  329.     struct sPlane
  330.     {
  331.         vec3  normal;
  332.         float offset;
  333.     };
  334.  
  335.     struct sRay
  336.     {  
  337.         vec3 origin;
  338.         vec3 normal;
  339.     };
  340.  
  341.     bool intersect( sRay &ray, sSphere &sphere, vec3 &ipoint )
  342.     {
  343.         vec3  EO    = sphere.origin - ray.origin;
  344.         float v     = EO * ray.normal;
  345.         float disc  = sphere.radius * sphere.radius;
  346.               disc -= (EO*EO) - (v*v);
  347.  
  348.         if ( disc < 0.0 )
  349.             return false;
  350.  
  351.         float d = sqrtf( disc );
  352.         ipoint = ray.origin + ray.normal * (v-d);
  353.  
  354.         return true;
  355.     }
  356.  
  357.     bool intersect( sRay &ray, sPlane &plane, vec3 &ipoint )
  358.     {
  359.         float t = - ( ray.origin * plane.normal + plane.offset ) / ( ray.normal * plane.normal );
  360.         ipoint = ray.origin + ray.normal * t;
  361.         return (t > 0);
  362.     }
  363.  
  364.     const int nSpheres = 3;
  365.  
  366.     sSphere spheres[ nSpheres ] =
  367.     {
  368.         sSphere(    0,  32, 315, 96, randColour( ) ),
  369.         sSphere( -128, -32, 512, 48, randColour( ) ),
  370.         sSphere(    0, -64, 256, 64, randColour( ) )
  371.     };
  372.  
  373.     sPlane floor = { vec3( 0,-1, 0), 96.0f };
  374.  
  375.     void onInit( void )
  376.     {
  377.     /*
  378.         for ( int i=0; i<nSpheres; i++ )
  379.         {
  380.             sSphere &s = spheres[i];
  381.  
  382.             s.origin.x = (float) ( randi() % 256) - 128;
  383.             s.origin.y = (float) ( randi() % 256) - 128;
  384.             s.origin.z = (float) ( randi() % 256) + 128;
  385.             s.radius   = (float) ( randi() % 5) + 8;
  386.             s.colour   = randColour( );
  387.         }
  388.     */
  389.     }
  390.  
  391.     void onKeyHit( SDLKey key )
  392.     {
  393.         switch ( key )
  394.         {
  395.         case ( SDLK_SPACE ):
  396.             onInit( );
  397.         }
  398.     }
  399.    
  400.     u32 rayShoot( sRay &ray )
  401.     {
  402.         //
  403.         float min = -1.0f;
  404.         u32 colour = 0;
  405.         //
  406.         vec3 ipoint( 0, 0, 0 );
  407.         //
  408.         for ( int i=0; i<nSpheres; i++ )
  409.         {
  410.             if ( intersect( ray, spheres[i], ipoint ) )
  411.             {
  412.                 float dst = ipoint.lengthSqr( );
  413.  
  414.                 if ( dst < min || min < 0.0f )
  415.                 {
  416.                     min = dst;
  417.                     vec3 normal = (ipoint - spheres[i].origin);
  418.  
  419.                     float irad = 1.0f / spheres[i].radius;
  420.                     normal.x *= irad;
  421.                     normal.y *= irad;
  422.                     normal.z *= irad;
  423.  
  424.                     int r = (int)(127.0 + 127.0 * normal.x);
  425.                     int g = (int)(127.0 + 127.0 * normal.y);
  426.                     int b = (int)(127.0 - 127.0 * normal.z);
  427.  
  428. //                  colour = spheres[i].colour;
  429.                     colour = (r<<16) | (g<<8) | b;
  430.                 }
  431.             }
  432.         }
  433.  
  434.         if ( intersect( ray, floor, ipoint ) )
  435.         {
  436.             float dst = ipoint.lengthSqr( );
  437.             if ( dst < min || min < 0.0f )
  438.             {
  439.                 colour = 0x102040;
  440.             }
  441.         }
  442.  
  443.         return colour;
  444.     }
  445.  
  446.     void incWrap( float &x, float y )
  447.     {
  448.         const float _2PI = 6.28318530718f;
  449.         if ( (x+=y) > _2PI ) x -= _2PI;
  450.     }
  451.  
  452.     float t = 0.0;
  453.  
  454.     void onTick( void )
  455.     {
  456.         float hvs = vidSize / 2.0;
  457.  
  458.         for ( int y=0; y<vidSize; y++ )
  459.         {
  460.             for ( int x=0; x<vidSize; x++ )
  461.             {
  462.                 sRay ray = { vec3( ), vec3( x-hvs, y-hvs, hvs*2 ) };
  463.                 ray.normal.normalize( );
  464.                 drawColour = rayShoot( ray );
  465.                 plot( x, y );
  466.             }
  467.         }
  468.  
  469.         incWrap( t, 0.01f );
  470.  
  471.         spheres[0].origin.x = sin( (float)t ) * 256.0f;
  472.  
  473.     }
  474.  
  475. }; // namespace demo
  476. using namespace demo;
  477.  
  478. // ---- ----- ---- ---- ---- ---- ---- ---- FRAMEWORK FUNCIONS
  479. namespace framework
  480. {
  481.     static bool app_init( void )
  482.     {
  483.         if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
  484.             return false;
  485.  
  486.         SDL_WM_SetCaption( app_name, NULL );
  487.  
  488.         screen = SDL_SetVideoMode( scrRes, scrRes, 32, 0 );
  489.         if ( screen == NULL )
  490.             return false;
  491.  
  492.         if ( vidScale == 1 )    video = (u32*)screen->pixels;
  493.         else                    video = new u32[ nPixels ];
  494.  
  495.         return true;
  496.     }
  497.  
  498.     static void blit_2x( void )
  499.     {
  500.         //
  501.         const int stride = screen->w;
  502.  
  503.         u32 *dst = (u32*) screen->pixels;
  504.  
  505.         int a = 0;
  506.  
  507.         for ( int i=0; i<nPixels; i++ )
  508.         {
  509.             u32 colour = video[ i ];
  510.            
  511.             // x4 pixel write
  512.             dst[0       ] = colour;
  513.             dst[1       ] = colour;
  514.             dst[  stride] = colour;
  515.             dst[1+stride] = colour;
  516.  
  517.             dst += 2;
  518.             if ( a++ >= vidSize )
  519.             {
  520.                 a = 0;
  521.                 // add on ONE stride not two since one length
  522.                 // has already been walked
  523.                 dst += stride;
  524.             }
  525.         }
  526.     }
  527.  
  528.     static void app_draw( void )
  529.     {
  530.         if ( vidScale <= 1 )
  531.             return;
  532.  
  533.         if ( vidScale == 2 )
  534.         {
  535.             blit_2x( );
  536.             return;
  537.         }
  538.  
  539.         for ( int i=0; i<nPixels; i++ )
  540.         {
  541.             SDL_Rect rect =
  542.             {
  543.                 (i % vidSize) * vidScale,
  544.                 (i / vidSize) * vidScale,
  545.                                 vidScale,
  546.                                 vidScale
  547.             };
  548.             SDL_FillRect( screen, &rect, video[ i ] );
  549.         }
  550.     }
  551.  
  552.     static bool app_tick( void )
  553.     {
  554.         static bool active = true;
  555.  
  556.         SDL_Event event;
  557.         while ( SDL_PollEvent( &event ) )
  558.         {
  559.             switch ( event.type )
  560.             {
  561.             case ( SDL_QUIT ):
  562.                 active = false;
  563.                 break;
  564.             case ( SDL_KEYUP ):
  565.                 {
  566.                     if ( event.key.keysym.sym == SDLK_ESCAPE )
  567.                         active = false;
  568.                     else
  569.                         onKeyHit( event.key.keysym.sym );
  570.                 }
  571.                 break;
  572.             }
  573.         }
  574.         return active;
  575.     }
  576.  
  577.     static void app_quit( void )
  578.     {
  579.         //
  580.         if ( video != NULL )
  581.             if ( video != screen->pixels )
  582.                 delete [] video;
  583.         video = NULL;
  584.         //
  585.         if ( screen != NULL )
  586.             SDL_FreeSurface( screen );
  587.         //
  588.         SDL_Quit( );
  589.     }
  590.  
  591. }; // namespace framework
  592.  
  593. // windows entry point
  594. int __stdcall WinMain( int, int, int, int )
  595. {
  596.     // start up SDL
  597.     atexit( app_quit );
  598.     if (! app_init( ) )
  599.         return 1;
  600.     // get keyboard access
  601.     u32 keyCount = 0;
  602.     byte *keys = SDL_GetKeyState( (int*) &keyCount );
  603.     // seed the random
  604.     randSeed ^= SDL_GetTicks( );
  605.     // call the on initialize function 
  606.     onInit( );
  607.     //
  608.     int oldTicks = SDL_GetTicks( );
  609.     // work out the tick threshold in milliseconds
  610.     const int tickThresh = 1000 / tickFPS;
  611.     //
  612.     while ( app_tick( ) )
  613.     {
  614.         int diff = SDL_GetTicks() - oldTicks;
  615.  
  616.         if ( diff < 10  )
  617.             SDL_Delay( 10 );
  618.  
  619.         if ( diff > 500 )
  620.         {
  621.             oldTicks += diff;
  622.             continue;
  623.         }
  624.  
  625.         while ( diff > tickThresh )
  626.         {
  627.             // grab the mouse state
  628.             SDL_GetMouseState( &mousex, &mousey );
  629.             // tick the application
  630.             onTick( );
  631.             app_draw( );
  632.             SDL_Flip( screen );
  633.             // progress the tick count
  634.             oldTicks += tickThresh;
  635.             diff     -= tickThresh;
  636.         }
  637.     }
  638.     return 0;
  639. }
RAW Paste Data