home *** CD-ROM | disk | FTP | other *** search
/ Altsys Virtuoso 2.0K / virtuoso_20k.iso / DemoApps / Graphics / Viewers / raytracers / rpi / Source / trace.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-08  |  5.0 KB  |  254 lines

  1.  
  2. /*
  3.  * (c) 1988 by George Kyriazis
  4.  */
  5.  
  6. /* 
  7.  * This is the actual ray-tracing part
  8.  */
  9.  
  10. #include    "ray.h"
  11. #include    "vector.h"
  12. #include    <stdio.h>
  13. #include    <math.h>
  14.  
  15. struct    intersect    intersect();
  16. struct    color    shade();
  17. struct    color    bgcolor();
  18.  
  19. double    quickcos(x)
  20. double    x;
  21. {
  22.     double    val;
  23.  
  24.     val = 1 - x*x/2.4684;
  25.  
  26.     return val;
  27. }
  28.  
  29. double    quickinvcos(x)
  30. double    x;
  31. {
  32.     double    val;
  33.  
  34.     val = sqrt(2.4684*(1-x));
  35.  
  36.     return val;
  37. }
  38.  
  39. /*
  40.  * floating point random number generator
  41.  */
  42. double    rnd()
  43. {
  44.     double    t;
  45.  
  46.     t = (double)( random() & 0xffffff ) / 16777215;
  47.  
  48.     return t;
  49. }
  50.  
  51. /*
  52.  * Random number between -1 and 1
  53.  */
  54. double    rand1()
  55. {
  56.     return ( rnd()*2 - .5 );
  57. }
  58.  
  59. /*
  60.  * approximate a gaussian random number generator between -1 and 1
  61.  */
  62. double    grand()
  63. {
  64.     double    t;
  65.  
  66. /* get a random number between -1 and 1 */
  67.     t = ( rnd() - .5 ) * 2;
  68.  
  69. /* and then square it.  DOn't lose the sign! */
  70.     return (t*ABS(t));
  71. }
  72.  
  73. /*
  74.  * pick a random ray somewhere inside the solid angle
  75.  */
  76. struct    ray    sample_ray(r, theta)
  77. struct    ray    r;
  78. double    theta;
  79. {
  80.     double    phi1, phi2;
  81.     struct    vector    c;    /* directional cosines */
  82.     struct    ray    r2;
  83.  
  84. /*
  85.  * adds the following 2 angles in 2 of the 3 angles specified by the
  86.  * directional cosines
  87.  */
  88.     phi1 = grand() * theta;
  89.     phi2 = grand() * theta;
  90.  
  91.     c = r.dir;
  92.  
  93. /* choose two of them that are linearly independent */
  94.     if( c.x > .5 ) {
  95.         c.x = quickcos(quickinvcos(c.x) + phi1);
  96.         c.y = quickcos(quickinvcos(c.y) + phi2);
  97.     } else
  98.         if( c.y < .5 ) {
  99.             c.y = quickcos(quickinvcos(c.y) + phi1);
  100.             c.z = quickcos(quickinvcos(c.z) + phi2);
  101.         } else {
  102.             c.z = quickcos(quickinvcos(c.z) + phi1);
  103.             c.x = quickcos(quickinvcos(c.x) + phi2);
  104.         }
  105.  
  106. /* the third directional cosine is fixed when normalizing */
  107.     r2.pos = r.pos;
  108.     r2.dir = norm( c );
  109.     r2.theta = 0;
  110.     r2.obj = r.obj;
  111.  
  112.     return r2;
  113. }
  114.  
  115. /*
  116.  * trace a single strait ray
  117.  */
  118. struct    color    trace_a_ray(r, n)
  119. struct    ray    r;
  120. int    n;        /* recursion level */
  121. {
  122.     struct    intersect    inter;
  123.     struct    color    col;
  124.     double    m;
  125.  
  126. /* update stats */
  127.     rayline++;
  128. /* check for intersection with the object */
  129.     inter = intersect(r);
  130. /* if no intersection, return some background color */
  131.     if( inter.obj == NULL )
  132.         return bgcolor(r);
  133. /* more stats */
  134.     intersectline++;
  135. /* else calculate the shading function there */
  136.     col = shade(inter, r, n);
  137. /* if the color > 1, that means that the components are too big. Normalize. */
  138.     m = col.r;
  139.     if( col.g > m )
  140.         m = col.g;
  141.     if( col.b > m )
  142.         m = col.b;
  143.     if( m > 1 ) {
  144. /* overflow condition */
  145. /* normalize it! */
  146.         col.r /= m;
  147.         col.g /= m;
  148.         col.b /= m;
  149.     }
  150.     return col;
  151. }
  152.  
  153. /*
  154.  * Trace a ray within the specified solid angle
  155.  */
  156. struct    color    trace(r, n)
  157. struct    ray    r;
  158. int    n;
  159. {
  160.     struct    ray    r2;
  161.  
  162.     r2 = sample_ray(r, r.theta);
  163.  
  164.     return ( trace_a_ray(r2, n) );
  165. }
  166.  
  167. /*
  168.  * raytrace the whole scene
  169.  */
  170. raytrace(fname)
  171. char    *fname;
  172. {
  173.     int    x, y, x1, y1;
  174.     double    xr, yr, xstep, ystep;
  175.     struct    color    col, color;
  176.     struct    ray    ray, r2;
  177.     int    r, g, b;
  178.     double    m;
  179.     FILE    *f;
  180.     int    i;
  181.     double    p_w;
  182.  
  183.     p_w = fov / MIN(xres, yres);    /* pixel width in radians */
  184.  
  185.     hor = norm( vcross(up, eye_dir) );    /* the x screen vector */
  186.     ver = norm( vcross( eye_dir, hor) );    /* the y screen vector */
  187.  
  188.     f = fopen(fname, "w");
  189.     if(f == NULL) {
  190.         perror("fopen");
  191.         exit(1);
  192.     }
  193.  
  194.     ray.pos = eye;        /* eye is the beginning of the ray */
  195.  
  196.     ray.obj = NULL;        /* not coming from an object */
  197.  
  198.     fwrite(&xres, sizeof(long int), 1, f);
  199.     fwrite(&yres, sizeof(long int), 1, f);
  200.  
  201.     yr = 1.;
  202.     xstep = 2. / xres; ystep = 2. / yres;
  203.     for(y = 0; y < yres;y++) {
  204.         xr = -1.;
  205.         for(x = 0; x < xres; x++) {
  206.         /* ray direction calculations */
  207.             ray.dir = vadd( svproduct(xr*fov, hor),
  208.                 svproduct(yr*fov, ver) );
  209.             ray.dir = norm( vadd( ray.dir, eye_dir) );
  210.             ray.theta = 0;
  211.             col.r = col.g = col.b = 0;
  212.  
  213. /* the time blur has to be done in linear time and not randomly */
  214. /* randomization is used so we won't get the strobo effect      */
  215.             for( i = tries; i--; ) {
  216.                 Time = (time2+time1)/2 +
  217.                     (time2-time1)*(i+rand1())/tries;
  218.                 r2 = sample_ray(ray, p_w);
  219.                 color = trace_a_ray(r2, 0);
  220.             /* sum all the intensities together */
  221.                 col.r += color.r / tries;
  222.                 col.g += color.g / tries;
  223.                 col.b += color.b / tries;
  224.             }
  225.         /* calc the integer value to be put to the file */
  226.             r = col.r * 255;
  227.             g = col.g * 255;
  228.             b = col.b * 255;
  229.             putc(r,f);
  230.             putc(g,f);
  231.             putc(b,f);
  232.  
  233.             xr += xstep;
  234.         }
  235.         yr -= ystep;
  236.         printf("Finished scanline %d. r:%.2lf/%d sh:%d rl:%d rr:%d int:%d\n",
  237.             y, (double)rayline / yres,  rayline, shadowline,
  238.             reflectline, refractline, intersectline);
  239.     /* update statistics */
  240.         raycount += rayline; rayline = 0;
  241.         shadowcount += shadowline; shadowline = 0;
  242.         reflectcount += reflectline; reflectline = 0;
  243.         refractcount += refractline; refractline = 0;
  244.         intersectcount += intersectline; intersectline = 0;
  245.         objtestcount += objtestline; objtestline = 0;
  246.     }
  247.     printf("\nTotal number of rays traced: %d\n", raycount);
  248.     printf("Total number of not shadowed intersections: %d\n", shadowcount);
  249.     printf("Total reflected rays traced: %d\n", reflectcount);
  250.     printf("Total refracted rays traced: %d\n", refractcount);
  251.     printf("Total object intersections: %d\n", intersectcount);
  252.     printf("Total objects tested: %d\n", objtestcount);
  253. }
  254.