diff --git a/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp b/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp index ae239544e5..2ccecbb575 100644 --- a/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp +++ b/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp @@ -7,9 +7,15 @@ */ #include "WavefrontOBJLoader.h" +#include #include #include +static inline GLuint get_index_value(StringView& representation) +{ + return representation.to_uint().value_or(1) - 1; +} + RefPtr WavefrontOBJLoader::load(Core::File& file) { Vector vertices; @@ -29,7 +35,6 @@ RefPtr WavefrontOBJLoader::load(Core::File& file) auto tex_coord_line = object_line.split_view(' '); if (tex_coord_line.size() != 3) { dbgln("Wavefront: Malformed TexCoord line. Aborting."); - dbgln("{}", object_line); return nullptr; } @@ -68,54 +73,40 @@ RefPtr WavefrontOBJLoader::load(Core::File& file) continue; } - // This line describes a face (a collection of 3 vertices, aka a triangle) + // This line describes a face (a collection of 3+ vertices, aka a triangle or polygon) if (object_line.starts_with("f")) { - auto face_line = object_line.split_view(' '); - if (face_line.size() != 4) { + auto face_line = object_line.substring_view(2).split_view(' '); + auto number_of_vertices = face_line.size(); + if (number_of_vertices < 3) { dbgln("Wavefront: Malformed face line. Aborting."); return nullptr; } - GLuint vert_index[3]; - GLuint tex_coord_index[3]; - GLuint normal_index[3]; - if (object_line.contains("/")) { - for (int i = 1; i <= 3; ++i) { - auto vertex_data = face_line.at(i).split_view("/", true); + auto vertex_indices = FixedArray::must_create_but_fixme_should_propagate_errors(number_of_vertices); + auto tex_coord_indices = FixedArray::must_create_but_fixme_should_propagate_errors(number_of_vertices); + auto normal_indices = FixedArray::must_create_but_fixme_should_propagate_errors(number_of_vertices); - vert_index[i - 1] = vertex_data.at(0).to_uint().value_or(1); - tex_coord_index[i - 1] = vertex_data.at(1).to_uint().value_or(1); - - if (vertex_data.size() == 3) - normal_index[i - 1] = vertex_data.at(2).to_uint().value_or(1); - else - normal_index[i - 1] = 1; - } - } else { - vert_index[0] = (face_line.at(1).to_uint().value_or(1)); - vert_index[1] = (face_line.at(2).to_uint().value_or(1)); - vert_index[2] = (face_line.at(3).to_uint().value_or(1)); - tex_coord_index[0] = 0; - tex_coord_index[1] = 0; - tex_coord_index[2] = 0; - normal_index[0] = 0; - normal_index[1] = 0; - normal_index[2] = 0; + for (size_t i = 0; i < number_of_vertices; ++i) { + auto vertex_parts = face_line.at(i).split_view('/', true); + vertex_indices[i] = get_index_value(vertex_parts[0]); + tex_coord_indices[i] = (vertex_parts.size() >= 2) ? get_index_value(vertex_parts[1]) : 0; + normal_indices[i] = (vertex_parts.size() >= 3) ? get_index_value(vertex_parts[2]) : 0; } - // Create a new triangle - triangles.append( - { - vert_index[0] - 1, - vert_index[1] - 1, - vert_index[2] - 1, - tex_coord_index[0] - 1, - tex_coord_index[1] - 1, - tex_coord_index[2] - 1, - normal_index[0] - 1, - normal_index[1] - 1, - normal_index[2] - 1, + // Create a triangle for each part of the polygon + for (size_t i = 0; i < number_of_vertices - 2; ++i) { + triangles.append({ + vertex_indices[0], + vertex_indices[i + 1], + vertex_indices[i + 2], + tex_coord_indices[0], + tex_coord_indices[i + 1], + tex_coord_indices[i + 2], + normal_indices[0], + normal_indices[i + 1], + normal_indices[i + 2], }); + } } }