diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2010-05-03 11:29:11 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2010-05-03 21:21:58 -0400 |
commit | 642839824e911a23fb863cd1983f2f61481530c9 (patch) | |
tree | 5309f409826e636878e6aae53a778d6f3088c975 /progs/egl/opengles2/es2gears.c | |
parent | e2ea69afef2eeeb31b73772c3bf8ef696dadbc17 (diff) |
progs/egl/opengles2: Add es2gears demo
Because every subdirectory under progs has to have a version of gears.
Diffstat (limited to 'progs/egl/opengles2/es2gears.c')
-rw-r--r-- | progs/egl/opengles2/es2gears.c | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/progs/egl/opengles2/es2gears.c b/progs/egl/opengles2/es2gears.c new file mode 100644 index 0000000000..8e7a3e5249 --- /dev/null +++ b/progs/egl/opengles2/es2gears.c @@ -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; +} |