/* * Copyright 2011-2014 hasufell * * This file is part of a hasufell project. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation version 2 of the License only. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * @file gl_setup.c * Operations for setting up SDL and the OpenGL context. * @brief set up SDL/OpenGL */ #include "err.h" #include "filereader.h" #include "gl_draw.h" #include "gl_setup.h" #include "half_edge.h" #include #include #include /* * static function declaration */ static void init_opengl(void); static bool process_events(SDL_Window *win, SDL_GLContext glctx); static void reshape(SDL_Window *win); static bool process_window_events(SDL_Window *win, SDL_GLContext glctx, SDL_WindowEvent *win_event); static bool process_keypress(SDL_KeyboardEvent *key_event); static void gl_destroy(SDL_Window *win, SDL_GLContext glctx); /** * Sets the initial values to start the program. */ static void init_opengl(void) { glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glViewport(0, 0, 680, 480); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(CAMERA_ANGLE, (GLfloat) 640 / (GLfloat) 480, NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -5.0); } /** * Processes all sort of Events the SDL system catches. * * @param win the SDL window * @param glctx the OpenGL context * @return true if the app is still running, false if it should * terminate */ static bool process_events(SDL_Window *win, SDL_GLContext glctx) { SDL_Event e; bool running = true; while (SDL_PollEvent(&e)) if (e.type == SDL_QUIT) { running = false; } else if (e.type == SDL_WINDOWEVENT) { running = process_window_events(win, glctx, &(e.window)); } else if (e.type == SDL_KEYDOWN) { running = process_keypress(&(e.key)); } return running; } /** * Is called whenever the window size changes, so * the object is reshaped into the new window size. * * @param win the SDL window */ static void reshape(SDL_Window *win) { int w, h; SDL_GetWindowSize(win, &w, &h); glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(CAMERA_ANGLE, (GLfloat) w / (GLfloat) h, NEAR_CLIPPING_PLANE, FAR_CLIPPING_PLANE); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -5.0); } /** * Processes all sort of window events the SDL system catches. * * @param win the SDL window * @param glctx the OpenGL context * @param win_event the window event to process * @return true if the app is still running, false if it should * terminate */ static bool process_window_events(SDL_Window *win, SDL_GLContext glctx, SDL_WindowEvent *win_event) { bool running = true; if (win_event->event == SDL_WINDOWEVENT_RESIZED) reshape(win); else if (win_event->event == SDL_WINDOWEVENT_CLOSE) running = false; return running; } /** * Processes all sort of keyboard events the SDL system catches. * * press t to increase the day * * press T to decrease the day * * press j to increase the year * * press J to decrease the year * * press b to toggle GL_CULL_FACE * * press D to toggle disco mode * * press S to toggle shade model between GL_SMOOTH and GL_FLAT * * press n to toggle normals * * press k to increase length of normals * * press l to decrease length of normals * * press x to rotate the middle object in x direction * * press X to rotate the middle object in -x direction * * press y to rotate the middle object in y direction * * press Y to rotate the middle object in -y direction * * press c to rotate the middle object in z direction * * press C to rotate the middle object in -z direction * * press w to translate the whole scene in y direction * * press s to translate the whole scene in -y direction * * press a to translate the whole scene in -x direction * * press d to translate the whole scene in x direction * * press q to quit * * @param key_event the key event to process * @return true if the app is still running, false if it should * terminate */ static bool process_keypress(SDL_KeyboardEvent *key_event) { SDL_Keycode key = key_event->keysym.sym; SDL_Keymod mod = key_event->keysym.mod; bool running = true; switch (key) { /* case 'b': */ /* if (glIsEnabled(GL_CULL_FACE)) */ /* glDisable(GL_CULL_FACE); */ /* else */ /* glEnable(GL_CULL_FACE); */ /* break; */ case 't': if (mod & KMOD_SHIFT) { dayabs -= 15; } else { dayabs += 15; } break; case 'j': if (mod & KMOD_SHIFT) { yearabs -= 50; } else { yearabs += 50; } break; case 'x': if (mod & KMOD_SHIFT) { draw_obj(-2, 0, 0, 0); } else { draw_obj(2, 0, 0, 0); } break; case 'y': if (mod & KMOD_SHIFT) { draw_obj(0, -2, 0, 0); } else { draw_obj(0, 2, 0, 0); } break; case 'c': if (mod & KMOD_SHIFT) { draw_obj(0, 0, -2, 0); } else { draw_obj(0, 0, 2, 0); } break; case 'd': if (mod & KMOD_SHIFT) { draw_vertices(obj, true); } else { glTranslatef(1.0f, 0.0f, 0.0f); } break; case 's': if (mod & KMOD_SHIFT) { if (shademodel) { glShadeModel(GL_FLAT); shademodel = false; } else { glShadeModel(GL_SMOOTH); shademodel = true; } } else { glTranslatef(0.0f, -1.0f, 0.0f); } break; case 'b': if (mod & KMOD_SHIFT) { draw_obj(0, 0, 0, -0.02); } else { draw_obj(0, 0, 0, 0.02); } break; case 'k': if (mod & KMOD_SHIFT) { if (ball_speed - 0.2f > 0) ball_speed -= 0.2f; } else { ball_speed += 0.2f; } break; case 'f': if (mod & KMOD_SHIFT) { draw_bezier = !draw_bezier; } else { draw_frame = !draw_frame; } break; case 'l': if (mod & KMOD_SHIFT) { draw_normals(obj, 0.01f); } else { draw_normals(obj, -0.01f); } break; case 'w': glTranslatef(0.0f, 1.0f, 0.0f); break; case 'a': glTranslatef(-1.0f, 0.0f, 0.0f); break; case 'n': show_normals = !show_normals; break; case '+': glTranslatef(0.0f, 0.0f, 1.0f); break; case '-': glTranslatef(0.0f, 0.0f, -1.0f); break; case 'q': running = false; break; } return running; } /** * Destroy the gl session/window. */ static void gl_destroy(SDL_Window *win, SDL_GLContext glctx) { delete_object(obj); free(obj); SDL_GL_DeleteContext(glctx); SDL_DestroyWindow(win); SDL_Quit(); } /** * Initialize the global obj object. * * @param sun the file to parse and build the object from which * will construct the sun * @param object the file to parse and build the object from which * will float around the sun * @param bez the file to parse and build the object from which * will define on which curve the object floats around the sun */ void init_object(char const * const sun, char const * const object, char const * const bez) { obj = read_obj_file(sun); float_obj = read_obj_file(object); bez_obj = read_obj_file(bez); if (!obj) { ABORT("Failed to read object file \"%s\"!", sun); } else if (!float_obj) { ABORT("Failed to read object file \"%s\"!", object); } else if (!bez_obj) { ABORT("Failed to read object file \"%s\"!", bez); } NORMALIZE_OBJECT(obj); NORMALIZE_OBJECT(float_obj); NORMALIZE_OBJECT(bez_obj); } /** * Starts the main SDL loop which runs until the user * ends the program. */ void init_sdl_loop(void) { SDL_Window *win; SDL_GLContext glctx; const int window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; if (SDL_Init(SDL_INIT_VIDEO)) { fprintf(stderr, "Failed initalizing SDL!\n"); abort(); } if (!(win = SDL_CreateWindow("Drow Engine", 100, 100, 640, 480, window_flags))) { fprintf(stderr, "Failed creating SDL window!\n"); abort(); } if (!(glctx = SDL_GL_CreateContext(win))) { fprintf(stderr, "Failed creating OpenGL context!\n"); abort(); } SDL_GL_SetSwapInterval(1); init_opengl(); while (1) { bool running = process_events(win, glctx); if (!running) break; draw_scene(); SDL_GL_SwapWindow(win); } gl_destroy(win, glctx); }