progs/egl/opengles2: Add es2gears demo
authorKristian Høgsberg <krh@bitplanet.net>
Mon, 3 May 2010 15:29:11 +0000 (11:29 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 4 May 2010 01:21:58 +0000 (21:21 -0400)
Because every subdirectory under progs has to have a version of gears.

progs/egl/opengles2/Makefile
progs/egl/opengles2/es2gears.c [new file with mode: 0644]

index 1ee2af241271d4537fea826b0da0fa25e76840b4..89feb34acc1d90796c909710a1dff7cd7dbcb7b4 100644 (file)
@@ -6,7 +6,9 @@ include $(TOP)/configs/current
 
 INCLUDE_DIRS = \
        -I$(TOP)/include \
-       $(X11_CFLAGS)
+       -I$(TOP)/progs/egl/eglut \
+       $(X11_CFLAGS) \
+
 
 HEADERS = $(TOP)/include/GLES/egl.h
 
@@ -18,11 +20,12 @@ ES2_LIB_DEPS = \
 
 ES2_LIBS = \
        -L$(TOP)/$(LIB_DIR) -lEGL \
-       -L$(TOP)/$(LIB_DIR) -lGLESv2 $(LIBDRM_LIB) $(X11_LIBS)
+       -L$(TOP)/$(LIB_DIR) -lGLESv2 $(LIBDRM_LIB) $(X11_LIBS) \
 
 PROGRAMS = \
        es2_info \
-       tri
+       tri \
+       es2gears
 
 
 .c.o:
@@ -43,7 +46,8 @@ es2_info: es2_info.o $(ES2_LIB_DEPS)
 tri: tri.o $(ES2_LIB_DEPS)
        $(CC) $(CFLAGS) tri.o $(ES2_LIBS) -o $@
 
-
+es2gears: es2gears.o $(ES2_LIB_DEPS)
+       $(CC) $(CFLAGS) es2gears.o ../eglut/libeglut-x11.a $(ES2_LIBS) -lm -o $@
 
 clean:
        rm -f *.o *~
diff --git a/progs/egl/opengles2/es2gears.c b/progs/egl/opengles2/es2gears.c
new file mode 100644 (file)
index 0000000..8e7a3e5
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Ported to GLES2.
+ * Kristian Høgsberg <krh@bitplanet.net>
+ * May 3, 2010
+ */
+
+/*
+ * Command line options:
+ *    -info      print GL implementation information
+ *
+ */
+
+
+#define GL_GLEXT_PROTOTYPES
+#define EGL_EGLEXT_PROTOTYPES
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "eglut.h"
+
+struct gear {
+   GLfloat *vertices;
+   GLuint vbo;
+   int count;
+};
+
+static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+static struct gear *gear1, *gear2, *gear3;
+static GLfloat angle = 0.0;
+static GLuint proj_location, light_location, color_location;
+static GLfloat proj[16];
+
+static GLfloat *
+vert(GLfloat *p, GLfloat x, GLfloat y, GLfloat z, GLfloat *n)
+{
+   p[0] = x;
+   p[1] = y;
+   p[2] = z;
+   p[3] = n[0];
+   p[4] = n[1];
+   p[5] = n[2];
+
+   return p + 6;
+}
+
+/*  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 struct gear *
+gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+     GLint teeth, GLfloat tooth_depth)
+{
+   GLint i;
+   GLfloat r0, r1, r2;
+   GLfloat da;
+   GLfloat *p, *v;
+   struct gear *gear;
+   double s[5], c[5];
+   GLfloat verts[3 * 14], normal[3];
+   const int tris_per_tooth = 20;
+
+   gear = malloc(sizeof *gear);
+   if (gear == NULL)
+      return NULL;
+
+   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;
+
+   gear->vertices = calloc(teeth * tris_per_tooth * 3 * 6,
+                          sizeof *gear->vertices);
+   s[4] = 0;
+   c[4] = 1;
+   v = gear->vertices;
+   for (i = 0; i < teeth; i++) {
+      s[0] = s[4];
+      c[0] = c[4];
+      sincos(i * 2.0 * M_PI / teeth + da, &s[1], &c[1]);
+      sincos(i * 2.0 * M_PI / teeth + da * 2, &s[2], &c[2]);
+      sincos(i * 2.0 * M_PI / teeth + da * 3, &s[3], &c[3]);
+      sincos(i * 2.0 * M_PI / teeth + da * 4, &s[4], &c[4]);
+
+      normal[0] = 0.0;
+      normal[1] = 0.0;
+      normal[2] = 1.0;
+
+      v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
+
+      v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
+      v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal);
+      v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
+      v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal);
+      v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal);
+      v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal);
+      v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal);
+
+      v = vert(v, r0 * c[4], r0 * s[4], width * 0.5, normal);
+      v = vert(v, r0 * c[0], r0 * s[0], width * 0.5, normal);
+      v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
+      v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal);
+
+      normal[0] = 0.0;
+      normal[1] = 0.0;
+      normal[2] = -1.0;
+
+      v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
+
+      v = vert(v, r0 * c[4], r0 * s[4], -width * 0.5, normal);
+      v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
+      v = vert(v, r0 * c[0], r0 * s[0], -width * 0.5, normal);
+      v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal);
+      v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal);
+      v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal);
+      v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal);
+
+      v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
+
+      v = vert(v, r1 * c[0], r1 * s[0], width * 0.5, normal);
+      v = vert(v, r1 * c[0], r1 * s[0], -width * 0.5, normal);
+      v = vert(v, r2 * c[1], r2 * s[1], width * 0.5, normal);
+      v = vert(v, r2 * c[1], r2 * s[1], -width * 0.5, normal);
+      v = vert(v, r2 * c[2], r2 * s[2], width * 0.5, normal);
+      v = vert(v, r2 * c[2], r2 * s[2], -width * 0.5, normal);
+      v = vert(v, r1 * c[3], r1 * s[3], width * 0.5, normal);
+      v = vert(v, r1 * c[3], r1 * s[3], -width * 0.5, normal);
+      v = vert(v, r1 * c[4], r1 * s[4], width * 0.5, normal);
+      v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
+
+      v = vert(v, r1 * c[4], r1 * s[4], -width * 0.5, normal);
+   }
+
+   gear->count = (v - gear->vertices) / 6;
+
+   glGenBuffers(1, &gear->vbo);
+   glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+   glBufferData(GL_ARRAY_BUFFER, gear->count * 6 * 4,
+               gear->vertices, GL_STATIC_DRAW);
+
+   return gear;
+}
+
+static void
+multiply(GLfloat *m, const GLfloat *n)
+{
+   GLfloat tmp[16];
+   const GLfloat *row, *column;
+   div_t d;
+   int i, j;
+
+   for (i = 0; i < 16; i++) {
+      tmp[i] = 0;
+      d = div(i, 4);
+      row = n + d.quot * 4;
+      column = m + d.rem;
+      for (j = 0; j < 4; j++)
+        tmp[i] += row[j] * column[j * 4];
+   }
+   memcpy(m, &tmp, sizeof tmp);
+}
+
+static void
+rotate(GLfloat *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z)
+{
+   double s, c;
+
+   sincos(angle, &s, &c);
+   GLfloat r[16] = {
+      x * x * (1 - c) + c,     y * x * (1 - c) + z * s, x * z * (1 - c) - y * s, 0,
+      x * y * (1 - c) - z * s, y * y * (1 - c) + c,     y * z * (1 - c) + x * s, 0, 
+      x * z * (1 - c) + y * s, y * z * (1 - c) - x * s, z * z * (1 - c) + c,     0,
+      0, 0, 0, 1
+   };
+
+   multiply(m, r);
+}
+
+static void
+translate(GLfloat *m, GLfloat x, GLfloat y, GLfloat z)
+{
+   GLfloat t[16] = { 1, 0, 0, 0,  0, 1, 0, 0,  0, 0, 1, 0,  x, y, z, 1 };
+
+   multiply(m, t);
+}
+
+static const GLfloat light[3] = { 1.0, 1.0, -1.0 };
+       
+static void
+draw_gear(struct gear *gear, GLfloat *m,
+         GLfloat x, GLfloat y, GLfloat angle, const GLfloat *color)
+{
+   GLfloat tmp[16];
+
+   memcpy(tmp, m, sizeof tmp);
+   translate(tmp, x, y, 0);
+   rotate(tmp, 2 * M_PI * angle / 360.0, 0, 0, 1);
+   glUniformMatrix4fv(proj_location, 1, GL_FALSE, tmp);
+   glUniform3fv(light_location, 1, light);
+   glUniform4fv(color_location, 1, color);
+
+   glBindBuffer(GL_ARRAY_BUFFER, gear->vbo);
+
+   glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
+                        6 * sizeof(GLfloat), NULL);
+   glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
+                        6 * sizeof(GLfloat), (GLfloat *) 0 + 3);
+   glEnableVertexAttribArray(0);
+   glEnableVertexAttribArray(1);
+   glDrawArrays(GL_TRIANGLE_STRIP, 0, gear->count);
+}
+
+static void
+gears_draw(void)
+{
+   const static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 };
+   const static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 };
+   const static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };
+   GLfloat m[16];
+
+   glClearColor(0.0, 0.0, 0.0, 0.0);
+   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+   memcpy(m, proj, sizeof m);
+   rotate(m, 2 * M_PI * view_rotx / 360.0, 1, 0, 0);
+   rotate(m, 2 * M_PI * view_roty / 360.0, 0, 1, 0);
+   rotate(m, 2 * M_PI * view_rotz / 360.0, 0, 0, 1);
+
+   draw_gear(gear1, m, -3.0, -2.0, angle, red);
+   draw_gear(gear2, m, 3.1, -2.0, -2 * angle - 9.0, green);
+   draw_gear(gear3, m, -3.1, 4.2, -2 * angle - 25.0, blue);
+}
+
+/* new window size or exposure */
+static void
+gears_reshape(int width, int height)
+{
+   GLfloat ar, m[16] = {
+      1.0, 0.0, 0.0, 0.0,
+      0.0, 1.0, 0.0, 0.0,
+      0.0, 0.0, 0.1, 0.0,
+      0.0, 0.0, 0.0, 1.0,
+   };
+      
+   if (width < height)
+      ar = width;
+   else
+      ar = height;
+
+   m[0] = 0.1 * ar / width;
+   m[5] = 0.1 * ar / height;
+   memcpy(proj, m, sizeof proj);
+   glViewport(0, 0, (GLint) width, (GLint) height);
+}
+
+static void
+gears_special(int special)
+{
+   switch (special) {
+   case EGLUT_KEY_LEFT:
+      view_roty += 5.0;
+      break;
+   case EGLUT_KEY_RIGHT:
+      view_roty -= 5.0;
+      break;
+   case EGLUT_KEY_UP:
+      view_rotx += 5.0;
+      break;
+   case EGLUT_KEY_DOWN:
+      view_rotx -= 5.0;
+      break;
+   }
+}
+
+static void
+gears_idle(void)
+{
+   static double tRot0 = -1.0;
+   double dt, t = eglutGet(EGLUT_ELAPSED_TIME) / 1000.0;
+
+   if (tRot0 < 0.0)
+      tRot0 = t;
+   dt = t - tRot0;
+   tRot0 = t;
+
+   /* advance rotation for next frame */
+   angle += 70.0 * dt;  /* 70 degrees per second */
+   if (angle > 3600.0)
+      angle -= 3600.0;
+
+  eglutPostRedisplay();
+}
+
+static const char vertex_shader[] =
+   "uniform mat4 proj;\n"
+   "attribute vec4 position;\n"
+   "attribute vec4 normal;\n"
+   "varying vec3 rotated_normal;\n"
+   "varying vec3 rotated_position;\n"
+   "vec4 tmp;\n"
+   "void main()\n"
+   "{\n"
+   "   gl_Position = proj * position;\n"
+   "   rotated_position = gl_Position.xyz;\n"
+   "   tmp = proj * normal;\n"
+   "   rotated_normal = tmp.xyz;\n"
+   "}\n";
+
+ static const char fragment_shader[] =
+   //"precision mediump float;\n"
+   "uniform vec4 color;\n"
+   "uniform vec3 light;\n"
+   "varying vec3 rotated_normal;\n"
+   "varying vec3 rotated_position;\n"
+   "vec3 light_direction;\n"
+   "vec4 white = vec4(1.0, 1.0, 1.0, 1.0);\n"
+   "void main()\n"
+   "{\n"
+   "   light_direction = normalize(light - rotated_position);\n"
+   "   gl_FragColor = color + white * dot(light_direction, rotated_normal);\n"
+   "}\n";
+
+static void
+gears_init(void)
+{
+   GLuint v, f, program;
+   const char *p;
+   char msg[512];
+
+   glEnable(GL_CULL_FACE);
+   glEnable(GL_DEPTH_TEST);
+
+   p = vertex_shader;
+   v = glCreateShader(GL_VERTEX_SHADER);
+   glShaderSource(v, 1, &p, NULL);
+   glCompileShader(v);
+   glGetShaderInfoLog(v, sizeof msg, NULL, msg);
+   printf("vertex shader info: %s\n", msg);
+
+   p = fragment_shader;
+   f = glCreateShader(GL_FRAGMENT_SHADER);
+   glShaderSource(f, 1, &p, NULL);
+   glCompileShader(f);
+   glGetShaderInfoLog(f, sizeof msg, NULL, msg);
+   printf("fragment shader info: %s\n", msg);
+
+   program = glCreateProgram();
+   glAttachShader(program, v);
+   glAttachShader(program, f);
+   glBindAttribLocation(program, 0, "position");
+   glBindAttribLocation(program, 1, "normal");
+
+   glLinkProgram(program);
+   glGetProgramInfoLog(program, sizeof msg, NULL, msg);
+   printf("info: %s\n", msg);
+
+   glUseProgram(program);
+   proj_location = glGetUniformLocation(program, "proj");
+   light_location = glGetUniformLocation(program, "light");
+   color_location = glGetUniformLocation(program, "color");
+
+   /* make the gears */
+   gear1 = gear(1.0, 4.0, 1.0, 20, 0.7);
+   gear2 = gear(0.5, 2.0, 2.0, 10, 0.7);
+   gear3 = gear(1.3, 2.0, 0.5, 10, 0.7);
+}
+
+int
+main(int argc, char *argv[])
+{
+   eglutInitWindowSize(300, 300);
+   eglutInitAPIMask(EGLUT_OPENGL_ES2_BIT);
+   eglutInit(argc, argv);
+
+   eglutCreateWindow("es2gears");
+
+   eglutIdleFunc(gears_idle);
+   eglutReshapeFunc(gears_reshape);
+   eglutDisplayFunc(gears_draw);
+   eglutSpecialFunc(gears_special);
+
+   gears_init();
+
+   eglutMainLoop();
+
+   return 0;
+}