From b366f3d0c573468ecd0b59da43dfcbc847334b19 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 14 Feb 2020 17:09:48 +0100 Subject: Add obj parser --- src/model_loader/ObjModelLoader.cpp | 143 ++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/model_loader/ObjModelLoader.cpp (limited to 'src/model_loader') 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 +#include +#include +#include + +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(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(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(found_ptr - str.data); + } + + void ObjModelLoader::load_from_file(const char *filepath, std::vector &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 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 -- cgit v1.2.3