19/src/TRS.cpp

187 lines
8.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "TRS.h"
#include <GLM/gtx/matrix_decompose.hpp>
// Инициализирует дополнительную информацию модели
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;
}
}
Rotate::Rotate()
{
tool = loadOBJtoScene("../resources/models/tools/rotate.obj", "../resources/models/tools/", "../resources/textures/");
// Масштабирование
tool.root.e_scale() = glm::vec3(0.3);
int value = 1;
for (auto it = tool.models.begin(); it != tool.models.end(); ++it)
{
it->id.etc = value;
value *= 2;
}
}
// Взаимодействие с инструментом
void Rotate::process(GLuint64 selectedID, GLuint etc, const glm::vec4& drot)
{
// Если взаимодействие с осями инструмента
if (etc > 0)
// Если есть выбранная модель - рендерим инструмент для неё
if (selectedID)
{
// Указатель на объект
Node* selectedObject = (Node*) selectedID;
glm::quat &selectedRot = selectedObject->e_rotation();
// Матрица родительского поворота
glm::mat3 parentRotation(1);
// Учет родительского поворота для вращения
Node* parent = selectedObject->getParent();
if (parent)
{
// Извлекаем 3x3 подматрицу, отвечающую за вращение и масштаб
parentRotation = glm::mat3(parent->getTransformMatrix());
// Нормализуем столбцы подматрицы, чтобы исключить масштабирование
for (int i = 0; i < 3; i++)
parentRotation[i] = glm::normalize(parentRotation[i]);
}
// Поворот по осям
if (etc & 01)
selectedRot = glm::angleAxis(drot.y * R_SENSITIVITY, parentRotation * glm::vec3(1.0f, 0.0f, 0.0f)) * selectedRot;
if (etc & 02)
selectedRot = glm::angleAxis(drot.x * R_SENSITIVITY, parentRotation * glm::vec3(0.0f, 1.0f, 0.0f)) * selectedRot;
if (etc & 04)
selectedRot = glm::angleAxis(drot.z * R_SENSITIVITY, parentRotation * glm::vec3(0.0f, 0.0f, 1.0f)) * selectedRot;
}
}
Scale::Scale()
{
tool = loadOBJtoScene("../resources/models/tools/scale.obj", "../resources/models/tools/", "../resources/textures/");
// Масштабирование
tool.root.e_scale() = glm::vec3(0.3);
// Инициализация дополнительной информации
init_etc();
}
// Взаимодействие с инструментом
void Scale::process(GLuint64 selectedID, GLuint etc, const glm::vec4& dscale)
{
// Если взаимодействие с осями инструмента
if (etc > 0)
// Если есть выбранная модель - рендерим инструмент для неё
if (selectedID)
{
// Указатель на объект
Node* selectedObject = (Node*) selectedID;
// Для хранения результата
glm::vec3 dVec(0);
// Масштабирование с учетом чувствительности для соответствующих осей
if (etc & 01)
dVec.x = dscale.x * S_SENSITIVITY;
if (etc & 02)
dVec.y = dscale.y * S_SENSITIVITY;
if (etc & 04)
dVec.z = dscale.z * S_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_scale() += dVec;
}
}