187 lines
8.0 KiB
C++
187 lines
8.0 KiB
C++
#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;
|
||
}
|
||
} |