-
-
Save dolphin78/5eb9fa9024d7dcc222a656277bcb2677 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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