home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Graphics⁄Sound / RTrace-1.0-src / cone.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-17  |  11.4 KB  |  342 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 - Cone/Cylinder - Version 7.3                       *
  28.  *                                                                    *
  29.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  30.  *    ADAPTED BY : Antonio Costa, INESC-Norte, April 1992             *
  31.  *    MODIFIED BY: Antonio Costa, INESC-Norte, June 1992              *
  32.  **********************************************************************/
  33.  
  34. /***** Cone/Cylinder *****/
  35. real
  36. cone_intersect(position, vector, object)
  37.   xyz_ptr         position, vector;
  38.   object_ptr      object;
  39. {
  40.   REG real        slope, delta, k, k0, distance1, distance2, temp;
  41.   xyz_struct      new_position, new_vector, v, p, d;
  42.   cone_ptr        cone;
  43.  
  44.   if (object->transf != NULL)
  45.   {
  46.     transform(object->transf, position, &new_position);
  47.     transform_vector(object->transf, position, vector, &new_position,
  48.                      &new_vector);
  49.     NORMALIZE(new_vector);
  50.   } else
  51.   {
  52.     STRUCT_ASSIGN(new_position, *position);
  53.     STRUCT_ASSIGN(new_vector, *vector);
  54.   }
  55.   REALINC(cone_tests);
  56.   cone = (cone_ptr) object->data;
  57.   slope = cone->slope;
  58.   v.x = new_position.x - cone->base.x;
  59.   v.y = new_position.y - cone->base.y;
  60.   v.z = new_position.z - cone->base.z;
  61.   p.x = DOT_PRODUCT(v, cone->u);
  62.   p.y = DOT_PRODUCT(v, cone->v);
  63.   p.z = DOT_PRODUCT(v, cone->w);
  64.   d.x = DOT_PRODUCT(new_vector, cone->u);
  65.   d.y = DOT_PRODUCT(new_vector, cone->v);
  66.   d.z = DOT_PRODUCT(new_vector, cone->w);
  67.   if (slope > -ROUNDOFF)
  68.   {
  69.     /* Cylinder */
  70.     temp = cone->base_radius;
  71.     k0 = 2.0 * (SQR(d.x) + SQR(d.y));
  72.     k = 2.0 * (p.x * d.x + p.y * d.y);
  73.   } else
  74.   {
  75.     /* Cone */
  76.     temp = slope * p.z + cone->base_radius;
  77.     k0 = 2.0 * (SQR(d.x) + SQR(d.y) - SQR(slope) * SQR(d.z));
  78.     k = 2.0 * (p.x * d.x + p.y * d.y - slope * d.z * temp);
  79.   }
  80.   if (ABS(k0) < ROUNDOFF)
  81.   {
  82.     if (ABS(k) < ROUNDOFF)
  83.       return 0.0;
  84.     distance1 = (SQR(temp) - SQR(p.x) - SQR(p.y)) / k;
  85.     if (distance1 <= threshold_distance)
  86.       return 0.0;
  87.   } else
  88.   {
  89.     delta = SQR(k) - 2.0 * k0 * (SQR(p.x) + SQR(p.y) - SQR(temp));
  90.     if (delta < 0.0)
  91.       return 0.0;
  92.     delta = SQRT(delta);
  93.     distance1 = (-k + delta) / k0;
  94.     if (distance1 <= threshold_distance)
  95.       return 0.0;
  96.     distance2 = (-k - delta) / k0;
  97.     if (distance2 > threshold_distance)
  98.     {
  99.       p.x = distance2 * new_vector.x + new_position.x;
  100.       p.y = distance2 * new_vector.y + new_position.y;
  101.       p.z = distance2 * new_vector.z + new_position.z;
  102.       k = DOT_PRODUCT(cone->w, p);
  103.       if ((k >= cone->min_d) AND(k <= cone->max_d))
  104.       {
  105.         if (object->transf != NULL)
  106.         {
  107.           STRUCT_ASSIGN(*(cone->position), p);
  108.           return transform_distance(object->inv_transf, distance2,
  109.                                     &new_position, &new_vector, position);
  110.         } else
  111.           return distance2;
  112.       }
  113.       p.x = distance1 * new_vector.x + new_position.x;
  114.       p.y = distance1 * new_vector.y + new_position.y;
  115.       p.z = distance1 * new_vector.z + new_position.z;
  116.       k = DOT_PRODUCT(cone->w, p);
  117.       if ((k >= cone->min_d) AND(k <= cone->max_d))
  118.       {
  119.         if (object->transf != NULL)
  120.         {
  121.           STRUCT_ASSIGN(*(cone->position), p);
  122.           return transform_distance(object->inv_transf, distance1,
  123.                                     &new_position, &new_vector, position);
  124.         } else
  125.           return distance1;
  126.       }
  127.       return 0.0;
  128.     }
  129.   }
  130.   p.x = distance1 * new_vector.x + new_position.x;
  131.   p.y = distance1 * new_vector.y + new_position.y;
  132.   p.z = distance1 * new_vector.z + new_position.z;
  133.   k = DOT_PRODUCT(cone->w, p);
  134.   if ((k >= cone->min_d) AND(k <= cone->max_d))
  135.   {
  136.     if (object->transf != NULL)
  137.     {
  138.       STRUCT_ASSIGN(*(cone->position), p);
  139.       return transform_distance(object->inv_transf, distance1,
  140.                                 &new_position, &new_vector, position);
  141.     } else
  142.       return distance1;
  143.   }
  144.   return 0.0;
  145. }
  146. void
  147. cone_normal(position, object, normal)
  148.   xyz_ptr         position;
  149.   object_ptr      object;
  150.   xyz_ptr         normal;
  151. {
  152.   REG real        k;
  153.   xyz_struct      old_position, new_normal;
  154.   cone_ptr        cone;
  155.  
  156.   cone = (cone_ptr) object->data;
  157.   if (object->transf != NULL)
  158.     STRUCT_ASSIGN(old_position, *(cone->position));
  159.   else
  160.     STRUCT_ASSIGN(old_position, *position);
  161.   k = -(DOT_PRODUCT(old_position, cone->w) + cone->base_d);
  162.   normal->x = k * cone->w.x + old_position.x - cone->base.x;
  163.   normal->y = k * cone->w.y + old_position.y - cone->base.y;
  164.   normal->z = k * cone->w.z + old_position.z - cone->base.z;
  165.   NORMALIZE(*normal);
  166.   if (cone->slope > -ROUNDOFF)
  167.   {
  168.     if (object->transf != NULL)
  169.     {
  170.       transform_normal_vector(object->transf, cone->position, normal,
  171.                               &new_normal);
  172.       STRUCT_ASSIGN(*normal, new_normal);
  173.       NORMALIZE(*normal);
  174.     }
  175.     return;
  176.   }
  177.   k = -cone->slope;
  178.   normal->x = k * cone->w.x + normal->x;
  179.   normal->y = k * cone->w.y + normal->y;
  180.   normal->z = k * cone->w.z + normal->z;
  181.   if (object->transf != NULL)
  182.   {
  183.     transform_normal_vector(object->transf, cone->position, normal,
  184.                             &new_normal);
  185.     STRUCT_ASSIGN(*normal, new_normal);
  186.   }
  187.   NORMALIZE(*normal);
  188. }
  189. void
  190. cone_enclose(object)
  191.   object_ptr      object;
  192. {
  193.   REG real        k, base_delta, apex_delta;
  194.   real            x, y, z, xs, ys, zs;
  195.   xyz_struct      temp, vertex;
  196.   cone_ptr        cone;
  197.  
  198.   cone = (cone_ptr) object->data;
  199.   k = SQRT(1.0 - SQR(cone->w.x));
  200.   apex_delta = k * cone->apex_radius + threshold_distance;
  201.   base_delta = k * cone->base_radius + threshold_distance;
  202.   object->min->x = MIN(cone->base.x - base_delta, cone->apex.x - apex_delta);
  203.   object->max->x = MAX(cone->base.x + base_delta, cone->apex.x + apex_delta);
  204.   k = SQRT(1.0 - SQR(cone->w.y));
  205.   apex_delta = k * cone->apex_radius + threshold_distance;
  206.   base_delta = k * cone->base_radius + threshold_distance;
  207.   object->min->y = MIN(cone->base.y - base_delta, cone->apex.y - apex_delta);
  208.   object->max->y = MAX(cone->base.y + base_delta, cone->apex.y + apex_delta);
  209.   k = SQRT(1.0 - SQR(cone->w.z));
  210.   apex_delta = k * cone->apex_radius + threshold_distance;
  211.   base_delta = k * cone->base_radius + threshold_distance;
  212.   object->min->z = MIN(cone->base.z - base_delta, cone->apex.z - apex_delta);
  213.   object->max->z = MAX(cone->base.z + base_delta, cone->apex.z + apex_delta);
  214.   if (object->transf != NULL)
  215.   {
  216.     ALLOCATE(cone->position, xyz_struct, 1);
  217.     x = (object->min->x + object->max->x) * 0.5;
  218.     y = (object->min->y + object->max->y) * 0.5;
  219.     z = (object->min->z + object->max->z) * 0.5;
  220.     xs = (object->max->x - object->min->x) * 0.5;
  221.     ys = (object->max->y - object->min->y) * 0.5;
  222.     zs = (object->max->z - object->min->z) * 0.5;
  223.     temp.x = x - xs;
  224.     temp.y = y - ys;
  225.     temp.z = z - zs;
  226.     transform(object->inv_transf, &temp, object->min);
  227.     STRUCT_ASSIGN(*(object->max), *(object->min));
  228.     temp.x = x - xs;
  229.     temp.y = y - ys;
  230.     temp.z = z + zs;
  231.     transform(object->inv_transf, &temp, &vertex);
  232.     if (vertex.x < object->min->x)
  233.       object->min->x = vertex.x;
  234.     if (vertex.x > object->max->x)
  235.       object->max->x = vertex.x;
  236.     if (vertex.y < object->min->y)
  237.       object->min->y = vertex.y;
  238.     if (vertex.y > object->max->y)
  239.       object->max->y = vertex.y;
  240.     if (vertex.z < object->min->z)
  241.       object->min->z = vertex.z;
  242.     if (vertex.z > object->max->z)
  243.       object->max->z = vertex.z;
  244.     temp.x = x - xs;
  245.     temp.y = y + ys;
  246.     temp.z = z - zs;
  247.     transform(object->inv_transf, &temp, &vertex);
  248.     if (vertex.x < object->min->x)
  249.       object->min->x = vertex.x;
  250.     if (vertex.x > object->max->x)
  251.       object->max->x = vertex.x;
  252.     if (vertex.y < object->min->y)
  253.       object->min->y = vertex.y;
  254.     if (vertex.y > object->max->y)
  255.       object->max->y = vertex.y;
  256.     if (vertex.z < object->min->z)
  257.       object->min->z = vertex.z;
  258.     if (vertex.z > object->max->z)
  259.       object->max->z = vertex.z;
  260.     temp.x = x - xs;
  261.     temp.y = y + ys;
  262.     temp.z = z + zs;
  263.     transform(object->inv_transf, &temp, &vertex);
  264.     if (vertex.x < object->min->x)
  265.       object->min->x = vertex.x;
  266.     if (vertex.x > object->max->x)
  267.       object->max->x = vertex.x;
  268.     if (vertex.y < object->min->y)
  269.       object->min->y = vertex.y;
  270.     if (vertex.y > object->max->y)
  271.       object->max->y = vertex.y;
  272.     if (vertex.z < object->min->z)
  273.       object->min->z = vertex.z;
  274.     if (vertex.z > object->max->z)
  275.       object->max->z = vertex.z;
  276.     temp.x = x + xs;
  277.     temp.y = y - ys;
  278.     temp.z = z - zs;
  279.     transform(object->inv_transf, &temp, &vertex);
  280.     if (vertex.x < object->min->x)
  281.       object->min->x = vertex.x;
  282.     if (vertex.x > object->max->x)
  283.       object->max->x = vertex.x;
  284.     if (vertex.y < object->min->y)
  285.       object->min->y = vertex.y;
  286.     if (vertex.y > object->max->y)
  287.       object->max->y = vertex.y;
  288.     if (vertex.z < object->min->z)
  289.       object->min->z = vertex.z;
  290.     if (vertex.z > object->max->z)
  291.       object->max->z = vertex.z;
  292.     temp.x = x + xs;
  293.     temp.y = y - ys;
  294.     temp.z = z + zs;
  295.     transform(object->inv_transf, &temp, &vertex);
  296.     if (vertex.x < object->min->x)
  297.       object->min->x = vertex.x;
  298.     if (vertex.x > object->max->x)
  299.       object->max->x = vertex.x;
  300.     if (vertex.y < object->min->y)
  301.       object->min->y = vertex.y;
  302.     if (vertex.y > object->max->y)
  303.       object->max->y = vertex.y;
  304.     if (vertex.z < object->min->z)
  305.       object->min->z = vertex.z;
  306.     if (vertex.z > object->max->z)
  307.       object->max->z = vertex.z;
  308.     temp.x = x + xs;
  309.     temp.y = y + ys;
  310.     temp.z = z - zs;
  311.     transform(object->inv_transf, &temp, &vertex);
  312.     if (vertex.x < object->min->x)
  313.       object->min->x = vertex.x;
  314.     if (vertex.x > object->max->x)
  315.       object->max->x = vertex.x;
  316.     if (vertex.y < object->min->y)
  317.       object->min->y = vertex.y;
  318.     if (vertex.y > object->max->y)
  319.       object->max->y = vertex.y;
  320.     if (vertex.z < object->min->z)
  321.       object->min->z = vertex.z;
  322.     if (vertex.z > object->max->z)
  323.       object->max->z = vertex.z;
  324.     temp.x = x + xs;
  325.     temp.y = y + ys;
  326.     temp.z = z + zs;
  327.     transform(object->inv_transf, &temp, &vertex);
  328.     if (vertex.x < object->min->x)
  329.       object->min->x = vertex.x;
  330.     if (vertex.x > object->max->x)
  331.       object->max->x = vertex.x;
  332.     if (vertex.y < object->min->y)
  333.       object->min->y = vertex.y;
  334.     if (vertex.y > object->max->y)
  335.       object->max->y = vertex.y;
  336.     if (vertex.z < object->min->z)
  337.       object->min->z = vertex.z;
  338.     if (vertex.z > object->max->z)
  339.       object->max->z = vertex.z;
  340.   }
  341. }
  342.