home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / raytrace / pxm_ray / pxm_ray.lha / pxm-ray / pixel_trace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-09  |  4.0 KB  |  220 lines

  1.  
  2. /* 
  3.  * This is the actual ray-tracing part
  4.  */
  5.  
  6. /*
  7.  *    (c) 1988 by George Kyriazis
  8.  */
  9.  
  10. #include    "pxm.h"
  11. #include    "ray.h"
  12. #include    <math.h>
  13. #include    "vector.h"
  14.  
  15. struct    intersect    intersect();
  16. struct    color    shade();
  17. struct    color    bgcolor();
  18. double    rnd(), rand();
  19.  
  20. double    quickcos(x)
  21. register    double    x;
  22. {
  23.     register    double    val;
  24.  
  25.     val = 1 - x*x/2.4684;
  26.  
  27.     return val;
  28. }
  29.  
  30. double    quickinvcos(x)
  31. register    double    x;
  32. {
  33.     register    double    val;
  34.  
  35.     val = sqrt(2.4684*(1-x));
  36.  
  37.     return val;
  38. }
  39.  
  40. /*
  41.  * aproximate a gaussian random number generator between -1 and 1
  42.  */
  43. double    grand()
  44. {
  45.     register    double    t;
  46.  
  47.     t = ( rnd() - .5 ) * 2;
  48.  
  49.     return (t*ABS(t));
  50. }
  51. /*
  52.  * pick a random ray somewhere inside the solid angle
  53.  */
  54. struct    ray    sample_ray(r, theta)
  55. struct    ray    r;
  56. double    theta;
  57. {
  58.     double    phi1, phi2;
  59.     double    c[3];    /* directional cosines */
  60.     struct    ray    r2;
  61.  
  62.     phi1 = grand() * theta;
  63.     phi2 = grand() * theta;
  64.  
  65.     c[0] = r.dir.x;
  66.     c[1] = r.dir.y;
  67.     c[2] = r.dir.z;
  68.  
  69. /* Choose two of them that are linearly independant */
  70.     if( c[0] > .5 ) {
  71.         c[0] = quickcos(quickinvcos(c[0]) + phi1);
  72.         c[1] = quickcos(quickinvcos(c[1]) + phi2);
  73.     } else
  74.         if( c[1] < .5 ) {
  75.             c[1] = quickcos(quickinvcos(c[1]) + phi1);
  76.             c[2] = quickcos(quickinvcos(c[2]) + phi2);
  77.         } else {
  78.             c[2] = quickcos(quickinvcos(c[2]) + phi1);
  79.             c[0] = quickcos(quickinvcos(c[0]) + phi2);
  80.         }
  81.  
  82.     norm( c );
  83.  
  84.     r2.pos = r.pos;
  85.     r2.dir.x = c[0];
  86.     r2.dir.y = c[1];
  87.     r2.dir.z = c[2];
  88.     r2.theta = 0;
  89.     r2.obj = r.obj;
  90.  
  91.     return r2;
  92. }
  93.  
  94. struct    color    trace_a_ray(r, n)
  95. struct    ray    r;
  96. int    n;        /* recursion level */
  97. {
  98.     struct    intersect    inter;
  99.     struct    color    col;
  100.     double    m;
  101.  
  102. /* check for intersection with the object */
  103.     inter = intersect(r);
  104. /* if no intersection, return some background color */
  105.     if( inter.obj == NULL ) {
  106.         col = bgcolor(r);
  107.         return col;
  108.     }
  109. /* else calculate the shading function there */
  110.     col = shade(inter, r, n);
  111. /* if the color > 1, that means that the components are too big. Normalize. */
  112.     m = col.r;
  113.     if( col.g > m )
  114.         m = col.g;
  115.     if( col.b > m )
  116.         m = col.b;
  117.     if( m > 1 ) {
  118. /* overflow condition */
  119.         col.r /= m;
  120.         col.g /= m;
  121.         col.b /= m;
  122.     }
  123.     return col;
  124. }
  125.  
  126. struct    color    trace(r, n)
  127. struct    ray    r;
  128. int    n;
  129. {
  130.     struct    color    col;
  131.     struct    ray    r2;
  132.  
  133.     r2 = sample_ray(r, r.theta);
  134.     col = trace_a_ray(r2, n);
  135.  
  136.     return col;
  137. }
  138.  
  139.  
  140. raytrace(screen)
  141. SubScrn    *screen;
  142. {
  143.     int    x, y, x1, y1;
  144.     double    xr, yr;
  145.     struct    ray    ray, r2;
  146.     int    r, g, b;
  147.     struct    color    col, color;
  148.     PixelType    c;
  149.     int    xlo, xhi, ylo, yhi;
  150.     double    re_xlo, re_xhi, re_ylo, re_yhi;
  151.     double    a1, b1, a2, b2;
  152.     int    imin, imax, jmin, jmax;
  153.     register    int    i;
  154.     struct    ray    lns;
  155.     double    p_w;
  156.  
  157.     p_w = fov / MIN(xres, yres);
  158.  
  159.     hor = vcross(up, eye_dir); NORM(hor);
  160.     ver = vcross(eye_dir, hor); NORM(ver);
  161.     ray.pos = eye;
  162.     ray.obj = NULL;        /* not coming from an object */
  163.  
  164. /*
  165.  *    Pixel machine pedendant code.  Calculate the range that
  166.  *     we have to calculate
  167.  */
  168.     xlo = ylo = 0;
  169.     xhi = xres;
  170.     yhi = yres;
  171.  
  172.     re_xlo = -1.; re_xhi = 1.;
  173.     re_ylo = 1.; re_yhi = -1.;
  174.  
  175. /* taken right out of the mandelbrot demo.. */
  176.     a1 = (re_xhi - re_xlo) / (xhi - xlo);
  177.     b1 = re_xlo - a1 * xlo;
  178.     FXTOI( screen, a1, b1 );
  179.  
  180.     a2 = (re_yhi - re_ylo) / (yhi - ylo);
  181.     b2 = re_ylo - a2 * ylo;
  182.     FYTOJ( screen, a2, b2);
  183.  
  184.     imin = ILO( screen, (float) xlo );
  185.     jmin = JLO( screen, (float) ylo );
  186.     imax = IHI( screen, (float) xhi );
  187.     jmax = JHI( screen, (float) yhi );
  188.  
  189.     for( y = jmin; y < jmax; y++) {
  190.         yr = (float) y * a2 + b2;
  191.         for( x = imin; x < imax; x++) {
  192.             xr = (float) x * a1 + b1;
  193. /* field of view calculations */
  194.             ray.dir = vadd( svproduct(xr*fov, hor),
  195.                 svproduct(yr*fov,ver) );
  196.             ray.dir = vadd( ray.dir, eye_dir );
  197.             NORM( ray.dir );
  198.             ray.theta = 0;
  199.             col.r = col.g = col.b = 0;
  200.  
  201.             for(i = tries; i--;) {
  202.                 time = (time2+time1)/2 +
  203.                     (time2-time1)*(i+rand())/tries;
  204.                 r2 = sample_ray(ray, p_w);
  205.                 color = trace_a_ray(r2, 0);
  206.                 col.r += color.r / tries;
  207.                 col.g += color.g / tries;
  208.                 col.b += color.b / tries;
  209.             }
  210.             c.r = (int)(col.r * 65535);
  211.             c.g = (int)(col.g * 65535);
  212.             c.b = (int)(col.b * 65535);
  213.             c.o = 0;
  214.             putpix( screen, x, y, &c);
  215.  
  216.         }
  217.     }
  218.  
  219. }
  220.