diff options
author | Jelle Raaijmakers <jelle@gmta.nl> | 2022-04-10 00:04:52 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-04-10 12:08:31 +0200 |
commit | a021a7e240fc7169e251a7f4c308520476a4da3f (patch) | |
tree | 95643fc2e0833d6f41868265e24105c8519aa7d8 /Userland | |
parent | 1577a8ba42a13b71fb6e22f91e0bebf9677d243d (diff) | |
download | serenity-a021a7e240fc7169e251a7f4c308520476a4da3f.zip |
Applications: Support `.obj` polygons in `3DFileViewer`
Our `WavefrontOBJLoader` only supported faces with 3 vertices, but
`.obj` files can specify arbitrary polygons with 4 or more vertices.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp | 73 |
1 files changed, 32 insertions, 41 deletions
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 <AK/FixedArray.h> #include <LibCore/File.h> #include <stdlib.h> +static inline GLuint get_index_value(StringView& representation) +{ + return representation.to_uint().value_or(1) - 1; +} + RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file) { Vector<Vertex> vertices; @@ -29,7 +35,6 @@ RefPtr<Mesh> 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<Mesh> 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); - - 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; + auto vertex_indices = FixedArray<GLuint>::must_create_but_fixme_should_propagate_errors(number_of_vertices); + auto tex_coord_indices = FixedArray<GLuint>::must_create_but_fixme_should_propagate_errors(number_of_vertices); + auto normal_indices = FixedArray<GLuint>::must_create_but_fixme_should_propagate_errors(number_of_vertices); + + 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], }); + } } } |