1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 11:38:11 +00:00
serenity/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp
Gunnar Beutner 2a16c8bdb8 3DFileViewer: Clean up file handling
This unifies how 3DFileViewer handles the initial file when starting
the application and when opening files later on via the menu.

Errors are shown both for the initial load as well as when loading
files later on. An error during file load no longer clears the
existing model.

It also adds support for specifying the filename as a command-line
argument.

The opened file's name is shown in the titlebar.
2021-05-20 22:22:56 +02:00

72 lines
2.4 KiB
C++

/*
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
* Copyright (c) 2021, Mathieu Gaillard <gaillard.mathieu.39@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "WavefrontOBJLoader.h"
#include <LibCore/File.h>
#include <stdlib.h>
RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
{
Vector<Vertex> vertices;
Vector<Triangle> triangles;
dbgln("Wavefront: Loading {}...", file.name());
// Start reading file line by line
for (auto line = file.line_begin(); !line.at_end(); ++line) {
auto object_line = *line;
// FIXME: Parse texture coordinates and vertex normals
if (object_line.starts_with("vt") || object_line.starts_with("vn")) {
continue;
}
// This line describes a vertex (a position in 3D space)
if (object_line.starts_with("v")) {
auto vertex_line = object_line.split_view(' ');
if (vertex_line.size() != 4) {
dbgln("Wavefront: Malformed vertex line. Aborting.");
return nullptr;
}
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())) });
}
// This line describes a face (a collection of 3 vertices, aka a triangle)
else if (object_line.starts_with("f")) {
auto face_line = object_line.split_view(' ');
if (face_line.size() != 4) {
dbgln("Wavefront: Malformed face line. Aborting.");
return nullptr;
}
if (object_line.contains("/")) {
for (int i = 1; i <= 3; ++i) {
face_line.at(i) = face_line.at(i).split_view("/").at(0);
}
}
// Create a new triangle
triangles.append(
{
face_line.at(1).to_uint().value() - 1,
face_line.at(2).to_uint().value() - 1,
face_line.at(3).to_uint().value() - 1,
});
}
}
if (vertices.is_empty()) {
dbgln("Wavefront: Failed to read any data from 3D file: {}", file.name());
return nullptr;
}
dbgln("Wavefront: Done.");
return adopt_ref(*new Mesh(vertices, triangles));
}