home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / RTrace 1.0 / source / patch_2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-17  |  11.4 KB  |  335 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 - Patch (part1) - Version 7.3.2                     *
  28.  *                                                                    *
  29.  *    MADE BY    : Antonio Costa, INESC-Norte, October 1988           *
  30.  *    ADAPTED BY : Antonio Costa, INESC-Norte, June 1989              *
  31.  *    MODIFIED BY: Antonio Costa, INESC-Norte, August 1992            *
  32.  **********************************************************************/
  33.  
  34. /***** Patch *****/
  35. #include "patch.h"
  36.  
  37. static real     small_distance;
  38. static xyz_struct k0, k1, k2, k3, k4, k5, k6, k7, p[4];
  39. static patch_ptr patch;
  40.  
  41. #define BIG_DISTANCE(p0, p1) ((boolean) (\
  42. SQR((p0).x - (p1).x) + SQR((p0).y - (p1).y) + SQR((p0).z - (p1).z) >=\
  43. SQR(threshold_distance)))
  44.  
  45. static void
  46. patch_bissect(p0, p2, p6, p8, u0, v0, delta, position, vector)
  47.   xyz_ptr         p0, p2, p6, p8;
  48.   real            u0, v0, delta;
  49.   xyz_ptr         position, vector;
  50. {
  51.   REG real        u, v, b0, b1, b2, b3, distance, delta2;
  52.   xyz_struct      p1, p3, p4, p5, p7, pmin, pmax, temp;
  53.  
  54.   delta2 = delta * 0.5;
  55.   /* Points 1 and 7 */
  56.   u = u0 + delta2;
  57.   b0 = BLEND0(u);
  58.   b1 = BLEND1(u);
  59.   CUBIC(patch, 0, u, k0);
  60.   CUBIC(patch, 2, u, k2);
  61.   MULTIPLY(p[0], b0, k4);
  62.   MULTIPLY(p[1], b1, k5);
  63.   MULTIPLY(p[2], b0, k6);
  64.   MULTIPLY(p[3], b1, k7);
  65.   SUBTRACT(k0, k4, k5, k0);
  66.   SUBTRACT(k2, k6, k7, k2);
  67.   /* Point 1 */
  68.   v = v0;
  69.   CUBIC(patch, 1, v, k1);
  70.   CUBIC(patch, 3, v, k3);
  71.   b2 = BLEND0(v);
  72.   b3 = BLEND1(v);
  73.   p1.x = k0.x * b2 + k1.x * b0 + k2.x * b3 + k3.x * b1;
  74.   p1.y = k0.y * b2 + k1.y * b0 + k2.y * b3 + k3.y * b1;
  75.   p1.z = k0.z * b2 + k1.z * b0 + k2.z * b3 + k3.z * b1;
  76.   /* Point 7 */
  77.   v = v0 + delta;
  78.   CUBIC(patch, 1, v, k1);
  79.   CUBIC(patch, 3, v, k3);
  80.   b2 = BLEND0(v);
  81.   b3 = BLEND1(v);
  82.   p7.x = k0.x * b2 + k1.x * b0 + k2.x * b3 + k3.x * b1;
  83.   p7.y = k0.y * b2 + k1.y * b0 + k2.y * b3 + k3.y * b1;
  84.   p7.z = k0.z * b2 + k1.z * b0 + k2.z * b3 + k3.z * b1;
  85.   /* Points 3, 4 and 5 */
  86.   v = v0 + delta2;
  87.   b0 = BLEND0(v);
  88.   b1 = BLEND1(v);
  89.   CUBIC(patch, 1, v, k1);
  90.   CUBIC(patch, 3, v, k3);
  91.   MULTIPLY(p[0], b0, k4);
  92.   MULTIPLY(p[1], b0, k5);
  93.   MULTIPLY(p[2], b1, k6);
  94.   MULTIPLY(p[3], b1, k7);
  95.   SUBTRACT(k1, k4, k6, k1);
  96.   SUBTRACT(k3, k5, k7, k3);
  97.   /* Point 3 */
  98.   u = u0;
  99.   CUBIC(patch, 0, u, k0);
  100.   CUBIC(patch, 2, u, k2);
  101.   b2 = BLEND0(u);
  102.   b3 = BLEND1(u);
  103.   p3.x = k0.x * b0 + k1.x * b2 + k2.x * b1 + k3.x * b3;
  104.   p3.y = k0.y * b0 + k1.y * b2 + k2.y * b1 + k3.y * b3;
  105.   p3.z = k0.z * b0 + k1.z * b2 + k2.z * b1 + k3.z * b3;
  106.   /* Point 4 */
  107.   u = u0 + delta2;
  108.   CUBIC(patch, 0, u, k0);
  109.   CUBIC(patch, 2, u, k2);
  110.   b2 = BLEND0(u);
  111.   b3 = BLEND1(u);
  112.   p4.x = k0.x * b0 + k1.x * b2 + k2.x * b1 + k3.x * b3;
  113.   p4.y = k0.y * b0 + k1.y * b2 + k2.y * b1 + k3.y * b3;
  114.   p4.z = k0.z * b0 + k1.z * b2 + k2.z * b1 + k3.z * b3;
  115.   /* Point 5 */
  116.   u = u0 + delta;
  117.   CUBIC(patch, 0, u, k0);
  118.   CUBIC(patch, 2, u, k2);
  119.   b2 = BLEND0(u);
  120.   b3 = BLEND1(u);
  121.   p5.x = k0.x * b0 + k1.x * b2 + k2.x * b1 + k3.x * b3;
  122.   p5.y = k0.y * b0 + k1.y * b2 + k2.y * b1 + k3.y * b3;
  123.   p5.z = k0.z * b0 + k1.z * b2 + k2.z * b1 + k3.z * b3;
  124.   subpatch_enclose(p0, &p1, &p3, &p4, &pmin, &pmax);
  125.   distance = bound_intersect(position, vector, &pmin, &pmax);
  126.   if ((distance > 0.0) AND(distance < small_distance))
  127.     if (BIG_DISTANCE(*p0, p4))
  128.       patch_bissect(p0, &p1, &p3, &p4, u0, v0, delta2, position, vector);
  129.     else
  130.     {
  131.       temp.x = (p0->x + p4.x) * 0.5 - position->x;
  132.       temp.y = (p0->y + p4.y) * 0.5 - position->y;
  133.       temp.z = (p0->z + p4.z) * 0.5 - position->z;
  134.       distance = LENGTH(temp);
  135.       if ((distance > threshold_distance) AND(distance < small_distance))
  136.       {
  137.         small_distance = distance;
  138.         patch->u_hit = u0 + delta2 * 0.5;
  139.         patch->v_hit = v0 + delta2 * 0.5;
  140.       }
  141.     }
  142.   subpatch_enclose(&p1, p2, &p4, &p5, &pmin, &pmax);
  143.   distance = bound_intersect(position, vector, &pmin, &pmax);
  144.   if ((distance > 0.0) AND(distance < small_distance))
  145.     if (BIG_DISTANCE(*p2, p4))
  146.       patch_bissect(&p1, p2, &p4, &p5, u0 + delta2, v0, delta2,
  147.                     position, vector);
  148.     else
  149.     {
  150.       temp.x = (p2->x + p4.x) * 0.5 - position->x;
  151.       temp.y = (p2->y + p4.y) * 0.5 - position->y;
  152.       temp.z = (p2->z + p4.z) * 0.5 - position->z;
  153.       distance = LENGTH(temp);
  154.       if ((distance > threshold_distance) AND(distance < small_distance))
  155.       {
  156.         small_distance = distance;
  157.         patch->u_hit = u0 + delta2 * 1.5;
  158.         patch->v_hit = v0 + delta2 * 0.5;
  159.       }
  160.     }
  161.   subpatch_enclose(&p3, &p4, p6, &p7, &pmin, &pmax);
  162.   distance = bound_intersect(position, vector, &pmin, &pmax);
  163.   if ((distance > 0.0) AND(distance < small_distance))
  164.     if (BIG_DISTANCE(*p6, p4))
  165.       patch_bissect(&p3, &p4, p6, &p7, u0, v0 + delta2, delta2,
  166.                     position, vector);
  167.     else
  168.     {
  169.       temp.x = (p6->x + p4.x) * 0.5 - position->x;
  170.       temp.y = (p6->y + p4.y) * 0.5 - position->y;
  171.       temp.z = (p6->z + p4.z) * 0.5 - position->z;
  172.       distance = LENGTH(temp);
  173.       if ((distance > threshold_distance) AND(distance < small_distance))
  174.       {
  175.         small_distance = distance;
  176.         patch->u_hit = u0 + delta2 * 0.5;
  177.         patch->v_hit = v0 + delta2 * 1.5;
  178.       }
  179.     }
  180.   subpatch_enclose(&p4, &p5, &p7, p8, &pmin, &pmax);
  181.   distance = bound_intersect(position, vector, &pmin, &pmax);
  182.   if ((distance > 0.0) AND(distance < small_distance))
  183.     if (BIG_DISTANCE(*p8, p4))
  184.       patch_bissect(&p4, &p5, &p7, p8, u0 + delta2, v0 + delta2, delta2,
  185.                     position, vector);
  186.     else
  187.     {
  188.       temp.x = (p8->x + p4.x) * 0.5 - position->x;
  189.       temp.y = (p8->y + p4.y) * 0.5 - position->y;
  190.       temp.z = (p8->z + p4.z) * 0.5 - position->z;
  191.       distance = LENGTH(temp);
  192.       if ((distance > threshold_distance) AND(distance < small_distance))
  193.       {
  194.         small_distance = distance;
  195.         patch->u_hit = u0 + delta2 * 1.5;
  196.         patch->v_hit = v0 + delta2 * 1.5;
  197.       }
  198.     }
  199. }
  200. void
  201. patch_divide(p0, p2, p6, p8, u0, v0, delta, level, position, vector)
  202.   xyz_ptr         p0, p2, p6, p8;
  203.   real            u0, v0, delta;
  204.   int             level;
  205.   xyz_ptr         position, vector;
  206. {
  207. #define LEVEL_MAX (8)
  208.   real            u, v, distance;
  209.   REG real        b0, b1, b2, b3, delta2;
  210.   xyz_struct      p1, p3, p4, p5, p7, pmin, pmax;
  211.  
  212.   delta2 = delta * 0.5;
  213.   /* Points 1 and 7 */
  214.   u = u0 + delta2;
  215.   b0 = BLEND0(u);
  216.   b1 = BLEND1(u);
  217.   CUBIC(patch, 0, u, k0);
  218.   CUBIC(patch, 2, u, k2);
  219.   MULTIPLY(p[0], b0, k4);
  220.   MULTIPLY(p[1], b1, k5);
  221.   MULTIPLY(p[2], b0, k6);
  222.   MULTIPLY(p[3], b1, k7);
  223.   SUBTRACT(k0, k4, k5, k0);
  224.   SUBTRACT(k2, k6, k7, k2);
  225.   /* Point 1 */
  226.   v = v0;
  227.   CUBIC(patch, 1, v, k1);
  228.   CUBIC(patch, 3, v, k3);
  229.   b2 = BLEND0(v);
  230.   b3 = BLEND1(v);
  231.   p1.x = k0.x * b2 + k1.x * b0 + k2.x * b3 + k3.x * b1;
  232.   p1.y = k0.y * b2 + k1.y * b0 + k2.y * b3 + k3.y * b1;
  233.   p1.z = k0.z * b2 + k1.z * b0 + k2.z * b3 + k3.z * b1;
  234.   /* Point 7 */
  235.   v = v0 + delta;
  236.   CUBIC(patch, 1, v, k1);
  237.   CUBIC(patch, 3, v, k3);
  238.   b2 = BLEND0(v);
  239.   b3 = BLEND1(v);
  240.   p7.x = k0.x * b2 + k1.x * b0 + k2.x * b3 + k3.x * b1;
  241.   p7.y = k0.y * b2 + k1.y * b0 + k2.y * b3 + k3.y * b1;
  242.   p7.z = k0.z * b2 + k1.z * b0 + k2.z * b3 + k3.z * b1;
  243.   /* Points 3, 4 and 5 */
  244.   v = v0 + delta2;
  245.   b0 = BLEND0(v);
  246.   b1 = BLEND1(v);
  247.   CUBIC(patch, 1, v, k1);
  248.   CUBIC(patch, 3, v, k3);
  249.   MULTIPLY(p[0], b0, k4);
  250.   MULTIPLY(p[1], b0, k5);
  251.   MULTIPLY(p[2], b1, k6);
  252.   MULTIPLY(p[3], b1, k7);
  253.   SUBTRACT(k1, k4, k6, k1);
  254.   SUBTRACT(k3, k5, k7, k3);
  255.   /* Point 3 */
  256.   u = u0;
  257.   CUBIC(patch, 0, u, k0);
  258.   CUBIC(patch, 2, u, k2);
  259.   b2 = BLEND0(u);
  260.   b3 = BLEND1(u);
  261.   p3.x = k0.x * b0 + k1.x * b2 + k2.x * b1 + k3.x * b3;
  262.   p3.y = k0.y * b0 + k1.y * b2 + k2.y * b1 + k3.y * b3;
  263.   p3.z = k0.z * b0 + k1.z * b2 + k2.z * b1 + k3.z * b3;
  264.   /* Point 4 */
  265.   u = u0 + delta2;
  266.   CUBIC(patch, 0, u, k0);
  267.   CUBIC(patch, 2, u, k2);
  268.   b2 = BLEND0(u);
  269.   b3 = BLEND1(u);
  270.   p4.x = k0.x * b0 + k1.x * b2 + k2.x * b1 + k3.x * b3;
  271.   p4.y = k0.y * b0 + k1.y * b2 + k2.y * b1 + k3.y * b3;
  272.   p4.z = k0.z * b0 + k1.z * b2 + k2.z * b1 + k3.z * b3;
  273.   /* Point 5 */
  274.   u = u0 + delta;
  275.   CUBIC(patch, 0, u, k0);
  276.   CUBIC(patch, 2, u, k2);
  277.   b2 = BLEND0(u);
  278.   b3 = BLEND1(u);
  279.   p5.x = k0.x * b0 + k1.x * b2 + k2.x * b1 + k3.x * b3;
  280.   p5.y = k0.y * b0 + k1.y * b2 + k2.y * b1 + k3.y * b3;
  281.   p5.z = k0.z * b0 + k1.z * b2 + k2.z * b1 + k3.z * b3;
  282.   subpatch_enclose(p0, &p1, &p3, &p4, &pmin, &pmax);
  283.   distance = bound_intersect(position, vector, &pmin, &pmax);
  284.   if ((distance > 0.0) AND(distance < small_distance))
  285.     if (level <= LEVEL_MAX)
  286.       patch_divide(p0, &p1, &p3, &p4, u0, v0, delta2, SUCC(level),
  287.                    position, vector);
  288.     else
  289.     {
  290.       if (NOT patch_damped_nr(u0 + delta2 * 0.5, v0 + delta2 * 0.5,
  291.                               position, vector))
  292.         patch_bissect(p0, &p1, &p3, &p4, u0, v0, delta2, position, vector);
  293.     }
  294.   subpatch_enclose(&p1, p2, &p4, &p5, &pmin, &pmax);
  295.   distance = bound_intersect(position, vector, &pmin, &pmax);
  296.   if ((distance > 0.0) AND(distance < small_distance))
  297.     if (level <= LEVEL_MAX)
  298.       patch_divide(&p1, p2, &p4, &p5, u0 + delta2, v0, delta2, SUCC(level),
  299.                    position, vector);
  300.     else
  301.     {
  302.       if (NOT patch_damped_nr(u0 + delta2 * 1.5, v0 + delta2 * 0.5,
  303.                               position, vector))
  304.         patch_bissect(&p1, p2, &p4, &p5, u0 + delta2, v0, delta2,
  305.                       position, vector);
  306.     }
  307.   subpatch_enclose(&p3, &p4, p6, &p7, &pmin, &pmax);
  308.   distance = bound_intersect(position, vector, &pmin, &pmax);
  309.   if ((distance > 0.0) AND(distance < small_distance))
  310.     if (level <= LEVEL_MAX)
  311.       patch_divide(&p3, &p4, p6, &p7, u0, v0 + delta2, delta2, SUCC(level),
  312.                    position, vector);
  313.     else
  314.     {
  315.       if (NOT patch_damped_nr(u0 + delta2 * 0.5, v0 + delta2 * 1.5,
  316.                               position, vector))
  317.         patch_bissect(&p3, &p4, p6, &p7, u0, v0 + delta2, delta2,
  318.                       position, vector);
  319.     }
  320.   subpatch_enclose(&p4, &p5, &p7, p8, &pmin, &pmax);
  321.   distance = bound_intersect(position, vector, &pmin, &pmax);
  322.   if ((distance > 0.0) AND(distance < small_distance))
  323.     if (level <= LEVEL_MAX)
  324.       patch_divide(&p4, &p5, &p7, p8, u0 + delta2, v0 + delta2, delta2,
  325.                    SUCC(level), position, vector);
  326.     else
  327.     {
  328.       if (NOT patch_damped_nr(u0 + delta2 * 1.5, v0 + delta2 * 1.5,
  329.                               position, vector))
  330.         patch_bissect(&p4, &p5, &p7, p8, u0 + delta2, v0 + delta2, delta2,
  331.                       position, vector);
  332.     }
  333. #undef LEVEL_MAX
  334. }
  335.