-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtree.cpp
152 lines (126 loc) · 4.26 KB
/
tree.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/** @file */
#include "turtle.h"
#include <unistd.h>
#define WIDTH 800
#define HEIGHT 800
/// animate the drawing of each branch
const bool animate = false;
string generatedString;
/// Draw pattern given the generated l system string and other graphics parameters
/// Parameters: string sentence : Generated l system string
/// int turnAngle : Interpret + and - with this angle
/// GLFWwindow * window: Pointer to window (for animation)
void drawPattern(string sentence, int turnAngle, int season, GLFWwindow* window)
{
Turtle turtle;
float angle = (PI / 180) * turnAngle;
turtle.translate(WIDTH/2, 0);
int draw_num = 0;
int trunk = 1; // To keep track when to stop tapering and start branch contraction
for (int i = 0; i < sentence.length(); i++) {
char current = sentence[i];
if (current == 'F') {
turtle.draw();
if (draw_num++ % 5 == 0 && trunk) {
turtle.setThickness(-1); // -1 corresponds to taper
}
} else if (current == '+') {
turtle.rotate(-angle);
} else if (current == '-') {
turtle.rotate(angle);
} else if (current == '[') {
if (animate) {
glfwSwapBuffers(window);
usleep(0.001 * 1e6);
}
turtle.saveState();
turtle.setThickness(0); // 0 corresponds to branch contraction
} else if (current == ']') {
turtle.restoreState();
turtle.setThickness(0); // 0 corresponds to branch contraction
} else if (current == 'X' && sentence[i + 1] != '[') {
trunk = 0; // Stop tapering
turtle.drawLeaf(season);
}
}
}
/// Given an axiom, use defined production rules to recursively generate a string.
/// Stores generated string in global variable `generatedString`
/// Implementation of an l system using context-free grammar.
/// Parameters:
/// string sentence : String generated until preveious recursive step (initially the axiom)
/// int depth : Depth of recursion for generating string
void generateString(string sentence, int depth)
{
if(depth == 0) {
generatedString = sentence;
return;
}
string nextSentence;
for (int i = 0; i < sentence.length(); i++) {
if (sentence[i] == 'X') {
// nextSentence += "F-[[X]+X]+F[-FX]+X";
int choice = rand() % 4;
if (choice == 0)
nextSentence += "F-[[X]+X]+F[[X]+X]-X";
else if (choice == 1)
nextSentence += "F-[[X]+X]+F[-FX]+X";
else if (choice == 2)
nextSentence += "F[+X][-X]FX";
else if (choice == 3)
nextSentence += "F[+X]F[-X]+X";
continue;
}
if (sentence[i] == 'F') {
nextSentence += "FF";
continue;
}
nextSentence += sentence[i];
}
generateString(nextSentence, depth - 1);
}
int main()
{
const int generations = 7;
srand(time(NULL));
// OpenGL initialisation code
if(glfwInit() == false) {
fprintf(stderr, "Error initializing GLFW\n");
return -1;
}
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "IS F311 Computer Graphics Project", NULL, NULL);
if(!window) {
glfwTerminate();
fprintf(stderr, "Error while creating a window\n");
return -1;
}
glfwMakeContextCurrent(window);
glViewport(0.0f, 0.0f, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WIDTH, 0, HEIGHT, 0, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
string sentence = "X";
int depth = 1;
Turtle turtle;
int turnAngle = 15 + rand() % 20;
int season = 0;
// Render loop for the OpenGL window. The scene is redrawn on every refresh.
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT);
if (depth < generations) {
generateString(sentence, depth++);
}
season = (season + 1) % 3;
drawPattern(generatedString, turnAngle, season, window);
glfwSwapBuffers(window);
glfwPollEvents();
// usleep(0.25 * 1e6);
sleep(1);
}
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}