From d6002ea387cf73a3957bdc3d1a66aabfb0d5f3a6 Mon Sep 17 00:00:00 2001 From: Nathan O Date: Mon, 21 Feb 2022 14:52:09 -0500 Subject: [PATCH] Allow specifying alternate config files - The program now takes a single, optional, command line argument: the path to the config file to read. If unspecified, it will continue to use the old config.txt. - Added dragon_curve.txt, a simpler example config. --- README.md | 19 +++++++++++-------- dragon_curve.txt | 15 +++++++++++++++ l_system_3d.c | 35 ++++++++++++++++++++++++++--------- l_system_3d.h | 1 + 4 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 dragon_curve.txt diff --git a/README.md b/README.md index fe69d4d..e3315f1 100644 --- a/README.md +++ b/README.md @@ -48,17 +48,20 @@ keypresses: Configuring the L-System ======================== -The system reads its configuration from the "config.txt" file. The file -must contain only ASCII characters. It starts with the L-system definition -(replacement rules). Following a line containing the keyword `actions`, the -file switches to defining the drawing actions the "turtle" takes when -encountering each character. (The `actions` line must occur exactly once in the -config.) +The system reads its configuration from the "config.txt" file by default. If +desired, you can pass a path to a different config as the program's first (and +only) command line argument. + +The config file must contain only ASCII characters. It starts with the L-system +definition (replacement rules). Following a line containing the keyword +`actions`, the file switches to defining the drawing actions the "turtle" takes +when encountering each character. (The `actions` line must occur exactly once +in the config.) If you want a longer example, the default "config.txt" contains instructions for drawing a multi-colored Sierpinski pyramid. A simpler, single, dragon-curve -example can be obtained by replacing the contents of "config.txt" with the -following lines: +example is also available in `dragon_curve.txt`. The contents of +`dragon_curve.txt` are copied here: ``` init F F F+G diff --git a/dragon_curve.txt b/dragon_curve.txt new file mode 100644 index 0000000..f6eeaba --- /dev/null +++ b/dragon_curve.txt @@ -0,0 +1,15 @@ +# Copied from https://en.wikipedia.org/wiki/L-system#Example_6:_Dragon_curve +init F +F F+G +G F-G + +actions +F +move_forward 1.0 +G +move_forward 1.0 +- +rotate -90.0 ++ +rotate 90.0 + diff --git a/l_system_3d.c b/l_system_3d.c index 366cc37..0bbddbd 100644 --- a/l_system_3d.c +++ b/l_system_3d.c @@ -34,6 +34,7 @@ static void FreeApplicationState(ApplicationState *s) { if (s->mesh) DestroyLSystemMesh(s->mesh); if (s->turtle) DestroyTurtle3D(s->turtle); if (s->config) DestroyLSystemConfig(s->config); + free(s->config_file_path); glDeleteBuffers(1, &(s->ubo)); if (s->window) glfwDestroyWindow(s->window); memset(s, 0, sizeof(*s)); @@ -203,20 +204,20 @@ static int DecreaseIterations(ApplicationState *s) { return 1; } -// Reloads the config file from ./config.txt. If this fails, then we'll just -// print a message and return. (The config can be faulty at runtime, but we -// won't start the program unless it's OK.) +// Reloads the config file. If this fails, then we'll just print a message and +// return. (The config can be faulty at runtime, but we won't start the program +// unless it's OK when starting.) static void ReloadConfig(ApplicationState *s) { LSystemConfig *new_config = NULL; LSystemConfig *old_config = s->config; - new_config = LoadLSystemConfig("./config.txt"); + new_config = LoadLSystemConfig(s->config_file_path); if (!new_config) { - printf("Failed loading new config file.\n"); + printf("Failed reloading the config file.\n"); return; } s->config = new_config; DestroyLSystemConfig(old_config); - printf("Config updated OK.\n"); + printf("Config %s updated OK.\n", s->config_file_path); } static void PrintMemoryUsage(ApplicationState *s) { @@ -341,6 +342,22 @@ int main(int argc, char **argv) { printf("Failed allocating application state.\n"); return 1; } + if (argc > 2) { + printf("Usage: %s [config file path]\n", argv[0]); + FreeApplicationState(s); + return 1; + } + if (argc == 2) { + s->config_file_path = strdup(argv[1]); + } else { + // Using strdup so that we can "free" it no matter what. + s->config_file_path = strdup("./config.txt"); + } + if (!s->config_file_path) { + printf("Failed copying config file path.\n"); + FreeApplicationState(s); + return 1; + } if (!SetupWindow(s)) { printf("Failed setting up window.\n"); FreeApplicationState(s); @@ -378,13 +395,13 @@ int main(int argc, char **argv) { to_return = 1; goto cleanup; } - s->config = LoadLSystemConfig("./config.txt"); + s->config = LoadLSystemConfig(s->config_file_path); if (!s->config) { - printf("Error parsing ./config.txt.\n"); + printf("Error parsing %s\n", s->config_file_path); to_return = 1; goto cleanup; } - printf("Config loaded OK!\n"); + printf("Config %s loaded OK!\n", s->config_file_path); s->l_system_string = (uint8_t *) strdup(s->config->init); if (!s->l_system_string) { printf("Error initializing L-system string.\n"); diff --git a/l_system_3d.h b/l_system_3d.h index bde7c20..f714afe 100644 --- a/l_system_3d.h +++ b/l_system_3d.h @@ -22,6 +22,7 @@ typedef struct { float aspect_ratio; double frame_start; double frame_duration; + char *config_file_path; LSystemMesh *mesh; LSystemConfig *config; Turtle3D *turtle;