move cursor to yaw the camera
move cursor and hold right mouse button to pitch the camera
move cursor and hold middle mouse button to roll the camera
scroll up / down to move the camera forward / back
Complete Source Code:
Main.cpp
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <map>
#include "Scene.h"
#include "Graphics.h"
using namespace std;
Scene scene;
struct {
struct { int X, Y; } CursorPosition;
map<int, bool> Key, MouseButton;
} inputstate;
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
Graphics::Resize(width, height);
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
inputstate.Key[key] = action != GLFW_RELEASE;
if (key == GLFW_KEY_E && action == GLFW_PRESS)
{ }
}
void cursor_position_callback(GLFWwindow* window, double xpos, double ypos)
{
int xdelta = inputstate.CursorPosition.X - xpos;
int ydelta = inputstate.CursorPosition.Y - ypos;
inputstate.CursorPosition.X = xpos;
inputstate.CursorPosition.Y = ypos;
/* camera roll */
if (inputstate.MouseButton[GLFW_MOUSE_BUTTON_MIDDLE])
scene.camera.Roll(xdelta * -0.01f);
/* camera yaw */
else
scene.camera.Yaw(xdelta * 0.01f);
/* camera pitch */
if (inputstate.MouseButton[GLFW_MOUSE_BUTTON_RIGHT])
scene.camera.Pitch(ydelta * -0.01f);
}
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods)
{
inputstate.MouseButton[button] = action != GLFW_RELEASE;
if (button == GLFW_MOUSE_BUTTON_RIGHT && action == GLFW_PRESS)
{ }
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (yoffset > 0)
scene.camera.Move(scene.camera.Forward() * 0.5f);
if (yoffset < 0)
scene.camera.Move(scene.camera.Back() * 0.5f);
}
void joystick_callback(int joy, int event)
{
if (event == GLFW_CONNECTED)
{ }
else if (event == GLFW_DISCONNECTED)
{ }
}
int main(int argc, char* argv[])
{
/* Initialize GLFW */
if (!glfwInit())
return -1;
/* Create a window and its OpenGL context */
bool fullscreen = false;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWmonitor* monitor = fullscreen ? glfwGetPrimaryMonitor() : NULL;
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", monitor, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Enable v-sync */
glfwSwapInterval(1);
/* Set callback functions */
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetKeyCallback(window, key_callback);
glfwSetCursorPosCallback(window, cursor_position_callback);
glfwSetMouseButtonCallback(window, mouse_button_callback);
glfwSetScrollCallback(window, scroll_callback);
glfwSetJoystickCallback(joystick_callback);
/* Initialize GLEW */
if (glewInit() != GLEW_OK)
{
glfwTerminate();
return -2;
}
/* Show OpenGL context information */
GLContextInfo infos = Graphics::GetContextInfos();
cout << "OpenGL version: " << infos.Version.Major << "." << infos.Version.Minor << endl;
cout << "Driver version: " << infos.Version.Driver << endl;
cout << "GLSL version: " << infos.Version.ShadingLanguage << endl;
cout << "Vendor: " << infos.Vendor << endl;
cout << "Renderer: " << infos.Renderer << endl;
/*cout << "Supported GLSL Versions: " << endl;
for (std::list<std::string>::iterator it = infos.SupportedGLSLVersions.begin(); it != infos.SupportedGLSLVersions.end(); it++)
cout << "GLSL " << *it << endl;
cout << "Supported Extensions: " << endl;
for (std::list<std::string>::iterator it = infos.SupportedExtensions.begin(); it != infos.SupportedExtensions.end(); it++)
cout << "Extension: " << *it << endl;*/
/* Initialize graphics subsystem */
int width = 0, height = 0;
glfwGetFramebufferSize(window, &width, &height);
if (!Graphics::Initialize(width, height))
{
glfwTerminate();
return -3;
}
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Calculate frame time */
static double time_lastframe = glfwGetTime();
double time_now = glfwGetTime();
double time_frame = time_now - time_lastframe;
time_lastframe = time_now;
/* Animate scene */
scene.AnimateNextFrame((float)time_frame);
/* Render scene */
Graphics::Render(scene);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
Graphics::CleanUp();
glfwTerminate();
return 0;
}
Scene.h
#ifndef SCENE_H
#define SCENE_H
#include "Camera.h"
#include "Orientation.h"
struct Scene
{
Scene();
void AnimateNextFrame(float timestep);
Camera camera;
Orientation triangle;
};
#endif // SCENE_H
Scene.cpp
#include "Scene.h"
Scene::Scene()
{
/* put the camera at the positive z-axis */
camera.SetPosition(glm::vec3(0, 0, 5));
/* turn the camera back to the origin */
camera.Yaw(glm::radians(180.0f));
}
void Scene::AnimateNextFrame(float timestep)
{
/* rotate triangle 90° per second */
triangle.Yaw(glm::radians(90.0f * timestep));
}