Skip to content

Commit

Permalink
Parse L-system config files
Browse files Browse the repository at this point in the history
 - Added support for parsing config files, and an example config. The
   config isn't used for anything yet. (That's coming next.)

 - Otherwise, this should behave as normal.
  • Loading branch information
Nathan O authored and Nathan O committed Feb 11, 2022
1 parent b7e2489 commit 42eda63
Show file tree
Hide file tree
Showing 10 changed files with 654 additions and 18 deletions.
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ l_system_mesh.o: l_system_mesh.c l_system_mesh.h utilities.h
turtle_3d.o: turtle_3d.c turtle_3d.h
gcc $(CFLAGS) -c -o turtle_3d.o turtle_3d.c -I cglm/include

l_system_3d: l_system_3d.c l_system_mesh.o turtle_3d.o utilities.o
parse_config.o: parse_config.c parse_config.h turtle_3d.h
gcc $(CFLAGS) -c -o parse_config.o parse_config.c

l_system_3d: l_system_3d.c l_system_mesh.o turtle_3d.o utilities.o \
parse_config.o
gcc $(CFLAGS) -o l_system_3d l_system_3d.c \
glad/src/glad.c \
utilities.o \
l_system_mesh.o \
turtle_3d.o \
parse_config.o \
-I glad/include \
-I cglm/include \
$(GLFW_CFLAGS)
Expand Down
113 changes: 113 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,116 @@

I will write a README when the project is done.

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.)

If you want a longer example, the default "config.txt" contains instructions
for drawing the dragon curve, and is shown below:
```
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
```

Any lines starting with `#` in the config file are ignored. So, in addition to
L-system characters being limited to ASCII, non-printing, whitespace
characters, and the `#` character are not allowed in replacement rules. Note
that the `#` must be the first non-whitespace character in the line.

Replacement Rules
-----------------

The first part of the config defines the replacement rules. This section of
the file ends when the line containing the word `actions` is encountered.
Exactly one line in this part of the file must give the initial contents of the
L-system string:

- `init <initial text>`

All other non-blank and non-comment lines in this section take the following
format:

- `<character> <string of replacement characters>`

The character is separated from the string of replacements by one or more tab
or space characters.

Characters with no defined replacement rules are left as-is during L-system
iteration. Any line containing a character with no following replacement text
indicates that the character is to be deleted when encountered (i.e. replaced
with a blank string).

Each character can have at most one replacement rule.

Action Rules
------------

Following the `actions` line, the config switches to defining what each
character means for drawing the graphics. Actions for a character are defined
as follows:

```
<character>
<action 1>
<action 2>
...
<action n>
```

In other words, the character must first appear on a line by itself. The
following lines must contain the arbitrary number of actions to be taken when
the character is processed. The list of actions ends when either the end of the
file is reached or another line containing a single character is reached. (Note
that none of the actions are a single character long, so there is no ambiguity
between lines containing a single character and lines containing an action.)

Each character is allowed at most one associated sequence of actions. Any
character that does not appear in the actions section prompts no drawing
actions when rendering the L-system. (This can also be achieved by including
a character in the actions section, but not specifying any actions after it.)

Available Actions
-----------------

The following list of actions are supported:

- `move_forward <distance>`: Moves the turtle forward, drawing a line, the
given distance. The distance is a floating-point number of units. Units are
not particularly relevant, because the resulting 3D rendering will be scaled
to fit in the viewport regardless.

- `rotate <degrees>`: Rotates the turtle to its left by the given
floating-point number of degrees.

- `yaw <degrees>`: The same as the `rotate` action.

- `pitch <degrees>`: Rotates the turtle in the upwards direction by the given
floating-point number of degrees.

- `roll <degrees>`: Rotates the turtle by the given number of degrees about
its forward-facing axis.

- `move_forward_nodraw <distance>`: Like `move_forward`, but does not draw a
line segment.

Prior to taking any actions, the turtle is initialized at position (0, 0, 0),
facing in the positive-X direction, with its pitch and roll set so that its
"back" is facing upwards; in the positive-Y direction.

1 change: 1 addition & 0 deletions build_windows.bat
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ gcc -Wall -Werror -O3 -o l_system_3d ^
l_system_3d.c ^
l_system_mesh.c ^
turtle_3d.c ^
parse_config.c ^
utilities.c ^
glad\src\glad.c ^
-I cglm\include ^
Expand Down
20 changes: 20 additions & 0 deletions config.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Draw a dragon curve.
init F
F F+G
G F-G

actions

F
move_forward 1.0

G
move_forward 1.0

-
rotate -90.0

+
# Comments can go anywhere, so long as the '#' is at the start of the line.
rotate 90.0

20 changes: 17 additions & 3 deletions l_system_3d.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "l_system_mesh.h"
#include "parse_config.h"
#include "turtle_3d.h"
#include "utilities.h"
#include "l_system_3d.h"

#define DEFAULT_WINDOW_WIDTH (800)
#define DEFAULT_WINDOW_HEIGHT (600)
#define PI (3.1415926536)

ApplicationState* AllocateApplicationState(void) {
ApplicationState *to_return = NULL;
Expand All @@ -29,6 +29,7 @@ void FreeApplicationState(ApplicationState *s) {
if (!s) return;
if (s->mesh) DestroyLSystemMesh(s->mesh);
if (s->turtle) DestroyTurtle3D(s->turtle);
if (s->config) DestroyLSystemConfig(s->config);
glDeleteBuffers(1, &(s->ubo));
if (s->window) glfwDestroyWindow(s->window);
memset(s, 0, sizeof(*s));
Expand Down Expand Up @@ -85,7 +86,7 @@ static int SetupUniformBuffer(ApplicationState *s) {
}

static int Rotate90(Turtle3D *t) {
return RotateTurtle(t, PI * 0.5);
return RotateTurtle(t, 90);
}

// This generates the vertices for the L-system, and updates the mesh. Returns
Expand All @@ -108,7 +109,7 @@ static int GenerateVertices(ApplicationState *s) {
t->color[0] = 1;
t->color[1] = 1;
if (!MoveTurtleForward(t, 1.0)) return 0;
if (!PitchTurtle(t, PI * 0.5)) return 0;
if (!PitchTurtle(t, 90)) return 0;
t->color[0] = 0.7;
t->color[1] = 0.1;
if (!MoveTurtleForward(t, 0.5)) return 0;
Expand Down Expand Up @@ -219,6 +220,19 @@ int main(int argc, char **argv) {
to_return = 1;
goto cleanup;
}
s->config = LoadLSystemConfig("./config.txt");
if (!s->config) {
printf("Error parsing ./config.txt.\n");
to_return = 1;
goto cleanup;
}
printf("Config loaded OK!\n");
// TODO: Create the actual L-system
// - Parse the config file
// - If the config file is faulty, then display some basic test model, to
// avoid closing the program if someone mistakenly reloads a bad config.
// - Iterate the string. Create an LSystem type, probably.
// - Make the turtle follow the rules.
if (!GenerateVertices(s)) {
printf("Failed generating vertices.\n");
to_return = 1;
Expand Down
2 changes: 2 additions & 0 deletions l_system_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <cglm/cglm.h>
#include <glad/glad.h>
#include "l_system_mesh.h"
#include "parse_config.h"
#include "turtle_3d.h"

// Uniforms shared with all shaders. Must match the layout in
Expand All @@ -19,6 +20,7 @@ typedef struct {
int window_height;
float aspect_ratio;
LSystemMesh *mesh;
LSystemConfig *config;
Turtle3D *turtle;
GLuint ubo;
SharedUniforms shared_uniforms;
Expand Down
Loading

0 comments on commit 42eda63

Please sign in to comment.