#define PROG_NAME "CameraPath" #define PROG_DESC "???" #define PROG_VERS "1.0" #define CameraPath_C_COPYRIGHT \ "" #define PROG_INFO \ "" \ " " /* Generates equally spaced sample points along a closed path around the origin Writes the sample points as camera positions in the format expected by the "Wire4"-Interactive 4D Wireframe Display Program (".w4"). Also writes a plain text file with one point per line (preceded by its integer ID). Implemented by stolfi 16-10-2000 */ #include #include #define _GNU_SOURCE #include #include //#include TYPE double Row3I = ARRAY [0..2] OF INTEGER; double double = double; typedef struct Options_t { char *outFile; /* Output file name prefix */ double dist; /* Nominal distance from origin */ bool_t normalize; /* If TRUE, normalize From-To vectors to length "dist". */ uint renderPoints; /* Subsampling ratio for camera positions.*/ wire4Points: uint; /* Number of nodes on path for Wire4 plotting. */ To4: r4_t; /* Look at point */ Up4: r4_t; /* Head-up point */ Over4: r4_t; /* Hyperhead-up point */ } <* FATAL Wr.Failure, Thread.Alerted, OSError.E); void WriteColor(FILE *wr, *c: Row3I) /* Write colors in RGB mode */ { Mis.WriteInt(wr,c[0]); fprintf(wr," "); Mis.WriteInt(wr,c[1]); fprintf(wr," "); Mis.WriteInt(wr,c[2]); } /* END WriteColor */ Options_t *GetOptions(int argc, char **argv); int main(int argc, char **argv) { Options_t *o = GetOptions(argc, argv); char *topo_cmt = jsprintf("Created by %s on %s", PROG_NAME, Today()); /* Random_t coins = MakeRandomSource(4615); */ ??? cmt = "Made by CameraPath on " & Today() & "\n"; ??? w4 = FileWr.Open(o->outFile & ".w4"); ??? txt = FileWr.Open(o->outFile & ".from4"); { WriteComments(w4,o,cmt); WriteComments(txt,o,cmt); WriteWire4Header(w4, 3.0*o->dist); SamplePath(o,w4,txt); fclose(w4); fclose(txt); return 0; } void WriteComments ( FILE *wr, <*UNUSED);*o: Options_t; char *cmt; ) { filefmt_write_comment(wr,cmt,'#'); fprintf(wr, "\n"); } /* END WriteComments */ void WriteWire4Header(FILE *wr, dist: double) { fprintf(wr, "DegreeRing@{Edge->?}s"); fprintf(wr," 0"); fprintf(wr,"\nDepthCueLevels 10"); fprintf(wr,"\nFogDensity 0.5"); fprintf(wr,"\n"); fprintf(wr, "\nFrom4: " & Fmt.LongReal(dist) & " 00 00 00"); fprintf(wr, "\nTo4 : 00 00 00 00"); fprintf(wr, "\nUp4 : 00 00 +1 00"); fprintf(wr, "\nOver4: 00 00 00 +1"); fprintf(wr, "\nVangle4: 30"); fprintf(wr, "\n"); fprintf(wr, "\nFrom3: " & Fmt.LongReal(dist) & " 00 00"); fprintf(wr, "\nTo3 : 00 00 00"); fprintf(wr, "\nUp3 : 00 00 +1"); fprintf(wr, "\nVangle3: 30"); fprintf(wr, "\n"); } /* END WriteWire4Header */ PROCEDURE SamplePath(*o: Options_t; w4: Wr.T; txt: Wr.T) Row3I vcolor = Row3I{100,100,100}; ecolor : Row3I = Row3I{0,255,255}; vradius : REAL = 1.0; eradius : REAL = 1.0; CONST TwoPi == 6.28318530717958648; { r4_t EvalPath(t: double) { ??? r1 = 1.0; with ( t1 == t, c1 == cos(t1), s1 == sin(t1), double r2 = 0.7, t2 == 2.0*t + 1.0, c2 == cos(t2), s2 == sin(t2); double p = (r4_t){ r1*c1, r1*s1, r2*c2, r2*s2 } ){ if (o->normalize) { return r4_Scale(o->dist, r4_Dir(p)); } else { return r4_Scale(o->dist, p); } } } EvalPath; PROCEDURE ComputeSampleTimes(nSteps: uint): REF double_vec_t == /* Returns array "t[0..nSteps]" with "nSteps+1" equally spaced times in "[0..TwoPi]", including "t[0] == 0" and "t[nSteps] == TwoPi". */ r4_t pAnt; VAR { ??? fns = ((double)nSteps); ??? rt = double_vec_new(nSteps + 1); with (t == rt^ DO pAnt = EvalPath(0.0); t[0] = 0.0; for (i = 1; i <= (nSteps); i++) { ??? fi = FLOAT(i,double), ti == TwoPi*fi/fns; { t[i] = ti;} } return rt; } } ComputeSampleTimes; PROCEDURE ComputePathLengths( *t: double_vec_t; ): REF double_vec_t == /* Computes "s[i]" == path length from "t==0" to each "t[i]" */ double *sAnt; pAnt: r4_t; { ??? nt = (t.nel); ??? rs = double_vec_new(nt); with (s == rs^ DO pAnt = EvalPath(0.0); sAnt = 0.0; for (i = 0; i < nt; i++) { ??? pi = EvalPath(t[i]); { sAnt = sAnt + r4_Dist(pAnt, pi); s[i] = sAnt; pAnt = pi } } return rs; } } ComputePathLengths; r4_vec_t *ComputeEquallySpacedPoints( *t: double_vec_t;/*Times of some sample points along curve */ *s: double_vec_t;/*Lengths to those sample points along curve */ uint np; )== /* Divides the interval "t[0]..t[(t.nel-1)]" into np equal intervals and returns an array with the beginning of each interval. */ uint *iCur; tGoal: double; { ??? nt = (t.nel); ??? rp = r4_vec_new(np); with (p == rp^, double sIni = s[0], sFin == s[(s.nel-1)], ds == sFin - sIni ){ assert(nt == (s.nel)); iCur = 0; for (k = 0; k < np; k++) { ??? sGoal = sIni + ds * ((double)k)/((double)np); { while (iCur < nt - 1) && (s[iCur+1] < sGoal){ iCur++; } if (iCur >= nt-1) { tGoal = t[nt-1] } else { ??? ds = s[iCur+1] - s[iCur], dt == t[iCur+1] - t[iCur]; { tGoal = t[iCur] + dt * (sGoal - s[iCur])/ds } } p[k] = EvalPath(tGoal); } } return rp; } } ComputeEquallySpacedPoints; void WriteCoord(FILE *wr, x: double) { fprintf(wr, Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec = 4), 7)); } WriteCoord; void WritePoint4DForWire4( *c: r4_t; vcolor: Row3I; REAL vradius; ) { WriteCoord(w4,c[0]); fprintf(w4, " "); WriteCoord(w4,c[1]); fprintf(w4, " "); WriteCoord(w4,c[2]); fprintf(w4, " "); WriteCoord(w4,c[3]); fprintf(w4, " : "); WriteColor(w4, vcolor); fprintf(w4, " : "); Mis.WriteRadius(w4, vradius); fprintf(w4, "\n"); } WritePoint4DForWire4; void WritePoint4DAsText(*c: r4_t; uint i) { fprintf(txt, " " & Fmt.Int(i) & " "); WriteCoord(txt,c[0]); fprintf(txt, " "); WriteCoord(txt,c[1]); fprintf(txt, " "); WriteCoord(txt,c[2]); fprintf(txt, " "); WriteCoord(txt,c[3]); fprintf(txt, "\n"); } WritePoint4DAsText; { ??? nr = o->renderPoints; ??? nw = o->wire4Points; ??? ns = 50*MAX(nr; with ( nw), double t = ComputeSampleTimes(ns)^; double s = ComputePathLengths(t)^ ){ /* Camera positions for rendering */ ??? pr = ComputeEquallySpacedPoints(t, s, nr)^; { for (k = 0 TO (pr.nel-1)) { WritePoint4DAsText(pr[k],k); } }; /* Camera positions for wire4 */ fprintf(w4, "\n\nNodeList : "); fprintf(w4, Fmt.Int(nw+5) & "\n"); ??? pw = ComputeEquallySpacedPoints(t, s, nw)^; { for (k = 0 TO (pw.nel-1)) { WritePoint4DForWire4(pw[k],vcolor,vradius); } } /* reference axis nodes */ fprintf(w4, " 0 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 1 0 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 1 0 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 1 0 : 255 255 255 : 0\n"); fprintf(w4, " 0 0 0 1 : 255 255 255 : 0\n"); fprintf(w4, "\n"); fprintf(w4, "\n@{Edge->?}List " & Fmt.Int(nw+4) & ":\n"); for (i = 0; i < nw; i++) { fprintf(w4, Fmt.Pad(Fmt.Int(i), 4) & " " \ Fmt.Pad(Fmt.Int((i+1) % nw),4)); fprintf(w4, " : "); /* color */ WriteColor(w4, ecolor); fprintf(w4, " : "); Mis.WriteRadius(w4, eradius); fprintf(w4, "\n"); } /* reference axis @{edge->?}s */ fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+1)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+2)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+3)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, " " & Fmt.Int(nw) & " " & Fmt.Int(nw+4)); fprintf(w4, " : 125 125 125 : 1\n"); fprintf(w4, "\nWallList 0\n"); fclose(w4); } } } /* END SamplePath */ Options_t *GetOptions(int argc, char **argv) Options_t *o = (Options_t *)malloc(sizeof(Options_t)); { argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); argparser_get_keyword(pp, "-outFile"); o->outFile = argparser_get_next(pp); argparser_get_keyword(pp, "-dist"); o->dist = pp.getNextLongReal(1.0d-10,1.0d+10); o->normalize = argparser_keyword_present(pp, "-normalize"); if ((argparser_keyword_present(pp, "-renderPoints"))) { o->renderPoints = argparser_get_next_int(pp, 1,10000); } else { o->renderPoints = 10; } if ((argparser_keyword_present(pp, "-wire4Points"))) { o->wire4Points = argparser_get_next_int(pp, 1,10000); } else { o->wire4Points = 10; } argparser_finish(pp); ----------------------------------- #define _HELP \ fprintf(stderr, "Usage: CameraPath \\\n" \ " -outFile \\\n" \ " -dist [ -normalize ] \\\n" \ " [ -renderPoints ] \\\n" \ " [ -wire4Points ]\n"); END¦ } } return o; } /* END GetOptions */ /* end CameraPath */