home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / macraysh.sit / Code / Source / viewing.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-28  |  8.4 KB  |  272 lines

  1. /*
  2.  * viewing.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: viewing.c,v 4.0 91/07/17 14:48:18 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    viewing.c,v $
  19.  * Revision 4.0  91/07/17  14:48:18  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include "rayshade.h"
  24. #include "viewing.h"
  25. #include "sampling.h"
  26. #include "options.h"
  27. #include "defaults.h"
  28. #include "picture.h"
  29. #include "stats.h"
  30.  
  31. RSCamera    Camera;
  32. RSScreen    Screen;
  33.  
  34. void SampleScreen(), SampleScreenFiltered();
  35.  
  36. void
  37. RSViewing()
  38. {
  39.     Float magnitude;
  40.  
  41.     VecSub(Camera.lookp, Camera.pos, &Camera.dir);
  42.     Screen.firstray = Camera.dir;
  43.  
  44.     Camera.lookdist = VecNormalize(&Camera.dir);
  45.     if (VecNormCross(&Camera.dir, &Camera.up, &Screen.scrni) == 0.)
  46.         RLerror(RL_PANIC,
  47.             "The view and up directions are identical?\n",0,0,0);
  48.     (void)VecNormCross(&Screen.scrni, &Camera.dir, &Screen.scrnj);
  49.  
  50.     /*
  51.      * Add stereo separation if desired.
  52.      */
  53.     if (Options.stereo) {
  54.         if (Options.stereo == LEFT)
  55.             magnitude = -.5 * Options.eyesep;
  56.         else
  57.             magnitude =  .5 * Options.eyesep;
  58.         Camera.pos.x += magnitude * Screen.scrni.x;
  59.         Camera.pos.y += magnitude * Screen.scrni.y;
  60.         Camera.pos.z += magnitude * Screen.scrni.z;
  61.         VecSub(Camera.lookp, Camera.pos, &Screen.firstray);
  62.         Camera.dir = Screen.firstray;
  63.         Camera.lookdist = VecNormalize(&Camera.dir);
  64.         (void)VecNormCross(&Camera.dir, &Camera.up, &Screen.scrni);
  65.         (void)VecNormCross(&Screen.scrni, &Camera.dir, &Screen.scrnj);
  66.     }
  67.  
  68.     magnitude = 2.*Camera.lookdist * tan(deg2rad(0.5*Camera.hfov)) /
  69.                 Screen.xres;
  70.  
  71.     VecScale(magnitude, Screen.scrni, &Screen.scrnx);
  72.     magnitude = 2.*Camera.lookdist * tan(deg2rad(0.5*Camera.vfov)) /
  73.                 Screen.yres;
  74.     VecScale(magnitude, Screen.scrnj, &Screen.scrny);
  75.  
  76.     Screen.firstray.x -= 0.5*Screen.yres*Screen.scrny.x +
  77.                  0.5*Screen.xres*Screen.scrnx.x;
  78.     Screen.firstray.y -= 0.5*Screen.yres*Screen.scrny.y +
  79.                  0.5*Screen.xres*Screen.scrnx.y;
  80.     Screen.firstray.z -= 0.5*Screen.yres*Screen.scrny.z +
  81.                  0.5*Screen.xres*Screen.scrnx.z;
  82.  
  83.     if (Camera.focaldist == UNSET)
  84.         Camera.focaldist = Camera.lookdist;
  85. }
  86.  
  87. /*
  88.  * Adjust the initial ray to account for an aperture and a focal
  89.  * distance.  The ray argument is assumed to be an initial ray, and
  90.  * always reset to the eye point.  It is assumed to be unit length.
  91.  */
  92. void
  93. focus_blur_ray(ray)
  94. Ray *ray;
  95. {
  96.     Vector circle_point, aperture_inc;
  97.     extern void UnitCirclePoint();
  98.     /*
  99.      * Find a point on a unit circle and scale by aperture size.
  100.      * This simulates rays passing thru different parts of the aperture.
  101.      * Treat the point as a vector and rotate it so the circle lies
  102.      * in the plane of the screen.  Add the aperture increment to the
  103.      * starting position of the ray.  Stretch the ray to be focaldist 
  104.      * in length.  Subtract the aperture increment from the end of the
  105.      * long ray.  This insures that the ray heads toward a point at
  106.      * the specified focus distance, so that point will be in focus.
  107.      * Normalize the ray, and that's it.  Really.
  108.      */
  109.     UnitCirclePoint(&circle_point, ray->sample);
  110.     VecComb(Camera.aperture * circle_point.x, Screen.scrni,
  111.             Camera.aperture * circle_point.y, Screen.scrnj,
  112.             &aperture_inc);
  113.     VecAdd(aperture_inc, Camera.pos, &(ray->pos));
  114.     VecScale(Camera.focaldist, ray->dir, &(ray->dir));
  115.     VecSub(ray->dir, aperture_inc, &(ray->dir));
  116.     (void)VecNormalize(&ray->dir);
  117. }
  118.  
  119. void
  120. ViewingSetup()
  121. {
  122. #define SWAP(a,b)     (tmp = (a), (a) = (b), (b) = tmp)
  123.  
  124.       Float tmp;
  125.       int xwidth, ywidth;
  126.  
  127.     if (Options.stereo && Options.eyesep == UNSET)
  128.         RLerror(RL_PANIC,
  129.             "No eye separation specified for stereo rendering.\n",0,0,0);
  130.     /*
  131.      * Because we want the user to be able to override the input file
  132.      * through the command line, we have to initialize some variables to
  133.      * bogus values so that when the file is being parsed, it is
  134.      * possible to tell if a given variable has been set on the
  135.      * command line.
  136.      *
  137.      * If such variables are not set to legal values on the command
  138.      * line or in the input file, we must do it here.
  139.      */
  140.     if (Screen.xres == UNSET)
  141.         Screen.xres = XRESOLUTION;
  142.     if (Screen.yres == UNSET)
  143.         Screen.yres = YRESOLUTION;
  144.  
  145.       /*
  146.        * The window to be rendered is defined by applying
  147.        * the crop window to the sub window.  The subwindow
  148.        * is defined using pixel numbers, and must be within
  149.        * [0, xres -1],[0, yres -1].  The default is the entire
  150.        * screen.  The crop window is specified using normalized
  151.        * coordinates.
  152.        */
  153.  
  154.       if (!Options.window_set) {
  155.               /* If no window set, set equal to entire screen. */
  156.               Options.window[LOW][X] = Options.window[LOW][Y] = 0;
  157.               Options.window[HIGH][X] = Screen.xres -1;
  158.               Options.window[HIGH][Y] = Screen.yres -1;
  159.       }
  160.  
  161.     /* Truncate crop window to legal limits. */
  162.     if (Options.crop[LOW][X] > Options.crop[HIGH][X])
  163.         SWAP(Options.crop[LOW][X], Options.crop[HIGH][X]);
  164.     if (Options.crop[LOW][Y] > Options.crop[HIGH][Y])
  165.         SWAP(Options.crop[LOW][Y], Options.crop[HIGH][Y]);
  166.     if (Options.crop[LOW][X] < 0.) Options.crop[LOW][X] = 0.;
  167.     if (Options.crop[LOW][Y] < 0.) Options.crop[LOW][Y] = 0.;
  168.     if (Options.crop[HIGH][X] > 1.) Options.crop[HIGH][X] = 1.;
  169.     if (Options.crop[HIGH][Y] > 1.) Options.crop[HIGH][Y] = 1.;
  170.  
  171.     xwidth = Options.window[HIGH][X] - Options.window[LOW][X];
  172.     ywidth = Options.window[HIGH][Y] - Options.window[LOW][Y];
  173.  
  174.     /* Compute x and y extents of window to be renered. */
  175.     Screen.minx = (int)(Options.window[LOW][X] + Options.crop[LOW][X] * xwidth);
  176.     Screen.maxx = (int)(Options.window[LOW][X] + Options.crop[HIGH][X] * xwidth);
  177.     Screen.miny = (int)(Options.window[LOW][Y] + Options.crop[LOW][Y] * ywidth);
  178.     Screen.maxy = (int)(Options.window[LOW][Y] + Options.crop[HIGH][Y] * ywidth);
  179.  
  180. /*    if (Options.xmin < 0.) Options.xmin = 0.;
  181.     if (Options.ymin < 0.) Options.ymin = 0.;
  182.     if (Options.xmax > 1.) Options.xmax = 1.;
  183.     if (Options.xmax > 1.) Options.xmax = 1.;
  184.  
  185.     Screen.minx = (int)(Options.xmin * Screen.xres);
  186.     Screen.maxx = (int)(Options.xmax * Screen.xres -1);
  187.     Screen.miny = (int)(Options.ymin * Screen.yres);
  188.     Screen.maxy = (int)(Options.ymax * Screen.yres -1); */
  189.  
  190.     Screen.xsize = Screen.maxx - Screen.minx + 1;
  191.     Screen.ysize = Screen.maxy - Screen.miny + 1;
  192.  
  193.     /*
  194.      * Sanity check.
  195.      */
  196.     if (Screen.minx < 0 || Screen.miny < 0 ||
  197.         Screen.maxx >= Screen.xres || Screen.maxy >= Screen.yres)
  198.         RLerror(RL_PANIC, "Invalid window specification.\n",0,0,0);
  199.  
  200.     /*
  201.      * If not defined in the input file, calculate VFOV
  202.      * by hand.  This assumes that pixels are square, which is
  203.      * probably a bad idea.  ("aspect" option?)
  204.      */
  205.     if (Camera.vfov == UNSET)
  206.         Camera.vfov = Camera.hfov * Screen.yres / Screen.xres;
  207. }
  208.  
  209. void
  210. SampleScreenFiltered(x, y, u, v, ray, color, sample)
  211. Float x, y;
  212. Ray *ray;
  213. Pixel *color;
  214. int sample, u, v;
  215. {
  216.     SampleScreen(x, y, ray, color, sample);
  217.     color->r *= Sampling.filter[u][v];
  218.     color->g *= Sampling.filter[u][v];
  219.     color->b *= Sampling.filter[u][v];
  220.     color->alpha *= Sampling.filter[u][v];
  221. }    
  222.  
  223. void
  224. SampleScreen(x, y, ray, color, sample)
  225. Float x, y;        /* Screen position to sample */
  226. Ray *ray;        /* ray, with origin and medium properly set */
  227. Pixel *color;        /* resulting color */
  228. int sample;        /* sample number */
  229. {
  230.     Float dist;
  231.     HitList hitlist;
  232.     Color ctmp, fullintens;
  233.     extern void focus_blur_ray(), ShadeRay();
  234.  
  235.     /*
  236.      * Calculate ray direction.
  237.      */
  238.     Stats.EyeRays++;
  239.     ray->dir.x = Screen.firstray.x + x*Screen.scrnx.x + y*Screen.scrny.x;
  240.     ray->dir.y = Screen.firstray.y + x*Screen.scrnx.y + y*Screen.scrny.y;
  241.     ray->dir.z = Screen.firstray.z + x*Screen.scrnx.z + y*Screen.scrny.z;
  242.  
  243.     (void)VecNormalize(&ray->dir);
  244.  
  245.     ray->sample = sample;
  246.  
  247.     if (Camera.aperture > 0.0) {
  248.         /*
  249.          * If the aperture is open, adjust the initial ray
  250.          * to account for depth of field.  
  251.          */
  252.         focus_blur_ray(ray);
  253.     }
  254.  
  255.     /*
  256.      * Do the actual ray trace.
  257.      */
  258.     fullintens.r = fullintens.g = fullintens.b = 1.;
  259.     dist = FAR_AWAY;
  260.     hitlist.nodes = 0;
  261.     (void)TraceRay(ray, &hitlist, EPSILON, &dist);
  262.     ShadeRay(&hitlist, ray, dist, &Screen.background, &ctmp, &fullintens);
  263.     color->r = ctmp.r;
  264.     color->g = ctmp.g;
  265.     color->b = ctmp.b;
  266.     if (hitlist.nodes != 0) {
  267.         color->alpha = 1.;
  268.     } else {
  269.         color->alpha = 0.;
  270.     }
  271. }
  272.