aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2020-02-14 17:09:48 +0100
committerdec05eba <dec05eba@protonmail.com>2021-11-18 15:22:10 +0100
commitb366f3d0c573468ecd0b59da43dfcbc847334b19 (patch)
tree543a781260fc23197e301c6e2e42107a0a914027
parent83c78e2b5cc9b0cb737ec3785722ae280bd29b65 (diff)
Add obj parser
-rw-r--r--include/DataView.hpp2
-rw-r--r--include/File.hpp7
-rw-r--r--include/model_loader/ObjModelLoader.hpp11
-rw-r--r--src/File.cpp51
-rw-r--r--src/main.cpp45
-rw-r--r--src/model_loader/ObjModelLoader.cpp143
6 files changed, 253 insertions, 6 deletions
diff --git a/include/DataView.hpp b/include/DataView.hpp
index c9e25e7..d4200c5 100644
--- a/include/DataView.hpp
+++ b/include/DataView.hpp
@@ -23,4 +23,6 @@ namespace amalgine
T *data;
usize size;
};
+
+ using StringView = DataView<char>;
}
diff --git a/include/File.hpp b/include/File.hpp
new file mode 100644
index 0000000..6c5212f
--- /dev/null
+++ b/include/File.hpp
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <stddef.h>
+
+namespace amalgine {
+ char* file_get_content(const char *filepath, size_t *filesize);
+} \ No newline at end of file
diff --git a/include/model_loader/ObjModelLoader.hpp b/include/model_loader/ObjModelLoader.hpp
new file mode 100644
index 0000000..3cdeb7d
--- /dev/null
+++ b/include/model_loader/ObjModelLoader.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "../Triangle.hpp"
+#include <vector>
+
+namespace amalgine {
+ class ObjModelLoader {
+ public:
+ static void load_from_file(const char *filepath, std::vector<Triangle3D> &triangles);
+ };
+} \ No newline at end of file
diff --git a/src/File.cpp b/src/File.cpp
new file mode 100644
index 0000000..b41d0ca
--- /dev/null
+++ b/src/File.cpp
@@ -0,0 +1,51 @@
+#include "../include/File.hpp"
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+namespace amalgine {
+ char* file_get_content(const char *filepath, size_t *filesize) {
+ struct stat file_stat;
+ int fd = open(filepath, O_RDONLY);
+ char *result = NULL;
+ *filesize = 0;
+ if(fd == -1) {
+ perror(filepath);
+ return NULL;
+ }
+
+ if(fstat(fd, &file_stat) == -1) {
+ perror(filepath);
+ goto cleanup;
+ }
+
+ if(!S_ISREG(file_stat.st_mode)) {
+ fprintf(stderr, "Error: %s is not a file\n", filepath);
+ goto cleanup;
+ }
+
+ *filesize = file_stat.st_size;
+ result = (char*)malloc(*filesize + 1);
+ if(!result) {
+ *filesize = 0;
+ fprintf(stderr, "Error: Failed to malloc %lu bytes from file %s\n", *filesize, filepath);
+ goto cleanup;
+ }
+
+ result[*filesize] = '\0';
+ if((size_t)read(fd, result, *filesize) != *filesize) {
+ free(result);
+ result = NULL;
+ *filesize = 0;
+ fprintf(stderr, "Error: Failed to read all data from file %s\n", filepath);
+ goto cleanup;
+ }
+
+ cleanup:
+ close(fd);
+ return result;
+ }
+} \ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index c073a43..6f825b1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -5,6 +5,8 @@
#include "../include/RenderBackend/OpenGL/DeviceFrame.hpp"
#include "../include/Triangle.hpp"
+#include "../include/model_loader/ObjModelLoader.hpp"
+
#include <cstdio>
#include <chrono>
@@ -21,6 +23,10 @@ static GLFWwindow *createWindow();
static std::unique_ptr<Shader> load_shader_from_file(const char *filepath, Shader::Type shader_type);
static std::unique_ptr<ShaderProgram> build_shader_program_from_shaders(const std::vector<Shader*> &shaders);
+struct Userdata {
+ float cam_dist;
+};
+
int main()
{
initGlfw();
@@ -44,7 +50,10 @@ int main()
Vertex3D(0.0f, 1.0f, 0.0f)
),
};
- DataView<Triangle3D> cpuTriangles(cpuTriangle.data(), cpuTriangle.size());
+ //DataView<Triangle3D> cpuTriangles(cpuTriangle.data(), cpuTriangle.size());
+ std::vector<Triangle3D> triangles;
+ ObjModelLoader::load_from_file("/home/dec05eba/Downloads/FinalBaseMesh.obj", triangles);
+ DataView<Triangle3D> cpuTriangles(triangles.data(), triangles.size());
DeviceMemory *gpuTriangle = frame.alloc();
gpuTriangle->copy(cpuTriangles, DeviceMemory::StorageType::STATIC);
@@ -64,9 +73,19 @@ int main()
Result<Uniform> view_uniform = shader_program->get_uniform_by_name("view");
Result<Uniform> model_uniform = shader_program->get_uniform_by_name("model");
- glm::vec3 character_pos(0.0f, 3.0f, 3.0f);
+ Userdata userdata;
+ userdata.cam_dist = 3.0f;
+ glm::vec3 character_pos(0.0f, 0.0f, userdata.cam_dist);
auto t_start = std::chrono::high_resolution_clock::now();
+
+ glfwSetWindowUserPointer(window, &userdata);
+
+ glfwSetScrollCallback(window, [](GLFWwindow *window, double xoffset, double yoffset){
+ Userdata *userdata = (Userdata*)glfwGetWindowUserPointer(window);
+ userdata->cam_dist += yoffset;
+ });
+ //glEnable(GL_CULL_FACE);
while(!glfwWindowShouldClose(window)) {
glfwPollEvents();
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
@@ -76,10 +95,17 @@ int main()
float time_delta = std::chrono::duration_cast<std::chrono::duration<float>>(t_now - t_start).count();
t_start = t_now;
+ float move_speed = time_delta * 3.0f;
if(glfwGetKey(window, GLFW_KEY_W))
- character_pos.y -= time_delta;
+ character_pos.y -= move_speed;
if(glfwGetKey(window, GLFW_KEY_S))
- character_pos.y += time_delta;
+ character_pos.y += move_speed;
+ if(glfwGetKey(window, GLFW_KEY_A))
+ character_pos.x += move_speed;
+ if(glfwGetKey(window, GLFW_KEY_D))
+ character_pos.x -= move_speed;
+
+ character_pos.z = userdata.cam_dist;
glm::mat4 view = glm::lookAt(
character_pos,
@@ -100,7 +126,9 @@ int main()
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
// Do the actual screen clearing, using the color set using glClearColor
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
frame.draw(shader_program.get());
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glfwSwapBuffers(window);
}
@@ -121,7 +149,7 @@ void initGlfw()
exit(-1);
}
- glfwWindowHint(GLFW_SAMPLES, 4);
+ glfwWindowHint(GLFW_SAMPLES, 4); // anti aliasing
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
@@ -138,7 +166,12 @@ void initGlew() {
}
}
+static void error_callback(int error, const char *description) {
+ fprintf(stderr, "Opengl error: %s (%d)\n", description, error);
+}
+
GLFWwindow* createWindow() {
+ glfwSetErrorCallback(error_callback);
GLFWwindow *window = glfwCreateWindow(1280, 720, "Amalgine", nullptr, nullptr);
if(!window)
{
@@ -149,7 +182,7 @@ GLFWwindow* createWindow() {
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_FALSE);
glfwMakeContextCurrent(window);
- glfwSwapInterval(0);
+ glfwSwapInterval(1); // 1 = enable vsync
initGlew();
return window;
}
diff --git a/src/model_loader/ObjModelLoader.cpp b/src/model_loader/ObjModelLoader.cpp
new file mode 100644
index 0000000..1bae458
--- /dev/null
+++ b/src/model_loader/ObjModelLoader.cpp
@@ -0,0 +1,143 @@
+#include "../../include/model_loader/ObjModelLoader.hpp"
+#include "../../include/File.hpp"
+#include "../../include/DataView.hpp"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+namespace amalgine {
+ static StringView get_line(char *str, size_t size) {
+ #if 0
+ char *found_ptr = (char*)memchr(str, '\n', size);
+ if(!found_ptr)
+ found_ptr = str + size;
+ return { str, static_cast<size_t>(found_ptr - str) };
+ #endif
+ for(size_t i = 0; i < size; ++i) {
+ char c = str[i];
+ if(c == '\n')
+ return { str, i };
+ }
+ return { str, size };
+ }
+
+ static bool is_whitespace(char c) {
+ switch(c) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\r':
+ case '\v':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ static bool contains_non_whitespace(const char *str, size_t size) {
+ for(size_t i = 0; i < size; ++i) {
+ if(!is_whitespace(str[i]))
+ return true;
+ }
+ return false;
+ }
+
+ // Return the number of columns, limited by @output_size
+ static int split_columns(const StringView &str, StringView *output, int output_size) {
+ char *data = str.data;
+ ssize_t size = str.size;
+
+ int column = 0;
+ while(size > 0) {
+ char *found_ptr = (char*)memchr(data, ' ', size);
+ if(!found_ptr)
+ found_ptr = data + size;
+
+ size_t column_size = static_cast<size_t>(found_ptr - data);
+ if(column_size > 0 && contains_non_whitespace(data, column_size)) {
+ output[column++] = { data, column_size };
+ if(column == output_size)
+ break;
+ }
+
+ data = found_ptr + 1;
+ size -= (column_size + 1);
+ }
+
+ return column;
+ }
+
+ static size_t find_or_end(const StringView &str, char c) {
+ char *found_ptr = (char*)memchr(str.data, c, str.size);
+ if(!found_ptr)
+ found_ptr = str.data + str.size;
+ return static_cast<size_t>(found_ptr - str.data);
+ }
+
+ void ObjModelLoader::load_from_file(const char *filepath, std::vector<Triangle3D> &triangles) {
+ size_t file_size;
+ char *file_data = file_get_content(filepath, &file_size);
+ triangles.clear();
+ if(!file_data)
+ return;
+
+ const int max_columns = 12;
+ StringView columns[max_columns];
+
+ std::vector<Vertex3D> vertices;
+
+ char *data = file_data;
+ ssize_t size = file_size;
+ while(size > 0) {
+ StringView line_data = get_line(data, size);
+
+ if(line_data.size > 2 && memcmp(line_data.data, "v ", 2) == 0) {
+ //printf("line: |%.*s|\n", line_data.size, line_data.data);
+ StringView column_data = { line_data.data + 1, line_data.size - 1 };
+
+ int num_columns = split_columns(column_data, columns, max_columns);
+ if(num_columns >= 3) {
+ columns[0].data[columns[0].size] = '\0';
+ columns[1].data[columns[1].size] = '\0';
+ columns[2].data[columns[2].size] = '\0';
+ vertices.push_back({ atof(columns[0].data), atof(columns[1].data), atof(columns[2].data) });
+ }
+ } else if(line_data.size > 2 && memcmp(line_data.data, "f ", 2) == 0) {
+ //printf("line: |%.*s|\n", line_data.size, line_data.data);
+ StringView column_data = { line_data.data + 1, line_data.size - 1 };
+
+ int num_columns = split_columns(column_data, columns, max_columns);
+ if(num_columns == 3 || num_columns == 4) {
+ bool valid = true;
+ int indices[4];
+ for(int i = 0; i < num_columns; ++i) {
+ columns[i].size = find_or_end(columns[i], '/');
+ columns[i].data[columns[i].size] = '\0';
+ indices[i] = atoi(columns[i].data);
+ //printf("column[%d] = %.*s = %d\n", i, columns[i].size, columns[i].data, vertices.size());
+ if(indices[i] < 1 || indices[i] > vertices.size()) {
+ valid = false;
+ break;
+ }
+ --indices[i];
+ }
+
+ if(valid) {
+ if(num_columns == 3) {
+ triangles.push_back({ vertices[indices[0]], vertices[indices[1]], vertices[indices[2]] });
+ } else if(num_columns == 4) {
+ triangles.push_back({ vertices[indices[0]], vertices[indices[1]], vertices[indices[3]] });
+ triangles.push_back({ vertices[indices[3]], vertices[indices[2]], vertices[indices[1]] });
+ }
+ }
+ }
+ }
+
+ data += (line_data.size + 1);
+ size -= (line_data.size + 1);
+ }
+
+ free(file_data);
+ }
+} \ No newline at end of file