91 lines
3.2 KiB
C++
91 lines
3.2 KiB
C++
//
|
|
// Created by sebastian on 07.02.26.
|
|
//
|
|
|
|
#include "OBJLoader.h"
|
|
|
|
#define TINYOBJLOADER_IMPLEMENTATION
|
|
#include <complex>
|
|
#include <filesystem>
|
|
#include <iostream>
|
|
|
|
#include "tiny_obj_loader.h"
|
|
|
|
std::shared_ptr<TexturedModel> OBJLoader::loadModel(const std::string &modelPath, const std::string& texturePath, Loader &loader) {
|
|
tinyobj::attrib_t attrib;
|
|
std::vector<tinyobj::shape_t> shapes;
|
|
std::vector<tinyobj::material_t> materials;
|
|
std::string warn, err;
|
|
std::string baseDir = std::filesystem::path(modelPath).parent_path().string();
|
|
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, modelPath.c_str(), baseDir.c_str());
|
|
|
|
if (!warn.empty()) {
|
|
std::cout << "OBJ Loader warning: " << warn << std::endl;
|
|
}
|
|
if (!err.empty()) {
|
|
std::cerr << "OBJ Loader error: " << err << std::endl;
|
|
}
|
|
if (!ret) {
|
|
throw std::runtime_error("Failed to load OBJ");
|
|
}
|
|
|
|
std::vector<SubModel> subModels;
|
|
|
|
|
|
for (const auto& shape : shapes) {
|
|
std::vector<float> vertices;
|
|
std::vector<float> normals;
|
|
std::vector<float> uvs;
|
|
std::vector<int> indices;
|
|
int indexOffset = 0;
|
|
for (const auto& index : shape.mesh.indices) {
|
|
// Vertex-Position
|
|
vertices.push_back(attrib.vertices[3*index.vertex_index + 0]);
|
|
vertices.push_back(attrib.vertices[3*index.vertex_index + 1]);
|
|
vertices.push_back(attrib.vertices[3*index.vertex_index + 2]);
|
|
|
|
// UV-Koordinaten
|
|
if (!attrib.texcoords.empty()) {
|
|
uvs.push_back(attrib.texcoords[2*index.texcoord_index + 0]);
|
|
uvs.push_back(1.0f - attrib.texcoords[2*index.texcoord_index + 1]);
|
|
} else {
|
|
uvs.push_back(0.0f);
|
|
uvs.push_back(0.0f);
|
|
}
|
|
|
|
normals.push_back(attrib.normals[3*index.normal_index + 0]);
|
|
normals.push_back(attrib.normals[3*index.normal_index + 1]);
|
|
normals.push_back(attrib.normals[3*index.normal_index + 2]);
|
|
|
|
// Index
|
|
indices.push_back(indexOffset);
|
|
indexOffset++;
|
|
}
|
|
|
|
RawModel rawModel = loader.loadToVAO(vertices, normals, uvs, indices);
|
|
|
|
std::shared_ptr<ModelTexture> texture = nullptr;
|
|
if (!materials.empty() && !shape.mesh.material_ids.empty()) {
|
|
int matID = shape.mesh.material_ids[0];
|
|
if (matID >= 0 && matID < static_cast<int>(materials.size())) {
|
|
tinyobj::material_t &mat = materials[matID];
|
|
if (!mat.diffuse_texname.empty()) {
|
|
std::string texFile = mat.diffuse_texname;
|
|
std::filesystem::path fullTexPath = std::filesystem::path(baseDir) / std::filesystem::path(texFile);
|
|
texture = std::make_shared<ModelTexture>(loader.loadTextureFromFile(fullTexPath.string()));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!texture) {
|
|
texture = std::make_shared<ModelTexture>(loader.loadTextureFromFile(texturePath));
|
|
}
|
|
|
|
subModels.emplace_back(
|
|
std::make_shared<RawModel>(rawModel), texture
|
|
);
|
|
}
|
|
|
|
return std::make_shared<TexturedModel>(subModels);
|
|
}
|