132001f49Smrg
232001f49Smrg/*
332001f49Smrg * GearTrain Simulator * Version:  1.00
432001f49Smrg *
532001f49Smrg * Copyright (C) 1999  Shobhan Kumar Dutta  All Rights Reserved.
632001f49Smrg * <skdutta@del3.vsnl.net.in>
732001f49Smrg *
832001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
932001f49Smrg * copy of this software and associated documentation files (the "Software"),
1032001f49Smrg * to deal in the Software without restriction, including without limitation
1132001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1232001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
1332001f49Smrg * Software is furnished to do so, subject to the following conditions:
1432001f49Smrg *
1532001f49Smrg * The above copyright notice and this permission notice shall be included
1632001f49Smrg * in all copies or substantial portions of the Software.
1732001f49Smrg *
1832001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1932001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2032001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2132001f49Smrg * SHOBHAN KUMAR DUTTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
2232001f49Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
2332001f49Smrg * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2432001f49Smrg * SOFTWARE.
2532001f49Smrg */
2632001f49Smrg
2732001f49Smrg
2832001f49Smrg#include <assert.h>
2932001f49Smrg#include <math.h>
3032001f49Smrg#include <stdlib.h>
3132001f49Smrg#include "glut_wrap.h"
3232001f49Smrg#include <string.h>
3332001f49Smrg#include <stdio.h>
3432001f49Smrg
3532001f49Smrg#ifndef min
3632001f49Smrg#define min(x, y) ( x < y ? x : y )
3732001f49Smrg#endif
3832001f49Smrg
3932001f49Smrg#ifndef M_PI
4032001f49Smrg#define M_PI 3.14159265
4132001f49Smrg#endif	/*  */
4232001f49Smrgtypedef GLfloat TDA[4];
4332001f49Smrg
4432001f49SmrgTDA background;
4532001f49Smrg
4632001f49Smrg
4732001f49Smrgstruct AXLE
4832001f49Smrg  {
4932001f49Smrg    char name[20];
5032001f49Smrg      GLint id;
5132001f49Smrg      GLfloat radius;
5232001f49Smrg      GLint axis;
5332001f49Smrg      TDA color;
5432001f49Smrg      TDA position;
5532001f49Smrg      GLfloat length;
5632001f49Smrg      GLint motored;
5732001f49Smrg      GLfloat angular_velocity;
5832001f49Smrg      GLint direction;
5932001f49Smrg  };
6032001f49Smrg
6132001f49Smrg
6232001f49Smrgstruct GEAR
6332001f49Smrg  {
6432001f49Smrg    char name[20];
6532001f49Smrg    char type[7];
6632001f49Smrg      GLint face;
6732001f49Smrg      GLint id;
6832001f49Smrg      GLfloat radius;
6932001f49Smrg      GLfloat width;
7032001f49Smrg      GLint teeth;
7132001f49Smrg      GLfloat tooth_depth;
7232001f49Smrg      GLfloat angle;
7332001f49Smrg      GLfloat angular_velocity;
7432001f49Smrg      TDA color;
7532001f49Smrg      GLint relative_position;
7632001f49Smrg      TDA position;
7732001f49Smrg    char axle_name[20];
7832001f49Smrg      GLint axis;
7932001f49Smrg      GLint direction;
8032001f49Smrg      GLint motored;
8132001f49Smrg  };
8232001f49Smrg
8332001f49Smrg
8432001f49Smrgstruct BELT
8532001f49Smrg  {
8632001f49Smrg    char name[20];
8732001f49Smrg      GLint id;
8832001f49Smrg    char gear1_name[20];
8932001f49Smrg    char gear2_name[20];
9032001f49Smrg  };
9132001f49Smrg
9232001f49Smrg
9332001f49SmrgFILE * mainfile;
9432001f49Smrgstruct GEAR g[10];
9532001f49Smrgstruct AXLE a[10];
9632001f49Smrgstruct BELT b[10];
9732001f49Smrgint number_of_gears;
9832001f49Smrgint number_of_axles;
9932001f49Smrgint number_of_belts;
10032001f49Smrg
10132001f49Smrg
10232001f49Smrgchar Buf1[256], Buf2[256], Buf3[256], Buf4[256], Buf5[256];
10332001f49Smrg
10432001f49Smrgstatic GLint T0 = 0;
10532001f49Smrgstatic GLint Frames = 0;
10632001f49Smrg
10732001f49Smrg
10832001f49Smrgstatic void
10932001f49SmrgClear_Buffers (void)
11032001f49Smrg{
11132001f49Smrg    memset (Buf1, '\0', 256);
11232001f49Smrg    memset (Buf2, '\0', 256);
11332001f49Smrg    memset (Buf3, '\0', 256);
11432001f49Smrg    memset (Buf4, '\0', 256);
11532001f49Smrg    memset (Buf5, '\0', 256);
11632001f49Smrg}
11732001f49Smrg
11832001f49Smrg
11932001f49Smrgstatic void
12032001f49SmrgLoadTriplet (TDA A)
12132001f49Smrg{
12232001f49Smrg    int result;
12332001f49Smrg    Clear_Buffers ();
12432001f49Smrg    result = fscanf (mainfile, "%s %s %s %s", Buf1, Buf2, Buf3, Buf4);
12532001f49Smrg    assert(result != EOF);
12632001f49Smrg    A[0] = atof (Buf2);
12732001f49Smrg    A[1] = atof (Buf3);
12832001f49Smrg    A[2] = atof (Buf4);
12932001f49Smrg}
13032001f49Smrg
13132001f49Smrg
13232001f49Smrgstatic void
13332001f49SmrgLoadReal (float *a)
13432001f49Smrg{
13532001f49Smrg    int result;
13632001f49Smrg    Clear_Buffers ();
13732001f49Smrg    result = fscanf (mainfile, "%s %s", Buf1, Buf2);
13832001f49Smrg    assert(result != EOF);
13932001f49Smrg    *a = atof (Buf2);
14032001f49Smrg}
14132001f49Smrg
14232001f49Smrg
14332001f49Smrgstatic void
14432001f49SmrgLoadInteger (int *a)
14532001f49Smrg{
14632001f49Smrg    int result;
14732001f49Smrg    Clear_Buffers ();
14832001f49Smrg    result = fscanf (mainfile, "%s %s", Buf1, Buf2);
14932001f49Smrg    assert(result != EOF);
15032001f49Smrg    *a = atoi (Buf2);
15132001f49Smrg}
15232001f49Smrg
15332001f49Smrg
15432001f49Smrgstatic void
15532001f49SmrgLoadText (char *a)
15632001f49Smrg{
15732001f49Smrg    int result;
15832001f49Smrg    Clear_Buffers ();
15932001f49Smrg    result = fscanf (mainfile, "%s %s", Buf1, Buf2);
16032001f49Smrg    assert(result != EOF);
16132001f49Smrg    strcpy (a, Buf2);
16232001f49Smrg}
16332001f49Smrg
16432001f49Smrg
16532001f49Smrgstatic void
16632001f49Smrggetdata (char filename[])
16732001f49Smrg{
16832001f49Smrg    int gear_count = 0, axle_count = 0, belt_count = 0, i;
16932001f49Smrg
17032001f49Smrg    mainfile = fopen (filename, "r");
17132001f49Smrg    if (!mainfile) {
17232001f49Smrg       printf("Error: couldn't open %s\n", filename);
17332001f49Smrg       exit(-1);
17432001f49Smrg    }
17532001f49Smrg
17632001f49Smrg    do
17732001f49Smrg    {
17832001f49Smrg	int result;
17932001f49Smrg	Clear_Buffers ();
18032001f49Smrg	result = fscanf (mainfile, "%s", Buf1);
18132001f49Smrg	(void) result;
18232001f49Smrg	if (ferror (mainfile))
18332001f49Smrg	{
18432001f49Smrg	    printf ("\nError opening file !\n");
18532001f49Smrg	    exit (1);
18632001f49Smrg	}
18732001f49Smrg
18832001f49Smrg	if (!(strcmp (Buf1, "BACKGROUND")))
18932001f49Smrg	  LoadTriplet (background);
19032001f49Smrg
19132001f49Smrg	if (!(strcmp (Buf1, "ANAME")))
19232001f49Smrg	{
19332001f49Smrg	    LoadText (a[axle_count].name);
19432001f49Smrg	    axle_count++;
19532001f49Smrg	}
19632001f49Smrg
19732001f49Smrg	if (!(strcmp (Buf1, "ARADIUS")))
19832001f49Smrg	  LoadReal (&a[axle_count - 1].radius);
19932001f49Smrg
20032001f49Smrg	if (!(strcmp (Buf1, "AAXIS")))
20132001f49Smrg	  LoadInteger (&a[axle_count - 1].axis);
20232001f49Smrg
20332001f49Smrg	if (!(strcmp (Buf1, "ACOLOR")))
20432001f49Smrg	  LoadTriplet (a[axle_count - 1].color);
20532001f49Smrg
20632001f49Smrg	if (!(strcmp (Buf1, "APOSITION")))
20732001f49Smrg	  LoadTriplet (a[axle_count - 1].position);
20832001f49Smrg
20932001f49Smrg	if (!(strcmp (Buf1, "ALENGTH")))
21032001f49Smrg	  LoadReal (&a[axle_count - 1].length);
21132001f49Smrg
21232001f49Smrg	if (!(strcmp (Buf1, "AMOTORED")))
21332001f49Smrg	  LoadInteger (&a[axle_count - 1].motored);
21432001f49Smrg
21532001f49Smrg	if (!(strcmp (Buf1, "AANGULARVELOCITY")))
21632001f49Smrg	  LoadReal (&a[axle_count - 1].angular_velocity);
21732001f49Smrg
21832001f49Smrg	if (!(strcmp (Buf1, "ADIRECTION")))
21932001f49Smrg	  LoadInteger (&a[axle_count - 1].direction);
22032001f49Smrg
22132001f49Smrg	if (!(strcmp (Buf1, "GNAME")))
22232001f49Smrg	{
22332001f49Smrg	    LoadText (g[gear_count].name);
22432001f49Smrg	    gear_count++;
22532001f49Smrg	}
22632001f49Smrg
22732001f49Smrg	if (!(strcmp (Buf1, "GTYPE")))
22832001f49Smrg	  LoadText (g[gear_count - 1].type);
22932001f49Smrg
23032001f49Smrg	if (!(strcmp (Buf1, "GFACE")))
23132001f49Smrg	  LoadInteger (&g[gear_count - 1].face);
23232001f49Smrg
23332001f49Smrg	if (!(strcmp (Buf1, "GRADIUS")))
23432001f49Smrg	  LoadReal (&g[gear_count - 1].radius);
23532001f49Smrg
23632001f49Smrg	if (!(strcmp (Buf1, "GWIDTH")))
23732001f49Smrg	  LoadReal (&g[gear_count - 1].width);
23832001f49Smrg
23932001f49Smrg	if (!(strcmp (Buf1, "GTEETH")))
24032001f49Smrg	  LoadInteger (&g[gear_count - 1].teeth);
24132001f49Smrg
24232001f49Smrg	if (!(strcmp (Buf1, "GTOOTHDEPTH")))
24332001f49Smrg	  LoadReal (&g[gear_count - 1].tooth_depth);
24432001f49Smrg
24532001f49Smrg	if (!(strcmp (Buf1, "GCOLOR")))
24632001f49Smrg	  LoadTriplet (g[gear_count - 1].color);
24732001f49Smrg
24832001f49Smrg	if (!(strcmp (Buf1, "GAXLE")))
24932001f49Smrg	  LoadText (g[gear_count - 1].axle_name);
25032001f49Smrg
25132001f49Smrg	if (!(strcmp (Buf1, "GPOSITION")))
25232001f49Smrg	  LoadInteger (&g[gear_count - 1].relative_position);
25332001f49Smrg
25432001f49Smrg	if (!(strcmp (Buf1, "BELTNAME")))
25532001f49Smrg	{
25632001f49Smrg	    LoadText (b[belt_count].name);
25732001f49Smrg	    belt_count++;
25832001f49Smrg	}
25932001f49Smrg
26032001f49Smrg	if (!(strcmp (Buf1, "GEAR1NAME")))
26132001f49Smrg	  LoadText (b[belt_count - 1].gear1_name);
26232001f49Smrg
26332001f49Smrg	if (!(strcmp (Buf1, "GEAR2NAME")))
26432001f49Smrg	  LoadText (b[belt_count - 1].gear2_name);
26532001f49Smrg    }
26632001f49Smrg    while (Buf1[0] != 0);
26732001f49Smrg
26832001f49Smrg    number_of_gears = gear_count;
26932001f49Smrg    number_of_axles = axle_count;
27032001f49Smrg    number_of_belts = belt_count;
27132001f49Smrg
27232001f49Smrg    for (i = 0; i < number_of_gears; i++)
27332001f49Smrg    {
27432001f49Smrg	g[i].axis = -1;
27532001f49Smrg	g[i].direction = 0;
27632001f49Smrg	g[i].angular_velocity = 0.0;
27732001f49Smrg    }
27832001f49Smrg
27932001f49Smrg    fclose (mainfile);
28032001f49Smrg}
28132001f49Smrg
28232001f49Smrg
28332001f49Smrgstatic void
28432001f49Smrgaxle (GLint j, GLfloat radius, GLfloat length)
28532001f49Smrg{
28632001f49Smrg    GLfloat angle, rad, incr = 10.0 * M_PI / 180.0;
28732001f49Smrg
28832001f49Smrg    /* draw main cylinder */
28932001f49Smrg    glBegin (GL_QUADS);
29032001f49Smrg    for (angle = 0.0; angle < 360.0; angle += 5.0)
29132001f49Smrg    {
29232001f49Smrg	rad = angle * M_PI / 180.0;
29332001f49Smrg	glNormal3f (cos (rad), sin (rad), 0.0);
29432001f49Smrg	glVertex3f (radius * cos (rad), radius * sin (rad), length / 2);
29532001f49Smrg	glVertex3f (radius * cos (rad), radius * sin (rad), -length / 2);
29632001f49Smrg	glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), -length / 2);
29732001f49Smrg	glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), length / 2);
29832001f49Smrg    }
29932001f49Smrg    glEnd ();
30032001f49Smrg
30132001f49Smrg    /* draw front face */
30232001f49Smrg    glNormal3f (0.0, 0.0, 1.0);
30332001f49Smrg    glBegin (GL_TRIANGLES);
30432001f49Smrg    for (angle = 0.0; angle < 360.0; angle += 5.0)
30532001f49Smrg    {
30632001f49Smrg	rad = angle * M_PI / 180.0;
30732001f49Smrg	glVertex3f (0.0, 0.0, length / 2);
30832001f49Smrg      	glVertex3f (radius * cos (rad), radius * sin (rad), length / 2);
30932001f49Smrg	glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), length / 2);
31032001f49Smrg	glVertex3f (0.0, 0.0, length / 2);
31132001f49Smrg    }
31232001f49Smrg    glEnd ();
31332001f49Smrg
31432001f49Smrg    /* draw back face */
31532001f49Smrg    glNormal3f (0.0, 0.0, -1.0);
31632001f49Smrg    glBegin (GL_TRIANGLES);
31732001f49Smrg    for (angle = 0.0; angle <= 360.0; angle += 5.0)
31832001f49Smrg    {
31932001f49Smrg	rad = angle * M_PI / 180.0;
32032001f49Smrg	glVertex3f (0.0, 0.0, -length / 2);
32132001f49Smrg	glVertex3f (radius * cos (rad), radius * sin (rad), -length / 2);
32232001f49Smrg	glVertex3f (radius * cos (rad + incr), radius * sin (rad + incr), -length / 2);
32332001f49Smrg	glVertex3f (0.0, 0.0, -length / 2);
32432001f49Smrg    }
32532001f49Smrg    glEnd ();
32632001f49Smrg}
32732001f49Smrg
32832001f49Smrg
32932001f49Smrg
33032001f49Smrgstatic void
33132001f49Smrggear (GLint j, char type[], GLfloat radius, GLfloat width,
33232001f49Smrg      GLint teeth, GLfloat tooth_depth)
33332001f49Smrg{
33432001f49Smrg    GLint i;
33532001f49Smrg    GLfloat r1, r2_front, r2_back;
33632001f49Smrg    GLfloat angle, da;
33732001f49Smrg    GLfloat u, v, len, fraction = 0.5;
33832001f49Smrg    GLfloat n = 1.0;
33932001f49Smrg
34032001f49Smrg    r1 = radius - tooth_depth;
34132001f49Smrg    r2_front = r2_back = radius;
34232001f49Smrg
34332001f49Smrg    fraction = 0.5;
34432001f49Smrg    n = 1.0;
34532001f49Smrg
34632001f49Smrg    da = 2.0 * M_PI / teeth / 4.0;
34732001f49Smrg    if (!(strcmp (type, "BEVEL")))
34832001f49Smrg    {
34932001f49Smrg        if (g[j].face)
35032001f49Smrg            r2_front = radius - width;
35132001f49Smrg        else
35232001f49Smrg            r2_back = radius - width;
35332001f49Smrg    }
35432001f49Smrg
35532001f49Smrg    /* draw front face */
35632001f49Smrg	glNormal3f (0.0, 0.0, 1.0 * n);
35732001f49Smrg	glBegin (GL_QUAD_STRIP);
35832001f49Smrg	for (i = 0; i <= teeth; i++)
35932001f49Smrg	{
36032001f49Smrg	    angle = i * 2.0 * M_PI / teeth;
36132001f49Smrg	    glVertex3f (0.0, 0.0, width * fraction);
36232001f49Smrg	    glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
36332001f49Smrg	    glVertex3f (0.0, 0.0, width * fraction);
36432001f49Smrg	    glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
36532001f49Smrg	}
36632001f49Smrg	glEnd ();
36732001f49Smrg
36832001f49Smrg    /* draw front sides of teeth */
36932001f49Smrg	glNormal3f (0.0, 0.0, 1.0 * n);
37032001f49Smrg	glBegin (GL_QUADS);
37132001f49Smrg	da = 2.0 * M_PI / teeth / 4.0;
37232001f49Smrg	for (i = 0; i < teeth; i++)
37332001f49Smrg	{
37432001f49Smrg	    angle = i * 2.0 * M_PI / teeth;
37532001f49Smrg	    glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
37632001f49Smrg	    glVertex3f (r2_front * cos (angle + da), r2_front * sin (angle + da), width * fraction);
37732001f49Smrg	    glVertex3f (r2_front * cos (angle + 2 * da), r2_front * sin (angle + 2 * da), width * fraction);
37832001f49Smrg	    glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
37932001f49Smrg	}
38032001f49Smrg	glEnd ();
38132001f49Smrg
38232001f49Smrg    /* draw back face */
38332001f49Smrg    glNormal3f (0.0, 0.0, -1.0 * n);
38432001f49Smrg    glBegin (GL_QUAD_STRIP);
38532001f49Smrg    for (i = 0; i <= teeth; i++)
38632001f49Smrg    {
38732001f49Smrg	angle = i * 2.0 * M_PI / teeth;
38832001f49Smrg	glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
38932001f49Smrg	glVertex3f (0.0, 0.0, -width * fraction);
39032001f49Smrg	glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
39132001f49Smrg	glVertex3f (0.0, 0.0, -width * fraction);
39232001f49Smrg    }
39332001f49Smrg    glEnd ();
39432001f49Smrg
39532001f49Smrg    /* draw back sides of teeth */
39632001f49Smrg    glNormal3f (0.0, 0.0, -1.0 * n);
39732001f49Smrg    glBegin (GL_QUADS);
39832001f49Smrg    da = 2.0 * M_PI / teeth / 4.0;
39932001f49Smrg    for (i = 0; i < teeth; i++)
40032001f49Smrg    {
40132001f49Smrg	angle = i * 2.0 * M_PI / teeth;
40232001f49Smrg	glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
40332001f49Smrg	glVertex3f (r2_back * cos (angle + 2 * da), r2_back * sin (angle + 2 * da), -width * fraction);
40432001f49Smrg	glVertex3f (r2_back * cos (angle + da), r2_back * sin (angle + da), -width * fraction);
40532001f49Smrg	glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
40632001f49Smrg    }
40732001f49Smrg    glEnd ();
40832001f49Smrg
40932001f49Smrg
41032001f49Smrg    /* draw outward faces of teeth. The visible faces are the backfaces, for testing purposes */
41132001f49Smrg	glBegin (GL_QUAD_STRIP);
41232001f49Smrg	for (i = 0; i < teeth; i++)
41332001f49Smrg	{
41432001f49Smrg	    angle = i * 2.0 * M_PI / teeth;
41532001f49Smrg
41632001f49Smrg	    glNormal3f (-cos (angle - 0.5*da), -sin (angle - 0.5*da), 0.0);
41732001f49Smrg	    glVertex3f (r1 * cos (angle), r1 * sin (angle), -width * fraction);
41832001f49Smrg	    glVertex3f (r1 * cos (angle), r1 * sin (angle), width * fraction);
41932001f49Smrg	    u = (r2_front+r2_back)/2.0 * cos (angle + da) - r1 * cos (angle);
42032001f49Smrg	    v = (r2_front+r2_back)/2.0 * sin (angle + da) - r1 * sin (angle);
42132001f49Smrg	    len = sqrt (u * u + v * v);
42232001f49Smrg	    u /= len;
42332001f49Smrg	    v /= len;
42432001f49Smrg	    glNormal3f (-v, u, 0.0);
42532001f49Smrg	    glVertex3f (r2_back * cos (angle + da), r2_back * sin (angle + da), -width * fraction);
42632001f49Smrg	    glVertex3f (r2_front * cos (angle + da), r2_front * sin (angle + da), width * fraction);
42732001f49Smrg	    glNormal3f (-cos (angle + 1.5*da), -sin (angle + 1.5*da), 0.0);
42832001f49Smrg	    glVertex3f (r2_back * cos (angle + 2 * da), r2_back * sin (angle + 2 * da), -width * fraction);
42932001f49Smrg	    glVertex3f (r2_front * cos (angle + 2 * da), r2_front * sin (angle + 2 * da), width * fraction);
43032001f49Smrg	    u = r1 * cos (angle + 3 * da) - (r2_front+r2_back)/2.0 * cos (angle + 2 * da);
43132001f49Smrg	    v = r1 * sin (angle + 3 * da) - (r2_front+r2_back)/2.0 * sin (angle + 2 * da);
43232001f49Smrg	    len = sqrt (u * u + v * v);
43332001f49Smrg	    u /= len;
43432001f49Smrg	    v /= len;
43532001f49Smrg	    glNormal3f (-v, u, 0.0);
43632001f49Smrg	    glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), -width * fraction);
43732001f49Smrg	    glVertex3f (r1 * cos (angle + 3 * da), r1 * sin (angle + 3 * da), width * fraction);
43832001f49Smrg	    glNormal3f (-cos (angle + 3.5*da), -sin (angle + 3.5*da), 0.0);
43932001f49Smrg	}
44032001f49Smrg
44132001f49Smrg    glNormal3f (-cos (-0.5*da), -sin (-0.5*da), 0.0);
44232001f49Smrg    glVertex3f (r1 * cos (0), r1 * sin (0), -width * fraction);
44332001f49Smrg    glVertex3f (r1 * cos (0), r1 * sin (0), width * fraction);
44432001f49Smrg    glEnd ();
44532001f49Smrg}
44632001f49Smrg
44732001f49Smrg
44832001f49Smrgstatic void
44932001f49Smrgbelt (struct GEAR g1, struct GEAR g2)
45032001f49Smrg{
45132001f49Smrg    GLfloat D, alpha, phi, angle, incr, width;
45232001f49Smrg    GLint indexes[3] =
45332001f49Smrg    {
45432001f49Smrg       0, 0, 0
45532001f49Smrg    };
45632001f49Smrg
45732001f49Smrg    GLfloat col[3] =
45832001f49Smrg    {
45932001f49Smrg       0.0, 0.0, 0.0
46032001f49Smrg    };
46132001f49Smrg
46232001f49Smrg    width = min (g1.width, g2.width);
46332001f49Smrg    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));
46432001f49Smrg    alpha = acos ((g2.position[0] - g1.position[0]) / D);
46532001f49Smrg    phi = acos ((g1.radius - g2.radius) / D);
46632001f49Smrg    glBegin (GL_QUADS);
46732001f49Smrg    glColor3fv (col);
46832001f49Smrg    glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
46932001f49Smrg    incr = 1.2 * 360.0 / g1.teeth * M_PI / 180.00;
47032001f49Smrg    for (angle = alpha + phi; angle <= 2 * M_PI - phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.00)
47132001f49Smrg    {
47232001f49Smrg	glNormal3f (cos (angle), sin (angle), 0.0);
47332001f49Smrg	glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), width * 0.5);
47432001f49Smrg	glVertex3f (g1.radius * cos (angle), g1.radius * sin (angle), -width * 0.5);
47532001f49Smrg	glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), -width * 0.5);
47632001f49Smrg	glVertex3f (g1.radius * cos (angle + incr), g1.radius * sin (angle + incr), width * 0.5);
47732001f49Smrg    }
47832001f49Smrg    glEnd ();
47932001f49Smrg    glBegin (GL_QUADS);
48032001f49Smrg    glColor3fv (col);
48132001f49Smrg    glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
48232001f49Smrg    incr = 1.2 * 360.0 / g2.teeth * M_PI / 180.00;
48332001f49Smrg    for (angle = -phi + alpha; angle <= phi + alpha; angle += 360.0 / g1.teeth * M_PI / 180.0)
48432001f49Smrg    {
48532001f49Smrg	glNormal3f (cos (angle), sin (angle), 0.0);
48632001f49Smrg	glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * 0.5);
48732001f49Smrg	glVertex3f (g2.radius * cos (angle) + g2.position[0] - g1.position[0], g2.radius * sin (angle) + g2.position[1] - g1.position[1], width * -0.5);
48832001f49Smrg	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);
48932001f49Smrg	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);
49032001f49Smrg    }
49132001f49Smrg    glEnd ();
49232001f49Smrg
49332001f49Smrg    glBegin (GL_QUADS);
49432001f49Smrg    glColor3fv (col);
49532001f49Smrg    glMaterialiv (GL_FRONT, GL_COLOR_INDEXES, indexes);
49632001f49Smrg    glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * 0.5);
49732001f49Smrg    glVertex3f (g1.radius * cos (alpha + phi), g1.radius * sin (alpha + phi), width * -0.5);
49832001f49Smrg    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);
49932001f49Smrg    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);
50032001f49Smrg    glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * 0.5);
50132001f49Smrg    glVertex3f (g1.radius * cos (alpha - phi), g1.radius * sin (alpha - phi), width * -0.5);
50232001f49Smrg    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);
50332001f49Smrg    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);
50432001f49Smrg    glEnd ();
50532001f49Smrg}
50632001f49Smrg
50732001f49Smrg
50832001f49Smrgstatic int
50932001f49Smrgaxle_find (char axle_name[])
51032001f49Smrg{
51132001f49Smrg    int i;
51232001f49Smrg
51332001f49Smrg    for (i = 0; i < number_of_axles; i++)
51432001f49Smrg    {
51532001f49Smrg	if (!(strcmp (axle_name, a[i].name)))
51632001f49Smrg           break;
51732001f49Smrg    }
51832001f49Smrg    return i;
51932001f49Smrg}
52032001f49Smrg
52132001f49Smrg
52232001f49Smrgstatic int
52332001f49Smrggear_find (char gear_name[])
52432001f49Smrg{
52532001f49Smrg    int i;
52632001f49Smrg
52732001f49Smrg    for (i = 0; i < number_of_gears; i++)
52832001f49Smrg    {
52932001f49Smrg	if (!(strcmp (gear_name, g[i].name)))
53032001f49Smrg           break;
53132001f49Smrg    }
53232001f49Smrg    return i;
53332001f49Smrg}
53432001f49Smrg
53532001f49Smrg
53632001f49Smrgstatic void
53732001f49Smrgprocess (void)
53832001f49Smrg{
53932001f49Smrg    GLfloat x, y, z, D, dist;
54032001f49Smrg    GLint axle_index, i, j, g1, g2, k;
54132001f49Smrg
54232001f49Smrg    for (i = 0; i < number_of_gears; i++)
54332001f49Smrg    {
54432001f49Smrg	x = 0.0;
54532001f49Smrg	y = 0.0;
54632001f49Smrg	z = 0.0;
54732001f49Smrg	axle_index = axle_find (g[i].axle_name);
54832001f49Smrg	g[i].axis = a[axle_index].axis;
54932001f49Smrg	g[i].motored = a[axle_index].motored;
55032001f49Smrg	if (a[axle_index].motored)
55132001f49Smrg	{
55232001f49Smrg	    g[i].direction = a[axle_index].direction;
55332001f49Smrg	    g[i].angular_velocity = a[axle_index].angular_velocity;
55432001f49Smrg	}
55532001f49Smrg	if (g[i].axis == 0)
55632001f49Smrg           x = 1.0;
55732001f49Smrg        else if (g[i].axis == 1)
55832001f49Smrg           y = 1.0;
55932001f49Smrg        else
56032001f49Smrg           z = 1.0;
56132001f49Smrg
56232001f49Smrg	g[i].position[0] = a[axle_index].position[0] + x * g[i].relative_position;
56332001f49Smrg	g[i].position[1] = a[axle_index].position[1] + y * g[i].relative_position;
56432001f49Smrg	g[i].position[2] = a[axle_index].position[2] + z * g[i].relative_position;
56532001f49Smrg    }
56632001f49Smrg
56732001f49Smrg    for (k = 0; k < number_of_axles; k++)
56832001f49Smrg    {
56932001f49Smrg	for (i = 0; i < number_of_gears - 1; i++)
57032001f49Smrg	{
57132001f49Smrg	    for (j = 0; j < number_of_gears; j++)
57232001f49Smrg	    {
57332001f49Smrg		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))
57432001f49Smrg		{
57532001f49Smrg		    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));
57632001f49Smrg		    if (D < 1.1 * (g[i].radius - g[i].tooth_depth + g[j].radius - g[j].tooth_depth))
57732001f49Smrg		    {
57832001f49Smrg			printf ("Gear %s and %s are too close to each other.", g[i].name, g[j].name);
57932001f49Smrg			exit (1);
58032001f49Smrg		    }
58132001f49Smrg
58232001f49Smrg		    if (g[i].axis == 0)
58332001f49Smrg		    {
58432001f49Smrg			dist = g[i].position[0] - g[j].position[0];
58532001f49Smrg		    }
58632001f49Smrg		    else if (g[i].axis == 1)
58732001f49Smrg		    {
58832001f49Smrg			dist = g[i].position[1] - g[j].position[1];
58932001f49Smrg		    }
59032001f49Smrg		    else
59132001f49Smrg                       dist = g[i].position[2] - g[j].position[2];
59232001f49Smrg
59332001f49Smrg		    dist = fabs (dist);
59432001f49Smrg
59532001f49Smrg		    if (dist < (g[i].width / 2 + g[j].width / 2))
59632001f49Smrg		    {
59732001f49Smrg			if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * (g[i].radius + g[j].radius)))
59832001f49Smrg			{
59932001f49Smrg			    axle_index = axle_find (g[j].axle_name);
60032001f49Smrg			    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))
60132001f49Smrg			    {
60232001f49Smrg				printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
60332001f49Smrg				exit (1);
60432001f49Smrg			    }
60532001f49Smrg
60632001f49Smrg			    g[j].motored = (a[axle_index].motored = 1);
60732001f49Smrg			    g[j].direction = (a[axle_index].direction = -g[i].direction);
60832001f49Smrg			    a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth;
60932001f49Smrg			    g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius);
61032001f49Smrg			}
61132001f49Smrg
61232001f49Smrg			if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * (g[i].radius + g[j].radius)))
61332001f49Smrg			{
61432001f49Smrg			    axle_index = axle_find (g[i].axle_name);
61532001f49Smrg			    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))
61632001f49Smrg			    {
61732001f49Smrg				printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
61832001f49Smrg				exit (1);
61932001f49Smrg			    }
62032001f49Smrg
62132001f49Smrg			    g[i].motored = (a[axle_index].motored = 1);
62232001f49Smrg			    g[i].direction = (a[axle_index].direction = -g[j].direction);
62332001f49Smrg			    a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth;
62432001f49Smrg			    g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius);
62532001f49Smrg
62632001f49Smrg			}
62732001f49Smrg		    }
62832001f49Smrg		}
62932001f49Smrg
63032001f49Smrg		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))
63132001f49Smrg		{
63232001f49Smrg		    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));
63332001f49Smrg		    if ((g[i].motored) && (!(g[j].motored)) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius)))
63432001f49Smrg		    {
63532001f49Smrg			axle_index = axle_find (g[j].axle_name);
63632001f49Smrg			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))
63732001f49Smrg			{
63832001f49Smrg			    printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
63932001f49Smrg			    exit (1);
64032001f49Smrg			}
64132001f49Smrg			g[j].motored = (a[axle_index].motored = 1);
64232001f49Smrg			g[j].direction = (a[axle_index].direction = -g[i].direction);
64332001f49Smrg			a[axle_index].angular_velocity = g[i].angular_velocity * g[i].teeth / g[j].teeth;
64432001f49Smrg			g[j].angular_velocity = (a[axle_index].angular_velocity *= g[i].radius / g[j].radius);
64532001f49Smrg		    }
64632001f49Smrg
64732001f49Smrg
64832001f49Smrg		    if ((!(g[i].motored)) && (g[j].motored) && (D < 0.95 * sqrt (g[i].radius * g[i].radius + g[j].radius * g[j].radius)))
64932001f49Smrg		    {
65032001f49Smrg			axle_index = axle_find (g[i].axle_name);
65132001f49Smrg			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))
65232001f49Smrg			{
65332001f49Smrg			    printf ("Error in tooth linkage of gears %s and %s.", g[i].name, g[j].name);
65432001f49Smrg			    exit (1);
65532001f49Smrg			}
65632001f49Smrg			g[i].motored = (a[axle_index].motored = 1);
65732001f49Smrg			g[i].direction = (a[axle_index].direction = -g[j].direction);
65832001f49Smrg			a[axle_index].angular_velocity = g[j].angular_velocity * g[j].teeth / g[i].teeth;
65932001f49Smrg			g[i].angular_velocity = (a[axle_index].angular_velocity *= g[j].radius / g[i].radius);
66032001f49Smrg		    }
66132001f49Smrg		}
66232001f49Smrg	    }
66332001f49Smrg	}
66432001f49Smrg
66532001f49Smrg	for (i = 0; i < number_of_gears; i++)
66632001f49Smrg	{
66732001f49Smrg	    axle_index = axle_find (g[i].axle_name);
66832001f49Smrg	    g[i].motored = a[axle_index].motored;
66932001f49Smrg	    if (a[axle_index].motored)
67032001f49Smrg	    {
67132001f49Smrg		g[i].direction = a[axle_index].direction;
67232001f49Smrg		g[i].angular_velocity = a[axle_index].angular_velocity;
67332001f49Smrg	    }
67432001f49Smrg	}
67532001f49Smrg
67632001f49Smrg	for (i = 0; i < number_of_belts; i++)
67732001f49Smrg	{
67832001f49Smrg	    g1 = gear_find (b[i].gear1_name);
67932001f49Smrg	    g2 = gear_find (b[i].gear2_name);
68032001f49Smrg	    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));
68132001f49Smrg	    if (!((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL"))))
68232001f49Smrg	    {
68332001f49Smrg		printf ("Belt %s invalid.", b[i].name);
68432001f49Smrg		exit (1);
68532001f49Smrg	    }
68632001f49Smrg
68732001f49Smrg	    if ((g[g1].axis == g[g2].axis) && (!strcmp (g[g1].type, g[g2].type)) && (!strcmp (g[g1].type, "NORMAL")))
68832001f49Smrg	    {
68932001f49Smrg	      /*
69032001f49Smrg	         if((g[g1].motored)&&(g[g2].motored))
69132001f49Smrg	         if(g[g2].angular_velocity!=(g[g1].angular_velocity*g[g1].radius/g[g2].radius))
69232001f49Smrg	         {
69332001f49Smrg	         printf("Error in belt linkage of gears %s and %s".,g[g1].name,g[g2].name);
69432001f49Smrg	         exit(1);
69532001f49Smrg	         }
69632001f49Smrg              */
69732001f49Smrg               if (g[g1].axis == 0)
69832001f49Smrg                  {
69932001f49Smrg		    dist = g[g1].position[0] - g[g2].position[0];
70032001f49Smrg		}
70132001f49Smrg		else if (g[i].axis == 1)
70232001f49Smrg		{
70332001f49Smrg		    dist = g[g1].position[1] - g[g2].position[1];
70432001f49Smrg		}
70532001f49Smrg		else
70632001f49Smrg                   dist = g[g1].position[2] - g[g2].position[2];
70732001f49Smrg
70832001f49Smrg		dist = fabs (dist);
70932001f49Smrg
71032001f49Smrg		if (dist > (g[g1].width / 2 + g[g2].width / 2))
71132001f49Smrg		{
71232001f49Smrg		    printf ("Belt %s invalid.", b[i].name);
71332001f49Smrg		    exit (1);
71432001f49Smrg		}
71532001f49Smrg
71632001f49Smrg		if (dist < (g[g1].width / 2 + g[g2].width / 2))
71732001f49Smrg		{
71832001f49Smrg		    if (D < g[g1].radius + g[g2].radius)
71932001f49Smrg		    {
72032001f49Smrg			printf ("Gears %s and %s too close to be linked with belts", g[g1].name, g[g2].name);
72132001f49Smrg			exit (1);
72232001f49Smrg		    }
72332001f49Smrg
72432001f49Smrg		    if ((g[g1].motored) && (!(g[g2].motored)))
72532001f49Smrg		    {
72632001f49Smrg			axle_index = axle_find (g[g2].axle_name);
72732001f49Smrg			g[g2].motored = (a[axle_index].motored = 1);
72832001f49Smrg			g[g2].direction = (a[axle_index].direction = g[g1].direction);
72932001f49Smrg			g[g2].angular_velocity = (a[axle_index].angular_velocity = g[g1].angular_velocity * g[g1].radius / g[g2].radius);
73032001f49Smrg		    }
73132001f49Smrg
73232001f49Smrg		    if ((!(g[g1].motored)) && (g[g2].motored))
73332001f49Smrg		    {
73432001f49Smrg			axle_index = axle_find (g[g1].axle_name);
73532001f49Smrg			g[g1].motored = (a[axle_index].motored = 1);
73632001f49Smrg			g[g1].direction = (a[axle_index].direction = g[g2].direction);
73732001f49Smrg			g[g1].angular_velocity = (a[axle_index].angular_velocity = g[g2].angular_velocity * g[g2].radius / g[g1].radius);
73832001f49Smrg		    }
73932001f49Smrg		}
74032001f49Smrg	    }
74132001f49Smrg	}
74232001f49Smrg
74332001f49Smrg	for (i = 0; i < number_of_gears; i++)
74432001f49Smrg	{
74532001f49Smrg	    axle_index = axle_find (g[i].axle_name);
74632001f49Smrg	    g[i].motored = a[axle_index].motored;
74732001f49Smrg	    if (a[axle_index].motored)
74832001f49Smrg	    {
74932001f49Smrg		g[i].direction = a[axle_index].direction;
75032001f49Smrg		g[i].angular_velocity = a[axle_index].angular_velocity;
75132001f49Smrg	    }
75232001f49Smrg	}
75332001f49Smrg    }
75432001f49Smrg}
75532001f49Smrg
75632001f49Smrg
75732001f49Smrg
75832001f49SmrgGLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 10.0;
75932001f49Smrg
76032001f49Smrg
76132001f49Smrgstatic void
76232001f49Smrgdraw (void)
76332001f49Smrg{
76432001f49Smrg    int i;
76532001f49Smrg    GLfloat x, y, z;
76632001f49Smrg    int index;
76732001f49Smrg
76832001f49Smrg    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
76932001f49Smrg
77032001f49Smrg    glPushMatrix ();
77132001f49Smrg    glRotatef (view_rotx, 1.0, 0.0, 0.0);
77232001f49Smrg    glRotatef (view_roty, 0.0, 1.0, 0.0);
77332001f49Smrg    glRotatef (view_rotz, 0.0, 0.0, 1.0);
77432001f49Smrg
77532001f49Smrg    for (i = 0; i < number_of_gears; i++)
77632001f49Smrg    {
77732001f49Smrg	x = 0.0;
77832001f49Smrg	y = 0.0;
77932001f49Smrg	z = 0.0;
78032001f49Smrg	glPushMatrix ();
78132001f49Smrg/*glTranslatef( -3.0, -2.0, 0.0 );*/
78232001f49Smrg	glTranslatef (g[i].position[0], g[i].position[1], g[i].position[2]);
78332001f49Smrg	if (g[i].axis == 0)
78432001f49Smrg           y = 1.0;
78532001f49Smrg        else if (g[i].axis == 1)
78632001f49Smrg           x = 1.0;
78732001f49Smrg        else
78832001f49Smrg           z = 1.0;
78932001f49Smrg
79032001f49Smrg	if (z != 1.0)
79132001f49Smrg           glRotatef (90.0, x, y, z);
79232001f49Smrg
79332001f49Smrg	glRotatef (g[i].direction * g[i].angle, 0.0, 0.0, 1.0);
79432001f49Smrg	glCallList (g[i].id);
79532001f49Smrg	glPopMatrix ();
79632001f49Smrg    }
79732001f49Smrg
79832001f49Smrg    for (i = 0; i < number_of_axles; i++)
79932001f49Smrg    {
80032001f49Smrg	x = 0.0;
80132001f49Smrg	y = 0.0;
80232001f49Smrg	z = 0.0;
80332001f49Smrg	glPushMatrix ();
80432001f49Smrg	glTranslatef (a[i].position[0], a[i].position[1], a[i].position[2]);
80532001f49Smrg	if (a[i].axis == 0)
80632001f49Smrg           y = 1.0;
80732001f49Smrg        else if (a[i].axis == 1)
80832001f49Smrg           x = 1.0;
80932001f49Smrg        else
81032001f49Smrg           z = 1.0;
81132001f49Smrg
81232001f49Smrg	if (z != 1.0)
81332001f49Smrg           glRotatef (90.0, x, y, z);
81432001f49Smrg
81532001f49Smrg	glCallList (a[i].id);
81632001f49Smrg	glPopMatrix ();
81732001f49Smrg    }
81832001f49Smrg
81932001f49Smrg    for (i = 0; i < number_of_belts; i++)
82032001f49Smrg    {
82132001f49Smrg	x = 0.0;
82232001f49Smrg	y = 0.0;
82332001f49Smrg	z = 0.0;
82432001f49Smrg	glPushMatrix ();
82532001f49Smrg	index = gear_find (b[i].gear1_name);
82632001f49Smrg	glTranslatef (g[index].position[0], g[index].position[1], g[index].position[2]);
82732001f49Smrg	if (g[index].axis == 0)
82832001f49Smrg           y = 1.0;
82932001f49Smrg        else if (g[index].axis == 1)
83032001f49Smrg           x = 1.0;
83132001f49Smrg        else
83232001f49Smrg           z = 1.0;
83332001f49Smrg
83432001f49Smrg	if (z != 1.0)
83532001f49Smrg           glRotatef (90.0, x, y, z);
83632001f49Smrg
83732001f49Smrg	glCallList (b[i].id);
83832001f49Smrg	glPopMatrix ();
83932001f49Smrg    }
84032001f49Smrg
84132001f49Smrg    glPopMatrix ();
84232001f49Smrg    glutSwapBuffers ();
84332001f49Smrg
84432001f49Smrg    {
84532001f49Smrg	GLint t = glutGet(GLUT_ELAPSED_TIME);
84632001f49Smrg	Frames++;
84732001f49Smrg	if (t - T0 >= 5000) {
84832001f49Smrg	    GLfloat seconds = (t - T0) / 1000.0;
84932001f49Smrg	    GLfloat fps = Frames / seconds;
85032001f49Smrg	    printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
85132001f49Smrg            fflush(stdout);
85232001f49Smrg	    T0 = t;
85332001f49Smrg	    Frames = 0;
85432001f49Smrg	}
85532001f49Smrg    }
85632001f49Smrg}
85732001f49Smrg
85832001f49Smrg
85932001f49Smrgstatic void
86032001f49Smrgidle (void)
86132001f49Smrg{
86232001f49Smrg    int i;
86332001f49Smrg    static double t0 = -1.;
86432001f49Smrg    double dt, t = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
86532001f49Smrg    if (t0 < 0.0)
86632001f49Smrg       t0 = t;
86732001f49Smrg    dt = t - t0;
86832001f49Smrg    t0 = t;
86932001f49Smrg    for (i = 0; i < number_of_gears; i++)
87032001f49Smrg      g[i].angle += g[i].angular_velocity * dt;
87132001f49Smrg    glutPostRedisplay();
87232001f49Smrg}
87332001f49Smrg
87432001f49Smrg
87532001f49Smrg
87632001f49Smrg
87732001f49Smrg/* change view angle, exit upon ESC */
87832001f49Smrgstatic void
87932001f49Smrgkey (unsigned char k, int x, int y)
88032001f49Smrg{
88132001f49Smrg    switch (k)
88232001f49Smrg    {
88332001f49Smrg    case 'x':
88432001f49Smrg	view_rotx += 5.0;
88532001f49Smrg        break;
88632001f49Smrg    case 'X':
88732001f49Smrg	view_rotx -= 5.0;
88832001f49Smrg        break;
88932001f49Smrg    case 'y':
89032001f49Smrg	view_roty += 5.0;
89132001f49Smrg        break;
89232001f49Smrg    case 'Y':
89332001f49Smrg	view_roty -= 5.0;
89432001f49Smrg        break;
89532001f49Smrg    case 'z':
89632001f49Smrg	view_rotz += 5.0;
89732001f49Smrg        break;
89832001f49Smrg    case 'Z':
89932001f49Smrg	view_rotz -= 5.0;
90032001f49Smrg        break;
90132001f49Smrg    case 0x1B:
90232001f49Smrg	exit(0);
90332001f49Smrg    }
90432001f49Smrg}
90532001f49Smrg
90632001f49Smrg
90732001f49Smrg
90832001f49Smrg
90932001f49Smrg/* new window size or exposure */
91032001f49Smrgstatic void
91132001f49Smrgreshape (int width, int height)
91232001f49Smrg{
91332001f49Smrg    glViewport (0, 0, (GLint) width, (GLint) height);
91432001f49Smrg    glMatrixMode (GL_PROJECTION);
91532001f49Smrg    glLoadIdentity ();
91632001f49Smrg    if (width > height)
91732001f49Smrg    {
91832001f49Smrg	GLfloat w = (GLfloat) width / (GLfloat) height;
91932001f49Smrg	glFrustum (-w, w, -1.0, 1.0, 5.0, 60.0);
92032001f49Smrg    }
92132001f49Smrg    else
92232001f49Smrg    {
92332001f49Smrg	GLfloat h = (GLfloat) height / (GLfloat) width;
92432001f49Smrg	glFrustum (-1.0, 1.0, -h, h, 5.0, 60.0);
92532001f49Smrg    }
92632001f49Smrg
92732001f49Smrg    glMatrixMode (GL_MODELVIEW);
92832001f49Smrg    glLoadIdentity ();
92932001f49Smrg    glTranslatef (0.0, 0.0, -40.0);
93032001f49Smrg    glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
93132001f49Smrg}
93232001f49Smrg
93332001f49Smrg
93432001f49Smrg
93532001f49Smrgstatic void
93632001f49Smrginit (void)
93732001f49Smrg{
93832001f49Smrg    GLfloat matShine = 20.00F;
93932001f49Smrg    const GLfloat light0Pos[4] =
94032001f49Smrg    {
94132001f49Smrg       0.70F, 0.70F, 1.25F, 0.50F
94232001f49Smrg    };
94332001f49Smrg    int i;
94432001f49Smrg
94532001f49Smrg    glShadeModel(GL_FLAT);
94632001f49Smrg    glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
94732001f49Smrg
94832001f49Smrg    glClearColor (background[0], background[1], background[2], 1.0F);
94932001f49Smrg    glClearIndex ((GLfloat) 0.0);
95032001f49Smrg
95132001f49Smrg    glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, matShine);
95232001f49Smrg    glLightfv (GL_LIGHT0, GL_POSITION, light0Pos);
95332001f49Smrg    glEnable (GL_LIGHT0);
95432001f49Smrg
95532001f49Smrg    glEnable (GL_LIGHTING);
95632001f49Smrg    glEnable (GL_DEPTH_TEST);
95732001f49Smrg    for (i = 0; i < number_of_gears; i++)
95832001f49Smrg      g[i].angle = 0.0;
95932001f49Smrg
96032001f49Smrg    for (i = 0; i < number_of_gears; i++)
96132001f49Smrg    {
96232001f49Smrg	g[i].id = glGenLists (1);
96332001f49Smrg	glNewList (g[i].id, GL_COMPILE);
96432001f49Smrg	glColor3fv (g[i].color);
96532001f49Smrg	glMaterialfv (GL_FRONT, GL_SPECULAR, g[i].color);
96632001f49Smrg	gear (i, g[i].type, g[i].radius, g[i].width, g[i].teeth, g[i].tooth_depth);
96732001f49Smrg	glEndList ();
96832001f49Smrg    }
96932001f49Smrg
97032001f49Smrg    for (i = 0; i < number_of_axles; i++)
97132001f49Smrg    {
97232001f49Smrg	a[i].id = glGenLists (1);
97332001f49Smrg	glNewList (a[i].id, GL_COMPILE);
97432001f49Smrg	glColor3fv (a[i].color);
97532001f49Smrg	glMaterialfv (GL_FRONT, GL_SPECULAR, a[i].color);
97632001f49Smrg	axle (i, a[i].radius, a[i].length);
97732001f49Smrg	glEndList ();
97832001f49Smrg    }
97932001f49Smrg
98032001f49Smrg    for (i = 0; i < number_of_belts; i++)
98132001f49Smrg    {
98232001f49Smrg	b[i].id = glGenLists (1);
98332001f49Smrg	glNewList (b[i].id, GL_COMPILE);
98432001f49Smrg	belt (g[gear_find (b[i].gear1_name)], g[gear_find (b[i].gear2_name)]);
98532001f49Smrg	glEndList ();
98632001f49Smrg    }
98732001f49Smrg
98832001f49Smrg    glEnable (GL_COLOR_MATERIAL);
98932001f49Smrg}
99032001f49Smrg
99132001f49Smrg
99232001f49Smrg
99332001f49Smrgint
99432001f49Smrgmain (int argc, char *argv[])
99532001f49Smrg{
99632001f49Smrg    char *file;
99732001f49Smrg
99832001f49Smrg    glutInitWindowSize(640,480);
99932001f49Smrg    glutInit(&argc, argv);
100032001f49Smrg    glutInitDisplayMode (GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE );
100132001f49Smrg
100232001f49Smrg    if (glutCreateWindow ("Gear Train Simulation") == GL_FALSE)
100332001f49Smrg      exit (1);
100432001f49Smrg
100532001f49Smrg    if (argc < 2)
100632001f49Smrg       file = DEMOS_DATA_DIR "geartrain.dat";
100732001f49Smrg    else
100832001f49Smrg       file = argv[1];
100932001f49Smrg
101032001f49Smrg    getdata (file);
101132001f49Smrg    process ();
101232001f49Smrg    init ();
101332001f49Smrg
101432001f49Smrg    glutDisplayFunc (draw);
101532001f49Smrg    glutReshapeFunc (reshape);
101632001f49Smrg    glutKeyboardFunc (key);
101732001f49Smrg    glutIdleFunc (idle);
101832001f49Smrg    glutMainLoop ();
101932001f49Smrg    return 0;
102032001f49Smrg}
1021