Skip to content

Instantly share code, notes, and snippets.

@dolphin78
Last active June 6, 2022 09:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dolphin78/5eb9fa9024d7dcc222a656277bcb2677 to your computer and use it in GitHub Desktop.
Save dolphin78/5eb9fa9024d7dcc222a656277bcb2677 to your computer and use it in GitHub Desktop.
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <gf/gf.h>
#include <gf/gf3d.h>
#include <GLES/egl.h>
static gf_dev_t gdev;
static gf_dev_info_t gdev_info;
static gf_display_t display;
static gf_display_info_t display_info;
static gf_surface_t surfaces[2];
static gf_3d_target_t target;
static gf_context_t context;
static gf_layer_t layer;
static int width,height;
static EGLDisplay egl_disp;
static EGLConfig egl_config;
static EGLContext egl_ctx;
static EGLSurface egl_surf;
struct {
EGLint surface_type;
EGLint red_size;
EGLint green_size;
EGLint blue_size;
EGLint alpha_size;
EGLint samples;
EGLint config_id;
} egl_conf_attr;
struct {
EGLint render_buffer[2];
EGLint none;
} egl_surf_attr = {
.render_buffer = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER }, /* Ask for double-buffering */
.none = EGL_NONE /* End of list */
};
/* return current time (in seconds) */
static double current_time(void)
{
struct timeval tv;
struct timezone tz;
(void) gettimeofday(&tv, &tz);
return (double) tv.tv_sec + tv.tv_usec / 1000000.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;
/**
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)
{
// printf("BEFORE: draw_gear\n");
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);
// printf("AFTER: draw_gear\n");
}
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)
{
// printf("BEFORE: draw\n");
glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_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.1, -2.0, 0.0);
glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
draw_gear(gear2);
glPopMatrix();
glPushMatrix();
glTranslatef(-3.0, -2.0, 0.0);
glRotatef(angle, 0.0, 0.0, 1.0);
draw_gear(gear1);
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();
// printf("AFTER: draw\n");
}
/* 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};
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);
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION));
printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR));
printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS));
/* 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()
{
double st = current_time();
double ct = st;
double seconds = st;
double fps;
int frames = 0;
while (1)
{
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();
eglSwapBuffers(egl_disp, egl_surf);
frames++;
dt = ct - seconds;
if (dt >= 5.0)
{
fps = frames / dt;
printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, dt, fps);
seconds = ct;
frames = 0;
}
}
}
static void findEGLConfig() {
EGLConfig *egl_configs;
EGLint egl_num_configs;
EGLint val;
eglGetConfigs(egl_disp, NULL, 0, &egl_num_configs);
egl_configs = malloc(egl_num_configs * sizeof(*egl_configs));
eglGetConfigs(egl_disp, egl_configs, egl_num_configs, &egl_num_configs);
int i;
for (i=0;i<egl_num_configs;i++) {
/* Make sure the surface type matches that of your render target */
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_SURFACE_TYPE, &val);
if ((val & egl_conf_attr.surface_type) != egl_conf_attr.surface_type) {
printf("failed: Make sure the surface type matches that of your render target\n");
continue;
}
/* Make sure the renderable type has the OpenGL ES bit. */
eglGetConfigAttrib(egl_disp, egl_configs[i], EGL_RENDERABLE_TYPE, &val);
if (!(val & EGL_OPENGL_ES_BIT)) {
printf("Make sure the renderable type has the OpenGL ES bit.\n");
continue;
}
egl_config = egl_configs[i];
break;
}
printf("egl_num_configs: %d, curr_config: %d\n", egl_num_configs, i);
}
static int initGLES(int layerId, gf_sid_t srufaceId1, gf_sid_t srufaceId2)
{
if (gf_dev_attach(&gdev, GF_DEVICE_INDEX(0), &gdev_info) != GF_ERR_OK) {
printf("gf_dev_attach() failed\n");
return -1;
}
if (gf_display_attach(&display, gdev, 0, &display_info) != GF_ERR_OK) {
printf("gf_display_attach() failed\n");
return -1;
}
printf("%dX%d, refresh = %dHz\n", display_info.xres, display_info.yres, display_info.refresh);
printf("Number of layers: %d\n", display_info.nlayers);
width = display_info.xres;
height = display_info.yres;
egl_disp = eglGetDisplay(gdev);
if (egl_disp == EGL_NO_DISPLAY) {
fprintf(stderr, "eglGetDisplay() failed\n");
return -1;
}
int rc = eglInitialize(egl_disp, NULL, NULL);
if (rc != EGL_TRUE) {
printf("eglInitialize\n");
return -1;
}
findEGLConfig();
egl_ctx = eglCreateContext(egl_disp, egl_config, EGL_NO_CONTEXT, NULL);
printf("eglCreateContext created!\n");
if (gf_context_create(&context) != GF_ERR_OK) {
fprintf(stderr, "gf_context_create failed\n");
return -1;
}
if(gf_surface_attach_by_sid(&surfaces[0], gdev, srufaceId1) != GF_ERR_OK) {
printf("*** Error: gf_surface_attach_by_sid() failed!\n");
gf_dev_detach(gdev);
return -1;
}
if(gf_surface_attach_by_sid(&surfaces[1], gdev, srufaceId2) != GF_ERR_OK) {
printf("*** Error: gf_surface_attach_by_sid() failed!\n");
gf_dev_detach(gdev);
return -1;
}
if(gf_layer_attach(&layer, display, layerId, GF_LAYER_ATTACH_PASSIVE) != GF_ERR_OK) {
printf("*** Error: gf_layer_attach() failed!\n");
return -1;
}
gf_surface_info_t surfaceInfo;
gf_surface_get_info(surfaces[0], &surfaceInfo);
printf("Resolution: %dx%d, Format: %x, Flags: %x\n", surfaceInfo.w, surfaceInfo.h, surfaceInfo.format, surfaceInfo.flags);
if (gf_3d_target_create(&target, layer,
surfaces, 2, width, height, surfaceInfo.format) != GF_ERR_OK) {
fprintf(stderr, "Unable to create rendering target\n");
return NULL;
}
egl_surf = eglCreateWindowSurface(egl_disp, egl_config, target, (EGLint*)&egl_surf_attr);
printf("AFTER: eglCreateWindowSurface\n");
eglMakeCurrent(egl_disp, egl_surf, egl_surf, egl_ctx);
// rc = eglSwapInterval(egl_disp, 10);
// if (rc != EGL_TRUE) {
// printf("eglSwapInterval\n");
// return -1;
// }
/* We will use one vertex array for all of our rendering */
glEnableClientState(GL_VERTEX_ARRAY);
return 0;
}
int main(int argc, char** argv)
{
if(argc < 3) {
printf("*** Error: layer and surface IDs not specified!\n");
return -1;
}
int layerId = atoi(argv[1]);
gf_sid_t srufaceId1 = atoi(argv[2]);
gf_sid_t srufaceId2 = atoi(argv[3]);
initGLES(layerId, srufaceId1, srufaceId2);
init(argc, argv);
reshape(width, height);
run_gears();
printf("Exit gears\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment