Guest User

Raytrace5.cpp

a guest
Jan 9th, 2014
25
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. #include <intrin.h>
  7.  
  8. // setup some basic data types
  9. typedef   signed long long s64;
  10. typedef unsigned long long u64;
  11. typedef unsigned int       u32;
  12. typedef   signed int       s32;
  13. typedef   signed short     s16;
  14. typedef unsigned char      byte;
  15. typedef   signed long long fp64;
  16.  
  17. // ---- ----- ---- ---- ---- ---- ---- ---- FRAMEWORK SPECIFICS
  18. namespace framework
  19. {
  20.     #define _threading
  21.  
  22.     // number of threads alive
  23.     volatile long threads = 0;
  24.  
  25.     // true while program is running
  26.     volatile bool active = true;
  27.  
  28.     // the title name for this application
  29.     const char *app_name    = "Raytrace Demo";
  30.  
  31.     // size of the video buffer
  32.     const int vidSize       = 256;
  33.  
  34.     // pixel size
  35.     const int vidScale      = 2;
  36.  
  37.     // video buffer
  38.     u32 *video              = NULL;
  39.      
  40.     // number of pixels in the video buffer
  41.     const int nPixels       = vidSize * vidSize;
  42.  
  43.     // calculated real SDL video buffer size
  44.     const int scrRes        = vidSize * vidScale;
  45.  
  46.     // the real SDL video buffer
  47.     SDL_Surface *screen     = NULL;
  48.  
  49.     // rate onTick is called in FPS
  50.     const int tickFPS       = 60;
  51.  
  52.     // mouse position
  53.     int mousex              = 0;
  54.     int mousey              = 0;
  55.  
  56. }; // namespace framework
  57. using namespace framework;
  58.  
  59. // ---- ----- ---- ---- ---- ---- ---- ---- MATH HELPER FUNCTIONS
  60. namespace mathHelper
  61. {
  62.     static u32 randSeed = 0xBABEFACE;
  63.  
  64.     static s64 absi( s64 a )
  65.     {
  66.         if ( a < 0 ) return -a;
  67.         else         return  a;
  68.     }
  69.  
  70.     static s64 maxi( s64 a, s64 b )
  71.     {
  72.         if ( a > b ) return a;
  73.         else         return b;
  74.     }
  75.  
  76.     static s64 mini( s64 a, s64 b )
  77.     {
  78.         if ( a < b ) return a;
  79.         else         return b;
  80.     }
  81.  
  82.     inline u32 randi( void )
  83.     {
  84.         randSeed *= 1103515245;
  85.         randSeed += 12345;
  86.         return (randSeed >> 15) & 0xFFFF;
  87.     }
  88.  
  89.     inline u32 scale( u32 a, byte scale )
  90.     {
  91.         return (a * scale) >> 8;
  92.     }
  93.  
  94. }; // namespace mathHelper
  95. using namespace mathHelper;
  96.  
  97. // ---- ----- ---- ---- ---- ---- ---- ---- DRAWING HELPER FUNCTIONS
  98. namespace videoHelper
  99. {
  100. //  static u32 drawColour = 0xFFFFFF;
  101.  
  102.     inline void plot( int x, int y, u32 drawColour )
  103.     {
  104.         bool out  = x < 0;
  105.              out |= y < 0;
  106.              out |= x >= vidSize;
  107.              out |= y >= vidSize;
  108.         if ( out ) return;
  109.         video[ x + y * vidSize ] = drawColour;
  110.     }
  111.  
  112.     u32 randColour( void )
  113.     {
  114.         return ((randi()&0xFF) << 16 ) | ((randi()&0xFF) << 8 ) | ((randi()&0xFF) );
  115.     }
  116.  
  117. }; // namesapce videoHelper
  118. using namespace videoHelper;
  119.  
  120. // ---- ----- ---- ---- ---- ---- ---- ---- DEMO CODE ( the good stuff )
  121. namespace demo
  122. {  
  123.     inline float isqrtf( float number )
  124.     {
  125.         long i;
  126.         float x2, y;
  127.         const float threehalfs = 1.5F;
  128.  
  129.         x2 = number * 0.5F;
  130.         y  = number;
  131.         i  = * ( long * ) &y;                       // evil floating point bit level hacking
  132.         i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
  133.         y  = * ( float * ) &i;
  134.         y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
  135.         y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
  136.         return y;
  137.     }
  138.  
  139.     struct vec3
  140.     {
  141.         float x, y, z;
  142.  
  143.         vec3( )
  144.             : x( 0 ), y( 0 ), z( 0 )
  145.         {
  146.         }
  147.  
  148.         vec3( float _tx, float _ty, float _tz )
  149.             : x( _tx ), y( _ty ), z( _tz )
  150.         {
  151.         }
  152.  
  153.         void fnorm( void )
  154.         {
  155.             float d = isqrtf( x*x + y*y + z*z );
  156.             x *= d;
  157.             y *= d;
  158.             z *= d;
  159.         }
  160.  
  161.         vec3 project( vec3 &a )
  162.         {
  163.             return (*this) * ((a * (*this)) / length( ));
  164.         }
  165.  
  166.         vec3 operator - ( const vec3 &a ) const
  167.         {
  168.             return vec3( x - a.x, y - a.y, z - a.z );
  169.         }
  170.  
  171.         vec3 operator + ( const vec3 &a ) const
  172.         {
  173.             return vec3( x + a.x, y + a.y, z + a.z );
  174.         }
  175.  
  176.         float operator * ( const vec3 &a ) const
  177.         {
  178.             return x*a.x + y*a.y + z*a.z;
  179.         }
  180.  
  181.         vec3 operator * ( const float s ) const
  182.         {
  183.             return vec3( x*s, y*s, z*s );
  184.         }
  185.  
  186.         float length( void )
  187.         {
  188.             return sqrt( lengthSqr() );
  189.         }
  190.  
  191.         float lengthSqr( void ) const
  192.         {
  193.             return x*x + y*y + z*z;
  194.         }
  195.  
  196.         static vec3 findNormal( const vec3 &s, const vec3 &d )
  197.         {
  198.             vec3 n = d - s;
  199.             n.fnorm( );
  200.             return n;
  201.         }
  202.  
  203.         static float lengthSqr( const vec3 &s, const vec3 &d )
  204.         {
  205.             return (d.x-s.x)*(d.x-s.x) + (d.y-s.y)*(d.y-s.y) + (d.z-s.z)*(d.z-s.z);
  206.         }
  207.  
  208.         static vec3 reflect( const vec3 &n, const vec3 &r )
  209.         {
  210.             return r - n * ( 2 * (r * n) );
  211.         }
  212.  
  213.     };
  214.  
  215.     struct sSphere
  216.     {
  217.         sSphere( )
  218.             : origin( 0, 0, 0 ), radius( 0 )
  219.         {
  220.         }
  221.  
  222.         sSphere( vec3 &center, float r )
  223.             : origin( center ), radius( r ), material( 0 )
  224.         {
  225.         }
  226.  
  227.         sSphere( vec3 &center, float r, u32 m )
  228.             : origin( center ), radius( r ), material( m )
  229.         {
  230.         }
  231.  
  232.         vec3   origin;
  233.         float radius;
  234.         u32    material;
  235.     };
  236.  
  237.     struct sPlane
  238.     {
  239.         vec3  normal;
  240.         float offset;
  241.         u32   material;
  242.     };
  243.  
  244.     struct sRay
  245.     {  
  246.         sRay( )
  247.         {
  248.         }
  249.  
  250.         sRay( vec3 &a )
  251.             : origin( ), normal( a )
  252.         {
  253.         }
  254.  
  255.         sRay( vec3 &a, vec3 &b )
  256.         {
  257.             origin = a;
  258.             normal = b - a;
  259.             normal.fnorm( );
  260.         }
  261.  
  262.         vec3 origin;
  263.         vec3 normal;
  264.     };
  265.  
  266.     //
  267.     // precise ray intersection test
  268.     //
  269.     bool intersect( sRay &ray, sSphere &sphere, vec3 &ipoint )
  270.     {
  271.         float t1 = -1;
  272.         float t2 = -1;
  273.         float discriminant;
  274.         float t = -1;
  275.         //temporary == e-c
  276.         vec3 temp = ray.origin - sphere.origin;
  277.         float b = 2 * (ray.normal * temp);
  278.         float a = ray.normal * ray.normal;
  279.         float c = temp * temp - (sphere.radius * sphere.radius);
  280.         float disc;
  281.         disc = b*b - 4*a*c;
  282.         if ( disc < 0 )
  283.             return false;
  284.         else
  285.         {
  286.             discriminant = 1.0f / isqrtf( disc );
  287.             t1 = (-b+discriminant)/(2*a);
  288.             t2 = (-b-discriminant)/(2*a);  
  289.  
  290.             if (t2 > 0)
  291.             {
  292.                 ipoint = ray.origin + ray.normal * t2;
  293.                 return true;
  294.             }
  295.             if ( t1 > 0 )
  296.             {
  297.                 ipoint = ray.origin + ray.normal * t1;
  298.                 return true;
  299.             }
  300.         }
  301.         return false;
  302.     }
  303.    
  304.     bool intersect( sRay &ray, sPlane &plane, vec3 &ipoint )
  305.     {
  306.         float t = - ( ray.origin * plane.normal + plane.offset ) / ( ray.normal * plane.normal );
  307.         ipoint = ray.origin + ray.normal * t;
  308.         return (t > 0);
  309.     }
  310.    
  311.     const int nSpheres = 3;
  312.  
  313.     sSphere spheres[ nSpheres ] =
  314.     {
  315.         sSphere( vec3(   0, 128.f - 128.f, 420        ), 32.f, 0 ),
  316.         sSphere( vec3( -64, 128.f -  48.f, 512.f-64.f ), 64.f, 1 ),
  317.         sSphere( vec3(  32, 128.f -  32.f, 360        ), 32.f, 0 )
  318.     };
  319.  
  320.     sPlane planes[] =
  321.     {
  322.         { vec3( 0,-1, 0), 128.0f, 0 },
  323.         { vec3( 0, 1, 0), 128.0f, 0 },
  324.         { vec3( 0, 0,-1), 512.0f, 0 },
  325.         { vec3( 1, 0, 0), 128.0f, 0 },
  326.         { vec3(-1, 0, 0), 128.0f, 0 }
  327.     };
  328.    
  329.     vec3 light( 0,-120, 256+128 );
  330.    
  331.     bool useShadows = true;
  332.  
  333.     void rayShoot( sRay &ray, vec3 &xpoint, vec3 &normal, u32 &material, float &min )
  334.     {
  335.         min = 99999999.f;
  336.         vec3  ipoint;
  337.  
  338.         // sphere intersections
  339.         for ( int i=0; i<nSpheres; i++ )
  340.         {
  341.             sSphere &sphere = spheres[ i ];
  342.             if ( intersect( ray, sphere, ipoint ) )
  343.             {
  344.                 float dst = (ipoint-ray.origin).lengthSqr( );
  345.                 if ( dst < min /*|| min < 0.0f*/ )
  346.                 {
  347.                     xpoint      = ipoint;
  348.                     float irad  = 1.0f / sphere.radius;
  349.                     min         = dst;
  350.                     normal      = (ipoint - sphere.origin);
  351.                     normal.x   *= irad;
  352.                     normal.y   *= irad;
  353.                     normal.z   *= irad;
  354.                     material    = sphere.material;
  355.                 }
  356.             }
  357.         }
  358.  
  359.         // plane intersections
  360.         for ( int i=0; i<5; i++ )
  361.         {
  362.             sPlane &plane = planes[i];
  363.             if ( intersect( ray, plane, ipoint ) )
  364.             {
  365.                 float dst = (ipoint-ray.origin).lengthSqr( );
  366.                 if ( dst < min /*|| min < 0.0f*/ )
  367.                 {
  368.                     xpoint   = ipoint;
  369.                     min      = dst;
  370.                     normal   = plane.normal;
  371.                     material = plane.material;
  372.                 }
  373.             }
  374.         }
  375.  
  376.     }
  377.  
  378.     void incWrap( float &x, float y )
  379.     {
  380.         const float _2PI = 6.28318530718f;
  381.         if ( (x+=y) > _2PI ) x -= _2PI;
  382.     }
  383.  
  384.     int renderRegion( void *arg )
  385.     {
  386. #ifdef _threading
  387.         _InterlockedIncrement( &threads );
  388. #endif
  389.         float hvs = vidSize / 2.0;
  390.  
  391.         SDL_Rect *rect = (SDL_Rect*)arg;
  392.  
  393.         int x1 = rect->x;
  394.         int x2 = rect->x + rect->w;
  395.         int y1 = rect->y;
  396.         int y2 = rect->y + rect->h;
  397.        
  398.         u32 drawColour = 0;
  399.  
  400. #ifdef _threading
  401.         while ( active )
  402.         {
  403. #endif
  404.             for ( int y=y1; y<y2; y++ )
  405.             {
  406.                 for ( int x=x1; x<x2; x++ )
  407.                 {
  408.                     sRay ray( vec3( x-hvs, y-hvs, hvs*2 ) );
  409.                     ray.normal.fnorm( );
  410.  
  411.                     vec3  ipoint;
  412.                     vec3  normal;
  413.                     float dist;
  414.                     u32   material = 0;
  415.  
  416.                     rayShoot( ray, ipoint, normal, material, dist );
  417.  
  418.                     if ( material == 1 )
  419.                     {
  420.                         ray.normal = vec3::reflect( normal, ray.normal );
  421.                         ray.normal.fnorm( );
  422.                         ray.origin = ipoint + ray.normal;
  423.                    
  424.                         rayShoot( ray, ipoint, normal, material, dist );
  425.                     }
  426.                    
  427.                     {
  428.                         //
  429.                         // dot product lighting
  430.                         //
  431.                         vec3 lightNorm = vec3::findNormal( ipoint, light );
  432.                         float dplight = normal * lightNorm;
  433.                         if (  dplight < 0.0f )
  434.                               dplight = 0.0f;
  435.                         u32 dp3 = (u32)( dplight * 255 );
  436.                         drawColour = dp3 | (dp3 << 8) | (dp3 << 16);
  437.  
  438.                         //
  439.                         // shadows
  440.                         //
  441.  
  442.                         // distance from intersection point to light
  443.                         float ldist = vec3::lengthSqr( ipoint, light );
  444.  
  445.                         // trace from light to interection point
  446.                         sRay lightRay( light, ipoint );
  447.                         u32   colour = 0;
  448.                         float mdist  = 0;
  449.                         rayShoot( lightRay, vec3(), vec3(), colour, mdist );
  450.  
  451.                         if ( useShadows )
  452.                         {
  453.                             if ( ldist-1 > mdist )
  454.                                 drawColour = 0; //(drawColour>>1) & 0x7f7f7f;
  455.                         }
  456.  
  457.                     }
  458.  
  459.                     plot( x, y, drawColour );
  460.                 }
  461.             }
  462. #ifdef _threading
  463.         } // while ( active )
  464. #endif
  465.  
  466. #ifdef _threading
  467.         _InterlockedDecrement( &threads );
  468. #endif
  469.         return 1;
  470.     }
  471.  
  472.     void onTick( void )
  473.     {
  474.         static float t=0.0f; incWrap( t, 0.012346f );
  475.         spheres[0].origin.x = sin( (float)t ) * 64.f;
  476.  
  477. #ifndef _threading
  478.         SDL_Rect r1 = { 0  ,   0, vidSize, vidSize };
  479.         renderRegion( &r1 );
  480. #endif
  481.  
  482.         static float g=0.0f; incWrap( g, 0.024243f );
  483.         light.x = sin( g ) * 64;
  484.         light.z = cos( g ) * 64 + (256+128);
  485.     }
  486.  
  487.     void onInit( void )
  488.     {
  489. #ifdef _threading
  490.         int hvs = vidSize / 2;
  491.         SDL_Rect r1 = {     0  ,   0, hvs, hvs };
  492.         SDL_Rect r3 = {     hvs,   0, hvs, hvs };
  493.        
  494.         SDL_Rect r5 = {     0  , hvs, hvs, hvs };
  495.         SDL_Rect r7 = {     hvs, hvs, hvs, hvs };
  496.  
  497.         SDL_CreateThread( renderRegion, &r1 );
  498.         SDL_CreateThread( renderRegion, &r3 );
  499.  
  500.         SDL_CreateThread( renderRegion, &r5 );
  501.         SDL_CreateThread( renderRegion, &r7 );
  502. #endif
  503.     }
  504.  
  505.     void onKeyHit( SDLKey key )
  506.     {
  507.         switch ( key )
  508.         {
  509.         case ( SDLK_SPACE ):
  510.             useShadows = !useShadows;
  511.         }
  512.     }
  513.  
  514. }; // namespace demo
  515. using namespace demo;
  516.  
  517. // ---- ----- ---- ---- ---- ---- ---- ---- FRAMEWORK FUNCIONS
  518. namespace framework
  519. {
  520.     static bool app_init( void )
  521.     {
  522.         if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
  523.             return false;
  524.  
  525.         SDL_WM_SetCaption( app_name, NULL );
  526.  
  527.         screen = SDL_SetVideoMode( scrRes, scrRes, 32, 0 );
  528.         if ( screen == NULL )
  529.             return false;
  530.  
  531.         if ( vidScale == 1 )    video = (u32*)screen->pixels;
  532.         else                    video = new u32[ nPixels ];
  533.  
  534.         return true;
  535.     }
  536.  
  537.     static void blit_2x( void )
  538.     {
  539.         //
  540.         const int stride = screen->w;
  541.  
  542.         u32 *dst = (u32*) screen->pixels;
  543.  
  544.         int a = 0;
  545.  
  546.         for ( int i=0; i<nPixels; i++ )
  547.         {
  548.             u32 colour = video[ i ];
  549.            
  550.             // x4 pixel write
  551.             dst[0       ] = colour;
  552.             dst[1       ] = colour;
  553.             dst[  stride] = colour;
  554.             dst[1+stride] = colour;
  555.  
  556.             dst += 2;
  557.             if ( a++ >= vidSize )
  558.             {
  559.                 a = 0;
  560.                 // add on ONE stride not two since one length
  561.                 // has already been walked
  562.                 dst += stride;
  563.             }
  564.         }
  565.     }
  566.  
  567.     static void app_draw( void )
  568.     {
  569.         if ( vidScale <= 1 )
  570.             return;
  571.  
  572.         if ( vidScale == 2 )
  573.         {
  574.             blit_2x( );
  575.             return;
  576.         }
  577.  
  578.         for ( int i=0; i<nPixels; i++ )
  579.         {
  580.             SDL_Rect rect =
  581.             {
  582.                 (i % vidSize) * vidScale,
  583.                 (i / vidSize) * vidScale,
  584.                                 vidScale,
  585.                                 vidScale
  586.             };
  587.             SDL_FillRect( screen, &rect, video[ i ] );
  588.         }
  589.     }
  590.  
  591.     static bool app_tick( void )
  592.     {
  593.         SDL_Event event;
  594.         while ( SDL_PollEvent( &event ) )
  595.         {
  596.             switch ( event.type )
  597.             {
  598.             case ( SDL_QUIT ):
  599.                 active = false;
  600.                 break;
  601.             case ( SDL_KEYUP ):
  602.                 {
  603.                     if ( event.key.keysym.sym == SDLK_ESCAPE )
  604.                     {
  605.                         active = false;
  606.                     }
  607.                     else
  608.                         onKeyHit( event.key.keysym.sym );
  609.                 }
  610.                 break;
  611.             }
  612.         }
  613.         return active;
  614.     }
  615.  
  616.     static void app_quit( void )
  617.     {
  618.         //
  619.         if ( video != NULL )
  620.             if ( video != screen->pixels )
  621.                 delete [] video;
  622.         video = NULL;
  623.         //
  624.         if ( screen != NULL )
  625.             SDL_FreeSurface( screen );
  626.         //
  627.         SDL_Quit( );
  628.     }
  629.  
  630. }; // namespace framework
  631.  
  632. // windows entry point
  633. int __stdcall WinMain( int, int, int, int )
  634. {
  635.     // start up SDL
  636.     atexit( app_quit );
  637.     if (! app_init( ) )
  638.         return 1;
  639.     // get keyboard access
  640.     u32 keyCount = 0;
  641.     byte *keys = SDL_GetKeyState( (int*) &keyCount );
  642.     // seed the random
  643.     randSeed ^= SDL_GetTicks( );
  644.     // call the on initialize function 
  645.     onInit( );
  646.     //
  647.     int oldTicks = SDL_GetTicks( );
  648.     // work out the tick threshold in milliseconds
  649.     const int tickThresh = 1000 / tickFPS;
  650.     //
  651.     while ( app_tick( ) )
  652.     {
  653.         int diff = SDL_GetTicks() - oldTicks;
  654.  
  655.         if ( diff < 10  )
  656.             SDL_Delay( 10 );
  657.  
  658.         if ( diff > 500 )
  659.         {
  660.             oldTicks += diff;
  661.             continue;
  662.         }
  663.  
  664.         while ( diff > tickThresh )
  665.         {
  666.             // grab the mouse state
  667.             SDL_GetMouseState( &mousex, &mousey );
  668.             // tick the application
  669.             onTick( );
  670.             app_draw( );
  671.             SDL_Flip( screen );
  672.             // progress the tick count
  673.             oldTicks += tickThresh;
  674.             diff     -= tickThresh;
  675.         }
  676.     }
  677.  
  678.     //
  679.     while ( threads > 0 )
  680.         SDL_Delay( 100 );
  681.  
  682.     return 0;
  683. }
RAW Paste Data