#include #include #include #include #include char filename[80]; char vuename[80]; char tplname[80]; char outname[80]; int fstart; int fend; int fstep; void process_args (int argc, char *argv[]); void read_vue (char *fname, int *start, int *end); void add_ext (char *fname, char *ext, int force); void abortmsg (char *msg, int exit_code); char *after (char *str, char *target); char lookahead (FILE *f); char upcase (char ch); int main (int argc, char *argv[]) { FILE *tpl, *out; char fstring[] = "%03d"; char ch; int frame, digits, i; /* Handle the command line args */ process_args (argc, argv); /* Get the start/end frame numbers from the .vue file */ read_vue (vuename, &fstart, &fend); if (fstart > fend) abortmsg ("No frames generated.", 1); digits = (fend < 1) ? 1 : (floor(log10(fend)) + 1); out = fopen (outname, "w"); if (out == NULL) { printf ("Unable to open output file '%s'", outname); exit(1); } printf ("Output to: %s\n", outname); for (frame = fstart; frame <= fend; frame = frame + fstep) { tpl = fopen (tplname, "r"); if (tpl == NULL) { printf ("Unable to open template file '%s'\n", tplname); exit(1); } while (1) { ch = getc (tpl); if (feof(tpl)) break; if (ch == '$') { if (lookahead(tpl) == '#' && (strlen(filename) + digits > 8)) { for (i = 0; i < 8 - digits; i++) putc (filename[i], out); } else fprintf (out, "%s", filename); } else if (ch == '#') { fstring[2] = '0' + digits; fprintf (out, fstring, frame); } else putc (ch, out); } fclose (tpl); } fclose (out); return 0; } void process_args (int argc, char *argv[]) { int i; printf("\n\n3DS2POV Animation Utility\n"); printf ("\n"); if (argc < 2) { printf ("Usage: 3dsani inputfile [options]\n\n"); printf ("Options: -a - Specifies name of the 3ds animation (.vue) file\n"); printf (" -t - Specifies name of the template (.tpl) file\n"); printf (" -o - Specifies name of the output (.bat) file\n"); printf (" -snnn - Start animation at frame nnn\n"); printf (" -ennn - End animation at frame nnn\n"); printf (" -pnnn - Render every nnn'th frane\n"); printf ("\nex. 3dsani ruby -aruby.vue -tani.tpl -oruby.bat -s0 -e10\n\n"); exit(1); } strcpy (filename, ""); strcpy (vuename, ""); strcpy (tplname, ""); strcpy (outname, ""); fstart = -1; fend = -1; fstep = 1; for (i = 1; i < argc; i++) { if (argv[i][0] == '-' || argv[i][0] == '/') { switch (upcase(argv[i][1])) { case 'A': strcpy (vuename, &argv[i][2]); break; case 'T': strcpy (tplname, &argv[i][2]); break; case 'O': strcpy (outname, &argv[i][2]); break; case 'S': if (argv[i][2] != '\0') fstart = atoi (&argv[i][2]); break; case 'E': if (argv[i][2] != '\0') fend = atoi (&argv[i][2]); break; case 'P': if (argv[i][2] != '\0') { fstep = atoi (&argv[i][2]); if (fstep < 1) fstep = 1; } break; default : printf ("\nInvalid option -%c\n", argv[i][1]); exit (1); } } else if (strlen (filename) == 0) { strcpy (filename, argv[i]); add_ext (filename, "", 1); } else abortmsg ("Too many file names specified.", 1); } if (strlen (filename) == 0) abortmsg ("No file name specified", 1); if (strlen(vuename) == 0) { strcpy (vuename, filename); add_ext (vuename, "vue", 1); } if (strlen (tplname) == 0) { strcpy (tplname, filename); add_ext (tplname, "tpl", 1); } if (strlen (outname) == 0) { strcpy (outname, filename); add_ext (outname, "bat", 1); } add_ext (vuename, "vue", 0); add_ext (tplname, "tpl", 0); add_ext (outname, "bat", 0); } /* Read the start/end frame numbers from the .vue file */ void read_vue (char *fname, int *start, int *end) { FILE *f; char string[256]; int fmin, fmax, frame; f = fopen (fname, "r"); if (f != NULL) { fmin = +MAXINT; fmax = -MAXINT; while (fgets (string, 256, f) != NULL) { if (strstr (string, "frame") == string) { frame = atoi (after (string, "frame")); if (frame < fmin) fmin = frame; if (frame > fmax) fmax = frame; } } if (*start < 0 && fmin != +MAXINT) *start = fmin; if (*end < 0 && fmax != -MAXINT) *end = fmax; fclose(f); } if (*start < 0) abortmsg ("No start frame specified", 1); if (*end < 0) abortmsg ("No end frame specified", 1); printf ("Generating frames %d through %d", *start, *end); if (fstep > 1) printf (" (every %d frames)", fstep); printf ("\n"); } void add_ext (char *fname, char *ext, int force) { int i; for (i = 0; i < strlen(fname); i++) if (fname[i] == '.') break; if (fname[i] == '\0' || force) { if (strlen(ext) > 0) fname[i++] = '.'; strcpy (&fname[i], ext); } } void abortmsg (char *msg, int exit_code) { printf ("\n%s\n", msg); exit (exit_code); } char *after (char *str, char *target) { static char result[256]; char *search; search = strstr (str, target); if (search == NULL) strncpy (result, "", 256); else strncpy (result, search + strlen(target), 256); result[255] = '\0'; return result; } /* Peek at the next character in the file */ char lookahead (FILE *f) { char ch; ch = getc (f); ungetc (ch, f); return ch; } char upcase (char c) { if (c >= 'a' && c <= 'z') c = c - 'a' + 'A'; return c; }