Add default version of glesgears.c

Source downloaded from:
https://community.khronos.org/t/glesgears/1278

Change-Id: I66d99b69db1b3a54eed1fe3302a6c0b30c0b3d44
diff --git a/opengl/glesgears.c b/opengl/glesgears.c
new file mode 100644
index 0000000..fae3233
--- /dev/null
+++ b/opengl/glesgears.c
@@ -0,0 +1,415 @@
+/*
+ * 3-D gear wheels.  This program is in the public domain.
+ *
+ * Command line options:
+ *    -info      print GL implementation information
+ *    -exit      automatically exit after 30 seconds
+ *
+ *
+ * Brian Paul
+ */
+
+/* Conversion to use vertex buffer objects by Michael J. Clark */
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "window.h"
+
+#define MAX_CONFIGS 10
+#define MAX_MODES 100
+
+
+#ifdef _WIN32
+  #define WIN32_LEAN_AND_MEAN 1
+  #include <windows.h>
+
+  static double
+  current_time(void)
+  {
+     DWORD tv;
+
+     tv = GetTickCount();
+     return (tv/1000.0);
+  }
+  
+#else
+  #include <sys/time.h>
+  #include <unistd.h>
+
+  /* return current time (in seconds) */
+  static double
+  current_time(void)
+  {
+     struct timeval tv;
+  #ifdef __VMS
+     (void) gettimeofday(&tv, NULL );
+  #else
+     struct timezone tz;
+     (void) gettimeofday(&tv, &tz);
+  #endif
+     return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
+  }
+#endif
+
+#include <GLES/gl.h>
+#include <GLES/egl.h>
+
+
+#ifndef M_PI
+#define M_PI 3.14159265
+#endif
+
+
+static GLint autoexit = 0;
+static GLfloat viewDist = 40.0;
+
+typedef struct {
+  GLfloat pos[3];
+  GLfloat norm[3];
+} vertex_t;
+
+typedef struct {
+  vertex_t *vertices;
+  GLshort *indices;
+  GLfloat color[4];
+  int nvertices, nindices;
+  GLuint ibo;
+} gear_t;
+
+static gear_t *red_gear;
+static gear_t *green_gear;
+static gear_t *blue_gear;
+
+/**
+
+  Draw a gear wheel.  You'll probably want to call this function when
+  building a display list since we do a lot of trig here.
+ 
+  Input:  inner_radius - radius of hole at center
+          outer_radius - radius at center of teeth
+          width - width of gear
+          teeth - number of teeth
+          tooth_depth - depth of tooth
+
+ **/
+
+static gear_t*
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth, GLfloat color[])
+{
+  GLint i, j;
+  GLfloat r0, r1, r2;
+  GLfloat ta, da;
+  GLfloat u1, v1, u2, v2, len;
+  GLfloat cos_ta, cos_ta_1da, cos_ta_2da, cos_ta_3da, cos_ta_4da;
+  GLfloat sin_ta, sin_ta_1da, sin_ta_2da, sin_ta_3da, sin_ta_4da;
+  GLshort ix0, ix1, ix2, ix3, ix4, ix5;
+  vertex_t *vt, *nm;
+  GLshort *ix;
+
+  gear_t *gear = calloc(1, sizeof(gear_t));
+  gear->nvertices = teeth * 40;
+  gear->nindices = teeth * 66 * 3;
+  gear->vertices = calloc(gear->nvertices, sizeof(vertex_t));
+  gear->indices = calloc(gear->nindices, sizeof(GLshort));
+  memcpy(&gear->color[0], &color[0], sizeof(GLfloat) * 4);
+
+  r0 = inner_radius;
+  r1 = outer_radius - tooth_depth / 2.0;
+  r2 = outer_radius + tooth_depth / 2.0;
+  da = 2.0 * M_PI / teeth / 4.0;
+
+  vt = gear->vertices;
+  nm = gear->vertices;
+  ix = gear->indices;
+
+#define VERTEX(x,y,z) ((vt->pos[0] = x),(vt->pos[1] = y),(vt->pos[2] = z), \
+                       (vt++ - gear->vertices))
+#define NORMAL(x,y,z) ((nm->norm[0] = x),(nm->norm[1] = y),(nm->norm[2] = z), \
+                       (nm++ - gear->vertices))
+#define INDEX(a,b,c) ((*ix++ = a),(*ix++ = b),(*ix++ = c))
+
+  for (i = 0; i < teeth; i++) {
+    ta = i * 2.0 * M_PI / teeth;
+
+    cos_ta = cos(ta);
+    cos_ta_1da = cos(ta + da);
+    cos_ta_2da = cos(ta + 2 * da);
+    cos_ta_3da = cos(ta + 3 * da);
+    cos_ta_4da = cos(ta + 4 * da);
+    sin_ta = sin(ta);
+    sin_ta_1da = sin(ta + da);
+    sin_ta_2da = sin(ta + 2 * da);
+    sin_ta_3da = sin(ta + 3 * da);
+    sin_ta_4da = sin(ta + 4 * da);
+               
+    u1 = r2 * cos_ta_1da - r1 * cos_ta;
+    v1 = r2 * sin_ta_1da - r1 * sin_ta;
+    len = sqrt(u1 * u1 + v1 * v1);
+    u1 /= len;
+    v1 /= len;
+    u2 = r1 * cos_ta_3da - r2 * cos_ta_2da;
+    v2 = r1 * sin_ta_3da - r2 * sin_ta_2da;
+
+    /* front face */
+    ix0 = VERTEX(r0 * cos_ta,          r0 * sin_ta,          width * 0.5);
+    ix1 = VERTEX(r1 * cos_ta,          r1 * sin_ta,          width * 0.5);
+    ix2 = VERTEX(r0 * cos_ta,          r0 * sin_ta,          width * 0.5);
+    ix3 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      width * 0.5);
+    ix4 = VERTEX(r0 * cos_ta_4da,      r0 * sin_ta_4da,      width * 0.5);
+    ix5 = VERTEX(r1 * cos_ta_4da,      r1 * sin_ta_4da,      width * 0.5);
+    for (j = 0; j < 6; j++) {
+      NORMAL(0.0,                  0.0,                  1.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+    INDEX(ix2, ix3, ix4);
+    INDEX(ix3, ix5, ix4);
+               
+    /* front sides of teeth */
+    ix0 = VERTEX(r1 * cos_ta,          r1 * sin_ta,          width * 0.5);
+    ix1 = VERTEX(r2 * cos_ta_1da,      r2 * sin_ta_1da,      width * 0.5);
+    ix2 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      width * 0.5);
+    ix3 = VERTEX(r2 * cos_ta_2da,      r2 * sin_ta_2da,      width * 0.5);
+    for (j = 0; j < 4; j++) {
+      NORMAL(0.0,                  0.0,                  1.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+
+    /* back face */
+    ix0 = VERTEX(r1 * cos_ta,          r1 * sin_ta,          -width * 0.5);
+    ix1 = VERTEX(r0 * cos_ta,          r0 * sin_ta,          -width * 0.5);
+    ix2 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      -width * 0.5);
+    ix3 = VERTEX(r0 * cos_ta,          r0 * sin_ta,          -width * 0.5);
+    ix4 = VERTEX(r1 * cos_ta_4da,      r1 * sin_ta_4da,      -width * 0.5);
+    ix5 = VERTEX(r0 * cos_ta_4da,      r0 * sin_ta_4da,      -width * 0.5);
+    for (j = 0; j < 6; j++) {
+      NORMAL(0.0,                  0.0,                  -1.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+    INDEX(ix2, ix3, ix4);
+    INDEX(ix3, ix5, ix4);
+               
+    /* back sides of teeth */
+    ix0 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      -width * 0.5);
+    ix1 = VERTEX(r2 * cos_ta_2da,      r2 * sin_ta_2da,      -width * 0.5);
+    ix2 = VERTEX(r1 * cos_ta,          r1 * sin_ta,          -width * 0.5);
+    ix3 = VERTEX(r2 * cos_ta_1da,      r2 * sin_ta_1da,      -width * 0.5);
+    for (j = 0; j < 4; j++) {
+      NORMAL(0.0,                  0.0,                  -1.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+               
+    /* draw outward faces of teeth */
+    ix0 = VERTEX(r1 * cos_ta,          r1 * sin_ta,          width * 0.5);
+    ix1 = VERTEX(r1 * cos_ta,          r1 * sin_ta,          -width * 0.5);
+    ix2 = VERTEX(r2 * cos_ta_1da,      r2 * sin_ta_1da,      width * 0.5);
+    ix3 = VERTEX(r2 * cos_ta_1da,      r2 * sin_ta_1da,      -width * 0.5);
+    for (j = 0; j < 4; j++) {
+      NORMAL(v1,                   -u1,                  0.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+    ix0 = VERTEX(r2 * cos_ta_1da,      r2 * sin_ta_1da,      width * 0.5);
+    ix1 = VERTEX(r2 * cos_ta_1da,      r2 * sin_ta_1da,      -width * 0.5);
+    ix2 = VERTEX(r2 * cos_ta_2da,      r2 * sin_ta_2da,      width * 0.5);
+    ix3 = VERTEX(r2 * cos_ta_2da,      r2 * sin_ta_2da,      -width * 0.5);
+    for (j = 0; j < 4; j++) {
+      NORMAL(cos_ta,               sin_ta,               0.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+    ix0 = VERTEX(r2 * cos_ta_2da,      r2 * sin_ta_2da,      width * 0.5);
+    ix1 = VERTEX(r2 * cos_ta_2da,      r2 * sin_ta_2da,      -width * 0.5);
+    ix2 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      width * 0.5);
+    ix3 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      -width * 0.5);
+    for (j = 0; j < 4; j++) {
+      NORMAL(v2,                   -u2,                  0.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+    ix0 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      width * 0.5);
+    ix1 = VERTEX(r1 * cos_ta_3da,      r1 * sin_ta_3da,      -width * 0.5);
+    ix2 = VERTEX(r1 * cos_ta_4da,      r1 * sin_ta_4da,      width * 0.5);
+    ix3 = VERTEX(r1 * cos_ta_4da,      r1 * sin_ta_4da,      -width * 0.5);
+    for (j = 0; j < 4; j++) {
+      NORMAL(cos_ta,               sin_ta,               0.0);
+    }
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+
+    /* draw inside radius cylinder */
+    ix0 = VERTEX(r0 * cos_ta,          r0 * sin_ta,          -width * 0.5);
+    ix1 = VERTEX(r0 * cos_ta,          r0 * sin_ta,          width * 0.5);
+    ix2 = VERTEX(r0 * cos_ta_4da,      r0 * sin_ta_4da,      -width * 0.5);
+    ix3 = VERTEX(r0 * cos_ta_4da,      r0 * sin_ta_4da,      width * 0.5);
+    NORMAL(-cos_ta,              -sin_ta,              0.0);
+    NORMAL(-cos_ta,              -sin_ta,              0.0);
+    NORMAL(-cos_ta_4da,          -sin_ta_4da,          0.0);
+    NORMAL(-cos_ta_4da,          -sin_ta_4da,          0.0);
+    INDEX(ix0, ix1, ix2);
+    INDEX(ix1, ix3, ix2);
+  }
+
+  return gear;
+}
+
+
+void draw_gear(gear_t* gear) {
+
+  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, gear->color);
+  glVertexPointer(3, GL_FLOAT, sizeof(vertex_t), gear->vertices[0].pos);
+  glNormalPointer(GL_FLOAT, sizeof(vertex_t), gear->vertices[0].norm);
+  glDrawElements(GL_TRIANGLES, gear->nindices/3, GL_UNSIGNED_SHORT,
+                   gear->indices);
+}
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static gear_t *gear1, *gear2, *gear3;
+static GLfloat angle = 0.0;
+
+static void
+draw(void)
+{
+  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glPushMatrix();
+
+    glTranslatef(0.0, 0.0, -viewDist);
+
+    glRotatef(view_rotx, 1.0, 0.0, 0.0);
+    glRotatef(view_roty, 0.0, 1.0, 0.0);
+    glRotatef(view_rotz, 0.0, 0.0, 1.0);
+
+    glPushMatrix();
+      glTranslatef(-3.0, -2.0, 0.0);
+      glRotatef(angle, 0.0, 0.0, 1.0);
+      draw_gear(gear1);
+    glPopMatrix();
+
+    glPushMatrix();
+      glTranslatef(3.1, -2.0, 0.0);
+      glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+      draw_gear(gear2);
+    glPopMatrix();
+
+    glPushMatrix();
+      glTranslatef(-3.1, 4.2, 0.0);
+      glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+      draw_gear(gear3);
+    glPopMatrix();
+
+  glPopMatrix();
+  glFinish();
+}
+
+
+/* new window size or exposure */
+static void
+reshape(int width, int height)
+{
+  GLfloat h = (GLfloat) height / (GLfloat) width;
+
+  glViewport(0, 0, (GLint) width, (GLint) height);
+  glMatrixMode(GL_PROJECTION);
+  glLoadIdentity();
+  glFrustumf(-1.0, 1.0, -h, h, 5.0, 200.0);
+  glMatrixMode(GL_MODELVIEW);
+}
+ 
+
+static void
+init(int argc, char *argv[])
+{
+  static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
+  static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0};
+  static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0};
+  static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0};
+  GLint i;
+
+  glLightfv(GL_LIGHT0, GL_POSITION, pos);
+  glEnable(GL_CULL_FACE);
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_DEPTH_TEST);
+
+  glShadeModel(GL_SMOOTH);
+
+  glEnableClientState(GL_NORMAL_ARRAY);
+  glEnableClientState(GL_VERTEX_ARRAY);
+
+  for ( i=1; i<argc; i++ ) {
+    if (strcmp(argv[i], "-info")==0) {
+      printf("GL_RENDERER   = %s
+", (char *) glGetString(GL_RENDERER));
+      printf("GL_VERSION    = %s
+", (char *) glGetString(GL_VERSION));
+      printf("GL_VENDOR     = %s
+", (char *) glGetString(GL_VENDOR));
+      printf("GL_EXTENSIONS = %s
+", (char *) glGetString(GL_EXTENSIONS));
+    }
+    else if ( strcmp(argv[i], "-exit")==0) {
+      autoexit = 30;
+      printf("Auto Exit after %i seconds.
+", autoexit );
+    }
+  }
+
+  /* make the gears */
+  gear1 = gear(1.0, 4.0, 1.0, 20, 0.7, red);
+  gear2 = gear(0.5, 2.0, 2.0, 10, 0.7, green);
+  gear3 = gear(1.3, 2.0, 0.5, 10, 0.7, blue);
+}
+
+static void run_gears(GLint ttr)
+{
+  double st = current_time();
+  double ct = st;
+  double seconds = st;
+  double fps;
+  int    frames = 0;
+       
+  while ((ttr == 0) ||(ct - st < ttr))
+  {
+    double tt = current_time();
+    double dt = tt - ct;
+    ct = tt;
+    
+    /* advance rotation for next frame */
+    angle += 70.0 * dt;  /* 70 degrees per second */
+    if (angle > 3600.0)
+          angle -= 3600.0;        
+    draw(); 
+    postEGLWindow();
+    frames++;
+    dt = ct - seconds;
+    if (dt >= 5.0) 
+	{
+      fps = frames / dt;
+	  printf("%d frames in %3.1f seconds = %6.3f FPS
+", frames, dt, fps);
+	  seconds = ct;
+	  frames = 0;
+    }
+  }       
+}
+
+int
+main(int argc, char *argv[])
+{
+    int width  = 300;
+    int height = 300;
+
+    createEGLWindow(width, height, "Gears");    
+    init(argc, argv);
+    reshape(width, height);
+    run_gears(autoexit);
+    return 0;
+}