From 7fb8af73bfde77edd0e71432030070c9c9a920e1 Mon Sep 17 00:00:00 2001 From: Pedro Pereira Date: Fri, 5 Nov 2021 01:08:29 +0000 Subject: [PATCH] 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"). --- Userland/Applications/3DFileViewer/Common.h | 5 +++ .../3DFileViewer/WavefrontOBJLoader.cpp | 42 ++++++++++++++++--- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Userland/Applications/3DFileViewer/Common.h b/Userland/Applications/3DFileViewer/Common.h index 781519dcae..c84c6cf086 100644 --- a/Userland/Applications/3DFileViewer/Common.h +++ b/Userland/Applications/3DFileViewer/Common.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2021, Jesse Buhagiar * Copyright (c) 2021, Mathieu Gaillard + * Copyright (c) 2021, Pedro Pereira * * 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; }; diff --git a/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp b/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp index 83b23c9782..bb881c333a 100644 --- a/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp +++ b/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2021, Jesse Buhagiar * Copyright (c) 2021, Mathieu Gaillard + * Copyright (c) 2021, Pedro Pereira * * SPDX-License-Identifier: BSD-2-Clause */ @@ -12,6 +13,7 @@ RefPtr WavefrontOBJLoader::load(Core::File& file) { Vector vertices; + Vector normals; Vector tex_coords; Vector triangles; @@ -39,8 +41,17 @@ RefPtr 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(atof(String(normal_line.at(1)).characters())), + static_cast(atof(String(normal_line.at(2)).characters())), + static_cast(atof(String(normal_line.at(3)).characters())) }); + continue; } @@ -55,9 +66,12 @@ RefPtr WavefrontOBJLoader::load(Core::File& file) vertices.append({ static_cast(atof(String(vertex_line.at(1)).characters())), static_cast(atof(String(vertex_line.at(2)).characters())), static_cast(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 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 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, + }); } }