home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / RTrace 1.0 / source / shadligh.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-16  |  8.7 KB  |  265 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * This code received contributions from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *  Paul Strauss        - shading model
  11.  *  Craig Kolb          - textures
  12.  *  David Buck          - textures
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted
  15.  * provided that the above copyright notice and this paragraph are
  16.  * duplicated in all such forms and that any documentation,
  17.  * advertising materials, and other materials related to such
  18.  * distribution and use acknowledge that the software was developed
  19.  * by Antonio Costa, at INESC-Norte. The name of the author and
  20.  * INESC-Norte may not be used to endorse or promote products derived
  21.  * from this software without specific prior written permission.
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  23.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  24.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25.  */
  26. #include "defs.h"
  27. #include "extern.h"
  28.  
  29. /**********************************************************************
  30.  *    RAY TRACING - Lighting - Version 7.3                            *
  31.  *                                                                    *
  32.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  33.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  34.  *    MODIFIED BY: Antonio Costa, INESC-Norte, June 1992              *
  35.  **********************************************************************/
  36.  
  37. /***** Lighting *****/
  38. void
  39. vector_to_light(l, position, lighting)
  40.   REG int         l;
  41.   xyz_ptr         position, lighting;
  42. {
  43.   lighting->x = light[l].coords.x - position->x;
  44.   lighting->y = light[l].coords.y - position->y;
  45.   lighting->z = light[l].coords.z - position->z;
  46.   light_distance = LENGTH(*lighting);
  47.   NORMALIZE(*lighting);
  48. }
  49. real
  50. light_intensity(l, lighting)
  51.   REG int         l;
  52.   xyz_ptr         lighting;
  53. {
  54.   real            k;
  55.   dir_light_ptr   light_ptr;
  56.  
  57.   if (light[l].light_type == DIRECT_LIGHT_TYPE)
  58.   {
  59.     light_ptr = (dir_light_ptr) light[l].data;
  60.     k = DOT_PRODUCT(light_ptr->vector, *lighting);
  61.     if (k > light_ptr->cos_angle)
  62.       return POWER((k - light_ptr->cos_angle) * light_ptr->t,
  63.                    light_ptr->factor);
  64.     return 0.0;
  65.   }
  66.   return 1.0;
  67. }
  68. static void
  69. point_light_brightness(source_id, l, position, lighting, brightness)
  70.   int             source_id, l;
  71.   xyz_ptr         position, lighting;
  72.   rgb_ptr         brightness;
  73. {
  74.   boolean         intersect, shadow;
  75.   REG int         id, cached_id, octant, surface_id;
  76.   real            distance;
  77.   object_ptr      intersect_object;
  78.  
  79.   if (light_mode != 0)
  80.     ATTEN_COLOR(light_distance, light[l].attenuation[0],
  81.                 light[l].attenuation[1], light[l].attenuation[2],
  82.                 light[l].brightness, *brightness);
  83.   shadow = FALSE;
  84.   FIND_OCTANT(octant, *lighting);
  85.   if ((shade_level < LIGHT_CACHE_LEVEL_MAX)
  86.       AND(light[l].cache_id[shade_level] != NO_OBJECTS))
  87.   {
  88.     id = light[l].cache_id[shade_level];
  89.     cached_id = id;
  90.     if ((id != source_id) OR NOT CONVEX(object[id]->object_type)
  91.         OR(COLOR_BIG(surface[object[id]->surface_id]->transparent, ROUNDOFF)
  92.         AND SELF_INTERSECT(object[id]->object_type, TRUE)))
  93.     {
  94.       intersect = octant_intersect(octant, position, lighting,
  95.                                    object[id]->min, object[id]->max);
  96.       if (intersect AND CHECK_BOUNDS(object[id]->object_type))
  97.       {
  98.         distance = bound_intersect(position, lighting, object[id]->min,
  99.                                    object[id]->max);
  100.         intersect = (boolean)
  101.           ((distance > 0.0) AND(distance < light_distance));
  102.       }
  103.       if (intersect)
  104.       {
  105.         REALINC(shadow_rays);
  106.         OBJECT_INTERSECT(distance, position, lighting, object[id]);
  107.         if ((distance > 0.0) AND(distance < light_distance))
  108.         {
  109.           REALINC(shadow_hits);
  110.           REALINC(shadow_cache_hits);
  111.           if (light_mode == 0)
  112.             shadow = TRUE;
  113.           else
  114.           {
  115.             surface_id = object[id]->surface_id;
  116.             brightness->r *= surface[surface_id]->transparent.r;
  117.             brightness->g *= surface[surface_id]->transparent.g;
  118.             brightness->b *= surface[surface_id]->transparent.b;
  119.             if (NOT COLOR_BIG(*brightness, threshold_level))
  120.               shadow = TRUE;
  121.           }
  122.         } else
  123.           light[l].cache_id[shade_level] = NO_OBJECTS;
  124.       } else
  125.         light[l].cache_id[shade_level] = NO_OBJECTS;
  126.     } else
  127.       light[l].cache_id[shade_level] = NO_OBJECTS;
  128.   } else
  129.     cached_id = NO_OBJECTS;
  130.   if (NOT shadow)
  131.   {
  132.     PQUEUE_INITIALIZE;
  133.     cluster_intersect(octant, source_id, cached_id, position, lighting,
  134.                       (cluster_ptr) ROOT_OBJECT->data, &light_distance,
  135.                       NULL, FALSE);
  136.     while (NOT shadow AND PQUEUE_NOT_EMPTY)
  137.     {
  138.       REALINC(shadow_rays);
  139.       pqueue_extract(&distance, &intersect_object);
  140.       if (CHECK_BOUNDS(intersect_object->object_type))
  141.         OBJECT_INTERSECT(distance, position, lighting, intersect_object);
  142.       if ((distance > 0.0) AND(distance < light_distance))
  143.       {
  144.         REALINC(shadow_hits);
  145.         if (light_mode == 0)
  146.           shadow = TRUE;
  147.         else
  148.         {
  149.           surface_id = intersect_object->surface_id;
  150.           brightness->r *= surface[surface_id]->transparent.r;
  151.           brightness->g *= surface[surface_id]->transparent.g;
  152.           brightness->b *= surface[surface_id]->transparent.b;
  153.           if (NOT COLOR_BIG(*brightness, threshold_level))
  154.             shadow = TRUE;
  155.         }
  156.         if (shade_level < LIGHT_CACHE_LEVEL_MAX)
  157.           light[l].cache_id[shade_level] = intersect_object->id;
  158.       }
  159.     }
  160.   }
  161.   if (shadow)
  162.   {
  163.     brightness->r = 0.0;
  164.     brightness->g = 0.0;
  165.     brightness->b = 0.0;
  166.   } else
  167.   if (light_mode == 0)
  168.     ATTEN_COLOR(light_distance, light[l].attenuation[0],
  169.                 light[l].attenuation[1], light[l].attenuation[2],
  170.                 light[l].brightness, *brightness);
  171. }
  172. static void
  173. extended_light_brightness(source_id, l, position, lighting, brightness)
  174.   int             source_id, l;
  175.   xyz_ptr         position, lighting;
  176.   rgb_ptr         brightness;
  177. {
  178.   REG int         i, j, samples;
  179.   REG real        k, u, v, diameter;
  180.   ext_light_ptr   ext_light;
  181.   xyz_struct      temp, light_l, light_lu, light_u, light_v;
  182.   rgb_struct      new_brightness;
  183.  
  184.   ext_light = (ext_light_ptr) light[l].data;
  185.   diameter = ext_light->diameter;
  186.   ATTEN_DISTANCE(diameter, k);
  187.   samples = TRUNC(k * diameter / pixel_distance);
  188.   if (samples <= 1)
  189.   {
  190.     point_light_brightness(source_id, l, position, lighting, brightness);
  191.     return;
  192.   }
  193.   samples = MIN(samples, ext_light->samples);
  194.   brightness->r = 0.0;
  195.   brightness->g = 0.0;
  196.   brightness->b = 0.0;
  197.   k = 1.0 / (real) samples;
  198.   if (ABS(lighting->y) > 1.0 - ROUNDOFF)
  199.   {
  200.     temp.x = 0.0;
  201.     temp.y = 0.0;
  202.     temp.z = 1.0;
  203.   } else
  204.   {
  205.     temp.x = 0.0;
  206.     temp.y = 1.0;
  207.     temp.z = 0.0;
  208.   }
  209.   CROSS_PRODUCT(light_u, *lighting, temp);
  210.   NORMALIZE(light_u);
  211.   CROSS_PRODUCT(light_v, *lighting, light_u);
  212.   light_l.x = light[l].coords.x - position->x;
  213.   light_l.y = light[l].coords.y - position->y;
  214.   light_l.z = light[l].coords.z - position->z;
  215.   for (i = 0; i <= samples; POSINC(i))
  216.   {
  217.     u = (((real) i + JITTER) * k - 0.5) * diameter;
  218.     light_lu.x = light_l.x + u * light_u.x;
  219.     light_lu.y = light_l.y + u * light_u.y;
  220.     light_lu.z = light_l.z + u * light_u.z;
  221.     for (j = 0; j <= samples; POSINC(j))
  222.     {
  223.       if (((i == 0) OR(i == samples))
  224.           AND((j == 0) OR(j == samples)))
  225.         continue;
  226.       v = (((real) j + JITTER) * k - 0.5) * diameter;
  227.       temp.x = light_lu.x + v * light_v.x;
  228.       temp.y = light_lu.y + v * light_v.y;
  229.       temp.z = light_lu.z + v * light_v.z;
  230.       NORMALIZE(temp);
  231.       point_light_brightness(source_id, l, position, &temp, &new_brightness);
  232.       brightness->r += new_brightness.r;
  233.       brightness->g += new_brightness.g;
  234.       brightness->b += new_brightness.b;
  235.     }
  236.   }
  237.   k = 1.0 / (SQR((real) (samples + 1)) - 4.0);
  238.   brightness->r *= k;
  239.   brightness->g *= k;
  240.   brightness->b *= k;
  241.   if (NOT COLOR_BIG(*brightness, ROUNDOFF))
  242.   {
  243.     brightness->r = 0.0;
  244.     brightness->g = 0.0;
  245.     brightness->b = 0.0;
  246.   }
  247. }
  248. void
  249. light_brightness(source_id, l, position, lighting, brightness)
  250.   int             source_id, l;
  251.   xyz_ptr         position, lighting;
  252.   rgb_ptr         brightness;
  253. {
  254.   switch (light[l].light_type)
  255.   {
  256.   case POINT_LIGHT_TYPE:
  257.   case DIRECT_LIGHT_TYPE:
  258.     point_light_brightness(source_id, l, position, lighting, brightness);
  259.     break;
  260.   case EXTENDED_LIGHT_TYPE:
  261.     extended_light_brightness(source_id, l, position, lighting, brightness);
  262.     break;
  263.   }
  264. }
  265.