home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / curves.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  18KB  |  498 lines

  1. /*
  2.  * $Source: f:/miner/source/main/editor/rcs/curves.c $
  3.  * $Revision: 2.0 $
  4.  * $Author: john $
  5.  * $Date: 1995/02/27 11:35:50 $
  6.  *
  7.  * curve generation stuff
  8.  *
  9.  * 
  10.  *
  11.  */
  12.  
  13. #pragma off (unreferenced)
  14. static char rcsid[] = "$Id: curves.c 2.0 1995/02/27 11:35:50 john Exp $";
  15. #pragma on (unreferenced)
  16.  
  17. #include <time.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <ctype.h>
  22. #include <stdarg.h>
  23. #include <conio.h>
  24. #include <dos.h>
  25.  
  26. #include "inferno.h"
  27. #include "mono.h"
  28. #include "vecmat.h"
  29. #include "gr.h"
  30. #include "key.h"
  31. #include "editor.h"
  32. #include "gameseg.h"
  33.  
  34. #define ONE_OVER_SQRT2 F1_0 * 0.707106781
  35. #define CURVE_RIGHT 1
  36. #define CURVE_UP 2
  37.  
  38. segment *OriginalSeg;
  39. segment *OriginalMarkedSeg;
  40. int OriginalSide;
  41. int OriginalMarkedSide;
  42. segment *CurveSegs[MAX_SEGMENTS];
  43. int CurveNumSegs;
  44. const fix Mh[4][4] = { { 2*F1_0, -2*F1_0,  1*F1_0,  1*F1_0 },
  45.                        {-3*F1_0,  3*F1_0, -2*F1_0, -1*F1_0 },
  46.                        { 0*F1_0,  0*F1_0,  1*F1_0,  0*F1_0 },
  47.                        { 1*F1_0,  0*F1_0,  0*F1_0,  0*F1_0 } };
  48.  
  49. void create_curve(vms_vector *p1, vms_vector *p4, vms_vector *r1, vms_vector *r4, vms_equation *coeffs) {
  50. // Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t~3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4
  51.  
  52.     coeffs->x3 = fixmul(2*F1_0,p1->x) - fixmul(2*F1_0,p4->x) + r1->x + r4->x;
  53.     coeffs->x2 = fixmul(-3*F1_0,p1->x) + fixmul(3*F1_0,p4->x) - fixmul(2*F1_0,r1->x) - fixmul(1*F1_0,r4->x);
  54.     coeffs->x1 = r1->x;
  55.     coeffs->x0 = p1->x;
  56.     coeffs->y3 = fixmul(2*F1_0,p1->y) - fixmul(2*F1_0,p4->y) + r1->y + r4->y;
  57.     coeffs->y2 = fixmul(-3*F1_0,p1->y) + fixmul(3*F1_0,p4->y) - fixmul(2*F1_0,r1->y) - fixmul(1*F1_0,r4->y);
  58.     coeffs->y1 = r1->y;
  59.     coeffs->y0 = p1->y;
  60.     coeffs->z3 = fixmul(2*F1_0,p1->z) - fixmul(2*F1_0,p4->z) + r1->z + r4->z;
  61.     coeffs->z2 = fixmul(-3*F1_0,p1->z) + fixmul(3*F1_0,p4->z) - fixmul(2*F1_0,r1->z) - fixmul(1*F1_0,r4->z);
  62.     coeffs->z1 = r1->z;
  63.     coeffs->z0 = p1->z;
  64.  
  65. }
  66.  
  67. vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t) {
  68.     fix t2, t3;
  69.     vms_vector coord;
  70.  
  71.     if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
  72.  
  73.     t2 = fixmul(t,t); t3 = fixmul(t2,t);
  74.  
  75.     coord.x = fixmul(coeffs->x3,t3) + fixmul(coeffs->x2,t2) + fixmul(coeffs->x1,t) + coeffs->x0;
  76.     coord.y = fixmul(coeffs->y3,t3) + fixmul(coeffs->y2,t2) + fixmul(coeffs->y1,t) + coeffs->y0;
  77.     coord.z = fixmul(coeffs->z3,t3) + fixmul(coeffs->z2,t2) + fixmul(coeffs->z1,t) + coeffs->z0;
  78.  
  79.     return coord;
  80. }
  81.  
  82.  
  83. fix curve_dist(vms_equation *coeffs, int degree, fix t0, vms_vector *p0, fix dist) {
  84.      vms_vector coord;
  85.     fix t, diff;
  86.  
  87.     if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
  88.  
  89.     for (t=t0;t<1*F1_0;t+=0.001*F1_0) {
  90.         coord = evaluate_curve(coeffs, 3, t);
  91.         diff = dist - vm_vec_dist(&coord, p0);
  92.         if (diff<ACCURACY)   //&&(diff>-ACCURACY))
  93.             return t;
  94.     }
  95.     return -1*F1_0;
  96.  
  97. }
  98.  
  99. void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir) {
  100.     fix t2;
  101.  
  102.     if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
  103.  
  104.     t2 = fixmul(t0,t0);
  105.  
  106.     dir->x = fixmul(3*F1_0,fixmul(coeffs->x3,t2)) + fixmul(2*F1_0,fixmul(coeffs->x2,t0)) + coeffs->x1;
  107.     dir->y = fixmul(3*F1_0,fixmul(coeffs->y3,t2)) + fixmul(2*F1_0,fixmul(coeffs->y2,t0)) + coeffs->y1;
  108.     dir->z = fixmul(3*F1_0,fixmul(coeffs->z3,t2)) + fixmul(2*F1_0,fixmul(coeffs->z2,t0)) + coeffs->z1;
  109.     vm_vec_normalize( dir );
  110.  
  111. }
  112.  
  113. void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t) {
  114.     vms_vector coord, dcoord;
  115.     fix t, dt;
  116.  
  117.     gr_setcolor(15);
  118.     gr_box(  75,  40, 325, 290 );
  119.     gr_box(  75, 310, 325, 560 );
  120.     gr_box( 475, 310, 725, 560 );
  121.     //gr_pal_fade_in( grd_curscreen->pal );
  122.  
  123.     for (t=min_t;t<max_t-del_t;t+=del_t) {
  124.         dt = t+del_t;
  125.  
  126.         coord = evaluate_curve(coeffs, 3, t);
  127.         dcoord = evaluate_curve(coeffs, 3, dt);
  128.  
  129.         gr_setcolor(9);
  130.         gr_line (  75*F1_0 + coord.x, 290*F1_0 - coord.z,  75*F1_0 + dcoord.x, 290*F1_0 - dcoord.z );
  131.         gr_setcolor(10);
  132.         gr_line (  75*F1_0 + coord.x, 560*F1_0 - coord.y,  75*F1_0 + dcoord.x, 560*F1_0 - dcoord.y );
  133.         gr_setcolor(12);
  134.         gr_line ( 475*F1_0 + coord.z, 560*F1_0 - coord.y, 475*F1_0 + dcoord.z, 560*F1_0 - dcoord.y );
  135.  
  136.     }
  137.  
  138. }
  139.  
  140.  
  141. vms_vector *vm_vec_interp(vms_vector *result, vms_vector *v0, vms_vector *v1, fix scale) {
  142.     vms_vector tvec;
  143.  
  144.     vm_vec_sub(&tvec, v1, v0);
  145.     vm_vec_scale_add(result, v0, &tvec, scale);
  146.     vm_vec_normalize(result);
  147.     return result;
  148. }
  149.  
  150. vms_vector p1, p4, r1, r4;
  151. vms_vector r4t, r1save;
  152.  
  153. int generate_curve( fix r1scale, fix r4scale ) {
  154.     vms_vector vec_dir, tvec;
  155.     vms_vector coord,prev_point;
  156.     vms_equation coeffs;
  157.     fix enddist, nextdist;
  158.     int firstsegflag;
  159.     fix t, maxscale;
  160.     fixang rangle, uangle;
  161.  
  162.     compute_center_point_on_side( &p1, Cursegp, Curside );
  163.  
  164.     switch( Curside ) {
  165.         case WLEFT:
  166.             extract_right_vector_from_segment(Cursegp, &r1);
  167.             vm_vec_scale( &r1, -F1_0 );
  168.             break;
  169.         case WTOP:
  170.             extract_up_vector_from_segment(Cursegp, &r1);
  171.             break;
  172.         case WRIGHT:
  173.             extract_right_vector_from_segment(Cursegp, &r1);
  174.             break;
  175.         case WBOTTOM:
  176.             extract_up_vector_from_segment(Cursegp, &r1);
  177.             vm_vec_scale( &r1, -F1_0 );
  178.             break;
  179.         case WBACK:
  180.             extract_forward_vector_from_segment(Cursegp, &r1);
  181.             break;
  182.         case WFRONT:
  183.             extract_forward_vector_from_segment(Cursegp, &r1);
  184.             vm_vec_scale( &r1, -F1_0 );
  185.             break;
  186.         }            
  187.  
  188.     compute_center_point_on_side( &p4, Markedsegp, Markedside );
  189.  
  190.     switch( Markedside ) {
  191.         case WLEFT:
  192.             extract_right_vector_from_segment(Markedsegp, &r4);
  193.             extract_up_vector_from_segment(Markedsegp, &r4t);
  194.             break;
  195.         case WTOP:
  196.             extract_up_vector_from_segment(Markedsegp, &r4);
  197.             vm_vec_scale( &r4, -F1_0 );
  198.             extract_forward_vector_from_segment(Markedsegp, &r4t);
  199.             vm_vec_scale( &r4t, -F1_0 );
  200.             break;
  201.         case WRIGHT:
  202.             extract_right_vector_from_segment(Markedsegp, &r4);
  203.             vm_vec_scale( &r4, -F1_0 );
  204.             extract_up_vector_from_segment(Markedsegp, &r4t);
  205.             break;
  206.         case WBOTTOM:
  207.             extract_up_vector_from_segment(Markedsegp, &r4);
  208.             extract_forward_vector_from_segment(Markedsegp, &r4t);
  209.             break;
  210.         case WBACK:
  211.             extract_forward_vector_from_segment(Markedsegp, &r4);
  212.             vm_vec_scale( &r4, -F1_0 );
  213.             extract_up_vector_from_segment(Markedsegp, &r4t);
  214.             break;
  215.         case WFRONT:
  216.             extract_forward_vector_from_segment(Markedsegp, &r4);
  217.             extract_up_vector_from_segment(Markedsegp, &r4t);
  218.             break;
  219.         }
  220.  
  221.     r1save = r1;
  222.     tvec = r1;
  223.     vm_vec_scale(&r1,r1scale);
  224.     vm_vec_scale(&r4,r4scale);
  225.  
  226.     create_curve( &p1, &p4, &r1, &r4, &coeffs );
  227.     OriginalSeg = Cursegp;
  228.     OriginalMarkedSeg = Markedsegp;
  229.     OriginalSide = Curside;
  230.     OriginalMarkedSide = Markedside;
  231.     CurveNumSegs = 0;
  232.     coord = prev_point = p1;
  233.  
  234.     t=0;
  235.     firstsegflag = 1;
  236.     enddist = F1_0; nextdist = 0;
  237.     while ( enddist > fixmul( nextdist, 1.5*F1_0 )) {
  238.             vms_matrix  rotmat,rotmat2;
  239.             vms_vector    tdest;
  240.  
  241.             if (firstsegflag==1)
  242.                 firstsegflag=0;
  243.             else
  244.                 extract_forward_vector_from_segment(Cursegp, &tvec);
  245.             nextdist = vm_vec_mag(&tvec);                                   // nextdist := distance to next point
  246.             t = curve_dist(&coeffs, 3, t, &prev_point, nextdist);               // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve)
  247.             coord = evaluate_curve(&coeffs, 3, t);                                          // coord := point about forward vector magnitude units away from prev_point
  248.             enddist = vm_vec_dist(&coord, &p4);                  // enddist := distance from current to end point, vec_dir used as a temporary variable
  249.             //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point));
  250.             vm_vec_normalized_dir(&vec_dir, &coord, &prev_point);
  251.         if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) {
  252.             med_extract_matrix_from_segment( Cursegp,&rotmat );                   // rotmat := matrix describing orientation of Cursegp
  253.             vm_vec_rotate(&tdest,&vec_dir,&rotmat);    // tdest := vec_dir in reference frame of Cursegp
  254.             vec_dir = tdest;
  255.  
  256.             vm_vector_2_matrix(&rotmat2,&vec_dir,NULL,NULL);
  257. //            mprintf(0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3));
  258. //           mprintf(0, "  [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6));
  259. //            mprintf(0, "  [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9));
  260.  
  261.             med_rotate_segment( Cursegp, &rotmat2 );
  262.             prev_point = coord;
  263.             Curside = Side_opposite[AttachSide];
  264.  
  265.             CurveSegs[CurveNumSegs]=Cursegp;
  266.             CurveNumSegs++;
  267.         } else return 0;
  268.     }
  269.  
  270.     extract_up_vector_from_segment( Cursegp,&tvec );
  271.     uangle = vm_vec_delta_ang( &tvec, &r4t, &r4 );
  272.     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
  273.     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
  274.     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
  275.     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
  276.     extract_right_vector_from_segment( Cursegp,&tvec );
  277.     rangle = vm_vec_delta_ang( &tvec, &r4t, &r4 );
  278.     if (rangle >= F1_0/8) rangle -= F1_0/4;
  279.     if (rangle >= F1_0/8) rangle -= F1_0/4;
  280.     if (rangle <= -F1_0/8) rangle += F1_0/4;
  281.     if (rangle <= -F1_0/8) rangle += F1_0/4;
  282.  
  283.     if ((uangle != 0) && (rangle != 0)) {
  284.         maxscale = CurveNumSegs*F1_0;
  285. //        mprintf(0, "Banked Curve Generation.. %f.\n", f2fl(maxscale));
  286.         generate_banked_curve(maxscale, coeffs);
  287.     }
  288.  
  289.     if (CurveNumSegs) {
  290.         med_form_bridge_segment( Cursegp, Side_opposite[AttachSide], Markedsegp, Markedside );
  291.         CurveSegs[CurveNumSegs] = &Segments[ Markedsegp->children[Markedside] ];
  292.         CurveNumSegs++;
  293.     }
  294.  
  295.     Cursegp = OriginalSeg;
  296.     Curside = OriginalSide;
  297.  
  298.     med_create_new_segment_from_cursegp();
  299.  
  300.     //warn_if_concave_segments();
  301.  
  302.     if (CurveNumSegs) return 1;
  303.         else return 0;
  304. }
  305.  
  306. void generate_banked_curve(fix maxscale, vms_equation coeffs) {
  307.     vms_vector vec_dir, tvec, b4r4t;
  308.     vms_vector coord,prev_point;
  309.     fix enddist, nextdist;
  310.     int firstsegflag;
  311.     fixang rangle, uangle, angle, scaled_ang;
  312.     fix t;
  313.  
  314.     if (CurveNumSegs) {
  315.  
  316.     extract_up_vector_from_segment( Cursegp,&b4r4t );
  317.     uangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 );
  318.     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
  319.     if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
  320.     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
  321.     if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
  322. //    mprintf(0, "up angle %f\n", f2fl(uangle)*360);
  323.  
  324.     extract_right_vector_from_segment( Cursegp,&b4r4t );
  325.     rangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 );
  326.     if (rangle >= F1_0/8) rangle -= F1_0/4;
  327.     if (rangle >= F1_0/8) rangle -= F1_0/4;
  328.     if (rangle <= -F1_0/8) rangle += F1_0/4;
  329.     if (rangle <= -F1_0/8) rangle += F1_0/4;
  330. //    mprintf(0, "right angle %f\n", f2fl(rangle)*360);
  331.  
  332.     angle = uangle;
  333.     if (abs(rangle) < abs(uangle)) angle = rangle;
  334.  
  335.     delete_curve();
  336.  
  337.     coord = prev_point = p1;
  338.  
  339. #define MAGIC_NUM 0.707*F1_0
  340.  
  341.     if (maxscale)
  342.         scaled_ang = fixdiv(angle,fixmul(maxscale,MAGIC_NUM));
  343.     mprintf((0, "scaled angle = %f\n", f2fl(scaled_ang)));
  344.  
  345.     t=0; 
  346.     tvec = r1save;
  347.     firstsegflag = 1;
  348.     enddist = F1_0; nextdist = 0;
  349.     while ( enddist > fixmul( nextdist, 1.5*F1_0 )) {
  350.             vms_matrix  rotmat,rotmat2;
  351.             vms_vector  tdest;
  352.  
  353.             if (firstsegflag==1)
  354.                 firstsegflag=0;
  355.             else
  356.                 extract_forward_vector_from_segment(Cursegp, &tvec);
  357.             nextdist = vm_vec_mag(&tvec);                                   // nextdist := distance to next point
  358.             t = curve_dist(&coeffs, 3, t, &prev_point, nextdist);               // t = argument at which function is forward vector magnitude units away from prev_point (in 3-space, not along curve)
  359.             coord = evaluate_curve(&coeffs, 3, t);                                          // coord := point about forward vector magnitude units away from prev_point
  360.             enddist = vm_vec_dist(&coord, &p4);                  // enddist := distance from current to end point, vec_dir used as a temporary variable
  361.             //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point));
  362.             vm_vec_normalized_dir(&vec_dir, &coord, &prev_point);
  363.         if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) {
  364.             med_extract_matrix_from_segment( Cursegp,&rotmat );                   // rotmat := matrix describing orientation of Cursegp
  365.             vm_vec_rotate(&tdest,&vec_dir,&rotmat);    // tdest := vec_dir in reference frame of Cursegp
  366.             vec_dir = tdest;
  367.             vm_vec_ang_2_matrix(&rotmat2,&vec_dir,scaled_ang);
  368. //            mprintf((0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3)));
  369. //            mprintf((0, "  [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6)));
  370. //            mprintf((0, "  [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9)));
  371.  
  372.             med_rotate_segment( Cursegp, &rotmat2 );
  373.             prev_point = coord;
  374.             Curside = Side_opposite[AttachSide];
  375.  
  376.             CurveSegs[CurveNumSegs]=Cursegp;
  377.             CurveNumSegs++;
  378.         }
  379.       }
  380.     }
  381. }
  382.  
  383.  
  384. void delete_curve() {
  385.     int i;
  386.  
  387.     for (i=0; i<CurveNumSegs; i++) {
  388. //        mprintf((0, "[%d] %d\n", i, CurveSegs[i]->segnum ));
  389.         if (CurveSegs[i]->segnum != -1)
  390.             med_delete_segment(CurveSegs[i]);
  391.     }
  392.     Markedsegp = OriginalMarkedSeg;
  393.     Markedside = OriginalMarkedSide;
  394.     Cursegp = OriginalSeg;
  395.     Curside = OriginalSide;
  396.     med_create_new_segment_from_cursegp();
  397.     CurveNumSegs = 0;
  398. //    mprintf((0, "Num_segments %d\n", Num_segments));
  399.  
  400.     //editor_status("");
  401.     //warn_if_concave_segments();
  402. }
  403.  
  404. /*
  405. void main() {
  406.     vms_vector p1;
  407.     vms_vector p4;
  408.     vms_vector r1;
  409.     vms_vector r4;
  410.     vms_equation coeffs;
  411.     float x, y, z;
  412.     vms_vector test, test2, tvec;
  413.     fix t, t0;
  414.     fix distance, dist;
  415.     int key;
  416.  
  417.  
  418.     key_init();
  419.     printf("Enter p1 (x,y,z): ");
  420.     scanf("%f %f %f", &x, &y, &z);
  421.     p1.x = x*F1_0; p1.y = y*F1_0; p1.z = z*F1_0;
  422.     printf("Enter p4 (x,y,z): ");
  423.     scanf("%f %f %f", &x, &y, &z);
  424.     p4.x = x*F1_0; p4.y = y*F1_0; p4.z = z*F1_0;
  425.     printf("Enter r1 <x,y,z>: ");
  426.     scanf("%f %f %f", &x, &y, &z);
  427.     r1.x = x*F1_0; r1.y = y*F1_0; r1.z = z*F1_0;
  428.     printf("Enter r4 <x,y,z>: ");
  429.     scanf("%f %f %f", &x, &y, &z);
  430.     r4.x = x*F1_0; r4.y = y*F1_0; r4.z = z*F1_0;
  431.  
  432.     create_curve( &p1, &p4, &r1, &r4, &coeffs );
  433.  
  434.     printf("\nQ(t) = ");
  435.     printf("x [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.x3), f2fl(coeffs.x2), f2fl(coeffs.x1), f2fl(coeffs.x0));
  436.     printf("       y [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.y3), f2fl(coeffs.y2), f2fl(coeffs.y1), f2fl(coeffs.y0));
  437.     printf("       z [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.z3), f2fl(coeffs.z2), f2fl(coeffs.z1), f2fl(coeffs.z0));
  438.  
  439.     printf("\nChecking direction vectors.\n");
  440.  
  441.     for (t=0*F1_0;t<1*F1_0;t+=0.1*F1_0) {
  442.         curve_dir(&coeffs, 3, t, &test);
  443.         printf(" t = %.3f  dir = <%6.3f, %6.3f, %6.3f >\n", f2fl(t), f2fl(test.x), f2fl(test.y), f2fl(test.z) );
  444.     }
  445.  
  446.     printf("\nChecking distance function.\n");
  447.     printf("Enter a distance: ");
  448.     scanf("%f", &x);
  449.     distance = x*F1_0;
  450.     printf("Enter a (0<t<1) value: ");
  451.     scanf("%f", &y);
  452.     t0 = y*F1_0;
  453.  
  454.     gr_init(15);  // 800x600 mode
  455.     plot_parametric(&coeffs, 0*F1_0, 1*F1_0, 0.05*F1_0);
  456.  
  457.     test = evaluate_curve(&coeffs, 3, t0);
  458.     t = curve_dist(&coeffs, 3, t0, &test, distance);
  459.     test2 = evaluate_curve(&coeffs, 3, t);
  460.  
  461.     dist = vm_vec_mag(vm_vec_sub(&tvec, &test, &test2));
  462.  
  463.     if (t != -1*F1_0) {
  464.         gr_setcolor(14);
  465.         gr_rect(  74+f2fl(test.x), 289-f2fl(test.z),  76+f2fl(test.x), 291-f2fl(test.z) );
  466.         gr_rect(  74+f2fl(test.x), 559-f2fl(test.y),  76+f2fl(test.x), 561-f2fl(test.y) );
  467.         gr_rect( 474+f2fl(test.z), 559-f2fl(test.y), 476+f2fl(test.z), 561-f2fl(test.y) );
  468.         gr_setcolor(13);
  469.         gr_rect(  74+f2fl(test2.x), 289-f2fl(test2.z),  76+f2fl(test2.x), 291-f2fl(test2.z) );
  470.         gr_rect(  74+f2fl(test2.x), 559-f2fl(test2.y),  76+f2fl(test2.x), 561-f2fl(test2.y) );
  471.         gr_rect( 474+f2fl(test2.z), 559-f2fl(test2.y), 476+f2fl(test2.z), 561-f2fl(test2.y) );
  472.     }
  473.  
  474.     key = -1;
  475.     while (1)
  476.         if (key == KEY_ESC) break;
  477.         else key = key_getch();
  478.  
  479.     gr_close();
  480.     key_close();
  481.  
  482.     if (t == -1*F1_0) {
  483.         printf("From t=%.3f to t=1.000, ", f2fl(t0));
  484.         printf("two points separated by the distance %.3f\n do not exist on this curve.\n", x);
  485.     }
  486.     else {
  487.         printf("\nThe distance between points at:\n");
  488.         printf(" t0 = %.3f  ( %6.3f,%6.3f,%6.3f ) and\n", f2fl(t0), f2fl(test.x), f2fl(test.y), f2fl(test.z));
  489.         printf(" t  = %.3f  ( %6.3f,%6.3f,%6.3f ) is:\n", f2fl(t), f2fl(test2.x), f2fl(test2.y), f2fl(test2.z));
  490.         printf(" expected: %.3f\n", x);
  491.         printf("  actual : %.3f\n", f2fl(dist) );
  492.     }
  493.  
  494. }
  495. */
  496.  
  497.  
  498.