use gray background, memset TempImage to white to help with debugging
[mesa.git] / progs / demos / geartrain.c
1 /* $Id: geartrain.c,v 1.6 2000/04/06 02:22:59 brianp Exp $ */
2
3 /*
4 * GearTrain Simulator * Version: 1.00
5 *
6 * Copyright (C) 1999 Shobhan Kumar Dutta All Rights Reserved.
7 * <skdutta@del3.vsnl.net.in>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * SHOBHAN KUMAR DUTTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
24 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28
29 #include <math.h>
30 #include <stdlib.h>
31 #include <GL/glut.h>
32 #include <string.h>
33 #include <stdio.h>
34
35 #define min(x, y) ( x < y ? x : y )
36
37 #ifndef M_PI
38 #define M_PI 3.14159265
39 #endif /* */
40 typedef GLfloat TDA[4];
41
42 TDA background;
43
44
45 struct AXLE
46 {
47 char name[20];
48 GLint id;
49 GLfloat radius;
50 GLint axis;
51 TDA color;
52 TDA position;
53 GLfloat length;
54 GLint motored;
55 GLfloat angular_velocity;
56 GLint direction;
57 };
58
59
60 struct GEAR
61 {
62 char name[20];
63 char type[7];
64 GLint face;
65 GLint id;
66 GLfloat radius;
67 GLfloat width;
68 GLint teeth;
69 GLfloat tooth_depth;
70 GLfloat angle;
71 GLfloat angular_velocity;
72 TDA color;
73 GLint relative_position;
74 TDA position;
75 char axle_name[20];
76 GLint axis;
77 GLint direction;
78 GLint motored;
79 };
80
81
82 struct BELT
83 {
84 char name[20];
85 GLint id;
86 char gear1_name[20];
87 char gear2_name[20];
88 };
89
90
91 FILE * mainfile;
92 struct GEAR g[10];
93 struct AXLE a[10];
94 struct BELT b[10];
95 int number_of_gears;
96 int number_of_axles;
97 int number_of_belts;
98
99
100 char Buf1[256], Buf2[256], Buf3[256], Buf4[256], Buf5[256];
101
102
103 static void
104 strset (char buf[], char ch)
105 {
106 int i;
107 for (i = 0; i < strlen (buf); i++)
108 buf[i] = ch;
109 }
110
111
112 static void
113 Clear_Buffers ()
114 {
115 strset (Buf1, 0);
116 strset (Buf2, 0);
117 strset (Buf3, 0);
118 strset (Buf4, 0);
119 strset (Buf5, 0);
120 }
121
122
123 static void
124 LoadTriplet (TDA A)
125 {
126 Clear_Buffers ();
127 fscanf (mainfile, "%s %s %s %s", Buf1, Buf2, Buf3, Buf4);
128 A[0] = atof (Buf2);
129 A[1] = atof (Buf3);
130 A[2] = atof (Buf4);
131 }
132
133
134 static void
135 LoadReal (float *a)
136 {
137 Clear_Buffers ();
138 fscanf (mainfile, "%s %s", Buf1, Buf2);
139 *a = atof (Buf2);
140 }
141
142
143 static void
144 LoadInteger (int *a)
145 {
146 Clear_Buffers ();
147 fscanf (mainfile, "%s %s", Buf1, Buf2);
148 *a = atoi (Buf2);
149 }
150
151
152 static void
153 LoadText (char *a)
154 {
155 Clear_Buffers ();
156 fscanf (mainfile, "%s %s", Buf1, Buf2);
157 strcpy (a, Buf2);
158 }
159
160
161 static void
162 getdata (char filename[])
163 {
164 int gear_count = 0, axle_count = 0, belt_count = 0, i;
165
166 mainfile = fopen (filename, "r");
167 if (!mainfile) {
168 printf("Error: couldn't open %s\n", filename);
169 exit(-1);
170 }
171
172 do
173 {
174 Clear_Buffers ();
175 fscanf (mainfile, "%s", Buf1);
176 if (ferror (mainfile))
177 {
178 printf ("\nError opening file !\n");
179 exit (1);
180 }
181
182 if (!(strcmp (Buf1, "BACKGROUND")))
183 LoadTriplet (background);
184
185 if (!(strcmp (Buf1, "ANAME")))
186 {
187 LoadText (a[axle_count].name);
188 axle_count++;
189 }
190
191 if (!(strcmp (Buf1, "ARADIUS")))
192 LoadReal (&a[axle_count - 1].radius);
193
194 if (!(strcmp (Buf1, "AAXIS")))
195 LoadInteger (&a[axle_count - 1].axis);
196
197 if (!(strcmp (Buf1, "ACOLOR")))
198 LoadTriplet (a[axle_count - 1].color);
199
200 if (!(strcmp (Buf1, "APOSITION")))
201 LoadTriplet (a[axle_count - 1].position);
202
203 if (!(strcmp (Buf1, "ALENGTH")))
204 LoadReal (&a[axle_count - 1].length);
205
206 if (!(strcmp (Buf1, "AMOTORED")))
207 LoadInteger (&a[axle_count - 1].motored);
208
209 if (!(strcmp (Buf1, "AANGULARVELOCITY")))
210 LoadReal (&a[axle_count - 1].angular_velocity);
211
212 if (!(strcmp (Buf1, "ADIRECTION")))
213 LoadInteger (&a[axle_count - 1].direction);
214
215 if (!(strcmp (Buf1, "GNAME")))
216 {
217 LoadText (g[gear_count].name);
218 gear_count++;
219 }
220
221 if (!(strcmp (Buf1, "GTYPE")))
222 LoadText (g[gear_count - 1].type);
223
224 if (!(strcmp (Buf1, "GFACE")))
225 LoadInteger (&g[gear_count - 1].face);
226
227 if (!(strcmp (Buf1, "GRADIUS")))
228 LoadReal (&g[gear_count - 1].radius);
229
230 if (!(strcmp (Buf1, "GWIDTH")))
231 LoadReal (&g[gear_count - 1].width);
232
233 if (!(strcmp (Buf1, "GTEETH")))
234 LoadInteger (&g[gear_count - 1].teeth);
235
236 if (!(strcmp (Buf1, "GTOOTHDEPTH")))
237 LoadReal (&g[gear_count - 1].tooth_depth);
238
239 if (!(strcmp (Buf1, "GCOLOR")))
240 LoadTriplet (g[gear_count - 1].color);
241
242 if (!(strcmp (Buf1, "GAXLE")))
243 LoadText (g[gear_count - 1].axle_name);
244
245 if (!(strcmp (Buf1, "GPOSITION")))
246 LoadInteger (&g[gear_count - 1].relative_position);
247
248 if (!(strcmp (Buf1, "BELTNAME")))
249 {
250 LoadText (b[belt_count].name);
251 belt_count++;
252 }
253
254 if (!(strcmp (Buf1, "GEAR1NAME")))
255 LoadText (b[belt_count - 1].gear1_name);
256
257 if (!(strcmp (Buf1, "GEAR2NAME")))
258 LoadText (b[belt_count - 1].gear2_name);
259 }
260
261 while (Buf1[0] != 0);
262
263 for (i = 0; i < number_of_gears; i++)
264 {
265 g[i].axis = -1;
266 g[i].direction = 0;
267 g[i].angular_velocity = 0.0;
268 }
269
270 number_of_gears = gear_count;
271 number_of_axles = axle_count;
272 number_of_belts = belt_count;
273 fclose (mainfile);
274 }
275
276
277 static void
278 axle (GLint j, GLfloat radius, GLfloat length)
279 {
280 GLfloat angle, rad, incr = 10.0 * M_PI / 180.0;
281
282 /* draw main cylinder */
283 glBegin (GL_QUADS);
284 for (angle = 0.0; angle < 360.0; angle += 5.0)
285 {
286 rad = angle * M_PI / 180.0;
287 glNormal3f (cos (rad), sin (rad), 0.0);
288 glVertex3f (radius * cos (rad), radius * sin (rad), length / 2);
289 glVertex3f (radius * cos (rad), radius * sin (rad), -length / 2);
290 glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), -length / 2);
291 glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), length / 2);
292 }
293 glEnd ();
294
295 /* draw front face */
296 glNormal3f (0.0, 0.0, 1.0);
297 glBegin (GL_TRIANGLES);
298 for (angle = 0.0; angle < 360.0; angle += 5.0)
299 {
300 rad = angle * M_PI / 180.0;
301 glVertex3f (0.0, 0.0, length / 2);
302 glVertex3f (radius * cos (rad), radius * sin (rad), length / 2);
303 glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), length / 2);
304 glVertex3f (0.0, 0.0, length / 2);
305 }
306 glEnd ();
307
308 /* draw back face */
309 glNormal3f (0.0, 0.0, -1.0);
310 glBegin (GL_TRIANGLES);
311 for (angle = 0.0; angle <= 360.0; angle += 5.0)
312 {
313 rad = angle * M_PI / 180.0;
314 glVertex3f (0.0, 0.0, -length / 2);
315 glVertex3f (radius * cos (rad), radius * sin (rad), -length / 2);
316 glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), -length / 2);
317 glVertex3f (0.0, 0.0, -length / 2);
318 }
319 glEnd ();
320 }
321
322
323
324 static void
325 gear (GLint j, char type[], GLfloat radius, GLfloat width,
326 GLint teeth, GLfloat tooth_depth)
327 {
328 GLint i;
329 GLfloat r1, r2;
330 GLfloat angle, da;
331 GLfloat u, v, len, fraction = 0.5;
332 GLfloat n = 1.0;
333
334 r1 = radius - tooth_depth;
335 r2 = radius;
336
337 da = 2.0 * M_PI / teeth / 4.0;
338 if (!g[j].face)
339 {
340 fraction = -0.5;
341 n = -1.0;
342 }
343 if (!(strcmp (type, "NORMAL")))
344 {
345 fraction = 0.5;
346 n = 1.0;
347 }
348
349 /* draw front face */
350 if (!(strcmp (type, "NORMAL")))
351 {
352 glNormal3f (0.0, 0.0, 1.0 * n);
353 glBegin (GL_QUAD_STRIP);
354 for (i = 0; i <= teeth; i++)
355 {
356 angle = i * 2.0 * M_PI / teeth;
357 glVertex3f (0.0, 0.0, width * fraction);
358 glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
359 glVertex3f (0.0, 0.0, width * fraction);
360 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
361 }
362 glEnd ();
363 }
364 else
365 {
366 glNormal3f (0.0, 0.0, 1.0 * n);
367 glBegin (GL_QUAD_STRIP);
368 for (i = 0; i <= teeth; i++)
369 {
370 angle = i * 2.0 * M_PI / teeth;
371 glVertex3f (0.0, 0.0, width * fraction);
372 glVertex3f ((r2 - width) * cos (angle), (r2 - width) * sin (angle), width * fraction);
373 glVertex3f (0.0, 0.0, width * fraction);
374 glVertex3f ((r2 - width) * cos (angle + 3 * da), (r2 - width) * sin (angle + 3 * da), width * fraction);
375 }
376 glEnd ();
377 }
378
379 /* draw front sides of teeth */
380 if (!(strcmp (type, "NORMAL")))
381 {
382 glNormal3f (0.0, 0.0, 1.0 * n);
383 glBegin (GL_QUADS);
384 da = 2.0 * M_PI / teeth / 4.0;
385 for (i = 0; i < teeth; i++)
386 {
387 angle = i * 2.0 * M_PI / teeth;
388 glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
389 glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), width * fraction);
390 glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), width * fraction);
391 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
392 }
393 glEnd ();
394 }
395
396 glNormal3f (0.0, 0.0, -1.0 * n);
397
398 /* draw back face */
399 glBegin (GL_QUAD_STRIP);
400 for (i = 0; i <= teeth; i++)
401 {
402 angle = i * 2.0 * M_PI / teeth;
403 glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
404 glVertex3f (0.0, 0.0, -width * fraction);
405 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
406 glVertex3f (0.0, 0.0, -width * fraction);
407 }
408 glEnd ();
409
410 /* draw back sides of teeth */
411 glNormal3f (0.0, 0.0, -1.0 * n);
412 glBegin (GL_QUADS);
413 da = 2.0 * M_PI / teeth / 4.0;
414 for (i = 0; i < teeth; i++)
415 {
416 angle = i * 2.0 * M_PI / teeth;
417 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
418 glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), -width * fraction);
419 glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), -width * fraction);
420 glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
421 }
422 glEnd ();
423
424
425 /* draw outward faces of teeth */
426 if (!(strcmp (type, "NORMAL")))
427 {
428 glBegin (GL_QUAD_STRIP);
429 for (i = 0; i < teeth; i++)
430 {
431 angle = i * 2.0 * M_PI / teeth;
432
433 glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
434 glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
435 u = r2 * cos (angle + da) - r1 * cos (angle);
436 v = r2 * sin (angle + da) - r1 * sin (angle);
437 len = sqrt (u * u + v * v);
438 u /= len;
439 v /= len;
440 glNormal3f (v, -u, 0.0);
441 glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), width * fraction);
442 glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), -width * fraction);
443 glNormal3f (cos (angle), sin (angle), 0.0);
444 glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), width * fraction);
445 glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), -width * fraction);
446 u = r1 * cos (angle + 3 * da) - r2 * cos (angle + 2 * da);
447 v = r1 * sin (angle + 3 * da) - r2 * sin (angle + 2 * da);
448 glNormal3f (v, -u, 0.0);
449 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
450 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
451 glNormal3f (cos (angle), sin (angle), 0.0);
452 }
453 }
454 else
455 {
456 glBegin (GL_QUAD_STRIP);
457 for (i = 0; i < teeth; i++)
458 {
459 angle = i * 2.0 * M_PI / teeth;
460 glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
461 glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
462 u = r2 * cos (angle + da) - r1 * cos (angle);
463 v = r2 * sin (angle + da) - r1 * sin (angle);
464 len = sqrt (u * u + v * v);
465 u /= len;
466 v /= len;
467 glNormal3f (v, -u, 0.0);
468 glVertex3f ((r2 - width) * cos (angle + da), (r2 - width) * sin (angle + da), width * fraction);
469 glVertex3f (r2 * cos (angle + da), r2 * sin (angle + da), -width * fraction);
470 glNormal3f (cos (angle), sin (angle), n);
471 glVertex3f ((r2 - width) * cos (angle + 2 * da), (r2 - width) * sin (angle + 2 * da), width * fraction);
472 glVertex3f (r2 * cos (angle + 2 * da), r2 * sin (angle + 2 * da), -width * fraction);
473 u = r1 * cos (angle + 3 * da) - r2 * cos (angle + 2 * da);
474 v = r1 * sin (angle + 3 * da) - r2 * sin (angle + 2 * da);
475 glNormal3f (v, -u, 0.0);
476 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
477 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
478 glNormal3f (cos (angle), sin (angle), n);
479 }
480 }
481
482 glVertex3f (r1 * cos (0), r1 * sin (0), width * fraction);
483 glVertex3f (r1 * cos (0), r1 * sin (0), -width * fraction);
484 glEnd ();
485 }
486
487
488 static void
489 belt (struct GEAR g1, struct GEAR g2)
490 {
491 GLfloat D, alpha, phi, angle, incr, width;
492 GLint indexes[3] =
493 {
494 0, 0, 0
495 };
496
497 GLfloat col[3] =
498 {
499 0.0, 0.0, 0.0
500 };
501
502 width = min (g1.width, g2.width);
503 D = sqrt (pow (g1.position[0] - g2.position[0], 2) + pow (g1.position[1] - g2.position[1], 2) + pow (g1.position[2] - g2.position[2], 2));
504 alpha = acos ((g2.position[0] - g1.position[0]) / D);
505 phi = acos ((g1.radius - g2.radius) / D);
506 glBegin (GL_QUADS);
507 glColor3fv (col);
508 glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
509 incr = 1.2 * 360.0 / g1.teeth * M_PI / 180.00;
510 for (angle = alpha + phi; angle <= 2 * M_PI - phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.00)
511 {
512 glNormal3f (cos (angle), sin (angle), 0.0);
513 glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), width * 0.5);
514 glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), -width * 0.5);
515 glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), -width * 0.5);
516 glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), width * 0.5);
517 }
518 glEnd ();
519 glBegin (GL_QUADS);
520 glColor3fv (col);
521 glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
522 incr = 1.2 * 360.0 / g2.teeth * M_PI / 180.00;
523 for (angle = -phi + alpha; angle <= phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.0)
524 {
525 glNormal3f (cos (angle), sin (angle), 0.0);
526 glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * 0.5);
527 glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * -0.5);
528 glVertex3f (g2.radius * cos (angle + incr) + g2.position[0] - g1.position[0], g2.radius * sin (angle + incr) + g2.position[1] - g1.position[1], width * -0.5);
529 glVertex3f (g2.radius * cos (angle + incr) + g2.position[0] - g1.position[0], g2.radius * sin (angle + incr) + g2.position[1] - g1.position[1], width * 0.5);
530 }
531 glEnd ();
532
533 glBegin (GL_QUADS);
534 glColor3fv (col);
535 glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
536 glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * 0.5);
537 glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * -0.5);
538 glVertex3f (g2.radius * cos (alpha + phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha + phi) + g2.position[1] - g1.position[1], width * -0.5);
539 glVertex3f (g2.radius * cos (alpha + phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha + phi) + g2.position[1] - g1.position[1], width * 0.5);
540 glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * 0.5);
541 glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * -0.5);
542 glVertex3f (g2.radius * cos (alpha - phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha - phi) + g2.position[1] - g1.position[1], width * -0.5);
543 glVertex3f (g2.radius * cos (alpha - phi) + g2.position[0] - g1.position[0], g2.radius * sin (alpha - phi) + g2.position[1] - g1.position[1], width * 0.5);
544 glEnd ();
545 }
546
547
548 static int
549 axle_find (char axle_name[])
550 {
551 int i;
552
553 for (i = 0; i < number_of_axles; i++)
554 {
555 if (!(strcmp (axle_name, a[i].name)))
556 break;
557 }
558 return i;
559 }
560
561
562 static int
563 gear_find (char gear_name[])
564 {
565 int i;
566
567 for (i = 0; i < number_of_gears; i++)
568 {
569 if (!(strcmp (gear_name, g[i].name)))
570 break;
571 }
572 return i;
573 }
574
575
576 static void
577 process ()
578 {
579 GLfloat x, y, z, D, dist;
580 GLint axle_index, i, j, g1, g2, k;
581 char error[80];
582
583 for (i = 0; i < number_of_gears; i++)
584 {
585 x = 0.0;
586 y = 0.0;
587 z = 0.0;
588 axle_index = axle_find (g[i].axle_name);
589 g[i].axis = a[axle_index].axis;
590 g[i].motored = a[axle_index].motored;
591 if (a[axle_index].motored)
592 {
593 g[i].direction = a[axle_index].direction;
594 g[i].angular_velocity = a[axle_index].angular_velocity;
595 }
596 if (g[i].axis == 0)
597 x = 1.0;
598 else if (g[i].axis == 1)
599 y = 1.0;
600 else
601 z = 1.0;
602
603 g[i].position[0] = a[axle_index].position[0] + x * g[i].relative_position;
604 g[i].position[1] = a[axle_index].position[1] + y * g[i].relative_position;
605 g[i].position[2] = a[axle_index].position[2] + z * g[i].relative_position;
606 }
607
608 for (k = 0; k < number_of_axles; k++)
609 {
610 for (i = 0; i < number_of_gears - 1; i++)
611 {
612 for (j = 0; j < number_of_gears; j++)
613 {
614 if (!(strcmp (g[i].type, g[j].type)) && (!(strcmp (g[i].type, "NORMAL"))) && ((strcmp (g[i].axle_name, g[j].axle_name) != 0)) && (g[i].axis == g[j].axis))
615 {
616 D = sqrt (pow (g[i].position[0] - g[j].position[0], 2) + pow (g[i].position[1] - g[j].position[1], 2) + pow (g[i].position[2] - g[j].position[2], 2));
617 if (D < 1.1 * (g[i].radius - g[i].tooth_depth + g[j].radius - g[j].tooth_depth))
618 {
619 printf (error, "Gear %s and %s are too close to each other.", g[i].name, g[j].name);
620
621 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
622 exit (1);
623 }
624
625 if (g[i].axis == 0)
626 {
627 dist = g[i].position[0] - g[j].position[0];
628 }
629 else if (g[i].axis == 1)
630 {
631 dist = g[i].position[1] - g[j].position[1];
632 }
633 else
634 dist = g[i].position[2] - g[j].position[2];
635
636 dist = fabs (dist);
637
638 if (dist < (g[i].width / 2 + g[j].width / 2))
639 {
640 if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * (g[i].radius + g[j].radius)))
641 {
642 axle_index = axle_find (g[j].axle_name);
643 if ((a[axle_index].direction != 0) && (g[j].angular_velocity != g[i].angular_velocity * g[i].teeth / g[j].teeth * g[i].radius / g[j].radius))
644 {
645 printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
646 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
647 exit (1);
648 }
649
650 g[j].motored = (a[axle_index].motored = 1);
651 g[j].direction = (a[axle_index].direction = -g[i].direction);
652 a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth;
653 g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius);
654 }
655
656 if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * (g[i].radius + g[j].radius)))
657 {
658 axle_index = axle_find (g[i].axle_name);
659 if ((a[axle_index].direction != 0) && (g[i].angular_velocity != g[j].angular_velocity * g[j].teeth / g[i].teeth * g[j].radius / g[i].radius))
660 {
661 printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
662 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
663 exit (1);
664 }
665
666 g[i].motored = (a[axle_index].motored = 1);
667 g[i].direction = (a[axle_index].direction = -g[j].direction);
668 a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth;
669 g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius);
670
671 }
672 }
673 }
674
675 if (!(strcmp (g[i].type, g[j].type)) && (!(strcmp (g[i].type, "BEVEL"))) && ((strcmp (g[i].axle_name, g[j].axle_name) != 0)) && (g[i].axis != g[j].axis))
676 {
677 D = sqrt (pow (g[i].position[0] - g[j].position[0], 2) + pow (g[i].position[1] - g[j].position[1], 2) + pow (g[i].position[2] - g[j].position[2], 2));
678 if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius)))
679 {
680 axle_index = axle_find (g[j].axle_name);
681 if ((a[axle_index].direction != 0) && (g[j].angular_velocity != g[i].angular_velocity * g[i].teeth / g[j].teeth * g[i].radius / g[j].radius))
682 {
683 printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
684 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
685 exit (1);
686 }
687 g[j].motored = (a[axle_index].motored = 1);
688 g[j].direction = (a[axle_index].direction = -g[i].direction);
689 a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth;
690 g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius);
691 }
692
693
694 if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius)))
695 {
696 axle_index = axle_find (g[i].axle_name);
697 if ((a[axle_index].direction != 0) && (g[i].angular_velocity != g[j].angular_velocity * g[j].teeth / g[i].teeth * g[j].radius / g[i].radius))
698 {
699 printf (error, "Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
700 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
701 exit (1);
702 }
703 g[i].motored = (a[axle_index].motored = 1);
704 g[i].direction = (a[axle_index].direction = -g[j].direction);
705 a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth;
706 g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius);
707 }
708 }
709 }
710 }
711
712 for (i = 0; i < number_of_gears; i++)
713 {
714 axle_index = axle_find (g[i].axle_name);
715 g[i].motored = a[axle_index].motored;
716 if (a[axle_index].motored)
717 {
718 g[i].direction = a[axle_index].direction;
719 g[i].angular_velocity = a[axle_index].angular_velocity;
720 }
721 }
722
723 for (i = 0; i < number_of_belts; i++)
724 {
725 g1 = gear_find (b[i].gear1_name);
726 g2 = gear_find (b[i].gear2_name);
727 D = sqrt (pow (g[g1].position[0] - g[g2].position[0], 2) + pow (g[g1].position[1] - g[g2].position[1], 2) + pow (g[g1].position[2] - g[g2].position[2], 2));
728 if (!((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL"))))
729 {
730 printf (error, "Belt %s invalid.", b[i].name);
731 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
732 exit (1);
733 }
734
735 if ((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL")))
736 {
737 /*
738 if((g[g1].motored)&&(g[g2].motored))
739 if(g[g2].angular_velocity!=(g[g1].angular_velocity*g[g1].radius/g[g2].radius))
740 {
741 printf(error,"Error in belt linkage of gears %s and %s".,g[g1].name,g[g2].name);
742 MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);
743 exit(1);
744 }
745 */
746 if (g[g1].axis == 0)
747 {
748 dist = g[g1].position[0] - g[g2].position[0];
749 }
750 else if (g[i].axis == 1)
751 {
752 dist = g[g1].position[1] - g[g2].position[1];
753 }
754 else
755 dist = g[g1].position[2] - g[g2].position[2];
756
757 dist = fabs (dist);
758
759 if (dist > (g[g1].width / 2 + g[g2].width / 2))
760 {
761 printf (error, "Belt %s invalid.", b[i].name);
762 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
763 exit (1);
764 }
765
766 if (dist < (g[g1].width / 2 + g[g2].width / 2))
767 {
768 if (D < g[g1].radius + g[g2].radius)
769 {
770 printf (error, "Gears %s and %s too close to be linked with belts", g[g1].name, g[g2].name);
771 /*MessageBox(NULL,error,windowName,MB_ICONEXCLAMATION|MB_OK);*/
772 exit (1);
773 }
774
775 if ((g[g1].motored) && (!(g[g2].motored)))
776 {
777 axle_index = axle_find (g[g2].axle_name);
778 g[g2].motored = (a[axle_index].motored = 1);
779 g[g2].direction = (a[axle_index].direction = g[g1].direction);
780 g[g2].angular_velocity = (a[axle_index].angular_velocity = g[g1].angular_velocity * g[g1].radius / g[g2].radius);
781 }
782
783 if ((!(g[g1].motored)) && (g[g2].motored))
784 {
785 axle_index = axle_find (g[g1].axle_name);
786 g[g1].motored = (a[axle_index].motored = 1);
787 g[g1].direction = (a[axle_index].direction = g[g2].direction);
788 g[g1].angular_velocity = (a[axle_index].angular_velocity = g[g2].angular_velocity * g[g2].radius / g[g1].radius);
789 }
790 }
791 }
792 }
793
794 for (i = 0; i < number_of_gears; i++)
795 {
796 axle_index = axle_find (g[i].axle_name);
797 g[i].motored = a[axle_index].motored;
798 if (a[axle_index].motored)
799 {
800 g[i].direction = a[axle_index].direction;
801 g[i].angular_velocity = a[axle_index].angular_velocity;
802 }
803 }
804 }
805 }
806
807
808
809 GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 10.0;
810
811
812 static void
813 draw (void)
814 {
815 int i;
816 GLfloat x, y, z;
817 int index;
818
819 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
820
821 glPushMatrix ();
822 glRotatef (view_rotx, 1.0, 0.0, 0.0);
823 glRotatef (view_roty, 0.0, 1.0, 0.0);
824 glRotatef (view_rotz, 0.0, 0.0, 1.0);
825
826 for (i = 0; i < number_of_gears; i++)
827 {
828 x = 0.0;
829 y = 0.0;
830 z = 0.0;
831 glPushMatrix ();
832 /*glTranslatef( -3.0, -2.0, 0.0 );*/
833 glTranslatef (g[i].position[0], g[i].position[1], g[i].position[2]);
834 if (g[i].axis == 0)
835 y = 1.0;
836 else if (g[i].axis == 1)
837 x = 1.0;
838 else
839 z = 1.0;
840
841 if (z != 1.0)
842 glRotatef (90.0, x, y, z);
843
844 glRotatef (g[i].direction * g[i].angle, 0.0, 0.0, 1.0);
845 glCallList (g[i].id);
846 glPopMatrix ();
847 }
848
849 for (i = 0; i < number_of_axles; i++)
850 {
851 x = 0.0;
852 y = 0.0;
853 z = 0.0;
854 glPushMatrix ();
855 glTranslatef (a[i].position[0], a[i].position[1], a[i].position[2]);
856 if (a[i].axis == 0)
857 y = 1.0;
858 else if (a[i].axis == 1)
859 x = 1.0;
860 else
861 z = 1.0;
862
863 if (z != 1.0)
864 glRotatef (90.0, x, y, z);
865
866 glCallList (a[i].id);
867 glPopMatrix ();
868 }
869
870 for (i = 0; i < number_of_belts; i++)
871 {
872 x = 0.0;
873 y = 0.0;
874 z = 0.0;
875 glPushMatrix ();
876 index = gear_find (b[i].gear1_name);
877 glTranslatef (g[index].position[0], g[index].position[1], g[index].position[2]);
878 if (g[index].axis == 0)
879 y = 1.0;
880 else if (g[index].axis == 1)
881 x = 1.0;
882 else
883 z = 1.0;
884
885 if (z != 1.0)
886 glRotatef (90.0, x, y, z);
887
888 glCallList (b[i].id);
889 glPopMatrix ();
890 }
891
892 glPopMatrix ();
893 glutSwapBuffers ();
894 }
895
896
897
898
899 static void
900 idle (void)
901 {
902 int i;
903 for (i = 0; i < number_of_gears; i++)
904 g[i].angle += g[i].angular_velocity;
905 glutPostRedisplay();
906 }
907
908
909
910
911 /* change view angle, exit upon ESC */
912 static void
913 key (unsigned char k, int x, int y)
914 {
915 switch (k)
916 {
917 case 'x':
918 view_rotx += 5.0;
919 break;
920 case 'X':
921 view_rotx -= 5.0;
922 break;
923 case 'y':
924 view_roty += 5.0;
925 break;
926 case 'Y':
927 view_roty -= 5.0;
928 break;
929 case 'z':
930 view_rotz += 5.0;
931 break;
932 case 'Z':
933 view_rotz -= 5.0;
934 break;
935 case 0x1B:
936 exit(0);
937 }
938 }
939
940
941
942
943 /* new window size or exposure */
944 static void
945 reshape (int width, int height)
946 {
947 glViewport (0, 0, (GLint) width, (GLint) height);
948 glMatrixMode (GL_PROJECTION);
949 glLoadIdentity ();
950 if (width > height)
951 {
952 GLfloat w = (GLfloat) width / (GLfloat) height;
953 glFrustum (-w, w, -1.0, 1.0, 5.0, 60.0);
954 }
955 else
956 {
957 GLfloat h = (GLfloat) height / (GLfloat) width;
958 glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
959 }
960
961 glMatrixMode (GL_MODELVIEW);
962 glLoadIdentity ();
963 glTranslatef (0.0, 0.0, -40.0);
964 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
965 }
966
967
968
969 static void
970 init (void)
971 {
972 GLfloat matShine = 20.00F;
973 GLfloat light0Pos[4] =
974 {
975 0.70F, 0.70F, 1.25F, 0.50F
976 };
977 int i;
978
979 glClearColor (background[0], background[1], background[2], 1.0F);
980 glClearIndex ((GLfloat) 0.0);
981
982 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, matShine);
983 glLightfv (GL_LIGHT0, GL_POSITION, light0Pos);
984 glEnable (GL_LIGHT0);
985
986 glEnable (GL_LIGHTING);
987 glEnable (GL_DEPTH_TEST);
988 for (i = 0; i < number_of_gears; i++)
989 g[i].angle = 0.0;
990
991 for (i = 0; i < number_of_gears; i++)
992 {
993 g[i].id = glGenLists (1);
994 glNewList (g[i].id, GL_COMPILE);
995 glColor3fv (g[i].color);
996 glMaterialfv (GL_FRONT, GL_SPECULAR, g[i].color);
997 gear (i, g[i].type, g[i].radius, g[i].width, g[i].teeth, g[i].tooth_depth);
998 glEndList ();
999 }
1000
1001 for (i = 0; i < number_of_axles; i++)
1002 {
1003 a[i].id = glGenLists (1);
1004 glNewList (a[i].id, GL_COMPILE);
1005 glColor3fv (a[i].color);
1006 glMaterialfv (GL_FRONT, GL_SPECULAR, a[i].color);
1007 axle (i, a[i].radius, a[i].length);
1008 glEndList ();
1009 }
1010
1011 for (i = 0; i < number_of_belts; i++)
1012 {
1013 b[i].id = glGenLists (1);
1014 glNewList (b[i].id, GL_COMPILE);
1015 belt (g[gear_find (b[i].gear1_name)], g[gear_find (b[i].gear2_name)]);
1016 glEndList ();
1017 }
1018
1019 glEnable (GL_COLOR_MATERIAL);
1020 }
1021
1022
1023
1024 int
1025 main (int argc, char *argv[])
1026 {
1027 char *file;
1028
1029 if (argc < 2)
1030 file = "geartrain.dat";
1031 else
1032 file = argv[1];
1033
1034 glutInitWindowPosition (0, 0);
1035 glutInitWindowSize(640,480);
1036 glutInitDisplayMode (GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
1037
1038 if (glutCreateWindow ("Gear Train Simulation") == GL_FALSE)
1039 exit (1);
1040
1041 getdata (file);
1042 process ();
1043 init ();
1044
1045 glutDisplayFunc (draw);
1046 glutReshapeFunc (reshape);
1047 glutKeyboardFunc (key);
1048 glutIdleFunc (idle);
1049 glutMainLoop ();
1050 return 0;
1051 }
1052