132001f49Smrg/* 232001f49Smrg * Copyright (C) 2008 Tunsgten Graphics,Inc. All Rights Reserved. 332001f49Smrg */ 432001f49Smrg 532001f49Smrg/* 632001f49Smrg * Draw a lit, textured torus with X/EGL and OpenGL ES 1.x 732001f49Smrg * Brian Paul 832001f49Smrg * July 2008 932001f49Smrg */ 1032001f49Smrg 1132001f49Smrg 1232001f49Smrg#include <assert.h> 1332001f49Smrg#include <math.h> 1432001f49Smrg#include <stdlib.h> 1532001f49Smrg#include <stdio.h> 1632001f49Smrg#include <GLES/gl.h> 1732001f49Smrg 1832001f49Smrg#include "eglut.h" 1932001f49Smrg 2032001f49Smrgstatic const struct { 2132001f49Smrg GLenum internalFormat; 2232001f49Smrg const char *name; 2332001f49Smrg GLuint num_entries; 2432001f49Smrg GLuint size; 2532001f49Smrg} cpal_formats[] = { 2632001f49Smrg { GL_PALETTE4_RGB8_OES, "GL_PALETTE4_RGB8_OES", 16, 3 }, 2732001f49Smrg { GL_PALETTE4_RGBA8_OES, "GL_PALETTE4_RGBA8_OES", 16, 4 }, 2832001f49Smrg { GL_PALETTE4_R5_G6_B5_OES, "GL_PALETTE4_R5_G6_B5_OES", 16, 2 }, 2932001f49Smrg { GL_PALETTE4_RGBA4_OES, "GL_PALETTE4_RGBA4_OES", 16, 2 }, 3032001f49Smrg { GL_PALETTE4_RGB5_A1_OES, "GL_PALETTE4_RGB5_A1_OES", 16, 2 }, 3132001f49Smrg { GL_PALETTE8_RGB8_OES, "GL_PALETTE8_RGB8_OES", 256, 3 }, 3232001f49Smrg { GL_PALETTE8_RGBA8_OES, "GL_PALETTE8_RGBA8_OES", 256, 4 }, 3332001f49Smrg { GL_PALETTE8_R5_G6_B5_OES, "GL_PALETTE8_R5_G6_B5_OES", 256, 2 }, 3432001f49Smrg { GL_PALETTE8_RGBA4_OES, "GL_PALETTE8_RGBA4_OES", 256, 2 }, 3532001f49Smrg { GL_PALETTE8_RGB5_A1_OES, "GL_PALETTE8_RGB5_A1_OES", 256, 2 } 3632001f49Smrg}; 3732001f49Smrg#define NUM_CPAL_FORMATS (sizeof(cpal_formats) / sizeof(cpal_formats[0])) 3832001f49Smrg 3932001f49Smrgstatic GLfloat view_rotx = 0.0, view_roty = 0.0, view_rotz = 0.0; 4032001f49Smrgstatic GLint tex_format = NUM_CPAL_FORMATS; 4132001f49Smrgstatic GLboolean animate = GL_TRUE; 4232001f49Smrgstatic int win; 4332001f49Smrg 4432001f49Smrg 4532001f49Smrgstatic void 4632001f49SmrgNormal(GLfloat *n, GLfloat nx, GLfloat ny, GLfloat nz) 4732001f49Smrg{ 4832001f49Smrg n[0] = nx; 4932001f49Smrg n[1] = ny; 5032001f49Smrg n[2] = nz; 5132001f49Smrg} 5232001f49Smrg 5332001f49Smrgstatic void 5432001f49SmrgVertex(GLfloat *v, GLfloat vx, GLfloat vy, GLfloat vz) 5532001f49Smrg{ 5632001f49Smrg v[0] = vx; 5732001f49Smrg v[1] = vy; 5832001f49Smrg v[2] = vz; 5932001f49Smrg} 6032001f49Smrg 6132001f49Smrgstatic void 6232001f49SmrgTexcoord(GLfloat *v, GLfloat s, GLfloat t) 6332001f49Smrg{ 6432001f49Smrg v[0] = s; 6532001f49Smrg v[1] = t; 6632001f49Smrg} 6732001f49Smrg 6832001f49Smrg 6932001f49Smrg/* Borrowed from glut, adapted */ 7032001f49Smrgstatic void 7132001f49Smrgdraw_torus(GLfloat r, GLfloat R, GLint nsides, GLint rings) 7232001f49Smrg{ 7332001f49Smrg int i, j; 7432001f49Smrg GLfloat theta, phi, theta1; 7532001f49Smrg GLfloat cosTheta, sinTheta; 7632001f49Smrg GLfloat cosTheta1, sinTheta1; 7732001f49Smrg GLfloat ringDelta, sideDelta; 7832001f49Smrg GLfloat varray[100][3], narray[100][3], tarray[100][2]; 7932001f49Smrg int vcount; 8032001f49Smrg 8132001f49Smrg glVertexPointer(3, GL_FLOAT, 0, varray); 8232001f49Smrg glNormalPointer(GL_FLOAT, 0, narray); 8332001f49Smrg glTexCoordPointer(2, GL_FLOAT, 0, tarray); 8432001f49Smrg glEnableClientState(GL_VERTEX_ARRAY); 8532001f49Smrg glEnableClientState(GL_NORMAL_ARRAY); 8632001f49Smrg glEnableClientState(GL_TEXTURE_COORD_ARRAY); 8732001f49Smrg 8832001f49Smrg ringDelta = 2.0 * M_PI / rings; 8932001f49Smrg sideDelta = 2.0 * M_PI / nsides; 9032001f49Smrg 9132001f49Smrg theta = 0.0; 9232001f49Smrg cosTheta = 1.0; 9332001f49Smrg sinTheta = 0.0; 9432001f49Smrg for (i = rings - 1; i >= 0; i--) { 9532001f49Smrg theta1 = theta + ringDelta; 9632001f49Smrg cosTheta1 = cos(theta1); 9732001f49Smrg sinTheta1 = sin(theta1); 9832001f49Smrg 9932001f49Smrg vcount = 0; /* glBegin(GL_QUAD_STRIP); */ 10032001f49Smrg 10132001f49Smrg phi = 0.0; 10232001f49Smrg for (j = nsides; j >= 0; j--) { 10332001f49Smrg GLfloat s0, s1, t; 10432001f49Smrg GLfloat cosPhi, sinPhi, dist; 10532001f49Smrg 10632001f49Smrg phi += sideDelta; 10732001f49Smrg cosPhi = cos(phi); 10832001f49Smrg sinPhi = sin(phi); 10932001f49Smrg dist = R + r * cosPhi; 11032001f49Smrg 11132001f49Smrg s0 = 20.0 * theta / (2.0 * M_PI); 11232001f49Smrg s1 = 20.0 * theta1 / (2.0 * M_PI); 11332001f49Smrg t = 8.0 * phi / (2.0 * M_PI); 11432001f49Smrg 11532001f49Smrg Normal(narray[vcount], cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); 11632001f49Smrg Texcoord(tarray[vcount], s1, t); 11732001f49Smrg Vertex(varray[vcount], cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi); 11832001f49Smrg vcount++; 11932001f49Smrg 12032001f49Smrg Normal(narray[vcount], cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); 12132001f49Smrg Texcoord(tarray[vcount], s0, t); 12232001f49Smrg Vertex(varray[vcount], cosTheta * dist, -sinTheta * dist, r * sinPhi); 12332001f49Smrg vcount++; 12432001f49Smrg } 12532001f49Smrg 12632001f49Smrg /*glEnd();*/ 12732001f49Smrg assert(vcount <= 100); 12832001f49Smrg glDrawArrays(GL_TRIANGLE_STRIP, 0, vcount); 12932001f49Smrg 13032001f49Smrg theta = theta1; 13132001f49Smrg cosTheta = cosTheta1; 13232001f49Smrg sinTheta = sinTheta1; 13332001f49Smrg } 13432001f49Smrg 13532001f49Smrg glDisableClientState(GL_VERTEX_ARRAY); 13632001f49Smrg glDisableClientState(GL_NORMAL_ARRAY); 13732001f49Smrg glDisableClientState(GL_TEXTURE_COORD_ARRAY); 13832001f49Smrg} 13932001f49Smrg 14032001f49Smrg 14132001f49Smrgstatic void 14232001f49Smrgdraw(void) 14332001f49Smrg{ 14432001f49Smrg glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 14532001f49Smrg 14632001f49Smrg glPushMatrix(); 14732001f49Smrg glRotatef(view_rotx, 1, 0, 0); 14832001f49Smrg glRotatef(view_roty, 0, 1, 0); 14932001f49Smrg glRotatef(view_rotz, 0, 0, 1); 15032001f49Smrg glScalef(0.5, 0.5, 0.5); 15132001f49Smrg 15232001f49Smrg draw_torus(1.0, 3.0, 30, 60); 15332001f49Smrg 15432001f49Smrg glPopMatrix(); 15532001f49Smrg} 15632001f49Smrg 15732001f49Smrg 15832001f49Smrg/* new window size or exposure */ 15932001f49Smrgstatic void 16032001f49Smrgreshape(int width, int height) 16132001f49Smrg{ 16232001f49Smrg GLfloat ar = (GLfloat) width / (GLfloat) height; 16332001f49Smrg 16432001f49Smrg glViewport(0, 0, (GLint) width, (GLint) height); 16532001f49Smrg 16632001f49Smrg glMatrixMode(GL_PROJECTION); 16732001f49Smrg glLoadIdentity(); 16832001f49Smrg 16932001f49Smrg#ifdef GL_VERSION_ES_CM_1_0 17032001f49Smrg glFrustumf(-ar, ar, -1, 1, 5.0, 60.0); 17132001f49Smrg#else 17232001f49Smrg glFrustum(-ar, ar, -1, 1, 5.0, 60.0); 17332001f49Smrg#endif 17432001f49Smrg 17532001f49Smrg glMatrixMode(GL_MODELVIEW); 17632001f49Smrg glLoadIdentity(); 17732001f49Smrg glTranslatef(0.0, 0.0, -15.0); 17832001f49Smrg} 17932001f49Smrg 18032001f49Smrg 18132001f49Smrgstatic GLint 18232001f49Smrgmake_cpal_texture(GLint idx) 18332001f49Smrg{ 18432001f49Smrg#define SZ 64 18532001f49Smrg GLenum internalFormat = GL_PALETTE4_RGB8_OES + idx; 18632001f49Smrg GLenum Filter = GL_LINEAR; 18732001f49Smrg GLubyte palette[256 * 4 + SZ * SZ]; 18832001f49Smrg GLubyte *indices; 18932001f49Smrg GLsizei image_size; 19032001f49Smrg GLuint i, j; 19132001f49Smrg GLuint packed_indices = 0; 19232001f49Smrg 19332001f49Smrg assert(cpal_formats[idx].internalFormat == internalFormat); 19432001f49Smrg 19532001f49Smrg /* init palette */ 19632001f49Smrg switch (internalFormat) { 19732001f49Smrg case GL_PALETTE4_RGB8_OES: 19832001f49Smrg case GL_PALETTE8_RGB8_OES: 19932001f49Smrg /* first entry */ 20032001f49Smrg palette[0] = 255; 20132001f49Smrg palette[1] = 255; 20232001f49Smrg palette[2] = 255; 20332001f49Smrg /* second entry */ 20432001f49Smrg palette[3] = 127; 20532001f49Smrg palette[4] = 127; 20632001f49Smrg palette[5] = 127; 20732001f49Smrg break; 20832001f49Smrg case GL_PALETTE4_RGBA8_OES: 20932001f49Smrg case GL_PALETTE8_RGBA8_OES: 21032001f49Smrg /* first entry */ 21132001f49Smrg palette[0] = 255; 21232001f49Smrg palette[1] = 255; 21332001f49Smrg palette[2] = 255; 21432001f49Smrg palette[3] = 255; 21532001f49Smrg /* second entry */ 21632001f49Smrg palette[4] = 127; 21732001f49Smrg palette[5] = 127; 21832001f49Smrg palette[6] = 127; 21932001f49Smrg palette[7] = 255; 22032001f49Smrg break; 22132001f49Smrg case GL_PALETTE4_R5_G6_B5_OES: 22232001f49Smrg case GL_PALETTE8_R5_G6_B5_OES: 22332001f49Smrg { 22432001f49Smrg GLushort *pal = (GLushort *) palette; 22532001f49Smrg /* first entry */ 22632001f49Smrg pal[0] = (31 << 11 | 63 << 5 | 31); 22732001f49Smrg /* second entry */ 22832001f49Smrg pal[1] = (15 << 11 | 31 << 5 | 15); 22932001f49Smrg } 23032001f49Smrg break; 23132001f49Smrg case GL_PALETTE4_RGBA4_OES: 23232001f49Smrg case GL_PALETTE8_RGBA4_OES: 23332001f49Smrg { 23432001f49Smrg GLushort *pal = (GLushort *) palette; 23532001f49Smrg /* first entry */ 23632001f49Smrg pal[0] = (15 << 12 | 15 << 8 | 15 << 4 | 15); 23732001f49Smrg /* second entry */ 23832001f49Smrg pal[1] = (7 << 12 | 7 << 8 | 7 << 4 | 15); 23932001f49Smrg } 24032001f49Smrg break; 24132001f49Smrg case GL_PALETTE4_RGB5_A1_OES: 24232001f49Smrg case GL_PALETTE8_RGB5_A1_OES: 24332001f49Smrg { 24432001f49Smrg GLushort *pal = (GLushort *) palette; 24532001f49Smrg /* first entry */ 24632001f49Smrg pal[0] = (31 << 11 | 31 << 6 | 31 << 1 | 1); 24732001f49Smrg /* second entry */ 24832001f49Smrg pal[1] = (15 << 11 | 15 << 6 | 15 << 1 | 1); 24932001f49Smrg } 25032001f49Smrg break; 25132001f49Smrg } 25232001f49Smrg 25332001f49Smrg image_size = cpal_formats[idx].size * cpal_formats[idx].num_entries; 25432001f49Smrg indices = palette + image_size; 25532001f49Smrg for (i = 0; i < SZ; i++) { 25632001f49Smrg for (j = 0; j < SZ; j++) { 25732001f49Smrg GLfloat d; 25832001f49Smrg GLint index; 25932001f49Smrg d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2); 26032001f49Smrg d = sqrt(d); 26132001f49Smrg index = (d < SZ / 3) ? 0 : 1; 26232001f49Smrg 26332001f49Smrg if (cpal_formats[idx].num_entries == 16) { 26432001f49Smrg /* 4-bit indices packed in GLubyte */ 26532001f49Smrg packed_indices |= index << (4 * (1 - (j % 2))); 26632001f49Smrg if (j % 2) { 26732001f49Smrg *(indices + (i * SZ + j - 1) / 2) = packed_indices & 0xff; 26832001f49Smrg packed_indices = 0; 26932001f49Smrg image_size += 1; 27032001f49Smrg } 27132001f49Smrg } 27232001f49Smrg else { 27332001f49Smrg /* 8-bit indices */ 27432001f49Smrg *(indices + i * SZ + j) = index; 27532001f49Smrg image_size += 1; 27632001f49Smrg } 27732001f49Smrg } 27832001f49Smrg } 27932001f49Smrg 28032001f49Smrg glActiveTexture(GL_TEXTURE0); /* unit 0 */ 28132001f49Smrg glBindTexture(GL_TEXTURE_2D, 42); 28232001f49Smrg glCompressedTexImage2D(GL_TEXTURE_2D, 0, internalFormat, SZ, SZ, 0, 28332001f49Smrg image_size, palette); 28432001f49Smrg 28532001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter); 28632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter); 28732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 28832001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 28932001f49Smrg#undef SZ 29032001f49Smrg 29132001f49Smrg return image_size; 29232001f49Smrg} 29332001f49Smrg 29432001f49Smrg 29532001f49Smrgstatic GLint 29632001f49Smrgmake_texture(void) 29732001f49Smrg{ 29832001f49Smrg#define SZ 64 29932001f49Smrg GLenum Filter = GL_LINEAR; 30032001f49Smrg GLubyte image[SZ][SZ][4]; 30132001f49Smrg GLuint i, j; 30232001f49Smrg 30332001f49Smrg for (i = 0; i < SZ; i++) { 30432001f49Smrg for (j = 0; j < SZ; j++) { 30532001f49Smrg GLfloat d = (i - SZ/2) * (i - SZ/2) + (j - SZ/2) * (j - SZ/2); 30632001f49Smrg d = sqrt(d); 30732001f49Smrg if (d < SZ/3) { 30832001f49Smrg image[i][j][0] = 255; 30932001f49Smrg image[i][j][1] = 255; 31032001f49Smrg image[i][j][2] = 255; 31132001f49Smrg image[i][j][3] = 255; 31232001f49Smrg } 31332001f49Smrg else { 31432001f49Smrg image[i][j][0] = 127; 31532001f49Smrg image[i][j][1] = 127; 31632001f49Smrg image[i][j][2] = 127; 31732001f49Smrg image[i][j][3] = 255; 31832001f49Smrg } 31932001f49Smrg } 32032001f49Smrg } 32132001f49Smrg 32232001f49Smrg glActiveTexture(GL_TEXTURE0); /* unit 0 */ 32332001f49Smrg glBindTexture(GL_TEXTURE_2D, 42); 32432001f49Smrg glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SZ, SZ, 0, 32532001f49Smrg GL_RGBA, GL_UNSIGNED_BYTE, image); 32632001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, Filter); 32732001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, Filter); 32832001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 32932001f49Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 33032001f49Smrg#undef SZ 33132001f49Smrg 33232001f49Smrg return sizeof(image); 33332001f49Smrg} 33432001f49Smrg 33532001f49Smrg 33632001f49Smrg 33732001f49Smrgstatic void 33832001f49Smrginit(void) 33932001f49Smrg{ 34032001f49Smrg static const GLfloat red[4] = {1, 0, 0, 0}; 34132001f49Smrg static const GLfloat white[4] = {1.0, 1.0, 1.0, 1.0}; 34232001f49Smrg static const GLfloat diffuse[4] = {0.7, 0.7, 0.7, 1.0}; 34332001f49Smrg static const GLfloat specular[4] = {0.001, 0.001, 0.001, 1.0}; 34432001f49Smrg static const GLfloat pos[4] = {20, 20, 50, 1}; 34532001f49Smrg 34632001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red); 34732001f49Smrg glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, white); 34832001f49Smrg glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 9.0); 34932001f49Smrg 35032001f49Smrg glEnable(GL_LIGHTING); 35132001f49Smrg glEnable(GL_LIGHT0); 35232001f49Smrg glLightfv(GL_LIGHT0, GL_POSITION, pos); 35332001f49Smrg glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); 35432001f49Smrg glLightfv(GL_LIGHT0, GL_SPECULAR, specular); 35532001f49Smrg 35632001f49Smrg glClearColor(0.4, 0.4, 0.4, 0.0); 35732001f49Smrg glEnable(GL_DEPTH_TEST); 35832001f49Smrg 35932001f49Smrg make_texture(); 36032001f49Smrg glEnable(GL_TEXTURE_2D); 3617ec3b29aSmrg 3627ec3b29aSmrg /* Enable automatic normalizing to get proper lighting when torus is 3637ec3b29aSmrg * scaled down via glScalef 3647ec3b29aSmrg */ 3657ec3b29aSmrg glEnable(GL_NORMALIZE); 36632001f49Smrg} 36732001f49Smrg 36832001f49Smrg 36932001f49Smrgstatic void 37032001f49Smrgidle(void) 37132001f49Smrg{ 37232001f49Smrg if (animate) { 37332001f49Smrg view_rotx += 1.0; 37432001f49Smrg view_roty += 2.0; 37532001f49Smrg eglutPostRedisplay(); 37632001f49Smrg } 37732001f49Smrg} 37832001f49Smrg 37932001f49Smrgstatic void 38032001f49Smrgkey(unsigned char key) 38132001f49Smrg{ 38232001f49Smrg switch (key) { 38332001f49Smrg case ' ': 38432001f49Smrg animate = !animate; 38532001f49Smrg break; 38632001f49Smrg case 't': 38732001f49Smrg { 38832001f49Smrg GLint size; 38932001f49Smrg tex_format = (tex_format + 1) % (NUM_CPAL_FORMATS + 1); 39032001f49Smrg if (tex_format < NUM_CPAL_FORMATS) { 39132001f49Smrg size = make_cpal_texture(tex_format); 39232001f49Smrg printf("Using %s (%d bytes)\n", 39332001f49Smrg cpal_formats[tex_format].name, size); 39432001f49Smrg } 39532001f49Smrg else { 39632001f49Smrg size = make_texture(); 39732001f49Smrg printf("Using uncompressed texture (%d bytes)\n", size); 39832001f49Smrg } 39932001f49Smrg 40032001f49Smrg eglutPostRedisplay(); 40132001f49Smrg } 40232001f49Smrg break; 40332001f49Smrg case 27: 40432001f49Smrg eglutDestroyWindow(win); 40532001f49Smrg exit(0); 40632001f49Smrg break; 40732001f49Smrg default: 40832001f49Smrg break; 40932001f49Smrg } 41032001f49Smrg} 41132001f49Smrg 41232001f49Smrgstatic void 41332001f49Smrgspecial_key(int key) 41432001f49Smrg{ 41532001f49Smrg switch (key) { 41632001f49Smrg case EGLUT_KEY_LEFT: 41732001f49Smrg view_roty += 5.0; 41832001f49Smrg break; 41932001f49Smrg case EGLUT_KEY_RIGHT: 42032001f49Smrg view_roty -= 5.0; 42132001f49Smrg break; 42232001f49Smrg case EGLUT_KEY_UP: 42332001f49Smrg view_rotx += 5.0; 42432001f49Smrg break; 42532001f49Smrg case EGLUT_KEY_DOWN: 42632001f49Smrg view_rotx -= 5.0; 42732001f49Smrg break; 42832001f49Smrg default: 42932001f49Smrg break; 43032001f49Smrg } 43132001f49Smrg} 43232001f49Smrg 43332001f49Smrgint 43432001f49Smrgmain(int argc, char *argv[]) 43532001f49Smrg{ 43632001f49Smrg eglutInitWindowSize(300, 300); 43732001f49Smrg eglutInitAPIMask(EGLUT_OPENGL_ES1_BIT); 43832001f49Smrg eglutInit(argc, argv); 43932001f49Smrg 44032001f49Smrg win = eglutCreateWindow("torus"); 44132001f49Smrg 44232001f49Smrg eglutIdleFunc(idle); 44332001f49Smrg eglutReshapeFunc(reshape); 44432001f49Smrg eglutDisplayFunc(draw); 44532001f49Smrg eglutKeyboardFunc(key); 44632001f49Smrg eglutSpecialFunc(special_key); 44732001f49Smrg 44832001f49Smrg init(); 44932001f49Smrg 45032001f49Smrg eglutMainLoop(); 45132001f49Smrg 45232001f49Smrg return 0; 45332001f49Smrg} 454