working rotation and zoom. pan bad

This commit is contained in:
2025-08-18 13:41:15 -05:00
parent 2a1654e80c
commit a00bac0b3f
15 changed files with 320 additions and 204 deletions

3
.gitmodules vendored
View File

@@ -1,3 +1,6 @@
[submodule "ext/glfw"]
path = ext/glfw
url = https://github.com/glfw/glfw.git
[submodule "ext/glm"]
path = ext/glm
url = https://github.com/g-truc/glm.git

View File

@@ -72,7 +72,7 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>$(SolutionDir)ext\glfw\build\src\Debug;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64)</LibraryPath>
<IncludePath>$(SolutionDir)ext\glfw\include;$(SolutionDir)inc;$(IncludePath)</IncludePath>
<IncludePath>$(SolutionDir)ext\glm;$(SolutionDir)ext\glfw\include;$(SolutionDir)inc;$(IncludePath)</IncludePath>
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
<SourcePath>$(SolutionDir)src;$(SourcePath)</SourcePath>
@@ -111,7 +111,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp17</LanguageStandard>
<LanguageStandard>stdcpp20</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -136,6 +136,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="src\body.cpp" />
<ClCompile Include="src\glad.c" />
<ClCompile Include="src\main.cpp" />
<ClCompile Include="src\shaders.cpp" />

View File

@@ -27,5 +27,8 @@
<ClCompile Include="src\glad.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\body.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -1,25 +1,31 @@
[
{
"directory": "C:/Users/sethh/Documents/repos/LivePlotter/",
"command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/sethh/Documents/repos/LivePlotter/src/util.cpp\" -std=c++17 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/sethh/Documents/repos/LivePlotter/src/util.cpp"
"directory": "C:/Users/seth/Documents/repos/LivePlotter/",
"command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/main.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/seth/Documents/repos/LivePlotter/src/main.cpp"
}
,
{
"directory": "C:/Users/sethh/Documents/repos/LivePlotter/",
"command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c \"C:/Users/sethh/Documents/repos/LivePlotter/src/glad.c\" -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/sethh/Documents/repos/LivePlotter/src/glad.c"
"directory": "C:/Users/seth/Documents/repos/LivePlotter/",
"command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/shaders.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/seth/Documents/repos/LivePlotter/src/shaders.cpp"
}
,
{
"directory": "C:/Users/sethh/Documents/repos/LivePlotter/",
"command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/sethh/Documents/repos/LivePlotter/src/shaders.cpp\" -std=c++17 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/sethh/Documents/repos/LivePlotter/src/shaders.cpp"
"directory": "C:/Users/seth/Documents/repos/LivePlotter/",
"command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c \"C:/Users/seth/Documents/repos/LivePlotter/src/glad.c\" -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/seth/Documents/repos/LivePlotter/src/glad.c"
}
,
{
"directory": "C:/Users/sethh/Documents/repos/LivePlotter/",
"command": "\"C:/Users/sethh/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/sethh/Documents/repos/LivePlotter/src/main.cpp\" -std=c++17 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/atlmfc/include\" -isystem\"C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/sethh/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/sethh/Documents/repos/LivePlotter/src/main.cpp"
"directory": "C:/Users/seth/Documents/repos/LivePlotter/",
"command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/util.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/seth/Documents/repos/LivePlotter/src/util.cpp"
}
,
{
"directory": "C:/Users/seth/Documents/repos/LivePlotter/",
"command": "\"C:/Users/seth/AppData/Roaming/ClangPowerTools/LLVM_Lite/Bin/clang++.exe\" -x c++ \"C:/Users/seth/Documents/repos/LivePlotter/src/body.cpp\" -std=c++20 -Wall -fms-compatibility-version=19.10 -Wmicrosoft -Wno-invalid-token-paste -Wno-unknown-pragmas -Wno-unused-value -fsyntax-only \"-DUNICODE\" \"-D_UNICODE\" \"-D_MT\" \"-D_DLL\" \"-D_DEBUG\" \"-D_CONSOLE\" \"-D_DEBUG_FUNCTIONAL_MACHINERY\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/atlmfc/include\" -isystem\"C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/VS/include\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/ucrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/um\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/shared\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/winrt\" -isystem\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.26100.0/cppwinrt\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glm\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/ext/glfw/include\" -isystem\"C:/Users/seth/Documents/repos/LivePlotter/inc\"",
"file": "C:/Users/seth/Documents/repos/LivePlotter/src/body.cpp"
}
]

1
ext/glm Submodule

Submodule ext/glm added at 2d4c4b4dd3

19
inc/body.hpp Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include <glm/ext/matrix_float4x4.hpp>
#include <glm/glm.hpp>
#include "util.hpp"
struct body {
glm::mat4 pose;
uint ebo;
uint vao;
uint vbo;
uint shader;
array<float> verts;
array<int> faces;
glm::vec4 color;
};
bool load_body(body* out_body, const char* obj_filepath);
void draw_body(const body& b);

View File

@@ -1,3 +0,0 @@
#include "util.hpp"

View File

@@ -2,18 +2,16 @@
#include <glad/glad.h>
#include <variant>
#include <glm/glm.hpp>
#include "util.hpp"
namespace shader {
// Reads shader source files, compiles, and links
bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepath);
bool load_shader(uint* out_id, const char* vertex_filepath, const char* fragment_filepath);
// Sets shader as active on the gpu
void use(uint id);
void use_shader(uint id);
// Set uniform value
typedef std::variant<int, float, bool, vec4, vec3, vec2, vec4i, vec3i, vec2i> uniform_variant;
typedef std::variant<int, float, bool, glm::vec4, glm::vec3, glm::vec2, glm::ivec4, glm::ivec3, glm::ivec2, glm::mat4>
uniform_variant;
void set_uniform(uint id, const char* name, uniform_variant value);
} // namespace shaders

View File

@@ -5,45 +5,9 @@
template<class T> struct array {
T* data;
size_t len;
T& operator[](int i);
inline T& operator[](int i) { return data[i]; }
};
typedef unsigned int uint;
bool read_file(array<char>* out, const char* filepath);
struct vec4 {
float x;
float y;
float z;
float w;
};
struct vec3 {
float x;
float y;
float z;
};
struct vec2 {
float x;
float y;
};
struct vec4i {
int x;
int y;
int z;
int w;
};
struct vec3i {
int x;
int y;
int z;
};
struct vec2i {
int x;
int y;
};

120
src/body.cpp Normal file
View File

@@ -0,0 +1,120 @@
#include <cassert>
#include <glad/glad.h>
#include "util.hpp"
#include "body.hpp"
#include "shaders.hpp"
enum class ParserState {
PREFIX,
VERTEX,
FACE,
FACE_SKIP,
};
bool load_body(body* out_body, const char* obj_filepath) {
array<char> source;
if (!read_file(&source, obj_filepath)) {
return false;
}
size_t num_verts = 0;
size_t num_faces = 0;
for (int i = 1; i < source.len; i++) {
if (source[i] == ' ' && source[i - 1] == 'v') {
num_verts++;
} else if (source[i] == ' ' && source[i - 1] == 'f') {
num_faces++;
}
}
array<float> verts = { (float*)malloc(sizeof(float) * num_verts * 3), num_verts * 3 };
array<int> faces = { (int*)malloc(sizeof(int) * num_faces * 3), num_faces*3 };
// Get ready for the parsing loop
ParserState state = ParserState::PREFIX;
int vert_i = 0;
int face_i = 0;
int start = 0;
for (int i = 1; i < source.len; i++) {
if (source[i] == '\n') {
state = ParserState::PREFIX;
continue;
}
switch (state) {
case ParserState::PREFIX:
if (source[i - 1] == 'v' && source[i] == ' ') {
state = ParserState::VERTEX;
start = i + 1;
} else if (i > 0 && source[i - 1] == 'f' && source[i] == ' ') {
state = ParserState::FACE;
start = i + 1;
}
break;
case ParserState::VERTEX:
if (source[i] == ' ' || source[i] == '\r' || source[i] == '\n') {
verts[vert_i] = atof(&source[start])/1.5;
vert_i++;
start = i + 1;
}
break;
case ParserState::FACE:
if (source[i] == '/') {
state = ParserState::FACE_SKIP;
faces[face_i] = atoi(&source[start]) - 1;
face_i++;
}
break;
case ParserState::FACE_SKIP:
if (source[i] == ' ') {
state = ParserState::FACE;
start = i + 1;
}
}
}
// Need a good validation check here. This is a stand in.
if (verts.len == 0 || faces.len == 0) {
printf(
"Obj file appears incomplete or corrupted. Num verts %zu. Num Faces %zu.\n", verts.len, faces.len);
return false;
}
uint vao, vbo, ebo;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, verts.len * sizeof(float), verts.data, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, faces.len * sizeof(int), faces.data, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
*out_body = { .pose = glm::mat4(1),
.ebo = ebo,
.vao = vao,
.vbo = vbo,
.shader = 0,
.verts = verts,
.faces = faces,
.color = glm::vec4(0.5, 0.5, 0.5, 1)
};
return true;
}
void draw_body(const body& b) {
use_shader(b.shader);
set_uniform(b.shader, "global_t", b.pose);
set_uniform(b.shader, "color", b.color);
glBindVertexArray(b.vao);
glDrawElements(GL_TRIANGLES, b.faces.len, GL_UNSIGNED_INT, 0);
//glDisableVertexAttribArray(0);
}

View File

@@ -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();
}

View File

@@ -1,5 +1,7 @@
#include <typeinfo>
#include <cstdlib>
#include <stdio.h>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "util.hpp"
#include "shaders.hpp"
@@ -14,11 +16,9 @@ struct overload : Ts ... {
};
template<class... Ts> overload(Ts...) -> overload<Ts...>;
namespace shader {
bool _compile_shader(uint *out_id, const char* filepath, int shader_type);
bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepath) {
bool load_shader(uint* out_id, const char* vertex_filepath, const char* fragment_filepath) {
uint vertex_id;
if (!_compile_shader(&vertex_id, vertex_filepath, GL_VERTEX_SHADER))
return false;
@@ -49,25 +49,24 @@ bool load(uint* out_id, const char* vertex_filepath, const char* fragment_filepa
return true;
}
void use(uint id) { glUseProgram(id); }
void use_shader(uint id) { glUseProgram(id); }
void set_uniform(uint id, const char* name, uniform_variant value) {
const auto visitor = overload {
[id, name](int i) { glUniform1i(glGetUniformLocation(id, name), i); },
[id, name](float f) { glUniform1f(glGetUniformLocation(id, name), f); },
[id, name](bool b) { glUniform1i(glGetUniformLocation(id, name), b); },
[id, name](vec4 v) { glUniform4f(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); },
[id, name](vec3 v) { glUniform3f(glGetUniformLocation(id, name), v.x, v.y, v.z); },
[id, name](vec2 v) { glUniform2f(glGetUniformLocation(id, name), v.x, v.y); },
[id, name](vec4i v) { glUniform4i(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); },
[id, name](vec3i v) { glUniform3i(glGetUniformLocation(id, name), v.x, v.y, v.z); },
[id, name](vec2i v) { glUniform2i(glGetUniformLocation(id, name), v.x, v.y); },
[id, name](glm::vec4 v) { glUniform4f(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); },
[id, name](glm::vec3 v) { glUniform3f(glGetUniformLocation(id, name), v.x, v.y, v.z); },
[id, name](glm::vec2 v) { glUniform2f(glGetUniformLocation(id, name), v.x, v.y); },
[id, name](glm::ivec4 v) { glUniform4i(glGetUniformLocation(id, name), v.x, v.y, v.z, v.w); },
[id, name](glm::ivec3 v) { glUniform3i(glGetUniformLocation(id, name), v.x, v.y, v.z); },
[id, name](glm::ivec2 v) { glUniform2i(glGetUniformLocation(id, name), v.x, v.y); },
[id, name](glm::mat4 v) { glUniformMatrix4fv(glGetUniformLocation(id, name), 1, GL_FALSE, glm::value_ptr(v)); },
};
visit(visitor, value);
}
// Privates
bool _compile_shader(uint *out_id, const char* filepath, int shader_type) {
array<char> source;
if (!read_file(&source, filepath))
@@ -77,6 +76,8 @@ bool _compile_shader(uint *out_id, const char* filepath, int shader_type) {
glShaderSource(id, 1, &source.data, (int*)&source.len);
glCompileShader(id);
free(source.data);
int status;
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE) {
@@ -89,5 +90,3 @@ bool _compile_shader(uint *out_id, const char* filepath, int shader_type) {
*out_id = id;
return status == GL_TRUE;
}
} // namespace shader

View File

@@ -2,8 +2,15 @@
uniform vec4 color;
in vec3 frag_pos;
out vec4 frag_color;
void main() {
frag_color = color;
vec3 dx = dFdx(frag_pos) * 100;
vec3 dy = dFdy(frag_pos) * 100;
vec3 N = normalize(cross(dFdx(frag_pos), dFdy(frag_pos)));
frag_color = color + vec4(N/2, 1)/3;
//frag_color = vec4(length(dx), length(dy), length(dy), 1.0);
//frag_color += color;
}

View File

@@ -1,8 +1,13 @@
#version 330 core
layout (location = 0) in vec3 pos;
uniform vec4 color;
layout (location = 0) in vec3 pos;
out vec3 frag_pos;
uniform mat4 global_t;
uniform mat4 camera_t;
uniform mat4 projection_t;
void main() {
gl_Position = vec4(pos.x, pos.y, pos.z, 1.0);
gl_Position = projection_t * camera_t * global_t * vec4(pos.x, pos.y, pos.z, 1.0);
frag_pos = pos;
}

View File

@@ -1,4 +1,5 @@
#include <cstdio>
#include <assert.h>
#include <stdlib.h>
#include "util.hpp"