Index: new-game.cpp
===================================================================
--- new-game.cpp	(revision 9d22ee96401b020eba946d6488e674159862e65a)
+++ new-game.cpp	(revision 7ee66ea5a8d495a1570159c91decf4bfe6e73ef4)
@@ -2,4 +2,8 @@
 
 #include "logger.h"
+
+#include <glm/mat4x4.hpp> // glm::mat4
+#include <glm/gtc/matrix_transform.hpp>
+#include <glm/gtc/type_ptr.hpp>
 
 #include <GL/glew.h>
@@ -9,7 +13,12 @@
 #include <iostream>
 #include <fstream>
+
+#define _USE_MATH_DEFINES
 #include <cmath>
 
 using namespace std;
+using namespace glm;
+
+#define ONE_DEG_IN_RAD (2.0 * M_PI) / 360.0 // 0.017444444
 
 GLuint loadShader(GLenum type, string file);
@@ -87,4 +96,7 @@
      -0.5f, -0.5f,  0.0f,
       0.5f, -0.5f,  0.0f,
+      0.5f, -0.5f,  0.0f,
+     -0.5f, -0.5f,  0.0f,
+      0.0f,  0.5f,  0.0f,
    };
 
@@ -93,7 +105,10 @@
      0.0, 0.0, 1.0,
      0.0, 1.0, 0.0,
-   };
-
-   GLfloat model[] = {
+     0.0, 1.0, 0.0,
+     0.0, 0.0, 1.0,
+     1.0, 0.0, 0.0,
+   };
+
+   GLfloat model_mat[] = {
      1.0f, 0.0f, 0.0f, 0.0f, // column 1
      0.0f, 1.0f, 0.0f, 0.0f, // column 2
@@ -132,8 +147,45 @@
    glLinkProgram(shader_program);
 
-   GLint location = glGetUniformLocation(shader_program, "model");
-
    float speed = 1.0f;
    float last_position = 0.0f;
+
+   float cam_speed = 1.0f;
+   float cam_yaw_speed = 30.0f*ONE_DEG_IN_RAD;
+
+   float cam_pos[] = {0.0f, 0.0f, 2.0f};
+   float cam_yaw = 0.0f;
+
+   mat4 T = translate(mat4(), vec3(-cam_pos[0], -cam_pos[1], -cam_pos[2]));
+   mat4 R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
+   mat4 view_mat = R*T;
+
+   float near = 0.1f;
+   float far = 100.0f;
+   float fov = 67.0f * ONE_DEG_IN_RAD;
+   float aspect = (float)width / (float)height;
+
+   float range = tan(fov * 0.5f) * near;
+   float Sx = near / (range * aspect);
+   float Sy = near / range;
+   float Sz = -(far + near) / (far - near);
+   float Pz = -(2.0f * far * near) / (far - near);
+
+   float proj_mat[] = {
+     Sx, 0.0f, 0.0f, 0.0f,
+     0.0f, Sy, 0.0f, 0.0f,
+     0.0f, 0.0f, Sz, -1.0f,
+     0.0f, 0.0f, Pz, 0.0f,
+   };
+
+   GLint model_mat_loc = glGetUniformLocation(shader_program, "model");
+   GLint view_mat_loc = glGetUniformLocation(shader_program, "view");
+   GLint proj_mat_loc = glGetUniformLocation(shader_program, "proj");
+
+   glUseProgram(shader_program);
+   glUniformMatrix4fv(model_mat_loc, 1, GL_FALSE, model_mat);
+   glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
+   glUniformMatrix4fv(proj_mat_loc, 1, GL_FALSE, proj_mat);
+
+   bool cam_moved = false;
 
    double previous_seconds = glfwGetTime();
@@ -147,13 +199,15 @@
       }
 
+      /*
       model[12] = last_position + speed*elapsed_seconds;
       last_position = model[12];
-      glUseProgram(shader_program);
-      glUniformMatrix4fv(location, 1, GL_FALSE, model);
+      */
 
       glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
       glBindVertexArray(vao);
 
-      glDrawArrays(GL_TRIANGLES, 0, 3);
+      // Each point is made of 3 floats
+      int numPoints = (sizeof(points) / sizeof(float)) / 3;
+      glDrawArrays(GL_TRIANGLES, 0, numPoints);
 
       glfwPollEvents();
@@ -162,4 +216,42 @@
       if (GLFW_PRESS == glfwGetKey(window, GLFW_KEY_ESCAPE)) {
          glfwSetWindowShouldClose(window, 1);
+      }
+
+      float dist = cam_speed * elapsed_seconds;
+      if (glfwGetKey(window, GLFW_KEY_A)) {
+         cam_pos[0] -= cos(cam_yaw*ONE_DEG_IN_RAD)*dist;
+         cam_pos[2] += sin(cam_yaw*ONE_DEG_IN_RAD)*dist;
+         cam_moved = true;
+      }
+      if (glfwGetKey(window, GLFW_KEY_D)) {
+         cam_pos[0] += cos(cam_yaw)*dist;
+         cam_pos[2] -= sin(cam_yaw)*dist;
+         cam_moved = true;
+      }
+      if (glfwGetKey(window, GLFW_KEY_W)) {
+         cam_pos[0] -= sin(cam_yaw)*dist;
+         cam_pos[2] -= cos(cam_yaw)*dist;
+         cam_moved = true;
+      }
+      if (glfwGetKey(window, GLFW_KEY_S)) {
+         cam_pos[0] += sin(cam_yaw)*dist;
+         cam_pos[2] += cos(cam_yaw)*dist;
+         cam_moved = true;
+      }
+      if (glfwGetKey(window, GLFW_KEY_LEFT)) {
+         cam_yaw += cam_yaw_speed * elapsed_seconds;
+         cam_moved = true;
+      }
+      if (glfwGetKey(window, GLFW_KEY_RIGHT)) {
+         cam_yaw -= cam_yaw_speed * elapsed_seconds;
+         cam_moved = true;
+      }
+      if (cam_moved) {
+         T = translate(mat4(), vec3(-cam_pos[0], -cam_pos[1], -cam_pos[2]));
+         R = rotate(mat4(), -cam_yaw, vec3(0.0f, 1.0f, 0.0f));
+         view_mat = R*T;
+
+         glUniformMatrix4fv(view_mat_loc, 1, GL_FALSE, value_ptr(view_mat));
+         cam_moved = false;
       }
    }
Index: test.vert
===================================================================
--- test.vert	(revision 9d22ee96401b020eba946d6488e674159862e65a)
+++ test.vert	(revision 7ee66ea5a8d495a1570159c91decf4bfe6e73ef4)
@@ -1,5 +1,5 @@
 #version 410
 
-uniform mat4 model;
+uniform mat4 model, view, proj;
 
 layout(location = 0) in vec3 vertex_position;
@@ -10,4 +10,4 @@
 void main() {
   color = vertex_color;
-  gl_Position = model * vec4(vertex_position, 1.0);
+  gl_Position = proj * view * model * vec4(vertex_position, 1.0);
 }
