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 "glut_wrap.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 /* */ 42typedef GLfloat TDA[4]; 43 44TDA background; 45 46 47struct 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 62struct 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 84struct BELT 85 { 86 char name[20]; 87 GLint id; 88 char gear1_name[20]; 89 char gear2_name[20]; 90 }; 91 92 93FILE * mainfile; 94struct GEAR g[10]; 95struct AXLE a[10]; 96struct BELT b[10]; 97int number_of_gears; 98int number_of_axles; 99int number_of_belts; 100 101 102char Buf1[256], Buf2[256], Buf3[256], Buf4[256], Buf5[256]; 103 104static GLint T0 = 0; 105static GLint Frames = 0; 106 107 108static void 109Clear_Buffers (void) 110{ 111 memset (Buf1, '\0', 256); 112 memset (Buf2, '\0', 256); 113 memset (Buf3, '\0', 256); 114 memset (Buf4, '\0', 256); 115 memset (Buf5, '\0', 256); 116} 117 118 119static void 120LoadTriplet (TDA A) 121{ 122 int result; 123 Clear_Buffers (); 124 result = fscanf (mainfile, "%s %s %s %s", Buf1, Buf2, Buf3, Buf4); 125 assert(result != EOF); 126 A[0] = atof (Buf2); 127 A[1] = atof (Buf3); 128 A[2] = atof (Buf4); 129} 130 131 132static void 133LoadReal (float *a) 134{ 135 int result; 136 Clear_Buffers (); 137 result = fscanf (mainfile, "%s %s", Buf1, Buf2); 138 assert(result != EOF); 139 *a = atof (Buf2); 140} 141 142 143static void 144LoadInteger (int *a) 145{ 146 int result; 147 Clear_Buffers (); 148 result = fscanf (mainfile, "%s %s", Buf1, Buf2); 149 assert(result != EOF); 150 *a = atoi (Buf2); 151} 152 153 154static void 155LoadText (char *a) 156{ 157 int result; 158 Clear_Buffers (); 159 result = fscanf (mainfile, "%s %s", Buf1, Buf2); 160 assert(result != EOF); 161 strcpy (a, Buf2); 162} 163 164 165static void 166getdata (char filename[]) 167{ 168 int gear_count = 0, axle_count = 0, belt_count = 0, i; 169 170 mainfile = fopen (filename, "r"); 171 if (!mainfile) { 172 printf("Error: couldn't open %s\n", filename); 173 exit(-1); 174 } 175 176 do 177 { 178 int result; 179 Clear_Buffers (); 180 result = fscanf (mainfile, "%s", Buf1); 181 (void) result; 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 while (Buf1[0] != 0); 267 268 number_of_gears = gear_count; 269 number_of_axles = axle_count; 270 number_of_belts = belt_count; 271 272 for (i = 0; i < number_of_gears; i++) 273 { 274 g[i].axis = -1; 275 g[i].direction = 0; 276 g[i].angular_velocity = 0.0; 277 } 278 279 fclose (mainfile); 280} 281 282 283static void 284axle (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 330static void 331gear (GLint j, char type[], GLfloat radius, GLfloat width, 332 GLint teeth, GLfloat tooth_depth) 333{ 334 GLint i; 335 GLfloat r1, r2_front, r2_back; 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_front = r2_back = radius; 342 343 fraction = 0.5; 344 n = 1.0; 345 346 da = 2.0 * M_PI / teeth / 4.0; 347 if (!(strcmp (type, "BEVEL"))) 348 { 349 if (g[j].face) 350 r2_front = radius - width; 351 else 352 r2_back = radius - width; 353 } 354 355 /* draw front face */ 356 glNormal3f (0.0, 0.0, 1.0 * n); 357 glBegin (GL_QUAD_STRIP); 358 for (i = 0; i <= teeth; i++) 359 { 360 angle = i * 2.0 * M_PI / teeth; 361 glVertex3f (0.0, 0.0, width * fraction); 362 glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction); 363 glVertex3f (0.0, 0.0, width * fraction); 364 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction); 365 } 366 glEnd (); 367 368 /* draw front sides of teeth */ 369 glNormal3f (0.0, 0.0, 1.0 * n); 370 glBegin (GL_QUADS); 371 da = 2.0 * M_PI / teeth / 4.0; 372 for (i = 0; i < teeth; i++) 373 { 374 angle = i * 2.0 * M_PI / teeth; 375 glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction); 376 glVertex3f (r2_front * cos (angle + da), r2_front * sin (angle + da), width * fraction); 377 glVertex3f (r2_front * cos (angle + 2 * da), r2_front * sin (angle + 2 * da), width * fraction); 378 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction); 379 } 380 glEnd (); 381 382 /* draw back face */ 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 (r1 * cos (angle), r1 * sin (angle), -width * fraction); 389 glVertex3f (0.0, 0.0, -width * fraction); 390 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction); 391 glVertex3f (0.0, 0.0, -width * fraction); 392 } 393 glEnd (); 394 395 /* draw back sides of teeth */ 396 glNormal3f (0.0, 0.0, -1.0 * n); 397 glBegin (GL_QUADS); 398 da = 2.0 * M_PI / teeth / 4.0; 399 for (i = 0; i < teeth; i++) 400 { 401 angle = i * 2.0 * M_PI / teeth; 402 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction); 403 glVertex3f (r2_back * cos (angle + 2 * da), r2_back * sin (angle + 2 * da), -width * fraction); 404 glVertex3f (r2_back * cos (angle + da), r2_back * sin (angle + da), -width * fraction); 405 glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction); 406 } 407 glEnd (); 408 409 410 /* draw outward faces of teeth. The visible faces are the backfaces, for testing purposes */ 411 glBegin (GL_QUAD_STRIP); 412 for (i = 0; i < teeth; i++) 413 { 414 angle = i * 2.0 * M_PI / teeth; 415 416 glNormal3f (-cos (angle - 0.5*da), -sin (angle - 0.5*da), 0.0); 417 glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction); 418 glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction); 419 u = (r2_front+r2_back)/2.0 * cos (angle + da) - r1 * cos (angle); 420 v = (r2_front+r2_back)/2.0 * sin (angle + da) - r1 * sin (angle); 421 len = sqrt (u * u + v * v); 422 u /= len; 423 v /= len; 424 glNormal3f (-v, u, 0.0); 425 glVertex3f (r2_back * cos (angle + da), r2_back * sin (angle + da), -width * fraction); 426 glVertex3f (r2_front * cos (angle + da), r2_front * sin (angle + da), width * fraction); 427 glNormal3f (-cos (angle + 1.5*da), -sin (angle + 1.5*da), 0.0); 428 glVertex3f (r2_back * cos (angle + 2 * da), r2_back * sin (angle + 2 * da), -width * fraction); 429 glVertex3f (r2_front * cos (angle + 2 * da), r2_front * sin (angle + 2 * da), width * fraction); 430 u = r1 * cos (angle + 3 * da) - (r2_front+r2_back)/2.0 * cos (angle + 2 * da); 431 v = r1 * sin (angle + 3 * da) - (r2_front+r2_back)/2.0 * sin (angle + 2 * da); 432 len = sqrt (u * u + v * v); 433 u /= len; 434 v /= len; 435 glNormal3f (-v, u, 0.0); 436 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction); 437 glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction); 438 glNormal3f (-cos (angle + 3.5*da), -sin (angle + 3.5*da), 0.0); 439 } 440 441 glNormal3f (-cos (-0.5*da), -sin (-0.5*da), 0.0); 442 glVertex3f (r1 * cos (0), r1 * sin (0), -width * fraction); 443 glVertex3f (r1 * cos (0), r1 * sin (0), width * fraction); 444 glEnd (); 445} 446 447 448static void 449belt (struct GEAR g1, struct GEAR g2) 450{ 451 GLfloat D, alpha, phi, angle, incr, width; 452 GLint indexes[3] = 453 { 454 0, 0, 0 455 }; 456 457 GLfloat col[3] = 458 { 459 0.0, 0.0, 0.0 460 }; 461 462 width = min (g1.width, g2.width); 463 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)); 464 alpha = acos ((g2.position[0] - g1.position[0]) / D); 465 phi = acos ((g1.radius - g2.radius) / D); 466 glBegin (GL_QUADS); 467 glColor3fv (col); 468 glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes); 469 incr = 1.2 * 360.0 / g1.teeth * M_PI / 180.00; 470 for (angle = alpha + phi; angle <= 2 * M_PI - phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.00) 471 { 472 glNormal3f (cos (angle), sin (angle), 0.0); 473 glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), width * 0.5); 474 glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), -width * 0.5); 475 glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), -width * 0.5); 476 glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), width * 0.5); 477 } 478 glEnd (); 479 glBegin (GL_QUADS); 480 glColor3fv (col); 481 glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes); 482 incr = 1.2 * 360.0 / g2.teeth * M_PI / 180.00; 483 for (angle = -phi + alpha; angle <= phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.0) 484 { 485 glNormal3f (cos (angle), sin (angle), 0.0); 486 glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * 0.5); 487 glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * -0.5); 488 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); 489 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); 490 } 491 glEnd (); 492 493 glBegin (GL_QUADS); 494 glColor3fv (col); 495 glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes); 496 glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * 0.5); 497 glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * -0.5); 498 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); 499 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); 500 glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * 0.5); 501 glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * -0.5); 502 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); 503 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); 504 glEnd (); 505} 506 507 508static int 509axle_find (char axle_name[]) 510{ 511 int i; 512 513 for (i = 0; i < number_of_axles; i++) 514 { 515 if (!(strcmp (axle_name, a[i].name))) 516 break; 517 } 518 return i; 519} 520 521 522static int 523gear_find (char gear_name[]) 524{ 525 int i; 526 527 for (i = 0; i < number_of_gears; i++) 528 { 529 if (!(strcmp (gear_name, g[i].name))) 530 break; 531 } 532 return i; 533} 534 535 536static void 537process (void) 538{ 539 GLfloat x, y, z, D, dist; 540 GLint axle_index, i, j, g1, g2, k; 541 542 for (i = 0; i < number_of_gears; i++) 543 { 544 x = 0.0; 545 y = 0.0; 546 z = 0.0; 547 axle_index = axle_find (g[i].axle_name); 548 g[i].axis = a[axle_index].axis; 549 g[i].motored = a[axle_index].motored; 550 if (a[axle_index].motored) 551 { 552 g[i].direction = a[axle_index].direction; 553 g[i].angular_velocity = a[axle_index].angular_velocity; 554 } 555 if (g[i].axis == 0) 556 x = 1.0; 557 else if (g[i].axis == 1) 558 y = 1.0; 559 else 560 z = 1.0; 561 562 g[i].position[0] = a[axle_index].position[0] + x * g[i].relative_position; 563 g[i].position[1] = a[axle_index].position[1] + y * g[i].relative_position; 564 g[i].position[2] = a[axle_index].position[2] + z * g[i].relative_position; 565 } 566 567 for (k = 0; k < number_of_axles; k++) 568 { 569 for (i = 0; i < number_of_gears - 1; i++) 570 { 571 for (j = 0; j < number_of_gears; j++) 572 { 573 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)) 574 { 575 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)); 576 if (D < 1.1 * (g[i].radius - g[i].tooth_depth + g[j].radius - g[j].tooth_depth)) 577 { 578 printf ("Gear %s and %s are too close to each other.", g[i].name, g[j].name); 579 exit (1); 580 } 581 582 if (g[i].axis == 0) 583 { 584 dist = g[i].position[0] - g[j].position[0]; 585 } 586 else if (g[i].axis == 1) 587 { 588 dist = g[i].position[1] - g[j].position[1]; 589 } 590 else 591 dist = g[i].position[2] - g[j].position[2]; 592 593 dist = fabs (dist); 594 595 if (dist < (g[i].width / 2 + g[j].width / 2)) 596 { 597 if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * (g[i].radius + g[j].radius))) 598 { 599 axle_index = axle_find (g[j].axle_name); 600 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)) 601 { 602 printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name); 603 exit (1); 604 } 605 606 g[j].motored = (a[axle_index].motored = 1); 607 g[j].direction = (a[axle_index].direction = -g[i].direction); 608 a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth; 609 g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius); 610 } 611 612 if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * (g[i].radius + g[j].radius))) 613 { 614 axle_index = axle_find (g[i].axle_name); 615 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)) 616 { 617 printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name); 618 exit (1); 619 } 620 621 g[i].motored = (a[axle_index].motored = 1); 622 g[i].direction = (a[axle_index].direction = -g[j].direction); 623 a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth; 624 g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius); 625 626 } 627 } 628 } 629 630 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)) 631 { 632 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)); 633 if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius))) 634 { 635 axle_index = axle_find (g[j].axle_name); 636 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)) 637 { 638 printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name); 639 exit (1); 640 } 641 g[j].motored = (a[axle_index].motored = 1); 642 g[j].direction = (a[axle_index].direction = -g[i].direction); 643 a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth; 644 g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius); 645 } 646 647 648 if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius))) 649 { 650 axle_index = axle_find (g[i].axle_name); 651 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)) 652 { 653 printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name); 654 exit (1); 655 } 656 g[i].motored = (a[axle_index].motored = 1); 657 g[i].direction = (a[axle_index].direction = -g[j].direction); 658 a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth; 659 g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius); 660 } 661 } 662 } 663 } 664 665 for (i = 0; i < number_of_gears; i++) 666 { 667 axle_index = axle_find (g[i].axle_name); 668 g[i].motored = a[axle_index].motored; 669 if (a[axle_index].motored) 670 { 671 g[i].direction = a[axle_index].direction; 672 g[i].angular_velocity = a[axle_index].angular_velocity; 673 } 674 } 675 676 for (i = 0; i < number_of_belts; i++) 677 { 678 g1 = gear_find (b[i].gear1_name); 679 g2 = gear_find (b[i].gear2_name); 680 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)); 681 if (!((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL")))) 682 { 683 printf ("Belt %s invalid.", b[i].name); 684 exit (1); 685 } 686 687 if ((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL"))) 688 { 689 /* 690 if((g[g1].motored)&&(g[g2].motored)) 691 if(g[g2].angular_velocity!=(g[g1].angular_velocity*g[g1].radius/g[g2].radius)) 692 { 693 printf("Error in belt linkage of gears %s and %s".,g[g1].name,g[g2].name); 694 exit(1); 695 } 696 */ 697 if (g[g1].axis == 0) 698 { 699 dist = g[g1].position[0] - g[g2].position[0]; 700 } 701 else if (g[i].axis == 1) 702 { 703 dist = g[g1].position[1] - g[g2].position[1]; 704 } 705 else 706 dist = g[g1].position[2] - g[g2].position[2]; 707 708 dist = fabs (dist); 709 710 if (dist > (g[g1].width / 2 + g[g2].width / 2)) 711 { 712 printf ("Belt %s invalid.", b[i].name); 713 exit (1); 714 } 715 716 if (dist < (g[g1].width / 2 + g[g2].width / 2)) 717 { 718 if (D < g[g1].radius + g[g2].radius) 719 { 720 printf ("Gears %s and %s too close to be linked with belts", g[g1].name, g[g2].name); 721 exit (1); 722 } 723 724 if ((g[g1].motored) && (!(g[g2].motored))) 725 { 726 axle_index = axle_find (g[g2].axle_name); 727 g[g2].motored = (a[axle_index].motored = 1); 728 g[g2].direction = (a[axle_index].direction = g[g1].direction); 729 g[g2].angular_velocity = (a[axle_index].angular_velocity = g[g1].angular_velocity * g[g1].radius / g[g2].radius); 730 } 731 732 if ((!(g[g1].motored)) && (g[g2].motored)) 733 { 734 axle_index = axle_find (g[g1].axle_name); 735 g[g1].motored = (a[axle_index].motored = 1); 736 g[g1].direction = (a[axle_index].direction = g[g2].direction); 737 g[g1].angular_velocity = (a[axle_index].angular_velocity = g[g2].angular_velocity * g[g2].radius / g[g1].radius); 738 } 739 } 740 } 741 } 742 743 for (i = 0; i < number_of_gears; i++) 744 { 745 axle_index = axle_find (g[i].axle_name); 746 g[i].motored = a[axle_index].motored; 747 if (a[axle_index].motored) 748 { 749 g[i].direction = a[axle_index].direction; 750 g[i].angular_velocity = a[axle_index].angular_velocity; 751 } 752 } 753 } 754} 755 756 757 758GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 10.0; 759 760 761static void 762draw (void) 763{ 764 int i; 765 GLfloat x, y, z; 766 int index; 767 768 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 769 770 glPushMatrix (); 771 glRotatef (view_rotx, 1.0, 0.0, 0.0); 772 glRotatef (view_roty, 0.0, 1.0, 0.0); 773 glRotatef (view_rotz, 0.0, 0.0, 1.0); 774 775 for (i = 0; i < number_of_gears; i++) 776 { 777 x = 0.0; 778 y = 0.0; 779 z = 0.0; 780 glPushMatrix (); 781/*glTranslatef( -3.0, -2.0, 0.0 );*/ 782 glTranslatef (g[i].position[0], g[i].position[1], g[i].position[2]); 783 if (g[i].axis == 0) 784 y = 1.0; 785 else if (g[i].axis == 1) 786 x = 1.0; 787 else 788 z = 1.0; 789 790 if (z != 1.0) 791 glRotatef (90.0, x, y, z); 792 793 glRotatef (g[i].direction * g[i].angle, 0.0, 0.0, 1.0); 794 glCallList (g[i].id); 795 glPopMatrix (); 796 } 797 798 for (i = 0; i < number_of_axles; i++) 799 { 800 x = 0.0; 801 y = 0.0; 802 z = 0.0; 803 glPushMatrix (); 804 glTranslatef (a[i].position[0], a[i].position[1], a[i].position[2]); 805 if (a[i].axis == 0) 806 y = 1.0; 807 else if (a[i].axis == 1) 808 x = 1.0; 809 else 810 z = 1.0; 811 812 if (z != 1.0) 813 glRotatef (90.0, x, y, z); 814 815 glCallList (a[i].id); 816 glPopMatrix (); 817 } 818 819 for (i = 0; i < number_of_belts; i++) 820 { 821 x = 0.0; 822 y = 0.0; 823 z = 0.0; 824 glPushMatrix (); 825 index = gear_find (b[i].gear1_name); 826 glTranslatef (g[index].position[0], g[index].position[1], g[index].position[2]); 827 if (g[index].axis == 0) 828 y = 1.0; 829 else if (g[index].axis == 1) 830 x = 1.0; 831 else 832 z = 1.0; 833 834 if (z != 1.0) 835 glRotatef (90.0, x, y, z); 836 837 glCallList (b[i].id); 838 glPopMatrix (); 839 } 840 841 glPopMatrix (); 842 glutSwapBuffers (); 843 844 { 845 GLint t = glutGet(GLUT_ELAPSED_TIME); 846 Frames++; 847 if (t - T0 >= 5000) { 848 GLfloat seconds = (t - T0) / 1000.0; 849 GLfloat fps = Frames / seconds; 850 printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps); 851 fflush(stdout); 852 T0 = t; 853 Frames = 0; 854 } 855 } 856} 857 858 859static void 860idle (void) 861{ 862 int i; 863 static double t0 = -1.; 864 double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0; 865 if (t0 < 0.0) 866 t0 = t; 867 dt = t - t0; 868 t0 = t; 869 for (i = 0; i < number_of_gears; i++) 870 g[i].angle += g[i].angular_velocity * dt; 871 glutPostRedisplay(); 872} 873 874 875 876 877/* change view angle, exit upon ESC */ 878static void 879key (unsigned char k, int x, int y) 880{ 881 switch (k) 882 { 883 case 'x': 884 view_rotx += 5.0; 885 break; 886 case 'X': 887 view_rotx -= 5.0; 888 break; 889 case 'y': 890 view_roty += 5.0; 891 break; 892 case 'Y': 893 view_roty -= 5.0; 894 break; 895 case 'z': 896 view_rotz += 5.0; 897 break; 898 case 'Z': 899 view_rotz -= 5.0; 900 break; 901 case 0x1B: 902 exit(0); 903 } 904} 905 906 907 908 909/* new window size or exposure */ 910static void 911reshape (int width, int height) 912{ 913 glViewport (0, 0, (GLint) width, (GLint) height); 914 glMatrixMode (GL_PROJECTION); 915 glLoadIdentity (); 916 if (width > height) 917 { 918 GLfloat w = (GLfloat) width / (GLfloat) height; 919 glFrustum (-w, w, -1.0, 1.0, 5.0, 60.0); 920 } 921 else 922 { 923 GLfloat h = (GLfloat) height / (GLfloat) width; 924 glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0); 925 } 926 927 glMatrixMode (GL_MODELVIEW); 928 glLoadIdentity (); 929 glTranslatef (0.0, 0.0, -40.0); 930 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 931} 932 933 934 935static void 936init (void) 937{ 938 GLfloat matShine = 20.00F; 939 const GLfloat light0Pos[4] = 940 { 941 0.70F, 0.70F, 1.25F, 0.50F 942 }; 943 int i; 944 945 glShadeModel(GL_FLAT); 946 glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1); 947 948 glClearColor (background[0], background[1], background[2], 1.0F); 949 glClearIndex ((GLfloat) 0.0); 950 951 glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, matShine); 952 glLightfv (GL_LIGHT0, GL_POSITION, light0Pos); 953 glEnable (GL_LIGHT0); 954 955 glEnable (GL_LIGHTING); 956 glEnable (GL_DEPTH_TEST); 957 for (i = 0; i < number_of_gears; i++) 958 g[i].angle = 0.0; 959 960 for (i = 0; i < number_of_gears; i++) 961 { 962 g[i].id = glGenLists (1); 963 glNewList (g[i].id, GL_COMPILE); 964 glColor3fv (g[i].color); 965 glMaterialfv (GL_FRONT, GL_SPECULAR, g[i].color); 966 gear (i, g[i].type, g[i].radius, g[i].width, g[i].teeth, g[i].tooth_depth); 967 glEndList (); 968 } 969 970 for (i = 0; i < number_of_axles; i++) 971 { 972 a[i].id = glGenLists (1); 973 glNewList (a[i].id, GL_COMPILE); 974 glColor3fv (a[i].color); 975 glMaterialfv (GL_FRONT, GL_SPECULAR, a[i].color); 976 axle (i, a[i].radius, a[i].length); 977 glEndList (); 978 } 979 980 for (i = 0; i < number_of_belts; i++) 981 { 982 b[i].id = glGenLists (1); 983 glNewList (b[i].id, GL_COMPILE); 984 belt (g[gear_find (b[i].gear1_name)], g[gear_find (b[i].gear2_name)]); 985 glEndList (); 986 } 987 988 glEnable (GL_COLOR_MATERIAL); 989} 990 991 992 993int 994main (int argc, char *argv[]) 995{ 996 char *file; 997 998 glutInitWindowSize(640,480); 999 glutInit(&argc, argv); 1000 glutInitDisplayMode (GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE ); 1001 1002 if (glutCreateWindow ("Gear Train Simulation") == GL_FALSE) 1003 exit (1); 1004 1005 if (argc < 2) 1006 file = DEMOS_DATA_DIR "geartrain.dat"; 1007 else 1008 file = argv[1]; 1009 1010 getdata (file); 1011 process (); 1012 init (); 1013 1014 glutDisplayFunc (draw); 1015 glutReshapeFunc (reshape); 1016 glutKeyboardFunc (key); 1017 glutIdleFunc (idle); 1018 glutMainLoop (); 1019 return 0; 1020} 1021