Guest User

Raytace3.cpp

a guest
Jan 9th, 2014
46
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       = 196;
  24.  
  25.     // pixel size
  26.     const int vidScale      = 3;
  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.     inline float isqrtf( float number )
  259.     {
  260.         long i;
  261.         float x2, y;
  262.         const float threehalfs = 1.5F;
  263.  
  264.         x2 = number * 0.5F;
  265.         y  = number;
  266.         i  = * ( long * ) &y;                       // evil floating point bit level hacking
  267.         i  = 0x5f3759df - ( i >> 1 );               // what the fuck?
  268.         y  = * ( float * ) &i;
  269.         y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
  270.         y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed
  271.         return y;
  272.     }
  273.  
  274.     struct vec3
  275.     {
  276.         float x, y, z;
  277.  
  278.         vec3( )
  279.             : x( 0 ), y( 0 ), z( 0 )
  280.         {
  281.         }
  282.  
  283.         vec3( float _tx, float _ty, float _tz )
  284.             : x( _tx ), y( _ty ), z( _tz )
  285.         {
  286.         }
  287.  
  288.         void fnorm( void )
  289.         {
  290.             float d = isqrtf( x*x + y*y + z*z );
  291.             x *= d;
  292.             y *= d;
  293.             z *= d;
  294.         }
  295. /*
  296.         void norm( void )
  297.         {
  298.             float d = 1.0f / sqrtf( x*x + y*y + z*z );
  299.             x *= d;
  300.             y *= d;
  301.             z *= d;
  302.         }
  303.  */
  304.  
  305.         vec3 project( vec3 &a )
  306.         {
  307.             return (*this) * ((a * (*this)) / length( ));
  308.         }
  309.  
  310.         vec3 operator - ( const vec3 &a ) const
  311.         {
  312.             return vec3( x - a.x, y - a.y, z - a.z );
  313.         }
  314.  
  315.         vec3 operator + ( const vec3 &a ) const
  316.         {
  317.             return vec3( x + a.x, y + a.y, z + a.z );
  318.         }
  319.  
  320.         float operator * ( const vec3 &a )
  321.         {
  322.             return x*a.x + y*a.y + z*a.z;
  323.         }
  324.  
  325.         vec3 operator * ( const float s )
  326.         {
  327.             return vec3( x*s, y*s, z*s );
  328.         }
  329.  
  330.         float length( void )
  331.         {
  332.             return sqrt( lengthSqr() );
  333.         }
  334.  
  335.         float lengthSqr( void )
  336.         {
  337.             return x*x + y*y + z*z;
  338.         }
  339.  
  340.         static vec3 findNormal( const vec3 &s, const vec3 &d )
  341.         {
  342.             vec3 n = d - s;
  343.             n.fnorm( );
  344.             return n;
  345.         }
  346.  
  347.         static float lengthSqr( const vec3 &s, const vec3 &d )
  348.         {
  349.             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);
  350.         }
  351.  
  352.     };
  353.  
  354.     struct sSphere
  355.     {
  356.         sSphere( )
  357.             : origin( 0, 0, 0 ), radius( 0 )
  358.         {
  359.         }
  360.  
  361.         sSphere( vec3 &center, float r )
  362.             : origin( center ), radius( r )
  363.         {
  364.         }
  365.  
  366.         sSphere( vec3 &center, float r, u32 c )
  367.             : origin( center ), radius( r ), colour( c )
  368.         {
  369.         }
  370.  
  371.         vec3   origin;
  372.         float radius;
  373.         u32    colour;
  374.     };
  375.  
  376.     struct sPlane
  377.     {
  378.         vec3  normal;
  379.         float offset;
  380.         u32   colour;
  381.     };
  382.  
  383.     struct sRay
  384.     {  
  385.         sRay( )
  386.         {
  387.         }
  388.  
  389.         sRay( vec3 &a )
  390.             : origin( ), normal( a )
  391.         {
  392.         }
  393.  
  394.         sRay( vec3 &a, vec3 &b )
  395.         {
  396.             origin = a;
  397.             normal = b - a;
  398.             normal.fnorm( );
  399.         }
  400.  
  401.         vec3 origin;
  402.         vec3 normal;
  403.     };
  404.  
  405.     //
  406.     // precise ray intersection test
  407.     //
  408.     bool intersect( sRay &ray, sSphere &sphere, vec3 &ipoint )
  409.     {
  410.         float t1 = -1;
  411.         float t2 = -1;
  412.         float discriminent;
  413.         float t = -1;
  414.         //temporary == e-c
  415.         vec3 temp = ray.origin - sphere.origin;
  416.         float b = 2 * (ray.normal * temp);
  417.         float a = ray.normal * ray.normal;
  418.         float c = temp * temp - (sphere.radius * sphere.radius);
  419.         float disc;
  420.         disc = b*b - 4*a*c;
  421.         if ( disc < 0 )
  422.             return false;
  423.         else
  424.         {
  425.             discriminent = 1.0f / isqrtf( disc );
  426.             t1 = (-b+discriminent)/(2*a);
  427.             t2 = (-b-discriminent)/(2*a);  
  428.  
  429.             if (t2 > 0)
  430.             {
  431.                 ipoint = ray.origin + ray.normal * t2;
  432.                 return true;
  433.             }
  434.             if ( t1 > 0 )
  435.             {
  436.                 ipoint = ray.origin + ray.normal * t1;
  437.                 return true;
  438.             }
  439.         }
  440.         return false;
  441.     }
  442.    
  443.     bool intersect( sRay &ray, sPlane &plane, vec3 &ipoint )
  444.     {
  445.         float t = - ( ray.origin * plane.normal + plane.offset ) / ( ray.normal * plane.normal );
  446.         ipoint = ray.origin + ray.normal * t;
  447.         return (t > 0);
  448.     }
  449.    
  450.     const int nSpheres = 3;
  451.  
  452.     sSphere spheres[ nSpheres ] =
  453.     {
  454.         sSphere( vec3(   0, 128.f - 128.f, 420        ), 32.f, randColour( ) ),
  455.         sSphere( vec3( -64, 128.f -  48.f, 512.f-64.f ), 64.f, randColour( ) ),
  456.         sSphere( vec3(  32, 128.f -  32.f, 360        ), 32.f, randColour( ) )
  457.     };
  458.  
  459.     sPlane planes[] =
  460.     {
  461.         { vec3( 0,-1, 0), 128.0f, 0xC0D0E0 },
  462.         { vec3( 0, 1, 0), 128.0f, 0xC0D0E0 },
  463.         { vec3( 0, 0,-1), 512.0f, 0xC0D0E0 },
  464.         { vec3( 1, 0, 0), 128.0f, 0xFF7070 },
  465.         { vec3(-1, 0, 0), 128.0f, 0x70FF70 }
  466.     };
  467.    
  468.     vec3 light( 0,-120, 256+128 );
  469.    
  470.     bool useShadows = true;
  471.  
  472.     void onInit( void )
  473.     {
  474.     }
  475.  
  476.  
  477.     void onKeyHit( SDLKey key )
  478.     {
  479.         switch ( key )
  480.         {
  481.         case ( SDLK_SPACE ):
  482.             useShadows = !useShadows;
  483.         }
  484.     }
  485.  
  486.     void rayShoot( sRay &ray, vec3 &xpoint, vec3 &normal, u32 &colour, float &min )
  487.     {
  488.         min = 99999999.f;
  489.         vec3  ipoint;
  490.  
  491.         // sphere intersections
  492.         for ( int i=0; i<nSpheres; i++ )
  493.         {
  494.             sSphere &sphere = spheres[ i ];
  495.             if ( intersect( ray, sphere, ipoint ) )
  496.             {
  497.                 float dst = (ipoint-ray.origin).lengthSqr( );
  498.                 if ( dst < min /*|| min < 0.0f*/ )
  499.                 {
  500.                     xpoint      = ipoint;
  501.                     float irad  = 1.0f / sphere.radius;
  502.                     min         = dst;
  503.                     normal      = (ipoint - sphere.origin);
  504.                     normal.x   *= irad;
  505.                     normal.y   *= irad;
  506.                     normal.z   *= irad;
  507.                     colour      = sphere.colour;
  508.                 }
  509.             }
  510.         }
  511.  
  512.         // plane intersections
  513.         for ( int i=0; i<5; i++ )
  514.         {
  515.             sPlane &plane = planes[i];
  516.             if ( intersect( ray, plane, ipoint ) )
  517.             {
  518.                 float dst = (ipoint-ray.origin).lengthSqr( );
  519.                 if ( dst < min /*|| min < 0.0f*/ )
  520.                 {
  521.                     xpoint = ipoint;
  522.                     min    = dst;
  523.                     normal = plane.normal;
  524.                     colour = plane.colour;
  525.                 }
  526.             }
  527.         }
  528.  
  529.     }
  530.  
  531.     void incWrap( float &x, float y )
  532.     {
  533.         const float _2PI = 6.28318530718f;
  534.         if ( (x+=y) > _2PI ) x -= _2PI;
  535.     }
  536.  
  537.     void onTick( void )
  538.     {
  539.         float hvs = vidSize / 2.0;
  540.  
  541.         for ( int y=0; y<vidSize; y++ )
  542.             for ( int x=0; x<vidSize; x++ )
  543.             {
  544.                 sRay ray( vec3( x-hvs, y-hvs, hvs*2 ) );
  545.                 ray.normal.fnorm( );
  546.  
  547.                 vec3  ipoint;
  548.                 vec3  normal;
  549.                 float dist;
  550.  
  551.                 rayShoot( ray, ipoint, normal, drawColour, dist );
  552.  
  553.                 //
  554.                 // dot product lighting
  555.                 //
  556.                 vec3 lightNorm = vec3::findNormal( ipoint, light );
  557.                 float dplight = normal * lightNorm;
  558.                 if (  dplight < 0.0f )
  559.                       dplight = 0.0f;
  560.                 u32 dp3 = (u32)( dplight * 255 );
  561.                 drawColour = dp3 | (dp3 << 8) | (dp3 << 16);
  562.  
  563.                 //
  564.                 // shadows
  565.                 //
  566.  
  567.                 // distance from intersection point to light
  568.                 float ldist = vec3::lengthSqr( ipoint, light );
  569.  
  570.                 // trace from light to interection point
  571.                 sRay lightRay( light, ipoint );
  572.                 u32   colour = 0;
  573.                 float mdist  = 0;
  574.                 rayShoot( lightRay, vec3(), vec3(), colour, mdist );
  575.                                
  576.                 if ( useShadows )
  577.                 {
  578.                     if ( ldist-1 > mdist )
  579.                         drawColour = 0; //(drawColour>>1) & 0x7f7f7f;
  580.                 }
  581.  
  582.                 plot( x, y );
  583.             }
  584.  
  585.         static float t=0.0f; incWrap( t, 0.012346f );
  586.         spheres[0].origin.x = sin( (float)t ) * 64.f;
  587.  
  588.        
  589.         static float g=0.0f; incWrap( g, 0.024243f );
  590.         light.x = sin( g ) * 64;
  591.         light.z = cos( g ) * 64 + (256+128);
  592.        
  593.     }
  594.  
  595. }; // namespace demo
  596. using namespace demo;
  597.  
  598. // ---- ----- ---- ---- ---- ---- ---- ---- FRAMEWORK FUNCIONS
  599. namespace framework
  600. {
  601.     static bool app_init( void )
  602.     {
  603.         if ( SDL_Init( SDL_INIT_VIDEO ) != 0 )
  604.             return false;
  605.  
  606.         SDL_WM_SetCaption( app_name, NULL );
  607.  
  608.         screen = SDL_SetVideoMode( scrRes, scrRes, 32, 0 );
  609.         if ( screen == NULL )
  610.             return false;
  611.  
  612.         if ( vidScale == 1 )    video = (u32*)screen->pixels;
  613.         else                    video = new u32[ nPixels ];
  614.  
  615.         return true;
  616.     }
  617.  
  618.     static void blit_2x( void )
  619.     {
  620.         //
  621.         const int stride = screen->w;
  622.  
  623.         u32 *dst = (u32*) screen->pixels;
  624.  
  625.         int a = 0;
  626.  
  627.         for ( int i=0; i<nPixels; i++ )
  628.         {
  629.             u32 colour = video[ i ];
  630.            
  631.             // x4 pixel write
  632.             dst[0       ] = colour;
  633.             dst[1       ] = colour;
  634.             dst[  stride] = colour;
  635.             dst[1+stride] = colour;
  636.  
  637.             dst += 2;
  638.             if ( a++ >= vidSize )
  639.             {
  640.                 a = 0;
  641.                 // add on ONE stride not two since one length
  642.                 // has already been walked
  643.                 dst += stride;
  644.             }
  645.         }
  646.     }
  647.  
  648.     static void app_draw( void )
  649.     {
  650.         if ( vidScale <= 1 )
  651.             return;
  652.  
  653.         if ( vidScale == 2 )
  654.         {
  655.             blit_2x( );
  656.             return;
  657.         }
  658.  
  659.         for ( int i=0; i<nPixels; i++ )
  660.         {
  661.             SDL_Rect rect =
  662.             {
  663.                 (i % vidSize) * vidScale,
  664.                 (i / vidSize) * vidScale,
  665.                                 vidScale,
  666.                                 vidScale
  667.             };
  668.             SDL_FillRect( screen, &rect, video[ i ] );
  669.         }
  670.     }
  671.  
  672.     static bool app_tick( void )
  673.     {
  674.         static bool active = true;
  675.  
  676.         SDL_Event event;
  677.         while ( SDL_PollEvent( &event ) )
  678.         {
  679.             switch ( event.type )
  680.             {
  681.             case ( SDL_QUIT ):
  682.                 active = false;
  683.                 break;
  684.             case ( SDL_KEYUP ):
  685.                 {
  686.                     if ( event.key.keysym.sym == SDLK_ESCAPE )
  687.                         active = false;
  688.                     else
  689.                         onKeyHit( event.key.keysym.sym );
  690.                 }
  691.                 break;
  692.             }
  693.         }
  694.         return active;
  695.     }
  696.  
  697.     static void app_quit( void )
  698.     {
  699.         //
  700.         if ( video != NULL )
  701.             if ( video != screen->pixels )
  702.                 delete [] video;
  703.         video = NULL;
  704.         //
  705.         if ( screen != NULL )
  706.             SDL_FreeSurface( screen );
  707.         //
  708.         SDL_Quit( );
  709.     }
  710.  
  711. }; // namespace framework
  712.  
  713. // windows entry point
  714. int __stdcall WinMain( int, int, int, int )
  715. {
  716.     // start up SDL
  717.     atexit( app_quit );
  718.     if (! app_init( ) )
  719.         return 1;
  720.     // get keyboard access
  721.     u32 keyCount = 0;
  722.     byte *keys = SDL_GetKeyState( (int*) &keyCount );
  723.     // seed the random
  724.     randSeed ^= SDL_GetTicks( );
  725.     // call the on initialize function 
  726.     onInit( );
  727.     //
  728.     int oldTicks = SDL_GetTicks( );
  729.     // work out the tick threshold in milliseconds
  730.     const int tickThresh = 1000 / tickFPS;
  731.     //
  732.     while ( app_tick( ) )
  733.     {
  734.         int diff = SDL_GetTicks() - oldTicks;
  735.  
  736.         if ( diff < 10  )
  737.             SDL_Delay( 10 );
  738.  
  739.         if ( diff > 500 )
  740.         {
  741.             oldTicks += diff;
  742.             continue;
  743.         }
  744.  
  745.         while ( diff > tickThresh )
  746.         {
  747.             // grab the mouse state
  748.             SDL_GetMouseState( &mousex, &mousey );
  749.             // tick the application
  750.             onTick( );
  751.             app_draw( );
  752.             SDL_Flip( screen );
  753.             // progress the tick count
  754.             oldTicks += tickThresh;
  755.             diff     -= tickThresh;
  756.         }
  757.     }
  758.     return 0;
  759. }
RAW Paste Data