diff --git a/include/TRS.h b/include/TRS.h new file mode 100644 index 0000000..7c3505f --- /dev/null +++ b/include/TRS.h @@ -0,0 +1,27 @@ +#ifndef TRS_H +#define TRS_H + +#define T_SENSITIVITY 0.001f + +#include "Scene.h" + +// Интерфейс инструмента +class TRS +{ + public: + void render(GLuint64 selectedID, ShaderProgram &shaderProgram, UBO &material_buffer); // Рендер инструмента нужного типа для выбранного объекта + virtual void process(GLuint64 selectedID, GLuint etc, const glm::vec4& dpos) = 0; // Взаимодействие с инструментом + protected: + void init_etc(); // Инициализирует дополнительную информацию модели + Scene tool; // Модель +}; + +// Инструмент трансформации +class Transform : public TRS +{ + public: + Transform(); + virtual void process(GLuint64 selectedID, GLuint etc, const glm::vec4& dpos); // Взаимодействие с инструментом +}; + +#endif // TRS_H \ No newline at end of file diff --git a/shaders/tools.frag b/shaders/tools.frag new file mode 100644 index 0000000..176002c --- /dev/null +++ b/shaders/tools.frag @@ -0,0 +1,38 @@ +#version 420 core + +layout(std140, binding = 1) uniform Material +{ + vec3 ka; + vec3 kd; + vec3 ks; + float p; + bool normalmapped; + bool parallaxmapped; + bool displacementmapped; +}; + +layout (location = 1) out vec3 gNormal; +layout (location = 3) out vec4 gAmbientSpecular; +layout (location = 4) out uvec3 gID; + +in vec3 vertex; // Позиция вершины в пространстве +in vec3 N; // Нормаль трансформированная +in vec2 texCoord; // Текстурные координаты +in vec3 T; // Касательный вектор +in vec3 B; // Бикасательный вектор +in vec3 view; // Вектор от поверхности к камере + +uniform float parallax_heightScale = 0.1; + +uniform uvec3 ID = uvec3(0); + +void main() +{ + gNormal = vec3(0); + // Сохранение фоновой составляющей + gAmbientSpecular.rgb = ka; + // Сохранение идентификатора объекта + gID = ID; + + gl_FragDepth = 0.01 * gl_FragCoord.z; +} \ No newline at end of file diff --git a/src/TRS.cpp b/src/TRS.cpp new file mode 100644 index 0000000..ec8f714 --- /dev/null +++ b/src/TRS.cpp @@ -0,0 +1,81 @@ +#include "TRS.h" + +// Инициализирует дополнительную информацию модели +void TRS::init_etc() +{ + int value = 1; + for (auto it = tool.models.begin(); it != tool.models.end(); ++it) + it->id.etc = value++; +} + +// Рендер инструмента нужного типа для выбранного объекта +void TRS::render(GLuint64 selectedID, ShaderProgram &shaderProgram, UBO &material_buffer) +{ + // Если есть выбранная модель - рендерим инструмент для неё + if (selectedID) + { + // Указатель на объект + Node* selectedObject = (Node*) selectedID; + + // Смещение выбранного объекта в глобальных координатах из его матрицы трансформации (включая родительские) + tool.root.e_position() = glm::vec3(selectedObject->getTransformMatrix()[3]); + + // Замена идентификатора инструмента идентификатором выбранного объекта + tool.set_group_id(selectedID); // без замены доп. информации + + // Рендер инструмента + tool.render(shaderProgram, material_buffer); + } +} + +Transform::Transform() +{ + tool = loadOBJtoScene("../resources/models/tools/transform.obj", "../resources/models/tools/", "../resources/textures/"); + + // Масштабирование + tool.root.e_scale() = glm::vec3(0.3); + + // Инициализация дополнительной информации + init_etc(); +} + +// Взаимодействие с инструментом +void Transform::process(GLuint64 selectedID, GLuint etc, const glm::vec4& dpos) +{ + // Если взаимодействие с осями инструмента + if (etc > 0) + // Если есть выбранная модель - рендерим инструмент для неё + if (selectedID) + { + // Указатель на объект + Node* selectedObject = (Node*) selectedID; + + glm::vec3 dVec(0.0f, 0.0f, 0.0f); + + // Сдвиг с учетом чувствительности для соответствующих осей + if (etc & 01) + dVec.x = dpos.x * T_SENSITIVITY; + if (etc & 02) + dVec.y = dpos.y * T_SENSITIVITY; + if (etc & 04) + dVec.z = dpos.z * T_SENSITIVITY; + + // Если есть родитель - требуется учесть его поворот + Node* parent = selectedObject->getParent(); + if (parent) + { + // Извлекаем 3x3 подматрицу, отвечающую за вращение и масштаб + glm::mat3 rotationMatrix = glm::mat3(parent->getTransformMatrix()); + + // Нормализуем столбцы подматрицы, чтобы исключить масштабирование + for (int i = 0; i < 3; i++) + rotationMatrix[i] = glm::normalize(rotationMatrix[i]); + + // Применим поворот родителя к вектору сдвига + dVec = glm::inverse(rotationMatrix) * dVec; + } + + // Добавим сдвиг от инструмента к позиции выбранного объекта + selectedObject->e_position() += dVec; + } +} diff --git a/src/main.cpp b/src/main.cpp index dbce366..0de3f7c 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include "Scene.h" #include "Shader.h" #include "Lights.h" +#include "TRS.h" #define WINDOW_CAPTION "OPENGL notes on rekovalev.site" @@ -154,6 +155,7 @@ int main(void) scene.root.e_position().z = 1; scene.models.begin()->material.kd = {0.5,0.5,0.5}; scene.models.begin()->material.ka = {0.05,0.05,0.05}; + scene.set_group_id((GLuint64) &scene); // Установка цвета очистки буфера цвета glClearColor(0.0f, 0.0f, 0.0f, 1.0f); @@ -433,6 +435,16 @@ int main(void) ID selected; // Выбранная модель + // Шейдер для инструментов + ShaderProgram toolsShader; + // Загрузим шейдеры + toolsShader.load(GL_VERTEX_SHADER, "shaders/gshader.vert"); + toolsShader.load(GL_FRAGMENT_SHADER, "shaders/tools.frag"); + toolsShader.link(); + + // Инструменты + Transform transform; + // Пока не произойдет событие запроса закрытия окна while(!glfwWindowShouldClose(window)) { @@ -454,6 +466,11 @@ int main(void) scene.render(gShader, material_data); rectangle.render(gShader, material_data); + // Используем шейдер для инструментов + toolsShader.use(); + // Рендерим инструменты для выбранного объекта + transform.render(selected.value, toolsShader, material_data); + // Выбор объекта if (mouse.left == 0100000) { @@ -578,6 +595,11 @@ int main(void) && mouse.x != mouse.prev_x && mouse.y != mouse.prev_y) Camera::current().rotate(glm::vec2(mouse.x - mouse.prev_x, mouse.prev_y - mouse.y)); + + // Взаимодействие с инструментом при зажатой левой кнопке + if (mouse.left > 0100000) + if (selected.etc) + transform.process(selected.value, selected.etc, glm::transpose(Camera::current().getVP()) * glm::vec4(mouse.x - mouse.prev_x, mouse.prev_y - mouse.y, 0, 1)); } return 0;