home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / macraysh.sit / Code / Source / surfshade.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-05  |  4.7 KB  |  184 lines

  1. /*
  2.  * surfshade.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  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: surfshade.c,v 4.0 91/07/17 14:41:15 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    surfshade.c,v $
  19.  * Revision 4.0  91/07/17  14:41:15  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include "geom.h"
  24. #include "surface.h"
  25.  
  26. /*
  27.  * Compute surface properties from given hitlist
  28.  * Returns TRUE if ray is entering object, FALSE otherwise.
  29.  */
  30. int
  31. ComputeSurfProps(hitlist, ray, pos, norm, gnorm, surf, smooth)
  32. HitList *hitlist;    /* Hit information (path through DAG) */
  33. Ray *ray;        /* Ray in world space */
  34. Vector *pos;        /* Intersection point */
  35. Vector *norm, *gnorm;    /* shading normal, geometric normal (return values) */
  36. Surface *surf;        /* Copy of surface to use, texture-modified */
  37. int *smooth;
  38. {
  39.     HitNode *hp;
  40.     int i;
  41.     Ray rtmp;
  42.     Geom *prim, *obj;
  43.     Float k, kp;
  44.     int texturing, transforming, entering;
  45.     Trans prim2model, world2model;
  46.  
  47.     hp = hitlist->data;
  48.     prim = hp->obj;
  49.  
  50.     /*
  51.      * Compute point of intersection in "primitive space".
  52.      */
  53.     VecAddScaled(hp->ray.pos, hp->dist, hp->ray.dir, pos);
  54.  
  55.     /*
  56.      * Find normal to primitive at point of intersection.
  57.      */
  58.     *smooth = PrimNormal(prim, pos, norm, gnorm);
  59.  
  60.     texturing = transforming = FALSE;
  61.  
  62.     /*
  63.      * Walk down hit list, constructing world<-->primitive transformation
  64.      * and determining if we need to perform texture mapping.
  65.      * The last node is the World node, which cannot be textured or
  66.      * transformed, so we skip it.
  67.      */
  68.     for (i = 0, hp = hitlist->data; i < hitlist->nodes -1; hp++, i++) {
  69.         obj = hp->obj;
  70.         if (hp->dotrans) {
  71.             /*
  72.              * Here we're actually computing prim2world.
  73.              * When finished, we invert it.
  74.              */
  75.             if (transforming) {
  76.                 TransCompose(&hp->trans, &world2model,
  77.                     &world2model);
  78.             } else {
  79.                 TransCopy(&hp->trans, &world2model);
  80.             }
  81.             transforming = TRUE;
  82.         }
  83.         if (obj->texture)
  84.             texturing = TRUE;
  85.     }
  86.  
  87.     /*
  88.      * Determine if we're entering or exiting the surface,
  89.      * flipping surface normals if necessary.
  90.      */
  91.     k = dotp(&hitlist->data[0].ray.dir, norm);
  92.     if (*smooth) {
  93.         /*
  94.          * If gnorm and shading norm differ and
  95.          * their dot products with the ray have
  96.          * different signs, use the geometric normal
  97.          * instead, ala Snyder & Barr's paper.
  98.          */
  99.         kp = dotp(&hitlist->data[0].ray.dir, gnorm);
  100.         if (k <= 0. && kp > 0. || k >= 0. && kp < 0.)
  101.             k = kp;
  102.     }
  103.  
  104.     if (k > 0.) {
  105.         /* flip normals */
  106.         VecScale(-1., *gnorm, gnorm);
  107.         VecScale(-1., *norm, norm);
  108.         /*
  109.          * Normal indicates that we're exiting.
  110.          * Only set entering to TRUE if csg has indicated
  111.          * that the ray is, indeed, entering.
  112.          */
  113.         entering = (hitlist->data[0].enter == ENTERING);
  114.     } else {
  115.         /*
  116.          * Normal indicates that we're entering.
  117.          * Set entering flag as such unless csg has
  118.          * told us that we're exiting.
  119.          */
  120.         entering = !(hitlist->data[0].enter == EXITING);
  121.     }
  122.         
  123.     /*
  124.      * If there are no transformations, then world2model is identity.
  125.      */
  126.     if (!transforming)
  127.         TransInit(&world2model);
  128.     /*
  129.      * If we're not performing texturing, we simply need to compute
  130.      * the normal and point of intersection to world space.
  131.      */
  132.     if (!texturing) {
  133.         /*
  134.           * At this point 'world2model' is really 'prim2world'.
  135.          */
  136.         if (transforming) {
  137.             NormalTransform(norm, &world2model.itrans);
  138.             NormalTransform(gnorm, &world2model.itrans);
  139.             VecAddScaled(ray->pos,
  140.                      hitlist->data[hitlist->nodes -1].dist,
  141.                      ray->dir, pos);
  142.         }
  143.         return entering;
  144.     }
  145.     /*
  146.      * world2model currently transforms from primitive to world space.
  147.      * Invert it to get transformation from world to primitive space.
  148.      */
  149.     TransInvert(&world2model, &world2model);
  150.     TransInit(&prim2model);
  151.     rtmp = hitlist->data[0].ray;
  152.     /*
  153.      * Walk down hitlist.
  154.      */
  155.     for (hp = hitlist->data, i = 0; i < hitlist->nodes -1; i++, hp++) {
  156.         obj = hp->obj;
  157.         if (hp->dotrans) {
  158.             NormalTransform(norm, &hp->trans.itrans);
  159.             if (texturing) {
  160.                 /*
  161.                  * Compose prim<-->model and world<-->model
  162.                  * with current transformation.
  163.                  */
  164.                 TransCompose(&hp->trans, &prim2model,
  165.                     &prim2model);
  166.                 TransCompose(&hp->trans, &world2model,
  167.                     &world2model);
  168.                 /*
  169.                  * Transform point and ray to model space.
  170.                  */
  171.                 PointTransform(pos, &hp->trans.trans);
  172.                 (void)RayTransform(&rtmp, &hp->trans.trans);
  173.             }
  174.         }
  175.         /*
  176.          * Apply textures
  177.          */
  178.         if (obj->texture)
  179.             TextApply(obj->texture, prim, &rtmp, pos, norm,
  180.                 gnorm, surf, &prim2model, &world2model);
  181.     }
  182.     return entering;
  183. }
  184.