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