1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:17:44 +00:00

3DFileViewer: Add vertex normal parsing to WavefrontOBJLoader

This change allows us to parse vertex-normal lines "vn x y z"
and map them to the correct index on face lines ("f v1/vt1/vn1").
This commit is contained in:
Pedro Pereira 2021-11-05 01:08:29 +00:00 committed by Andreas Kling
parent a8fed919e7
commit 7fb8af73bf
2 changed files with 41 additions and 6 deletions

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
* Copyright (c) 2021, Mathieu Gaillard <gaillard.mathieu.39@gmail.com>
* Copyright (c) 2021, Pedro Pereira <pmh.pereira@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -30,4 +31,8 @@ struct Triangle {
GLuint tex_coord_index0;
GLuint tex_coord_index1;
GLuint tex_coord_index2;
GLuint normal_index0;
GLuint normal_index1;
GLuint normal_index2;
};

View file

@ -1,6 +1,7 @@
/*
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
* Copyright (c) 2021, Mathieu Gaillard <gaillard.mathieu.39@gmail.com>
* Copyright (c) 2021, Pedro Pereira <pmh.pereira@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -12,6 +13,7 @@
RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
{
Vector<Vertex> vertices;
Vector<Vertex> normals;
Vector<TexCoord> tex_coords;
Vector<Triangle> triangles;
@ -39,8 +41,17 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
continue;
}
// FIXME: Parse texture coordinates and vertex normals
if (object_line.starts_with("vn")) {
auto normal_line = object_line.split_view(' ');
if (normal_line.size() != 4) {
dbgln("Wavefront: Malformed vertex normal line. Aborting.");
return nullptr;
}
normals.append({ static_cast<GLfloat>(atof(String(normal_line.at(1)).characters())),
static_cast<GLfloat>(atof(String(normal_line.at(2)).characters())),
static_cast<GLfloat>(atof(String(normal_line.at(3)).characters())) });
continue;
}
@ -55,9 +66,12 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
vertices.append({ static_cast<GLfloat>(atof(String(vertex_line.at(1)).characters())),
static_cast<GLfloat>(atof(String(vertex_line.at(2)).characters())),
static_cast<GLfloat>(atof(String(vertex_line.at(3)).characters())) });
continue;
}
// This line describes a face (a collection of 3 vertices, aka a triangle)
else if (object_line.starts_with("f")) {
if (object_line.starts_with("f")) {
auto face_line = object_line.split_view(' ');
if (face_line.size() != 4) {
dbgln("Wavefront: Malformed face line. Aborting.");
@ -66,10 +80,18 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
GLuint vert_index[3];
GLuint tex_coord_index[3];
GLuint normal_index[3];
if (object_line.contains("/")) {
for (int i = 1; i <= 3; ++i) {
vert_index[i - 1] = face_line.at(i).split_view("/").at(0).to_uint().value_or(1);
tex_coord_index[i - 1] = face_line.at(i).split_view("/").at(1).to_uint().value_or(1);
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));
@ -78,16 +100,24 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
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;
}
// Create a new triangle
triangles.append(
{ vert_index[0] - 1,
{
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 });
tex_coord_index[2] - 1,
normal_index[0] - 1,
normal_index[1] - 1,
normal_index[2] - 1,
});
}
}