mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:47:36 +00:00
3DFileViewer: Support textured models
Models that contain UV co-ordinates are now supported, and will display with a texture wrapped around it, provided a `bmp` with the same name as the object is in the same directory as the 3D Model.
This commit is contained in:
parent
3287709df9
commit
343e66b816
7 changed files with 13657 additions and 9899 deletions
|
@ -12,6 +12,7 @@
|
|||
RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
|
||||
{
|
||||
Vector<Vertex> vertices;
|
||||
Vector<TexCoord> tex_coords;
|
||||
Vector<Triangle> triangles;
|
||||
|
||||
dbgln("Wavefront: Loading {}...", file.name());
|
||||
|
@ -20,8 +21,26 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
|
|||
for (auto line = file.line_begin(); !line.at_end(); ++line) {
|
||||
auto object_line = *line;
|
||||
|
||||
// Ignore file comments
|
||||
if (object_line.starts_with("#"))
|
||||
continue;
|
||||
|
||||
if (object_line.starts_with("vt")) {
|
||||
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;
|
||||
}
|
||||
|
||||
tex_coords.append({ static_cast<GLfloat>(atof(String(tex_coord_line.at(1)).characters())),
|
||||
static_cast<GLfloat>(atof(String(tex_coord_line.at(2)).characters())) });
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// FIXME: Parse texture coordinates and vertex normals
|
||||
if (object_line.starts_with("vt") || object_line.starts_with("vn")) {
|
||||
if (object_line.starts_with("vn")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -33,10 +52,9 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
|
|||
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())) });
|
||||
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")) {
|
||||
|
@ -46,19 +64,30 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
GLuint vert_index[3];
|
||||
GLuint tex_coord_index[3];
|
||||
if (object_line.contains("/")) {
|
||||
for (int i = 1; i <= 3; ++i) {
|
||||
face_line.at(i) = face_line.at(i).split_view("/").at(0);
|
||||
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);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
// 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,
|
||||
});
|
||||
{ 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 });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,5 +97,5 @@ RefPtr<Mesh> WavefrontOBJLoader::load(Core::File& file)
|
|||
}
|
||||
|
||||
dbgln("Wavefront: Done.");
|
||||
return adopt_ref(*new Mesh(vertices, triangles));
|
||||
return adopt_ref(*new Mesh(vertices, tex_coords, triangles));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue