Basic transform stuff
This commit is contained in:
156
src/dawn/display/Transform.cpp
Normal file
156
src/dawn/display/Transform.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
// 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;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user