procedural generator for the steam tunnels part
[dosdemo] / tools / procgen / steamtun.cc
1 //#define BASE_STR
2 #define BASE_LEFTJ
3 //#define RIGHT_STR1
4 #define RIGHT_STR2
5 //#define LEFT_STR1
6 //#define LEFT_STR2
7 //#define LEFT_STR3
8 //#define LEFT_STR4
9
10 #define CON_RAD(r)      ((r) * 1.4)
11 #define CON_WIDTH       0.04
12
13 static Object *gen_base_straight();
14 static Object *gen_base_left_junction();
15 static Object *gen_base_right_junction();
16 static Object *gen_pipeworks();
17 static Object *gen_pipe(float x, float y, float rad);
18 static Object *gen_pipe_inwall(float x, float y, float rad);
19 static Object *gen_pipe_s(float x, float y0, float y1, float rad);
20
21 static Mat4 xform;
22
23 #define add_object(o) \
24         do { \
25                 Object *tmp = o; \
26                 if(head) { \
27                         tail->next = tmp; \
28                         tail = tmp; \
29                 } else { \
30                         head = tail = tmp; \
31                 } \
32                 while(tail->next) tail = tail->next; \
33         } while(0)
34
35 extern "C" Object *generate()
36 {
37         Object *head = 0, *tail = 0;
38
39 #ifdef BASE_STR
40         add_object(gen_base_straight());
41 #endif
42 #ifdef BASE_LEFTJ
43         add_object(gen_base_left_junction());
44 #endif
45         add_object(gen_pipeworks());
46         return head;
47 }
48
49 static Object *gen_base_straight()
50 {
51         Object *owalls = new Object;
52         owalls->mesh = new Mesh;
53         gen_box(owalls->mesh, -1, -2, -1, 1, 2);
54
55         xform.rotation_x(deg_to_rad(90));
56         owalls->mesh->apply_xform(xform);
57
58         owalls->mesh->remove_faces(16, 23);
59
60         xform.translation(0, 0.5, 0);
61         owalls->mesh->apply_xform(xform);
62
63         return owalls;
64 }
65
66 static Object *gen_base_left_junction()
67 {
68         Mesh tmp;
69
70         Object *obj = new Object;
71         obj->mesh = new Mesh;
72
73         gen_box(obj->mesh, -1, -2, -1, 1, 3);
74
75         xform.rotation_x(deg_to_rad(90));
76         xform.translate(0, 0.5, 0);
77         obj->mesh->apply_xform(xform);
78
79         obj->mesh->remove_faces(24, 35);
80         obj->mesh->remove_faces(6, 11);
81
82         for(int i=0; i<2; i++) {
83                 float sign = i == 0 ? 1.0f : -1.0f;
84                 gen_plane(&tmp, 0.5, 1, 1, 1);
85                 xform.rotation_y(deg_to_rad(90));
86                 xform.translate(-0.5, 0.5, sign * 0.75);
87                 tmp.apply_xform(xform);
88                 obj->mesh->append(tmp);
89         }
90
91         gen_box(&tmp, -1, -0.5, -1, 1, 1);
92         xform.rotation_z(deg_to_rad(90));
93         xform.translate(-0.75, 0.5, 0);
94         tmp.apply_xform(xform);
95
96         tmp.remove_faces(8, 11);
97
98         obj->mesh->append(tmp);
99
100         return obj;
101 }
102
103 static Object *gen_pipeworks()
104 {
105         Object *head = 0, *tail = 0;
106
107         float start_y = CON_RAD(0.08) + 0.01;
108
109 #if defined(RIGHT_STR1) || defined(RIGHT_STR2)
110         add_object(gen_pipe(0.5 - 0.08, start_y, 0.08));
111 #endif
112         start_y += (CON_RAD(0.08) + CON_RAD(0.05)) * 0.9;
113
114         for(int i=0; i<3; i++) {
115                 float x = 0.5 - CON_RAD(0.05);
116                 float y = start_y + i * (CON_RAD(0.05) * 1.8);
117
118 #ifdef RIGHT_STR2
119                 if(i == 1) {
120                         add_object(gen_pipe_inwall(x, y, 0.05));
121                 } else {
122                         add_object(gen_pipe(x, y, 0.05));
123                 }
124 #endif
125 #ifdef RIGHT_STR1
126                 add_object(gen_pipe(x, y, 0.05));
127 #endif
128         }
129
130 #if defined(LEFT_STR1) || defined(LEFT_STR2) || defined(LEFT_STR3) || defined(LEFT_STR4)
131         //add_object(gen_pipe(-0.5 + 0.08, start_y, 0.08));
132         add_object(gen_pipe(-0.5 + CON_RAD(0.05), 0.8, 0.05));
133 #endif
134 #ifdef LEFT_STR1
135         add_object(gen_pipe(-0.5 + CON_RAD(0.05), 0.68, 0.05));
136 #endif
137 #ifdef LEFT_STR2
138         add_object(gen_pipe(-0.5 + CON_RAD(0.05), 0.3, 0.05));
139 #endif
140 #ifdef LEFT_STR3
141         add_object(gen_pipe_s(-0.5 + CON_RAD(0.05), 0.3, 0.67, 0.05));
142 #endif
143 #ifdef LEFT_STR4
144         add_object(gen_pipe_s(-0.5 + CON_RAD(0.05), 0.67, 0.3, 0.05));
145 #endif
146         return head;
147 }
148
149 static Object *gen_pipe(float x, float y, float rad)
150 {
151         Object *opipe = new Object;
152         opipe->mesh = new Mesh;
153
154
155         for(int i=0; i<2; i++) {
156                 Mesh tmp;
157
158                 float pipelen = 1 - CON_WIDTH * 2;
159                 gen_cylinder(&tmp, rad, pipelen, 6, 1);
160                 xform.translation(0, i - pipelen / 2 - CON_WIDTH, 0);
161                 tmp.apply_xform(xform);
162                 opipe->mesh->append(tmp);
163
164                 gen_cylinder(&tmp, CON_RAD(rad), CON_WIDTH, 7, 1, 1);
165                 xform.translation(0, 1 - i - CON_WIDTH / 2, 0);
166                 tmp.apply_xform(xform);
167                 opipe->mesh->append(tmp);
168
169                 gen_cylinder(&tmp, CON_RAD(rad), CON_WIDTH, 7, 1, 1);
170                 xform.translation(0, 1 - i - CON_WIDTH * 1.5 - pipelen, 0);
171                 tmp.apply_xform(xform);
172                 opipe->mesh->append(tmp);
173         }
174
175         xform.rotation_x(deg_to_rad(90));
176         opipe->mesh->apply_xform(xform);
177         opipe->xform.translation(x, y, 0);
178
179         return opipe;
180 }
181
182 static Object *gen_pipe_inwall(float x, float y, float rad)
183 {
184         Object *opipe = new Object;
185         opipe->mesh = new Mesh;
186
187         const float pipelen = 0.2;
188         float zoffs = 1.0 - pipelen - CON_WIDTH;
189
190         for(int i=0; i<2; i++) {
191                 Mesh tmp;
192                 float sign = i == 0 ? 1.0f : -1.0f;
193
194                 gen_torus(&tmp, rad * 2.0, rad, 4, 7, 0.25);
195                 xform = Mat4::identity;
196                 if(i > 0) xform.rotate_y(deg_to_rad(90));
197                 xform.translate(rad * 2.0, 0, sign * zoffs);
198                 tmp.apply_xform(xform);
199                 opipe->mesh->append(tmp);
200
201                 gen_cylinder(&tmp, rad, pipelen, 7, 1);
202                 xform.rotation_x(deg_to_rad(90));
203                 xform.rotate_z(deg_to_rad(90));
204                 xform.translate(0, 0, sign * (zoffs + pipelen / 2.0));
205                 tmp.apply_xform(xform);
206                 opipe->mesh->append(tmp);
207
208                 gen_cylinder(&tmp, CON_RAD(rad), CON_WIDTH, 7, 1, 1);
209                 xform.rotation_x(deg_to_rad(90));
210                 xform.translate(0, 0, sign * (1 - CON_WIDTH / 2.0));
211                 tmp.apply_xform(xform);
212                 opipe->mesh->append(tmp);
213         }
214
215         opipe->xform.translation(x, y, 0);
216
217         return opipe;
218 }
219
220 static Object *gen_pipe_s(float x, float y0, float y1, float rad)
221 {
222         Mesh tmp;
223         float dist = fabs(y0 - y1);
224         float pipelen = 1.0f - rad * 2.0 - CON_WIDTH / 2.0;
225
226         Object *obj = new Object;
227         obj->mesh = new Mesh;
228
229         for(int i=0; i<2; i++) {
230                 float zsign = i == 0 ? 1.0f : -1.0f;
231                 float ysign = zsign * (y0 > y1 ? 1.0f : -1.0f);
232
233                 gen_torus(&tmp, rad * 2.0, rad, 4, 6, 0.25);
234                 xform.rotation_z(deg_to_rad(90) * ysign);
235                 if(i != 0) xform.rotate_x(deg_to_rad(y0 < y1 ? -90 : 90));
236                 xform.translate(0, ysign * (-dist / 2.0 + rad * 2.0), zsign * rad * 2.0);
237                 tmp.apply_xform(xform);
238                 obj->mesh->append(tmp);
239
240                 gen_cylinder(&tmp, rad, pipelen, 6, 1);
241                 xform.rotation_x(deg_to_rad(90));
242                 xform.translate(0, ysign * -dist / 2.0, zsign * (pipelen / 2.0 + rad * 2.0));
243                 tmp.apply_xform(xform);
244                 obj->mesh->append(tmp);
245
246                 gen_cylinder(&tmp, CON_RAD(rad), CON_WIDTH, 7, 1, 1);
247                 xform.rotation_x(deg_to_rad(90));
248                 xform.translate(0, ysign * -dist / 2.0, zsign * (1 - CON_WIDTH / 2.0));
249                 tmp.apply_xform(xform);
250                 obj->mesh->append(tmp);
251
252                 gen_cylinder(&tmp, CON_RAD(rad), CON_WIDTH, 7, 1, 1);
253                 xform.rotation_x(deg_to_rad(90));
254                 xform.translate(0, ysign * -dist / 2.0, zsign * (rad * 2.0 + CON_WIDTH / 2.0));
255                 tmp.apply_xform(xform);
256                 obj->mesh->append(tmp);
257         }
258
259         gen_cylinder(&tmp, rad, dist - rad * 4.0, 6, 1);
260         obj->mesh->append(tmp);
261
262         obj->xform.translation(x, (y0 + y1) / 2.0, 0);
263         return obj;
264 }