Загрузчик моделей
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", |         "iosfwd": "cpp", | ||||||
|         "map": "cpp", |         "map": "cpp", | ||||||
|         "atomic": "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 <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 | class Model | ||||||
| { | { | ||||||
|     public: |     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; |     first_index_byteOffset = first_byteOffset; | ||||||
|     indices_count = count; |     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,45 +184,12 @@ int main(void) | |||||||
|     glUseProgram(shaderProgram); |     glUseProgram(shaderProgram); | ||||||
|     // Установим значения текстур
 |     // Установим значения текстур
 | ||||||
|     Texture::init_textures(shaderProgram); |     Texture::init_textures(shaderProgram); | ||||||
|  |     // camera.move({0,0,-20});
 | ||||||
| 
 | 
 | ||||||
|     // Вершины прямоугольника
 |     // Загрузка сцены из obj файла
 | ||||||
|     glm::vec3 verticies[] = {  {-0.5f, -0.5f, 0.0f} |     std::vector<Model> scene; | ||||||
|                              , { 0.5f, -0.5f, 0.0f} |     loadOBJtoVector("../resources/models/cubes.obj", scene, "../resources/models/", "../resources/textures/");  | ||||||
|                              , { 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); |  | ||||||
| 
 |  | ||||||
|     // Установка цвета очистки буфера цвета
 |     // Установка цвета очистки буфера цвета
 | ||||||
|     glClearColor(0.0f, 0.0f, 0.0f, 1.0f); |     glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | ||||||
| 
 | 
 | ||||||
| @ -238,7 +205,10 @@ int main(void) | |||||||
|         glClear(GL_COLOR_BUFFER_BIT); |         glClear(GL_COLOR_BUFFER_BIT); | ||||||
| 
 | 
 | ||||||
|         // Тут производится рендер
 |         // Тут производится рендер
 | ||||||
|         rectangle.render(mvp_uniform); |         for (auto& model : scene) | ||||||
|  |         { | ||||||
|  |             model.render(mvp_uniform);   | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         // Представление содержимого буфера цепочки показа на окно
 |         // Представление содержимого буфера цепочки показа на окно
 | ||||||
|         glfwSwapBuffers(window); |         glfwSwapBuffers(window); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user