/************************************************************************ 3DPath v1.00 Copyright (c) 1994 by Keith Vertanen, Scott Perowitz & Aleksey Przhelyaskovskiy Contact authors before distributing modified copies ************************************************************************/ #include #include #include #include #include #include // for getch() primitive #include // for sqrt() #include "spline.cpp" #define VER "v1.00" #define ERR1 "\nERROR: You must specify names of a point and a script files.\n\n" #define ERR2 "\nERROR: Invalid option.\n\n" #define ERR3 "\nERROR: File name must be specified.\n\n" #define ERR4 "\nERROR: Number of frames should be specified.\n\n" #define ERR5 "\nERROR: Cannot open script file: " #define ERR6 "\nERROR: Not enough control points for cubic spline.\n\n" #define ERR7 "\nERROR: No location section.\n\n" #define ERR8 "\nERROR: No closing '>' in location section.\n\n" #define ERR9 "\nERROR: No look_at section.\n\n" #define ERR10 "\nERROR: No closing '>' in look_at section.\n\n" #define ERR11 "\nERROR: Invalid example batch file.\n\n" #define ERR12 "\nERROR: Cannot open example file: " #define ERR13 "\nERROR: Not enough control points for spline.\n\n"; void show_help(); // display command line help void read_command_line(int argc, char *argv[], int *num_frames, int *degree, int *view, int *test_script, int *batch, char point_file[40], char script_file[40], char out_file[40], char override_file[40], char example_file[40], char static_look_at[40]) ; //parse the command line int find_length(char *open_file); // gets # of lines in a file void read_points(char point_file[40], point *control, int *num_control, int *closed); // read the control points into array int search(char *text, char *pattern); // find position of pattern in text void int_to_str(char text[5], int num); // convert int to string void do_script(char script_file[40], char override_file[40], point *position, int num_frames, char static_look_at[40], int closed); void show_spline(int view, int num_control, int num_frames, point *position, point *control_points); void make_test_script(char script_file[40],char override_file[40], point *position,int num_frames); void do_batch(char out_file[40], char example_file[40], char override_file[40], char script_file[40], int num_frames,int closed); void main(int argc, char *argv[]) { char point_file[40], script_file[40], out_file[40], override_file[40], example_file[40]; int num_frames, num_control=0, degree=3, view=0, test_script=0, batch=0, closed=0, j; point *control_points, *position; char static_look_at[40]; for (j=0; j<40; j++) // null all the filename arrays { point_file[j]=NULL; script_file[j]=NULL; out_file[j]=NULL; override_file[j]=NULL; example_file[j]=NULL; static_look_at[j]=NULL; } strcpy(example_file, "3dsample.bat"); // get all the filenames and options from the command line read_command_line(argc,argv,&num_frames,°ree,&view,&test_script, &batch,point_file,script_file,out_file, override_file,example_file,static_look_at); // allocate the control array and read it from the point file num_control=find_length(point_file); if (num_control<=degree) { cout << ERR13; exit(-1); } control_points=new point[num_control+1]; read_points(point_file, control_points, &num_control, &closed); // allocate the position array and calculate it from the bspline if (closed) // add an extra if closed since we'll drop the duplicate last point num_frames++; position=new point[num_frames]; bspline(num_control-1,degree+1,control_points,position,num_frames); if (test_script) // does user want just a test script generated { make_test_script(script_file,override_file,position,num_frames); } else { if (view>0) show_spline(view,num_control,num_frames,position,control_points); else do_script(script_file,override_file,position,num_frames, static_look_at,closed); } if (batch!=0) do_batch(out_file,example_file,override_file,script_file,num_frames,closed); } void show_help() { cout << "3DPath " << VER << " Copyright (c) 1994 by\n"; cout << "Keith Vertanen, Scott Perowitz & Aleksey Przhelyaskovskiy\n"; cout << "=================================================================\n"; cout << "Command line:\n"; cout << " 3DPath pointfile[.3d] scriptfile[.pov]\n\n"; cout << "Optional switches:\n"; cout << " -f(# frames) how many frames to generate (default 100)\n"; cout << " -b(filename) create output batch file (filename optional)\n"; cout << " -d(filename) example batch file to base output on\n"; cout << " -o(filename) override filename for the output scripts\n"; cout << " -p(#) degree of polynomial for spline (default 3)\n"; cout << " -xy -xz -yz view curve in xy, xz, or yz plane without generating scripts\n"; cout << " -l(x,y,z) use static look_at vector of x,y,z (i.e. -l100,50,25)\n"; cout << " -t create test script with path as spheres\n"; } void read_command_line(int argc, char *argv[], int *num_frames, int *degree, int *view, int *test_script, int *batch,char point_file[40], char script_file[40],char out_file[40], char override_file[40],char example_file[40], char static_look_at[40]) { int i,j,k,l; int found; // if # of arguments < 2, print help screen & exit if (argc <= 2) { show_help(); // this line should be changed to the call to a help screen exit(-1); } //if *num_frames=-1; // go through the arguments for (i=1; i < argc; i++) { switch (i) { case 1: { found=0; for (j=0; j1)) num_lines++; } source.close(); } else { cout << "\nERROR: Cannot open point file: " << open_file << ".\n"; exit(-1); } return num_lines; } void read_points(char *point_file, point *control, int *num_lines, int *closed) { int i; char line[256]; double x,y,z; int len=255; char stop='\n'; ifstream source; source.open(point_file,ios::nocreate); // open her up again if (source) { i=0; while (i<(*num_lines)) { source.getline(line,len,stop); if ((line[0]!='#') && (strlen(line)>1)) { istrstream ins(line,strlen(line)); ins >> x >> y >> z; (control[i]).x=x; (control[i]).y=y; (control[i]).z=z; i++; } } } else { cout << "\nERROR: Cannot open point file: " << point_file << "\n"; exit(-1); } if ((control[i-1].x==control[0].x) && (control[i-1].y==control[0].y) && (control[i-1].z==control[0].z)) // if first pt = last pt, insert smoothing point { double dx,dy,dz; control[i].x=control[i-1].x; // copy last point down one control[i].y=control[i-1].y; control[i].z=control[i-1].z; dx=control[1].x-control[0].x; dy=control[1].y-control[0].y; dz=control[1].z-control[0].z; control[i-1].x=control[0].x-dx; control[i-1].y=control[0].y-dy; control[i-1].z=control[0].z-dz; *num_lines=*num_lines+1; // pass back that we have one more control point cout << "Closed path detected, inserting control point to smooth.\n"; *closed=1; } } int search(char *text, char *pattern) { int i, j, M, N; char *p,*a; p=strupr(pattern); a=strupr(text); M=strlen(p); N=strlen(a); for (i=0, j=0; j0) || (j>0)) // no leading zeros wanted { switch (a) { case 0 : { text[j]='0'; break; } case 1 : { text[j]='1'; break; } case 2 : { text[j]='2'; break; } case 3 : { text[j]='3'; break; } case 4 : { text[j]='4'; break; } case 5 : { text[j]='5'; break; } case 6 : { text[j]='6'; break; } case 7 : { text[j]='7'; break; } case 8 : { text[j]='8'; break; } case 9 : { text[j]='9'; break; } } j++; num=num-(e*a); } e=e/10; } for (i=j; i<6; i++) text[i]=NULL; } void do_script(char script_file[40], char override_file[40], point *position, int num_frames, char static_look_at[40], int closed) { int current_frame, end_camera, i = 0; int begin_camera_pos; int begin_location, end_location, begin_look_at, end_look_at = 0; int begin_location_pos, end_location_pos, begin_look_at_pos, end_look_at_pos = 0; int j; char ch, insertion[200]; char *x; double xt,yt,zt; ifstream script; script.open(script_file,ios::nocreate); // open up script source file if (script) { int len=255; char stop='\n'; char line[256]; char *ptr; char a='>'; // We will now find, with surgical precision, the line number and // position of the location and look_at keywords in the camera section // of the script file. NOTE: location must precede look_at or else while (script.eof()==0) // search the file to find the location of camera section { script.getline(line,len,stop); begin_camera_pos=search(line,"camera"); if (begin_camera_pos=strlen(line)) { if (script.eof()) { cout << ERR7; exit(-1); } script.getline(line,len,stop); begin_location_pos=search(line,"location"); i++; } begin_location=i+1; begin_location_pos++; ptr=strchr(line,a); while (!ptr) { if (script.eof()) { cout << ERR8; exit(-1); } script.getline(line,len,stop); ptr=strchr(line,a); i++; } end_location_pos=ptr-line+1; end_location=i+1; begin_look_at_pos=search(line,"look_at"); while (begin_look_at_pos>=strlen(line)) { if (script.eof()) { cout << ERR9; exit(-1); } script.getline(line,len,stop); begin_look_at_pos=search(line,"look_at"); i++; } begin_look_at=i+1; begin_look_at_pos++; ptr=strchr(line,a); while (!ptr) { if (script.eof()) { cout << ERR10; exit(-1); } script.getline(line,len,stop); ptr=strchr(line,a); i++; } end_look_at_pos=ptr-line+1; end_look_at=i+1; break; } i++; } script.close(); // okay, lets make the actual files char our_name[40]; for (i=0; i<40; i++) // blank out the array our_name[i]=NULL; if (strlen(override_file)==0) // did the user give us an override name { i=0; while (i<40 && script_file[i]!='.') { our_name[i]=script_file[i]; i++; } } else { i=0; while (i<40 && override_file[i]!='.') { our_name[i]=override_file[i]; i++; } } ofstream output; char numstr[6]; char numstr2[6]; char open_name[40]; int_to_str(numstr,num_frames); j=strlen(our_name)-1; while ((j>=0) && (our_name[j]!='\\')) j--; if (strlen(our_name)-j-1+strlen(numstr)>8) // check if we need to chop name { for (i=j+9-strlen(numstr); i<40; i++) our_name[i]=NULL; } int_to_str(numstr2,num_frames); // here is the loop that actually generates the output script files cout << "Generating frame #"; if (closed) // if smooth closed path, don't double up the first and last frames num_frames--; for (i=1; i<=num_frames; i++) { cout << i; int_to_str(numstr,i); strcpy(open_name,our_name); // copy our_name for (j=0; j"); output.write(insertion,strlen(insertion)); if (begin_location!=end_location) // if closure on different line { for (j=begin_location; jend_location_pos) output.put(ch); } for (j=end_location+1; j0) { strcat(insertion,static_look_at); strcat(insertion,">"); } else { if (i"); } output.write(insertion,strlen(insertion)); if (begin_look_at!=end_look_at) // if closure on different line { for (j=begin_look_at; jend_look_at_pos) output.put(ch); } while (!script.eof()) { script.getline(line,len,stop); output.write(line,strlen(line)); output.put('\n'); } script.close(); for (j=0; jmax_x) max_x=position[i].x; if (position[i].y>max_y) max_y=position[i].y; if (position[i].z>max_z) max_z=position[i].z; if (position[i].xmax_x) max_x=control_points[i].x; if (control_points[i].y>max_y) max_y=control_points[i].y; if (control_points[i].z>max_z) max_z=control_points[i].z; if (control_points[i].x0)) i--; j=0; while ((our_name[i]!='.') && (j<6) && (our_name[i]!=NULL)) { i++; j++; } our_name[i]='_'; i++; our_name[i]='3'; i++; our_name[i]='D'; i++; our_name[i]='.'; i++; our_name[i]='P'; i++; our_name[i]='O'; i++; our_name[i]='V'; i++; for (j=i; j<40; j++) our_name[j]=NULL; ifstream input; input.open(script_file,ios::nocreate); // open up example file if (input) { cout << "Creating test script file: " << our_name << "\n"; ofstream output; output.open(our_name); // open up output file int len=255; char stop='\n'; char line[256]; while (input.eof()==0) // copy the whole script file intact { input.getline(line,len,stop); output.write(line,strlen(line)); output.put('\n'); } input.close(); radius=0; for (i=0; i, "); gcvt(radius*0.9,15,t); strcat(insertion,t); output.write(insertion,strlen(insertion)); strcpy(insertion," pigment {color Red} }\n"); output.write(insertion,strlen(insertion)); } } else { cout << ERR5 << script_file << "\n"; // couldn't open script file exit(-1); } } void do_batch(char out_file[40], char example_file[40], char override_file[40], char script_file[40], int num_frames, int closed) { int current_frame, end_fname; int j, i=0,k; ifstream example; example.open(example_file,ios::nocreate); // open up example file if (example) { int len=1000; // hard code how big a batch file is available char stop=NULL; char data[1000]; example.get(data,len,stop); example.close(); // okay, lets make the out file char our_name[40]; for (i=0; i<40; i++) // blank out the array our_name[i]=NULL; if (strlen(override_file)==0) // did the user give us an override name { i=0; while (i<40 && script_file[i]!='.') { our_name[i]=script_file[i]; i++; } } else { i=0; while (i<40 && override_file[i]!='.') { our_name[i]=override_file[i]; i++; } } ofstream output; char numstr[6]; char numstr2[6]; char open_name[40]; int_to_str(numstr,num_frames); j=strlen(our_name)-1; while ((j>=0) && (our_name[j]!='\\')) j--; if (strlen(our_name)-j-1+strlen(numstr)>8) // check if we need to chop name { for (i=j+9-strlen(numstr); i<40; i++) our_name[i]=NULL; } int_to_str(numstr2,num_frames); output.open(out_file); // open up output file if (closed) // if smooth closed path, don't double up the first and last num_frames--; for (i=1; i<=num_frames; i++) { int_to_str(numstr,i); strcpy(open_name,our_name); // copy our_name for (j=0; j