Загрузчик моделей
This commit is contained in:
parent
ce660278a8
commit
f57885761e
41
.vscode/settings.json
vendored
41
.vscode/settings.json
vendored
@ -4,6 +4,45 @@
|
||||
"iosfwd": "cpp",
|
||||
"map": "cpp",
|
||||
"atomic": "cpp",
|
||||
"new": "cpp"
|
||||
"new": "cpp",
|
||||
"array": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"random": "cpp",
|
||||
"string": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
}
|
||||
}
|
@ -6,6 +6,11 @@
|
||||
|
||||
#include <GLM/glm.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#define DEFAULT_MTL_DIR "./"
|
||||
void loadOBJtoVector(const char* filename, std::vector<class Model>& scene, const char* mtl_directory = DEFAULT_MTL_DIR, const char* texture_directory = DEFAULT_MTL_DIR);
|
||||
|
||||
class Model
|
||||
{
|
||||
public:
|
||||
|
119
src/Model.cpp
119
src/Model.cpp
@ -220,3 +220,122 @@ void Model::set_index_range(GLuint beg, GLuint count)
|
||||
first_index = beg;
|
||||
indices_count = count;
|
||||
}
|
||||
|
||||
#define TINYOBJLOADER_IMPLEMENTATION
|
||||
#include "tiny_obj_loader.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
inline void hash_combine(std::size_t& seed) { }
|
||||
|
||||
template <typename T, typename... Rest>
|
||||
inline void hash_combine(std::size_t& seed, const T& v, Rest... rest) {
|
||||
std::hash<T> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
hash_combine(seed, rest...);
|
||||
}
|
||||
|
||||
void loadOBJtoVector(const char* filename, std::vector<Model>& scene, const char* mtl_directory, const char* texture_directory)
|
||||
{
|
||||
Model model;
|
||||
|
||||
tinyobj::attrib_t attrib;
|
||||
std::vector<tinyobj::shape_t> shapes;
|
||||
std::vector<tinyobj::material_t> materials;
|
||||
|
||||
std::string err;
|
||||
|
||||
// Если в процессе загрузки возникли ошибки - выдадим исключение
|
||||
if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename, mtl_directory))
|
||||
throw std::runtime_error(err);
|
||||
|
||||
std::vector<GLuint> indices; // индексы модели
|
||||
std::vector<glm::vec3> verteces; // вершины
|
||||
std::vector<glm::vec3> normals; // нормали
|
||||
std::vector<glm::vec2> texCords; // текстурные координаты
|
||||
size_t hash; // Для уникальных вершин
|
||||
std::map <int, int> uniqueVerteces; // словарь для уникальных вершин: ключ - хеш, значение - индекс вершины
|
||||
|
||||
int last_material_index = 0; // индекс последнего материала (для группировки моделей)
|
||||
int count = 0, offset; // для индексов начала и конца в индексном буфере
|
||||
std::vector<int> materials_range; // хранилище индексов
|
||||
std::vector<int> materials_ids; // индексы материалов
|
||||
|
||||
materials_range.push_back(count); // Закидываем начало отрезка в индексном буфере
|
||||
// Цикл по считанным моделям
|
||||
for (const auto& shape : shapes)
|
||||
{
|
||||
offset = count; // Переменная для
|
||||
last_material_index = shape.mesh.material_ids[(count - offset)/3]; // Запоминаем индекс материала
|
||||
|
||||
// Цикл по индексам модели
|
||||
for (const auto& index : shape.mesh.indices)
|
||||
{
|
||||
hash = 0;
|
||||
hash_combine( hash
|
||||
, attrib.vertices[3 * index.vertex_index + 0], attrib.vertices[3 * index.vertex_index + 1], attrib.vertices[3 * index.vertex_index + 2]
|
||||
, attrib.normals[3 * index.normal_index + 0], attrib.normals[3 * index.normal_index + 1], attrib.normals[3 * index.normal_index + 2]
|
||||
, attrib.texcoords[2 * index.texcoord_index + 0], attrib.texcoords[2 * index.texcoord_index + 1]);
|
||||
|
||||
if (!uniqueVerteces.count(hash))
|
||||
{
|
||||
uniqueVerteces[hash] = verteces.size();
|
||||
|
||||
// группируем вершины в массив на основании индексов
|
||||
verteces.push_back({ attrib.vertices[3 * index.vertex_index + 0]
|
||||
, attrib.vertices[3 * index.vertex_index + 1]
|
||||
, attrib.vertices[3 * index.vertex_index + 2]
|
||||
});
|
||||
// группируем нормали в массив на основании индексов
|
||||
normals.push_back({ attrib.normals[3 * index.normal_index + 0]
|
||||
, attrib.normals[3 * index.normal_index + 1]
|
||||
, attrib.normals[3 * index.normal_index + 2]
|
||||
});
|
||||
// группируем текстурные координаты в массив на основании индексов
|
||||
texCords.push_back({ attrib.texcoords[2 * index.texcoord_index + 0]
|
||||
, 1-attrib.texcoords[2 * index.texcoord_index + 1]
|
||||
});
|
||||
}
|
||||
// Сохраняем индекс в массив
|
||||
indices.push_back(uniqueVerteces[hash]);
|
||||
|
||||
// Если индекс последнего материала изменился, то необходимо сохранить его
|
||||
if (last_material_index != shape.mesh.material_ids[(count - offset)/3])
|
||||
{
|
||||
materials_range.push_back(count); // как конец отрезка
|
||||
materials_ids.push_back(last_material_index); // как используемый материал
|
||||
last_material_index = shape.mesh.material_ids[(count - offset)/3];
|
||||
}
|
||||
count++;
|
||||
} // for (const auto& index : shape.mesh.indices)
|
||||
|
||||
// Если последний материал не загружен - загружаем его
|
||||
if (materials_range[materials_range.size()-1] != count-1)
|
||||
{
|
||||
materials_range.push_back(count); // последний конец отрезка
|
||||
materials_ids.push_back(last_material_index); // последний используемый материал
|
||||
}
|
||||
} // for (const auto& shape : shapes)
|
||||
|
||||
|
||||
|
||||
// Загрузка в буферы
|
||||
model.load_verteces (&verteces[0], verteces.size());
|
||||
model.load_normals (&normals[0], normals.size());
|
||||
model.load_texCoords(&texCords[0], texCords.size());
|
||||
// Загрузка индексного буфера
|
||||
model.load_indices (&indices[0], indices.size());
|
||||
|
||||
|
||||
// Создаем копии модели, которые будут рендериться в заданном диапазоне
|
||||
// И присваиваем текстуры копиям на основании материала
|
||||
for (int i = 0; i < materials_range.size()-1; i++)
|
||||
{
|
||||
scene.push_back(model); // Создание копии с общим VAO
|
||||
auto s = --scene.end();
|
||||
s->set_index_range(materials_range[i], materials_range[i+1]-materials_range[i]);
|
||||
|
||||
Texture diffuse(TEX_DIFFUSE, texture_directory + materials[materials_ids[i]].diffuse_texname);
|
||||
s->set_texture(diffuse);
|
||||
}
|
||||
}
|
||||
|
46
src/main.cpp
46
src/main.cpp
@ -184,45 +184,12 @@ int main(void)
|
||||
glUseProgram(shaderProgram);
|
||||
// Установим значения текстур
|
||||
Texture::init_textures(shaderProgram);
|
||||
// camera.move({0,0,-20});
|
||||
|
||||
// Вершины прямоугольника
|
||||
glm::vec3 verticies[] = { {-0.5f, -0.5f, 0.0f}
|
||||
, { 0.5f, -0.5f, 0.0f}
|
||||
, { 0.5f, 0.5f, 0.0f}
|
||||
, {-0.5f, 0.5f, 0.0f}
|
||||
};
|
||||
// Модель прямоугольника
|
||||
Model rectangle;
|
||||
// Загрузка сцены из obj файла
|
||||
std::vector<Model> scene;
|
||||
loadOBJtoVector("../resources/models/cubes.obj", scene, "../resources/models/", "../resources/textures/");
|
||||
|
||||
// Загрузка вершин модели
|
||||
rectangle.load_verteces(verticies, sizeof(verticies)/sizeof(glm::vec3));
|
||||
|
||||
// индексы вершин
|
||||
GLuint indices[] = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
// Загрузка индексов модели
|
||||
rectangle.load_indices(indices, sizeof(indices));
|
||||
|
||||
// Текстурные координаты
|
||||
glm::vec2 texCoords[] = { {0.0f, 0.0f}
|
||||
, {1.0f, 0.0f}
|
||||
, {1.0f, 1.0f}
|
||||
, {0.0f, 1.0f}
|
||||
};
|
||||
|
||||
// Загрузка текстурных координат модели
|
||||
rectangle.load_texCoords(texCoords, sizeof(texCoords)/sizeof(glm::vec2));
|
||||
|
||||
// Зададим горизонтальное положение перед камерой
|
||||
rectangle.position.y = -1;
|
||||
rectangle.position.z = 3;
|
||||
rectangle.rotation.x = 90;
|
||||
rectangle.scale = glm::vec3(3);
|
||||
|
||||
// Текстура травы
|
||||
Texture grass(TEX_DIFFUSE, "../resources/textures/grass.png");
|
||||
rectangle.set_texture(grass);
|
||||
|
||||
// Установка цвета очистки буфера цвета
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
@ -238,7 +205,10 @@ int main(void)
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
// Тут производится рендер
|
||||
rectangle.render(mvp_uniform);
|
||||
for (auto& model : scene)
|
||||
{
|
||||
model.render(mvp_uniform);
|
||||
}
|
||||
|
||||
// Представление содержимого буфера цепочки показа на окно
|
||||
glfwSwapBuffers(window);
|
||||
|
Loading…
x
Reference in New Issue
Block a user