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;
+}