click-drag rotation

This commit is contained in:
2018-12-12 02:13:47 -05:00
parent fbdd9ac0df
commit 61d2b3a65b
6 changed files with 127 additions and 24 deletions

View File

@@ -18,6 +18,8 @@ private:
static void onCursorPos(GLFWwindow *window, double x, double y); static void onCursorPos(GLFWwindow *window, double x, double y);
static void onMouseButton(GLFWwindow *window, int button, int action, int mods);
protected: protected:
App(int gl_major, int gl_minor); App(int gl_major, int gl_minor);
@@ -43,6 +45,8 @@ protected:
virtual void onCursorPos(double x, double y) {} virtual void onCursorPos(double x, double y) {}
virtual void onMouseButton(int button, int action, int mods) {}
virtual void init() {} virtual void init() {}
virtual void display() {} virtual void display() {}

View File

@@ -124,6 +124,11 @@ void App::onCursorPos(GLFWwindow *window, double x, double y) {
if (app) app->onCursorPos(x, y); if (app) app->onCursorPos(x, y);
} }
void App::onMouseButton(GLFWwindow *window, int button, int action, int mods) {
auto *app = get(window);
if (app) app->onMouseButton(button, action, mods);
}
int App::run() { int App::run() {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _gl_major); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, _gl_major);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _gl_minor); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, _gl_minor);
@@ -137,6 +142,7 @@ int App::run() {
glfwSetWindowSizeCallback(getWindow(), App::onSize); glfwSetWindowSizeCallback(getWindow(), App::onSize);
glfwSetKeyCallback(getWindow(), App::onKey); glfwSetKeyCallback(getWindow(), App::onKey);
glfwSetCursorPosCallback(getWindow(), App::onCursorPos); glfwSetCursorPosCallback(getWindow(), App::onCursorPos);
glfwSetMouseButtonCallback(getWindow(), App::onMouseButton);
glfwMakeContextCurrent(_window); glfwMakeContextCurrent(_window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);

View File

@@ -9,6 +9,9 @@ target_link_libraries(${PROJECT_NAME}
glfw glfw
framework) framework)
target_include_directories(${PROJECT_NAME}
PRIVATE
include)
set(SHADERS set(SHADERS
shaders/main.frag shaders/main.frag

28
glapp/include/glmutil.h Normal file
View File

@@ -0,0 +1,28 @@
#ifndef GL_TEMPLATE_GLMUTILS_H
#define GL_TEMPLATE_GLMUTILS_H
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>
namespace glmutil {
glm::mat4 rotation(float angle, glm::vec3 axis) {
auto mat = glm::identity<glm::mat4>();
return glm::rotate(mat, angle, axis);
}
glm::mat4 scale(glm::vec3 v) {
auto mat = glm::identity<glm::mat4>();
return glm::scale(mat, v);
}
glm::mat4 eulerAngles(glm::vec3 angles){
auto mat = glm::identity<glm::mat4>();
mat = glm::rotate(mat, angles.x, glm::vec3(1, 0, 0));
mat = glm::rotate(mat, angles.y, glm::vec3(0, 1, 0));
mat = glm::rotate(mat, angles.z, glm::vec3(0, 0, 1));
return mat;
}
}
#endif //GL_TEMPLATE_GLMUTILS_H

View File

@@ -1,13 +1,17 @@
#version 440 core #version 440 core
uniform mat4 pvm;
layout(location=0) in vec3 vCol; layout(location=0) in vec3 vCol;
layout(location=1) in vec2 vPos; layout(location=1) in vec2 vPos;
smooth out vec3 color; smooth out vec3 color;
layout(std140, binding=3) uniform Matrices {
mat4 proj;
mat4 view;
mat4 model;
};
void main() { void main() {
gl_Position = pvm * vec4(vPos, 0, 1); gl_Position = proj * view * model * vec4(vPos, 0, 1);
color = vCol; color = vCol;
} }

View File

@@ -1,5 +1,6 @@
#include <framework.h> #include <framework.h>
#include <util.h> #include <util.h>
#include "glmutil.h"
#include <glm/vec3.hpp> #include <glm/vec3.hpp>
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
@@ -18,14 +19,33 @@ struct Vertex {
glm::vec3 col; glm::vec3 col;
}; };
struct Matrices {
glm::mat4 proj;
glm::mat4 view;
glm::mat4 model;
};
class GLApp : public App { class GLApp : public App {
private: private:
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
GLuint vertex_array = 0; Matrices mats{
GLuint vertex_buffer = 0; glm::identity<glm::mat4>(),
glm::identity<glm::mat4>(),
glm::identity<glm::mat4>(),
};
glm::vec2 mouse_root = glm::vec2(0);
glm::vec2 angle_root = glm::vec2(0);
glm::vec2 angles = glm::vec2(0);
GLuint circle_vert_arr = 0;
GLuint circle_vert_buf = 0, matrix_buffer = 0;
GLuint vertex_shader = 0, fragment_shader = 0, program = 0; GLuint vertex_shader = 0, fragment_shader = 0, program = 0;
GLuint pvm_location = 0, vpos_location = 0, vcol_location = 0; GLuint vpos_location = 0, vcol_location = 0;
GLuint matrices_index = 0;
GLuint matrices_binding_point = 0;
protected: protected:
void onKey(int key, int scan_code, int action, int mods) override { void onKey(int key, int scan_code, int action, int mods) override {
@@ -33,12 +53,32 @@ protected:
close(); close();
} }
void onMouseButton(int button, int action, int mods) override {
if (button == 0 && action == GLFW_PRESS) {
double x, y;
glfwGetCursorPos(getWindow(), &x, &y);
mouse_root = glm::vec2(x, y);
angle_root = angles;
}
}
void onCursorPos(double x, double y)
override {
if (glfwGetMouseButton(getWindow(), 0)) {
auto dx = (float) x - mouse_root.x;
auto dy = (float) y - mouse_root.y;
angles = angle_root + glm::vec2(dx, dy) / 100.f;
}
}
void init() override { void init() override {
vertices.push_back({ vertices.push_back({
glm::vec2(0), glm::vec3(1) glm::vec2(0), glm::vec3(1)
}); });
const int N = 16; const int N = 60;
const float TAU = 6.28318f; const float TAU = 6.28318f;
for (int i = 0; i <= N; ++i) { for (int i = 0; i <= N; ++i) {
@@ -48,17 +88,18 @@ protected:
auto c = glm::vec3(t) + glm::vec3(0, 1, 2) / 3.f; auto c = glm::vec3(t) + glm::vec3(0, 1, 2) / 3.f;
vertices.push_back({ vertices.push_back({
glm::cos(TAU * p), glm::cos(TAU * c) glm::cos(TAU * p),
glm::cos(TAU * c)
}); });
} }
setTitle("Hello Square!"); setTitle("Hello Square!");
glGenVertexArrays(1, &vertex_array); glGenVertexArrays(1, &circle_vert_arr);
glBindVertexArray(vertex_array); glBindVertexArray(circle_vert_arr);
glGenBuffers(1, &vertex_buffer); glGenBuffers(1, &circle_vert_buf);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); glBindBuffer(GL_ARRAY_BUFFER, circle_vert_buf);
util::bufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW); util::bufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
program = util::buildProgram({ program = util::buildProgram({
@@ -66,11 +107,17 @@ protected:
fragment_shader = util::buildShader("shaders/main.frag"), fragment_shader = util::buildShader("shaders/main.frag"),
}); });
pvm_location = (GLuint) glGetUniformLocation(program, "pvm"); glGenBuffers(1, &matrix_buffer);
vpos_location = (GLuint) glGetAttribLocation(program, "vPos"); vpos_location = (GLuint) glGetAttribLocation(program, "vPos");
vcol_location = (GLuint) glGetAttribLocation(program, "vCol"); vcol_location = (GLuint) glGetAttribLocation(program, "vCol");
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); matrices_index = (GLuint) glGetUniformBlockIndex(program, "Matrices");
glBindBufferBase(GL_UNIFORM_BUFFER, matrices_binding_point, matrix_buffer);
glUniformBlockBinding(program, matrices_index, matrices_binding_point);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, circle_vert_buf);
glEnableVertexAttribArray(vpos_location); glEnableVertexAttribArray(vpos_location);
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void *) nullptr); glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 5, (void *) nullptr);
glEnableVertexAttribArray(vcol_location); glEnableVertexAttribArray(vcol_location);
@@ -80,31 +127,41 @@ protected:
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void display() override { void display()
override {
int width, height; int width, height;
float ratio; float ratio;
glfwGetFramebufferSize(getWindow(), &width, &height); glfwGetFramebufferSize(getWindow(), &width, &height
);
ratio = (float) width / height; ratio = (float) width / height;
glViewport(0, 0, width, height); glViewport(0, 0, width, height);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
auto pvm = glm::ortho(-ratio, ratio, -1.f, 1.f); mats.proj = glm::ortho(-ratio, ratio, -1.f, 1.f);
pvm = glm::rotate(pvm, (float) glfwGetTime(), glm::vec3(0.f, 0.f, 1.f)); mats.view = glmutil::scale(glm::vec3(0.9f)) * glmutil::eulerAngles(glm::vec3(angles.y, 0, angles.x));
pvm = glm::scale(pvm, glm::vec3(0.9f)); mats.model = glmutil::rotation((float) glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
glBindVertexArray(vertex_array); glBindBuffer(GL_UNIFORM_BUFFER, matrix_buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(Matrices), &mats, GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glBindVertexArray(circle_vert_arr);
glUseProgram(program); glUseProgram(program);
glUniformMatrix4fv(pvm_location, 1, GL_FALSE, glm::value_ptr(pvm));
glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) vertices.size()); glDrawArrays(GL_TRIANGLE_FAN, 0, (GLsizei) vertices.size());
glBindVertexArray(0); glBindVertexArray(0);
swapBuffers(); swapBuffers();
} }
void deinit() override { void deinit()
glDeleteBuffers(1, &vertex_buffer);
override {
glDeleteBuffers(1, &circle_vert_buf);
glDeleteVertexArrays(1, &circle_vert_arr);
glDeleteProgram(program); glDeleteProgram(program);
glDeleteShader(vertex_shader); glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader); glDeleteShader(fragment_shader);
@@ -116,6 +173,7 @@ public:
int main() { int main() {
GLApp app = GLApp(); GLApp
app = GLApp();
app.launch(); app.launch();
} }