Skip to content

Instantly share code, notes, and snippets.

@roxlu roxlu/test-cam.cpp Secret
Created Apr 2, 2019

Embed
What would you like to do?
#include <stdlib.h>
#include <stdio.h>
#include <sstream>
#include <poly/Glad.h>
#include <GLFW/glfw3.h>
#include <poly/Log.h>
#include <poly/CommandLineOptions.h>
#include <poly/MiniTrace.h>
#include <poly/Pointer.h>
#include <poly/Math.h>
#include <poly/Shaders.h>
#include <poly/TurnTableSmooth.h>
#include <poly/Grid.h>
using namespace poly;
/* -------------------------------------------- */
void button_callback(GLFWwindow* win, int bt, int action, int mods);
void cursor_callback(GLFWwindow* win, double x, double y);
void key_callback(GLFWwindow* win, int key, int scancode, int action, int mods);
void char_callback(GLFWwindow* win, unsigned int key);
void error_callback(int err, const char* desc);
void resize_callback(GLFWwindow* window, int width, int height);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
/* -------------------------------------------- */
int win_h = 0;
int win_w = 0;
TurnTableSmooth table;
class Cam {
public:
void init(const vec3& pos, const vec3& target, const vec3& up, float winWidth, float winHeight);
void update();
void onMouseDown(float x, float y);
void onMouseMove(float x, float y);
void onMouseUp();
vec4 screenToWorld(float x, float y);
public:
float win_width = 0.0f;
float win_height = 0.0f;
float zoom = 1.0f;
vec3 pos;
vec3 target;
vec3 up;
vec3 dir;
vec2 pan;
mat4 pm; /* Projection Matrix. */
mat4 lm; /* Lookat matrix */
mat4 vm; /* View matrix. */
float yaw = 0.0f; /* Around Y-axis. */
float pitch = 0.0f; /* Around X-axis. */
mat4 screen_to_world; /* Inverted projection matrix. */
vec4 mouse_down_pos;
bool is_down = false;
};
Cam cam;
/* -------------------------------------------- */
int main(int argc, char* argv[]) {
glfwSetErrorCallback(error_callback);
CommandLineOptions cmd;
cmd.addU32("width", false, 1920, "Window width");
cmd.addU32("height", false, 1080, "Window height");
cmd.addU32("x", false, 0, "Window X position");
cmd.addU32("y", false, 0, "Window Y position");
cmd.addFlag("decorated", "Draw window title, min/max buttons and border.");
if (0 != cmd.init(argc, argv)) {
SX_ERROR("Failed to initialize.");
exit(EXIT_FAILURE);
}
if(!glfwInit()) {
printf("Error: cannot setup glfw.\n");
exit(EXIT_FAILURE);
}
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GL_FALSE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_DECORATED, (true == cmd.hasFlag("decorated")) ? GL_TRUE : GL_FALSE);
GLFWwindow* win = NULL;
int w = cmd.getU32("width");
int h = cmd.getU32("height");
int x = cmd.getU32("x");
int y = cmd.getU32("y");
win_w = w;
win_h = h;
win = glfwCreateWindow(w, h, "TURN TABLE", NULL, NULL);
if(!win) {
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetFramebufferSizeCallback(win, resize_callback);
glfwSetKeyCallback(win, key_callback);
glfwSetCharCallback(win, char_callback);
glfwSetCursorPosCallback(win, cursor_callback);
glfwSetMouseButtonCallback(win, button_callback);
glfwSetScrollCallback(win, scroll_callback);
glfwMakeContextCurrent(win);
glfwSwapInterval(1);
if (cmd.getU32("x") && cmd.getU32("y")) {
glfwSetWindowPos(win, x, y);
}
if (!gladLoadGL()) {
printf("Cannot load GL.\n");
exit(1);
}
// ----------------------------------------------------------------
// THIS IS WHERE YOU START CALLING OPENGL FUNCTIONS, NOT EARLIER!!
// ----------------------------------------------------------------
mtr_init("turntable.json");
MTR_META_PROCESS_NAME("turntable");
MTR_META_THREAD_NAME("main");
poly_log_init(1024, argc, argv);
poly_log_add_sink_stdout();
glDisable(GL_DEPTH_TEST);
glDisable(GL_DITHER);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/* -------------------------------------------------------------------- */
mat4 pm;
pm.perspective(60.0f, win_w / win_h, 0.1f, 100.0f);
mat4 vm;
vm.lookat(vec3(0, 3, 3), vec3(0, 0, 0), vec3(0, 1, 0));
vm.print();
ShaderP3C4 shader_pc;
if (0 != shader_pc.init()) {
exit(EXIT_FAILURE);
}
Grid grid;
grid.init(50, 50, 0.1, 0.1);
table.lookat(vec3(0, 3, 3), vec3(0,0,0), vec3(0,1,0));
cam.init(vec3(0, 5, 5), vec3(0,0,0), vec3(0,1,0), win_w, win_h);
/* -------------------------------------------------------------------- */
/* Our main render loop. */
while(!glfwWindowShouldClose(win)) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, w, h);
glClearColor(0.13f, 0.13f, 0.13f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
MTR_SCOPE("main", "update()");
cam.update();
shader_pc.use();
shader_pc.setProjectionMatrix(pm.ptr());
shader_pc.setViewMatrix(cam.vm.ptr());
grid.draw();
glfwSwapBuffers(win);
glfwPollEvents();
}
mtr_flush();
mtr_shutdown();
glfwTerminate();
return EXIT_SUCCESS;
}
void char_callback(GLFWwindow* win, unsigned int key) {
}
void key_callback(GLFWwindow* win, int key, int scancode, int action, int mods) {
if (GLFW_RELEASE == action) {
return;
}
switch(key) {
case GLFW_KEY_A: {
/* left */
cam.pan.x -= 1;
break;
}
case GLFW_KEY_D: {
/* right */
cam.pan.x += 1;
break;
}
case GLFW_KEY_EQUAL: {
cam.zoom += 0.1;
break;
}
case GLFW_KEY_MINUS: {
cam.zoom -= 0.1;
break;
}
case GLFW_KEY_UP: {
cam.pitch -= 1 * DEG_TO_RAD;
break;
}
case GLFW_KEY_DOWN: {
cam.pitch += 1 * DEG_TO_RAD;
break;
}
case GLFW_KEY_LEFT: {
cam.yaw -= 1 * DEG_TO_RAD;
break;
}
case GLFW_KEY_RIGHT: {
cam.yaw += 1 * DEG_TO_RAD;
break;
}
case GLFW_KEY_SPACE: {
break;
}
case GLFW_KEY_ESCAPE: {
glfwSetWindowShouldClose(win, GL_TRUE);
break;
}
};
}
void resize_callback(GLFWwindow* window, int width, int height) {
}
void cursor_callback(GLFWwindow* win, double x, double y) {
Pointer p;
p.id = 666;
p.x = x;
p.y = y;
p.type = POINTER_TYPE_MOUSE;
p.button = POINTER_BUTTON_LEFT;
p.state = POINTER_STATE_MOVE;
table.onMouseMove(x, y);
cam.onMouseMove(x, y);
}
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
table.onScroll(yoffset);
}
void button_callback(GLFWwindow* win, int bt, int action, int mods) {
double mx = 0.0f;
double my = 0.0f;
glfwGetCursorPos(win, &mx, &my);
SX_VERBOSE("mouse: %2.2f, %2.2f", mx, my);
Pointer p;
p.id = 666;
p.x = mx;
p.y = my;
p.type = POINTER_TYPE_MOUSE;
p.button = POINTER_BUTTON_LEFT;
if (GLFW_PRESS == action) {
p.state = POINTER_STATE_DOWN;
table.onMouseDown(mx, my, bt);
cam.onMouseDown(mx, my);
}
else if (GLFW_RELEASE == action) {
p.state = POINTER_STATE_UP;
table.onMouseUp(bt);
cam.onMouseUp();
}
}
void error_callback(int err, const char* desc) {
printf("GLFW error: %s (%d)\n", desc, err);
}
/* -------------------------------------------------------------------- */
void Cam::init(const vec3& p, const vec3& t, const vec3& u, float winWidth, float winHeight) {
win_width = winWidth;
win_height = winHeight;
dir = t - p;
pos = p;
target = t;
up = u;
pm.perspective(60.0f, win_w / win_h, 0.1f, 100.0f);
}
void Cam::update() {
lm.lookat(target - (dir * zoom), target, up);
mat4 inv = lm;
inv.invert();
mat4 trans;
trans.translate(pan.x, pan.y, 0.0);
mat4 rot;
rot.rotateY(yaw);
rot.rotateX(pitch);
vm = lm * rot;
/* experiment for panning */
screen_to_world = pm * vm;
screen_to_world.invert();
}
void Cam::onMouseDown(float x, float y) {
mouse_down_pos = screenToWorld(x, y);
is_down = true;
}
void Cam::onMouseMove(float x, float y) {
if (false == is_down) {
return;
}
}
void Cam::onMouseUp() {
is_down = false;
}
vec4 Cam::screenToWorld(float x, float y) {
float nx = 2.0 * x / win_width - 1.0;
float ny = -2.0 * y / win_height + 1.0;
vec4 world_pos(x, y, 0.0f, 1.0f);
return screen_to_world * world_pos;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.