aboutsummaryrefslogtreecommitdiff
path: root/src/model_loader/ObjModelLoader.cpp
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 /src/model_loader/ObjModelLoader.cpp
parent83c78e2b5cc9b0cb737ec3785722ae280bd29b65 (diff)
Add obj parser
Diffstat (limited to 'src/model_loader/ObjModelLoader.cpp')
-rw-r--r--src/model_loader/ObjModelLoader.cpp143
1 files changed, 143 insertions, 0 deletions
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