/* square using vertex buffer objects */
#include "include/Angel.h"
#include <string>
#include <iostream>
#include <sstream>
#include <streambuf>
#define WINDOW_TITLE "Tutorial"
using namespace std;
void createVBO( void );
void createCube( void );
void destroyCube( void );
void drawCube( void );
struct vertex {
vec4 XYZW;
vec4 RGBA;
};
int current_width = 800, current_height = 600, window_id = 0;
uint frame_count = 0;
GLuint proj_mat_uniform_loc, view_mat_uniform_loc, model_mat_uniform_loc, buffer_ids[3], program;
GLfloat cube_angle, cam_tz=-2.0f, cam_ty, cam_tx, cam_thetax, cam_thetay, cam_thetaz;
mat4 proj_matrix, view_matrix, model_matrix;
bool displayedRound = false;
clock_t last_time = 0;
vertex vertices[] = {
{ vec4(-.5f, -.5f, .5f, 1.0f), vec4(0.0f, 0.0f, 1.0f, 1.0f) },
{ vec4(-.5f, .5f, .5f, 1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f) },
{ vec4( .5f, .5f, .5f, 1.0f), vec4(0.0f, 1.0f, 0.0f, 1.0f) },
{ vec4( .5f, -.5f, .5f, 1.0f), vec4(1.0f, 1.0f, 0.0f, 1.0f) },
{ vec4(-.5f, -.5f, -.5f, 1.0f), vec4(1.0f, 1.0f, 1.0f, 1.0f) },
{ vec4(-.5f, .5f, -.5f, 1.0f), vec4(1.0f, 0.0f, 0.0f, 1.0f) },
{ vec4( .5f, .5f, -.5f, 1.0f), vec4(1.0f, 0.0f, 1.0f, 1.0f) },
{ vec4( .5f, -.5f, -.5f, 1.0f), vec4(0.0f, 0.0f, 1.0f, 1.0f) }
};
// GLuint vao_id, vbo_id, program, colour_buffer_id, index_buffer_id[2], active_index_buffer;
//----------------------------------------------------------------------------
void
init( void )
{
program = InitShader("vshader.glsl", "fshader.glsl");
glUseProgram(program);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
view_matrix = Translate(cam_tx,cam_ty,cam_tz);
// cout << view_matrix << "\n";
proj_matrix = Perspective(90, (float) current_width/current_height, 0.1f, 100.0f);
createCube();
}
//----------------------------------------------------------------------------
void reshape (int width, int height){
current_width = width;
current_height = height;
glViewport(0,0,current_width, current_height);
proj_matrix = Perspective(90, (float) current_width/current_height, 0.1f, 100.0f);
glUseProgram(program);
glUniformMatrix4fv(proj_mat_uniform_loc, 1, GL_FALSE, proj_matrix);
glUseProgram(0);
// cout << "Current Height: " << height << ", Current Width: " << width << "\n";
}
void
display( void )
{
++frame_count;
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
drawCube();
// Force OpenGL to render
glutSwapBuffers();
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
keyboard( unsigned char key, int x, int y )
{
switch ( key ) {
case 033: //ESC
exit( EXIT_SUCCESS );
break;
case 'w':
cam_tz -= 0.01f;
break;
case 's':
cam_tz += 0.01f;
break;
case 'a':
cam_tx += 0.01f;
break;
case 'd':
cam_tx -= 0.01f;
break;
case 'r':
cam_ty -= 0.01f;
break;
case 'f':
cam_ty += 0.01f;
break;
case 'i':
cam_thetax -= 1;
break;
case 'k':
cam_thetax += 1;
break;
case 'j':
cam_thetay -= 1;
break;
case 'l':
cam_thetay += 1;
break;
case 'u':
cam_thetaz += 1;
break;
case 'o':
cam_thetaz -= 1;
break;
default:
break;
}
}
void timer( int value ){
if (value != 0){
string fps;
stringstream fps_stream(fps);
fps_stream << WINDOW_TITLE << ": " << frame_count * 4 << " Frames per Second @ " << current_width << " x " << current_height;
glutSetWindowTitle(fps_stream.str().c_str());
}
frame_count = 0;
glutTimerFunc(250, timer, 1);
}
void computeCubeRotation(int speed) {
if(speed != 0){
cube_angle += 45.0f/speed;
glutTimerFunc(10, computeCubeRotation, 128);
}
}
void idle( void ){
glutPostRedisplay();
}
void createCube(){
GLuint indices[] =
{
0,2,1, 0,3,2,
4,3,0, 4,7,3,
4,1,5, 4,0,1,
3,6,2, 3,7,6,
1,6,5, 1,2,6,
7,5,6, 7,4,5
};
program = InitShader("vshader_3d.glsl","fshader_3d.glsl");
model_mat_uniform_loc = glGetUniformLocation(program, "model_matrix");
view_mat_uniform_loc = glGetUniformLocation(program, "view_matrix");
proj_mat_uniform_loc = glGetUniformLocation(program, "proj_matrix");
glGenVertexArrays(1, &buffer_ids[0]);
glBindVertexArray(buffer_ids[0]);
glGenBuffers(2, &buffer_ids[1]);
glBindBuffer(GL_ARRAY_BUFFER, buffer_ids[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint in_Position = glGetAttribLocation(program, "in_Position");
GLuint in_Colour = glGetAttribLocation(program, "in_Colour");
glEnableVertexAttribArray(in_Position);
glEnableVertexAttribArray(in_Colour);
glVertexAttribPointer(in_Position, 4, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (GLvoid*)0);
glVertexAttribPointer(in_Colour, 4, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (GLvoid*)sizeof(vertices[0].XYZW));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_ids[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glBindVertexArray(0);
glutTimerFunc(10, computeCubeRotation, 128);
}
void destroyCube(){
glDeleteProgram(program);
glDeleteBuffers(2, &buffer_ids[1]);
glDeleteVertexArrays(1, &buffer_ids[0]);
}
void drawCube(){
view_matrix = LookAt(vec4(cam_tx, cam_ty, cam_tz-2, 1), RotateY(cam_thetay) * RotateX(cam_thetax) * vec4(cam_tx,cam_ty,cam_tz,1), RotateZ(cam_thetaz)*vec4(0,1,0,1));
// model_matrix = RotateX(cube_angle/2) * RotateY(cube_angle);
// cout << model_matrix << "\n";
glUseProgram(program);
glUniformMatrix4fv(model_mat_uniform_loc, 1, GL_FALSE, model_matrix);
glUniformMatrix4fv(view_mat_uniform_loc, 1, GL_FALSE, view_matrix);
if ((int)round(cube_angle) % 15 == 0){
if(!displayedRound){
cout << "Cube angle: " << (int)round(cube_angle) % 360 << " degrees\n";
cout << "MVP matrix: " << proj_matrix * view_matrix * model_matrix << "\n";
cout << "Projection matrix: " << proj_matrix << "\n";
cout << "MV matrix: " << view_matrix * model_matrix << "\n";
cout << "View matrix: " << view_matrix << "\n";
cout << "Model matrix: " << model_matrix << "\n";
for (int i=0; i<8; i++){
vec4 vertex = vertices[i].XYZW;
cout << (proj_matrix * view_matrix * model_matrix * vertex)/(proj_matrix * view_matrix * model_matrix * vertex).w << "\n";
}
cout << "\n";
displayedRound = true;
}
}
else {
displayedRound = false;
}
glBindVertexArray(buffer_ids[0]);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (GLvoid*)0);
glBindVertexArray(0);
glUseProgram(0);
}
//----------------------------------------------------------------------------
int
initWindow(int argc, char **argv)
{
// Initialize glut library
glutInit( &argc, argv );
glutInitContextVersion(3,3);
glutInitContextFlags(GLUT_FORWARD_COMPATIBLE);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
// Create the window
glutInitWindowSize( current_width, current_height );
glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA );
window_id = glutCreateWindow( WINDOW_TITLE );
// Initialize glew library
glewExperimental = GL_TRUE;
glewInit();
// Your own initialization
init();
// Set callback functions
glutReshapeFunc( reshape );
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutTimerFunc(0, timer, 0);
glutIdleFunc( idle );
glutCloseFunc( destroyCube );
return 0;
}
int
main( int argc, char **argv ) {
initWindow(argc, argv);
cout << "OpenGL Version " << glGetString(GL_VERSION) <<"\n";
// Start the main loop
glutMainLoop();
return 0;
}