#include <ctime>
#include <cstdlib>
#include <string>
#include <iostream>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include "geometry.h"
#include "scene.h"
class Main {
public:
bool sdl_initialized;
SDL_Window *mainWindow;
SDL_GLContext mainContext;
Scene *scene;
Main():
sdl_initialized(),
mainWindow(),
mainContext(),
scene()
{ }
~Main() { deinit(); }
bool init() {
srand(time(NULL));
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL_Init failed" << std::endl;
deinit();
return false;
}
sdl_initialized = true;
mainWindow = SDL_CreateWindow(
"simu",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
512,
512,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
if (!mainWindow)
{
std::cerr << "cannot create window" << std::endl;
std::cerr << SDL_GetError() << std::endl;
SDL_ClearError();
deinit();
return false;
}
mainContext = SDL_GL_CreateContext(mainWindow);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
// vsync
SDL_GL_SetSwapInterval(1);
scene = new Scene();
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POINT_SMOOTH);
glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
glEnable(GL_NORMALIZE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_LIGHT0);
float light0[] = {1, 1, 1, 0};
glLightfv(GL_LIGHT0, GL_POSITION, light0);
glEnable(GL_LIGHT1);
float light1[] = {-1, -1, -1, 0};
float color[] = {0.5, 0.5, 0.5, 1};
glLightfv(GL_LIGHT1, GL_POSITION, light1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, color);
//glLightfv(GL_LIGHT1, GL_SPECULAR, color);
glEnable(GL_COLOR_MATERIAL);
resize(512, 512);
return true;
}
void deinit() {
if (scene) { delete scene; scene = 0; }
if (mainContext) { SDL_GL_DeleteContext(mainContext); mainContext = 0; }
if (mainWindow) { SDL_DestroyWindow(mainWindow); mainWindow = 0; }
if (sdl_initialized) { SDL_Quit(); sdl_initialized = false; }
}
void resize(int width, int height) {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadMatrixd( Matrix4::perspective(90.0, (Real)width/height, 0.1, 100).a );
glMatrixMode(GL_MODELVIEW);
}
void loop() {
bool quit = false;
Uint32 prev_time = SDL_GetTicks();
while(!quit) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT)
quit = true;
if (event.type == SDL_WINDOWEVENT) {
if (event.window.event == SDL_WINDOWEVENT_RESIZED) {
resize(event.window.data1, event.window.data2);
}
}
if (event.type == SDL_KEYDOWN) {
switch (event.key.keysym.sym) {
case SDLK_ESCAPE:
quit = true;
break;
case SDLK_w:
scene->wireframe = !scene->wireframe;
break;
case SDLK_r:
scene->generate();
break;
default:
break;
}
}
if (event.type == SDL_MOUSEMOTION) {
if (event.motion.state & SDL_BUTTON_LMASK) {
scene->angles.z += event.motion.xrel;
scene->angles.x += event.motion.yrel;
}
if (event.motion.state & SDL_BUTTON_RMASK) {
scene->offset.z *= pow(2, event.motion.yrel/100.0);
}
if (event.motion.state & SDL_BUTTON_MMASK) {
scene->offset.x += 0.1*event.motion.xrel;
scene->offset.y -= 0.1*event.motion.yrel;
}
}
}
Uint32 curr_time = SDL_GetTicks();
double dt = (curr_time - prev_time)/1000.0;
prev_time = curr_time;
scene->update(dt);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
scene->draw();
SDL_GL_SwapWindow(mainWindow);
}
}
};
int main(int argc, char **argv)
{
Main app;
if (!app.init()) return -1;
app.loop();
return 0;
}