home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * This is the actual ray-tracing part
- */
-
- /*
- * (c) 1988 by George Kyriazis
- */
-
- #include "pxm.h"
- #include "ray.h"
- #include <math.h>
- #include "vector.h"
-
- struct intersect intersect();
- struct color shade();
- struct color bgcolor();
- double rnd(), rand();
-
- double quickcos(x)
- register double x;
- {
- register double val;
-
- val = 1 - x*x/2.4684;
-
- return val;
- }
-
- double quickinvcos(x)
- register double x;
- {
- register double val;
-
- val = sqrt(2.4684*(1-x));
-
- return val;
- }
-
- /*
- * aproximate a gaussian random number generator between -1 and 1
- */
- double grand()
- {
- register double t;
-
- t = ( rnd() - .5 ) * 2;
-
- return (t*ABS(t));
- }
- /*
- * pick a random ray somewhere inside the solid angle
- */
- struct ray sample_ray(r, theta)
- struct ray r;
- double theta;
- {
- double phi1, phi2;
- double c[3]; /* directional cosines */
- struct ray r2;
-
- phi1 = grand() * theta;
- phi2 = grand() * theta;
-
- c[0] = r.dir.x;
- c[1] = r.dir.y;
- c[2] = r.dir.z;
-
- /* Choose two of them that are linearly independant */
- if( c[0] > .5 ) {
- c[0] = quickcos(quickinvcos(c[0]) + phi1);
- c[1] = quickcos(quickinvcos(c[1]) + phi2);
- } else
- if( c[1] < .5 ) {
- c[1] = quickcos(quickinvcos(c[1]) + phi1);
- c[2] = quickcos(quickinvcos(c[2]) + phi2);
- } else {
- c[2] = quickcos(quickinvcos(c[2]) + phi1);
- c[0] = quickcos(quickinvcos(c[0]) + phi2);
- }
-
- norm( c );
-
- r2.pos = r.pos;
- r2.dir.x = c[0];
- r2.dir.y = c[1];
- r2.dir.z = c[2];
- r2.theta = 0;
- r2.obj = r.obj;
-
- return r2;
- }
-
- struct color trace_a_ray(r, n)
- struct ray r;
- int n; /* recursion level */
- {
- struct intersect inter;
- struct color col;
- double m;
-
- /* check for intersection with the object */
- inter = intersect(r);
- /* if no intersection, return some background color */
- if( inter.obj == NULL ) {
- col = bgcolor(r);
- return col;
- }
- /* else calculate the shading function there */
- col = shade(inter, r, n);
- /* if the color > 1, that means that the components are too big. Normalize. */
- m = col.r;
- if( col.g > m )
- m = col.g;
- if( col.b > m )
- m = col.b;
- if( m > 1 ) {
- /* overflow condition */
- col.r /= m;
- col.g /= m;
- col.b /= m;
- }
- return col;
- }
-
- struct color trace(r, n)
- struct ray r;
- int n;
- {
- struct color col;
- struct ray r2;
-
- r2 = sample_ray(r, r.theta);
- col = trace_a_ray(r2, n);
-
- return col;
- }
-
-
- raytrace(screen)
- SubScrn *screen;
- {
- int x, y, x1, y1;
- double xr, yr;
- struct ray ray, r2;
- int r, g, b;
- struct color col, color;
- PixelType c;
- int xlo, xhi, ylo, yhi;
- double re_xlo, re_xhi, re_ylo, re_yhi;
- double a1, b1, a2, b2;
- int imin, imax, jmin, jmax;
- register int i;
- struct ray lns;
- double p_w;
-
- p_w = fov / MIN(xres, yres);
-
- hor = vcross(up, eye_dir); NORM(hor);
- ver = vcross(eye_dir, hor); NORM(ver);
- ray.pos = eye;
- ray.obj = NULL; /* not coming from an object */
-
- /*
- * Pixel machine pedendant code. Calculate the range that
- * we have to calculate
- */
- xlo = ylo = 0;
- xhi = xres;
- yhi = yres;
-
- re_xlo = -1.; re_xhi = 1.;
- re_ylo = 1.; re_yhi = -1.;
-
- /* taken right out of the mandelbrot demo.. */
- a1 = (re_xhi - re_xlo) / (xhi - xlo);
- b1 = re_xlo - a1 * xlo;
- FXTOI( screen, a1, b1 );
-
- a2 = (re_yhi - re_ylo) / (yhi - ylo);
- b2 = re_ylo - a2 * ylo;
- FYTOJ( screen, a2, b2);
-
- imin = ILO( screen, (float) xlo );
- jmin = JLO( screen, (float) ylo );
- imax = IHI( screen, (float) xhi );
- jmax = JHI( screen, (float) yhi );
-
- for( y = jmin; y < jmax; y++) {
- yr = (float) y * a2 + b2;
- for( x = imin; x < imax; x++) {
- xr = (float) x * a1 + b1;
- /* field of view calculations */
- ray.dir = vadd( svproduct(xr*fov, hor),
- svproduct(yr*fov,ver) );
- ray.dir = vadd( ray.dir, eye_dir );
- NORM( ray.dir );
- ray.theta = 0;
- col.r = col.g = col.b = 0;
-
- for(i = tries; i--;) {
- time = (time2+time1)/2 +
- (time2-time1)*(i+rand())/tries;
- r2 = sample_ray(ray, p_w);
- color = trace_a_ray(r2, 0);
- col.r += color.r / tries;
- col.g += color.g / tries;
- col.b += color.b / tries;
- }
- c.r = (int)(col.r * 65535);
- c.g = (int)(col.g * 65535);
- c.b = (int)(col.b * 65535);
- c.o = 0;
- putpix( screen, x, y, &c);
-
- }
- }
-
- }
-