summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorJelle Raaijmakers <jelle@gmta.nl>2022-04-10 00:04:52 +0200
committerAndreas Kling <kling@serenityos.org>2022-04-10 12:08:31 +0200
commita021a7e240fc7169e251a7f4c308520476a4da3f (patch)
tree95643fc2e0833d6f41868265e24105c8519aa7d8 /Userland
parent1577a8ba42a13b71fb6e22f91e0bebf9677d243d (diff)
downloadserenity-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.cpp73
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],
});
+ }
}
}