summaryrefslogtreecommitdiff
path: root/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp
diff options
context:
space:
mode:
authorErik Biederstadt <biederstadterik@gmail.com>2021-05-19 11:57:59 -0600
committerLinus Groh <mail@linusgroh.de>2021-05-19 19:34:12 +0100
commit585e7890cdd416b77bd28c2ef853477b42c606ef (patch)
treeb44d8a4bb7a6306f8b947a566056976afa6ff36c /Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp
parent132ecfc47b2b21706fff16f08ab30bcb7879af73 (diff)
downloadserenity-585e7890cdd416b77bd28c2ef853477b42c606ef.zip
3DFileViewer: Move `Demos/GLTeapot` to `Applications/3DFileViewer`
Also changes the category to `Graphics`
Diffstat (limited to 'Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp')
-rw-r--r--Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp76
1 files changed, 76 insertions, 0 deletions
diff --git a/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp b/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp
new file mode 100644
index 0000000000..891f13dc8f
--- /dev/null
+++ b/Userland/Applications/3DFileViewer/WavefrontOBJLoader.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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(const String& fname)
+{
+ auto obj_file_or_error = Core::File::open(fname, Core::OpenMode::ReadOnly);
+ Vector<Vertex> vertices;
+ Vector<Triangle> triangles;
+
+ dbgln("Wavefront: Loading {}...", fname);
+
+ if (obj_file_or_error.is_error())
+ return nullptr;
+
+ // Start reading file line by line
+ for (auto line = obj_file_or_error.value()->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: {}", fname);
+ return nullptr;
+ }
+
+ dbgln("Wavefront: Done.");
+ return adopt_ref(*new Mesh(vertices, triangles));
+}