Копия проекта с 03
This commit is contained in:
		
							parent
							
								
									3b5808973c
								
							
						
					
					
						commit
						685e8cbbff
					
				
							
								
								
									
										18
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								.vscode/c_cpp_properties.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| { | ||||
|     "configurations": [ | ||||
|         { | ||||
|             "name": "some_name", | ||||
|             "includePath": [ | ||||
|                 "${workspaceFolder}/include", | ||||
|                 "${workspaceFolder}/../dependencies/GLFW/include", | ||||
|                 "${workspaceFolder}/../dependencies/glad/include", | ||||
|                 "${workspaceFolder}/../dependencies/glm" | ||||
|             ], | ||||
|             "compilerPath": "C:/MinGW/bin/g++.exe", | ||||
|             "cStandard": "c11", | ||||
|             "cppStandard": "c++11", | ||||
|             "intelliSenseMode": "gcc-x86" | ||||
|         } | ||||
|     ], | ||||
|     "version": 4 | ||||
| } | ||||
							
								
								
									
										14
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,14 @@ | ||||
| { | ||||
|     "files.associations": { | ||||
|         "fstream": "cpp", | ||||
|         "iosfwd": "cpp", | ||||
|         "map": "cpp", | ||||
|         "atomic": "cpp", | ||||
|         "iostream": "cpp", | ||||
|         "array": "cpp", | ||||
|         "functional": "cpp", | ||||
|         "tuple": "cpp", | ||||
|         "type_traits": "cpp", | ||||
|         "utility": "cpp" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| { | ||||
|     "tasks": [ | ||||
|         { | ||||
|             "type": "cppbuild", | ||||
|             "label": "C/C++: make сборка", | ||||
|             "command": "make", | ||||
|             "args": [ | ||||
|                 "${input:target}" | ||||
|             ], | ||||
|             "options": { | ||||
|                 "cwd": "${workspaceRoot}" | ||||
|             }, | ||||
|             "problemMatcher": [ | ||||
|                 "$gcc" | ||||
|             ], | ||||
|             "group": { | ||||
|                 "kind": "build", | ||||
|                 "isDefault": true | ||||
|             }, | ||||
|             "detail": "Задача создана отладчиком." | ||||
|         } | ||||
|     ], | ||||
|     "inputs": [ | ||||
|         { | ||||
|             "id": "target", | ||||
|             "description": "Цель сборки (all, list, clean)", | ||||
|             "default": "all", | ||||
|             "type": "promptString" | ||||
|         }, | ||||
|     ], | ||||
|     "version": "2.0.0" | ||||
| } | ||||
							
								
								
									
										99
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,99 @@ | ||||
| # Компилятор и директория проекта
 | ||||
| ifeq ($(OS), Windows_NT) | ||||
| 	# С возможностью сборки x32 | ||||
| 	ifeq ($(MAKECMDGOALS), x32) | ||||
| 		CC = C:/MinGW/bin/g++.exe | ||||
| 	else | ||||
| 		CC = C:/MinGW64/bin/g++.exe | ||||
| 	endif | ||||
| 	PROJECT_DIR = $(shell echo %cd%) | ||||
| 	PATH_SEPARATOR = \\ | ||||
| 	# Имя исполняемого файла | ||||
| 	EXECUTABLE = $(notdir $(strip $(PROJECT_DIR))).exe | ||||
| else | ||||
| 	CC = g++ | ||||
| 	PROJECT_DIR = $(shell pwd) | ||||
| 	PATH_SEPARATOR = / | ||||
| 	# Имя исполняемого файла | ||||
| 	EXECUTABLE = $(notdir $(strip $(PROJECT_DIR))) | ||||
| endif | ||||
| 
 | ||||
| # Опции компилятора
 | ||||
| CFLAGS += -c | ||||
| CFLAGS += -I./include | ||||
| CFLAGS += -I../dependencies/GLFW/include | ||||
| CFLAGS += -I../dependencies/glad/include | ||||
| CFLAGS += -I../dependencies/glm | ||||
| 
 | ||||
| # Опции линкера
 | ||||
| LDFLAGS += --std=c++11 | ||||
| # Архитектурозависимые опции линкера
 | ||||
| ifeq ($(OS), Windows_NT) | ||||
| 	# GLFW в зависимости от архитектуры | ||||
| 	ifeq ($(MAKECMDGOALS), x32) | ||||
| 		LDFLAGS += -L../dependencies/GLFW/lib-mingw | ||||
| 	else | ||||
| 		LDFLAGS += -L../dependencies/GLFW/lib-mingw-w64 | ||||
| 	endif | ||||
| 
 | ||||
| 	LDFLAGS += -static | ||||
| 	LDFLAGS += -lglfw3dll | ||||
| 	LDFLAGS += -lopengl32 | ||||
| else | ||||
| 	LDFLAGS += -lglfw | ||||
| 	LDFLAGS += -lGL | ||||
| endif | ||||
| 
 | ||||
| # Библиотека GLAD
 | ||||
| GLAD := ../dependencies/glad/src/glad.c | ||||
| GLAD_O := $(GLAD:.c=.o) | ||||
| 
 | ||||
| # Файлы из директории src
 | ||||
| SOURCES_C = $(wildcard src/*.c) | ||||
| SOURCES_CPP = $(wildcard src/*.cpp)  | ||||
| 
 | ||||
| # Директория с объектными файлами
 | ||||
| OBJ_DIR := Obj | ||||
| # Объектные файлы
 | ||||
| OBJECTS = $(addprefix $(OBJ_DIR)/,$(SOURCES_C:src/%.c=%.o) $(SOURCES_CPP:src/%.cpp=%.o)) | ||||
| 
 | ||||
| # Для x32 сборки под Windows
 | ||||
| ifeq ($(OS), Windows_NT) | ||||
| 	ifeq ($(MAKECMDGOALS), x32) | ||||
| x32: all | ||||
| 	endif | ||||
| endif | ||||
| 
 | ||||
| # Цель по умолчанию, зависит от EXECUTABLE
 | ||||
| all: $(EXECUTABLE) | ||||
| 
 | ||||
| # Цель сборки исполняемого файла, зависит от OBJ_DIR, OBJECTS и GLAD_O
 | ||||
| $(EXECUTABLE): $(OBJ_DIR) $(OBJECTS) $(GLAD_O) | ||||
| 	$(CC)  $(OBJECTS)  $(GLAD_O) $(LDFLAGS) -o $@ | ||||
| 
 | ||||
| # Цель для сборки GLAD
 | ||||
| $(GLAD_O): $(GLAD) | ||||
| 	$(CC) $(CFLAGS) $< -o $@ | ||||
| 
 | ||||
| # Цель для создания директории с объектными файлами
 | ||||
| $(OBJ_DIR): | ||||
| 	@mkdir $(OBJ_DIR) | ||||
| 
 | ||||
| # Цель сборки объектных файлов
 | ||||
| $(OBJ_DIR)/%.o: src/%.c | ||||
| 	$(CC) $(CFLAGS) $< -o $@ | ||||
| $(OBJ_DIR)/%.o: src/%.cpp | ||||
| 	$(CC) $(CFLAGS) $< -o $@ | ||||
| 
 | ||||
| # Цель вывода всех файлов, учавствтующих в сборке
 | ||||
| list: | ||||
| 	@echo "В сборке участвуют:" $(OBJECTS) | ||||
| 
 | ||||
| # Очистка
 | ||||
| ifeq ($(OS), Windows_NT) | ||||
| clean: $(OBJ_DIR) | ||||
| 	@rmdir /s /q $(OBJ_DIR) | ||||
| else | ||||
| clean: $(OBJ_DIR) | ||||
| 	@rm -f $(EXECUTABLE) $(OBJECTS) | ||||
| endif | ||||
							
								
								
									
										50
									
								
								include/Buffers.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								include/Buffers.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| #ifndef BUFFERS_H | ||||
| #define BUFFERS_H | ||||
| 
 | ||||
| #include <glad/glad.h> | ||||
| 
 | ||||
| #include <map> | ||||
| 
 | ||||
| // Объект массива вершин
 | ||||
| class VAO | ||||
| { | ||||
|     public: | ||||
|         VAO(); // Создает VAO и активирует его
 | ||||
|         ~VAO(); // Уничтожает VAO
 | ||||
|         VAO(const VAO & copy); // Конструктор копирования
 | ||||
|         VAO& operator=(const VAO & other); // Оператор присваивания
 | ||||
| 
 | ||||
|         void use(); // Активация VAO
 | ||||
|         static void disable(); // Деактивация активного VAO
 | ||||
| 
 | ||||
|     private: | ||||
|         GLuint handler; // Дескриптор
 | ||||
|         static std::map<GLuint, GLuint> handler_count; // Счетчик использований дескриптора
 | ||||
| }; | ||||
| 
 | ||||
| // Тип буфера
 | ||||
| enum BUFFER_TYPE {  VERTEX = GL_ARRAY_BUFFER | ||||
|                   , ELEMENT = GL_ELEMENT_ARRAY_BUFFER | ||||
|                  }; | ||||
| 
 | ||||
| // Объект вершинного буфера
 | ||||
| class BO | ||||
| { | ||||
|     public: | ||||
|         BO(BUFFER_TYPE type); // Создает пустой буфер заданного типа
 | ||||
|         BO(BUFFER_TYPE type, const void *data, int size); // Создает и загружает туда данные
 | ||||
|         ~BO(); // Уничтожает буфер
 | ||||
|         BO(const BO & copy); // Конструктор копирования
 | ||||
|         BO& operator=(const BO & other); // Оператор присваивания
 | ||||
| 
 | ||||
|         void load(const void *data, int size, GLuint mode = GL_STATIC_DRAW); // Загрузка данных в буфер
 | ||||
|         void use();  | ||||
| 
 | ||||
|     protected: | ||||
|         GLuint handler; // Дескриптор
 | ||||
|         BUFFER_TYPE type; // Тип буфера
 | ||||
|     private: | ||||
|         static std::map<GLuint, GLuint> handler_count; // Счетчик использований дескриптора
 | ||||
| }; | ||||
| 
 | ||||
| #endif // BUFFERS_H
 | ||||
							
								
								
									
										62
									
								
								include/Camera.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								include/Camera.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,62 @@ | ||||
| #ifndef CAMERA_H | ||||
| #define CAMERA_H | ||||
| 
 | ||||
| #include <GLM/glm.hpp> | ||||
| #include <GLM/gtx/euler_angles.hpp> | ||||
| #include <GLM/gtc/matrix_transform.hpp> | ||||
| #include <GLM/ext/matrix_transform.hpp> | ||||
| 
 | ||||
| #include "Model.h" | ||||
| 
 | ||||
| // Ближняя граница области отсечения
 | ||||
| #define CAMERA_NEAR 0.1f | ||||
| // Дальняя граница области отсечения
 | ||||
| #define CAMERA_FAR 100.0f | ||||
| // Вектор, задающий верх для камеры
 | ||||
| #define CAMERA_UP_VECTOR glm::vec3(0.0f, 1.0f, 0.0f) | ||||
| // Вектор, задающий стандартный поворот углами Эйлера (в положительном направлении оси Z)
 | ||||
| #define CAMERA_DEFAULT_ROTATION glm::vec3(0.0f, 180.0f, 0.0f) | ||||
| // Стандартный угол обзора 
 | ||||
| #define CAMERA_FOVy 60.0f | ||||
| // Стандартная чувствительность
 | ||||
| #define CAMERA_DEFAULT_SENSIVITY 0.005f | ||||
| 
 | ||||
| class Camera : public Node | ||||
| { | ||||
|     public: | ||||
|         Camera(float aspect, const glm::vec3 &position = glm::vec3(0.0f), const glm::vec3 &initialRotation = CAMERA_DEFAULT_ROTATION, float fovy = CAMERA_FOVy); // Конструктор камеры с проекцией перспективы
 | ||||
|         Camera(float width, float height, const glm::vec3 &position = glm::vec3(0.0f), const glm::vec3 &initialRotation = CAMERA_DEFAULT_ROTATION); // Конструктор ортографической камеры
 | ||||
|         Camera(const Camera& copy); // Конструктор копирования камеры
 | ||||
|         Camera& operator=(const Camera& other); // Оператор присваивания
 | ||||
|         virtual ~Camera(); // Деструктор
 | ||||
| 
 | ||||
|         const glm::mat4& getVP(); // Возвращает ссылку на константную матрицу произведения матриц вида и проекции
 | ||||
|         const glm::mat4& getProjection(); // Возвращает ссылку на константную матрицу проекции 
 | ||||
|         const glm::mat4& getView(); // Возвращает ссылку на константную матрицу вида
 | ||||
|          | ||||
|         void rotate(const glm::vec2 &xyOffset); // Поворачивает камеру на dx и dy пикселей с учетом чувствительности
 | ||||
|          | ||||
|         void setPerspective(float fov, float aspect); // Устанавливает заданную матрицу перспективы
 | ||||
|         void setOrtho(float width, float height); // Устанавливает заданную ортографическую матрицу
 | ||||
|         void setSensitivity(float sensitivity); // Изменяет чувствительность мыши
 | ||||
|         const float& getSensitivity() const; // Возвращает чувствительность мыши
 | ||||
|          | ||||
|         void use(); // Использование этой камеры как текущей
 | ||||
|         static Camera& current(); // Ссылка на текущую используемую камеру
 | ||||
|     protected: | ||||
|         Camera(const glm::vec3 &position, const glm::vec3 &initialRotation); // Защищенный (protected) конструктор камеры без перспективы 
 | ||||
| 
 | ||||
|         glm::mat4 view; // Матрица вида
 | ||||
|         glm::mat4 projection; // Матрица проекции
 | ||||
|         glm::mat4 vp; // Матрица произведения вида и проекции
 | ||||
|         bool requiredRecalcVP; // Необходимость пересчета матрицы вида и проекции камеры
 | ||||
|          | ||||
|         float sensitivity; // Чувствительность мыши
 | ||||
|          | ||||
|         virtual void recalcMatrices(); // Метод пересчета матрицы вида и произведения Вида*Проекции по необходимости, должен сбрасывать флаг changed
 | ||||
| 
 | ||||
|         static Camera* p_current; // Указатель на текущую используемую камеру
 | ||||
| };       | ||||
| 
 | ||||
| 
 | ||||
| #endif // CAMERA_H
 | ||||
							
								
								
									
										75
									
								
								include/Model.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								include/Model.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,75 @@ | ||||
| #ifndef MODEL_H | ||||
| #define MODEL_H | ||||
| 
 | ||||
| #include "Buffers.h" | ||||
| 
 | ||||
| #include <GLM/glm.hpp> | ||||
| #include <GLM/gtc/quaternion.hpp> | ||||
| #include <GLM/gtc/matrix_transform.hpp> | ||||
| 
 | ||||
| #include <vector> | ||||
| 
 | ||||
| // Класс узла сцены
 | ||||
| class Node  | ||||
| { | ||||
|     public: | ||||
|         Node(Node* parent = NULL); // Конструктор с заданным родителем (по умолчанию NULL)
 | ||||
|         Node(const Node& copy); // Конструктор копирования
 | ||||
|         Node& operator=(const Node& other); // Оператор присваивания
 | ||||
|         virtual ~Node(); | ||||
| 
 | ||||
|         void setParent(Node * parent); // Устанавливает родителя для узла
 | ||||
| 
 | ||||
|         virtual const glm::mat4& getTransformMatrix(); // Возвращает матрицу трансформации модели
 | ||||
|         bool isChanged(); // Возвращает необходимость пересчета матрицы трансформации
 | ||||
| 
 | ||||
|         const glm::vec3& c_position() const; // Константный доступ к позиции
 | ||||
|         const glm::quat& c_rotation() const; // Константный доступ к повороту
 | ||||
|         const glm::vec3& c_scale() const; // Константный доступ к масштабированию
 | ||||
|         virtual glm::vec3& e_position(); // Неконстантная ссылка для изменений позиции
 | ||||
|         virtual glm::quat& e_rotation(); // Неконстантная ссылка для изменений поворота
 | ||||
|         virtual glm::vec3& e_scale(); // Неконстантная ссылка для изменений масштабирования 
 | ||||
| 
 | ||||
|         Node* getParent(); // Возвращает указатель на родителя
 | ||||
|         const std::vector<Node*>& getChildren() const; // Возвращает ссылку на вектор дочерних узлов
 | ||||
| 
 | ||||
|     protected: | ||||
|         Node *parent; // Родительский узел
 | ||||
|         std::vector<Node*> children; // Узлы-потомки !Не должны указывать на NULL!
 | ||||
| 
 | ||||
|         glm::vec3 position; // позиция модели
 | ||||
|         glm::quat rotation; // поворот модели
 | ||||
|         glm::vec3 scale;    // масштабирование модели
 | ||||
| 
 | ||||
|         bool changed; // Флаг необходимости пересчета матрицы трансформации
 | ||||
|         glm::mat4 transform; // Матрица трансформации модели
 | ||||
|         bool parent_changed; // Флаг изменений у родителя - необходимость пересчета итоговой трансформации
 | ||||
|         glm::mat4 result_transform; // Итоговая трансформация с учетом родительской
 | ||||
| 
 | ||||
|         virtual void recalcMatrices(); // Метод пересчета матрицы трансформации по необходимости, должен сбрасывать флаг changed
 | ||||
|         void invalidateParent(); // Проход потомков в глубину с изменением флага parent_changed
 | ||||
| }; | ||||
| 
 | ||||
| // Класс модели
 | ||||
| class Model : public Node | ||||
| { | ||||
|     public: | ||||
|         Model(Node *parent = NULL); // Конструктор по умолчанию
 | ||||
|         Model(const Model& copy); // Конструктор копирования
 | ||||
|         Model& operator=(const Model& other); // Оператор присваивания
 | ||||
|         virtual ~Model(); | ||||
| 
 | ||||
|         void render(const GLuint &model_uniform); // Вызов отрисовки
 | ||||
| 
 | ||||
|         void load_verteces(glm::vec3* verteces, GLuint count); // Загрузка вершин в буфер
 | ||||
|         void load_indices(GLuint* indices, GLuint count); // Загрузка индексов в буфер
 | ||||
|         void set_index_range(size_t first_byteOffset, size_t count); // Ограничение диапазона из буфера индексов
 | ||||
|          | ||||
|     private: | ||||
|         VAO vao; | ||||
|         BO vertex_vbo, index_vbo; // вершинный и индексный буферы
 | ||||
|         GLuint verteces_count; // Количество вершин
 | ||||
|         size_t first_index_byteOffset, indices_count; // Сдвиг в байтах для первого и количество индексов
 | ||||
| }; | ||||
| 
 | ||||
| #endif // MODEL_H
 | ||||
							
								
								
									
										32
									
								
								include/Scene.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								include/Scene.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| #ifndef SCENE_H | ||||
| #define SCENE_H | ||||
| 
 | ||||
| #include "Model.h" | ||||
| #include "Camera.h" | ||||
| 
 | ||||
| // Класс сцены
 | ||||
| class Scene | ||||
| { | ||||
|     public: | ||||
|         Scene(); // Конструктор пустой сцены
 | ||||
|         Scene(const Scene ©); // Конструктор копирования
 | ||||
|         Scene& operator=(const Scene& other); // Оператор присваивания
 | ||||
| 
 | ||||
|         void render(const GLuint &model_uniform); // Рендер сцены
 | ||||
| 
 | ||||
|         Node root; // Корневой узел
 | ||||
| 
 | ||||
|         // Списки объектов, выступающих узлами
 | ||||
|         std::vector<Node> nodes; // Список пустых узлов
 | ||||
|         std::vector<Model> models; // Список моделей для рендера
 | ||||
|         std::vector<Camera> cameras; // Список камер
 | ||||
|      | ||||
|     protected: | ||||
|         void rebuld_tree(const Scene& from); // Перестройка дерева после копирования или присваивания
 | ||||
|         template <class T> | ||||
|         void rebuild_Nodes_vector(T& nodes, const Scene& from); // Перестройка узлов выбранного списка
 | ||||
|         template <class T> | ||||
|         bool move_pointer(Node& for_node, const std::vector<T>& from_nodes, std::vector<T>& this_nodes); // Сдвигает родителя узла между двумя списками при условии его принадлежности к оригинальному, возвращает признак замены
 | ||||
| }; | ||||
| 
 | ||||
| #endif // SCENE_H
 | ||||
							
								
								
									
										8
									
								
								shaders/shader.frag
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								shaders/shader.frag
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| #version 330 core  | ||||
| 
 | ||||
| out vec3 color;  | ||||
| 
 | ||||
| void main()  | ||||
| {  | ||||
|     color = vec3(1, 0, 0);  | ||||
| }  | ||||
							
								
								
									
										11
									
								
								shaders/shader.vert
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								shaders/shader.vert
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| #version 330 core  | ||||
| 
 | ||||
| layout(location = 0) in vec3 pos;  | ||||
| 
 | ||||
| uniform mat4 vp; | ||||
| uniform mat4 model; | ||||
| 
 | ||||
| void main()  | ||||
| {  | ||||
|     gl_Position = vp * model * vec4(pos, 1.0); | ||||
| }  | ||||
							
								
								
									
										119
									
								
								src/Buffers.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								src/Buffers.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
| #include "Buffers.h" | ||||
| 
 | ||||
| // Счетчики использований дескрипторов
 | ||||
| std::map<GLuint, GLuint> VAO::handler_count;  | ||||
| std::map<GLuint, GLuint> BO::handler_count;  | ||||
| 
 | ||||
| // Создает VAO и активирует его
 | ||||
| VAO::VAO() | ||||
| {  | ||||
|     glGenVertexArrays(1, &handler); // Генерация одного объекта массива вершин
 | ||||
|     glBindVertexArray(handler);     // Привязка для использования
 | ||||
|     handler_count[handler] = 1;     // Инициализация счетчика для дескриптора 
 | ||||
| } | ||||
| 
 | ||||
| // Уничтожает VAO
 | ||||
| VAO::~VAO() | ||||
| { | ||||
|     // Если дескриптор никем не используется - освободим его
 | ||||
|     if (!--handler_count[handler]) | ||||
|     { | ||||
|         glDeleteVertexArrays(1, &handler); | ||||
|         handler_count.erase(handler); // Удаление из словаря
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Конструктор копирования
 | ||||
| VAO::VAO(const VAO & copy) : handler(copy.handler) | ||||
| { | ||||
|     handler_count[handler]++; | ||||
| } | ||||
| 
 | ||||
| // Оператор присваивания
 | ||||
| VAO& VAO::operator=(const VAO & other)  | ||||
| { | ||||
|     // Если это разные дескрипторы
 | ||||
|     if (handler != other.handler) | ||||
|     { // то следуюет удалить текущий перед заменой
 | ||||
|         this->~VAO();  | ||||
|         handler = other.handler; | ||||
|         handler_count[handler]++; | ||||
|     } | ||||
| 
 | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| // Активация VAO
 | ||||
| void VAO::use() | ||||
| { | ||||
|     glBindVertexArray(handler); // Привязка VAO для использования
 | ||||
| } | ||||
| 
 | ||||
| // Деактивация активного VAO
 | ||||
| void VAO::disable() | ||||
| { | ||||
|     glBindVertexArray(0);       // Отключение VAO
 | ||||
| } | ||||
| 
 | ||||
| // Создает пустой буфер заданного типа
 | ||||
| BO::BO(BUFFER_TYPE t) : type(t) | ||||
| { | ||||
|     glGenBuffers(1, &handler); // Генерация одного объекта буфера
 | ||||
|     handler_count[handler] = 1; | ||||
|     use(); // Привязка буфера
 | ||||
| } | ||||
| 
 | ||||
| // Создает и загружает туда данные
 | ||||
| BO::BO(BUFFER_TYPE t, const void *data, int size) : BO(t) | ||||
| { | ||||
|     load(data, size); | ||||
| } | ||||
| 
 | ||||
| // Уничтожает буфер
 | ||||
| BO::~BO() | ||||
| { | ||||
|     if (handler) // Если буфер был создан
 | ||||
|     { | ||||
|         // Если дескриптор никем не используется - освободим его
 | ||||
|         if (!--handler_count[handler]) | ||||
|         { | ||||
|             glDeleteBuffers(1, &handler); | ||||
|             handler_count.erase(handler); // Удаление из словаря
 | ||||
|         } | ||||
|         handler = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Конструктор копирования
 | ||||
| BO::BO(const BO & copy) : handler(copy.handler), type(copy.type) | ||||
| { | ||||
|     handler_count[handler]++; | ||||
| } | ||||
| 
 | ||||
| // Оператор присваивания
 | ||||
| BO& BO::operator=(const BO & other) | ||||
| { | ||||
|     // Если это разные дескрипторы
 | ||||
|     if (handler != other.handler) | ||||
|     { // то следуюет удалить текущий перед заменой
 | ||||
|         this->~BO();  | ||||
|         handler = other.handler; | ||||
|         handler_count[handler]++; | ||||
|     } | ||||
|     // Изменим тип
 | ||||
|     type = other.type; | ||||
| 
 | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| // Загрузка вершин в буфер
 | ||||
| void BO::load(const void *data, int size, GLuint mode) | ||||
| { | ||||
|     use(); // Привязка буфера
 | ||||
|     glBufferData(type, size, data, mode); | ||||
| } | ||||
| 
 | ||||
| void BO::use() | ||||
| { | ||||
|     glBindBuffer(type, handler); // Привязка элементного буфера
 | ||||
| } | ||||
							
								
								
									
										181
									
								
								src/Camera.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										181
									
								
								src/Camera.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,181 @@ | ||||
| #include "Camera.h" | ||||
| 
 | ||||
| // Указатель на текущую используемую камеру
 | ||||
| Camera* Camera::p_current = NULL;  | ||||
| 
 | ||||
| // Защищенный (protected) конструктор камеры без перспективы 
 | ||||
| Camera::Camera(const glm::vec3 &pos, const glm::vec3 &initialRotation) | ||||
| { | ||||
|     sensitivity = CAMERA_DEFAULT_SENSIVITY; | ||||
|     position = pos; // задаем позицию
 | ||||
|     // Определяем начальный поворот
 | ||||
|     glm::quat rotationAroundX = glm::angleAxis( glm::radians(initialRotation.x), glm::vec3(1.0f, 0.0f, 0.0f)); | ||||
|     glm::quat rotationAroundY = glm::angleAxis(-glm::radians(initialRotation.y), glm::vec3(0.0f, 1.0f, 0.0f)); | ||||
|     glm::quat rotationAroundZ = glm::angleAxis( glm::radians(initialRotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); | ||||
|     rotation = rotationAroundX * rotationAroundY * rotationAroundZ; | ||||
|     // Признак изменения
 | ||||
|     changed = true; | ||||
| } | ||||
| 
 | ||||
| // Конструктор камеры с проекцией перспективы
 | ||||
| Camera::Camera(float aspect, const glm::vec3 &position, const glm::vec3 &initialRotation, float fovy) | ||||
| : Camera(position, initialRotation) | ||||
| { | ||||
|     setPerspective(fovy, aspect); | ||||
| } | ||||
| 
 | ||||
| // Конструктор ортографической камеры
 | ||||
| Camera::Camera(float width, float height, const glm::vec3 &position, const glm::vec3 &initialRotation) | ||||
| : Camera(position, initialRotation) | ||||
| { | ||||
|     setOrtho(width, height); | ||||
| } | ||||
| 
 | ||||
| // Конструктор копирования камеры
 | ||||
| Camera::Camera(const Camera& copy)  | ||||
| : projection(copy.projection), requiredRecalcVP(copy.requiredRecalcVP), sensitivity(copy.sensitivity) | ||||
| { | ||||
|     // Если у оригинала не было изменений - перепишем матрицу вида-проекции
 | ||||
|     if (!requiredRecalcVP) | ||||
|         vp = copy.vp; | ||||
| } | ||||
| 
 | ||||
| // Оператор присваивания
 | ||||
| Camera& Camera::operator=(const Camera& other) | ||||
| { | ||||
|     projection = other.projection; | ||||
|     requiredRecalcVP = other.requiredRecalcVP; | ||||
|     sensitivity = other.sensitivity; | ||||
| 
 | ||||
|     // Если у оригинала не было изменений - перепишем матрицу вида-проекции
 | ||||
|     if (!requiredRecalcVP) | ||||
|         vp = other.vp; | ||||
| 
 | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| // Деструктор
 | ||||
| Camera::~Camera()  | ||||
| {  | ||||
|     if (p_current == this) | ||||
|         p_current = NULL; | ||||
| } | ||||
| 
 | ||||
| // Возвращает ссылку на константную матрицу проекции
 | ||||
| const glm::mat4& Camera::getProjection() | ||||
| { | ||||
|     return projection; | ||||
| } | ||||
| 
 | ||||
| // Возвращает ссылку на константную матрицу вида
 | ||||
| const glm::mat4& Camera::getView() | ||||
| { | ||||
|     recalcMatrices(); | ||||
| 
 | ||||
|     return view; | ||||
| } | ||||
| 
 | ||||
| // Возвращает ссылку на константную матрицу вида
 | ||||
| const glm::mat4& Camera::getVP() | ||||
| { | ||||
|     recalcMatrices(); | ||||
| 
 | ||||
|     return vp; | ||||
| } | ||||
| 
 | ||||
| // Устанавливает заданную матрицу перспективы
 | ||||
| void Camera::setPerspective(float fovy, float aspect) | ||||
| { | ||||
|     projection = glm::perspective(glm::radians(fovy), aspect, CAMERA_NEAR, CAMERA_FAR); | ||||
|     requiredRecalcVP = true; | ||||
| } | ||||
| 
 | ||||
| // Устанавливает заданную ортографическую матрицу
 | ||||
| void Camera::setOrtho(float width, float height) | ||||
| { | ||||
|     const float aspect = width / height; | ||||
|     projection = glm::ortho(-1.0f, 1.0f, -1.0f/aspect, 1.0f/aspect, CAMERA_NEAR, CAMERA_FAR); | ||||
|     requiredRecalcVP = true; | ||||
| } | ||||
| 
 | ||||
| // Изменяет чувствительность мыши
 | ||||
| void Camera::setSensitivity(float sens) | ||||
| { | ||||
|     sensitivity = sens; | ||||
| } | ||||
| 
 | ||||
| // Возвращает чувствительность мыши
 | ||||
| const float& Camera::getSensitivity() const | ||||
| { | ||||
|     return sensitivity;  | ||||
| } | ||||
| 
 | ||||
| // Метод пересчета матрицы вида и произведения Вида*Проекции по необходимости, должен сбрасывать флаг changed
 | ||||
| void Camera::recalcMatrices() | ||||
| { | ||||
|     if (changed || parent_changed) | ||||
|     { | ||||
|         glm::vec3 _position = position; | ||||
|         glm::quat _rotation = rotation; | ||||
|         if (parent) // Если есть родитель
 | ||||
|         { | ||||
|             glm::mat4 normalized_transform = parent->getTransformMatrix(); | ||||
|             for (int i = 0; i < 3; i++)  | ||||
|             { | ||||
|                 glm::vec3 axis = glm::vec3(normalized_transform[i]); | ||||
|                 normalized_transform[i] = glm::vec4(glm::normalize(axis), normalized_transform[i].w); | ||||
|             } | ||||
|             glm::vec4 tmp = normalized_transform * glm::vec4(_position, 1.0f); | ||||
|             tmp /= tmp.w; | ||||
|             _position = glm::vec3(tmp); | ||||
|             _rotation = glm::quat_cast(normalized_transform) * _rotation; | ||||
|         } | ||||
|         glm::mat4 rotationMatrix = glm::mat4_cast(glm::conjugate(_rotation)); | ||||
|         glm::mat4 translationMatrix = glm::translate(glm::mat4(1.0f), -_position); | ||||
|         view = rotationMatrix * translationMatrix; | ||||
|         requiredRecalcVP = true; | ||||
|     } | ||||
|    | ||||
|     Node::recalcMatrices(); | ||||
| 
 | ||||
|     if (requiredRecalcVP) | ||||
|     { | ||||
|         vp = projection * view; | ||||
|         requiredRecalcVP = false; // Изменения применены
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Поворачивает камеру на dx и dy пикселей с учетом чувствительности
 | ||||
| void Camera::rotate(const glm::vec2 &xyOffset) | ||||
| { | ||||
|     // xyOffset - сдвиги координат мыши, xyOffset.x означает поворот вокруг оси Y, а xyOffset.y - поворот вокруг оси X
 | ||||
|      | ||||
|     // Вращение вокруг оси Y
 | ||||
|     glm::quat qY = glm::angleAxis(-xyOffset.x * sensitivity, glm::vec3(0.0f, 1.0f, 0.0f)); | ||||
|      | ||||
|     // Вращение вокруг оси X
 | ||||
|     glm::quat qX = glm::angleAxis(xyOffset.y * sensitivity, glm::vec3(1.0f, 0.0f, 0.0f)); | ||||
| 
 | ||||
|     // Сначала применяем вращение вокруг Y, затем вокруг X
 | ||||
|     rotation = qY * rotation * qX; | ||||
| 
 | ||||
|     changed = true; | ||||
|     invalidateParent(); // Проход потомков в глубину с изменением флага parent_changed
 | ||||
| } | ||||
| 
 | ||||
| // Использование этой камеры как текущей
 | ||||
| void Camera::use() | ||||
| { | ||||
|     p_current = this; | ||||
| } | ||||
| 
 | ||||
| // Ссылка на текущую используемую камеру
 | ||||
| Camera& Camera::current() | ||||
| { | ||||
|     static Camera default_cam(800.0f/600.0f); | ||||
| 
 | ||||
|     if (!p_current) | ||||
|         return default_cam; | ||||
|     else | ||||
|         return *p_current; | ||||
| } | ||||
							
								
								
									
										306
									
								
								src/Model.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								src/Model.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,306 @@ | ||||
| #include "Model.h" | ||||
| 
 | ||||
| #include <algorithm> | ||||
| 
 | ||||
| // Конструктор с заданным родителем (по умолчанию NULL)
 | ||||
| Node::Node(Node* parent_) : parent(parent_), result_transform(1), parent_changed(false), | ||||
| position(0), rotation(1.0f, 0.0f, 0.0f, 0.0f), scale(1), changed(false), transform(1) | ||||
| { | ||||
|     if (parent) | ||||
|     { | ||||
|         // Запишем себя в потомки
 | ||||
|         parent->children.push_back(this); | ||||
|         parent_changed = true; | ||||
|     } | ||||
| }  | ||||
| 
 | ||||
| // Конструктор копирования
 | ||||
| Node::Node(const Node& copy): position(copy.position), rotation(copy.position), scale(copy.scale), | ||||
| parent(copy.parent), parent_changed(copy.parent_changed), transform(1), result_transform(1) | ||||
| { | ||||
|     // Запишем себя в потомки
 | ||||
|     if (parent) | ||||
|         parent->children.push_back(this); | ||||
|     // Если у оригинала не было изменений - перепишем матрицу трансформации
 | ||||
|     if (!changed) | ||||
|         transform = copy.transform; | ||||
|     // Если у родителя не было изменений для оригинала - перепишем результирующую матрицу трансформации
 | ||||
|     if (!parent_changed) | ||||
|         result_transform = copy.result_transform; | ||||
| } | ||||
| 
 | ||||
| Node::~Node() | ||||
| { | ||||
|     setParent(NULL); // Удаляем себя из потомков
 | ||||
|     // Сообщаем потомкам об удалении родителя
 | ||||
|     for (Node* child : children) | ||||
|         child->setParent(NULL); | ||||
| } | ||||
| 
 | ||||
| // Возвращает необходимость пересчета матрицы трансформации
 | ||||
| bool Node::isChanged()  | ||||
| {  | ||||
|     return changed;  | ||||
| }  | ||||
| 
 | ||||
| // Константный доступ к позиции
 | ||||
| const glm::vec3& Node::c_position() const  | ||||
| {  | ||||
|     return position;  | ||||
| }  | ||||
| 
 | ||||
| // Константный доступ к повороту
 | ||||
| const glm::quat& Node::c_rotation() const  | ||||
| {  | ||||
|     return rotation;  | ||||
| }  | ||||
| 
 | ||||
| // Константный доступ к масштабированию
 | ||||
| const glm::vec3& Node::c_scale() const  | ||||
| {  | ||||
|     return scale;  | ||||
| }  | ||||
| 
 | ||||
| // Неконстантная ссылка для изменений позиции
 | ||||
| glm::vec3& Node::e_position()  | ||||
| {  | ||||
|     changed = true; // Флаг о изменении
 | ||||
|     invalidateParent(); // Проход потомков в глубину с изменением флага parent_changed
 | ||||
|     return position;  | ||||
| }  | ||||
| 
 | ||||
| // Неконстантная ссылка для изменений поворота
 | ||||
| glm::quat& Node::e_rotation()  | ||||
| {  | ||||
|     changed = true; // Флаг о изменении
 | ||||
|     invalidateParent(); // Проход потомков в глубину с изменением флага parent_changed
 | ||||
|     return rotation;  | ||||
| }  | ||||
| 
 | ||||
| // Неконстантная ссылка для изменений масштабирования         
 | ||||
| glm::vec3& Node::e_scale()  | ||||
| {  | ||||
|     changed = true; // Флаг о изменении
 | ||||
|     invalidateParent(); // Проход потомков в глубину с изменением флага parent_changed
 | ||||
|     return scale;  | ||||
| }  | ||||
| 
 | ||||
| // Возвращает матрицу трансформации модели
 | ||||
| const glm::mat4& Node::getTransformMatrix()  | ||||
| { | ||||
|     // Если требуется - пересчитаем матрицу
 | ||||
|     recalcMatrices(); | ||||
|          | ||||
|     return result_transform; | ||||
| } | ||||
| 
 | ||||
| // Пересчет матрицы трансформации модели, если это требуется
 | ||||
| void Node::recalcMatrices()  | ||||
| { | ||||
|     // Если было изменение по векторам позиции, поворота и масштабирования
 | ||||
|     if  (changed) | ||||
|     { | ||||
|         transform = glm::mat4(1.0f); | ||||
|         // Перемещение модели
 | ||||
|         transform = glm::translate(transform, position); | ||||
|         // Поворот модели
 | ||||
|         transform = transform * glm::mat4_cast(rotation); | ||||
|         // Масштабирование
 | ||||
|         transform = glm::scale(transform, scale);   | ||||
|     } | ||||
| 
 | ||||
|     // Если собственная или родительская матрицы менялись - необходимо пересчитать итоговую
 | ||||
|     if (changed || parent_changed) | ||||
|     { | ||||
|         if (parent) // Если есть родитель
 | ||||
|             result_transform = parent->getTransformMatrix() * transform; | ||||
|         else // Если нет родителя
 | ||||
|             result_transform = transform; | ||||
| 
 | ||||
|         parent_changed = changed = false; // Изменения применены
 | ||||
|     } | ||||
| }  | ||||
| 
 | ||||
| // Проход потомков в глубину с изменением флага parent_changed
 | ||||
| void Node::invalidateParent() | ||||
| { | ||||
|     // Цикл по потомкам
 | ||||
|     for (Node* child : children) | ||||
|     { | ||||
|         child->parent_changed = true; // Флаг 
 | ||||
|         child->invalidateParent(); // Рекурсивный вызов для потомков выбранного потомка
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Устанавливает родителя для узла
 | ||||
| void Node::setParent(Node * parent) | ||||
| { | ||||
|     // Если замена происходит на другого родителя
 | ||||
|     if (parent != this->parent) | ||||
|     { | ||||
|         Node* tmp = parent; | ||||
|         // Проверка на зацикливание об самого себя
 | ||||
|         while (tmp) | ||||
|         { | ||||
|             if (tmp == this) | ||||
|                 return; // Можно выдать exception
 | ||||
|             tmp = tmp->parent; | ||||
|         } | ||||
|         // Если есть старый родитель - удалим себя из его потомков
 | ||||
|         if (this->parent) | ||||
|         { | ||||
|             // Поиск в списке родительских потомков
 | ||||
|             auto position = std::find(this->parent->children.begin(), this->parent->children.end(), this); | ||||
|             // Если итератор указывает в конец - ничего не найдено
 | ||||
|             if (position != this->parent->children.end())  | ||||
|                 this->parent->children.erase(position); // Само удаление
 | ||||
|         } | ||||
|          | ||||
|         this->parent = parent; // Заменяем указатель на родителя
 | ||||
|         // Если родитель не NULL - добавляем себя в детей
 | ||||
|         if (parent)  | ||||
|             parent->children.push_back(this); | ||||
|         // В любом случае необходимо пересчитать собственную итоговую матрицу
 | ||||
|         parent_changed = true; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Возвращает указатель на родителя
 | ||||
| Node* Node::getParent()  | ||||
| {  | ||||
|     return parent;  | ||||
| } | ||||
| 
 | ||||
| // Возвращает ссылку на вектор дочерних узлов
 | ||||
| const std::vector<Node*>& Node::getChildren() const  | ||||
| {  | ||||
|     return children;  | ||||
| } | ||||
| 
 | ||||
| // Оператор присваивания
 | ||||
| Node& Node::operator=(const Node& other) | ||||
| { | ||||
|     position = other.position; | ||||
|     rotation = other.rotation; | ||||
|     scale = other.scale; | ||||
|     changed = other.changed; | ||||
| 
 | ||||
|     if (!changed) | ||||
|         transform = other.transform; | ||||
|          | ||||
|     setParent(other.parent); | ||||
|      | ||||
|     // Если у other флаг parent_changed == false, то можно переписать матрицу результата с него
 | ||||
|     if (!other.parent_changed) | ||||
|     { | ||||
|         result_transform = other.result_transform; | ||||
|         parent_changed = false; // Сбрасываем флаг после смены родителя
 | ||||
|     } | ||||
| 
 | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| // Конструктор по умолчанию
 | ||||
| Model::Model(Node *parent) : Node(parent), verteces_count(0), first_index_byteOffset(0), indices_count(0),  | ||||
| vertex_vbo(VERTEX), index_vbo(ELEMENT) | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // Конструктор копирования
 | ||||
| Model::Model(const Model& copy) : Node(copy), | ||||
| vao(copy.vao),  | ||||
| verteces_count(copy.verteces_count), first_index_byteOffset(copy.first_index_byteOffset), indices_count(copy.indices_count),  | ||||
| vertex_vbo(copy.vertex_vbo), index_vbo(copy.index_vbo) | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // Оператор присваивания
 | ||||
| Model& Model::operator=(const Model& other) | ||||
| { | ||||
|     Node::operator=(other); // Явный вызов родительского оператора копирования
 | ||||
|      | ||||
|     vao = other.vao;  | ||||
|     verteces_count = other.verteces_count; | ||||
|     first_index_byteOffset = other.first_index_byteOffset; | ||||
|     indices_count = other.indices_count; | ||||
|      | ||||
|     vertex_vbo = other.vertex_vbo; | ||||
|     index_vbo = other.index_vbo; | ||||
|      | ||||
|     return *this; | ||||
| } | ||||
| 
 | ||||
| Model::~Model() | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // Вызов отрисовки
 | ||||
| void Model::render(const GLuint &model_uniform)  | ||||
| { | ||||
|     // Загрузим матрицу трансформации
 | ||||
|     glUniformMatrix4fv(model_uniform, 1, GL_FALSE, &getTransformMatrix()[0][0]); | ||||
| 
 | ||||
|     // Подключаем VAO
 | ||||
|     vao.use(); | ||||
|     // Если есть индексы - рисуем с их использованием
 | ||||
|     if (indices_count) | ||||
|     { | ||||
|         index_vbo.use(); | ||||
|         glDrawElements(GL_TRIANGLES, indices_count, GL_UNSIGNED_INT, (void*)(first_index_byteOffset)); | ||||
|     } | ||||
|     // Если есть вершины - рисуем на основании массива вершин
 | ||||
|     else if (verteces_count) | ||||
|         glDrawArrays(GL_TRIANGLES, 0, verteces_count); | ||||
| } | ||||
| 
 | ||||
| // Функция для конфигурации атрибута вершинного буфера
 | ||||
| void vertex_attrib_config() | ||||
| { | ||||
|     // Включаем необходимый атрибут у выбранного VAO
 | ||||
|     glEnableVertexAttribArray(0); | ||||
|     // Устанавливаем связь между VAO и привязанным VBO
 | ||||
|     glVertexAttribPointer(  0         // индекс атрибута, должен совпадать с Layout шейдера
 | ||||
|                           , 3         // количество компонент одного элемента
 | ||||
|                           , GL_FLOAT  // тип
 | ||||
|                           , GL_FALSE  // нормализованность значений
 | ||||
|                           , 0         // шаг
 | ||||
|                           , (void *)0 // отступ с начала массива
 | ||||
|                          ); | ||||
| } | ||||
| 
 | ||||
| // Загрузка вершин в буфер
 | ||||
| void Model::load_verteces(glm::vec3* verteces, GLuint count) | ||||
| { | ||||
|     // Подключаем VAO и вершинный буфер
 | ||||
|     vao.use(); | ||||
|     vertex_vbo.use(); | ||||
| 
 | ||||
|     // Загрузка вершин в память буфера
 | ||||
|     vertex_vbo.load(verteces, sizeof(glm::vec3)*count); | ||||
|     vertex_attrib_config(); | ||||
|     // Запоминаем количество вершин для отрисовки
 | ||||
|     verteces_count = count; | ||||
| } | ||||
| 
 | ||||
| // Загрузка индексов в буфер
 | ||||
| void Model::load_indices(GLuint* indices, GLuint count)  | ||||
| { | ||||
|     // Подключаем VAO и индексный буфер
 | ||||
|     vao.use(); | ||||
|     index_vbo.use(); | ||||
| 
 | ||||
|     // Загрузка вершин в память буфера
 | ||||
|     index_vbo.load(indices, sizeof(GLuint)*count); | ||||
|     // Запоминаем количество вершин для отрисовки
 | ||||
|     indices_count = count; | ||||
| } | ||||
| 
 | ||||
| // Ограничение диапазона из буфера индексов
 | ||||
| void Model::set_index_range(size_t first_byteOffset, size_t count) | ||||
| { | ||||
|     first_index_byteOffset = first_byteOffset; | ||||
|     indices_count = count; | ||||
| }  | ||||
							
								
								
									
										87
									
								
								src/Scene.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/Scene.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| #include "Scene.h" | ||||
| 
 | ||||
| // Конструктор пустой сцены
 | ||||
| Scene::Scene() | ||||
| { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| // Конструктор копирования
 | ||||
| Scene::Scene(const Scene ©): root(copy.root),  | ||||
| nodes(copy.nodes), models(copy.models), cameras(copy.cameras) | ||||
| { | ||||
|     rebuld_tree(copy); | ||||
| }  | ||||
| 
 | ||||
| // Оператор присваивания
 | ||||
| Scene& Scene::operator=(const Scene& other)  | ||||
| { | ||||
|     root = other.root; | ||||
|     nodes = other.nodes; | ||||
|     models = other.models; | ||||
|     cameras = other.cameras; | ||||
| 
 | ||||
|     rebuld_tree(other); | ||||
| 
 | ||||
|     return *this; | ||||
| }  | ||||
| 
 | ||||
| // Рендер сцены
 | ||||
| void Scene::render(const GLuint &model_uniform)  | ||||
| { | ||||
|     for (auto & model : models) | ||||
|         model.render(model_uniform); | ||||
| } | ||||
| 
 | ||||
| // Перестройка узлов выбранного списка
 | ||||
| template <class T> | ||||
| void Scene::rebuild_Nodes_vector(T& nodes, const Scene& from) | ||||
| { | ||||
|     for (int i = 0; i < nodes.size(); i++) | ||||
|     { | ||||
|         // Берем родителя, который указывает на оригинальный объект
 | ||||
|         Node* parent = nodes[i].getParent(); | ||||
|          | ||||
|         // Если родитель - оригинальный корневой узел, то меняем на собственный корневой узел
 | ||||
|         if (parent == &from.root)  | ||||
|         { | ||||
|             nodes[i].setParent(&root); | ||||
|             continue; | ||||
|         } | ||||
|          | ||||
|         // Если наши родителя - меняем на него
 | ||||
|         if (move_pointer(nodes[i], from.nodes, this->nodes)) | ||||
|             continue; | ||||
|         if (move_pointer(nodes[i], from.models, models)) | ||||
|             continue; | ||||
|         if (move_pointer(nodes[i], from.cameras, cameras)) | ||||
|             continue; | ||||
|              | ||||
|         // Не нашли родителя - значит он не часть этой сцены 
 | ||||
|         // и изменений по нему не требуется
 | ||||
|     } | ||||
| }  | ||||
| 
 | ||||
| // Сдвигает родителя узла между двумя списками при условии его принадлежности к оригинальному, возвращает признак замены
 | ||||
| template <class T> | ||||
| bool Scene::move_pointer(Node& for_node, const std::vector<T>& from_nodes, std::vector<T>& this_nodes) | ||||
| { | ||||
|     // Определим отступ в памяти
 | ||||
|     std::ptrdiff_t offset = (T*)for_node.getParent() - from_nodes.data(); | ||||
|     // Если отступ является частью оригинального списка
 | ||||
|     if (offset >= 0 && offset < from_nodes.size()) | ||||
|     { | ||||
|         for_node.setParent(this_nodes.data() + offset); // Замена родителя
 | ||||
|         return true; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| // Перестройка дерева после копирования или присваивания
 | ||||
| void Scene::rebuld_tree(const Scene& from) | ||||
| {     | ||||
|     // Восстановим родителей в пустых узлах для копии
 | ||||
|     rebuild_Nodes_vector(nodes, from); | ||||
|     rebuild_Nodes_vector(models, from); | ||||
|     rebuild_Nodes_vector(cameras, from); | ||||
| } | ||||
							
								
								
									
										235
									
								
								src/main.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										235
									
								
								src/main.cpp
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,235 @@ | ||||
| 
 | ||||
| #include <glad/glad.h> | ||||
| #include <GLFW/glfw3.h> | ||||
| #include <GLM/glm.hpp> | ||||
| 
 | ||||
| #include <iostream> | ||||
| 
 | ||||
| #include "Camera.h" | ||||
| #include "Model.h" | ||||
| 
 | ||||
| #define WINDOW_WIDTH 800 | ||||
| #define WINDOW_HEIGHT 600 | ||||
| #define WINDOW_CAPTION "OPENGL notes on rekovalev.site" | ||||
| 
 | ||||
| // Функция-callback для изменения размеров буфера кадра в случае изменения размеров поверхности окна
 | ||||
| void framebuffer_size_callback(GLFWwindow* window, int width, int height) | ||||
| { | ||||
|     glViewport(0, 0, width, height); | ||||
| } | ||||
| 
 | ||||
| #include <fstream> | ||||
| #include <sstream> | ||||
| 
 | ||||
| // Функция чтения шейдера из файла
 | ||||
| std::string readFile(const char* filename) | ||||
| { | ||||
|     std::string text; | ||||
| 	std::ifstream file(filename, std::ios::in); // Открываем файл на чтение
 | ||||
| 	// Если файл доступен и успешно открыт
 | ||||
|     if (file.is_open())  | ||||
|     {  | ||||
| 		std::stringstream sstr; // Буфер для чтения
 | ||||
| 		sstr << file.rdbuf(); // Считываем файл
 | ||||
| 		text = sstr.str(); // Преобразуем буфер к строке
 | ||||
| 		file.close(); // Закрываем файл
 | ||||
| 	} | ||||
| 
 | ||||
|     return text; | ||||
| } | ||||
| 
 | ||||
| // Функция для загрузки шейдеров
 | ||||
| // Принимает два адреса вершинного и фрагментного шейдеров
 | ||||
| // Возвращает дескриптор шейдерной программы
 | ||||
| GLuint LoadShaders(const char *vertex_file, const char *fragment_file) | ||||
| { | ||||
|     // Создание дескрипторов вершинного и фрагментного шейдеров
 | ||||
|     GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER); | ||||
|     GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); | ||||
| 
 | ||||
|     // Переменные под результат компиляции
 | ||||
|     GLint result = GL_FALSE; | ||||
|     int infoLogLength; | ||||
| 
 | ||||
|     // Считываем текст вершинного шейдера
 | ||||
|     std::string code = readFile(vertex_file); | ||||
|     const char* pointer = code.c_str(); // Преобразование к указателю на const char, так как функция принимает массив си-строк
 | ||||
| 
 | ||||
|     // Компиляция кода вершинного шейдера
 | ||||
|     glShaderSource(vertexShaderID, 1, &pointer, NULL); | ||||
|     glCompileShader(vertexShaderID); | ||||
| 
 | ||||
|     // Проверка результата компиляции
 | ||||
|     glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result); | ||||
|     glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); | ||||
|     if (infoLogLength > 0) | ||||
|     { | ||||
|         char* errorMessage = new char[infoLogLength + 1]; | ||||
|         glGetShaderInfoLog(vertexShaderID, infoLogLength, NULL, errorMessage); | ||||
|         std::cout << errorMessage; | ||||
|         delete errorMessage; | ||||
|     } | ||||
| 
 | ||||
|     // Считываем текст вершинного шейдера
 | ||||
|     code = readFile(fragment_file); | ||||
|     pointer = code.c_str(); // Преобразование к указателю на const char, так как функция принимает массив си-строк
 | ||||
| 
 | ||||
|     // Компиляция кода фрагментного шейдера
 | ||||
|     glShaderSource(fragmentShaderID, 1, &pointer, NULL); | ||||
|     glCompileShader(fragmentShaderID); | ||||
| 
 | ||||
|     // Проверка результата компиляции
 | ||||
|     glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result); | ||||
|     glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); | ||||
|     if (infoLogLength > 0) | ||||
|     { | ||||
|         char* errorMessage = new char[infoLogLength + 1]; | ||||
|         glGetShaderInfoLog(fragmentShaderID, infoLogLength, NULL, errorMessage); | ||||
|         std::cout << errorMessage; | ||||
|         delete errorMessage; | ||||
|     } | ||||
| 
 | ||||
|     // Привязка скомпилированных шейдеров
 | ||||
|     GLuint programID = glCreateProgram(); | ||||
|     glAttachShader(programID, vertexShaderID); | ||||
|     glAttachShader(programID, fragmentShaderID); | ||||
|     glLinkProgram(programID); | ||||
| 
 | ||||
|     // Проверка программы
 | ||||
|     glGetProgramiv(programID, GL_LINK_STATUS, &result); | ||||
|     glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength); | ||||
|     if (infoLogLength > 0) | ||||
|     { | ||||
|         char* errorMessage = new char[infoLogLength + 1]; | ||||
|         glGetProgramInfoLog(programID, infoLogLength, NULL, errorMessage); | ||||
|         std::cout << errorMessage; | ||||
|         delete errorMessage; | ||||
|     } | ||||
| 
 | ||||
|     // Освобождение дескрипторов шейдеров
 | ||||
|     glDeleteShader(vertexShaderID); | ||||
|     glDeleteShader(fragmentShaderID); | ||||
| 
 | ||||
|     return programID; | ||||
| } | ||||
| 
 | ||||
|   | ||||
| bool firstMouse = true; | ||||
| float lastX, lastY; | ||||
| 
 | ||||
| void mouse_callback(GLFWwindow* window, double xpos, double ypos) | ||||
| { | ||||
|     if (firstMouse) | ||||
|     { | ||||
|         lastX = xpos; | ||||
|         lastY = ypos; | ||||
|         firstMouse = false; | ||||
|     } | ||||
|    | ||||
|     glm::vec2 offset(xpos - lastX, lastY - ypos);  | ||||
|     lastX = xpos; | ||||
|     lastY = ypos; | ||||
| 
 | ||||
|     Camera::current().rotate(offset); | ||||
| }   | ||||
| 
 | ||||
| int main(void) | ||||
| { | ||||
|     GLFWwindow* window; // Указатель на окно GLFW3
 | ||||
| 
 | ||||
|     // Инициализация GLFW3
 | ||||
|     if (!glfwInit()) | ||||
|     { | ||||
|         std::cout << "GLFW init error\n"; | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     // Завершение работы с GLFW3 перед выходом
 | ||||
|     atexit(glfwTerminate); | ||||
| 
 | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); // Мажорная версия спецификаций OpenGL
 | ||||
|     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); // Минорная версия спецификаций OpenGL
 | ||||
|     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Контекст OpenGL, который поддерживает только основные функции
 | ||||
|   | ||||
|     // Создание окна GLFW3 с заданными шириной, высотой и заголовком окна
 | ||||
|     window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_CAPTION, NULL, NULL); | ||||
|     if (!window) | ||||
|     { | ||||
|         std::cout << "GLFW create window error\n"; | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     // Установка основного контекста окна
 | ||||
|     glfwMakeContextCurrent(window); | ||||
|     // Установка callback-функции для изменения размеров окна и буфера кадра
 | ||||
|     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); | ||||
|      | ||||
|     glfwSwapInterval(1); // Вертикальная синхронизация
 | ||||
| 
 | ||||
|     // Установка callback-функции для мыши и камеры
 | ||||
|     glfwSetCursorPosCallback(window, mouse_callback); | ||||
| 
 | ||||
|     // Загрузка функций OpenGL с помощью GLAD
 | ||||
|     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) | ||||
|     { | ||||
|         std::cout << "GLAD load GL error\n"; | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     // Компиляция шейдеров
 | ||||
|     GLuint shaderProgram = LoadShaders("shaders/shader.vert", "shaders/shader.frag"); | ||||
|     // Активация шейдера
 | ||||
|     glUseProgram(shaderProgram); | ||||
| 
 | ||||
|     // Вершины прямоугольника
 | ||||
|     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)); | ||||
| 
 | ||||
|     rectangle.e_position().z = 2; | ||||
|     rectangle.e_rotation() = {0.733f, 0.462f, 0.191f, 0.462f}; | ||||
|      | ||||
|     // Установка цвета очистки буфера цвета
 | ||||
|     glClearColor(0.0f, 0.0f, 0.0f, 1.0f); | ||||
| 
 | ||||
|     // Расположение Uniform-переменной
 | ||||
|     GLuint vp_uniform = glGetUniformLocation(shaderProgram, "vp"); | ||||
|     GLuint model_uniform = glGetUniformLocation(shaderProgram, "model"); | ||||
| 
 | ||||
|     // Пока не произойдет событие запроса закрытия окна
 | ||||
|     while(!glfwWindowShouldClose(window)) | ||||
|     { | ||||
|         // Загрузим матрицу проекции*вида
 | ||||
|         glUniformMatrix4fv(vp_uniform, 1, GL_FALSE, &Camera::current().getVP()[0][0]); | ||||
| 
 | ||||
|         // Очистка буфера цвета
 | ||||
|         glClear(GL_COLOR_BUFFER_BIT); | ||||
| 
 | ||||
|         // Тут производится рендер
 | ||||
|         rectangle.render(model_uniform); | ||||
| 
 | ||||
|         // Представление содержимого буфера цепочки показа на окно
 | ||||
|         glfwSwapBuffers(window); | ||||
|         // Обработка системных событий
 | ||||
|         glfwPollEvents(); | ||||
|     } | ||||
|      | ||||
|     // Удаление шейдерной программы
 | ||||
|     glDeleteProgram(shaderProgram); | ||||
| 
 | ||||
|     // Отключение атрибутов
 | ||||
|     glDisableVertexAttribArray(0); | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user