18 #define CON_RAD(r) ((r) * 1.4)
19 #define CON_WIDTH 0.04
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);
30 static unsigned char *gen_texture(int x, int y);
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
46 #define add_object(o) \
56 while(tail->next) tail = tail->next; \
60 extern "C" Object *generate()
62 Object *head = 0, *tail = 0;
65 add_object(gen_base_straight());
68 add_object(gen_base_left_junction());
71 add_object(gen_base_right_junction());
73 add_object(gen_pipeworks());
75 unsigned char *tex = gen_texture(256, 256);
78 tail->texture.pixels = tex;
79 tail->texture.width = tail->texture.height = 256;
80 tail->texture.fmt = PFMT_RGB;
87 static Object *gen_base_straight()
89 Object *owalls = new Object;
90 owalls->mesh = new Mesh;
91 gen_box(owalls->mesh, -1, -2, -1, 1, 2);
93 xform.rotation_x(deg_to_rad(90));
94 owalls->mesh->apply_xform(xform);
96 owalls->mesh->remove_faces(16, 23);
98 xform.translation(0, 0.5, 0);
99 owalls->mesh->apply_xform(xform);
101 owalls->mesh->texcoord_gen_box();
106 static Object *gen_base_left_junction()
110 Object *obj = new Object;
111 obj->mesh = new Mesh;
113 gen_box(obj->mesh, -1, -2, -1, 1, 3);
115 xform.rotation_x(deg_to_rad(90));
116 xform.translate(0, 0.5, 0);
117 obj->mesh->apply_xform(xform);
119 obj->mesh->remove_faces(24, 35);
120 obj->mesh->remove_faces(6, 11);
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);
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);
136 tmp.remove_faces(8, 11);
138 obj->mesh->append(tmp);
140 obj->mesh->texcoord_gen_box();
145 static Object *gen_base_right_junction()
147 Object *obj = gen_base_left_junction();
148 xform.rotation_y(deg_to_rad(180));
149 obj->mesh->apply_xform(xform);
151 obj->mesh->texcoord_gen_box();
155 static Object *gen_pipeworks()
157 Object *head = 0, *tail = 0;
159 // --- right straight pipes ---
160 float start_y = CON_RAD(FAT_RAD) + 0.01;
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;
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);
171 add_object(gen_pipe_inwall(x, y, STD_RAD));
174 add_object(gen_pipe(x, y, STD_RAD));
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));
184 add_object(gen_pipe(-0.5 + CON_RAD(STD_RAD), 0.68, STD_RAD));
187 add_object(gen_pipe(-0.5 + CON_RAD(STD_RAD), 0.3, STD_RAD));
190 add_object(gen_pipe_s(-0.5 + CON_RAD(STD_RAD), 0.3, 0.67, STD_RAD));
193 add_object(gen_pipe_s(-0.5 + CON_RAD(STD_RAD), 0.68, 0.3, STD_RAD));
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));
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));
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));
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));
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));
218 // --- right junction pipes ---
222 static void gen_conn(Mesh *mesh, float rad)
224 gen_cylinder(mesh, CON_RAD(rad), CON_WIDTH, 7, 1, 1);
226 xform.scaling(1, 0.05, 1);
227 mesh->texcoord_apply_xform(xform);
230 static Object *gen_pipe(float x, float y, float rad)
232 Object *opipe = new Object;
233 opipe->mesh = new Mesh;
236 for(int i=0; i<2; i++) {
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);
246 xform.translation(0, 1 - i - CON_WIDTH / 2, 0);
247 tmp.apply_xform(xform);
248 opipe->mesh->append(tmp);
251 xform.translation(0, 1 - i - CON_WIDTH * 1.5 - pipelen, 0);
252 tmp.apply_xform(xform);
253 opipe->mesh->append(tmp);
256 xform.rotation_x(deg_to_rad(90));
257 opipe->mesh->apply_xform(xform);
258 opipe->xform.translation(x, y, 0);
263 static Object *gen_pipe_inwall(float x, float y, float rad)
265 Object *opipe = new Object;
266 opipe->mesh = new Mesh;
268 const float pipelen = 0.2;
269 float zoffs = 1.0 - pipelen - CON_WIDTH;
271 for(int i=0; i<2; i++) {
273 float sign = i == 0 ? 1.0f : -1.0f;
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);
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);
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);
296 opipe->xform.translation(x, y, 0);
301 static Object *gen_pipe_s(float x, float y0, float y1, float rad)
304 float dist = fabs(y0 - y1);
305 float pipelen = 1.0f - rad * 2.0 - CON_WIDTH / 2.0;
307 Object *obj = new Object;
308 obj->mesh = new Mesh;
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);
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);
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);
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);
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);
340 gen_cylinder(&tmp, rad, dist - rad * 4.0, 6, 1);
341 obj->mesh->append(tmp);
343 obj->xform.translation(x, (y0 + y1) / 2.0, 0);
347 static Object *gen_pipe_corner(float x, float y, float z, float rad)
350 Object *obj = new Object;
351 obj->mesh = new Mesh;
353 float xoffs = CON_RAD(rad);
354 float pipelen = 0.5 - CON_WIDTH - (rad * 2.0 - xoffs + CON_WIDTH);
356 float sign = z >= 0.0f ? 1.0f : -1.0f;
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);
364 for(int i=0; i<2; i++) {
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);
374 xform.rotation_x(deg_to_rad(90));
375 xform.translate(xoffs, 0, sign * (1 - CON_WIDTH / 2));
376 tmp.apply_xform(xform);
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);
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);
394 obj->mesh->append(pipe);
397 obj->xform.translation(x, y, 0);
401 static unsigned char *gen_texture(int x, int y)
403 unsigned char *pixels = new unsigned char[x * y * 3];
404 unsigned char *ptr = pixels;
406 for(int i=0; i<y; i++) {
407 for(int j=0; j<x; j++) {
409 *ptr++ = (i ^ j) << 1;
410 *ptr++ = (i ^ j) << 2;