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

  1. /*
  2.  * Copyright (c) 1988, 1992 Antonio Costa, INESC-Norte.
  3.  * All rights reserved.
  4.  *
  5.  * Code, ideas or suggestions were taken from the following people:
  6.  *
  7.  *  Roman Kuchkuda      - basic ray tracer
  8.  *  Mark VandeWettering - MTV ray tracer
  9.  *  Augusto Sousa       - overall, shading model
  10.  *  Reid Judd           - portability
  11.  *
  12.  * Redistribution and use in source and binary forms are permitted
  13.  * provided that the above copyright notice and this paragraph are
  14.  * duplicated in all such forms and that any documentation,
  15.  * advertising materials, and other materials related to such
  16.  * distribution and use acknowledge that the software was developed
  17.  * by Antonio Costa, at INESC-Norte. The name of the author and
  18.  * INESC-Norte may not be used to endorse or promote products derived
  19.  * from this software without specific prior written permission.
  20.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  21.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  22.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  23.  */
  24. #include "defs.h"
  25. #include "extern.h" 
  26.  
  27. /**********************************************************************
  28.  *    RAY TRACING - Sphere - Version 8.0.0                            *
  29.  *                                                                    *
  30.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  31.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  32.  *    MODIFIED BY: Antonio Costa, INESC-Norte, September 1992         *
  33.  **********************************************************************/
  34.  
  35. /***** Sphere *****/
  36. real
  37. sphere_intersect(position, vector, object)
  38.   xyz_ptr         position, vector;
  39.   object_ptr      object;
  40. {
  41.   REG real        k, delta, distance;
  42.   xyz_struct      new_position, new_vector, p;
  43.   sphere_ptr      sphere;
  44.  
  45.   if (object->transf != NULL)
  46.   {
  47.     transform(object->transf, position, &new_position);
  48.     transform_vector(object->transf, position, vector, &new_position,
  49.                      &new_vector);
  50.     NORMALIZE(new_vector);
  51.   } else
  52.   {
  53.     STRUCT_ASSIGN(new_position, *position);
  54.     STRUCT_ASSIGN(new_vector, *vector);
  55.   }
  56.   REALINC(sphere_tests);
  57.   sphere = (sphere_ptr) object->data;
  58.   p.x = new_position.x - sphere->center.x;
  59.   p.y = new_position.y - sphere->center.y;
  60.   p.z = new_position.z - sphere->center.z;
  61.   k = DOT_PRODUCT(p, new_vector);
  62.   delta = SQR(k) - SQR(p.x) - SQR(p.y) - SQR(p.z) + sphere->radius2;
  63.   if (delta < 0.0)
  64.     return 0.0;
  65.   delta = SQRT(delta);
  66.   distance = -k - delta;
  67.   if (distance > threshold_distance)
  68.   {
  69.     if (object->transf != NULL)
  70.     {
  71.       sphere->position->x = new_position.x + distance * new_vector.x;
  72.       sphere->position->y = new_position.y + distance * new_vector.y;
  73.       sphere->position->z = new_position.z + distance * new_vector.z;
  74.       return transform_distance(object->inv_transf, distance,
  75.                                 &new_position, &new_vector, position);
  76.     } else
  77.       return distance;
  78.   }
  79.   distance = -k + delta;
  80.   if (distance > threshold_distance)
  81.   {
  82.     if (object->transf != NULL)
  83.     {
  84.       sphere->position->x = new_position.x + distance * new_vector.x;
  85.       sphere->position->y = new_position.y + distance * new_vector.y;
  86.       sphere->position->z = new_position.z + distance * new_vector.z;
  87.       return transform_distance(object->inv_transf, distance,
  88.                                 &new_position, &new_vector, position);
  89.     } else
  90.       return distance;
  91.   }
  92.   return 0.0;
  93. }
  94. void
  95. sphere_normal(position, object, normal)
  96.   xyz_ptr         position;
  97.   object_ptr      object;
  98.   xyz_ptr         normal;
  99. {
  100.   xyz_struct      old_position, new_normal;
  101.   sphere_ptr      sphere;
  102.  
  103.   sphere = (sphere_ptr) object->data;
  104.   if (object->transf != NULL)
  105.     STRUCT_ASSIGN(old_position, *(sphere->position));
  106.   else
  107.     STRUCT_ASSIGN(old_position, *position);
  108.   normal->x = old_position.x - sphere->center.x;
  109.   normal->y = old_position.y - sphere->center.y;
  110.   normal->z = old_position.z - sphere->center.z;
  111.   if (object->transf != NULL)
  112.   {
  113.     transform_normal_vector(object->transf, sphere->position, normal,
  114.                             &new_normal);
  115.     STRUCT_ASSIGN(*normal, new_normal);
  116.     NORMALIZE(*normal);
  117.   } else
  118.   {
  119.     normal->x *= sphere->radius;
  120.     normal->y *= sphere->radius;
  121.     normal->z *= sphere->radius;
  122.   }
  123. }
  124. void
  125. sphere_enclose(object)
  126.   object_ptr      object;
  127. {
  128.   REG real        x, y, z, r;
  129.   xyz_struct      temp, vertex;
  130.   sphere_ptr      sphere;
  131.  
  132.   sphere = (sphere_ptr) object->data;
  133.   r = sphere->radius + threshold_distance;
  134.   sphere->radius = 1.0 / sphere->radius;
  135.   x = sphere->center.x;
  136.   y = sphere->center.y;
  137.   z = sphere->center.z;
  138.   if (object->transf != NULL)
  139.   {
  140.     /* ALLOCATE(sphere->position, xyz_struct, 1, PARSE_TYPE); */    
  141.     ALLOCATE(sphere->position, xyz_struct, 1 );
  142.     temp.x = x - r;
  143.     temp.y = y - r;
  144.     temp.z = z - r;
  145.     transform(object->inv_transf, &temp, object->min);
  146.     STRUCT_ASSIGN(*(object->max), *(object->min));
  147.     temp.x = x - r;
  148.     temp.y = y - r;
  149.     temp.z = z + r;
  150.     transform(object->inv_transf, &temp, &vertex);
  151.     if (vertex.x < object->min->x)
  152.       object->min->x = vertex.x;
  153.     if (vertex.x > object->max->x)
  154.       object->max->x = vertex.x;
  155.     if (vertex.y < object->min->y)
  156.       object->min->y = vertex.y;
  157.     if (vertex.y > object->max->y)
  158.       object->max->y = vertex.y;
  159.     if (vertex.z < object->min->z)
  160.       object->min->z = vertex.z;
  161.     if (vertex.z > object->max->z)
  162.       object->max->z = vertex.z;
  163.     temp.x = x - r;
  164.     temp.y = y + r;
  165.     temp.z = z - r;
  166.     transform(object->inv_transf, &temp, &vertex);
  167.     if (vertex.x < object->min->x)
  168.       object->min->x = vertex.x;
  169.     if (vertex.x > object->max->x)
  170.       object->max->x = vertex.x;
  171.     if (vertex.y < object->min->y)
  172.       object->min->y = vertex.y;
  173.     if (vertex.y > object->max->y)
  174.       object->max->y = vertex.y;
  175.     if (vertex.z < object->min->z)
  176.       object->min->z = vertex.z;
  177.     if (vertex.z > object->max->z)
  178.       object->max->z = vertex.z;
  179.     temp.x = x - r;
  180.     temp.y = y + r;
  181.     temp.z = z + r;
  182.     transform(object->inv_transf, &temp, &vertex);
  183.     if (vertex.x < object->min->x)
  184.       object->min->x = vertex.x;
  185.     if (vertex.x > object->max->x)
  186.       object->max->x = vertex.x;
  187.     if (vertex.y < object->min->y)
  188.       object->min->y = vertex.y;
  189.     if (vertex.y > object->max->y)
  190.       object->max->y = vertex.y;
  191.     if (vertex.z < object->min->z)
  192.       object->min->z = vertex.z;
  193.     if (vertex.z > object->max->z)
  194.       object->max->z = vertex.z;
  195.     temp.x = x + r;
  196.     temp.y = y - r;
  197.     temp.z = z - r;
  198.     transform(object->inv_transf, &temp, &vertex);
  199.     if (vertex.x < object->min->x)
  200.       object->min->x = vertex.x;
  201.     if (vertex.x > object->max->x)
  202.       object->max->x = vertex.x;
  203.     if (vertex.y < object->min->y)
  204.       object->min->y = vertex.y;
  205.     if (vertex.y > object->max->y)
  206.       object->max->y = vertex.y;
  207.     if (vertex.z < object->min->z)
  208.       object->min->z = vertex.z;
  209.     if (vertex.z > object->max->z)
  210.       object->max->z = vertex.z;
  211.     temp.x = x + r;
  212.     temp.y = y - r;
  213.     temp.z = z + r;
  214.     transform(object->inv_transf, &temp, &vertex);
  215.     if (vertex.x < object->min->x)
  216.       object->min->x = vertex.x;
  217.     if (vertex.x > object->max->x)
  218.       object->max->x = vertex.x;
  219.     if (vertex.y < object->min->y)
  220.       object->min->y = vertex.y;
  221.     if (vertex.y > object->max->y)
  222.       object->max->y = vertex.y;
  223.     if (vertex.z < object->min->z)
  224.       object->min->z = vertex.z;
  225.     if (vertex.z > object->max->z)
  226.       object->max->z = vertex.z;
  227.     temp.x = x + r;
  228.     temp.y = y + r;
  229.     temp.z = z - r;
  230.     transform(object->inv_transf, &temp, &vertex);
  231.     if (vertex.x < object->min->x)
  232.       object->min->x = vertex.x;
  233.     if (vertex.x > object->max->x)
  234.       object->max->x = vertex.x;
  235.     if (vertex.y < object->min->y)
  236.       object->min->y = vertex.y;
  237.     if (vertex.y > object->max->y)
  238.       object->max->y = vertex.y;
  239.     if (vertex.z < object->min->z)
  240.       object->min->z = vertex.z;
  241.     if (vertex.z > object->max->z)
  242.       object->max->z = vertex.z;
  243.     temp.x = x + r;
  244.     temp.y = y + r;
  245.     temp.z = z + r;
  246.     transform(object->inv_transf, &temp, &vertex);
  247.     if (vertex.x < object->min->x)
  248.       object->min->x = vertex.x;
  249.     if (vertex.x > object->max->x)
  250.       object->max->x = vertex.x;
  251.     if (vertex.y < object->min->y)
  252.       object->min->y = vertex.y;
  253.     if (vertex.y > object->max->y)
  254.       object->max->y = vertex.y;
  255.     if (vertex.z < object->min->z)
  256.       object->min->z = vertex.z;
  257.     if (vertex.z > object->max->z)
  258.       object->max->z = vertex.z;
  259.   } else
  260.   {
  261.     object->max->x = x + r;
  262.     object->max->y = y + r;
  263.     object->max->z = z + r;
  264.     object->min->x = x - r;
  265.     object->min->y = y - r;
  266.     object->min->z = z - r;
  267.   }
  268. }
  269.