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