need reorganization
[dosdemo] / tools / procgen / steamtun.cc
1 //#define BASE_STR
2 //#define BASE_LEFTJ
3 #define BASE_RIGHTJ
4 //#define RIGHT_STR1
5 //#define RIGHT_STR2
6 //#define LEFT_STR1
7 //#define LEFT_STR2
8 //#define LEFT_STR3
9 //#define LEFT_STR4
10
11 //#define LEFT_J1
12 //#define LEFT_J2
13 //#define LEFT_J3
14 //#define LEFT_J4
15
16 #define STD_RAD         0.05
17 #define FAT_RAD         0.08
18 #define CON_RAD(r)      ((r) * 1.4)
19 #define CON_WIDTH       0.04
20
21 static Object *gen_base_straight();
22 static Object *gen_base_left_junction();
23 static Object *gen_base_right_junction();
24 static Object *gen_pipeworks();
25 static Object *gen_pipe(float x, float y, float rad);
26 static Object *gen_pipe_inwall(float x, float y, float rad);
27 static Object *gen_pipe_s(float x, float y0, float y1, float rad);
28 static Object *gen_pipe_corner(float x, float y, float z, float rad);
29
30 static unsigned char *gen_texture(int x, int y);
31
32 static Mat4 xform;
33
34 #define YSTEP   (CON_RAD(STD_RAD) * 1.8)
35 #define Y0              (CON_RAD(FAT_RAD) + 0.01)
36 #define Y1              (Y0 + YSTEP)
37 #define Y2              (Y1 + YSTEP)
38 #define Y3              (Y2 + YSTEP)
39 #define Y4              (Y3 + YSTEP)
40 #define Y5              (Y4 + YSTEP)
41 #define Y6              (Y5 + YSTEP)
42 static const float yslots[] = {
43         Y0, Y1, Y2, Y3, Y4, Y5, Y6
44 };
45
46 #define add_object(o) \
47         do { \
48                 Object *tmp = o; \
49                 if(tmp) { \
50                         if(head) { \
51                                 tail->next = tmp; \
52                                 tail = tmp; \
53                         } else { \
54                                 head = tail = tmp; \
55                         } \
56                         while(tail->next) tail = tail->next; \
57                 } \
58         } while(0)
59
60 extern "C" Object *generate()
61 {
62         Object *head = 0, *tail = 0;
63
64 #ifdef BASE_STR
65         add_object(gen_base_straight());
66 #endif
67 #ifdef BASE_LEFTJ
68         add_object(gen_base_left_junction());
69 #endif
70 #ifdef BASE_RIGHTJ
71         add_object(gen_base_right_junction());
72 #endif
73         add_object(gen_pipeworks());
74
75         unsigned char *tex = gen_texture(256, 256);
76         tail = head;
77         while(tail) {
78                 tail->texture.pixels = tex;
79                 tail->texture.width = tail->texture.height = 256;
80                 tail->texture.fmt = PFMT_RGB;
81                 tail = tail->next;
82         }
83
84         return head;
85 }
86
87 static Object *gen_base_straight()
88 {
89         Object *owalls = new Object;
90         owalls->mesh = new Mesh;
91         gen_box(owalls->mesh, -1, -2, -1, 1, 2);
92
93         xform.rotation_x(deg_to_rad(90));
94         owalls->mesh->apply_xform(xform);
95
96         owalls->mesh->remove_faces(16, 23);
97
98         xform.translation(0, 0.5, 0);
99         owalls->mesh->apply_xform(xform);
100
101         owalls->mesh->texcoord_gen_box();
102
103         return owalls;
104 }
105
106 static Object *gen_base_left_junction()
107 {
108         Mesh tmp;
109
110         Object *obj = new Object;
111         obj->mesh = new Mesh;
112
113         gen_box(obj->mesh, -1, -2, -1, 1, 3);
114
115         xform.rotation_x(deg_to_rad(90));
116         xform.translate(0, 0.5, 0);
117         obj->mesh->apply_xform(xform);
118
119         obj->mesh->remove_faces(24, 35);
120         obj->mesh->remove_faces(6, 11);
121
122         for(int i=0; i<2; i++) {
123                 float sign = i == 0 ? 1.0f : -1.0f;
124                 gen_plane(&tmp, 0.5, 1, 1, 1);
125                 xform.rotation_y(deg_to_rad(90));
126                 xform.translate(-0.5, 0.5, sign * 0.75);
127                 tmp.apply_xform(xform);
128                 obj->mesh->append(tmp);
129         }
130
131         gen_box(&tmp, -1, -0.5, -1, 1, 1);
132         xform.rotation_z(deg_to_rad(90));
133         xform.translate(-0.75, 0.5, 0);
134         tmp.apply_xform(xform);
135
136         tmp.remove_faces(8, 11);
137
138         obj->mesh->append(tmp);
139
140         obj->mesh->texcoord_gen_box();
141
142         return obj;
143 }
144
145 static Object *gen_base_right_junction()
146 {
147         Object *obj = gen_base_left_junction();
148         xform.rotation_y(deg_to_rad(180));
149         obj->mesh->apply_xform(xform);
150
151         obj->mesh->texcoord_gen_box();
152         return obj;
153 }
154
155 static Object *gen_pipeworks()
156 {
157         Object *head = 0, *tail = 0;
158
159         // --- right straight pipes ---
160         float start_y = CON_RAD(FAT_RAD) + 0.01;
161
162 #if defined(RIGHT_STR1) || defined(RIGHT_STR2)
163         add_object(gen_pipe(0.5 - FAT_RAD, start_y, FAT_RAD));
164         start_y += (CON_RAD(FAT_RAD) + CON_RAD(STD_RAD)) * 0.9;
165
166         for(int i=0; i<3; i++) {
167                 float x = 0.5 - CON_RAD(STD_RAD);
168                 float y = start_y + i * (CON_RAD(STD_RAD) * 1.8);
169 #ifdef RIGHT_STR2
170                 if(i == 1)
171                         add_object(gen_pipe_inwall(x, y, STD_RAD));
172                 else
173 #endif
174                         add_object(gen_pipe(x, y, STD_RAD));
175         }
176 #endif
177
178         // --- left straight pipes ---
179 #if defined(LEFT_STR1) || defined(LEFT_STR2) || defined(LEFT_STR3) || defined(LEFT_STR4)
180         //add_object(gen_pipe(-0.5 + FAT_RAD, start_y, FAT_RAD));
181         add_object(gen_pipe(-0.5 + CON_RAD(STD_RAD), 0.8, STD_RAD));
182 #endif
183 #ifdef LEFT_STR1
184         add_object(gen_pipe(-0.5 + CON_RAD(STD_RAD), 0.68, STD_RAD));
185 #endif
186 #ifdef LEFT_STR2
187         add_object(gen_pipe(-0.5 + CON_RAD(STD_RAD), 0.3, STD_RAD));
188 #endif
189 #ifdef LEFT_STR3
190         add_object(gen_pipe_s(-0.5 + CON_RAD(STD_RAD), 0.3, 0.67, STD_RAD));
191 #endif
192 #ifdef LEFT_STR4
193         add_object(gen_pipe_s(-0.5 + CON_RAD(STD_RAD), 0.68, 0.3, STD_RAD));
194 #endif
195
196         // --- left junction pipes ---
197 #if defined(LEFT_J1) || defined(LEFT_J2) || defined(LEFT_J3) || defined(LEFT_J4)
198         add_object(gen_pipe_corner(-0.5, 0.8, 0.5, STD_RAD));
199         add_object(gen_pipe_corner(-0.5, 0.8, -0.5, STD_RAD));
200 #endif
201 #ifdef LEFT_J1
202         add_object(gen_pipe_corner(-0.5, 0.68, 0.5, STD_RAD));
203         add_object(gen_pipe_corner(-0.5, 0.68, -0.5, STD_RAD));
204 #endif
205 #ifdef LEFT_J2
206         add_object(gen_pipe_corner(-0.5, 0.3, 0.5, STD_RAD));
207         add_object(gen_pipe_corner(-0.5, 0.3, -0.5, STD_RAD));
208 #endif
209 #ifdef LEFT_J3
210         add_object(gen_pipe_corner(-0.5, 0.3, 0.5, STD_RAD));
211         add_object(gen_pipe_corner(-0.5, 0.68, -0.5, STD_RAD));
212 #endif
213 #ifdef LEFT_J4
214         add_object(gen_pipe_corner(-0.5, 0.68, 0.5, STD_RAD));
215         add_object(gen_pipe_corner(-0.5, 0.3, -0.5, STD_RAD));
216 #endif
217
218         // --- right junction pipes ---
219         return head;
220 }
221
222 static void gen_conn(Mesh *mesh, float rad)
223 {
224         gen_cylinder(mesh, CON_RAD(rad), CON_WIDTH, 7, 1, 1);
225
226         xform.scaling(1, 0.05, 1);
227         mesh->texcoord_apply_xform(xform);
228 }
229
230 static Object *gen_pipe(float x, float y, float rad)
231 {
232         Object *opipe = new Object;
233         opipe->mesh = new Mesh;
234
235
236         for(int i=0; i<2; i++) {
237                 Mesh tmp;
238
239                 float pipelen = 1 - CON_WIDTH * 2;
240                 gen_cylinder(&tmp, rad, pipelen, 6, 1);
241                 xform.translation(0, i - pipelen / 2 - CON_WIDTH, 0);
242                 tmp.apply_xform(xform);
243                 opipe->mesh->append(tmp);
244
245                 gen_conn(&tmp, rad);
246                 xform.translation(0, 1 - i - CON_WIDTH / 2, 0);
247                 tmp.apply_xform(xform);
248                 opipe->mesh->append(tmp);
249
250                 gen_conn(&tmp, rad);
251                 xform.translation(0, 1 - i - CON_WIDTH * 1.5 - pipelen, 0);
252                 tmp.apply_xform(xform);
253                 opipe->mesh->append(tmp);
254         }
255
256         xform.rotation_x(deg_to_rad(90));
257         opipe->mesh->apply_xform(xform);
258         opipe->xform.translation(x, y, 0);
259
260         return opipe;
261 }
262
263 static Object *gen_pipe_inwall(float x, float y, float rad)
264 {
265         Object *opipe = new Object;
266         opipe->mesh = new Mesh;
267
268         const float pipelen = 0.2;
269         float zoffs = 1.0 - pipelen - CON_WIDTH;
270
271         for(int i=0; i<2; i++) {
272                 Mesh tmp;
273                 float sign = i == 0 ? 1.0f : -1.0f;
274
275                 gen_torus(&tmp, rad * 2.0, rad, 4, 7, 0.25);
276                 xform = Mat4::identity;
277                 if(i > 0) xform.rotate_y(deg_to_rad(90));
278                 xform.translate(rad * 2.0, 0, sign * zoffs);
279                 tmp.apply_xform(xform);
280                 opipe->mesh->append(tmp);
281
282                 gen_cylinder(&tmp, rad, pipelen, 7, 1);
283                 xform.rotation_x(deg_to_rad(90));
284                 xform.rotate_z(deg_to_rad(90));
285                 xform.translate(0, 0, sign * (zoffs + pipelen / 2.0));
286                 tmp.apply_xform(xform);
287                 opipe->mesh->append(tmp);
288
289                 gen_conn(&tmp, rad);
290                 xform.rotation_x(deg_to_rad(90));
291                 xform.translate(0, 0, sign * (1 - CON_WIDTH / 2.0));
292                 tmp.apply_xform(xform);
293                 opipe->mesh->append(tmp);
294         }
295
296         opipe->xform.translation(x, y, 0);
297
298         return opipe;
299 }
300
301 static Object *gen_pipe_s(float x, float y0, float y1, float rad)
302 {
303         Mesh tmp;
304         float dist = fabs(y0 - y1);
305         float pipelen = 1.0f - rad * 2.0 - CON_WIDTH / 2.0;
306
307         Object *obj = new Object;
308         obj->mesh = new Mesh;
309
310         for(int i=0; i<2; i++) {
311                 float zsign = i == 0 ? 1.0f : -1.0f;
312                 float ysign = zsign * (y0 > y1 ? 1.0f : -1.0f);
313
314                 gen_torus(&tmp, rad * 2.0, rad, 4, 6, 0.25);
315                 xform.rotation_z(deg_to_rad(90) * ysign);
316                 if(i != 0) xform.rotate_x(deg_to_rad(y0 < y1 ? -90 : 90));
317                 xform.translate(0, ysign * (-dist / 2.0 + rad * 2.0), zsign * rad * 2.0);
318                 tmp.apply_xform(xform);
319                 obj->mesh->append(tmp);
320
321                 gen_cylinder(&tmp, rad, pipelen, 6, 1);
322                 xform.rotation_x(deg_to_rad(90));
323                 xform.translate(0, ysign * -dist / 2.0, zsign * (pipelen / 2.0 + rad * 2.0));
324                 tmp.apply_xform(xform);
325                 obj->mesh->append(tmp);
326
327                 gen_conn(&tmp, rad);
328                 xform.rotation_x(deg_to_rad(90));
329                 xform.translate(0, ysign * -dist / 2.0, zsign * (1 - CON_WIDTH / 2.0));
330                 tmp.apply_xform(xform);
331                 obj->mesh->append(tmp);
332
333                 gen_conn(&tmp, rad);
334                 xform.rotation_x(deg_to_rad(90));
335                 xform.translate(0, ysign * -dist / 2.0, zsign * (rad * 2.0 + CON_WIDTH / 2.0));
336                 tmp.apply_xform(xform);
337                 obj->mesh->append(tmp);
338         }
339
340         gen_cylinder(&tmp, rad, dist - rad * 4.0, 6, 1);
341         obj->mesh->append(tmp);
342
343         obj->xform.translation(x, (y0 + y1) / 2.0, 0);
344         return obj;
345 }
346
347 static Object *gen_pipe_corner(float x, float y, float z, float rad)
348 {
349         Mesh tmp;
350         Object *obj = new Object;
351         obj->mesh = new Mesh;
352
353         float xoffs = CON_RAD(rad);
354         float pipelen = 0.5 - CON_WIDTH - (rad * 2.0 - xoffs + CON_WIDTH);
355
356         float sign = z >= 0.0f ? 1.0f : -1.0f;
357
358         gen_torus(&tmp, rad * 2.0, rad, 4, 6, 0.25);
359         xform.rotation_y(deg_to_rad(sign >= 0.0f ? -90 : 180));
360         xform.translate(xoffs - rad * 2.0, 0, sign * (0.5 + rad * 2.0 - xoffs));
361         tmp.apply_xform(xform);
362         obj->mesh->append(tmp);
363
364         for(int i=0; i<2; i++) {
365                 Mesh pipe;
366                 gen_cylinder(&tmp, rad, pipelen, 6, 1);
367                 xform.rotation_x(deg_to_rad(90));
368                 xform.rotate_z(deg_to_rad(90));
369                 xform.translate(xoffs, 0, sign * (1 - pipelen / 2 - CON_WIDTH));
370                 tmp.apply_xform(xform);
371                 pipe.append(tmp);
372
373                 gen_conn(&tmp, rad);
374                 xform.rotation_x(deg_to_rad(90));
375                 xform.translate(xoffs, 0, sign * (1 - CON_WIDTH / 2));
376                 tmp.apply_xform(xform);
377                 pipe.append(tmp);
378
379                 gen_conn(&tmp, rad);
380                 xform.rotation_x(deg_to_rad(90));
381                 xform.translate(xoffs, 0, sign * (0.5 + rad * 2.0 - xoffs + CON_WIDTH / 2.0));
382                 tmp.apply_xform(xform);
383                 pipe.append(tmp);
384
385                 if(i > 0) {
386                         xform = Mat4::identity;
387                         xform.translate(-xoffs, 0, sign * -0.5);
388                         xform.rotate_y(deg_to_rad(sign * -90));
389                         xform.translate(xoffs, 0, sign * 0.5);
390                         xform.translate(-xoffs, 0, sign * -xoffs);
391                         pipe.apply_xform(xform);
392                 }
393
394                 obj->mesh->append(pipe);
395         }
396
397         obj->xform.translation(x, y, 0);
398         return obj;
399 }
400
401 static unsigned char *gen_texture(int x, int y)
402 {
403         unsigned char *pixels = new unsigned char[x * y * 3];
404         unsigned char *ptr = pixels;
405
406         for(int i=0; i<y; i++) {
407                 for(int j=0; j<x; j++) {
408                         *ptr++ = i ^ j;
409                         *ptr++ = (i ^ j) << 1;
410                         *ptr++ = (i ^ j) << 2;
411                 }
412         }
413         return pixels;
414 }