2024-03-22 20:12:09 +08:00
|
|
|
// Copyright 2024 SquareBlock Inc. All Rights Reserved.
|
2024-03-21 21:34:29 +08:00
|
|
|
// Author: tianlei.richard@qq.com (tianlei.richard)
|
|
|
|
|
|
|
|
#include "mesh.h"
|
|
|
|
#include "OBJ_Loader.h"
|
|
|
|
#include "spdlog/spdlog.h"
|
2024-03-22 20:12:09 +08:00
|
|
|
#include <filesystem>
|
2024-03-21 21:34:29 +08:00
|
|
|
|
|
|
|
#define OBJL_VEC2_TO_EIGEN_VECTOR(objl_v) \
|
|
|
|
Eigen::Vector2d { objl_v.X, objl_v.Y }
|
|
|
|
#define OBJL_VEC3_TO_EIGEN_VECTOR(objl_v) \
|
|
|
|
Eigen::Vector3d { objl_v.X, objl_v.Y, objl_v.Z }
|
|
|
|
|
2024-03-29 18:09:16 +08:00
|
|
|
Mesh::Mesh(const std::vector<Vertex> &vertices,
|
|
|
|
const std::vector<std::array<size_t, 3>> &indices,
|
2024-03-22 20:12:09 +08:00
|
|
|
const std::shared_ptr<PhoneMaterial> &phone_material)
|
2024-03-29 18:09:16 +08:00
|
|
|
: vertices_(vertices), indices_(indices), material_(phone_material) {}
|
2024-03-21 21:34:29 +08:00
|
|
|
|
2024-03-29 18:09:16 +08:00
|
|
|
std::vector<Vertex> &Mesh::get_vertices() { return vertices_; }
|
|
|
|
|
|
|
|
std::vector<Vertex>::size_type Mesh::get_vertex_size() const {
|
2024-03-27 18:31:10 +08:00
|
|
|
return vertices_.size();
|
|
|
|
};
|
2024-03-26 21:34:06 +08:00
|
|
|
|
2024-03-27 18:31:10 +08:00
|
|
|
const decltype(Vertex::texture_coordinate) &
|
|
|
|
Mesh::get_texture_coordinate(const unsigned int index) const {
|
2024-03-29 18:09:16 +08:00
|
|
|
return (vertices_[index]).texture_coordinate;
|
2024-03-21 21:34:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Point3d Mesh::get_normal_vector(const unsigned int index) const {
|
2024-03-29 18:09:16 +08:00
|
|
|
return (vertices_[index]).normal;
|
2024-03-21 21:34:29 +08:00
|
|
|
}
|
|
|
|
|
2024-03-29 18:09:16 +08:00
|
|
|
std::vector<Triangle> Mesh::get_primitives() const {
|
|
|
|
std::vector<Triangle> primitives;
|
|
|
|
for (const auto &idx : indices_) {
|
|
|
|
primitives.push_back(Triangle(vertices_, idx[0], idx[1], idx[2]));
|
|
|
|
}
|
|
|
|
return primitives;
|
|
|
|
}
|
2024-03-27 18:31:10 +08:00
|
|
|
|
2024-03-29 18:09:16 +08:00
|
|
|
Triangle Mesh::get_primitive(const size_t index) const {
|
|
|
|
assert(index >= 0 && index < indices_.size());
|
|
|
|
return Triangle(vertices_, indices_[index][0], indices_[index][1],
|
|
|
|
indices_[index][2]);
|
|
|
|
}
|
2024-03-27 18:31:10 +08:00
|
|
|
|
|
|
|
const std::shared_ptr<PhoneMaterial> &Mesh::get_material() const {
|
|
|
|
return material_;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<Mesh> Mesh::load_mesh(
|
|
|
|
const std::string &obj_path,
|
|
|
|
const std::unordered_map<Texture::TextureType, std::string> texture_path) {
|
2024-03-26 21:34:06 +08:00
|
|
|
const auto &obj_file_path = std::filesystem::path(obj_path);
|
|
|
|
const auto &material_directory = obj_file_path.parent_path();
|
2024-03-22 20:12:09 +08:00
|
|
|
|
2024-03-21 21:34:29 +08:00
|
|
|
objl::Loader loader{};
|
2024-03-26 21:34:06 +08:00
|
|
|
assert(loader.LoadFile(obj_path.c_str()));
|
2024-03-21 21:34:29 +08:00
|
|
|
|
|
|
|
std::vector<Mesh> res;
|
|
|
|
for (const auto &mesh : loader.LoadedMeshes) {
|
|
|
|
spdlog::info("Current mesh has {} vertices.", mesh.Vertices.size());
|
|
|
|
|
2024-03-29 18:09:16 +08:00
|
|
|
std::vector<Vertex> vertices;
|
2024-03-22 20:12:09 +08:00
|
|
|
for (decltype(mesh.Vertices)::size_type i = 0; i < mesh.Vertices.size();
|
|
|
|
i++) {
|
2024-03-29 18:09:16 +08:00
|
|
|
vertices.push_back(Vertex(
|
2024-03-21 21:34:29 +08:00
|
|
|
OBJL_VEC3_TO_EIGEN_VECTOR(mesh.Vertices[i].Position),
|
|
|
|
OBJL_VEC3_TO_EIGEN_VECTOR(mesh.Vertices[i].Normal),
|
|
|
|
OBJL_VEC2_TO_EIGEN_VECTOR(mesh.Vertices[i].TextureCoordinate)));
|
|
|
|
}
|
2024-03-29 18:09:16 +08:00
|
|
|
std::vector<std::array<size_t, 3>> indices;
|
2024-03-22 20:12:09 +08:00
|
|
|
for (decltype(mesh.Indices)::size_type i = 0; i < mesh.Indices.size();
|
|
|
|
i += 3) {
|
2024-03-29 18:09:16 +08:00
|
|
|
indices.push_back(
|
|
|
|
{mesh.Indices[i], mesh.Indices[i + 1], mesh.Indices[i + 2]});
|
2024-03-21 21:34:29 +08:00
|
|
|
}
|
|
|
|
|
2024-03-27 18:31:10 +08:00
|
|
|
std::unordered_map<Texture::TextureType, std::shared_ptr<Texture>> textures;
|
2024-03-26 21:34:06 +08:00
|
|
|
if (!texture_path.empty()) {
|
2024-03-27 18:31:10 +08:00
|
|
|
for (const auto &[type, path] : texture_path) {
|
|
|
|
textures.insert({type, std::make_shared<Texture>(path)});
|
2024-03-26 21:34:06 +08:00
|
|
|
}
|
|
|
|
} else if (!mesh.MeshMaterial.map_Kd.empty()) {
|
2024-03-27 18:31:10 +08:00
|
|
|
textures.insert({Texture::DiffuseMap,
|
|
|
|
std::make_shared<Texture>(material_directory /
|
|
|
|
mesh.MeshMaterial.map_Kd)});
|
2024-03-22 20:12:09 +08:00
|
|
|
}
|
2024-03-27 18:31:10 +08:00
|
|
|
auto material = std::make_shared<PhoneMaterial>(
|
2024-03-28 21:55:30 +08:00
|
|
|
textures, std::make_shared<Lamp>(Point3d{}, 16.));
|
2024-03-22 20:12:09 +08:00
|
|
|
|
2024-03-29 18:09:16 +08:00
|
|
|
res.push_back(Mesh(vertices, indices, material));
|
2024-03-21 21:34:29 +08:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|