2021-10-02 20:36:07 +03:00
|
|
|
//
|
|
|
|
// Created by Иван Ильин on 15.03.2021.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include "Object.h"
|
2021-10-12 17:12:47 +03:00
|
|
|
#include "Matrix4x4.h"
|
2021-10-02 20:36:07 +03:00
|
|
|
#include "utils/Log.h"
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::translate(const Vec3D &dv) {
|
2021-10-28 16:58:02 +03:00
|
|
|
_position = _position + dv;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
for(auto &[attachedName, attachedObject] : _attachedObjects) {
|
|
|
|
if(!attachedObject.expired()) {
|
|
|
|
attachedObject.lock()->translate(dv);
|
|
|
|
}
|
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::scale(const Vec3D &s) {
|
2021-10-28 16:58:02 +03:00
|
|
|
for(auto &[attachedName, attachedObject] : _attachedObjects) {
|
|
|
|
if(!attachedObject.expired()) {
|
|
|
|
attachedObject.lock()->scale(s);
|
|
|
|
}
|
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::rotate(const Vec3D &r) {
|
2021-10-28 16:58:02 +03:00
|
|
|
_angle = _angle + r;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
Matrix4x4 rotationMatrix = Matrix4x4::RotationZ(r.z())*Matrix4x4::RotationY(r.y())*Matrix4x4::RotationX(r.z());
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
_left = rotationMatrix * _left;
|
|
|
|
_up = rotationMatrix * _up;
|
|
|
|
_lookAt = rotationMatrix * _lookAt;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
for(auto &[attachedName, attachedObject] : _attachedObjects) {
|
|
|
|
if(!attachedObject.expired()) {
|
|
|
|
attachedObject.lock()->rotateRelativePoint(position(), r);
|
|
|
|
}
|
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::rotate(const Vec3D &v, double rv) {
|
2021-10-02 20:36:07 +03:00
|
|
|
Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, rv);
|
2021-10-12 17:12:47 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
_left = rotationMatrix * _left;
|
|
|
|
_up = rotationMatrix * _up;
|
|
|
|
_lookAt = rotationMatrix * _lookAt;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
for(auto &[attachedName, attachedObject] : _attachedObjects) {
|
|
|
|
if(!attachedObject.expired()) {
|
|
|
|
attachedObject.lock()->rotateRelativePoint(position(), v, rv);
|
|
|
|
}
|
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::rotateRelativePoint(const Vec3D &s, const Vec3D &r) {
|
2021-10-28 16:58:02 +03:00
|
|
|
_angle = _angle + r;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
// Translate XYZ by vector r1
|
2021-10-28 16:58:02 +03:00
|
|
|
Vec3D r1(_position - s);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
// In translated coordinate system we rotate body and position
|
|
|
|
Matrix4x4 rotationMatrix = Matrix4x4::Rotation(r);
|
2021-10-12 17:12:47 +03:00
|
|
|
Vec3D r2(rotationMatrix*r1);
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
_left = rotationMatrix * _left;
|
|
|
|
_up = rotationMatrix * _up;
|
|
|
|
_lookAt = rotationMatrix * _lookAt;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
// After rotation we translate XYZ by vector -r2 and recalculate position
|
2021-10-28 16:58:02 +03:00
|
|
|
_position = s + r2;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
for(auto &[attachedName, attachedObject] : _attachedObjects) {
|
|
|
|
if(!attachedObject.expired()) {
|
|
|
|
attachedObject.lock()->rotateRelativePoint(s, r);
|
|
|
|
}
|
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::rotateRelativePoint(const Vec3D &s, const Vec3D &v, double r) {
|
2021-10-02 20:36:07 +03:00
|
|
|
// Translate XYZ by vector r1
|
2021-10-28 16:58:02 +03:00
|
|
|
Vec3D r1(_position - s);
|
2021-10-02 20:36:07 +03:00
|
|
|
// In translated coordinate system we rotate body and position
|
|
|
|
Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, r);
|
2021-10-12 17:12:47 +03:00
|
|
|
Vec3D r2 = rotationMatrix*r1;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
_left = rotationMatrix * _left;
|
|
|
|
_up = rotationMatrix * _up;
|
|
|
|
_lookAt = rotationMatrix * _lookAt;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
|
|
|
// After rotation we translate XYZ by vector -r2 and recalculate position
|
2021-10-28 16:58:02 +03:00
|
|
|
_position = s + r2;
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
for(auto &[attachedName, attachedObject] : _attachedObjects) {
|
|
|
|
if(!attachedObject.expired()) {
|
|
|
|
attachedObject.lock()->rotateRelativePoint(s, v, r);
|
|
|
|
}
|
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Object::rotateLeft(double rl) {
|
2021-10-28 16:58:02 +03:00
|
|
|
_angleLeftUpLookAt = Vec3D{_angleLeftUpLookAt.x() + rl,
|
|
|
|
_angleLeftUpLookAt.y(),
|
|
|
|
_angleLeftUpLookAt.z()};
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
rotate(Vec3D(_left), rl);
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Object::rotateUp(double ru) {
|
2021-10-28 16:58:02 +03:00
|
|
|
_angleLeftUpLookAt = Vec3D{_angleLeftUpLookAt.x(),
|
|
|
|
_angleLeftUpLookAt.y() + ru,
|
|
|
|
_angleLeftUpLookAt.z()};
|
2021-10-02 20:36:07 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
rotate(Vec3D(_up), ru);
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void Object::rotateLookAt(double rlAt) {
|
2021-10-28 16:58:02 +03:00
|
|
|
_angleLeftUpLookAt = Vec3D{_angleLeftUpLookAt.x(),
|
|
|
|
_angleLeftUpLookAt.y(),
|
|
|
|
_angleLeftUpLookAt.z() + rlAt};
|
|
|
|
rotate(Vec3D(_lookAt), rlAt);
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::translateToPoint(const Vec3D &point) {
|
2021-10-28 16:58:02 +03:00
|
|
|
translate(point - _position);
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
void Object::rotateToAngle(const Vec3D &v) {
|
2021-10-28 16:58:02 +03:00
|
|
|
rotate(v - _angle);
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-17 10:21:10 +03:00
|
|
|
std::shared_ptr<Object> Object::attached(const ObjectNameTag& tag) {
|
2021-10-28 16:58:02 +03:00
|
|
|
if(_attachedObjects.count(tag) == 0 || _attachedObjects.find(tag)->second.expired()) {
|
2021-10-16 16:14:51 +03:00
|
|
|
return nullptr;
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
|
|
|
return _attachedObjects.find(tag)->second.lock();
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
bool Object::checkIfAttached(Object *obj) {
|
|
|
|
for(const auto& [nameTag, attachedObject] : _attachedObjects) {
|
|
|
|
if (obj == attachedObject.lock().get() || attachedObject.lock()->checkIfAttached(obj)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Object::attach(std::shared_ptr<Object> object) {
|
|
|
|
if(this != object.get()) {
|
|
|
|
if(!object->checkIfAttached(this)) {
|
|
|
|
_attachedObjects.emplace(object->name(), object);
|
|
|
|
} else {
|
|
|
|
throw std::invalid_argument{"Object::attach: You tried to create infinite recursive call chains"};
|
|
|
|
}
|
|
|
|
} else {
|
2021-10-12 17:12:47 +03:00
|
|
|
throw std::invalid_argument{"Object::attach: You cannot attach object to itself"};
|
2021-10-28 16:58:02 +03:00
|
|
|
}
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
|
|
|
|
2021-10-17 10:21:10 +03:00
|
|
|
void Object::unattach(const ObjectNameTag& tag) {
|
|
|
|
_attachedObjects.erase(tag);
|
2021-10-02 20:36:07 +03:00
|
|
|
}
|
2021-10-16 20:22:55 +03:00
|
|
|
|
|
|
|
Object::~Object() {
|
|
|
|
_attachedObjects.clear();
|
|
|
|
}
|