vectozavr-shooter/engine/Object.cpp

189 lines
5.3 KiB
C++
Raw Normal View History

2021-10-02 20:36:07 +03:00
//
// Created by Иван Ильин on 15.03.2021.
//
#include "Object.h"
#include "Matrix4x4.h"
2021-10-02 20:36:07 +03:00
2021-10-31 11:39:08 +03:00
void Object::transform(const Matrix4x4 &t) {
_transformMatrix = t * _transformMatrix;
2021-10-02 20:36:07 +03:00
2021-10-31 11:39:08 +03:00
for (auto &[attachedName, attachedObject] : _attachedObjects) {
if (!attachedObject.expired()) {
attachedObject.lock()->transformRelativePoint(position(), t);
2021-10-28 16:58:02 +03:00
}
}
2021-10-02 20:36:07 +03:00
}
2021-10-31 11:39:08 +03:00
void Object::transformRelativePoint(const Vec3D &point, const Matrix4x4 &transform) {
2021-10-02 20:36:07 +03:00
// translate object in new coordinate system (connected with point)
_transformMatrix = Matrix4x4::Translation(position() - point) * _transformMatrix;
// transform object in the new coordinate system
2021-10-31 11:39:08 +03:00
_transformMatrix = transform * _transformMatrix;
// translate object back in self connected coordinate system
_position = _transformMatrix.w() + point;
_transformMatrix = Matrix4x4::Translation(-_transformMatrix.w()) * _transformMatrix;
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
for (auto &[attachedName, attachedObject] : _attachedObjects) {
if (!attachedObject.expired()) {
attachedObject.lock()->transformRelativePoint(point, transform);
2021-10-28 16:58:02 +03:00
}
}
2021-10-02 20:36:07 +03:00
}
void Object::translate(const Vec3D &dv) {
2021-10-02 20:36:07 +03:00
_position = _position + dv;
2021-10-02 20:36:07 +03:00
2021-10-31 11:39:08 +03:00
for (auto &[attachedName, attachedObject] : _attachedObjects) {
if (!attachedObject.expired()) {
attachedObject.lock()->translate(dv);
2021-10-28 16:58:02 +03:00
}
}
2021-10-02 20:36:07 +03:00
}
void Object::scale(const Vec3D &s) {
transform(Matrix4x4::Scale(s));
2021-10-02 20:36:07 +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
2021-10-31 11:39:08 +03:00
// TODO: when you rotate body _angle is changed only for this body but all attached objects have incorrect _angle
Matrix4x4 rotationMatrix = Matrix4x4::RotationZ(r.z()) * Matrix4x4::RotationY(r.y()) * Matrix4x4::RotationX(r.z());
transform(rotationMatrix);
}
2021-10-02 20:36:07 +03:00
void Object::rotate(const Vec3D &v, double rv) {
transform(Matrix4x4::Rotation(v, rv));
}
2021-10-02 20:36:07 +03:00
void Object::rotateRelativePoint(const Vec3D &s, const Vec3D &r) {
transformRelativePoint(s, Matrix4x4::Rotation(r));
2021-10-02 20:36:07 +03:00
}
void Object::rotateRelativePoint(const Vec3D &s, const Vec3D &v, double r) {
transformRelativePoint(s, Matrix4x4::Rotation(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-29 23:44:37 +03:00
rotate(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-29 23:44:37 +03:00
rotate(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};
2021-10-29 23:44:37 +03:00
rotate(lookAt(), rlAt);
2021-10-02 20:36:07 +03:00
}
void Object::translateToPoint(const Vec3D &point) {
2021-10-29 23:44:37 +03:00
translate(point - position());
2021-10-02 20:36:07 +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-31 11:39:08 +03:00
std::shared_ptr<Object> Object::attached(const ObjectNameTag &tag) {
if (_attachedObjects.count(tag) == 0 || _attachedObjects.find(tag)->second.expired()) {
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) {
2021-10-31 11:39:08 +03:00
for (const auto&[nameTag, attachedObject] : _attachedObjects) {
2021-10-28 16:58:02 +03:00
if (obj == attachedObject.lock().get() || attachedObject.lock()->checkIfAttached(obj)) {
return true;
}
}
return false;
}
void Object::attach(std::shared_ptr<Object> object) {
2021-10-31 11:39:08 +03:00
if (this != object.get()) {
if (!object->checkIfAttached(this)) {
2021-10-28 16:58:02 +03:00
_attachedObjects.emplace(object->name(), object);
} else {
throw std::invalid_argument{"Object::attach: You tried to create infinite recursive call chains"};
}
} else {
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-31 11:39:08 +03:00
void Object::unattach(const ObjectNameTag &tag) {
2021-10-17 10:21:10 +03:00
_attachedObjects.erase(tag);
2021-10-02 20:36:07 +03:00
}
2021-10-16 20:22:55 +03:00
2021-10-29 23:44:37 +03:00
// OpenGL function
2021-10-31 11:39:08 +03:00
GLfloat *Object::glView() const {
auto *v = (GLfloat *) malloc(4 * 4 * sizeof(GLfloat));
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
v[0] = -(GLfloat) left().x();
v[4] = -(GLfloat) left().y();
v[8] = -(GLfloat) left().z();
v[12] = (GLfloat) position().dot(left());
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
v[1] = (GLfloat) up().x();
v[5] = (GLfloat) up().y();
v[9] = (GLfloat) up().z();
v[13] = -(GLfloat) position().dot(up());
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
v[2] = -(GLfloat) lookAt().x();
v[6] = -(GLfloat) lookAt().y();
v[10] = -(GLfloat) lookAt().z();
v[14] = (GLfloat) position().dot(lookAt());
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
v[3] = (GLfloat) 0.0f;
v[7] = (GLfloat) 0.0f;
v[11] = (GLfloat) 0.0f;
v[15] = (GLfloat) 1.0f;
2021-10-29 23:44:37 +03:00
return v;
}
2021-10-31 11:39:08 +03:00
GLfloat *Object::glModel() const {
auto *m = (GLfloat *) malloc(4 * 4 * sizeof(GLfloat));
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
m[0] = (GLfloat) left().x();
m[4] = (GLfloat) up().x();
m[8] = (GLfloat) lookAt().x();
m[12] = (GLfloat) position().x();
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
m[1] = (GLfloat) left().y();
m[5] = (GLfloat) up().y();
m[9] = (GLfloat) lookAt().y();
m[13] = (GLfloat) position().y();
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
m[2] = (GLfloat) left().z();
m[6] = (GLfloat) up().z();
m[10] = (GLfloat) lookAt().z();
m[14] = (GLfloat) position().z();
2021-10-29 23:44:37 +03:00
2021-10-31 11:39:08 +03:00
m[3] = (GLfloat) 0.0f;
m[7] = (GLfloat) 0.0f;
m[11] = (GLfloat) 0.0f;
m[15] = (GLfloat) 1.0f;
2021-10-29 23:44:37 +03:00
return m;
}
2021-10-16 20:22:55 +03:00
Object::~Object() {
_attachedObjects.clear();
}