#include "pgr.h"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_projection.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
using namespace std;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Data
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
struct Point {
float color[4];
float position[3]; //LR TD FB
} const houseVertices[] = {
// Walls
{ { 0.0, 0.0, 1.0 }, { -5.0, -5.0, -5.0 } },
{ { 0.0, 1.0, 0.0 }, { -5.0, -5.0, 5.0 } },
{ { 0.0, 1.0, 1.0 }, { 5.0, -5.0, 5.0 } },
{ { 1.0, 0.0, 0.0 }, { 5.0, -5.0, -5.0 } },
{ { 1.0, 0.0, 1.0 }, { -5.0, 5.0, -5.0 } },
{ { 1.0, 1.0, 0.0 }, { -5.0, 5.0, 5.0 } },
{ { 1.0, 1.0, 1.0 }, { 5.0, 5.0, 5.0 } },
{ { 0.0, 0.0, 1.0 }, { 5.0, 5.0, -5.0 } },
{ { 0.0, 1.0, 0.0 }, { -5.0, -5.0, -5.0 } },
{ { 0.0, 1.0, 1.0 }, { -5.0, -5.0, 5.0 } },
{ { 1.0, 0.0, 0.0 }, { -5.0, 5.0, 5.0 } },
{ { 1.0, 0.0, 1.0 }, { -5.0, 5.0, -5.0 } },
{ { 0.0, 1.0, 0.0 }, { 5.0, -5.0, -5.0 } },
{ { 0.0, 1.0, 1.0 }, { 5.0, -5.0, 5.0 } },
{ { 1.0, 0.0, 0.0 }, { 5.0, 5.0, 5.0 } },
{ { 1.0, 0.0, 1.0 }, { 5.0, 5.0, -5.0 } },
// Roof
{ { 0.0, 0.0, 1.0 }, { -5.0, 5.0, -5.0 } },
{ { 0.0, 1.0, 1.0 }, { 5.0, 5.0, -5.0 } },
{ { 1.0, 1.0, 1.0 }, { 0.0, 11.0, 0.0 } },
{ { 1.0, 0.0, 0.0 }, { 5.0, 5.0, -5.0 } },
{ { 1.0, 1.0, 0.0 }, { 5.0, 5.0, 5.0 } },
{ { 1.0, 1.0, 1.0 }, { 0.0, 11.0, 0.0 } },
{ { 0.0, 1.0, 0.0 }, { 5.0, 5.0, 5.0 } },
{ { 0.0, 1.0, 1.0 }, { -5.0, 5.0, 5.0 } },
{ { 1.0, 1.0, 1.0 }, { 0.0, 11.0, 0.0 } },
{ { 0.0, 1.0, 0.0 }, { -5.0, 5.0, 5.0 } },
{ { 1.0, 1.0, 0.0 }, { -5.0, 5.0, -5.0 } },
{ { 1.0, 1.0, 1.0 }, { 0.0, 11.0, 0.0 } },
// Grass
{{0, 0.8, 0}, {-50, -5.01, -50}},
{{0, 0.8, 0}, {-50, -5.01, 50}},
{{0, 0.8, 0}, { 50, -5.01, 50}},
{{0, 0.8, 0}, { 50, -5.01, -50}}
};
// House indices
const unsigned char house[] = {
//Walls
0, 1, 2,
0, 2, 3,
4, 5, 6,
4, 6, 7,
8, 9, 10,
8, 10, 11,
12, 13, 14,
12, 14, 15,
//Roof
16, 17, 18,
19, 20, 21,
22, 23, 24,
25, 26, 27,
//Grass
28, 29, 30,
28, 30, 31
};
const Point windowsVertices[] = {
{{0, 0, 1, 0.5}, {-5, 5, 5}},
{{0, 0, 1, 0.5}, { 0, 5, 5}},
{{0, 0, 1, 0.5}, { 0, -5, 5}},
{{0, 0, 1, 0.5}, {-5, -5, 5}},
{{1, 0, 0, 0.5}, {-5, 5, -5}},
{{1, 0, 0, 0.5}, { 0, 5, -5}},
{{1, 0, 0, 0.5}, { 0, -5, -5}},
{{1, 0, 0, 0.5}, {-5, -5, -5}}
};
const unsigned char quad[] = {0, 1, 2, 3, 4, 5, 6, 7};
GLuint VBO, EBO, winVBO, quadEBO;
int width, height;
float rx = 0.0f, ry = 0.0f, pz = -70.0f, wheel = 1.0f;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Shaders
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
GLuint VS, FS, Prog;
GLuint positionAttrib, colorAttrib, mvpUniform;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Event handlers
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void onInit()
{
// Shader
VS = CompileShader(GL_VERTEX_SHADER, loadFile("lab01_task.vs").c_str());
FS = CompileShader(GL_FRAGMENT_SHADER, loadFile("lab01_task.fs").c_str());
Prog = LinkShader(2, VS, FS);
positionAttrib = glGetAttribLocation(Prog, "position");
colorAttrib = glGetAttribLocation(Prog, "color");
mvpUniform = glGetUniformLocation(Prog, "mvp");
// Copy house to graphics card
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(houseVertices), houseVertices, GL_STATIC_DRAW);
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(house), house, GL_STATIC_DRAW);
// Copy windows to graphic card
glGenBuffers(1, &winVBO);
glBindBuffer(GL_ARRAY_BUFFER, winVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(windowsVertices), windowsVertices, GL_STATIC_DRAW);
glGenBuffers(1, &quadEBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadEBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
}
void onWindowRedraw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glUseProgram(Prog);
//MVP
float aspect = (float)width / (float)height;
glm::mat4 mvp = glm::rotate(
glm::rotate(
glm::translate(
glm::perspective(10.0f * wheel, aspect, 1.0f, 1000.0f),
glm::vec3(0, 0, pz)
),
ry,
glm::vec3(1, 0, 0)
),
rx,
glm::vec3(0, 1, 0)
);
glUniformMatrix4fv(mvpUniform, 1, GL_FALSE, glm::value_ptr(mvp));
glEnableVertexAttribArray(positionAttrib);
glEnableVertexAttribArray(colorAttrib);
//Vykresleni domu
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(Point), (void*)offsetof(Point, position));
glVertexAttribPointer(colorAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(Point), (void*)offsetof(Point, color));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, sizeof(house)/sizeof(*house), GL_UNSIGNED_BYTE, NULL);
//Vykresleni oken
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, quadEBO);
glBindBuffer(GL_ARRAY_BUFFER, winVBO);
glVertexAttribPointer(positionAttrib, 3, GL_FLOAT, GL_FALSE, sizeof(Point), (void*)offsetof(Point, position));
glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(Point), (void*)offsetof(Point, color));
glDrawElements(GL_QUADS, sizeof(quad)/sizeof(*quad), GL_UNSIGNED_BYTE, NULL);
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
SDL_GL_SwapBuffers();
}
void onWindowResized(int w, int h)
{
glViewport(0, 0, w, h);
width = w; height = h;
}
void onKeyDown(SDLKey key, Uint16 /*mod*/)
{
switch(key) {
case SDLK_ESCAPE : quit(); return;
default : return;
}
}
void onKeyUp(SDLKey /*key*/, Uint16 /*mod*/)
{
}
void onMouseMove(unsigned /*x*/, unsigned /*y*/, int xrel, int yrel, Uint8 buttons)
{
if(buttons & SDL_BUTTON_LMASK)
{
rx += xrel;
ry += yrel;
redraw();
}
if(buttons & SDL_BUTTON_RMASK)
{
pz += yrel;
redraw();
}
}
void onMouseDown(Uint8 button, unsigned /*x*/, unsigned /*y*/)
{
switch(button) {
case SDL_BUTTON_WHEELUP : wheel += 1; break;
case SDL_BUTTON_WHEELDOWN : wheel -= 1; break;
default : return;
};
redraw();
}
void onMouseUp(Uint8 /*button*/, unsigned /*x*/, unsigned /*y*/)
{
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Main
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
int main(int /*argc*/, char ** /*argv*/)
{
try {
// Init SDL - only video subsystem will be used
if(SDL_Init(SDL_INIT_VIDEO) < 0) throw SDL_Exception();
// Shutdown SDL when program ends
atexit(SDL_Quit);
init(800, 600, 24, 16, 0);
mainLoop();
} catch(exception & ex) {
cout << "ERROR : " << ex.what() << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}