click-drag rotation
This commit is contained in:
@@ -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() {}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
28
glapp/include/glmutil.h
Normal 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
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user