123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- /*
- * $Source: f:/miner/source/main/editor/rcs/curves.c $
- * $Revision: 2.0 $
- * $Author: john $
- * $Date: 1995/02/27 11:35:50 $
- *
- * curve generation stuff
- *
- *
- *
- */
- #pragma off (unreferenced)
- static char rcsid[] = "$Id: curves.c 2.0 1995/02/27 11:35:50 john Exp $";
- #pragma on (unreferenced)
- #include <time.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <stdarg.h>
- #include <conio.h>
- #include <dos.h>
- #include "inferno.h"
- #include "mono.h"
- #include "vecmat.h"
- #include "gr.h"
- #include "key.h"
- #include "editor.h"
- #include "gameseg.h"
- #define ONE_OVER_SQRT2 F1_0 * 0.707106781
- #define CURVE_RIGHT 1
- #define CURVE_UP 2
- segment *OriginalSeg;
- segment *OriginalMarkedSeg;
- int OriginalSide;
- int OriginalMarkedSide;
- segment *CurveSegs[MAX_SEGMENTS];
- int CurveNumSegs;
- const fix Mh[4][4] = { { 2*F1_0, -2*F1_0, 1*F1_0, 1*F1_0 },
- {-3*F1_0, 3*F1_0, -2*F1_0, -1*F1_0 },
- { 0*F1_0, 0*F1_0, 1*F1_0, 0*F1_0 },
- { 1*F1_0, 0*F1_0, 0*F1_0, 0*F1_0 } };
- void create_curve(vms_vector *p1, vms_vector *p4, vms_vector *r1, vms_vector *r4, vms_equation *coeffs) {
- // Q(t) = (2t^3 - 3t^2 + 1) p1 + (-2t^3 + 3t^2) p4 + (t~3 - 2t^2 + t) r1 + (t^3 - t^2 ) r4
- coeffs->x3 = fixmul(2*F1_0,p1->x) - fixmul(2*F1_0,p4->x) + r1->x + r4->x;
- 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);
- coeffs->x1 = r1->x;
- coeffs->x0 = p1->x;
- coeffs->y3 = fixmul(2*F1_0,p1->y) - fixmul(2*F1_0,p4->y) + r1->y + r4->y;
- 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);
- coeffs->y1 = r1->y;
- coeffs->y0 = p1->y;
- coeffs->z3 = fixmul(2*F1_0,p1->z) - fixmul(2*F1_0,p4->z) + r1->z + r4->z;
- 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);
- coeffs->z1 = r1->z;
- coeffs->z0 = p1->z;
- }
- vms_vector evaluate_curve(vms_equation *coeffs, int degree, fix t) {
- fix t2, t3;
- vms_vector coord;
- if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
- t2 = fixmul(t,t); t3 = fixmul(t2,t);
- coord.x = fixmul(coeffs->x3,t3) + fixmul(coeffs->x2,t2) + fixmul(coeffs->x1,t) + coeffs->x0;
- coord.y = fixmul(coeffs->y3,t3) + fixmul(coeffs->y2,t2) + fixmul(coeffs->y1,t) + coeffs->y0;
- coord.z = fixmul(coeffs->z3,t3) + fixmul(coeffs->z2,t2) + fixmul(coeffs->z1,t) + coeffs->z0;
- return coord;
- }
- fix curve_dist(vms_equation *coeffs, int degree, fix t0, vms_vector *p0, fix dist) {
- vms_vector coord;
- fix t, diff;
- if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
- for (t=t0;t<1*F1_0;t+=0.001*F1_0) {
- coord = evaluate_curve(coeffs, 3, t);
- diff = dist - vm_vec_dist(&coord, p0);
- if (diff<ACCURACY) //&&(diff>-ACCURACY))
- return t;
- }
- return -1*F1_0;
- }
- void curve_dir(vms_equation *coeffs, int degree, fix t0, vms_vector *dir) {
- fix t2;
- if (degree!=3) printf("ERROR: for Hermite Curves degree must be 3\n");
- t2 = fixmul(t0,t0);
- dir->x = fixmul(3*F1_0,fixmul(coeffs->x3,t2)) + fixmul(2*F1_0,fixmul(coeffs->x2,t0)) + coeffs->x1;
- dir->y = fixmul(3*F1_0,fixmul(coeffs->y3,t2)) + fixmul(2*F1_0,fixmul(coeffs->y2,t0)) + coeffs->y1;
- dir->z = fixmul(3*F1_0,fixmul(coeffs->z3,t2)) + fixmul(2*F1_0,fixmul(coeffs->z2,t0)) + coeffs->z1;
- vm_vec_normalize( dir );
- }
- void plot_parametric(vms_equation *coeffs, fix min_t, fix max_t, fix del_t) {
- vms_vector coord, dcoord;
- fix t, dt;
- gr_setcolor(15);
- gr_box( 75, 40, 325, 290 );
- gr_box( 75, 310, 325, 560 );
- gr_box( 475, 310, 725, 560 );
- //gr_pal_fade_in( grd_curscreen->pal );
- for (t=min_t;t<max_t-del_t;t+=del_t) {
- dt = t+del_t;
- coord = evaluate_curve(coeffs, 3, t);
- dcoord = evaluate_curve(coeffs, 3, dt);
- gr_setcolor(9);
- gr_line ( 75*F1_0 + coord.x, 290*F1_0 - coord.z, 75*F1_0 + dcoord.x, 290*F1_0 - dcoord.z );
- gr_setcolor(10);
- gr_line ( 75*F1_0 + coord.x, 560*F1_0 - coord.y, 75*F1_0 + dcoord.x, 560*F1_0 - dcoord.y );
- gr_setcolor(12);
- gr_line ( 475*F1_0 + coord.z, 560*F1_0 - coord.y, 475*F1_0 + dcoord.z, 560*F1_0 - dcoord.y );
- }
- }
- vms_vector *vm_vec_interp(vms_vector *result, vms_vector *v0, vms_vector *v1, fix scale) {
- vms_vector tvec;
- vm_vec_sub(&tvec, v1, v0);
- vm_vec_scale_add(result, v0, &tvec, scale);
- vm_vec_normalize(result);
- return result;
- }
- vms_vector p1, p4, r1, r4;
- vms_vector r4t, r1save;
- int generate_curve( fix r1scale, fix r4scale ) {
- vms_vector vec_dir, tvec;
- vms_vector coord,prev_point;
- vms_equation coeffs;
- fix enddist, nextdist;
- int firstsegflag;
- fix t, maxscale;
- fixang rangle, uangle;
- compute_center_point_on_side( &p1, Cursegp, Curside );
- switch( Curside ) {
- case WLEFT:
- extract_right_vector_from_segment(Cursegp, &r1);
- vm_vec_scale( &r1, -F1_0 );
- break;
- case WTOP:
- extract_up_vector_from_segment(Cursegp, &r1);
- break;
- case WRIGHT:
- extract_right_vector_from_segment(Cursegp, &r1);
- break;
- case WBOTTOM:
- extract_up_vector_from_segment(Cursegp, &r1);
- vm_vec_scale( &r1, -F1_0 );
- break;
- case WBACK:
- extract_forward_vector_from_segment(Cursegp, &r1);
- break;
- case WFRONT:
- extract_forward_vector_from_segment(Cursegp, &r1);
- vm_vec_scale( &r1, -F1_0 );
- break;
- }
- compute_center_point_on_side( &p4, Markedsegp, Markedside );
- switch( Markedside ) {
- case WLEFT:
- extract_right_vector_from_segment(Markedsegp, &r4);
- extract_up_vector_from_segment(Markedsegp, &r4t);
- break;
- case WTOP:
- extract_up_vector_from_segment(Markedsegp, &r4);
- vm_vec_scale( &r4, -F1_0 );
- extract_forward_vector_from_segment(Markedsegp, &r4t);
- vm_vec_scale( &r4t, -F1_0 );
- break;
- case WRIGHT:
- extract_right_vector_from_segment(Markedsegp, &r4);
- vm_vec_scale( &r4, -F1_0 );
- extract_up_vector_from_segment(Markedsegp, &r4t);
- break;
- case WBOTTOM:
- extract_up_vector_from_segment(Markedsegp, &r4);
- extract_forward_vector_from_segment(Markedsegp, &r4t);
- break;
- case WBACK:
- extract_forward_vector_from_segment(Markedsegp, &r4);
- vm_vec_scale( &r4, -F1_0 );
- extract_up_vector_from_segment(Markedsegp, &r4t);
- break;
- case WFRONT:
- extract_forward_vector_from_segment(Markedsegp, &r4);
- extract_up_vector_from_segment(Markedsegp, &r4t);
- break;
- }
- r1save = r1;
- tvec = r1;
- vm_vec_scale(&r1,r1scale);
- vm_vec_scale(&r4,r4scale);
- create_curve( &p1, &p4, &r1, &r4, &coeffs );
- OriginalSeg = Cursegp;
- OriginalMarkedSeg = Markedsegp;
- OriginalSide = Curside;
- OriginalMarkedSide = Markedside;
- CurveNumSegs = 0;
- coord = prev_point = p1;
- t=0;
- firstsegflag = 1;
- enddist = F1_0; nextdist = 0;
- while ( enddist > fixmul( nextdist, 1.5*F1_0 )) {
- vms_matrix rotmat,rotmat2;
- vms_vector tdest;
- if (firstsegflag==1)
- firstsegflag=0;
- else
- extract_forward_vector_from_segment(Cursegp, &tvec);
- nextdist = vm_vec_mag(&tvec); // nextdist := distance to next point
- 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)
- coord = evaluate_curve(&coeffs, 3, t); // coord := point about forward vector magnitude units away from prev_point
- enddist = vm_vec_dist(&coord, &p4); // enddist := distance from current to end point, vec_dir used as a temporary variable
- //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point));
- vm_vec_normalized_dir(&vec_dir, &coord, &prev_point);
- if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) {
- med_extract_matrix_from_segment( Cursegp,&rotmat ); // rotmat := matrix describing orientation of Cursegp
- vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp
- vec_dir = tdest;
- vm_vector_2_matrix(&rotmat2,&vec_dir,NULL,NULL);
- // mprintf(0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3));
- // mprintf(0, " [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6));
- // mprintf(0, " [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9));
- med_rotate_segment( Cursegp, &rotmat2 );
- prev_point = coord;
- Curside = Side_opposite[AttachSide];
- CurveSegs[CurveNumSegs]=Cursegp;
- CurveNumSegs++;
- } else return 0;
- }
- extract_up_vector_from_segment( Cursegp,&tvec );
- uangle = vm_vec_delta_ang( &tvec, &r4t, &r4 );
- if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
- if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
- if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
- if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
- extract_right_vector_from_segment( Cursegp,&tvec );
- rangle = vm_vec_delta_ang( &tvec, &r4t, &r4 );
- if (rangle >= F1_0/8) rangle -= F1_0/4;
- if (rangle >= F1_0/8) rangle -= F1_0/4;
- if (rangle <= -F1_0/8) rangle += F1_0/4;
- if (rangle <= -F1_0/8) rangle += F1_0/4;
- if ((uangle != 0) && (rangle != 0)) {
- maxscale = CurveNumSegs*F1_0;
- // mprintf(0, "Banked Curve Generation.. %f.\n", f2fl(maxscale));
- generate_banked_curve(maxscale, coeffs);
- }
- if (CurveNumSegs) {
- med_form_bridge_segment( Cursegp, Side_opposite[AttachSide], Markedsegp, Markedside );
- CurveSegs[CurveNumSegs] = &Segments[ Markedsegp->children[Markedside] ];
- CurveNumSegs++;
- }
- Cursegp = OriginalSeg;
- Curside = OriginalSide;
- med_create_new_segment_from_cursegp();
- //warn_if_concave_segments();
- if (CurveNumSegs) return 1;
- else return 0;
- }
- void generate_banked_curve(fix maxscale, vms_equation coeffs) {
- vms_vector vec_dir, tvec, b4r4t;
- vms_vector coord,prev_point;
- fix enddist, nextdist;
- int firstsegflag;
- fixang rangle, uangle, angle, scaled_ang;
- fix t;
- if (CurveNumSegs) {
- extract_up_vector_from_segment( Cursegp,&b4r4t );
- uangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 );
- if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
- if (uangle >= F1_0 * 1/8) uangle -= F1_0 * 1/4;
- if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
- if (uangle <= -F1_0 * 1/8) uangle += F1_0 * 1/4;
- // mprintf(0, "up angle %f\n", f2fl(uangle)*360);
- extract_right_vector_from_segment( Cursegp,&b4r4t );
- rangle = vm_vec_delta_ang( &b4r4t, &r4t, &r4 );
- if (rangle >= F1_0/8) rangle -= F1_0/4;
- if (rangle >= F1_0/8) rangle -= F1_0/4;
- if (rangle <= -F1_0/8) rangle += F1_0/4;
- if (rangle <= -F1_0/8) rangle += F1_0/4;
- // mprintf(0, "right angle %f\n", f2fl(rangle)*360);
- angle = uangle;
- if (abs(rangle) < abs(uangle)) angle = rangle;
- delete_curve();
- coord = prev_point = p1;
- #define MAGIC_NUM 0.707*F1_0
- if (maxscale)
- scaled_ang = fixdiv(angle,fixmul(maxscale,MAGIC_NUM));
- mprintf((0, "scaled angle = %f\n", f2fl(scaled_ang)));
- t=0;
- tvec = r1save;
- firstsegflag = 1;
- enddist = F1_0; nextdist = 0;
- while ( enddist > fixmul( nextdist, 1.5*F1_0 )) {
- vms_matrix rotmat,rotmat2;
- vms_vector tdest;
- if (firstsegflag==1)
- firstsegflag=0;
- else
- extract_forward_vector_from_segment(Cursegp, &tvec);
- nextdist = vm_vec_mag(&tvec); // nextdist := distance to next point
- 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)
- coord = evaluate_curve(&coeffs, 3, t); // coord := point about forward vector magnitude units away from prev_point
- enddist = vm_vec_dist(&coord, &p4); // enddist := distance from current to end point, vec_dir used as a temporary variable
- //vm_vec_normalize(vm_vec_sub(&vec_dir, &coord, &prev_point));
- vm_vec_normalized_dir(&vec_dir, &coord, &prev_point);
- if (!med_attach_segment( Cursegp, &New_segment, Curside, AttachSide )) {
- med_extract_matrix_from_segment( Cursegp,&rotmat ); // rotmat := matrix describing orientation of Cursegp
- vm_vec_rotate(&tdest,&vec_dir,&rotmat); // tdest := vec_dir in reference frame of Cursegp
- vec_dir = tdest;
- vm_vec_ang_2_matrix(&rotmat2,&vec_dir,scaled_ang);
- // mprintf((0, "[ [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m1), f2fl(rotmat2.m2), f2fl(rotmat2.m3)));
- // mprintf((0, " [%6.2f %6.2f %6.2f]", f2fl(rotmat2.m4), f2fl(rotmat2.m5), f2fl(rotmat2.m6)));
- // mprintf((0, " [%6.2f %6.2f %6.2f] ]\n", f2fl(rotmat2.m7), f2fl(rotmat2.m8), f2fl(rotmat2.m9)));
- med_rotate_segment( Cursegp, &rotmat2 );
- prev_point = coord;
- Curside = Side_opposite[AttachSide];
- CurveSegs[CurveNumSegs]=Cursegp;
- CurveNumSegs++;
- }
- }
- }
- }
- void delete_curve() {
- int i;
- for (i=0; i<CurveNumSegs; i++) {
- // mprintf((0, "[%d] %d\n", i, CurveSegs[i]->segnum ));
- if (CurveSegs[i]->segnum != -1)
- med_delete_segment(CurveSegs[i]);
- }
- Markedsegp = OriginalMarkedSeg;
- Markedside = OriginalMarkedSide;
- Cursegp = OriginalSeg;
- Curside = OriginalSide;
- med_create_new_segment_from_cursegp();
- CurveNumSegs = 0;
- // mprintf((0, "Num_segments %d\n", Num_segments));
- //editor_status("");
- //warn_if_concave_segments();
- }
- /*
- void main() {
- vms_vector p1;
- vms_vector p4;
- vms_vector r1;
- vms_vector r4;
- vms_equation coeffs;
- float x, y, z;
- vms_vector test, test2, tvec;
- fix t, t0;
- fix distance, dist;
- int key;
- key_init();
- printf("Enter p1 (x,y,z): ");
- scanf("%f %f %f", &x, &y, &z);
- p1.x = x*F1_0; p1.y = y*F1_0; p1.z = z*F1_0;
- printf("Enter p4 (x,y,z): ");
- scanf("%f %f %f", &x, &y, &z);
- p4.x = x*F1_0; p4.y = y*F1_0; p4.z = z*F1_0;
- printf("Enter r1 <x,y,z>: ");
- scanf("%f %f %f", &x, &y, &z);
- r1.x = x*F1_0; r1.y = y*F1_0; r1.z = z*F1_0;
- printf("Enter r4 <x,y,z>: ");
- scanf("%f %f %f", &x, &y, &z);
- r4.x = x*F1_0; r4.y = y*F1_0; r4.z = z*F1_0;
- create_curve( &p1, &p4, &r1, &r4, &coeffs );
- printf("\nQ(t) = ");
- printf("x [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.x3), f2fl(coeffs.x2), f2fl(coeffs.x1), f2fl(coeffs.x0));
- printf(" y [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.y3), f2fl(coeffs.y2), f2fl(coeffs.y1), f2fl(coeffs.y0));
- printf(" z [%6.3f %6.3f %6.3f %6.3f]\n", f2fl(coeffs.z3), f2fl(coeffs.z2), f2fl(coeffs.z1), f2fl(coeffs.z0));
- printf("\nChecking direction vectors.\n");
- for (t=0*F1_0;t<1*F1_0;t+=0.1*F1_0) {
- curve_dir(&coeffs, 3, t, &test);
- printf(" t = %.3f dir = <%6.3f, %6.3f, %6.3f >\n", f2fl(t), f2fl(test.x), f2fl(test.y), f2fl(test.z) );
- }
- printf("\nChecking distance function.\n");
- printf("Enter a distance: ");
- scanf("%f", &x);
- distance = x*F1_0;
- printf("Enter a (0<t<1) value: ");
- scanf("%f", &y);
- t0 = y*F1_0;
- gr_init(15); // 800x600 mode
- plot_parametric(&coeffs, 0*F1_0, 1*F1_0, 0.05*F1_0);
- test = evaluate_curve(&coeffs, 3, t0);
- t = curve_dist(&coeffs, 3, t0, &test, distance);
- test2 = evaluate_curve(&coeffs, 3, t);
- dist = vm_vec_mag(vm_vec_sub(&tvec, &test, &test2));
- if (t != -1*F1_0) {
- gr_setcolor(14);
- gr_rect( 74+f2fl(test.x), 289-f2fl(test.z), 76+f2fl(test.x), 291-f2fl(test.z) );
- gr_rect( 74+f2fl(test.x), 559-f2fl(test.y), 76+f2fl(test.x), 561-f2fl(test.y) );
- gr_rect( 474+f2fl(test.z), 559-f2fl(test.y), 476+f2fl(test.z), 561-f2fl(test.y) );
- gr_setcolor(13);
- gr_rect( 74+f2fl(test2.x), 289-f2fl(test2.z), 76+f2fl(test2.x), 291-f2fl(test2.z) );
- gr_rect( 74+f2fl(test2.x), 559-f2fl(test2.y), 76+f2fl(test2.x), 561-f2fl(test2.y) );
- gr_rect( 474+f2fl(test2.z), 559-f2fl(test2.y), 476+f2fl(test2.z), 561-f2fl(test2.y) );
- }
- key = -1;
- while (1)
- if (key == KEY_ESC) break;
- else key = key_getch();
- gr_close();
- key_close();
- if (t == -1*F1_0) {
- printf("From t=%.3f to t=1.000, ", f2fl(t0));
- printf("two points separated by the distance %.3f\n do not exist on this curve.\n", x);
- }
- else {
- printf("\nThe distance between points at:\n");
- printf(" t0 = %.3f ( %6.3f,%6.3f,%6.3f ) and\n", f2fl(t0), f2fl(test.x), f2fl(test.y), f2fl(test.z));
- printf(" t = %.3f ( %6.3f,%6.3f,%6.3f ) is:\n", f2fl(t), f2fl(test2.x), f2fl(test2.y), f2fl(test2.z));
- printf(" expected: %.3f\n", x);
- printf(" actual : %.3f\n", f2fl(dist) );
- }
- }
- */
|