400 lines
8.4 KiB
C
400 lines
8.4 KiB
C
/*
|
|
* 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* @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 <GL/glut.h>
|
|
#include <GL/gl.h>
|
|
|
|
#include <SDL.h>
|
|
|
|
|
|
/*
|
|
* 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);
|
|
}
|