/* An example program showing how to set and use a depth buffer with an OpenGL * display. Use arrow keys to rotate, PgUp/PgDown to move closer/farther away. */ #include "allegro5/allegro.h" #include "allegro5/allegro_image.h" #include "allegro5/allegro_opengl.h" #include "allegro5/allegro_font.h" #include "common.c" struct camera { double xangle, yangle, zangle; double dist; }; struct camera camera = { 0.0, 0.0, 0.0, 20.0 }; double angle_speed = 5.0; double dist_speed = 1.0; GLuint tex; ALLEGRO_BITMAP *bmp; bool key[ALLEGRO_KEY_MAX]; static void set_camera_position(void) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 40.0); glTranslatef(0, 0, -camera.dist); glRotatef(camera.xangle, 1, 0, 0); glRotatef(camera.yangle, 0, 1, 0); glRotatef(camera.zangle, 0, 0, 1); glMatrixMode(GL_MODELVIEW); } static void keyboard(void) { if(key[ALLEGRO_KEY_LEFT]) camera.yangle += angle_speed; if(key[ALLEGRO_KEY_RIGHT]) camera.yangle -= angle_speed; if(key[ALLEGRO_KEY_UP]) camera.xangle += angle_speed; if(key[ALLEGRO_KEY_DOWN]) camera.xangle -= angle_speed; if(key[ALLEGRO_KEY_PGUP]) camera.dist -= dist_speed; if(key[ALLEGRO_KEY_PGDN]) camera.dist += dist_speed; } static void draw(void) { // Clear the RGB buffer and the depth buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Set the modelview matrix to be the identity matrix glLoadIdentity(); // Translate and rotate the object glTranslatef(-2.5, 0.0, 0.0); glRotatef(-30, 1.0, 0.0, 0.0); glRotatef(30, 0.0, 1.0, 0.0); glRotatef(30, 0.0, 0.0, 1.0); glColor3f(1.0, 0.0, 1.0); // Draw the sides of the three-sided pyramid glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex); glBegin(GL_TRIANGLE_FAN); glTexCoord2f(0, 0); glVertex3d(0, 4, 0); glTexCoord2f(1, 0); glVertex3d(0, -4, -4); glTexCoord2f(1, 1); glVertex3d(-4, -4, 4); glTexCoord2f(0, 1); glVertex3d(4, -4, 4); glTexCoord2f(1, 0); glVertex3d(0, -4, -4); glEnd(); glColor3f(0.0, 1.0, 1.0); // Draw the base of the pyramid glBegin(GL_TRIANGLES); glTexCoord2f(1, 0); glVertex3d(0, -4, -4); glTexCoord2f(0, 1); glVertex3d(4, -4, 4); glTexCoord2f(1, 1); glVertex3d(-4, -4, 4); glEnd(); glLoadIdentity(); glTranslatef(2.5, 0.0, 0.0); glRotatef(45, 1.0, 0.0, 0.0); glRotatef(45, 0.0, 1.0, 0.0); glRotatef(45, 0.0, 0.0, 1.0); glColor3f(0.0, 1.0, 0.0); glDisable(GL_TEXTURE_2D); // Draw the sides of the cube glBegin(GL_QUAD_STRIP); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glVertex3d(-3, 3, -3); glVertex3d(-3, -3, -3); glVertex3d(-3, 3, 3); glVertex3d(-3, -3, 3); glVertex3d(3, 3, 3); glVertex3d(3, -3, 3); glVertex3d(3, 3, -3); glVertex3d(3, -3, -3); glEnd(); glColor3f(0.0, 0.0, 1.0); // Draw the top of the cube glBegin(GL_QUADS); glVertex3d(-3, -3, -3); glVertex3d(3, -3, -3); glVertex3d(3, -3, 3); glVertex3d(-3, -3, 3); glEnd(); /* Bottom is texture-mapped */ glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3d(-3, 3, -3); glTexCoord2f(1, 0); glVertex3d(-3, 3, 3); glTexCoord2f(1, 1); glVertex3d(3, 3, 3); glTexCoord2f(0, 1); glVertex3d(3, 3, -3); glEnd(); } static void setup_textures(ALLEGRO_DISPLAY *display) { ALLEGRO_BITMAP *tmp_bmp; ALLEGRO_FONT *font; int w, h, depth; font = al_load_font("data/fixed_font.tga", 0, 0); if(!font) { abort_example("Error loading `data/fixed_font.tga'\n"); } tmp_bmp = al_load_bitmap("data/mysha.pcx"); if(!tmp_bmp) { abort_example("Error loading `data/mysha.pcx'\n"); } w = 128; h = 128; bmp = al_create_bitmap(w, h); al_set_target_bitmap(bmp); al_draw_scaled_bitmap(tmp_bmp, 0, 0, al_get_bitmap_width(bmp), al_get_bitmap_height(bmp), 0, 0, w, h, 0); depth = al_get_display_option(display, ALLEGRO_DEPTH_SIZE); if (!depth) al_draw_textf(font, al_map_rgb(255, 0, 0), 0, 5, 0, "No Z-buffer!"); else al_draw_textf(font, al_map_rgb(255, 0, 0), 0, 5, 0, "Z-buffer: %i bits", depth); al_set_target_backbuffer(display); al_destroy_bitmap(tmp_bmp); al_destroy_font(font); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL); tex = al_get_opengl_texture(bmp); } int main(void) { ALLEGRO_DISPLAY *display; ALLEGRO_EVENT_QUEUE *queue; ALLEGRO_TIMER *timer; ALLEGRO_EVENT event; if(!al_init()) { abort_example("Could not init Allegro.\n"); } al_init_image_addon(); al_init_font_addon(); al_install_keyboard(); al_set_new_display_flags(ALLEGRO_OPENGL); al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 16, ALLEGRO_SUGGEST); display = al_create_display(640, 480); if(!display) { abort_example("Could not create display.\n"); } timer = al_create_timer(1. / 60.); queue = al_create_event_queue(); al_register_event_source(queue,al_get_keyboard_event_source()); al_register_event_source(queue,al_get_display_event_source(display)); al_register_event_source(queue,al_get_timer_event_source(timer)); glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); setup_textures(display); al_start_timer(timer); while(true) { al_wait_for_event(queue, &event); switch(event.type) { case ALLEGRO_EVENT_DISPLAY_CLOSE: goto done; case ALLEGRO_EVENT_KEY_DOWN: if(event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) goto done; key[event.keyboard.keycode] = true; break; case ALLEGRO_EVENT_KEY_UP: key[event.keyboard.keycode] = false; break; case ALLEGRO_EVENT_TIMER: keyboard(); if(al_is_event_queue_empty(queue)) { set_camera_position(); draw(); al_flip_display(); } break; } } done: al_destroy_bitmap(bmp); return 0; }