#include #include #include #include #define M_PI 3.1415926535897932384626433832795029L #define M_PI_2 1.5707963267948966192313216916397514L # define timersub(a, b, result) \ do { \ (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ if ((result)->tv_usec < 0) { \ --(result)->tv_sec; \ (result)->tv_usec += 1000000; \ } \ } while (0) void idle(void); void animate(float dT); void display(void); void keyboard(unsigned char key, int x, int y); void init_sphere(unsigned int rings, unsigned int sectors); void draw_sphere(void); int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutCreateWindow("SinSphere"); glutIdleFunc(idle); glutKeyboardFunc(keyboard); glutDisplayFunc(display); init_sphere(10, 30); glutMainLoop(); return 0; } struct AnimationState { float time; float duration; float sphere_speed; float sphere_path_radius; float sphere_path_bobbing; float sphere_position[3]; }; static struct AnimationState animation = { 0., 5., /* play for 5 seconds */ 0.1, 3., 1., {1., 0., 0.} }; void animate(float dT) { if(animation.time < animation.duration) { animation.time += dT; animation.sphere_position[0] = animation.sphere_path_radius * cos(2*M_PI * animation.time * animation.sphere_speed); animation.sphere_position[1] = animation.sphere_path_bobbing * sin(2*M_PI * animation.time * 5 * animation.sphere_speed); animation.sphere_position[2] = animation.sphere_path_radius * sin(2*M_PI * animation.time * animation.sphere_speed); } } struct ViewState { float rotation; float rotation_step; }; static struct ViewState view = { 0., 0.1 }; void keyboard(unsigned char key, int x, int y) { switch(key) { case 'R': case 'r': /* restart animation */ animation.time = 0.; break; case '+': view.rotation += view.rotation_step; break; case '-': view.rotation -= view.rotation_step; break; } glutPostRedisplay(); } GLfloat *sphere_vertices_normals; unsigned int sphere_quads = 0; GLushort *sphere_indices; void init_sphere(unsigned int rings, unsigned int sectors) { float const R = 1./(float)(rings-1); float const S = 1./(float)(sectors-1); int r, s; sphere_vertices_normals = malloc(sizeof(GLfloat)*3 * rings*sectors); GLfloat *v = sphere_vertices_normals; for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) { float const y = sin( -M_PI_2 + M_PI * r * R ); float const x = cos(2*M_PI * s * S) * sin( M_PI * r * R ); float const z = sin(2*M_PI * s * S) * sin( M_PI * r * R ); v[0] = x; v[1] = y; v[2] = z; v+=3; } sphere_indices = malloc(sizeof(GLushort) * rings * sectors * 4); GLushort *i = sphere_indices; for(r = 0; r < rings; r++) for(s = 0; s < sectors; s++) { *i++ = r * sectors + s; *i++ = r * sectors + (s+1); *i++ = (r+1) * sectors + (s+1); *i++ = (r+1) * sectors + s; sphere_quads++; } } void draw_sphere() { glTranslatef(animation.sphere_position[0], animation.sphere_position[1], animation.sphere_position[2]); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glVertexPointer(3, GL_FLOAT, 0, sphere_vertices_normals); glNormalPointer(GL_FLOAT, 0, sphere_vertices_normals); glDrawElements(GL_QUADS, sphere_quads*4, GL_UNSIGNED_SHORT, sphere_indices); } void idle() { glutPostRedisplay(); } static GLfloat const light_pos[4] = {-1., 1., 1., 0.}; static GLfloat const light_color[4] = {1., 1., 1., 1.}; void display() { static struct timeval delta_T = {0., 0.}; struct timeval time_frame_begin, time_frame_end; int win_width, win_height; float win_aspect; gettimeofday(&time_frame_begin, 0); animate(delta_T.tv_sec + delta_T.tv_usec * 1.e-6); win_width = glutGet(GLUT_WINDOW_WIDTH); win_height = glutGet(GLUT_WINDOW_HEIGHT); win_aspect = (float)win_width/(float)win_height; glViewport(0, 0, win_width, win_height); glClearColor(0.6, 0.6, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-win_aspect, win_aspect, -1., 1., 1., 10.); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0,0,-5.5); glRotatef(view.rotation * 180./M_PI, 0, 1, 0); glLightfv(GL_LIGHT0, GL_POSITION, light_pos); glLightfv(GL_LIGHT0, GL_DIFFUSE, light_color); glPushMatrix(); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); draw_sphere(); glPopMatrix(); glutSwapBuffers(); gettimeofday(&time_frame_end, 0); timersub(&time_frame_end, &time_frame_begin, &delta_T); }