Add working camera
This commit is contained in:
parent
890117d3d0
commit
fbb4cd5101
@ -6,8 +6,9 @@ out vec4 vertex_color;
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
|
||||
void main() {
|
||||
gl_Position = projection * model * vec4(pos, 1.0);
|
||||
gl_Position = projection * view * model * vec4(pos, 1.0);
|
||||
vertex_color = vec4(clamp(pos, 0.0f, 1.0f), 1.0f);
|
||||
}
|
||||
|
||||
64
src/camera.cpp
Normal file
64
src/camera.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "camera.h"
|
||||
|
||||
|
||||
Camera::Camera(Vector3 position, Vector3 world_up, f32 yaw, f32 pitch, f32 movement_speed, f32 rotation_speed) : position(position), world_up(world_up), yaw(yaw), pitch(pitch), movement_speed(movement_speed), rotation_speed(rotation_speed) {
|
||||
update_camera(this);
|
||||
}
|
||||
|
||||
void update_camera(Camera *camera) {
|
||||
Vector3 new_front = Vector3(
|
||||
cos(glm::radians(camera->yaw)) * cos(glm::radians(camera->pitch)),
|
||||
sin(glm::radians(camera->pitch)),
|
||||
sin(glm::radians(camera->yaw)) * cos(glm::radians(camera->pitch))
|
||||
);
|
||||
new_front = glm::normalize(new_front);
|
||||
camera->front = new_front;
|
||||
|
||||
camera->right = glm::normalize(glm::cross(camera->front, camera->world_up));
|
||||
camera->up = glm::normalize(glm::cross(camera->right, camera->front));
|
||||
}
|
||||
|
||||
void key_control(Camera *camera, bool *ascii_keys, f32 dt) {
|
||||
f32 velocity = camera->movement_speed * dt;
|
||||
|
||||
if (ascii_keys[GLFW_KEY_W]) {
|
||||
camera->position += camera->front * velocity;
|
||||
}
|
||||
|
||||
if (ascii_keys[GLFW_KEY_S]) {
|
||||
camera->position -= camera->front * velocity;
|
||||
}
|
||||
|
||||
if (ascii_keys[GLFW_KEY_D]) {
|
||||
camera->position += camera->right * velocity;
|
||||
}
|
||||
|
||||
if (ascii_keys[GLFW_KEY_A]) {
|
||||
camera->position -= camera->right * velocity;
|
||||
}
|
||||
}
|
||||
|
||||
void mouse_control(Camera *camera, f32 x_change, f32 y_change) {
|
||||
x_change *= camera->rotation_speed;
|
||||
y_change *= camera->rotation_speed;
|
||||
|
||||
camera->yaw += x_change;
|
||||
camera->pitch += y_change;
|
||||
|
||||
// Clamp camera pitch
|
||||
if (camera->pitch > 89.0f) {
|
||||
camera->pitch = 89.0f;
|
||||
}
|
||||
|
||||
if (camera->pitch < -89.0f) {
|
||||
camera->pitch = -89.0f;
|
||||
}
|
||||
|
||||
update_camera(camera);
|
||||
}
|
||||
|
||||
|
||||
Matrix4 calculate_view_matrix(Camera *camera) {
|
||||
return glm::lookAt(camera->position, camera->position + camera->front, camera->up);
|
||||
}
|
||||
|
||||
28
src/camera.h
Normal file
28
src/camera.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "math.h"
|
||||
|
||||
struct Camera {
|
||||
Vector3 position;
|
||||
Vector3 front = Vector3(0.0f, 0.0f, -1.0f);
|
||||
Vector3 up;
|
||||
Vector3 right;
|
||||
Vector3 world_up;
|
||||
|
||||
f32 yaw;
|
||||
f32 pitch;
|
||||
f32 movement_speed;
|
||||
f32 rotation_speed;
|
||||
|
||||
Camera(Vector3 position, Vector3 up, f32 yaw, f32 pitch, f32 movement_speed, f32 rotation_speed);
|
||||
~Camera() = default;
|
||||
};
|
||||
|
||||
void update_camera(Camera *camera);
|
||||
void key_control(Camera *camera, bool *ascii_keys, f32 dt);
|
||||
void mouse_control(Camera *camera, f32 x_change, f32 y_change);
|
||||
Matrix4 calculate_view_matrix(Camera *camera);
|
||||
64
src/main.cpp
64
src/main.cpp
@ -1,6 +1,7 @@
|
||||
#include "mesh.h"
|
||||
#include "shader.h"
|
||||
#include "window.h"
|
||||
#include "camera.h"
|
||||
|
||||
|
||||
static const char *vertex_shader_code = "shaders/shader.vert";
|
||||
@ -10,9 +11,13 @@ int main() {
|
||||
Mesh *meshes[10] = {nullptr};
|
||||
Shader shaders[10];
|
||||
|
||||
Window window;
|
||||
Window window(1024, 720);
|
||||
bool success = setup_window(&window);
|
||||
|
||||
// Delta
|
||||
f32 dt = 0.0f;
|
||||
f32 last_dt = 0.f;
|
||||
|
||||
{
|
||||
// Create a mesh
|
||||
f32 vertices[] = {
|
||||
@ -29,9 +34,13 @@ int main() {
|
||||
0, 1, 2
|
||||
};
|
||||
|
||||
Mesh *triangle = new Mesh();
|
||||
create_mesh(triangle, vertices, indices, 12, 12);
|
||||
meshes[0] = triangle;
|
||||
Mesh *pyramid1 = new Mesh();
|
||||
create_mesh(pyramid1, vertices, indices, 12, 12);
|
||||
meshes[0] = pyramid1;
|
||||
|
||||
Mesh *pyramid2 = new Mesh();
|
||||
create_mesh(pyramid2, vertices, indices, 12, 12);
|
||||
meshes[1] = pyramid2;
|
||||
}
|
||||
|
||||
{
|
||||
@ -45,33 +54,56 @@ int main() {
|
||||
45.0f, (GLfloat)window.buffer_width / (GLfloat)window.buffer_height, 0.1f,
|
||||
100.0f);
|
||||
|
||||
u32 uniform_projection = 0, uniform_model = 0;
|
||||
f32 current_angle = 0.1f;
|
||||
Camera camera(Vector3(0.0f, 0.0f, 0.0f), Vector3(0.0f, 1.0f, 0.0f), 90.0f, 0.0f, 5.0f, 1.0f);
|
||||
|
||||
// Loop until window is closed
|
||||
while (!glfwWindowShouldClose(window.gl_window)) {
|
||||
// Calculate delta
|
||||
f32 now = glfwGetTime();
|
||||
dt = now - last_dt;
|
||||
last_dt = now;
|
||||
|
||||
// Get and handle user input events
|
||||
glfwPollEvents();
|
||||
|
||||
key_control(&camera, window.ascii_keys, dt);
|
||||
mouse_control(&camera, window.x_change_position, window.y_change_position);
|
||||
|
||||
// This sucks
|
||||
window.x_change_position = 0.0f;
|
||||
window.y_change_position = 0.0f;
|
||||
|
||||
// Clear window
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glUseProgram(shaders[0].id);
|
||||
uniform_model = shaders[0].uniform_model;
|
||||
uniform_projection = shaders[0].uniform_projection;
|
||||
|
||||
Matrix4 model(1.0f);
|
||||
model = glm::translate(model, Vector3(0.0f, 0.0f, -2.5f));
|
||||
model = glm::rotate(model, current_angle * RADIAN_FACTOR, Vector3(0.0f, 1.0f, 0.0f));
|
||||
model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f));
|
||||
{
|
||||
Matrix4 model(1.0f);
|
||||
model = glm::translate(model, Vector3(0.0f, 0.0f, -2.5f));
|
||||
// model = glm::rotate(model, current_angle * RADIAN_FACTOR, Vector3(0.0f, 1.0f, 0.0f));
|
||||
model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f));
|
||||
|
||||
current_angle += 0.5f;
|
||||
glUniformMatrix4fv(shaders[0].uniform_model, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glUniformMatrix4fv(shaders[0].uniform_projection, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
render_mesh(meshes[0]);
|
||||
}
|
||||
|
||||
glUniformMatrix4fv(uniform_model, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glUniformMatrix4fv(uniform_projection, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
{
|
||||
Matrix4 model(1.0f);
|
||||
model = glm::translate(model, Vector3(0.0f, 0.0f, -3.5f));
|
||||
// model = glm::rotate(model, current_angle * RADIAN_FACTOR, Vector3(0.0f, 1.0f, 0.0f));
|
||||
model = glm::scale(model, Vector3(0.4f, 0.4f, 1.0f));
|
||||
|
||||
glUniformMatrix4fv(shaders[0].uniform_model, 1, GL_FALSE, glm::value_ptr(model));
|
||||
glUniformMatrix4fv(shaders[0].uniform_projection, 1, GL_FALSE, glm::value_ptr(projection));
|
||||
render_mesh(meshes[1]);
|
||||
}
|
||||
|
||||
Matrix4 view = calculate_view_matrix(&camera);
|
||||
glUniformMatrix4fv(shaders[0].uniform_view, 1, GL_FALSE, glm::value_ptr(view));
|
||||
|
||||
render_mesh(meshes[0]);
|
||||
|
||||
glUseProgram(0);
|
||||
|
||||
|
||||
@ -63,6 +63,7 @@ bool create_shader(Shader *shader, const char *vertex_shader_path, const char *f
|
||||
|
||||
shader->uniform_projection = glGetUniformLocation(shader->id, "projection");
|
||||
shader->uniform_model = glGetUniformLocation(shader->id, "model");
|
||||
shader->uniform_view = glGetUniformLocation(shader->id, "view");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ struct Shader {
|
||||
u32 id;
|
||||
u32 uniform_projection;
|
||||
u32 uniform_model;
|
||||
u32 uniform_view;
|
||||
|
||||
Shader();
|
||||
~Shader();
|
||||
|
||||
@ -1,5 +1,23 @@
|
||||
#include "window.h"
|
||||
|
||||
|
||||
|
||||
Window::Window(u32 window_width, u32 window_height) {
|
||||
width = window_width;
|
||||
height = window_height;
|
||||
x_change_position = 0.0f;
|
||||
y_change_position = 0.0f;
|
||||
|
||||
for (size_t i = 0; i < 1024; i++) {
|
||||
ascii_keys[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
glfwDestroyWindow(gl_window);
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
bool setup_window(Window *window) {
|
||||
// Initialize GLFW
|
||||
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND);
|
||||
@ -20,7 +38,7 @@ bool setup_window(Window *window) {
|
||||
|
||||
window->gl_window = glfwCreateWindow(window->width, window->height, "Test Window", NULL, NULL);
|
||||
|
||||
if (!window) {
|
||||
if (!window->gl_window) {
|
||||
const char *desc;
|
||||
int code = glfwGetError(&desc);
|
||||
printf("GLFW window creation failed!");
|
||||
@ -36,7 +54,10 @@ bool setup_window(Window *window) {
|
||||
// Set context for GLEW to use
|
||||
glfwMakeContextCurrent(window->gl_window);
|
||||
|
||||
glGetError();
|
||||
glfwSetKeyCallback(window->gl_window, handle_keys);
|
||||
glfwSetCursorPosCallback(window->gl_window, handle_mouse);
|
||||
// Captures the mouse
|
||||
glfwSetInputMode(window->gl_window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
|
||||
|
||||
// Allow modern extension features
|
||||
glewExperimental = GL_TRUE;
|
||||
@ -56,5 +77,43 @@ bool setup_window(Window *window) {
|
||||
// Setup viewport size
|
||||
glViewport(0, 0, window->buffer_width, window->buffer_height);
|
||||
|
||||
glfwSetWindowUserPointer(window->gl_window, window);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void handle_keys(GLFWwindow *gl_window, int key, int code, int action, int mode) {
|
||||
Window *window = static_cast<Window *>(glfwGetWindowUserPointer(gl_window));
|
||||
|
||||
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
|
||||
glfwSetWindowShouldClose(gl_window, GL_TRUE);
|
||||
}
|
||||
|
||||
if (key >= 0 && key < 1024) {
|
||||
if (action == GLFW_PRESS) {
|
||||
window->ascii_keys[key] = true;
|
||||
} else if (action == GLFW_RELEASE) {
|
||||
window->ascii_keys[key] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handle_mouse(GLFWwindow *gl_window, f64 x_position, f64 y_position) {
|
||||
Window *window = static_cast<Window *>(glfwGetWindowUserPointer(gl_window));
|
||||
|
||||
if (window->first_mouse_movement) {
|
||||
window->last_x_position = x_position;
|
||||
window->last_y_position = y_position;
|
||||
window->first_mouse_movement = false;
|
||||
}
|
||||
|
||||
window->x_change_position = x_position - window->last_x_position;
|
||||
// The order here is to avoid up/down inversion
|
||||
window->y_change_position = window->last_y_position - y_position;
|
||||
|
||||
window->last_x_position = x_position;
|
||||
window->last_y_position = y_position;
|
||||
|
||||
// @Todo: reset x/y_change_position back to 0.0f
|
||||
}
|
||||
|
||||
|
||||
14
src/window.h
14
src/window.h
@ -12,7 +12,19 @@ struct Window {
|
||||
u32 width = 800, height = 600;
|
||||
s32 buffer_width, buffer_height;
|
||||
GLFWwindow *gl_window = nullptr;
|
||||
bool ascii_keys[1024];
|
||||
|
||||
// Camera coords
|
||||
f32 last_x_position;
|
||||
f32 last_y_position;
|
||||
f32 x_change_position;
|
||||
f32 y_change_position;
|
||||
bool first_mouse_movement;
|
||||
|
||||
Window(u32 window_width, u32 window_height);
|
||||
~Window();
|
||||
};
|
||||
|
||||
bool setup_window(Window *window);
|
||||
|
||||
void handle_keys(GLFWwindow *gl_window, int key, int code, int action, int mode);
|
||||
void handle_mouse(GLFWwindow *gl_window, f64 x_position, f64 y_position);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user