Initial Commit
This commit is contained in:
commit
913950478c
10 changed files with 775 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
cmake-build-debug
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "contrib/imgui"]
|
||||
path = contrib/imgui
|
||||
url = git@github.com:ocornut/imgui.git
|
||||
29
CMakeLists.txt
Normal file
29
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
cmake_minimum_required(VERSION 3.28)
|
||||
project(ModelExtractor)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
find_package(SDL2 CONFIG REQUIRED)
|
||||
find_package(glm CONFIG REQUIRED)
|
||||
find_package(GLEW REQUIRED)
|
||||
|
||||
add_subdirectory(contrib)
|
||||
|
||||
add_executable(ModelExtractor main.cpp
|
||||
gl_debug.cpp
|
||||
gl_debug.h)
|
||||
target_link_libraries(ModelExtractor SDL2::SDL2 GLEW::GLEW GL imgui glm)
|
||||
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
|
||||
target_compile_definitions(ModelExtractor PRIVATE __DEBUG)
|
||||
endif()
|
||||
target_compile_options(ModelExtractor PUBLIC -Wall -Wextra)
|
||||
|
||||
add_custom_command(TARGET ModelExtractor
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/base.vert
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/base.vert)
|
||||
|
||||
add_custom_command(TARGET ModelExtractor
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shaders/base.frag
|
||||
${CMAKE_CURRENT_BINARY_DIR}/shaders/base.frag)
|
||||
4
contrib/CMakeLists.txt
Normal file
4
contrib/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
add_library(imgui STATIC imgui/imgui.cpp imgui/imgui_draw.cpp imgui/imgui_tables.cpp imgui/imgui_widgets.cpp imgui/backends/imgui_impl_sdl2.cpp imgui/backends/imgui_impl_opengl3.cpp)
|
||||
target_link_libraries(imgui SDL2::SDL2 GL)
|
||||
target_include_directories(imgui PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/imgui)
|
||||
target_compile_options(imgui PUBLIC -Wall -Wextra)
|
||||
1
contrib/imgui
Submodule
1
contrib/imgui
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit f9cda1fa245b361a0e98428d88470eebaa187e5b
|
||||
80
gl_debug.cpp
Normal file
80
gl_debug.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
#include <iostream>
|
||||
#include "gl_debug.h"
|
||||
|
||||
#ifdef __DEBUG
|
||||
void GLAPIENTRY debug_func(GLenum source, GLenum type, GLuint, GLenum severity, GLsizei, const GLchar* msg, const void*) {
|
||||
const char* src;
|
||||
switch(source) {
|
||||
case GL_DEBUG_SOURCE_API:
|
||||
src = "[SOURCE_API]";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_OTHER:
|
||||
src = "[SOURCE_OTHER]";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_THIRD_PARTY:
|
||||
src = "[SOURCE_THIRD_PARTY]";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_APPLICATION:
|
||||
src = "[SOURCE_APP]";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER:
|
||||
src = "[SOURCE_SHADER_COMPILER]";
|
||||
break;
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
|
||||
src = "[SOURCE_WIN_SYS]";
|
||||
break;
|
||||
default:
|
||||
src = "[SOURCE_UNKNOWN]";
|
||||
break;
|
||||
}
|
||||
|
||||
const char* tp;
|
||||
switch(type) {
|
||||
case GL_DEBUG_TYPE_ERROR:
|
||||
tp = "[TYPE_ERROR]";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_OTHER:
|
||||
tp = "[TYPE_OTHER]";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_MARKER:
|
||||
tp = "[TYPE_MARKER]";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PERFORMANCE:
|
||||
tp = "[TYPE_PERF]";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_PORTABILITY:
|
||||
tp = "[TYPE_PORT]";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
|
||||
tp = "[TYPE_DEPRECATED]";
|
||||
break;
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
|
||||
tp = "[TYPE_UB]";
|
||||
break;
|
||||
default:
|
||||
tp = "[TYPE_UNKNOWN]";
|
||||
break;
|
||||
}
|
||||
|
||||
const char* sv;
|
||||
switch(severity) {
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
sv = "[SEV_LOW]";
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
sv = "[SEV_MED]";
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
sv = "[SEV_HIGH]";
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
||||
return;
|
||||
sv = "[SEV_NOTIF]";
|
||||
break;
|
||||
default:
|
||||
sv = "[SEV_UNKNOWN]";
|
||||
}
|
||||
|
||||
std::cerr << "[GL]" << sv << tp << src << ": " << msg << std::endl;
|
||||
}
|
||||
#endif
|
||||
7
gl_debug.h
Normal file
7
gl_debug.h
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef GL_DEBUG_H
|
||||
#define GL_DEBUG_H
|
||||
#include <GL/glew.h>
|
||||
|
||||
extern void GLAPIENTRY debug_func(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* msg, const void*);
|
||||
|
||||
#endif //GL_DEBUG_H
|
||||
614
main.cpp
Normal file
614
main.cpp
Normal file
|
|
@ -0,0 +1,614 @@
|
|||
#include <iostream>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
#include <glm/gtx/vec_swizzle.hpp>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <GL/glew.h>
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <imgui.h>
|
||||
#include <backends/imgui_impl_sdl2.h>
|
||||
#include <backends/imgui_impl_opengl3.h>
|
||||
#include <filesystem>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef __DEBUG
|
||||
#include "gl_debug.h"
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
bool contains(const std::vector<T>& vec, const T& val) {
|
||||
return std::find(vec.cbegin(), vec.cend(), val) != vec.cend();
|
||||
}
|
||||
|
||||
void print_info_log(GLuint object, bool is_program) {
|
||||
|
||||
GLint info_len = 0;
|
||||
if (is_program) {
|
||||
glGetProgramiv(object, GL_INFO_LOG_LENGTH, &info_len);
|
||||
} else {
|
||||
glGetShaderiv(object, GL_INFO_LOG_LENGTH, &info_len);
|
||||
}
|
||||
|
||||
if (info_len > 0) {
|
||||
std::vector<char> buffer;
|
||||
buffer.resize(info_len);
|
||||
GLint actual_len;
|
||||
|
||||
if (is_program) {
|
||||
glGetProgramInfoLog(object, buffer.size(), &actual_len, buffer.data());
|
||||
} else {
|
||||
glGetShaderInfoLog(object, buffer.size(), &actual_len, buffer.data());
|
||||
}
|
||||
|
||||
std::cout << "[GL] Info log: " << std::endl << buffer.data() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint compile_shader(GLenum type, const char* file) {
|
||||
|
||||
std::vector<GLchar> bytes;
|
||||
std::ifstream stream(file);
|
||||
if (!stream.is_open()) {
|
||||
std::cerr << "[GL] Failed to open file: " << file << std::endl;
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytes.assign(std::istreambuf_iterator<GLchar>(stream), std::istreambuf_iterator<GLchar>());
|
||||
|
||||
auto id = glCreateShader(type);
|
||||
const auto* data = bytes.data();
|
||||
auto len = static_cast<GLint>(bytes.size());
|
||||
glShaderSource(id, 1, &data, &len);
|
||||
glCompileShader(id);
|
||||
|
||||
print_info_log(id, false);
|
||||
|
||||
GLint status = 0;
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (status != GL_TRUE) {
|
||||
std::cerr << "[GL] Failed to compile shader" << std::endl;
|
||||
exit(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
GLuint program = 0;
|
||||
GLuint vao = 0;
|
||||
|
||||
void init_gl(SDL_Window* window, SDL_GLContext context) {
|
||||
#ifdef __DEBUG
|
||||
int count = 0;
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &count);
|
||||
|
||||
std::set<std::string> extensions;
|
||||
for(auto i = 0; i < count; i++) {
|
||||
const char* ext = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i));
|
||||
|
||||
extensions.emplace(ext);
|
||||
}
|
||||
|
||||
if (extensions.contains("GL_KHR_debug")) {
|
||||
std::cout << "[GL] Enabling debug output..." << std::endl;
|
||||
std::cout.flush();
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(debug_func, nullptr);
|
||||
|
||||
std::string msg = "Debug output test";
|
||||
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_OTHER, 494949, GL_DEBUG_SEVERITY_NOTIFICATION, msg.length(), msg.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
glClearColor(0.2, 0.2, 0.23, 1.0);
|
||||
|
||||
auto vsId = compile_shader(GL_VERTEX_SHADER, "shaders/base.vert");
|
||||
std::cout << "[GL] VS Ok." << std::endl;
|
||||
auto fsId = compile_shader(GL_FRAGMENT_SHADER, "shaders/base.frag");
|
||||
std::cout << "[GL] FS Ok." << std::endl;
|
||||
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vsId);
|
||||
glAttachShader(program, fsId);
|
||||
glLinkProgram(program);
|
||||
|
||||
print_info_log(program, true);
|
||||
|
||||
GLint link_status = 0;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &link_status);
|
||||
if (link_status != GL_TRUE) {
|
||||
std::cerr << "[GL] Failed to link program." << std::endl;
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
glDeleteShader(vsId);
|
||||
glDeleteShader(fsId);
|
||||
|
||||
std::cout << "[GL] Program Ok." << std::endl;
|
||||
|
||||
glUseProgram(program);
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplSDL2_InitForOpenGL(window, context);
|
||||
ImGui_ImplOpenGL3_Init("#version 460");
|
||||
|
||||
glCreateVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
}
|
||||
|
||||
char file_input[PATH_MAX];
|
||||
char file_output[PATH_MAX];
|
||||
int resolution[2] = { 1280, 720 };
|
||||
float near = 0.001f;
|
||||
float far = 100.0f;
|
||||
float fov = 30.0f;
|
||||
bool update_render = false;
|
||||
|
||||
float adjust_orientation[2] = {0, 0};
|
||||
|
||||
void load_data(const std::string&);
|
||||
void save_obj(const std::string& path);
|
||||
|
||||
void run_ui() {
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplSDL2_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
bool open_open = false;
|
||||
bool open_save = false;
|
||||
|
||||
ImGui::Begin("Camera settings", nullptr, ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoResize);
|
||||
ImVec2 size = {0, 0};
|
||||
ImGui::SetWindowSize("Camera settings", size, 1);
|
||||
if (ImGui::BeginMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("Open", "Ctrl+O")) {
|
||||
open_open = true;
|
||||
}
|
||||
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S")) {
|
||||
open_save = true;
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
if(ImGui::InputInt2("Resolution", resolution)) {
|
||||
update_render = true;
|
||||
}
|
||||
if(ImGui::InputFloat("Near", &near, 0, 0, "%.5f")) {
|
||||
update_render = true;
|
||||
}
|
||||
if(ImGui::InputFloat("Far", &far, 0, 0, "%.3f")) {
|
||||
update_render = true;
|
||||
}
|
||||
if (ImGui::InputFloat("FoV", &fov, 0, 0, "%.1f")) {
|
||||
update_render = true;
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Adjustments", nullptr, ImGuiWindowFlags_NoResize);
|
||||
ImGui::SetWindowSize("Adjustments", size, 1);
|
||||
ImGui::InputFloat2("Rotation adjust", adjust_orientation, "%.1f");
|
||||
ImGui::End();
|
||||
|
||||
if (open_open) {
|
||||
ImGui::OpenPopup("file_input");
|
||||
}
|
||||
|
||||
if(ImGui::BeginPopup("file_input", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Modal)) {
|
||||
ImGui::Text("Open File");
|
||||
ImGui::Separator();
|
||||
ImGui::InputTextWithHint("Directory Path", "Should contain a bunch of .csv", file_input, PATH_MAX, ImGuiInputTextFlags_None, nullptr, nullptr);
|
||||
|
||||
if (ImGui::Button("Ok")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
load_data(file_input);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (open_save) {
|
||||
ImGui::OpenPopup("file_save");
|
||||
}
|
||||
|
||||
if(ImGui::BeginPopup("file_save", ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Modal)) {
|
||||
ImGui::Text("Save File");
|
||||
ImGui::Separator();
|
||||
ImGui::InputTextWithHint("File Path", "Should end with .obj", file_output, PATH_MAX, ImGuiInputTextFlags_None, nullptr, nullptr);
|
||||
|
||||
if (ImGui::Button("Ok")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
std::filesystem::path target_path(file_output);
|
||||
if (std::filesystem::is_directory(target_path)) {
|
||||
target_path /= "out.obj";
|
||||
}
|
||||
save_obj(target_path.string());
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
}
|
||||
|
||||
|
||||
struct in_vertex {
|
||||
float position[4];
|
||||
float uv[2];
|
||||
};
|
||||
|
||||
struct out_vertex {
|
||||
float position[3];
|
||||
float uv[2];
|
||||
};
|
||||
|
||||
std::vector<in_vertex> loaded_vertices;
|
||||
std::vector<out_vertex> out_vertices;
|
||||
GLuint data_buffer = 0;
|
||||
bool camera_centered = false;
|
||||
|
||||
void load_data(const std::string& path) {
|
||||
std::cout << "[Main] Loading data via: " << path << std::endl;
|
||||
if (!std::filesystem::is_directory(path)) {
|
||||
std::cerr << "[Main] Could not open path." << std::endl;
|
||||
//TODO: Report error
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<in_vertex> vertices;
|
||||
std::filesystem::directory_iterator dir(path);
|
||||
while(dir != std::filesystem::directory_iterator()) {
|
||||
auto entry = *(dir++);
|
||||
if (!entry.is_regular_file() || (entry.path().filename().extension() != ".csv")) {
|
||||
std::cout << "[Main] Invalid file: " << entry.path() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::ifstream fs(entry.path());
|
||||
|
||||
std::stringstream line_stream;
|
||||
|
||||
std::string def;
|
||||
std::getline(fs, def);
|
||||
|
||||
line_stream.str(def);
|
||||
|
||||
std::vector<std::string> indices;
|
||||
while(!line_stream.eof()) {
|
||||
std::string idx;
|
||||
line_stream >> idx;
|
||||
|
||||
if (!idx.empty()) {
|
||||
if (idx.ends_with(',')) {
|
||||
idx = idx.substr(0, idx.length() - 1);
|
||||
}
|
||||
indices.push_back(idx);
|
||||
}
|
||||
}
|
||||
|
||||
std::string target_uvx, target_uvy;
|
||||
|
||||
if (contains<std::string>(indices, "o4.x") && contains<std::string>(indices, "o4.y") && !contains<std::string>(indices, "04.z")) {
|
||||
target_uvx = "o4.x";
|
||||
target_uvy = "o4.y";
|
||||
}
|
||||
|
||||
std::string line;
|
||||
|
||||
while(std::getline(fs, line) && !line.empty()) {
|
||||
size_t i = 0;
|
||||
|
||||
std::stringstream line_stream(line);
|
||||
in_vertex vertex {};
|
||||
bool found_x = false, found_y = false, found_z = false, found_w = false;
|
||||
bool found_uvx = false, found_uvy = false;
|
||||
|
||||
while(i < indices.size()) {
|
||||
std::string data;
|
||||
line_stream >> data;
|
||||
|
||||
if (data.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (data.ends_with(',')) {
|
||||
data = data.substr(0, data.length() - 1);
|
||||
}
|
||||
|
||||
auto val = std::stof(data);
|
||||
auto& index = indices[i];
|
||||
if (index == "out_position.x") {
|
||||
found_x = true;
|
||||
vertex.position[0] = val;
|
||||
}
|
||||
if (index == "out_position.y") {
|
||||
found_y = true;
|
||||
vertex.position[1] = val;
|
||||
}
|
||||
if (index == "out_position.z") {
|
||||
found_z = true;
|
||||
vertex.position[2] = val;
|
||||
}
|
||||
if (index == "out_position.w") {
|
||||
found_w = true;
|
||||
vertex.position[3] = val;
|
||||
}
|
||||
if (index == target_uvx) {
|
||||
found_uvx = true;
|
||||
vertex.uv[0] = val;
|
||||
}
|
||||
if (index == target_uvy) {
|
||||
found_uvy = true;
|
||||
vertex.uv[1] = val;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
if (found_x && found_y && found_z
|
||||
&& found_w && found_uvx && found_uvy) {
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loaded_vertices = std::move(vertices);
|
||||
std::cout << "[Main] Loaded " << loaded_vertices.size() << " vertoces." << std::endl;
|
||||
update_render = true;
|
||||
camera_centered = false;
|
||||
}
|
||||
|
||||
float mouse_sensitivity = 0.005;
|
||||
float camera_yaw = 0, camera_pitch = 0;
|
||||
glm::vec3 camera_position {};
|
||||
glm::quat camera_orientation {};
|
||||
|
||||
|
||||
glm::mat4 display_proj = glm::identity<glm::mat4>();
|
||||
glm::mat4 display_view = glm::identity<glm::mat4>();
|
||||
glm::mat4 display_model = glm::identity<glm::mat4>();
|
||||
glm::vec3 center = {};
|
||||
float size = 0.f;
|
||||
|
||||
|
||||
void save_obj(const std::string& path) {
|
||||
std::ofstream out(path);
|
||||
|
||||
if (out_vertices.size() % 3 != 0) {
|
||||
std::cerr << "Critical error" << std::endl;
|
||||
exit(1);
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto&[position, uv] : out_vertices) {
|
||||
glm::vec4 original_pos = glm::vec4(position[0], position[1], position[2], 1.0);
|
||||
glm::vec3 target_pos = glm::xyz(display_model * original_pos);
|
||||
|
||||
out << "v " << target_pos.x << " " << target_pos.y << " " << target_pos.z << "\n";
|
||||
out << "vt " << uv[0] << " " << (1.0f - uv[1]) << "\n";
|
||||
}
|
||||
|
||||
for(size_t i = 1; i <= out_vertices.size(); i += 3) {
|
||||
out << "f " << i + 2 << "/" << i + 2 << " " << i + 1 << "/" << i + 1 << " " << i << "/" << i << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void update_camera() {
|
||||
glm::mat4 m = glm::translate(glm::identity<glm::mat4>(), -camera_position);
|
||||
camera_orientation = glm::identity<glm::quat>();
|
||||
camera_orientation = glm::rotate(camera_orientation, camera_pitch, {1, 0, 0});
|
||||
camera_orientation = glm::rotate(camera_orientation, camera_yaw, {0, 1, 0});
|
||||
|
||||
display_view = glm::mat4(camera_orientation) * m;
|
||||
}
|
||||
|
||||
void update_adjustments() {
|
||||
display_model = glm::rotate(glm::identity<glm::mat4>(), glm::radians(adjust_orientation[0]), {1, 0, 0});
|
||||
display_model = glm::rotate(display_model, glm::radians(adjust_orientation[1]), {0, 1, 0});
|
||||
}
|
||||
|
||||
bool validate_params() {
|
||||
return fov > 0 && resolution[0] > 0 && resolution[1] > 0 && near > 0 && far > 0;
|
||||
}
|
||||
|
||||
void run_gl(SDL_Window* window) {
|
||||
glUseProgram(program);
|
||||
|
||||
|
||||
if (update_render && !loaded_vertices.empty() && validate_params()) {
|
||||
|
||||
std::cout << "[Main] Params: " << fov << " " << resolution[0] << "x" << resolution[1] << " " << near << " " << far << std::endl;
|
||||
glm::mat4 proj = glm::perspectiveFov<float>(glm::radians(fov), resolution[0], resolution[1], near, far);
|
||||
glm::mat4 inv = glm::inverse(proj);
|
||||
|
||||
std::cout << "[Main] Generating data..." << std::endl;
|
||||
out_vertices.clear();
|
||||
glm::vec3 max(-100000, -10000, -10000);
|
||||
glm::vec3 min(10000, 10000, 10000);
|
||||
for(auto& in : loaded_vertices) {
|
||||
glm::vec4 pos = { in.position[0], in.position[1], in.position[2], in.position[3] };
|
||||
glm::vec4 reverse = inv * pos;
|
||||
reverse /= reverse.w;
|
||||
|
||||
min = glm::min(glm::xyz(reverse), min);
|
||||
max = glm::max(glm::xyz(reverse), max);
|
||||
|
||||
out_vertices.push_back({{reverse.x, reverse.y, reverse.z}, {in.uv[0], in.uv[1]}});
|
||||
}
|
||||
|
||||
center = glm::mix(min, max, 0.5f);
|
||||
auto dist = glm::length(max - min) / 2;
|
||||
size = dist;
|
||||
if (!camera_centered) {
|
||||
camera_yaw = 0;
|
||||
camera_pitch = 0;
|
||||
camera_centered = true;
|
||||
}
|
||||
|
||||
for(auto& v : out_vertices) {
|
||||
v.position[0] -= center.x;
|
||||
v.position[1] -= center.y;
|
||||
v.position[2] -= center.z;
|
||||
}
|
||||
|
||||
if (data_buffer != 0) {
|
||||
glDeleteBuffers(1, &data_buffer);
|
||||
}
|
||||
|
||||
glGenBuffers(1, &data_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, data_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(out_vertex) * out_vertices.size(), out_vertices.data(), GL_STATIC_DRAW);
|
||||
update_render = false;
|
||||
}
|
||||
|
||||
if (data_buffer != 0) {
|
||||
update_camera();
|
||||
update_adjustments();
|
||||
|
||||
int size_x = 0, size_y = 0;
|
||||
SDL_GetWindowSize(window, &size_x, &size_y);
|
||||
display_proj = glm::perspectiveFov<float>(glm::radians(90.0f), size_x, size_y, 0.01f, 1000.0f);
|
||||
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, false, sizeof(out_vertex), nullptr);
|
||||
glUniformMatrix4fv(0, 1, false, glm::value_ptr(display_model));
|
||||
glUniformMatrix4fv(1, 1, false, glm::value_ptr(display_view));
|
||||
glUniformMatrix4fv(2, 1, false, glm::value_ptr(display_proj));
|
||||
glUniform4f(3, 0.9f, 0.9f, 0.9f, 1.0f);
|
||||
glDrawArrays(GL_TRIANGLES, 0, out_vertices.size());
|
||||
}
|
||||
|
||||
run_ui();
|
||||
}
|
||||
|
||||
glm::vec3 camera_movement { 0, 0, 0};
|
||||
bool rotating = false;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
setenv("SDL_VIDEODRIVER", "wayland", 1);
|
||||
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||
#ifdef __DEBUG
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
|
||||
#endif
|
||||
|
||||
auto* win = SDL_CreateWindow("ModelExtractor", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1290, 720, SDL_WINDOW_OPENGL);
|
||||
auto* ctx = SDL_GL_CreateContext(win);
|
||||
|
||||
SDL_ShowWindow(win);
|
||||
SDL_GL_MakeCurrent(win, ctx);
|
||||
|
||||
glewInit();
|
||||
|
||||
init_gl(win, ctx);
|
||||
|
||||
SDL_Event ev;
|
||||
bool alive = true;
|
||||
while(alive) {
|
||||
camera_movement = {0, 0, 0};
|
||||
while(SDL_PollEvent(&ev)) {
|
||||
ImGui_ImplSDL2_ProcessEvent(&ev);
|
||||
switch(ev.type) {
|
||||
case SDL_EventType::SDL_QUIT:
|
||||
alive = false;
|
||||
break;
|
||||
case SDL_EventType::SDL_MOUSEMOTION:
|
||||
if (rotating) {
|
||||
float rot_y = mouse_sensitivity * ev.motion.xrel;
|
||||
float rot_x = mouse_sensitivity * ev.motion.yrel;
|
||||
camera_yaw += rot_y;
|
||||
camera_pitch += rot_x;
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_MOUSEBUTTONDOWN:
|
||||
if (!ImGui::GetIO().WantCaptureMouse) {
|
||||
rotating = true;
|
||||
SDL_CaptureMouse(SDL_TRUE);
|
||||
SDL_SetWindowMouseGrab(win, SDL_TRUE);
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_KEYDOWN:
|
||||
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
||||
switch(ev.key.keysym.sym) {
|
||||
case SDL_KeyCode::SDLK_w:
|
||||
camera_movement.z -= 1.0f;
|
||||
break;
|
||||
case SDL_KeyCode::SDLK_s:
|
||||
camera_movement.z += 1.0f;
|
||||
break;
|
||||
case SDL_KeyCode::SDLK_a:
|
||||
camera_movement.x -= 1.0f;
|
||||
break;
|
||||
case SDL_KeyCode::SDLK_d:
|
||||
camera_movement.x += 1.0f;
|
||||
break;
|
||||
case SDL_KeyCode::SDLK_ESCAPE:
|
||||
rotating = false;
|
||||
SDL_CaptureMouse(SDL_FALSE);
|
||||
SDL_SetWindowMouseGrab(win, SDL_FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ImGui::IsAnyItemFocused()) {
|
||||
camera_position += glm::xyz(glm::vec4((camera_movement * 0.05f * size), 0.0) * glm::mat4(camera_orientation));
|
||||
}
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
run_gl(win);
|
||||
|
||||
SDL_GL_SwapWindow(win);
|
||||
}
|
||||
|
||||
if (data_buffer != 0) {
|
||||
glDeleteBuffers(1, &data_buffer);
|
||||
}
|
||||
|
||||
glDeleteVertexArrays(1, &vao);
|
||||
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
SDL_GL_MakeCurrent(win, nullptr);
|
||||
SDL_GL_DeleteContext(ctx);
|
||||
|
||||
SDL_DestroyWindow(win);
|
||||
|
||||
SDL_Quit();
|
||||
return 0;
|
||||
}
|
||||
15
shaders/base.frag
Normal file
15
shaders/base.frag
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#version 460
|
||||
|
||||
layout (location = 3) uniform vec4 color;
|
||||
|
||||
in vec4 pos;
|
||||
//in vec3 normal;
|
||||
//in vec2 uv;
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
//vec3 norm = normalize(normal);
|
||||
//out_color = vec4(dot(normalize(-pos.xyz), norm) * color.rgb, color.a);
|
||||
out_color = color;
|
||||
}
|
||||
21
shaders/base.vert
Normal file
21
shaders/base.vert
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#version 460
|
||||
|
||||
layout (location = 0) in vec3 in_pos;
|
||||
//layout (location = 1) in vec3 in_normal;
|
||||
//layout (location = 2) in vec2 in_uv;
|
||||
|
||||
layout(location = 0) uniform mat4 model;
|
||||
layout(location = 1) uniform mat4 view;
|
||||
layout(location = 2) uniform mat4 proj;
|
||||
|
||||
out vec4 pos;
|
||||
//out vec3 normal;
|
||||
//out vec2 uv;
|
||||
|
||||
void main() {
|
||||
pos = view * model * vec4(in_pos, 1.0);
|
||||
gl_Position = proj * pos;
|
||||
pos /= pos.w;
|
||||
//normal = in_normal;
|
||||
//uv = in_uv;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue