Skip to content

Commit

Permalink
Add push/pop color options
Browse files Browse the repository at this point in the history
 - Added instructions for pushing and popping the turtle's current
   color.
  • Loading branch information
yalue committed Feb 18, 2022
1 parent 8cd5397 commit 2035262
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ The following list of actions are supported:
It is an error to encounter this instruction if the stack is already empty.
Once again, the "0.0" argument is ignored, but required in the config.

- `push_color 0.0`: Analogous to `push_position`, but saves the turtle's
current color on a stack.

- `pop_color 0.0`: Analogous to `pop_position`, but restores the last color
pushed by `push_color`.

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.
Expand Down
4 changes: 4 additions & 0 deletions parse_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ static int ParseActionRules(LSystemConfig *config) {
"set_color_a",
"push_position",
"pop_position",
"push_color",
"pop_color",
};
TurtleInstruction action_fns[] = {
MoveTurtleForward,
Expand All @@ -307,6 +309,8 @@ static int ParseActionRules(LSystemConfig *config) {
SetTurtleAlpha,
PushTurtlePosition,
PopTurtlePosition,
PushTurtleColor,
PopTurtleColor,
};
char *current_line = NULL;
uint8_t current_char = 0;
Expand Down
67 changes: 67 additions & 0 deletions turtle_3d.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ static void FreePositionStack(PositionStack *s) {
memset(s, 0, sizeof(*s));
}

static int InitializeColorStack(ColorStack *s) {
s->size = 0;
s->buffer = (float *) calloc(INITIAL_STACK_CAPACITY, 4 * sizeof(float));
if (!s->buffer) return 0;
s->capacity = INITIAL_STACK_CAPACITY;
return 1;
}

static void FreeColorStack(ColorStack *s) {
free(s->buffer);
memset(s, 0, sizeof(*s));
}

Turtle3D* CreateTurtle3D(void) {
Turtle3D *to_return = NULL;
to_return = (Turtle3D *) calloc(1, sizeof(*to_return));
Expand All @@ -55,6 +68,13 @@ Turtle3D* CreateTurtle3D(void) {
free(to_return);
return NULL;
}
if (!InitializeColorStack(&(to_return->color_stack))) {
printf("Failed initializing stack of turtle colors.\n");
free(to_return->vertices);
free(to_return->position_stack.buffer);
free(to_return);
return NULL;
}
to_return->vertex_capacity = INITIAL_TURTLE_CAPACITY;
ResetTurtle3D(to_return);
return to_return;
Expand All @@ -80,12 +100,14 @@ void ResetTurtle3D(Turtle3D *t) {
t->vertex_count = 0;
// Clear the stack. As with the vertex array, don't free it, though.
t->position_stack.size = 0;
t->color_stack.size = 0;
}

void DestroyTurtle3D(Turtle3D *t) {
if (!t) return;
free(t->vertices);
FreePositionStack(&(t->position_stack));
FreeColorStack(&(t->color_stack));
memset(t, 0, sizeof(*t));
free(t);
}
Expand Down Expand Up @@ -309,3 +331,48 @@ int PopTurtlePosition(Turtle3D *t, float ignored) {
s->size--;
return 1;
}

int PushTurtleColor(Turtle3D *t, float ignored) {
ColorStack *s = &(t->color_stack);
float *new_buf = NULL;
float *v = NULL;
uint32_t new_cap = 0;
if (s->size >= s->capacity) {
new_cap = s->capacity * 2;
if (new_cap < s->capacity) {
printf("Turtle color stack overflow.\n");
return 0;
}
new_buf = (float *) realloc(s->buffer, new_cap * 4 * sizeof(float));
if (!new_buf) {
printf("Failed expanding color stack.\n");
return 0;
}
s->buffer = new_buf;
s->capacity = new_cap;
}
v = s->buffer + (4 * s->size);
v[0] = t->color[0];
v[1] = t->color[1];
v[2] = t->color[2];
v[3] = t->color[3];
s->size++;
return 1;
}

int PopTurtleColor(Turtle3D *t, float ignored) {
ColorStack *s = &(t->color_stack);
float *v = NULL;
if (s->size == 0) {
printf("Turtle color stack is empty.\n");
return 0;
}
s->size--;
v = s->buffer + (4 * s->size);
t->color[0] = v[0];
t->color[1] = v[1];
t->color[2] = v[2];
t->color[3] = v[3];
return 1;
}

14 changes: 14 additions & 0 deletions turtle_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ typedef struct {
TurtlePosition *buffer;
} PositionStack;

// Holds a stack of turtle colors.
typedef struct {
uint32_t size;
uint32_t capacity;
// A buffer of (capacity * 4) floats
float *buffer;
} ColorStack;

// Holds the state of a 3D "turtle" that follows instructions relative to
// itself in 3D space.
typedef struct {
Expand All @@ -52,6 +60,7 @@ typedef struct {
uint32_t vertex_count;
uint32_t vertex_capacity;
PositionStack position_stack;
ColorStack color_stack;
} Turtle3D;

// Allocates a new turtle, at position 0, 0, 0, with no vertices. Returns NULL
Expand Down Expand Up @@ -111,5 +120,10 @@ int PushTurtlePosition(Turtle3D *t, float ignored);
// argument is ignored.
int PopTurtlePosition(Turtle3D *t, float ignored);

// Basically the same as PushTurtlePosition/PopTurtlePosition, but saves and
// restores the turtle's current color.
int PushTurtleColor(Turtle3D *t, float ignored);
int PopTurtleColor(Turtle3D *t, float ignored);

#endif // TURTLE_3D_H

0 comments on commit 2035262

Please sign in to comment.