home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GRAPHICS / rayshade.lzh / intersect.c < prev    next >
Text File  |  1990-05-08  |  7KB  |  249 lines

  1. /*
  2.  * intersect.c
  3.  *
  4.  * Copyright (C) 1989, Craig E. Kolb
  5.  *
  6.  * This software may be freely copied, modified, and redistributed,
  7.  * provided that this copyright notice is preserved on all copies.
  8.  *
  9.  * There is no warranty or other guarantee of fitness for this software,
  10.  * it is provided solely .  Bug reports or fixes may be sent
  11.  * to the author, who may or may not act on them as he desires.
  12.  *
  13.  * You may not include this software in a program or other software product
  14.  * without supplying the source, or without informing the end-user that the
  15.  * source is available for no extra charge.
  16.  *
  17.  * If you modify this software, you should include a notice giving the
  18.  * name of the person performing the modification, the date of modification,
  19.  * and the reason for such modification.
  20.  *
  21.  * $Id: intersect.c,v 3.0 89/10/27 02:05:53 craig Exp $
  22.  *
  23.  * $Log:    intersect.c,v $
  24.  * Revision 3.0  89/10/27  02:05:53  craig
  25.  * Baseline for first official release.
  26.  * 
  27.  */
  28. #include <math.h>
  29. #include <stdio.h>
  30. #include "typedefs.h"
  31. #include "funcdefs.h"
  32. #include "constants.h"
  33.  
  34. /*
  35.  * Primitive intersection routines
  36.  */
  37. double (*objint[])() = {intsph, intbox, inttri, intsup, intplane, intcyl,
  38.             intpoly, inttri, intcone, inthf};
  39. /*
  40.  * Primitive normal routines
  41.  */
  42. int (*objnrm[])() = {nrmsph, nrmbox, nrmtri, nrmsup, nrmplane, nrmcyl,
  43.             nrmpoly, nrmtri, nrmcone, nrmhf};
  44. /*
  45.  * object extent box routines
  46.  */
  47. int (*objextent[])() = {sphextent, boxextent, triextent, supextent,
  48.             planeextent, cylextent, polyextent, triextent,
  49.             coneextent, hfextent};
  50.  
  51. unsigned long int primtests[PRIMTYPES], primhits[PRIMTYPES];
  52.  
  53. char *primnames[PRIMTYPES] = {  "Sphere", "Box", "Triangle", "Superq", "Plane",
  54.                 "Cylinder", "Polygon", "Phongtri", "Cone",
  55.                 "Heightfield"};
  56.  
  57. /*
  58.  * Flags indicating whether or not we should check for intersection
  59.  * with an object's bounding box before we check for intersection
  60.  * with the object.
  61.  */
  62. char CheckBounds[] = {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE,
  63.             TRUE, FALSE, FALSE, FALSE};
  64.  
  65. /*
  66.  * Top-level raytracing routine.  Increment ray number, initialize
  67.  * intersection information and trace ray through "World" object.
  68.  */
  69. double
  70. TraceRay(source, ray, hitinfo)
  71. Primitive *source;
  72. Ray *ray;
  73. HitInfo *hitinfo;
  74. {
  75.     extern Object *World;
  76.     extern double intersect();
  77.  
  78.     return intersect(World, source, ray, hitinfo);
  79. }
  80.  
  81. /*
  82.  * Intersect object & ray.  Return distance from "pos" along "ray" to
  83.  * intersection point.  Return value <= 0 indicates no intersection.
  84.  */
  85. double
  86. intersect(obj, source, ray, hitinfo)
  87. Object *obj;                /* Object to be tested. */
  88. Primitive *source;            /* Prim, if any, that pos is on. */
  89. Ray *ray;                /* Ray origin, direction. */
  90. HitInfo *hitinfo;            /* Data on intersection (pos, norm) */
  91. {
  92.     Ray newray;
  93.     double dist, distfact, TransformRay();
  94.     extern int Cache;
  95.  
  96.     /*
  97.      * Check ray/bounding volume intersection, if required.
  98.      */
  99.     if (CheckBounds[obj->type] &&
  100.         OutOfBounds(&ray->pos, obj->bounds) &&
  101.         IntBounds(ray, obj->bounds) < EPSILON)
  102.             return 0.;
  103.  
  104.     newray = *ray;
  105.  
  106.     /*
  107.      * Transform the ray if necessary.
  108.      */
  109.     if (obj->trans != (Trans *)0) {
  110.         /*
  111.          * Transforming the ray can change the distance between
  112.          * the ray origin and the point of intersection.
  113.          * We save the amount the ray is "stretched" and later
  114.          * divide the computed distance by this amount.
  115.          */
  116.         distfact = TransformRay(&newray, &obj->trans->world2obj);
  117.     }
  118.  
  119.     /*
  120.      * Call correct intersection routine.
  121.      */
  122.     if (obj->type == GRID)
  123.         dist = int_grid((Grid *)obj->data, source, &newray, hitinfo);
  124.     else if (obj->type == LIST)
  125.         dist = int_list((List *)obj->data, source, &newray, hitinfo);
  126.     else
  127.         dist = int_primitive((Primitive *)obj->data, source, &newray,
  128.                     hitinfo);
  129.  
  130.     if (dist < EPSILON)
  131.         return 0.;
  132.  
  133.     /*
  134.      * If this is a shadow ray, don't bother with texture mapping
  135.      * or transformation of normal.
  136.      */
  137.     if (ray->shadow) {
  138.         if (obj->trans == (Trans *)0)
  139.             return dist;
  140.         else if (Cache)
  141.             /*
  142.               * Keep track of total transformation applied to ray
  143.               * if necessary.
  144.               */
  145.             mmult(hitinfo->totaltrans, &obj->trans->world2obj,
  146.                 hitinfo->totaltrans);
  147.         return dist / distfact;
  148.     }
  149.     /*
  150.      * Perform texture mapping.
  151.      */
  152.     if (obj->texture)
  153.         apply_textures(hitinfo, obj->texture);
  154.  
  155.     if (obj->trans) {
  156.         /*
  157.          * Transform hitinfo structure.  As things stand,
  158.          * this just means transforming the normal and
  159.          * dividing "dist" by the amount the ray was
  160.          * stretched.
  161.          */
  162.         dist /= distfact;
  163.         TransformNormal(&hitinfo->norm, &obj->trans->world2obj);
  164.     }
  165.  
  166.     return dist;
  167. }
  168.  
  169. /*
  170.  * Intersect ray & primitive object.
  171.  */
  172. double
  173. int_primitive(prim, source, ray, hitinfo)
  174. Primitive *prim, *source;
  175. Ray *ray;
  176. HitInfo *hitinfo;
  177. {
  178.     double dist;
  179.  
  180.     if (prim == source && prim->type != HF)
  181.         /*
  182.          * Don't check for intersection with "source", unless
  183.          * source is a height field.  (Height fields may shadow
  184.          * themselves.)
  185.          */
  186.         return 0.;
  187.  
  188.     dist = (*objint[prim->type]) (&ray->pos, &ray->dir, prim);
  189.  
  190.     if (dist < EPSILON)
  191.         return 0.;
  192.  
  193.     primhits[prim->type]++;
  194.     hitinfo->prim = prim;
  195.     hitinfo->surf = *prim->surf;
  196.  
  197.     if (ray->shadow)
  198.         return dist;    /* If a shadow ray, don't bother with normal */
  199.     /*
  200.      * Calculate point of intersection in object space.
  201.       * (The point of intersection in world space is
  202.      * calculated in ShadeRay().)
  203.      */
  204.     addscaledvec(ray->pos, dist, ray->dir, &hitinfo->pos);
  205.  
  206.     /*
  207.      * Find normal to primitive.
  208.      */
  209.     (*objnrm[prim->type]) (&hitinfo->pos, prim, &hitinfo->norm);
  210.  
  211.     /*
  212.      * Make sure normal points towards ray origin.  If surface is
  213.      * transparent, keep as-is, as the normal indicates whether we're
  214.      * entering or exiting.  If the prim is a superquadric, don't flip,
  215.      * as this leads to strange edge effects.
  216.      */
  217.     if (dotp(&ray->dir, &hitinfo->norm) > 0 && hitinfo->surf.transp == 0. &&
  218.         prim->type != SUPERQ) {
  219.         scalar_prod(-1., hitinfo->norm, &hitinfo->norm);
  220.     }
  221.  
  222.     return dist;
  223. }
  224.  
  225. print_prim_stats()
  226. {
  227.     long int totaltests, totalhits;
  228.     extern FILE *fstats;
  229.     int i;
  230.  
  231.     totaltests = totalhits = 0;
  232.     for (i = 0; i < PRIMTYPES; i++) {
  233.         if (primtests[i] == 0)
  234.             continue;
  235.         fprintf(fstats,"%s intersection tests:\t%ld (%ld hit, %f%%)\n",
  236.                 primnames[i], primtests[i],
  237.                 primhits[i],
  238.                 100.*(float)primhits[i]/(float)primtests[i]);
  239.         totaltests += primtests[i];
  240.         totalhits += primhits[i];
  241.     }
  242.     fprintf(fstats,"Total intersection tests:\t%ld", totaltests);
  243.     if (totaltests == 0)
  244.         fprintf(fstats,"\n");
  245.     else
  246.         fprintf(fstats," (%ld hit, %f%%)\n", totalhits,
  247.             100.*(float)totalhits/(float)totaltests);
  248. }
  249.