Загрузчик моделей
This commit is contained in:
		
							parent
							
								
									062b5e28d7
								
							
						
					
					
						commit
						8fcff39358
					
				
							
								
								
									
										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
									
									
									
									
									
								
							| @ -183,3 +183,122 @@ void Model::set_index_range(size_t first_byteOffset, size_t count) | ||||
|     first_index_byteOffset = first_byteOffset; | ||||
|     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]*sizeof(GLuint), 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,44 +184,11 @@ 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;  | ||||
|      | ||||
|     // Загрузка вершин модели
 | ||||
|     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); | ||||
|     // Загрузка сцены из obj файла
 | ||||
|     std::vector<Model> scene; | ||||
|     loadOBJtoVector("../resources/models/cubes.obj", scene, "../resources/models/", "../resources/textures/");  | ||||
|      | ||||
|     // Установка цвета очистки буфера цвета
 | ||||
|     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