home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / RTrace 1.0 / source / box.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-16  |  10.9 KB  |  376 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.  *
  11.  * Redistribution and use in source and binary forms are permitted
  12.  * provided that the above copyright notice and this paragraph are
  13.  * duplicated in all such forms and that any documentation,
  14.  * advertising materials, and other materials related to such
  15.  * distribution and use acknowledge that the software was developed
  16.  * by Antonio Costa, at INESC-Norte. The name of the author and
  17.  * INESC-Norte may not be used to endorse or promote products derived
  18.  * from this software without specific prior written permission.
  19.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  20.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  21.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  22.  */
  23. #include "defs.h"
  24. #include "extern.h"
  25.  
  26. /**********************************************************************
  27.  *    RAY TRACING - Box - Version 7.0.1                               *
  28.  *                                                                    *
  29.  *    MADE BY    : Augusto Sousa, INESC-Norte, December 1989          *
  30.  *    ADAPTED BY : Antonio Costa, INESC-Norte, April 1990             *
  31.  *    MODIFIED BY: Antonio Costa, INESC-Norte, April 1992             *
  32.  **********************************************************************/
  33.  
  34. /***** Box (Parallelipiped) *****/
  35. #define X_POSITIVE (1)
  36. #define X_NEGATIVE (2)
  37. #define Y_POSITIVE (3)
  38. #define Y_NEGATIVE (4)
  39. #define Z_POSITIVE (5)
  40. #define Z_NEGATIVE (6)
  41.  
  42. real
  43. box_intersect(position, vector, object)
  44.   xyz_ptr         position, vector;
  45.   object_ptr      object;
  46. {
  47.   REG real        distance1, distance2, temp;
  48.   short int       small_hit, big_hit, small, big;
  49.   real            small_distance, big_distance;
  50.   xyz_struct      new_position, new_vector, low, high, center, size;
  51.   box_ptr         box;
  52.  
  53.   if (object->transf != NULL)
  54.   {
  55.     transform(object->transf, position, &new_position);
  56.     transform_vector(object->transf, position, vector, &new_position,
  57.                      &new_vector);
  58.     NORMALIZE(new_vector);
  59.   } else
  60.   {
  61.     STRUCT_ASSIGN(new_position, *position);
  62.     STRUCT_ASSIGN(new_vector, *vector);
  63.   }
  64.   REALINC(box_tests);
  65.   box = (box_ptr) object->data;
  66.   STRUCT_ASSIGN(center, box->center);
  67.   STRUCT_ASSIGN(size, box->size);
  68.   low.x = center.x - size.x;
  69.   low.y = center.y - size.y;
  70.   low.z = center.z - size.z;
  71.   high.x = center.x + size.x;
  72.   high.y = center.y + size.y;
  73.   high.z = center.z + size.z;
  74.   small_distance = -INFINITY;
  75.   big_distance = INFINITY;
  76.   if (ABS(new_vector.x) < ROUNDOFF)
  77.   {
  78.     if ((new_position.x <= low.x) OR(new_position.x >= high.x))
  79.       return 0.0;
  80.   } else
  81.   {
  82.     small_distance = (low.x - new_position.x) / new_vector.x;
  83.     big_distance = (high.x - new_position.x) / new_vector.x;
  84.     if (small_distance > big_distance)
  85.     {
  86.       temp = small_distance;
  87.       small_distance = big_distance;
  88.       big_distance = temp;
  89.       small_hit = X_POSITIVE;
  90.       big_hit = X_NEGATIVE;
  91.     } else
  92.     {
  93.       small_hit = X_NEGATIVE;
  94.       big_hit = X_POSITIVE;
  95.     }
  96.     if (big_distance < threshold_distance)
  97.       return 0.0;
  98.   }
  99.   if (ABS(new_vector.y) < ROUNDOFF)
  100.   {
  101.     if ((new_position.y <= low.y) OR(new_position.y >= high.y))
  102.       return 0.0;
  103.   } else
  104.   {
  105.     distance1 = (low.y - new_position.y) / new_vector.y;
  106.     distance2 = (high.y - new_position.y) / new_vector.y;
  107.     if (distance1 > distance2)
  108.     {
  109.       temp = distance1;
  110.       distance1 = distance2;
  111.       distance2 = temp;
  112.       small = Y_POSITIVE;
  113.       big = Y_NEGATIVE;
  114.     } else
  115.     {
  116.       small = Y_NEGATIVE;
  117.       big = Y_POSITIVE;
  118.     }
  119.     if (distance1 > small_distance)
  120.     {
  121.       small_distance = distance1;
  122.       small_hit = small;
  123.     }
  124.     if (distance2 < big_distance)
  125.     {
  126.       big_distance = distance2;
  127.       big_hit = big;
  128.     }
  129.     if ((small_distance > big_distance) OR(big_distance < threshold_distance))
  130.       return 0.0;
  131.   }
  132.   if (ABS(new_vector.z) < ROUNDOFF)
  133.   {
  134.     if ((new_position.z <= low.z) OR(new_position.z >= high.z))
  135.       return 0.0;
  136.   } else
  137.   {
  138.     distance1 = (low.z - new_position.z) / new_vector.z;
  139.     distance2 = (high.z - new_position.z) / new_vector.z;
  140.     if (distance1 > distance2)
  141.     {
  142.       temp = distance1;
  143.       distance1 = distance2;
  144.       distance2 = temp;
  145.       small = Z_POSITIVE;
  146.       big = Z_NEGATIVE;
  147.     } else
  148.     {
  149.       small = Z_NEGATIVE;
  150.       big = Z_POSITIVE;
  151.     }
  152.     if (distance1 > small_distance)
  153.     {
  154.       small_distance = distance1;
  155.       small_hit = small;
  156.     }
  157.     if (distance2 < big_distance)
  158.     {
  159.       big_distance = distance2;
  160.       big_hit = big;
  161.     }
  162.     if ((small_distance > big_distance) OR(big_distance < threshold_distance))
  163.       return 0.0;
  164.   }
  165.   if (small_distance < threshold_distance)
  166.   {
  167.     box->side_hit = big_hit;
  168.     if (object->transf != NULL)
  169.     {
  170.       box->position->x = new_position.x + big_distance * new_vector.x;
  171.       box->position->y = new_position.y + big_distance * new_vector.y;
  172.       box->position->z = new_position.z + big_distance * new_vector.z;
  173.       return transform_distance(object->inv_transf, big_distance,
  174.                                 &new_position, &new_vector, position);
  175.     } else
  176.       return big_distance;
  177.   }
  178.   box->side_hit = small_hit;
  179.   if (object->transf != NULL)
  180.   {
  181.     box->position->x = new_position.x + small_distance * new_vector.x;
  182.     box->position->y = new_position.y + small_distance * new_vector.y;
  183.     box->position->z = new_position.z + small_distance * new_vector.z;
  184.     return transform_distance(object->inv_transf, small_distance,
  185.                               &new_position, &new_vector, position);
  186.   } else
  187.     return small_distance;
  188. }
  189. void
  190. box_normal(position, object, normal)
  191.   xyz_ptr         position;
  192.   object_ptr      object;
  193.   xyz_ptr         normal;
  194. {
  195.   xyz_struct      new_normal;
  196.   box_ptr         box;
  197.  
  198.   box = (box_ptr) object->data;
  199.   normal->x = 0.0;
  200.   normal->y = 0.0;
  201.   normal->z = 0.0;
  202.   switch (box->side_hit)
  203.   {
  204.   case X_POSITIVE:
  205.     normal->x = 1.0;
  206.     break;
  207.   case X_NEGATIVE:
  208.     normal->x = -1.0;
  209.     break;
  210.   case Y_POSITIVE:
  211.     normal->y = 1.0;
  212.     break;
  213.   case Y_NEGATIVE:
  214.     normal->y = -1.0;
  215.     break;
  216.   case Z_POSITIVE:
  217.     normal->z = 1.0;
  218.     break;
  219.   case Z_NEGATIVE:
  220.     normal->z = -1.0;
  221.     break;
  222.   }
  223.   if (object->transf != NULL)
  224.   {
  225.     transform_normal_vector(object->transf, box->position, normal,
  226.                             &new_normal);
  227.     STRUCT_ASSIGN(*normal, new_normal);
  228.     NORMALIZE(*normal);
  229.   }
  230. }
  231. void
  232. box_enclose(object)
  233.   object_ptr      object;
  234. {
  235.   REG real        x, y, z, xs, ys, zs;
  236.   xyz_struct      temp, vertex;
  237.   box_ptr         box;
  238.  
  239.   box = (box_ptr) object->data;
  240.   x = box->center.x;
  241.   y = box->center.y;
  242.   z = box->center.z;
  243.   xs = box->size.x + threshold_distance;
  244.   ys = box->size.y + threshold_distance;
  245.   zs = box->size.z + threshold_distance;
  246.   if (object->transf != NULL)
  247.   {
  248.     ALLOCATE(box->position, xyz_struct, 1);
  249.     temp.x = x - xs;
  250.     temp.y = y - ys;
  251.     temp.z = z - zs;
  252.     transform(object->inv_transf, &temp, object->min);
  253.     STRUCT_ASSIGN(*(object->max), *(object->min));
  254.     temp.x = x - xs;
  255.     temp.y = y - ys;
  256.     temp.z = z + zs;
  257.     transform(object->inv_transf, &temp, &vertex);
  258.     if (vertex.x < object->min->x)
  259.       object->min->x = vertex.x;
  260.     if (vertex.x > object->max->x)
  261.       object->max->x = vertex.x;
  262.     if (vertex.y < object->min->y)
  263.       object->min->y = vertex.y;
  264.     if (vertex.y > object->max->y)
  265.       object->max->y = vertex.y;
  266.     if (vertex.z < object->min->z)
  267.       object->min->z = vertex.z;
  268.     if (vertex.z > object->max->z)
  269.       object->max->z = vertex.z;
  270.     temp.x = x - xs;
  271.     temp.y = y + ys;
  272.     temp.z = z - zs;
  273.     transform(object->inv_transf, &temp, &vertex);
  274.     if (vertex.x < object->min->x)
  275.       object->min->x = vertex.x;
  276.     if (vertex.x > object->max->x)
  277.       object->max->x = vertex.x;
  278.     if (vertex.y < object->min->y)
  279.       object->min->y = vertex.y;
  280.     if (vertex.y > object->max->y)
  281.       object->max->y = vertex.y;
  282.     if (vertex.z < object->min->z)
  283.       object->min->z = vertex.z;
  284.     if (vertex.z > object->max->z)
  285.       object->max->z = vertex.z;
  286.     temp.x = x - xs;
  287.     temp.y = y + ys;
  288.     temp.z = z + zs;
  289.     transform(object->inv_transf, &temp, &vertex);
  290.     if (vertex.x < object->min->x)
  291.       object->min->x = vertex.x;
  292.     if (vertex.x > object->max->x)
  293.       object->max->x = vertex.x;
  294.     if (vertex.y < object->min->y)
  295.       object->min->y = vertex.y;
  296.     if (vertex.y > object->max->y)
  297.       object->max->y = vertex.y;
  298.     if (vertex.z < object->min->z)
  299.       object->min->z = vertex.z;
  300.     if (vertex.z > object->max->z)
  301.       object->max->z = vertex.z;
  302.     temp.x = x + xs;
  303.     temp.y = y - ys;
  304.     temp.z = z - zs;
  305.     transform(object->inv_transf, &temp, &vertex);
  306.     if (vertex.x < object->min->x)
  307.       object->min->x = vertex.x;
  308.     if (vertex.x > object->max->x)
  309.       object->max->x = vertex.x;
  310.     if (vertex.y < object->min->y)
  311.       object->min->y = vertex.y;
  312.     if (vertex.y > object->max->y)
  313.       object->max->y = vertex.y;
  314.     if (vertex.z < object->min->z)
  315.       object->min->z = vertex.z;
  316.     if (vertex.z > object->max->z)
  317.       object->max->z = vertex.z;
  318.     temp.x = x + xs;
  319.     temp.y = y - ys;
  320.     temp.z = z + zs;
  321.     transform(object->inv_transf, &temp, &vertex);
  322.     if (vertex.x < object->min->x)
  323.       object->min->x = vertex.x;
  324.     if (vertex.x > object->max->x)
  325.       object->max->x = vertex.x;
  326.     if (vertex.y < object->min->y)
  327.       object->min->y = vertex.y;
  328.     if (vertex.y > object->max->y)
  329.       object->max->y = vertex.y;
  330.     if (vertex.z < object->min->z)
  331.       object->min->z = vertex.z;
  332.     if (vertex.z > object->max->z)
  333.       object->max->z = vertex.z;
  334.     temp.x = x + xs;
  335.     temp.y = y + ys;
  336.     temp.z = z - zs;
  337.     transform(object->inv_transf, &temp, &vertex);
  338.     if (vertex.x < object->min->x)
  339.       object->min->x = vertex.x;
  340.     if (vertex.x > object->max->x)
  341.       object->max->x = vertex.x;
  342.     if (vertex.y < object->min->y)
  343.       object->min->y = vertex.y;
  344.     if (vertex.y > object->max->y)
  345.       object->max->y = vertex.y;
  346.     if (vertex.z < object->min->z)
  347.       object->min->z = vertex.z;
  348.     if (vertex.z > object->max->z)
  349.       object->max->z = vertex.z;
  350.     temp.x = x + xs;
  351.     temp.y = y + ys;
  352.     temp.z = z + zs;
  353.     transform(object->inv_transf, &temp, &vertex);
  354.     if (vertex.x < object->min->x)
  355.       object->min->x = vertex.x;
  356.     if (vertex.x > object->max->x)
  357.       object->max->x = vertex.x;
  358.     if (vertex.y < object->min->y)
  359.       object->min->y = vertex.y;
  360.     if (vertex.y > object->max->y)
  361.       object->max->y = vertex.y;
  362.     if (vertex.z < object->min->z)
  363.       object->min->z = vertex.z;
  364.     if (vertex.z > object->max->z)
  365.       object->max->z = vertex.z;
  366.   } else
  367.   {
  368.     object->max->x = x + xs;
  369.     object->max->y = y + ys;
  370.     object->max->z = z + zs;
  371.     object->min->x = x - xs;
  372.     object->min->y = y - ys;
  373.     object->min->z = z - zs;
  374.   }
  375. }
  376.