Dawn/src/dawn/display/Transform.cpp
2022-10-21 22:01:37 -07:00

156 lines
3.9 KiB
C++

// Copyright (c) 2022 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "Transform.hpp"
#include "scene/SceneItem.hpp"
using namespace Dawn;
Transform::Transform(SceneItem &item) :
item(item),
transformLocal(1.0f),
transformWorld(1.0f)
{
this->updateLocalValuesFromLocalTransform();
}
void Transform::updateLocalValuesFromLocalTransform() {
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(
this->transformLocal,
this->localScale,
this->localRotation,
this->localPosition,
skew, perspective
);
}
void Transform::updateLocalTransformFromLocalValues() {
glm::mat4 translate = glm::translate(glm::mat4(1.0), this->localPosition);
glm::mat4 rotate = glm::mat4_cast(this->localRotation);
glm::mat4 scale = glm::scale(glm::mat4(1.0), this->localScale);
this->transformLocal = translate * rotate * scale;
this->updateWorldTransformFromLocalTransform();
}
void Transform::updateWorldTransformFromLocalTransform() {
glm::mat4 newWorld(1.0f);
auto parent = this->getParent();
if(parent != nullptr) newWorld = parent->getWorldTransform();
this->transformWorld = newWorld * transformLocal;
}
void Transform::updateLocalTransformFromWorldTransform() {
glm::mat4 parentMat(1.0f);
auto parent = this->getParent();
if(parent != nullptr) parentMat = parent->getWorldTransform();
this->transformLocal = parentMat / this->transformWorld;
this->updateLocalValuesFromLocalTransform();
}
void Transform::updateChildrenTransforms() {
auto it = this->children.begin();
while(it != this->children.end()) {
(*it)->updateWorldTransformFromLocalTransform();
++it;
}
}
void Transform::lookAt(glm::vec3 pos, glm::vec3 look) {
this->lookAt(pos, look, glm::vec3(0, 1, 0));
}
void Transform::lookAt(glm::vec3 pos, glm::vec3 look, glm::vec3 up) {
this->setWorldTransform(glm::lookAt(pos, look, up));
}
glm::vec3 Transform::getLocalPosition() {
return this->localPosition;
}
void Transform::setLocalPosition(glm::vec3 position) {
this->localPosition = position;
this->updateLocalTransformFromLocalValues();
this->updateChildrenTransforms();
}
glm::vec3 Transform::getLocalScale() {
return this->scale;
}
void Transform::setLocalScale(glm::vec3 scale) {
this->localScale = scale;
this->updateLocalTransformFromLocalValues();
this->updateChildrenTransforms();
}
glm::quat Transform::getLocalRotation() {
return this->localRotation;
}
void Transform::setLocalRotation(glm::quat rotation) {
this->localRotation = rotation;
this->updateLocalTransformFromLocalValues();
this->updateChildrenTransforms();
}
glm::mat4 Transform::getLocalTransform() {
return this->transformLocal;
}
void Transform::setLocalTransform(glm::mat4 transform) {
this->transformLocal = transform;
this->updateLocalValuesFromLocalTransform();
this->updateChildrenTransforms();
}
glm::mat4 Transform::getWorldTransform() {
return this->transformWorld;
}
void Transform::setWorldTransform(glm::mat4 transform) {
this->transformWorld = transform;
this->updateLocalTransformFromWorldTransform();
this->updateChildrenTransforms();
}
void Transform::setParent(Transform *parent) {
if(parent == this) throw "Cannot self reference";
auto currentParent = this->getParent();
if(currentParent == parent) return;
if(currentParent != nullptr) {
auto it = currentParent->children.begin();
while(it != currentParent->children.end()) {
if(*it == this) {
currentParent->children.erase(it);
break;
}
++it;
}
}
this->parent = parent;
if(parent != nullptr) parent->children.push_back(this);
}
Transform * Transform::getParent() {
return this->parent;
}
Transform::~Transform() {
this->setParent(nullptr);
auto it = this->parent->children.begin();
while(it != this->parent->children.end()) {
(*it)->setParent(nullptr);
++it;
}
}