working rotation and zoom. pan bad
This commit is contained in:
240
src/main.cpp
240
src/main.cpp
@@ -1,24 +1,91 @@
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <glad/glad.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <iostream>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
#include <stdio.h>
|
||||
#include <optional>
|
||||
|
||||
#include "util.hpp"
|
||||
#include "shaders.hpp"
|
||||
#include "body.hpp"
|
||||
|
||||
static GLFWwindow* window;
|
||||
static float width, height;
|
||||
|
||||
void framebuffer_size_callback(GLFWwindow* window, int width, int height) { glViewport(0, 0, width, height); }
|
||||
|
||||
void processInput(GLFWwindow* window) {
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
void framebuffer_size_callback(GLFWwindow* window, int w, int h) {
|
||||
width = w;
|
||||
height = h;
|
||||
glViewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
bool glfw_window_setup() {
|
||||
void process_input() {
|
||||
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
|
||||
}
|
||||
|
||||
static bool mouse_pressed = false;
|
||||
static bool scroll_pressed = false;
|
||||
static double prev_cursor_x, prev_cursor_y;
|
||||
|
||||
static double theta = 0.0; // angle of camera trans vect wrt x-z plane
|
||||
static double phi = 0.0; // angle of camera trans vect wrt x-axis
|
||||
|
||||
static glm::vec3 camera_loc = glm::vec3(0, 0, 2);
|
||||
static glm::vec3 focal_point = glm::vec3(0, 0, 0);
|
||||
static glm::vec3 up = glm::vec3(0, 1, 0);
|
||||
static glm::mat4 camera_t = glm::lookAt(camera_loc, focal_point, up);
|
||||
|
||||
static glm::vec4 strafe_x = camera_t[0];
|
||||
static glm::vec4 strafe_y = camera_t[1];
|
||||
|
||||
static void cursor_position_callback(GLFWwindow* window, double xpos, double ypos) {
|
||||
float dx = (xpos - prev_cursor_x);
|
||||
float dy = (ypos - prev_cursor_y);
|
||||
prev_cursor_x = xpos;
|
||||
prev_cursor_y = ypos;
|
||||
if (mouse_pressed) {
|
||||
phi += dx / width * glm::radians(360.0);
|
||||
theta += dy / height * glm::radians(360.0);
|
||||
}
|
||||
|
||||
if (scroll_pressed) {
|
||||
focal_point += strafe_x * (dx/300) + strafe_y * (dy/300);
|
||||
}
|
||||
|
||||
double len = glm::length(camera_loc);
|
||||
camera_loc.x = len * glm::cos(theta) * glm::cos(-phi);
|
||||
camera_loc.y = len * glm::sin(theta);
|
||||
camera_loc.z = -len * glm::cos(theta) * glm::sin(-phi);
|
||||
|
||||
camera_t = glm::lookAt(camera_loc, focal_point, up);
|
||||
}
|
||||
|
||||
void mouse_button_callback(GLFWwindow* window, int button, int action, int mods) {
|
||||
if (button == GLFW_MOUSE_BUTTON_RIGHT) {
|
||||
mouse_pressed = action == GLFW_PRESS;
|
||||
}
|
||||
|
||||
if (button == GLFW_MOUSE_BUTTON_MIDDLE) {
|
||||
scroll_pressed = action == GLFW_PRESS;
|
||||
strafe_x = camera_t[0];
|
||||
strafe_y = camera_t[1];
|
||||
}
|
||||
|
||||
glfwGetCursorPos(window, &prev_cursor_x, &prev_cursor_y);
|
||||
}
|
||||
|
||||
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
glm::vec4 k = camera_t[2];
|
||||
float d = yoffset;
|
||||
|
||||
camera_loc += k * (-d * glm::length(camera_loc) / 10);
|
||||
|
||||
camera_t = glm::lookAt(camera_loc, focal_point, up);
|
||||
}
|
||||
|
||||
bool glfw_setup() {
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
@@ -26,147 +93,72 @@ bool glfw_window_setup() {
|
||||
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
window = glfwCreateWindow(800, 800, "LearnOpenGL", NULL, NULL);
|
||||
if (window == NULL) {
|
||||
std::cout << "Failed to create GLFW windoww" << std::endl;
|
||||
printf("Failed to create GLFW window\n");
|
||||
glfwTerminate();
|
||||
return false;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
glfwSetCursorPosCallback(window, cursor_position_callback);
|
||||
glfwSetMouseButtonCallback(window, mouse_button_callback);
|
||||
glfwSetScrollCallback(window, scroll_callback);
|
||||
|
||||
cursor_position_callback(window, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class ParserState {
|
||||
PREFIX,
|
||||
VERTEX,
|
||||
FACE,
|
||||
FACE_SKIP,
|
||||
};
|
||||
std::optional<std::pair<array<float>, array<unsigned int>>> load_icosphere() {
|
||||
std::FILE* f = NULL;
|
||||
|
||||
if (fopen_s(&f, "Icosphere.obj", "r")) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// MEMORY LEAK!!! 84 verts currently
|
||||
float* vert_data = (float*)malloc(sizeof(float) * 128);
|
||||
size_t vert_data_size = 0;
|
||||
|
||||
// MEMORY LEAK!!! (I think)
|
||||
unsigned int* indices_data = (unsigned int*)malloc(sizeof(int) * 256);
|
||||
size_t indices_data_size = 0;
|
||||
|
||||
ParserState state = ParserState::PREFIX;
|
||||
|
||||
char ln[128];
|
||||
int len = 0;
|
||||
int start = 0;
|
||||
while ((ln[len] = std::fgetc(f)) != EOF) {
|
||||
switch (state) {
|
||||
case ParserState::PREFIX:
|
||||
if (len > 0 && ln[len - 1] == 'v' && ln[len] == ' ') {
|
||||
state = ParserState::VERTEX;
|
||||
start = len + 1;
|
||||
} else if (len > 0 && ln[len - 1] == 'f' && ln[len] == ' ') {
|
||||
state = ParserState::FACE;
|
||||
start = len + 1;
|
||||
}
|
||||
break;
|
||||
case ParserState::VERTEX:
|
||||
if (ln[len] == ' ' || ln[len] == '\n') {
|
||||
vert_data[vert_data_size] = atof(&ln[start]);
|
||||
vert_data_size++;
|
||||
start = len + 1;
|
||||
}
|
||||
break;
|
||||
case ParserState::FACE:
|
||||
if (ln[len] == '/') {
|
||||
state = ParserState::FACE_SKIP;
|
||||
indices_data[indices_data_size] = atoi(&ln[start]) - 1;
|
||||
indices_data_size++;
|
||||
}
|
||||
break;
|
||||
case ParserState::FACE_SKIP:
|
||||
if (ln[len] == ' ') {
|
||||
state = ParserState::FACE;
|
||||
start = len + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ln[len] == '\n') {
|
||||
len = 0;
|
||||
state = ParserState::PREFIX;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
|
||||
array<float> verts = { vert_data, vert_data_size };
|
||||
array<unsigned int> indices = { indices_data, indices_data_size };
|
||||
|
||||
return std::make_pair(verts, indices);
|
||||
}
|
||||
|
||||
int main() {
|
||||
if (!glfw_window_setup())
|
||||
if (!glfw_setup())
|
||||
return -1;
|
||||
|
||||
auto data = load_icosphere();
|
||||
if (!data) {
|
||||
std::cout << "ERROR loading the icosphere obj file failed" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto verts = data.value().first;
|
||||
auto indices = data.value().second;
|
||||
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
std::cout << "Failed to initialize GLAD" << std::endl;
|
||||
printf("Failed to initialize GLAD\n");
|
||||
return -1;
|
||||
}
|
||||
glViewport(0, 0, 800, 800);
|
||||
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||
width = 800;
|
||||
height = 800;
|
||||
|
||||
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
uint shader;
|
||||
const char* vertex_filepath = "src/shaders/vertex.glsl";
|
||||
const char* fragment_filepath = "src/shaders/fragment.glsl";
|
||||
if (!load_shader(&shader, vertex_filepath, fragment_filepath))
|
||||
return -1;
|
||||
|
||||
//glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
|
||||
glClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT); // Write to back buffer
|
||||
|
||||
glfwSwapBuffers(window); // front buffer is now back
|
||||
glClear(GL_COLOR_BUFFER_BIT); // Write to back buffer again (former front buf)
|
||||
|
||||
unsigned int VAO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
unsigned int VBO;
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, verts.len * sizeof(float), verts.data, GL_STATIC_DRAW);
|
||||
|
||||
unsigned int EBO;
|
||||
glGenBuffers(1, &EBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.len * sizeof(unsigned int), indices.data, GL_STATIC_DRAW);
|
||||
|
||||
uint program_id;
|
||||
const char* vertex_filepath = "src/shaders/vertex.glsl";
|
||||
const char* fragment_filepath = "src/shaders/fragment.glsl";
|
||||
if (!shader::load(&program_id, vertex_filepath, fragment_filepath))
|
||||
body b;
|
||||
if (!load_body(&b, "Icosphere.obj"))
|
||||
return -1;
|
||||
shader::use(program_id);
|
||||
|
||||
// Tell opengl which attribute our data is for (i.e. location)
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
b.shader = shader;
|
||||
b.pose = glm::translate(b.pose, glm::vec3(0, 0, 0));
|
||||
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
//set_uniform(shader, "color", glm::vec4 { sin(time), sin(time + glm::radians(45.0f)), sin(time + glm::radians(90.0f)), 1.0 } / 2.0f);
|
||||
//time = glfwGetTime();
|
||||
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
float time;
|
||||
|
||||
glm::mat4 projection_t
|
||||
= glm::perspective(glm::radians(60.0f), (float)width / (float)height, 0.1f, 1300.0f);
|
||||
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
float time = glfwGetTime();
|
||||
shader::set_uniform(program_id, "color", vec4 { 1, sin(time), 1, 1.0 });
|
||||
shader::use(program_id);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDrawElements(GL_TRIANGLES, indices.len, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(VAO);
|
||||
process_input();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
set_uniform(b.shader, "projection_t", projection_t);
|
||||
set_uniform(b.shader, "camera_t", camera_t);
|
||||
draw_body(b);
|
||||
|
||||
processInput(window);
|
||||
glfwSwapBuffers(window);
|
||||
glfwPollEvents();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user