88 lines
2.8 KiB
C++

#include "./mesh.hpp"
#include <mijin/io/stlstream.hpp>
#include <tiny_obj_loader.h>
namespace sdl_gpu_test
{
Mesh loadMesh(const mijin::PathReference& path)
{
std::unique_ptr<mijin::Stream> stream;
mijin::throwOnError(path.open(mijin::FileOpenMode::READ, stream));
mijin::IOStreamAdapter adapter(*stream);
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string warning;
std::string error;
const bool success = tinyobj::LoadObj(
/* attrib = */ &attrib,
/* shapes = */ &shapes,
/* materials = */ &materials,
/* warn = */ &warning,
/* err = */ &error,
/* inStream = */ &adapter
);
mijin::ensure(success, "Parsing OBJ file failed.");
Mesh mesh;
for (const tinyobj::shape_t& shape : shapes)
{
std::size_t indexOffset = 0;
for (const std::size_t faceVertices : shape.mesh.num_face_vertices)
{
if (faceVertices != 3)
{
// we only deal with triangles
indexOffset += faceVertices;
continue;
}
for (int vertexIdx = 0; vertexIdx < 3; ++vertexIdx)
{
const tinyobj::index_t& index = shape.mesh.indices[indexOffset + vertexIdx];
glm::vec3 normal = {1.f, 0.f, 0.f};
glm::vec2 texcoord = {0.f, 0.f};
if (index.normal_index > -1)
{
normal = {
attrib.normals[3 * index.normal_index + 0],
attrib.normals[3 * index.normal_index + 1],
attrib.normals[3 * index.normal_index + 2]
};
}
if (index.texcoord_index > -1)
{
texcoord = {
attrib.texcoords[2 * index.texcoord_index + 0],
1.f - attrib.texcoords[2 * index.texcoord_index + 1] // obj UV is weird
};
}
mesh.vertices.push_back({
.pos = {
attrib.vertices[3 * index.vertex_index + 0],
attrib.vertices[3 * index.vertex_index + 1],
attrib.vertices[3 * index.vertex_index + 2]
},
.normal = normal,
.texcoord = texcoord,
.color = {
attrib.colors[3 * index.vertex_index + 0],
attrib.colors[3 * index.vertex_index + 1],
attrib.colors[3 * index.vertex_index + 2],
1.f
}
});
}
indexOffset += 3;
}
}
return mesh;
}
}