From d3684f8aa6682592846c0071bb408fb8a6ac150b Mon Sep 17 00:00:00 2001 From: Vectozavr <60608292+vectozavr@users.noreply.github.com> Date: Tue, 12 Oct 2021 21:12:47 +0700 Subject: [PATCH] Point4D & Triangle now are completely immutable. - Deleted operator= for Point4D and Triangle - Add Vec3D & Vec2D to substitute Point4D in cases where we dont need 4 dimensions. Vec3D & Vec2D are immutable. - Small refactoring of EPA & GJK in RigidBody.cpp --- Bonus.cpp | 2 +- Bonus.h | 2 +- CMakeLists.txt | 10 +- Client.cpp | 25 +-- Client.h | 10 +- Player.cpp | 6 +- Player.h | 17 +- PlayerController.cpp | 33 ++- Server.cpp | 10 +- Shooter.cpp | 40 ++-- Shooter.h | 4 +- ShooterConsts.h | 13 ++ engine/Camera.cpp | 59 +++--- engine/Camera.h | 6 +- engine/Consts.h | 6 + engine/Engine.cpp | 2 +- engine/{utils => }/Matrix4x4.cpp | 64 +++--- engine/{utils => }/Matrix4x4.h | 12 +- engine/Mesh.cpp | 94 ++++----- engine/Mesh.h | 24 +-- engine/Mouse.cpp | 8 +- engine/Mouse.h | 6 +- engine/Object.cpp | 95 +++++---- engine/Object.h | 42 ++-- engine/Plane.cpp | 84 ++++---- engine/Plane.h | 20 +- engine/{utils => }/Point4D.cpp | 42 ++-- engine/{utils => }/Point4D.h | 9 +- engine/Screen.cpp | 4 +- engine/Screen.h | 4 +- engine/Triangle.cpp | 58 +++--- engine/Triangle.h | 14 +- engine/Vec2D.cpp | 71 +++++++ engine/Vec2D.h | 48 +++++ engine/Vec3D.cpp | 86 ++++++++ engine/Vec3D.h | 51 +++++ engine/World.cpp | 19 +- engine/World.h | 8 +- engine/animation/ARotate.h | 6 +- engine/animation/AScale.h | 6 +- engine/animation/ATranslate.h | 6 +- engine/animation/ATranslateToPoint.h | 12 +- engine/animation/Animation.cpp | 4 +- engine/animation/Animation.h | 9 +- engine/animation/Interpolation.h | 14 +- engine/gui/Window.cpp | 6 +- engine/gui/Window.h | 2 +- engine/network/ClientUDP.cpp | 2 +- engine/network/ReliableMsg.cpp | 2 +- engine/network/ServerUDP.cpp | 2 +- engine/physics/RigidBody.cpp | 297 ++++++++++++++------------- engine/physics/RigidBody.h | 58 +++--- engine/physics/Simplex.h | 41 ++-- engine/physics/Solver.cpp | 11 +- weapon/Ak47.cpp | 2 +- weapon/Gold_Ak47.h | 2 +- weapon/Gun.cpp | 2 +- weapon/Rifle.cpp | 2 +- weapon/Shotgun.cpp | 10 +- weapon/Shotgun.h | 2 +- weapon/Weapon.cpp | 12 +- weapon/Weapon.h | 10 +- 62 files changed, 958 insertions(+), 670 deletions(-) create mode 100644 ShooterConsts.h rename engine/{utils => }/Matrix4x4.cpp (69%) rename engine/{utils => }/Matrix4x4.h (71%) rename engine/{utils => }/Point4D.cpp (59%) rename engine/{utils => }/Point4D.h (80%) create mode 100644 engine/Vec2D.cpp create mode 100644 engine/Vec2D.h create mode 100644 engine/Vec3D.cpp create mode 100644 engine/Vec3D.h diff --git a/Bonus.cpp b/Bonus.cpp index b620342..83fff8a 100644 --- a/Bonus.cpp +++ b/Bonus.cpp @@ -4,7 +4,7 @@ #include "Bonus.h" -Bonus::Bonus(const std::string &bonusName, const std::string &filename, const std::string &materials, const Point4D &scale) { +Bonus::Bonus(const std::string &bonusName, const std::string &filename, const std::string &materials, const Vec3D &scale) { _name = bonusName; loadObj(filename, materials, scale); setCollider(false); diff --git a/Bonus.h b/Bonus.h index 613ab5c..4c81549 100644 --- a/Bonus.h +++ b/Bonus.h @@ -12,7 +12,7 @@ class Bonus : public RigidBody { protected: std::string _name; public: - explicit Bonus(const std::string &bonusName, const std::string& filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1}); + explicit Bonus(const std::string &bonusName, const std::string& filename, const std::string &materials = "", const Vec3D& scale = Vec3D{1, 1, 1}); [[nodiscard]] std::string name() const { return _name; } }; diff --git a/CMakeLists.txt b/CMakeLists.txt index 82b9c26..794afd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,10 +34,10 @@ add_executable(shooter # 3d engine: engine/utils/Time.h engine/utils/Time.cpp - engine/utils/Point4D.h - engine/utils/Point4D.cpp - engine/utils/Matrix4x4.h - engine/utils/Matrix4x4.cpp + engine/Point4D.h + engine/Point4D.cpp + engine/Matrix4x4.h + engine/Matrix4x4.cpp engine/Triangle.h engine/Triangle.cpp engine/Mesh.h @@ -94,7 +94,7 @@ add_executable(shooter engine/network/UDPSocket.h engine/network/config.h engine/animation/AFunction.h - engine/Consts.h) + engine/Consts.h engine/Vec3D.cpp engine/Vec3D.h engine/Vec2D.cpp engine/Vec2D.h ShooterConsts.h) if(APPLE OR UNIX) include_directories(/usr/local/include) diff --git a/Client.cpp b/Client.cpp index 1a7c880..e5fa3f7 100644 --- a/Client.cpp +++ b/Client.cpp @@ -28,7 +28,7 @@ void Client::processInit(sf::Packet& packet) { if(targetId != _socket.ownId()) { spawnPlayer(targetId); - _players[targetId]->translateToPoint(Point4D{ buf[0], buf[1], buf[2]}); + _players[targetId]->translateToPoint(Vec3D{ buf[0], buf[1], buf[2]}); _players[targetId]->setHealth(buf[3]); } } @@ -41,11 +41,11 @@ void Client::processUpdate(sf::Packet& packet) { while (packet >> targetId >> buf[0] >> buf[1] >> buf[2] >> buf[3] >> buf[4] >> buf[5]) { if (_players.count(targetId)) { std::string name = "Player_" + std::to_string(targetId); - _players[targetId]->translateToPoint(Point4D{buf[0], buf[1], buf[2]}); + _players[targetId]->translateToPoint(Vec3D{buf[0], buf[1], buf[2]}); _players[targetId]->setHealth(buf[3]); - _players[targetId]->rotateToAngle(Point4D{0, buf[4], 0}); + _players[targetId]->rotateToAngle(Vec3D{0, buf[4], 0}); - _players[targetId]->attached("head")->rotate(Matrix4x4::RotationY(buf[4]) * Point4D{1, 0, 0}, buf[5] - _players[targetId]->headAngle()); + _players[targetId]->attached("head")->rotate(Matrix4x4::RotationY(buf[4]) * Vec3D{1, 0, 0}, buf[5] - _players[targetId]->headAngle()); _players[targetId]->setHeadAngle(buf[5]); } else if (targetId == _socket.ownId()) { @@ -74,7 +74,6 @@ void Client::processCustomPacket(MsgType type, sf::Packet& packet) { sf::Uint16 buffId[2]; double dbuff[10]; std::string tmp, tmp2; - Point4D p1, p2; switch (type) { case MsgType::Kill: @@ -82,7 +81,7 @@ void Client::processCustomPacket(MsgType type, sf::Packet& packet) { if(buffId[0] == _socket.ownId()) { _player->addDeath(); // respawn - _player->translateToPoint(Point4D{50.0*(-1 + 2.0*(double)rand()/RAND_MAX),30.0*(double)rand()/RAND_MAX,50.0*(-1 + 2.0*(double)rand()/RAND_MAX)}); + _player->translateToPoint(Vec3D{50.0*(-1 + 2.0*(double)rand()/RAND_MAX),30.0*(double)rand()/RAND_MAX,50.0*(-1 + 2.0*(double)rand()/RAND_MAX)}); _player->playDeath(); _player->initWeapons(); _player->setFullAbility(); @@ -99,23 +98,21 @@ void Client::processCustomPacket(MsgType type, sf::Packet& packet) { case MsgType::FireTrace: packet >> dbuff[0] >> dbuff[1] >> dbuff[2] >> dbuff[3] >> dbuff[4] >> dbuff[5]; - p1 = Point4D(dbuff[0], dbuff[1], dbuff[2]); - p2 = Point4D(dbuff[3], dbuff[4], dbuff[5]); if(_addFireTraceCallBack != nullptr) - _addFireTraceCallBack(p1, p2); + _addFireTraceCallBack(Vec3D(dbuff[0], dbuff[1], dbuff[2]), Vec3D(dbuff[3], dbuff[4], dbuff[5])); break; case MsgType::InitBonuses: while (packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]) { if(_addBonusCallBack != nullptr) - _addBonusCallBack(tmp, Point4D(dbuff[0], dbuff[1], dbuff[2])); + _addBonusCallBack(tmp, Vec3D(dbuff[0], dbuff[1], dbuff[2])); } break; case MsgType::AddBonus: packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]; if(_addBonusCallBack != nullptr) - _addBonusCallBack(tmp, Point4D(dbuff[0], dbuff[1], dbuff[2])); + _addBonusCallBack(tmp, Vec3D(dbuff[0], dbuff[1], dbuff[2])); break; case MsgType::RemoveBonus: @@ -141,7 +138,7 @@ void Client::damagePlayer(sf::Uint16 targetId, double damage) { Log::log("Client: damagePlayer " + std::to_string(targetId) + " ( -" + std::to_string(damage) + "hp )"); } -void Client::addTrace(const Point4D& from, const Point4D& to) { +void Client::addTrace(const Vec3D& from, const Vec3D& to) { sf::Packet packet; packet << MsgType::FireTrace << from.x() << from.y() << from.z() << to.x() << to.y() << to.z(); @@ -170,11 +167,11 @@ void Client::setRemovePlayerCallBack(std::function remove) { _removePlayerCallBack = std::move(remove); } -void Client::setAddFireTraceCallBack(std::function addTrace) { +void Client::setAddFireTraceCallBack(std::function addTrace) { _addFireTraceCallBack = std::move(addTrace); } -void Client::setAddBonusCallBack(std::function addBonus) { +void Client::setAddBonusCallBack(std::function addBonus) { _addBonusCallBack = std::move(addBonus); } diff --git a/Client.h b/Client.h index 5ad48b0..77de858 100644 --- a/Client.h +++ b/Client.h @@ -17,8 +17,8 @@ private: std::function _spawnPlayerCallBack; std::function _removePlayerCallBack; - std::function _addFireTraceCallBack; - std::function _addBonusCallBack; + std::function _addFireTraceCallBack; + std::function _addBonusCallBack; std::function _removeBonusCallBack; public: explicit Client(std::shared_ptr player) : _player(player){}; @@ -27,8 +27,8 @@ public: void setSpawnPlayerCallBack(std::function spawn); void setRemovePlayerCallBack(std::function remove); - void setAddFireTraceCallBack(std::function addTrace); - void setAddBonusCallBack(std::function addBonus); + void setAddFireTraceCallBack(std::function addTrace); + void setAddBonusCallBack(std::function addBonus); void setRemoveBonusCallBack(std::function removeBonus); void processInit(sf::Packet& packet) override; @@ -44,7 +44,7 @@ public: void takeBonus(const std::string& bonusName); - void addTrace(const Point4D& from, const Point4D& to); + void addTrace(const Vec3D& from, const Vec3D& to); void addPlayer(sf::Uint16 id, std::shared_ptr player); }; diff --git a/Player.cpp b/Player.cpp index d4650e8..9e81c58 100644 --- a/Player.cpp +++ b/Player.cpp @@ -7,7 +7,7 @@ #include "engine/ResourceManager.h" #include "engine/utils/Log.h" -void Player::rotateWeaponsRelativePoint(const Point4D& point4D, const Point4D& v, double val) { +void Player::rotateWeaponsRelativePoint(const Vec3D& point4D, const Vec3D& v, double val) { for(auto& weapon : _weapons) weapon->rotateRelativePoint(point4D, v, val); } @@ -63,8 +63,8 @@ void Player::addWeapon(std::shared_ptr weapon) { attach(weapon, weapon->name()); _weapons.back()->translate(position()); - _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, Point4D{0, 1, 0}, _angle.y()); - _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, left(), headAngle()); + _weapons.back()->rotateRelativePoint(position() + Vec3D{0, 1.8, 0}, Vec3D{0, 1, 0}, _angle->y()); + _weapons.back()->rotateRelativePoint(position() + Vec3D{0, 1.8, 0}, left(), headAngle()); _weapons.back()->setAddTraceCallBack(_addTraceCallBack); } diff --git a/Player.h b/Player.h index 02c6b0f..53c9c14 100644 --- a/Player.h +++ b/Player.h @@ -42,17 +42,17 @@ private: size_t _selectedWeapon = 0; std::function _damagePlayerCallBack; - std::function _addTraceCallBack; + std::function _addTraceCallBack; std::function _takeBonusCallBack; std::function)> _addWeaponCallBack; std::function)> _removeWeaponCallBack; - std::function(const Point4D&, const Point4D&)> _rayCastFunction; + std::function(const Vec3D&, const Vec3D&)> _rayCastFunction; public: Player() { - loadObj("obj/cube.obj", "", Point4D{0.5, 1.9, 0.5}); - setAcceleration(Point4D{0, -_g, 0}); + loadObj("obj/cube.obj", "", Vec3D{0.5, 1.9, 0.5}); + setAcceleration(Vec3D{0, -_g, 0}); setCollision(true); setVisible(false); setColor({240, 168, 168}); @@ -68,6 +68,9 @@ public: void setHealth(double h) { _health = h; } + void setAbility(double a) { + _ability = a; + } [[nodiscard]] double health() const { return _health; } [[nodiscard]] double ability() const { return _ability; } @@ -93,7 +96,7 @@ public: void fire(); void reload(); - void rotateWeaponsRelativePoint(const Point4D& point4D, const Point4D& v, double val); + void rotateWeaponsRelativePoint(const Vec3D& point, const Vec3D& v, double val); [[nodiscard]] int kills() const {return _kills;} [[nodiscard]] int deaths() const {return _deaths;} @@ -107,7 +110,7 @@ public: void setDamagePlayerCallBack(std::function hit) { _damagePlayerCallBack = std::move(hit); } - void setAddTraceCallBack(std::function add) { + void setAddTraceCallBack(std::function add) { _addTraceCallBack = std::move(add); } void setTakeBonusCallBack(std::function take) { @@ -119,7 +122,7 @@ public: void setRemoveWeaponCallBack(std::function)> removeWeapon) { _removeWeaponCallBack = std::move(removeWeapon); } - void setRayCastFunction(std::function(const Point4D&, const Point4D&)> rayCastFunction) { + void setRayCastFunction(std::function(const Vec3D&, const Vec3D&)> rayCastFunction) { _rayCastFunction = std::move(rayCastFunction); } diff --git a/PlayerController.cpp b/PlayerController.cpp index 38c1506..b5408a8 100644 --- a/PlayerController.cpp +++ b/PlayerController.cpp @@ -51,21 +51,21 @@ void PlayerController::update() { Timeline::animate("camera_hor_oscil", new AWait(0)); Timeline::animate("camera_hor_oscil", new ATranslate(camera, camera->left() / 6, 0.3, Animation::LoopOut::None, Animation::InterpolationType::cos)); - Timeline::animate("camera_vert_oscil", new ATranslate(camera, -Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); + Timeline::animate("camera_vert_oscil", new ATranslate(camera, -Vec3D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); Timeline::animate("camera_vert_oscil", new AWait(0)); - Timeline::animate("camera_vert_oscil", new ATranslate(camera, Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); + Timeline::animate("camera_vert_oscil", new ATranslate(camera, Vec3D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); Timeline::animate("camera_vert_oscil", new AWait(0)); - Timeline::animate("camera_vert_oscil", new ATranslate(camera, -Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); + Timeline::animate("camera_vert_oscil", new ATranslate(camera, -Vec3D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); Timeline::animate("camera_vert_oscil", new AWait(0)); - Timeline::animate("camera_vert_oscil", new ATranslate(camera, Point4D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); + Timeline::animate("camera_vert_oscil", new ATranslate(camera, Vec3D{0, 1, 0} / 12, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); - Timeline::animate("camera_init", new ATranslateToPoint( camera, _player->position() + Point4D{0, 1.8, 0}, 0.3, Animation::LoopOut::None, Animation::InterpolationType::cos)); + Timeline::animate("camera_init", new ATranslateToPoint( camera, _player->position() + Vec3D{0, 1.8, 0}, 0.3, Animation::LoopOut::None, Animation::InterpolationType::cos)); } } else if(inRunning_old && !_inRunning) { Timeline::deleteAnimationList("camera_hor_oscil"); Timeline::deleteAnimationList("camera_vert_oscil"); Timeline::deleteAnimationList("camera_init"); - Timeline::animate("camera_init", new ATranslateToPoint( camera, _player->position() + Point4D{0, 1.8, 0}, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); + Timeline::animate("camera_init", new ATranslateToPoint( camera, _player->position() + Vec3D{0, 1.8, 0}, 0.15, Animation::LoopOut::None, Animation::InterpolationType::cos)); } // Left and right @@ -73,26 +73,26 @@ void PlayerController::update() { if (Keyboard::isKeyPressed(sf::Keyboard::A)) { _player->translate(_player->left() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) - _player->setVelocity(Point4D{0,0,0}); + _player->setVelocity(Vec3D{0,0,0}); } if (Keyboard::isKeyPressed(sf::Keyboard::D)) { _player->translate(-_player->left() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) - _player->setVelocity(Point4D{0,0,0}); + _player->setVelocity(Vec3D{0,0,0}); } // Forward and backward if (Keyboard::isKeyPressed(sf::Keyboard::W)) { _player->translate(_player->lookAt() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) - _player->setVelocity(Point4D{0,0,0}); + _player->setVelocity(Vec3D{0,0,0}); } if (Keyboard::isKeyPressed(sf::Keyboard::S)) { _player->translate(-_player->lookAt() * Time::deltaTime() * _walkSpeed * coeff); if(_player->inCollision()) - _player->setVelocity(Point4D{0,0,0}); + _player->setVelocity(Vec3D{0,0,0}); } if (_player->ability() > 0 && !_isInSlowMo && Keyboard::isKeyPressed(sf::Keyboard::LShift)) { @@ -111,24 +111,23 @@ void PlayerController::update() { } if (Keyboard::isKeyPressed(sf::Keyboard::Space) && _player->inCollision()) { - // if we just want to jump, we have to add particular speed if (!_isSliding) - _player->addVelocity(Point4D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * _jumpHeight) * coeff, 0 }); + _player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * _jumpHeight) * coeff, 0 }); // if we want to slide, we have to add speed * 60/fps to make it independent on frame rate else - _player->addVelocity(Point4D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * _jumpHeight) * coeff * 60.0 / Time::fps(), 0 }); + _player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * _jumpHeight) * coeff * 60.0 / Time::fps(), 0 }); - _player->translate(Point4D{ 0, Time::deltaTime() * _walkSpeed * 2 * coeff * 60.0 / Time::fps(), 0 }); + _player->translate(Vec3D{ 0, Time::deltaTime() * _walkSpeed * 2 * coeff * 60.0 / Time::fps(), 0 }); _isSliding = true; } else { _isSliding = false; } // Mouse movement - Point4D displacement = _mouse->getMouseDisplacement(); + Vec2D displacement = _mouse->getMouseDisplacement(); - _player->rotate(Point4D{0, -displacement.x() / 1000.0, 0}); + _player->rotate(Vec3D{0, -displacement.x() / 1000.0, 0}); _player->setVelocity(Matrix4x4::RotationY(-displacement.x() / 1000.0) * _player->velocity()); double rotationLeft = displacement.y() / 1000.0; @@ -140,7 +139,7 @@ void PlayerController::update() { rotationLeft = -Consts::PI / 2 - _player->headAngle(); _player->setHeadAngle(_player->headAngle() + rotationLeft); - _player->rotateWeaponsRelativePoint(_player->position() + Point4D{0, 1.8, 0}, _player->left(), rotationLeft); + _player->rotateWeaponsRelativePoint(_player->position() + Vec3D{0, 1.8, 0}, _player->left(), rotationLeft); if (_keyboard->isKeyTapped(sf::Keyboard::Right) || _keyboard->isKeyTapped(sf::Keyboard::E)) { _player->nextWeapon(); diff --git a/Server.cpp b/Server.cpp index c961c32..b8fbb8a 100644 --- a/Server.cpp +++ b/Server.cpp @@ -9,14 +9,12 @@ void Server::broadcast() { sf::Packet updatePacket; updatePacket << MsgType::Update; - for (auto& player : _players) - { + for (auto& player : _players) { //player.second->setHealth(player.second->health() + (Time::time() - _lastBroadcast)/100); updatePacket << player.first << player.second->position().x() << player.second->position().y() << player.second->position().z() << player.second->health() << player.second->angle().y() << player.second->headAngle(); } - for (auto& player : _players) - { + for (auto& player : _players) { _socket.send(updatePacket, player.first); } } @@ -53,8 +51,8 @@ void Server::processClientUpdate(sf::Uint16 senderId, sf::Packet& packet) { double buf[5]; packet >> buf[0] >> buf[1] >> buf[2] >> buf[3] >> buf[4]; - _players.at(senderId)->translateToPoint(Point4D{ buf[0], buf[1], buf[2] }); - _players.at(senderId)->rotateToAngle(Point4D{0, buf[3], 0}); + _players.at(senderId)->translateToPoint(Vec3D{ buf[0], buf[1], buf[2] }); + _players.at(senderId)->rotateToAngle(Vec3D{0, buf[3], 0}); _players.at(senderId)->setHeadAngle(buf[4]); } diff --git a/Shooter.cpp b/Shooter.cpp index 0f37bf4..da2fe71 100644 --- a/Shooter.cpp +++ b/Shooter.cpp @@ -56,8 +56,8 @@ void Shooter::InitNetwork() client->setSpawnPlayerCallBack([this](sf::Uint16 id){ spawnPlayer(id); }); client->setRemovePlayerCallBack([this](sf::Uint16 id){ removePlayer(id); }); - client->setAddFireTraceCallBack([this](const Point4D& from, const Point4D& to){ addFireTrace(from, to); }); - client->setAddBonusCallBack([this](const std::string& bonusName, const Point4D& position){ addBonus(bonusName, position); }); + client->setAddFireTraceCallBack([this](const Vec3D& from, const Vec3D& to){ addFireTrace(from, to); }); + client->setAddBonusCallBack([this](const std::string& bonusName, const Vec3D& position){ addBonus(bonusName, position); }); client->setRemoveBonusCallBack([this](const std::string& bonusName){ removeBonus(bonusName); }); } @@ -68,25 +68,25 @@ void Shooter::start() { mouse->setMouseCursorVisible(true); - world->loadMap("maps/map1.obj", "maps/materials.txt", "map", Point4D{5, 5, 5}); + world->loadMap("maps/map1.obj", "maps/materials.txt", "map", Vec3D{5, 5, 5}); player = std::make_shared(); playerController = std::make_shared(player, keyboard, mouse); - player->setAddTraceCallBack([this](const Point4D& from, const Point4D& to){ client->addTrace(from, to); addFireTrace(from, to); }); + player->setAddTraceCallBack([this](const Vec3D& from, const Vec3D& to){ client->addTrace(from, to); addFireTrace(from, to); }); player->setDamagePlayerCallBack([this] (sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); }); - player->setRayCastFunction([this](const Point4D& from, const Point4D& to) { return world->rayCast(from, to); }); + player->setRayCastFunction([this](const Vec3D& from, const Vec3D& to) { return world->rayCast(from, to); }); player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); }); - player->setAddWeaponCallBack([this](std::shared_ptr weapon){ addWeapon(weapon); }); player->setRemoveWeaponCallBack([this](std::shared_ptr weapon){ removeWeapon(weapon); }); + player->initWeapons(); - camera->translateToPoint(player->position() + Point4D{0, 1.8, 0}); + camera->translateToPoint(player->position() + Vec3D{0, 1.8, 0}); player->attach(camera, "camera"); world->addBody(player, "Player"); - player->translate(Point4D{0, 10, 0}); + player->translate(Vec3D{0, 10, 0}); client = std::make_shared(player); server = std::make_shared(); @@ -96,7 +96,7 @@ void Shooter::start() { mainMenu.setBackgroundTexture("textures/back.png", 1.1, 1.1, screen->width(), screen->height()); mainMenu.addButton(screen->width()/2, 200, 200, 20, [this] () { this->play(); }, "Play", 5, 5, "textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "sound/click.ogg"); - mainMenu.addButton(screen->width()/2, 350, 200, 20, [this] () { this->player->translateToPoint(Point4D{0, 0, 0}); this->player->setVelocity({}); this->play(); }, "Respawn", 5, 5, "textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "sound/click.ogg"); + mainMenu.addButton(screen->width()/2, 350, 200, 20, [this] () { this->player->translateToPoint(Vec3D{0, 0, 0}); this->player->setVelocity({}); this->play(); }, "Respawn", 5, 5, "textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "sound/click.ogg"); mainMenu.addButton(screen->width()/2, 500, 200, 20, [this] () { client->disconnect(); server->stop(); this->exit();}, "Exit", 5, 5, "textures/gui.png", {0, 66}, {0, 86}, {0, 46}, "engine/fonts/Roboto-Medium.ttf", {255, 255, 255}, "sound/click.ogg"); @@ -207,22 +207,22 @@ void Shooter::spawnPlayer(sf::Uint16 id) { client->addPlayer(id, newPlayer); world->addBody(newPlayer, name); newPlayer->setVisible(true); - newPlayer->setAcceleration(Point4D{0, 0, 0}); + newPlayer->setAcceleration(Vec3D{0, 0, 0}); // add head and other stuff: - world->loadBody(name + "_head", "obj/cube.obj", "", Point4D{0.7, 0.7, 0.7}); - world->body(name + "_head")->translate(Point4D{0, 2, 0}); + world->loadBody(name + "_head", "obj/cube.obj", "", Vec3D{0.7, 0.7, 0.7}); + world->body(name + "_head")->translate(Vec3D{0, 2, 0}); world->body(name + "_head")->setCollider(false); newPlayer->attach(world->body(name + "_head"), "head"); - world->loadBody(name + "_eye1", "obj/cube.obj", "", Point4D{0.2, 0.2, 0.05}); - world->body(name + "_eye1")->translate(Point4D{0.3, 2.1, 0.7}); + world->loadBody(name + "_eye1", "obj/cube.obj", "", Vec3D{0.2, 0.2, 0.05}); + world->body(name + "_eye1")->translate(Vec3D{0.3, 2.1, 0.7}); world->body(name + "_eye1")->setCollider(false); world->body(name + "_eye1")->setColor({147, 159, 255}); world->body(name + "_head")->attach(world->body(name + "_eye1"), "eye1"); - world->loadBody(name + "_eye2", "obj/cube.obj", "", Point4D{0.2, 0.2, 0.05}); - world->body(name + "_eye2")->translate(Point4D{-0.3, 2.1, 0.7}); + world->loadBody(name + "_eye2", "obj/cube.obj", "", Vec3D{0.2, 0.2, 0.05}); + world->body(name + "_eye2")->translate(Vec3D{-0.3, 2.1, 0.7}); world->body(name + "_eye2")->setCollider(false); world->body(name + "_eye2")->setColor({147, 159, 255}); world->body(name + "_head")->attach(world->body(name + "_eye2"), "eye2"); @@ -236,7 +236,7 @@ void Shooter::removePlayer(sf::Uint16 id) { world->removeBody(name + "_eye2"); } -void Shooter::addFireTrace(const Point4D &from, const Point4D &to) { +void Shooter::addFireTrace(const Vec3D &from, const Vec3D &to) { std::string traceName = "Client_fireTraces_" + std::to_string(fireTraces++); world->addBody(std::make_shared(Mesh::LineTo(from, to, 0.05)), traceName); world->body(traceName)->setCollider(false); @@ -249,11 +249,11 @@ void Shooter::deleteFireTrace(const std::string& traceName) { world->removeBody(traceName); } -void Shooter::addBonus(const string &bonusName, const Point4D &position) { +void Shooter::addBonus(const string &bonusName, const Vec3D &position) { std::string name = bonusName.substr(6, bonusName.size()-3-5); - world->addBody(std::make_shared(bonusName, "obj/" + name + ".obj", "obj/" + name + "_mat.txt", Point4D{3, 3, 3}), bonusName); + world->addBody(std::make_shared(bonusName, "obj/" + name + ".obj", "obj/" + name + "_mat.txt", Vec3D{3, 3, 3}), bonusName); world->body(bonusName)->translateToPoint(position); - Timeline::animate(bonusName + "_rotation", new ARotate(world->body(bonusName), Point4D{0, 2*Consts::PI, 0}, 4, Animation::LoopOut::Continue, Animation::InterpolationType::linear)); + Timeline::animate(bonusName + "_rotation", new ARotate(world->body(bonusName), Vec3D{0, 2*Consts::PI, 0}, 4, Animation::LoopOut::Continue, Animation::InterpolationType::linear)); } void Shooter::removeBonus(const string &bonusName) { diff --git a/Shooter.h b/Shooter.h index fec5737..729e119 100644 --- a/Shooter.h +++ b/Shooter.h @@ -43,9 +43,9 @@ private: void spawnPlayer(sf::Uint16 id); void removePlayer(sf::Uint16 id); - void addFireTrace(const Point4D& from, const Point4D& to); + void addFireTrace(const Vec3D& from, const Vec3D& to); void deleteFireTrace(const std::string& traceName); - void addBonus(const std::string& bonusName, const Point4D& position); + void addBonus(const std::string& bonusName, const Vec3D& position); void removeBonus(const std::string& bonusName); void addWeapon(std::shared_ptr weapon); void removeWeapon(std::shared_ptr weapon); diff --git a/ShooterConsts.h b/ShooterConsts.h new file mode 100644 index 0000000..3e7473a --- /dev/null +++ b/ShooterConsts.h @@ -0,0 +1,13 @@ +// +// Created by Иван Ильин on 10.10.2021. +// + +#ifndef SHOOTER_SHOOTERCONSTS_H +#define SHOOTER_SHOOTERCONSTS_H + +namespace ShooterConsts { + const double GRAVITY = 35; + +} + +#endif //SHOOTER_SHOOTERCONSTS_H diff --git a/engine/Camera.cpp b/engine/Camera.cpp index 8aed8aa..a95f1fd 100644 --- a/engine/Camera.cpp +++ b/engine/Camera.cpp @@ -8,11 +8,11 @@ #include #include "Consts.h" -std::vector &Camera::project(std::shared_ptr mesh) { +std::vector> Camera::project(std::shared_ptr mesh) { if(!_ready) { Log::log("Camera::project(): cannot project _tris without camera initialization ( Camera::init() ) "); - return this->_triangles; + return _triangles; } if(!mesh->isVisible()) @@ -24,37 +24,36 @@ std::vector &Camera::project(std::shared_ptr mesh) { // We don't want to waste time re-allocating memory every time std::vector clippedTriangles, tempBuffer; + for(auto& t : mesh->triangles()) { - double dot = t.norm().dot((mesh->position() + t[0] - _position).normalized()); + + double dot = t.norm().dot((mesh->position() + Vec3D(t[0]) - position()).normalized()); if(dot > 0) continue; - Triangle clipped[2]; // It needs to be cleared because it's reused through iterations. Usually it doesn't free memory. clippedTriangles.clear(); + tempBuffer.clear(); - // In the beginning we need to to translate drawTriangle from world coordinate to our camera system: + // In the beginning we need to to translate triangle from world coordinate to our camera system: // After that we apply clipping for all planes from _clipPlanes clippedTriangles.emplace_back(t * VM); for(auto& plane : _clipPlanes) { while(!clippedTriangles.empty()) { - clipped[0] = clippedTriangles.back(); - clipped[1] = clipped[0]; + std::vector clipResult = plane.clip(clippedTriangles.back()); clippedTriangles.pop_back(); - int additional = plane.clip(clipped[0], clipped[1]); - - for(int i = 0; i < additional; i++) - tempBuffer.emplace_back(clipped[i]); + for(auto & i : clipResult) + tempBuffer.emplace_back(i); } clippedTriangles.swap(tempBuffer); } - for(auto& clippedTriangle : clippedTriangles) { - sf::Color color = clippedTriangle.color(); + for(auto& clipped : clippedTriangles) { + sf::Color color = clipped.color(); sf::Color ambientColor = sf::Color((sf::Uint8)(color.r * (0.3 * std::abs(dot) + 0.7)), (sf::Uint8)(color.g * (0.3 * std::abs(dot) + 0.7)), (sf::Uint8)(color.b * (0.3 * std::abs(dot) + 0.7)), @@ -62,14 +61,14 @@ std::vector &Camera::project(std::shared_ptr mesh) { // Finally its time to project our clipped colored drawTriangle from 3D -> 2D // and transform it's coordinate to screen space (in pixels): - clippedTriangle = clippedTriangle * _SP; + Triangle clippedProjected = clipped * _SP; - clippedTriangle = Triangle(clippedTriangle[0] / clippedTriangle[0].w(), - clippedTriangle[1] / clippedTriangle[1].w(), - clippedTriangle[2] / clippedTriangle[2].w(), - ambientColor); + Triangle clippedProjectedNormalized = Triangle(clippedProjected[0] / clippedProjected[0].w(), + clippedProjected[1] / clippedProjected[1].w(), + clippedProjected[2] / clippedProjected[2].w(), + ambientColor); - _triangles.emplace_back(clippedTriangle); + _triangles.emplace_back(std::make_shared(clippedProjectedNormalized)); } } @@ -87,28 +86,28 @@ void Camera::init(int width, int height, double fov, double ZNear, double ZFar) // This is planes for clipping _tris. // Motivation: we are not interest in _tris that we cannot see. - _clipPlanes.emplace_back(Plane(Point4D{0, 0, 1}, Point4D{0, 0, ZNear})); // near plane - _clipPlanes.emplace_back(Plane(Point4D{0, 0, -1}, Point4D{0, 0, ZFar})); // far plane + _clipPlanes.emplace_back(Plane(Vec3D{0, 0, 1}, Vec3D{0, 0, ZNear})); // near plane + _clipPlanes.emplace_back(Plane(Vec3D{0, 0, -1}, Vec3D{0, 0, ZFar})); // far plane double thetta1 = Consts::PI*fov*0.5/180.0; double thetta2 = atan(_aspect * tan(thetta1)); - _clipPlanes.emplace_back(Plane(Point4D{-cos(thetta2), 0, sin(thetta2)}, Point4D{0, 0, 0})); // left plane - _clipPlanes.emplace_back(Plane(Point4D{cos(thetta2), 0, sin(thetta2)}, Point4D{0, 0, 0})); // right plane - _clipPlanes.emplace_back(Plane(Point4D{0, cos(thetta1), sin(thetta1)}, Point4D{0, 0, 0})); // down plane - _clipPlanes.emplace_back(Plane(Point4D{0, -cos(thetta1), sin(thetta1)}, Point4D{0, 0, 0})); // up plane + _clipPlanes.emplace_back(Plane(Vec3D{-cos(thetta2), 0, sin(thetta2)}, Vec3D{0, 0, 0})); // left plane + _clipPlanes.emplace_back(Plane(Vec3D{cos(thetta2), 0, sin(thetta2)}, Vec3D{0, 0, 0})); // right plane + _clipPlanes.emplace_back(Plane(Vec3D{0, cos(thetta1), sin(thetta1)}, Vec3D{0, 0, 0})); // down plane + _clipPlanes.emplace_back(Plane(Vec3D{0, -cos(thetta1), sin(thetta1)}, Vec3D{0, 0, 0})); // up plane _ready = true; Log::log("Camera::init(): camera successfully initialized."); } -std::vector &Camera::sorted() { +std::vector> Camera::sorted() { // Sort _tris from _back to front // This is some replacement for Z-buffer - std::sort(_triangles.begin(), _triangles.end(), [](Triangle &t1, Triangle &t2) + std::sort(_triangles.begin(), _triangles.end(), [](std::shared_ptr &t1, std::shared_ptr &t2) { - std::vector v_z1({t1[0].z(), t1[1].z(), t1[2].z()}); - std::vector v_z2({t2[0].z(), t2[1].z(), t2[2].z()}); + std::vector v_z1({(*t1)[0].z(), (*t1)[1].z(), (*t1)[2].z()}); + std::vector v_z2({(*t2)[0].z(), (*t2)[1].z(), (*t2)[2].z()}); std::sort(v_z1.begin(), v_z1.end()); std::sort(v_z2.begin(), v_z2.end()); @@ -127,5 +126,5 @@ void Camera::clear() { // That is like preparation for new camera shot: we need to set // the position of camera and insert new cartridge for photo. _triangles.clear(); - _V = Matrix4x4::View(_left, _up, _lookAt, _position); + _V = Matrix4x4::View(left(), up(), lookAt(), position()); } diff --git a/engine/Camera.h b/engine/Camera.h index 58d1f23..69d60fe 100644 --- a/engine/Camera.h +++ b/engine/Camera.h @@ -19,7 +19,7 @@ private: // To accelerate calculations we can use precalculated matrix that does not chance Matrix4x4 _SP; // screen-space-projections matrix - std::vector _triangles{}; + std::vector> _triangles{}; std::vector _clipPlanes{}; bool _ready = false; @@ -30,12 +30,12 @@ public: void init(int width, int height, double fov = 110.0, double ZNear = 0.1, double ZFar = 5000.0); - std::vector& project(std::shared_ptr mesh); + std::vector> project(std::shared_ptr mesh); void clear(); [[nodiscard]] int buffSize() const { return _triangles.size(); } - std::vector& sorted(); + std::vector> sorted(); }; diff --git a/engine/Consts.h b/engine/Consts.h index 81fdb74..2415018 100644 --- a/engine/Consts.h +++ b/engine/Consts.h @@ -7,6 +7,12 @@ namespace Consts { const double PI = 3.14159265358979323846264338327950288; + const double EPS = 0.000001; + + const int GJK_MAX_ITERATIONS = 50; + const double EPA_EPS = 0.0001; + + const double RAY_CAST_MAX_DISTANCE = 10000; } #endif //SHOOTER_CONSTS_H diff --git a/engine/Engine.cpp b/engine/Engine.cpp index 48c4173..b34ec07 100644 --- a/engine/Engine.cpp +++ b/engine/Engine.cpp @@ -55,7 +55,7 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name, // draw projected body for (auto &t : camera->sorted()) - screen->drawTriangle(t); + screen->drawTriangle(*t); _triPerSec = camera->buffSize() * Time::fps(); diff --git a/engine/utils/Matrix4x4.cpp b/engine/Matrix4x4.cpp similarity index 69% rename from engine/utils/Matrix4x4.cpp rename to engine/Matrix4x4.cpp index 337c22c..350f35c 100644 --- a/engine/utils/Matrix4x4.cpp +++ b/engine/Matrix4x4.cpp @@ -6,7 +6,7 @@ #include #include -#include "../Consts.h" +#include "Consts.h" Matrix4x4 Matrix4x4::operator*(const Matrix4x4 &matrix4X4) const { Matrix4x4 result = Matrix4x4::Zero(); @@ -27,6 +27,14 @@ Point4D Matrix4x4::operator*(const Point4D &point4D) const { ); } +Vec3D Matrix4x4::operator*(const Vec3D &vec) const { + return Vec3D( + _arr[0][0] * vec.x() + _arr[0][1] * vec.y() + _arr[0][2] * vec.z(), + _arr[1][0] * vec.x() + _arr[1][1] * vec.y() + _arr[1][2] * vec.z(), + _arr[2][0] * vec.x() + _arr[2][1] * vec.y() + _arr[2][2] * vec.z() + ); +} + Matrix4x4 Matrix4x4::Identity() { Matrix4x4 result; @@ -54,7 +62,7 @@ Matrix4x4 Matrix4x4::Zero() { return Matrix4x4::Constant(0); } -Matrix4x4 Matrix4x4::Scale(const Point4D& factor) { +Matrix4x4 Matrix4x4::Scale(const Vec3D& factor) { Matrix4x4 s{}; s._arr[0][0] = factor.x(); s._arr[1][1] = factor.y(); @@ -64,14 +72,8 @@ Matrix4x4 Matrix4x4::Scale(const Point4D& factor) { return s; } -Matrix4x4 Matrix4x4::Translation(const Point4D& v) { +Matrix4x4 Matrix4x4::Translation(const Vec3D& v) { Matrix4x4 t{}; -/* - * ( 1 0 0 dx )(_x) (_x + dx) - * ( 0 1 0 dy )(_y) = (_y + dy) - * ( 0 0 1 dz )(z) (z + dz) - * ( 0 0 0 1 )(1) ( 1 ) - */ t._arr[0][0] = 1.0; t._arr[1][1] = 1.0; @@ -129,25 +131,25 @@ Matrix4x4 Matrix4x4::RotationZ(double rz) { return Rz; } -Matrix4x4 Matrix4x4::Rotation(const Point4D& r) { +Matrix4x4 Matrix4x4::Rotation(const Vec3D& r) { return RotationX(r.x()) * RotationY(r.y()) * RotationZ(r.z()); } -Matrix4x4 Matrix4x4::Rotation(Point4D v, double rv) { +Matrix4x4 Matrix4x4::Rotation(const Vec3D& v, double rv) { Matrix4x4 Rv{}; - v = v.normalized(); + Vec3D nv(v.normalized()); - Rv._arr[0][0] = cos(rv) + (1.0 - cos(rv))*v.x()*v.x(); - Rv._arr[0][1] = (1.0 - cos(rv))*v.x()*v.y() - sin(rv)*v.z(); - Rv._arr[0][2] = (1.0 - cos(rv))*v.x()*v.z() + sin(rv)*v.y(); + Rv._arr[0][0] = cos(rv) + (1.0 - cos(rv))*nv.x()*nv.x(); + Rv._arr[0][1] = (1.0 - cos(rv))*nv.x()*nv.y() - sin(rv)*nv.z(); + Rv._arr[0][2] = (1.0 - cos(rv))*nv.x()*nv.z() + sin(rv)*nv.y(); - Rv._arr[1][0] = (1.0 - cos(rv))*v.x()*v.y() + sin(rv)*v.z(); - Rv._arr[1][1] = cos(rv) + (1.0 - cos(rv))*v.y()*v.y(); - Rv._arr[1][2] = (1.0 - cos(rv))*v.y()*v.z() - sin(rv)*v.x(); + Rv._arr[1][0] = (1.0 - cos(rv))*nv.x()*nv.y() + sin(rv)*nv.z(); + Rv._arr[1][1] = cos(rv) + (1.0 - cos(rv))*nv.y()*nv.y(); + Rv._arr[1][2] = (1.0 - cos(rv))*nv.y()*nv.z() - sin(rv)*nv.x(); - Rv._arr[2][0] = (1.0 - cos(rv))*v.z()*v.x() - sin(rv)*v.y(); - Rv._arr[2][1] = (1.0 - cos(rv))*v.z()*v.y() + sin(rv)*v.x(); - Rv._arr[2][2] = cos(rv) + (1.0 - cos(rv))*v.z()*v.z(); + Rv._arr[2][0] = (1.0 - cos(rv))*nv.z()*nv.x() - sin(rv)*nv.y(); + Rv._arr[2][1] = (1.0 - cos(rv))*nv.z()*nv.y() + sin(rv)*nv.x(); + Rv._arr[2][2] = cos(rv) + (1.0 - cos(rv))*nv.z()*nv.z(); Rv._arr[3][3] = 1.0; @@ -181,22 +183,22 @@ Matrix4x4 Matrix4x4::ScreenSpace(int width, int height) { return s; } -Matrix4x4 Matrix4x4::View(const Point4D &left, const Point4D &up, const Point4D &lookAt, const Point4D &eye) { +Matrix4x4 Matrix4x4::View(const Vec3D &left, const Vec3D &up, const Vec3D &lookAt, const Vec3D &eye) { Matrix4x4 V = Zero(); - V._arr[0][0] = left[0]; - V._arr[0][1] = left[1]; - V._arr[0][2] = left[2]; + V._arr[0][0] = left.x(); + V._arr[0][1] = left.y(); + V._arr[0][2] = left.z(); V._arr[0][3] = -eye.dot(left); - V._arr[1][0] = up[0]; - V._arr[1][1] = up[1]; - V._arr[1][2] = up[2]; + V._arr[1][0] = up.x(); + V._arr[1][1] = up.y(); + V._arr[1][2] = up.z(); V._arr[1][3] = -eye.dot(up); - V._arr[2][0] = lookAt[0]; - V._arr[2][1] = lookAt[1]; - V._arr[2][2] = lookAt[2]; + V._arr[2][0] = lookAt.x(); + V._arr[2][1] = lookAt.y(); + V._arr[2][2] = lookAt.z(); V._arr[2][3] = -eye.dot(lookAt); V._arr[3][3] = 1.0; diff --git a/engine/utils/Matrix4x4.h b/engine/Matrix4x4.h similarity index 71% rename from engine/utils/Matrix4x4.h rename to engine/Matrix4x4.h index 7c04d88..6bbe1e3 100644 --- a/engine/utils/Matrix4x4.h +++ b/engine/Matrix4x4.h @@ -7,6 +7,7 @@ #include #include "Point4D.h" +#include "Vec3D.h" class Matrix4x4 { private: @@ -18,21 +19,22 @@ public: [[nodiscard]] Matrix4x4 operator*(const Matrix4x4& matrix4X4) const; [[nodiscard]] Point4D operator*(const Point4D& point4D) const; + [[nodiscard]] Vec3D operator*(const Vec3D& vec) const; // Any useful matrix (static methods) Matrix4x4 static Identity(); Matrix4x4 static Zero(); Matrix4x4 static Constant (double value); - Matrix4x4 static Scale(const Point4D& factor); - Matrix4x4 static Translation(const Point4D& v); - Matrix4x4 static Rotation(const Point4D& r); + Matrix4x4 static Scale(const Vec3D& factor); + Matrix4x4 static Translation(const Vec3D& v); + Matrix4x4 static Rotation(const Vec3D& r); Matrix4x4 static RotationX (double rx); Matrix4x4 static RotationY (double ry); Matrix4x4 static RotationZ (double rz); - Matrix4x4 static Rotation (Point4D v, double rv); + Matrix4x4 static Rotation (const Vec3D& v, double rv); - Matrix4x4 static View(const Point4D& left, const Point4D& up, const Point4D& lookAt, const Point4D& eye); + Matrix4x4 static View(const Vec3D &left, const Vec3D &up, const Vec3D &lookAt, const Vec3D &eye); Matrix4x4 static Projection (double fov = 90.0, double aspect = 1.0, double ZNear = 1.0, double ZFar = 10.0); Matrix4x4 static ScreenSpace (int width, int height); }; diff --git a/engine/Mesh.cpp b/engine/Mesh.cpp index 0b5c520..ae2f582 100644 --- a/engine/Mesh.cpp +++ b/engine/Mesh.cpp @@ -12,13 +12,16 @@ using namespace std; Mesh &Mesh::operator*=(const Matrix4x4 &matrix4X4) { - for (auto& t : _tris) - t = t * matrix4X4; + std::vector newTriangles; + for(auto &t : _tris) { + newTriangles.emplace_back(t * matrix4X4); + } + setTriangles(newTriangles); return *this; } -Mesh &Mesh::loadObj(const std::string& filename, const std::string &materials, const Point4D& scale) { +Mesh &Mesh::loadObj(const std::string& filename, const std::string &materials, const Vec3D& scale) { auto objects = Mesh::LoadObjects(filename, materials, scale); for(auto& obj : objects) { @@ -29,61 +32,54 @@ Mesh &Mesh::loadObj(const std::string& filename, const std::string &materials, c return *this; } -Mesh::Mesh(const std::string& filename, const std::string &materials, const Point4D& scale){ +Mesh::Mesh(const std::string& filename, const std::string &materials, const Vec3D& scale){ loadObj(filename, materials, scale); } -Mesh::Mesh(const vector &tries){ - _tris = tries; -} - -Mesh::Mesh(const Mesh& mesh) { - *this = mesh; +Mesh::Mesh(const vector &tries) : _tris(tries) { } Mesh Mesh::Obj(const std::string& filename) { return Mesh(filename); } -void Mesh::rotate(const Point4D &r) { +void Mesh::rotate(const Vec3D &r) { Object::rotate(r); *this *= Matrix4x4::Rotation(r); } -void Mesh::rotate(const Point4D &v, double r) { +void Mesh::rotate(const Vec3D &v, double r) { Object::rotate(v, r); *this *= Matrix4x4::Rotation(v, r); } -void Mesh::scale(const Point4D &s) { +void Mesh::scale(const Vec3D &s) { Object::scale(s); *this *= Matrix4x4::Scale(s); } -Mesh &Mesh::operator=(const Mesh &mesh) { - _tris = mesh._tris; - _position = mesh._position; - _color = mesh._color; - return *this; -} - -void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &r) { +void Mesh::rotateRelativePoint(const Vec3D &s, const Vec3D &r) { Object::rotateRelativePoint(s, r); *this *= Matrix4x4::Rotation(r); } -void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) { +void Mesh::rotateRelativePoint(const Vec3D &s, const Vec3D &v, double r) { Object::rotateRelativePoint(s, v, r); *this *= Matrix4x4::Rotation(v, r); } -void Mesh::setColor(sf::Color c) { +void Mesh::setColor(const sf::Color& c) { _color = c; - for (auto& t : _tris) - t = Triangle(t[0], t[1], t[2], _color); + + // change color of all mesh triangles: + std::vector newTriangles; + for(auto &t : _tris) { + newTriangles.emplace_back(Triangle(t[0], t[1], t[2], c)); + } + setTriangles(newTriangles); } -std::vector> Mesh::LoadObjects(const string &filename, const string &materials, const Point4D &scale) { +std::vector> Mesh::LoadObjects(const string &filename, const string &materials, const Vec3D &scale) { std::vector> objects; map maters; @@ -170,26 +166,27 @@ std::vector> Mesh::LoadObjects(const string &filename, con return objects; } -Mesh Mesh::LineTo(const Point4D& from, const Point4D& to, double line_width, sf::Color color) { +Mesh Mesh::LineTo(const Vec3D& from, const Vec3D& to, double line_width, const sf::Color& color) { Mesh line; - Point4D v1 = (to - from).normalized(); - Point4D v2 = from.cross3D(from + Point4D{1, 0, 0}).normalized(); - Point4D v3 = v1.cross3D(v2).normalized(); + Vec3D v1 = (to - from).normalized(); + Vec3D v2 = from.cross(from + Vec3D{1, 0, 0}).normalized(); + Vec3D v3 = v1.cross(v2).normalized(); // from plane - Point4D p1 = from - v2 * line_width/2.0 - v3 * line_width/2.0; - Point4D p2 = from - v2 * line_width/2.0 + v3 * line_width/2.0; - Point4D p3 = from + v2 * line_width/2.0 + v3 * line_width/2.0; - Point4D p4 = from + v2 * line_width/2.0 - v3 * line_width/2.0; + Point4D p1 = (from - v2 * line_width/2.0 - v3 * line_width/2.0).makePoint4D(); + Point4D p2 = (from - v2 * line_width/2.0 + v3 * line_width/2.0).makePoint4D(); + Point4D p3 = (from + v2 * line_width/2.0 + v3 * line_width/2.0).makePoint4D(); + Point4D p4 = (from + v2 * line_width/2.0 - v3 * line_width/2.0).makePoint4D(); // to plane - Point4D p5 = to - v2 * line_width/2.0 - v3 * line_width/2.0; - Point4D p6 = to - v2 * line_width/2.0 + v3 * line_width/2.0; - Point4D p7 = to + v2 * line_width/2.0 + v3 * line_width/2.0; - Point4D p8 = to + v2 * line_width/2.0 - v3 * line_width/2.0; + Point4D p5 = (to - v2 * line_width/2.0 - v3 * line_width/2.0).makePoint4D(); + Point4D p6 = (to - v2 * line_width/2.0 + v3 * line_width/2.0).makePoint4D(); + Point4D p7 = (to + v2 * line_width/2.0 + v3 * line_width/2.0).makePoint4D(); + Point4D p8 = (to + v2 * line_width/2.0 - v3 * line_width/2.0).makePoint4D(); - line._tris = { + + line._tris = std::move(std::vector{ { p2, p4, p1 }, { p2, p3, p4 }, { p1, p6, p2 }, @@ -202,14 +199,19 @@ Mesh Mesh::LineTo(const Point4D& from, const Point4D& to, double line_width, sf: { p4, p7, p8 }, { p1, p8, p5 }, { p1, p4, p8 } - }; - + }); line.setColor(color); - for(auto& triangle : line._tris) - triangle = Triangle(Point4D{triangle[0].x(), triangle[0].y(), triangle[0].z(), 1}, - Point4D{triangle[1].x(), triangle[1].y(), triangle[1].z(), 1}, - Point4D{triangle[2].x(), triangle[2].y(), triangle[2].z(), 1}, line.color()); - return line; } + +Mesh::Mesh(const Mesh &mesh) : _tris(mesh._tris), _color(mesh._color), _visible(mesh._visible) { + +} + +void Mesh::setTriangles(const vector &t) { + _tris.clear(); + for (auto & tri : t) { + _tris.push_back(tri); + } +} diff --git a/engine/Mesh.h b/engine/Mesh.h index 7363a07..d78236b 100644 --- a/engine/Mesh.h +++ b/engine/Mesh.h @@ -19,38 +19,38 @@ private: Mesh& operator*=(const Matrix4x4& matrix4X4); public: Mesh() = default; + Mesh& operator=(const Mesh& mesh) = delete; Mesh(const Mesh& mesh); explicit Mesh(const std::vector& tries); - Mesh& operator=(const Mesh& mesh); - explicit Mesh(const std::string& filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1}); + explicit Mesh(const std::string& filename, const std::string &materials = "", const Vec3D& scale = Vec3D{1, 1, 1}); - Mesh& loadObj(const std::string& filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1}); + Mesh& loadObj(const std::string& filename, const std::string &materials = "", const Vec3D& scale = Vec3D{1, 1, 1}); [[nodiscard]] std::vectorconst &triangles() const { return _tris; } [[nodiscard]] std::vector& triangles() { return _tris; } - void setTriangles(const std::vector& t) { _tris = t; } + void setTriangles(const std::vector& t); // Translate body // Rotate body around XYZ axes - void rotate(const Point4D& r) override; + void rotate(const Vec3D& r) override; // Rotate body around normalised vector 'v' by 'r' radians - void rotate(const Point4D& v, double r) override; + void rotate(const Vec3D& v, double r) override; // Rotate body around XYZ by (r._x, r._y, r.z) radians relative val 'point4D' - void rotateRelativePoint(const Point4D& point4D, const Point4D& r) override; + void rotateRelativePoint(const Vec3D& point, const Vec3D& r) override; // Rotate body around normalised vector 'v' by 'r' radians relative val 'point4D' - void rotateRelativePoint(const Point4D& point4D, const Point4D& v, double r) override; - void scale(const Point4D& s) override; + void rotateRelativePoint(const Vec3D& point4D, const Vec3D& v, double r) override; + void scale(const Vec3D& s) override; [[nodiscard]] sf::Color color() const { return _color; } - void setColor(sf::Color c); + void setColor(const sf::Color& c); void setVisible(bool visibility) { _visible = visibility; } [[nodiscard]] bool isVisible() const { return _visible; } Mesh static Obj(const std::string& filename); - std::vector> static LoadObjects(const std::string& filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1}); - Mesh static LineTo(const Point4D& from, const Point4D& to, double line_width = 0.1, sf::Color color = {150, 150, 150, 255}); + std::vector> static LoadObjects(const std::string& filename, const std::string &materials = "", const Vec3D& scale = Vec3D{1, 1, 1}); + Mesh static LineTo(const Vec3D& from, const Vec3D& to, double line_width = 0.1, const sf::Color& color = {150, 150, 150, 255}); }; #endif //INC_3DZAVR_MESH_H diff --git a/engine/Mouse.cpp b/engine/Mouse.cpp index 231102e..453a664 100644 --- a/engine/Mouse.cpp +++ b/engine/Mouse.cpp @@ -5,18 +5,18 @@ #include "Mouse.h" #include "utils/Time.h" -Point4D Mouse::getMousePosition() const { +Vec2D Mouse::getMousePosition() const { sf::Vector2 pos = sf::Mouse::getPosition(*_window); - return Point4D(pos.x, pos.y, 0, 0); + return Vec2D(pos.x, pos.y); } -Point4D Mouse::getMouseDisplacement() const { +Vec2D Mouse::getMouseDisplacement() const { sf::Vector2 mousePos = sf::Mouse::getPosition(*_window); sf::Vector2 center = sf::Vector2(_window->getSize().x/2, _window->getSize().y/2); sf::Vector2 displacement = mousePos - center; //setMouseInCenter(); - return Point4D(displacement.x, displacement.y, 0, 0); + return Vec2D(displacement.x, displacement.y); } void Mouse::setMouseInCenter() const { diff --git a/engine/Mouse.h b/engine/Mouse.h index e88b6ba..6101916 100644 --- a/engine/Mouse.h +++ b/engine/Mouse.h @@ -7,7 +7,7 @@ #include #include -#include "utils/Point4D.h" +#include "Vec2D.h" class Mouse { private: @@ -22,8 +22,8 @@ public: static bool isButtonPressed(sf::Mouse::Button button); // returns true if this _button is _pressed bool isButtonTapped(sf::Mouse::Button button); // returns true if this _button is tapped and 1/5 sec passed (_button bouncing problem solved) - [[nodiscard]] Point4D getMousePosition() const; - [[nodiscard]] Point4D getMouseDisplacement() const; + [[nodiscard]] Vec2D getMousePosition() const; + [[nodiscard]] Vec2D getMouseDisplacement() const; void setMouseInCenter() const; void setMouseCursorVisible(bool visible); }; diff --git a/engine/Object.cpp b/engine/Object.cpp index ef56b3e..9d69dde 100644 --- a/engine/Object.cpp +++ b/engine/Object.cpp @@ -3,114 +3,121 @@ // #include "Object.h" -#include "utils/Matrix4x4.h" +#include "Matrix4x4.h" #include "utils/Log.h" -void Object::translate(const Point4D &dv) { - _position = _position + dv; +void Object::translate(const Vec3D &dv) { + _position = std::make_unique(*_position + dv); for(auto attached : _attachedObjects) attached.second->translate(dv); } -void Object::scale(const Point4D &s) { +void Object::scale(const Vec3D &s) { for(auto attached : _attachedObjects) attached.second->scale(s); } -void Object::rotate(const Point4D &r) { - _angle = _angle + r; +void Object::rotate(const Vec3D &r) { + _angle = std::make_unique(*_angle + r); Matrix4x4 rotationMatrix = Matrix4x4::RotationZ(r.z())*Matrix4x4::RotationY(r.y())*Matrix4x4::RotationX(r.z()); - _left = rotationMatrix * _left; - _up = rotationMatrix * _up; - _lookAt = rotationMatrix * _lookAt; + _left = std::make_unique(rotationMatrix * *_left); + _up = std::make_unique(rotationMatrix * *_up); + _lookAt = std::make_unique(rotationMatrix * *_lookAt); for(auto attached : _attachedObjects) attached.second->rotateRelativePoint(position(), r); } -void Object::rotate(const Point4D &v, double rv) { +void Object::rotate(const Vec3D &v, double rv) { Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, rv); - _left = rotationMatrix * _left; - _up = rotationMatrix * _up; - _lookAt = rotationMatrix * _lookAt; + + _left = std::make_unique(rotationMatrix * *_left); + _up = std::make_unique(rotationMatrix * *_up); + _lookAt = std::make_unique(rotationMatrix * *_lookAt); for(auto attached : _attachedObjects) attached.second->rotateRelativePoint(position(), v, rv); } -void Object::rotateRelativePoint(const Point4D &s, const Point4D &r) { - _angle = _angle + r; +void Object::rotateRelativePoint(const Vec3D &s, const Vec3D &r) { + _angle = std::make_unique(*_angle + r); // Translate XYZ by vector r1 - Point4D r1 = _position - s; + Vec3D r1(*_position - s); // In translated coordinate system we rotate body and position Matrix4x4 rotationMatrix = Matrix4x4::Rotation(r); - Point4D r2 = rotationMatrix*r1; + Vec3D r2(rotationMatrix*r1); - _left = rotationMatrix * _left; - _up = rotationMatrix * _up; - _lookAt = rotationMatrix * _lookAt; + _left = std::make_unique(rotationMatrix * *_left); + _up = std::make_unique(rotationMatrix * *_up); + _lookAt = std::make_unique(rotationMatrix * *_lookAt); // After rotation we translate XYZ by vector -r2 and recalculate position - _position = s + r2; + _position = std::make_unique(s + r2); for(auto attached : _attachedObjects) attached.second->rotateRelativePoint(s, r); } -void Object::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) { +void Object::rotateRelativePoint(const Vec3D &s, const Vec3D &v, double r) { // Translate XYZ by vector r1 - Point4D r1 = _position - s; + Vec3D r1(*_position - s); // In translated coordinate system we rotate body and position Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, r); - Point4D r2 = rotationMatrix*r1; + Vec3D r2 = rotationMatrix*r1; - _left = rotationMatrix * _left; - _up = rotationMatrix * _up; - _lookAt = rotationMatrix * _lookAt; + _left = std::make_unique(rotationMatrix * *_left); + _up = std::make_unique(rotationMatrix * *_up); + _lookAt = std::make_unique(rotationMatrix * *_lookAt); // After rotation we translate XYZ by vector -r2 and recalculate position - _position = s + r2; + _position = std::make_unique(s + r2); for(auto attached : _attachedObjects) attached.second->rotateRelativePoint(s, v, r); } void Object::rotateLeft(double rl) { - _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x() + rl, _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z()}; + _angleLeftUpLookAt = std::make_unique(Vec3D{_angleLeftUpLookAt->x() + rl, + _angleLeftUpLookAt->y(), + _angleLeftUpLookAt->z()}); - rotate(_left, rl); + rotate(*_left, rl); for(auto attached : _attachedObjects) - attached.second->rotateRelativePoint(position(), _left, rl); + attached.second->rotateRelativePoint(position(), *_left, rl); } void Object::rotateUp(double ru) { - _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y() + ru, _angleLeftUpLookAt.z()}; - rotate(_up, ru); + _angleLeftUpLookAt = std::make_unique(Vec3D{_angleLeftUpLookAt->x(), + _angleLeftUpLookAt->y() + ru, + _angleLeftUpLookAt->z()}); + rotate(*_up, ru); for(auto attached : _attachedObjects) - attached.second->rotateRelativePoint(position(), _up, ru); + attached.second->rotateRelativePoint(position(), *_up, ru); } void Object::rotateLookAt(double rlAt) { - _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z() + rlAt}; - rotate(_lookAt, rlAt); + _angleLeftUpLookAt = std::make_unique(Vec3D{_angleLeftUpLookAt->x(), + _angleLeftUpLookAt->y(), + _angleLeftUpLookAt->z() + rlAt}); + rotate(*_lookAt, rlAt); for(auto attached : _attachedObjects) - attached.second->rotateRelativePoint(position(), _lookAt, rlAt); + attached.second->rotateRelativePoint(position(), *_lookAt, rlAt); } -void Object::translateToPoint(const Point4D &point) { - translate(point - _position); +void Object::translateToPoint(const Vec3D &point) { + translate(point - *_position); } -void Object::rotateToAngle(const Point4D &v) { - rotate(v - _angle); +void Object::rotateToAngle(const Vec3D &v) { + rotate(v - *_angle); } std::shared_ptr Object::attached(const std::string &name) { @@ -120,7 +127,11 @@ std::shared_ptr Object::attached(const std::string &name) { } void Object::attach(std::shared_ptr object, const std::string &name) { - _attachedObjects.emplace(name, object); + // TODO: solve problem with possible infinite recursive call chains + if(this != object.get()) + _attachedObjects.emplace(name, object); + else + throw std::invalid_argument{"Object::attach: You cannot attach object to itself"}; } void Object::unattach(const std::string &name) { diff --git a/engine/Object.h b/engine/Object.h index 2ae19d0..0bcbd46 100644 --- a/engine/Object.h +++ b/engine/Object.h @@ -6,40 +6,40 @@ #define ENGINE_OBJECT_H #include -#include "utils/Point4D.h" +#include "Vec3D.h" #include #include class Object { protected: - Point4D _left = Point4D{1, 0, 0, 0}; // internal X - Point4D _up = Point4D{0, 1, 0, 0}; // internal Y - Point4D _lookAt = Point4D{0, 0, 1, 0}; // internal Z + std::unique_ptr _left = std::make_unique(Vec3D{1, 0, 0}); // internal X + std::unique_ptr _up = std::make_unique(Vec3D{0, 1, 0}); // internal Y + std::unique_ptr _lookAt = std::make_unique(Vec3D{0, 0, 1}); // internal Z std::map> _attachedObjects; - Point4D _position; - Point4D _angle; - Point4D _angleLeftUpLookAt; + std::unique_ptr _position = std::make_unique(Vec3D{0, 0, 0}); + std::unique_ptr _angle = std::make_unique(Vec3D{0, 0, 0}); + std::unique_ptr _angleLeftUpLookAt = std::make_unique(Vec3D{0, 0, 0}); public: Object() = default; - virtual void translate(const Point4D& dv); - virtual void translateToPoint(const Point4D& point); - virtual void scale(const Point4D& s); - virtual void rotate(const Point4D& r); - virtual void rotate(const Point4D& v, double rv); - virtual void rotateToAngle(const Point4D& v); - virtual void rotateRelativePoint(const Point4D& s, const Point4D& r); - virtual void rotateRelativePoint(const Point4D& s, const Point4D& v, double r); + virtual void translate(const Vec3D& dv); + virtual void translateToPoint(const Vec3D& point); + virtual void scale(const Vec3D& s); + virtual void rotate(const Vec3D& r); + virtual void rotate(const Vec3D& v, double rv); + virtual void rotateToAngle(const Vec3D& v); + virtual void rotateRelativePoint(const Vec3D& s, const Vec3D& r); + virtual void rotateRelativePoint(const Vec3D& s, const Vec3D& v, double r); - [[nodiscard]] Point4D position() const { return _position; } - [[nodiscard]] Point4D angle() const { return _angle; } - [[nodiscard]] Point4D angleLeftUpLookAt() const { return _angleLeftUpLookAt; } + [[nodiscard]] Vec3D position() const { return *_position; } + [[nodiscard]] Vec3D angle() const { return *_angle; } + [[nodiscard]] Vec3D angleLeftUpLookAt() const { return *_angleLeftUpLookAt; } - [[nodiscard]] Point4D left() const { return _left; } - [[nodiscard]] Point4D up() const { return _up; } - [[nodiscard]] Point4D lookAt() const { return _lookAt; } + [[nodiscard]] Vec3D left() const { return *_left; } + [[nodiscard]] Vec3D up() const { return *_up; } + [[nodiscard]] Vec3D lookAt() const { return *_lookAt; } void rotateLeft(double rl); void rotateUp(double ru); diff --git a/engine/Plane.cpp b/engine/Plane.cpp index 22f91fe..c9681f0 100644 --- a/engine/Plane.cpp +++ b/engine/Plane.cpp @@ -4,75 +4,71 @@ #include "Plane.h" -Plane::Plane(const Triangle& tri) { - _triangle = tri; - _n = tri.norm(); - _p = tri[0]; +Plane::Plane(const Triangle& tri) : _triangle(tri), _n(tri.norm()), _p(tri[0]) { + } -Plane::Plane(const Point4D &N, const Point4D &P) { - _n = N.normalized(); - _p = P; +Plane::Plane(const Vec3D &N, const Vec3D &P) : _n(N.normalized()), _p(P) { + } -Plane::Plane(const Plane &plane) { - _triangle = plane._triangle; - _n = plane._n; - _p = plane._p; +double Plane::distance(const Vec3D &point) const { + return point.dot(_n) - _p.dot(_n); } -double Plane::distance(const Point4D &point4D) const { - return point4D.dot(_n) - _p.dot(_n); -} - -std::pair Plane::intersection(const Point4D &start, const Point4D &end) const { +std::pair Plane::intersection(const Vec3D &start, const Vec3D &end) const { double s_dot_n = start.dot(_n); double k = (s_dot_n - _p.dot(_n)) / (s_dot_n - end.dot(_n)); - Point4D res = start + (end - start)*k; + Vec3D res = start + (end - start)*k; return std::make_pair(res, k); } -int Plane::clip(Triangle &tri, Triangle &additional_tri) const { +std::vector Plane::clip(const Triangle &tri) const { - Point4D insidePoints[3]; int inside = 0; - Point4D outsidePoints[3]; int outside = 0; + std::vector result; - double distances[3] = {distance(tri[0]), distance(tri[1]), distance(tri[2])}; + std::vector insidePoints; + std::vector outsidePoints; + + double distances[3] = {distance(Vec3D(tri[0])), + distance(Vec3D(tri[1])), + distance(Vec3D(tri[2]))}; for(int i = 0; i < 3; i++) { if (distances[i] >= 0) { - insidePoints[inside++] = tri[i]; + insidePoints.emplace_back(tri[i]); } else { - outsidePoints[outside++] = tri[i]; + outsidePoints.emplace_back(tri[i]); } } - if(inside == 0) { - return 0; + if(insidePoints.size() == 1) { + std::pair intersect1 = intersection(insidePoints[0], outsidePoints[0]); + std::pair intersect2 = intersection(insidePoints[0], outsidePoints[1]); + + result.emplace_back(insidePoints[0].makePoint4D(), + intersect1.first.makePoint4D(), + intersect2.first.makePoint4D(), + tri.color()); } - if(inside == 1) { - std::pair intersect1 = intersection(insidePoints[0], outsidePoints[0]); - std::pair intersect2 = intersection(insidePoints[0], outsidePoints[1]); + if(insidePoints.size() == 2) { + std::pair intersect1 = intersection(insidePoints[0], outsidePoints[0]); + std::pair intersect2 = intersection(insidePoints[1], outsidePoints[0]); - tri = Triangle(insidePoints[0], intersect1.first, intersect2.first, tri.color()); - - return 1; + result.emplace_back(insidePoints[0].makePoint4D(), + intersect1.first.makePoint4D(), + insidePoints[1].makePoint4D(), + tri.color()); + result.emplace_back(intersect1.first.makePoint4D(), + intersect2.first.makePoint4D(), + insidePoints[1].makePoint4D(), + tri.color()); } - if(inside == 2) { - std::pair intersect1 = intersection(insidePoints[0], outsidePoints[0]); - std::pair intersect2 = intersection(insidePoints[1], outsidePoints[0]); - - tri = Triangle(insidePoints[0], intersect1.first, insidePoints[1], tri.color()); - additional_tri = Triangle(intersect1.first, intersect2.first, insidePoints[1], tri.color()); - - return 2; + if(insidePoints.size() == 3) { + result.emplace_back(tri); } - if(inside == 3) { - return 1; - } - - return 0; + return result; } diff --git a/engine/Plane.h b/engine/Plane.h index 1ae7c1a..9c49909 100644 --- a/engine/Plane.h +++ b/engine/Plane.h @@ -5,7 +5,7 @@ #ifndef ENGINE_PLANE_H #define ENGINE_PLANE_H -#include "utils/Point4D.h" +#include "Point4D.h" #include "Triangle.h" class Plane { @@ -13,22 +13,22 @@ private: // You can define plane by defining the points in 3D space Triangle _triangle; // Or by defining normal vector and one val laying on the plane - Point4D _n = Point4D{0, 0, 1, 0}; - Point4D _p{}; + Vec3D _n = Vec3D{0, 0, 1}; + Vec3D _p{}; public: // A plain with normal vector '_n' and val '_p' lays on the plane Plane() = default; - Plane(const Point4D& N, const Point4D& P); - Plane(const Plane& plane); + Plane(const Vec3D& N, const Vec3D& P); + Plane(const Plane& plane) = default; explicit Plane(const Triangle& tri); - [[nodiscard]] double distance(const Point4D& point4D) const; + [[nodiscard]] double distance(const Vec3D& point4D) const; // Point4D in space where line ('start' to 'end') intersects plain with normal vector '_n' and val '_p' lays on the plane - [[nodiscard]] std::pair intersection(const Point4D& start, const Point4D& end) const; - int clip(Triangle& tri, Triangle& additional_tri) const; + [[nodiscard]] std::pair intersection(const Vec3D& start, const Vec3D& end) const; + [[nodiscard]] std::vector clip(const Triangle& tri) const; - [[nodiscard]] Point4D N() const { return _n; } - [[nodiscard]] Point4D P() const { return _p; } + [[nodiscard]] Vec3D N() const { return _n; } + [[nodiscard]] Vec3D P() const { return _p; } }; diff --git a/engine/utils/Point4D.cpp b/engine/Point4D.cpp similarity index 59% rename from engine/utils/Point4D.cpp rename to engine/Point4D.cpp index e8d8f86..9aa7e05 100644 --- a/engine/utils/Point4D.cpp +++ b/engine/Point4D.cpp @@ -4,6 +4,7 @@ #include "Point4D.h" #include +#include Point4D::Point4D (double x, double y, double z, double w) { _arr_point[0] = x; @@ -19,60 +20,51 @@ Point4D::Point4D(const Point4D &point4D) { _arr_point[3] = point4D.w(); } -[[nodiscard]] double Point4D::operator[] (int i) const { - return _arr_point[i]; -} - [[nodiscard]] Point4D Point4D::operator-() const { return Point4D(-x(), -y(), -z(), -w()); } -bool Point4D::operator==(const Point4D& point4D) const -{ - return this == &point4D || (*this - point4D).sqrAbs() < 0.0000000001; +bool Point4D::operator==(const Point4D& point4D) const { + return (*this - point4D).sqrAbs() < Consts::EPS; } -bool Point4D::operator!=(const Point4D& point4D) const -{ - return this != &point4D && (*this - point4D).sqrAbs() > 0.0000000001; + +bool Point4D::operator!=(const Point4D& point4D) const { + return !(*this == point4D); } // Operations with Point4D Point4D Point4D::operator+(const Point4D& point4D) const { return Point4D(x()+point4D.x(), y()+point4D.y(), z()+point4D.z(), w()+point4D.w()); } + Point4D Point4D::operator-(const Point4D& point4D) const { return Point4D(*this) + -point4D; } -double Point4D::dot(const Point4D& point4D) const -{ - return point4D.x() * x() + point4D.y() * y() + point4D.z() * z(); -} -[[nodiscard]] Point4D Point4D::cross3D(const Point4D& point4D) const { - return Point4D {y() * point4D.z() - point4D.y() * z(), - z() * point4D.x() - point4D.z() * x(), - x() * point4D.y() - point4D.x() * y()}; -} - Point4D Point4D::operator*(double number) const { return Point4D(x()*number, y()*number, z()*number, w()*number); } + Point4D Point4D::operator/(double number) const { - if(number != 0) + if(std::abs(number) > Consts::EPS) return Point4D(*this)*(1.0/number); else - return Point4D(); + throw std::domain_error{"Point4D::operator/(double number): division by zero"}; } // Other useful methods -double Point4D::sqrAbs() const -{ +double Point4D::sqrAbs() const { return x()*x() + y()*y() + z()*z(); } + double Point4D::abs() const { return sqrt(sqrAbs()); } Point4D Point4D::normalized() const { - return Point4D(*this)/abs(); + double vecAbs = abs(); + if(vecAbs > Consts::EPS) + return Point4D(*this)/abs(); + else + return Point4D(0); } diff --git a/engine/utils/Point4D.h b/engine/Point4D.h similarity index 80% rename from engine/utils/Point4D.h rename to engine/Point4D.h index 422c1a7..9a1c984 100644 --- a/engine/utils/Point4D.h +++ b/engine/Point4D.h @@ -6,6 +6,7 @@ #define ENGINE_POINT4D_H #include +#include "Consts.h" class Point4D { private: @@ -14,16 +15,15 @@ private: public: Point4D () = default; Point4D (const Point4D& point4D); - Point4D& operator=(const Point4D& point4D) { _arr_point = point4D._arr_point; return *this; }; explicit Point4D (double x, double y = 0.0, double z = 0.0, double w = 0.0); + Point4D& operator=(const Point4D& point4D) = delete; + [[nodiscard]] double x() const { return _arr_point[0]; } [[nodiscard]] double y() const { return _arr_point[1]; } [[nodiscard]] double z() const { return _arr_point[2]; } [[nodiscard]] double w() const { return _arr_point[3]; } - [[nodiscard]] double operator[] (int i) const; - [[nodiscard]] Point4D operator-() const; // Boolean operations @@ -34,9 +34,6 @@ public: [[nodiscard]] Point4D operator+(const Point4D& point4D) const; [[nodiscard]] Point4D operator-(const Point4D& point4D) const; - [[nodiscard]] double dot(const Point4D& point4D) const; // Returns dot product - [[nodiscard]] Point4D cross3D(const Point4D& point4D) const; // Returns cross product - // Operations with numbers [[nodiscard]] Point4D operator*(double number) const; [[nodiscard]] Point4D operator/(double number) const; diff --git a/engine/Screen.cpp b/engine/Screen.cpp index 2692343..19f51ac 100644 --- a/engine/Screen.cpp +++ b/engine/Screen.cpp @@ -78,7 +78,7 @@ void Screen::debugText(const std::string& text) { _window->draw(t); } -void Screen::drawTetragon(const Point4D &p1, const Point4D &p2, const Point4D &p3, const Point4D &p4, sf::Color color) { +void Screen::drawTetragon(const Vec2D &p1, const Vec2D &p2, const Vec2D &p3, const Vec2D &p4, sf::Color color) { sf::ConvexShape polygon; polygon.setPointCount(4); polygon.setPoint(0, sf::Vector2f((float)p1.x(), (float)p1.y())); @@ -89,7 +89,7 @@ void Screen::drawTetragon(const Point4D &p1, const Point4D &p2, const Point4D &p _window->draw(polygon); } -void Screen::drawText(const std::string& string, const Point4D &position, int size, sf::Color color) { +void Screen::drawText(const std::string& string, const Vec2D &position, int size, sf::Color color) { sf::Text text; text.setFont(*ResourceManager::loadFont("engine/fonts/Roboto-Medium.ttf")); diff --git a/engine/Screen.h b/engine/Screen.h index 777487f..55aa506 100644 --- a/engine/Screen.h +++ b/engine/Screen.h @@ -33,8 +33,8 @@ public: bool hasFocus() const { return _window->hasFocus(); } void drawTriangle(const Triangle& triangle); - void drawTetragon(const Point4D& p1, const Point4D& p2, const Point4D& p3, const Point4D& p4, sf::Color color); - void drawText(const std::string& string, const Point4D& position, int size, sf::Color color); + void drawTetragon(const Vec2D& p1, const Vec2D& p2, const Vec2D& p3, const Vec2D& p4, sf::Color color); + void drawText(const std::string& string, const Vec2D& position, int size, sf::Color color); void drawText(const sf::Text& text); void drawSprite(const sf::Sprite& sprite); diff --git a/engine/Triangle.cpp b/engine/Triangle.cpp index 5cad1ba..1ad2c9f 100644 --- a/engine/Triangle.cpp +++ b/engine/Triangle.cpp @@ -5,53 +5,47 @@ #include "Triangle.h" Triangle::Triangle () { - _p[0] = Point4D{0, 0, 0, 1}; - _p[1] = Point4D{0, 0, 0, 1}; - _p[2] = Point4D{0, 0, 0, 1}; + _points.emplace_back(Point4D(0, 0, 0, 1)); + _points.emplace_back(Point4D(0, 0, 0, 1)); + _points.emplace_back(Point4D(0, 0, 0, 1)); } -Triangle::Triangle(const Point4D& p1, const Point4D& p2, const Point4D& p3, sf::Color color) { - _p[0] = p1; - _p[1] = p2; - _p[2] = p3; - _color = color; +Triangle::Triangle(const Point4D& p1, const Point4D& p2, const Point4D& p3, sf::Color color) : _color(color) { + _points.emplace_back(Point4D(p1)); + _points.emplace_back(Point4D(p2)); + _points.emplace_back(Point4D(p3)); +} + +Triangle::Triangle(const Triangle &triangle) : _points(triangle._points), _color(triangle._color) { + } Triangle Triangle::operator*(const Matrix4x4 &matrix4X4) const { - Triangle res(*this); - - res._p[0] = matrix4X4 * _p[0]; - res._p[1] = matrix4X4 * _p[1]; - res._p[2] = matrix4X4 * _p[2]; - - return res; + return Triangle(matrix4X4 * _points[0], matrix4X4 * _points[1], matrix4X4 * _points[2], _color); } -Point4D Triangle::norm() const { +Vec3D Triangle::norm() const { - Point4D v1 = _p[1] - _p[0]; - Point4D v2 = _p[2] - _p[0]; + Vec3D v1 = Vec3D(_points[1] - _points[0]); + Vec3D v2 = Vec3D(_points[2] - _points[0]); + Vec3D crossProduct = v1.cross(v2); - return v1.cross3D(v2).normalized(); + if(crossProduct.sqrAbs() > Consts::EPS) + return crossProduct.normalized(); + else + return Vec3D(0); } Point4D Triangle::operator[](int i) const { - return _p[i]; + return _points[i]; } -Triangle::Triangle(const Triangle &triangle) { - _color = triangle._color; - _p[0] = triangle[0]; - _p[1] = triangle[1]; - _p[2] = triangle[2]; -} +bool Triangle::isPointInside(const Vec3D &point) const { + Vec3D triangleNorm = norm(); -bool Triangle::isPointInside(const Point4D &point) const { - Point4D triangleNorm = norm(); - - double dot1 = (point - _p[0]).cross3D(_p[1] - _p[0]).dot(triangleNorm); - double dot2 = (point - _p[1]).cross3D(_p[2] - _p[1]).dot(triangleNorm); - double dot3 = (point - _p[2]).cross3D(_p[0] - _p[2]).dot(triangleNorm); + double dot1 = (point - Vec3D(_points[0])).cross(Vec3D(_points[1] - _points[0])).dot(triangleNorm); + double dot2 = (point - Vec3D(_points[1])).cross(Vec3D(_points[2] - _points[1])).dot(triangleNorm); + double dot3 = (point - Vec3D(_points[2])).cross(Vec3D(_points[0] - _points[2])).dot(triangleNorm); if((dot1 >= 0 && dot2 >= 0 && dot3 >= 0) || (dot1 <= 0 && dot2 <= 0 && dot3 <= 0)) return true; diff --git a/engine/Triangle.h b/engine/Triangle.h index a5580dd..545ea2b 100644 --- a/engine/Triangle.h +++ b/engine/Triangle.h @@ -5,30 +5,32 @@ #ifndef ENGINE_TRIANGLE_H #define ENGINE_TRIANGLE_H -#include "utils/Point4D.h" -#include "utils/Matrix4x4.h" +#include "Point4D.h" +#include "Vec3D.h" +#include "Matrix4x4.h" #include class Triangle { private: sf::Color _color; - Point4D _p[3]; - + std::vector _points; public: Triangle (); Triangle (const Triangle& triangle); Triangle (const Point4D& p1, const Point4D& p2, const Point4D& p3, sf::Color color = {0, 0, 0}); + Triangle& operator=(const Triangle&) = delete; [[nodiscard]] Point4D operator[] (int i) const; - [[nodiscard]] Point4D norm() const; + [[nodiscard]] Vec3D norm() const; // Operations with Matrix4x4 [[nodiscard]] Triangle operator*(const Matrix4x4& matrix4X4) const; - [[nodiscard]] bool isPointInside(const Point4D& point) const; + [[nodiscard]] bool isPointInside(const Vec3D& point) const; [[nodiscard]] sf::Color color() const { return _color; } + }; diff --git a/engine/Vec2D.cpp b/engine/Vec2D.cpp new file mode 100644 index 0000000..7d50bf0 --- /dev/null +++ b/engine/Vec2D.cpp @@ -0,0 +1,71 @@ +// +// Created by Иван Ильин on 10.10.2021. +// + +#include +#include "Vec2D.h" + +Vec2D::Vec2D(const Vec2D &vec) { + _arr_point[0] = vec.x(); + _arr_point[1] = vec.y(); +} + +Vec2D::Vec2D (double x, double y) { + _arr_point[0] = x; + _arr_point[1] = y; +} + +Vec2D::Vec2D(const Point4D &point4D) { + _arr_point[0] = point4D.x(); + _arr_point[1] = point4D.y(); +} + +Vec2D Vec2D::operator-() const { + return Vec2D(-x(), -y()); +} + +bool Vec2D::operator==(const Vec2D& vec) const { + return (*this - vec).sqrAbs() < Consts::EPS; +} +bool Vec2D::operator!=(const Vec2D& vec) const { + return !(*this == vec); +} + +Vec2D Vec2D::operator+(const Vec2D& vec) const { + return Vec2D(x()+vec.x(), y()+vec.y()); +} +Vec2D Vec2D::operator-(const Vec2D& vec) const { + return Vec2D(*this) + -vec; +} + +Vec2D Vec2D::operator*(double number) const { + return Vec2D(x()*number, y()*number); +} + +Vec2D Vec2D::operator/(double number) const { + if(std::abs(number) > Consts::EPS) + return Vec2D(*this)*(1.0/number); + else + throw std::domain_error{"Vec2D::operator/(double number): division by zero"}; +} + +// Other useful methods +double Vec2D::sqrAbs() const { + return x()*x() + y()*y(); +} + +double Vec2D::abs() const { + return sqrt(sqrAbs()); +} + +Vec2D Vec2D::normalized() const { + double vecAbs = abs(); + if(vecAbs > Consts::EPS) + return Vec2D(*this)/abs(); + else + return Vec2D(0); +} + +double Vec2D::dot(const Vec2D& vec) const { + return vec.x() * x() + vec.y() * y(); +} diff --git a/engine/Vec2D.h b/engine/Vec2D.h new file mode 100644 index 0000000..04100ab --- /dev/null +++ b/engine/Vec2D.h @@ -0,0 +1,48 @@ +// +// Created by Иван Ильин on 10.10.2021. +// + +#ifndef SHOOTER_VEC2D_H +#define SHOOTER_VEC2D_H + + +#include +#include "Point4D.h" + +class Vec2D { +private: + std::array _arr_point{}; + +public: + Vec2D () = default; + Vec2D (const Vec2D& vec); + Vec2D (const Point4D& point4D); + explicit Vec2D (double x, double y = 0.0); + Vec2D& operator=(const Vec2D&) = delete; + + [[nodiscard]] double x() const { return _arr_point[0]; } + [[nodiscard]] double y() const { return _arr_point[1]; } + + [[nodiscard]] Vec2D operator-() const; + + // Boolean operations + bool operator==(const Vec2D& vec) const; + bool operator!=(const Vec2D& vec) const; + + [[nodiscard]] Vec2D operator+(const Vec2D& vec) const; + [[nodiscard]] Vec2D operator-(const Vec2D& vec) const; + + [[nodiscard]] double dot(const Vec2D& vec) const; // Returns dot product + + // Operations with numbers + [[nodiscard]] Vec2D operator*(double number) const; + [[nodiscard]] Vec2D operator/(double number) const; + + // Other useful methods + [[nodiscard]] double sqrAbs() const; // Returns squared vector length + [[nodiscard]] double abs() const; // Returns vector length + [[nodiscard]] Vec2D normalized() const; // Returns normalized vector without changing +}; + + +#endif //SHOOTER_VEC2D_H diff --git a/engine/Vec3D.cpp b/engine/Vec3D.cpp new file mode 100644 index 0000000..387a82f --- /dev/null +++ b/engine/Vec3D.cpp @@ -0,0 +1,86 @@ +// +// Created by Иван Ильин on 09.10.2021. +// + +#include "Vec3D.h" +#include +#include + +Vec3D::Vec3D(const Vec3D &vec) { + _arr_point[0] = vec.x(); + _arr_point[1] = vec.y(); + _arr_point[2] = vec.z(); +} + +Vec3D::Vec3D (const Point4D& point4D) { + _arr_point[0] = point4D.x(); + _arr_point[1] = point4D.y(); + _arr_point[2] = point4D.z(); +} + +Vec3D::Vec3D (double x, double y, double z) { + _arr_point[0] = x; + _arr_point[1] = y; + _arr_point[2] = z; +} + +Vec3D Vec3D::operator-() const { + return Vec3D(-x(), -y(), -z()); +} + +bool Vec3D::operator==(const Vec3D& vec) const { + return (*this - vec).sqrAbs() < Consts::EPS; +} +bool Vec3D::operator!=(const Vec3D& vec) const { + return !(*this == vec); +} + +// Operations with Vec3D +Vec3D Vec3D::operator+(const Vec3D& vec) const { + return Vec3D(x()+vec.x(), y()+vec.y(), z()+vec.z()); +} +Vec3D Vec3D::operator-(const Vec3D& vec) const { + return Vec3D(*this) + -vec; +} + +Vec3D Vec3D::operator*(double number) const { + return Vec3D(x()*number, y()*number, z()*number); +} + +Vec3D Vec3D::operator/(double number) const { + if(std::abs(number) > Consts::EPS) + return Vec3D(*this)*(1.0/number); + else + throw std::domain_error{"Vec3D::operator/(double number): division by zero"}; +} + +// Other useful methods +double Vec3D::sqrAbs() const { + return x()*x() + y()*y() + z()*z(); +} + +double Vec3D::abs() const { + return sqrt(sqrAbs()); +} + +Vec3D Vec3D::normalized() const { + double vecAbs = abs(); + if(vecAbs > Consts::EPS) + return Vec3D(*this)/abs(); + else + return Vec3D(0); +} + +double Vec3D::dot(const Vec3D& vec) const { + return vec.x() * x() + vec.y() * y() + vec.z() * z(); +} + +Vec3D Vec3D::cross(const Vec3D& vec) const { + return Vec3D{y() * vec.z() - vec.y() * z(), + z() * vec.x() - vec.z() * x(), + x() * vec.y() - vec.x() * y()}; +} + +Point4D Vec3D::makePoint4D() const { + return Point4D(x(), y(), z(), 1.0); +} diff --git a/engine/Vec3D.h b/engine/Vec3D.h new file mode 100644 index 0000000..d315067 --- /dev/null +++ b/engine/Vec3D.h @@ -0,0 +1,51 @@ +// +// Created by Иван Ильин on 09.10.2021. +// + +#ifndef SHOOTER_VEC3D_H +#define SHOOTER_VEC3D_H + +#include +#include "Point4D.h" + +class Vec3D { +private: + std::array _arr_point{}; + +public: + Vec3D () = default; + Vec3D (const Vec3D& vec); + explicit Vec3D (const Point4D& vec); + explicit Vec3D (double x, double y = 0.0, double z = 0.0); + Vec3D& operator=(const Vec3D&) = delete; + + [[nodiscard]] double x() const { return _arr_point[0]; } + [[nodiscard]] double y() const { return _arr_point[1]; } + [[nodiscard]] double z() const { return _arr_point[2]; } + + [[nodiscard]] Vec3D operator-() const; + + // Boolean operations + bool operator==(const Vec3D& vec) const; + bool operator!=(const Vec3D& vec) const; + + // Operations with Point4D + [[nodiscard]] Vec3D operator+(const Vec3D& vec) const; + [[nodiscard]] Vec3D operator-(const Vec3D& vec) const; + + [[nodiscard]] double dot(const Vec3D& vec) const; // Returns dot product + [[nodiscard]] Vec3D cross(const Vec3D& vec) const; // Returns cross product + + // Operations with numbers + [[nodiscard]] Vec3D operator*(double number) const; + [[nodiscard]] Vec3D operator/(double number) const; + + // Other useful methods + [[nodiscard]] double sqrAbs() const; // Returns squared vector length + [[nodiscard]] double abs() const; // Returns vector length + [[nodiscard]] Vec3D normalized() const; // Returns normalized vector without changing + [[nodiscard]] Point4D makePoint4D() const; +}; + + +#endif //SHOOTER_VEC3D_H diff --git a/engine/World.cpp b/engine/World.cpp index a2e6c38..3b2d3b2 100644 --- a/engine/World.cpp +++ b/engine/World.cpp @@ -14,36 +14,39 @@ void World::addBody(std::shared_ptr body, const string &name) { Log::log("World::addBody(): inserted body '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " tris."); } -void World::loadBody(const string &name, const string &filename, const std::string &materials, const Point4D& scale) { +void World::loadBody(const string &name, const string &filename, const std::string &materials, const Vec3D& scale) { _objects.emplace(name, std::make_shared(Mesh(filename, materials, scale))); Log::log("World::loadBody(): inserted body from " + filename + " with title '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " tris."); } -std::pair World::rayCast(const Point4D& from, const Point4D& to) { +std::pair World::rayCast(const Vec3D& from, const Vec3D& to) { - std::pair result{Point4D{0, 0,0, -1}, ""}; - double minDistance = 10000; + std::pair result; + std::unique_ptr point = std::make_unique(); + std::string name; + double minDistance = Consts::RAY_CAST_MAX_DISTANCE; for(auto& object : _objects) { if((object.first.find("Player") != std::string::npos) || (object.first.find("Bonus") != std::string::npos)) continue; for(auto& tri : object.second->triangles()) { - Triangle tri_translated(tri[0] + object.second->position(), tri[1] + object.second->position(), tri[2] + object.second->position()); + Triangle tri_translated(tri[0] + object.second->position().makePoint4D(), tri[1] + object.second->position().makePoint4D(), tri[2] + object.second->position().makePoint4D()); Plane plane(tri_translated); auto intersection = plane.intersection(from, to); double distance = (intersection.first - from).sqrAbs(); if(intersection.second > 0 && distance < minDistance && tri_translated.isPointInside(intersection.first)) { minDistance = distance; - result = {intersection.first, object.first}; + point = std::make_unique(intersection.first); + name = object.first; } } } - return result; + return {*point, name}; } -void World::loadMap(const std::string& filename, const std::string& materials, const std::string& name, const Point4D& scale) { +void World::loadMap(const std::string& filename, const std::string& materials, const std::string& name, const Vec3D& scale) { auto objs = Mesh::LoadObjects(filename, materials, scale); for(unsigned i = 0; i < objs.size(); i++) { string meshName = name + "_" + to_string(i); diff --git a/engine/World.h b/engine/World.h index bf33fa8..b1de54d 100644 --- a/engine/World.h +++ b/engine/World.h @@ -22,14 +22,14 @@ public: void addBody(std::shared_ptr mesh, const std::string& name = ""); std::shared_ptr body(const std::string& name); void removeBody(std::string name); - void loadBody(const std::string &name, const std::string &filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1}); + void loadBody(const std::string &name, const std::string &filename, const std::string &materials = "", const Vec3D& scale = Vec3D{1, 1, 1}); // rayCast returns pair of Point4D and std::string: - // 1) Point4D is point of collision (the last coordinate is -1 if there are no collisions) + // 1) Point4D is point of collision // 2) std::string - title of the object - std::pair rayCast(const Point4D& from, const Point4D& to); + std::pair rayCast(const Vec3D& from, const Vec3D& to); - void loadMap(const std::string& filename, const std::string& materials, const std::string& name = "map", const Point4D & scale = Point4D{1, 1, 1}); + void loadMap(const std::string& filename, const std::string& materials, const std::string& name = "map", const Vec3D & scale = Vec3D{1, 1, 1}); }; diff --git a/engine/animation/ARotate.h b/engine/animation/ARotate.h index 3cd8b50..84335d1 100644 --- a/engine/animation/ARotate.h +++ b/engine/animation/ARotate.h @@ -12,15 +12,13 @@ class ARotate : public Animation { private: std::shared_ptr _object; - Point4D value; + Vec3D value; public: - ARotate(std::shared_ptr object, const Point4D& r, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + ARotate(std::shared_ptr object, const Vec3D& r, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) : value(r) { _object = object; _duration = duration; _looped = looped; _intType = interpolationType; - - value = r; } bool update() override { diff --git a/engine/animation/AScale.h b/engine/animation/AScale.h index 37f11ec..8cf528f 100644 --- a/engine/animation/AScale.h +++ b/engine/animation/AScale.h @@ -13,17 +13,15 @@ class AScale : public Animation { private: std::shared_ptr _mesh; - Point4D value; + Vec3D value; std::vector triangles{}; public: - AScale(std::shared_ptr mesh, const Point4D &s, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + AScale(std::shared_ptr mesh, const Vec3D &s, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) : value(s) { _mesh = mesh; _duration = duration; _looped = looped; _intType = interpolationType; _waitFor = true; - - value = s; } bool update() override { diff --git a/engine/animation/ATranslate.h b/engine/animation/ATranslate.h index 4131fc1..17f2b9d 100644 --- a/engine/animation/ATranslate.h +++ b/engine/animation/ATranslate.h @@ -12,15 +12,13 @@ class ATranslate : public Animation { private: std::shared_ptr _object; - Point4D value; + Vec3D value; public: - ATranslate(std::shared_ptr object, const Point4D& t, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + ATranslate(std::shared_ptr object, const Vec3D& t, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) : value(t){ _object = object; _duration = duration; _looped = looped; _intType = interpolationType; - - value = t; } bool update() override { diff --git a/engine/animation/ATranslateToPoint.h b/engine/animation/ATranslateToPoint.h index a2518df..4ea0a41 100644 --- a/engine/animation/ATranslateToPoint.h +++ b/engine/animation/ATranslateToPoint.h @@ -12,23 +12,21 @@ class ATranslateToPoint : public Animation { private: std::shared_ptr _object; - Point4D point; - Point4D value; + Vec3D point; + std::unique_ptr value; public: - ATranslateToPoint(std::shared_ptr object, const Point4D& p, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) { + ATranslateToPoint(std::shared_ptr object, const Vec3D& p, double duration = 1, LoopOut looped = LoopOut::None, InterpolationType interpolationType = InterpolationType::bezier) : point(p) { _object = object; _duration = duration; _looped = looped; _intType = interpolationType; - - point = p; } bool update() override { if(!_started) { - value = point - _object->position(); + value = std::make_unique(point - _object->position()); } - _object->translate(value * _dp); + _object->translate(*value * _dp); return updateState(); } diff --git a/engine/animation/Animation.cpp b/engine/animation/Animation.cpp index 9738a89..458261b 100644 --- a/engine/animation/Animation.cpp +++ b/engine/animation/Animation.cpp @@ -25,8 +25,8 @@ bool Animation::updateState() { switch (_intType) { case InterpolationType::bezier: - _p = Interpolation::Bezier(_bezier[0], _bezier[1], _time); - _dp = Interpolation::dBezier(_bezier[0], _bezier[1], _time, _dtime); + _p = Interpolation::Bezier(*_bezier[0], *_bezier[1], _time); + _dp = Interpolation::dBezier(*_bezier[0], *_bezier[1], _time, _dtime); break; case InterpolationType::bouncing: _p = Interpolation::Bouncing(_time); diff --git a/engine/animation/Animation.h b/engine/animation/Animation.h index 1bf4800..e1f4db7 100644 --- a/engine/animation/Animation.h +++ b/engine/animation/Animation.h @@ -8,6 +8,7 @@ #include "../utils/Time.h" #include "../Triangle.h" #include "Interpolation.h" +#include "../Vec2D.h" class Animation { public: @@ -37,7 +38,8 @@ protected: double _dp = 0; InterpolationType _intType = InterpolationType::bezier; - Point4D _bezier[2] = {Point4D{0.8, 0}, Point4D{0.2, 1}}; + std::unique_ptr _bezier[2] = {std::make_unique(Vec2D{0.8, 0}), + std::make_unique(Vec2D{0.2, 1})}; // If '_waitFor' == true then we need to finish all animation before starting this one. (for example for a_wait() or a_scale()) bool _waitFor = false; @@ -47,7 +49,10 @@ public: Animation() = default; virtual ~Animation() = default; - void setBezierParams(const Point4D& p1, const Point4D& p2) { _bezier[0] = p1; _bezier[1] = p2; } + void setBezierPoints(const Vec2D& p1, const Vec2D& p2) { + _bezier[0] = std::make_unique(p1); + _bezier[1] = std::make_unique(p2); + } [[nodiscard]] bool waitFor() const { return _waitFor; } diff --git a/engine/animation/Interpolation.h b/engine/animation/Interpolation.h index 549fe3e..90ce54c 100644 --- a/engine/animation/Interpolation.h +++ b/engine/animation/Interpolation.h @@ -5,7 +5,7 @@ #ifndef ENGINE_INTERPOLATION_H #define ENGINE_INTERPOLATION_H -#include "../utils/Point4D.h" +#include "../Vec2D.h" #include #include "../Consts.h" @@ -13,12 +13,12 @@ namespace Interpolation { static double Linear(double t); static double Cos(double t); - static double Bezier(const Point4D& p1, const Point4D& p2, double t); + static double Bezier(const Vec2D& p1, const Vec2D& p2, double t); static double Bouncing(double t); static double dLinear(double t, double dt); static double dCos(double t, double dt); - static double dBezier(const Point4D& p1, const Point4D& p2, double t, double dt); + static double dBezier(const Vec2D& p1, const Vec2D& p2, double t, double dt); static double dBouncing(double t, double dt); }; @@ -32,11 +32,11 @@ double Interpolation::Cos(double t) { return 0.5*(1 - cos(Consts::PI*Interpolation::Linear(t))); } -double Interpolation::Bezier(const Point4D &p1, const Point4D &p2, double t) { +double Interpolation::Bezier(const Vec2D &p1, const Vec2D &p2, double t) { t = Interpolation::Linear(t); - double h = 0.000001; - double eps = 0.000001; + double h = Consts::EPS; + double eps = Consts::EPS; // We are trying to find 's' when px = t auto f = [=](double s){ @@ -77,7 +77,7 @@ double Interpolation::dCos(double t, double dt) { return 0.5*Consts::PI*sin(Consts::PI*t)*dt; } -double Interpolation::dBezier(const Point4D &p1, const Point4D &p2, double t, double dt) { +double Interpolation::dBezier(const Vec2D &p1, const Vec2D &p2, double t, double dt) { return Interpolation::Bezier(p1, p2, t + dt) - Interpolation::Bezier(p1, p2, t); } diff --git a/engine/gui/Window.cpp b/engine/gui/Window.cpp index bae9861..a250850 100644 --- a/engine/gui/Window.cpp +++ b/engine/gui/Window.cpp @@ -19,8 +19,8 @@ void Window::update() { _screen->setTitle(_name); _screen->drawSprite(_back); - Point4D mousePos = _mouse->getMousePosition(); - Point4D dMousePos = mousePos - _prevMousePosition; + Vec2D mousePos = _mouse->getMousePosition(); + Vec2D dMousePos = mousePos - *_prevMousePosition; _back.setPosition(_back.getPosition() - sf::Vector2f((float)(dMousePos.x() / 30), (float)(dMousePos.y() / 30))); bool isPressed = _mouse->isButtonTapped(sf::Mouse::Left); @@ -40,7 +40,7 @@ void Window::update() { } } - _prevMousePosition = mousePos; + _prevMousePosition = std::make_unique(mousePos); } void Window::setBackgroundTexture(const std::string &texture, double sx, double sy, int w, int h) { diff --git a/engine/gui/Window.h b/engine/gui/Window.h index 16f6535..7592e10 100644 --- a/engine/gui/Window.h +++ b/engine/gui/Window.h @@ -20,7 +20,7 @@ private: sf::Sprite _back; - Point4D _prevMousePosition; + std::unique_ptr _prevMousePosition = std::make_unique(Vec2D{0, 0}); std::shared_ptr _screen; std::shared_ptr _mouse; diff --git a/engine/network/ClientUDP.cpp b/engine/network/ClientUDP.cpp index 1ea7ba9..20fd51a 100644 --- a/engine/network/ClientUDP.cpp +++ b/engine/network/ClientUDP.cpp @@ -9,7 +9,7 @@ #include #include "../utils/Log.h" -ClientUDP::ClientUDP() : _lastBroadcast(std::numeric_limits::min()), _working(false) +ClientUDP::ClientUDP() : _lastBroadcast(-std::numeric_limits::max()), _working(false) { _socket.setTimeoutCallback(std::bind(&ClientUDP::timeout, this, std::placeholders::_1)); } diff --git a/engine/network/ReliableMsg.cpp b/engine/network/ReliableMsg.cpp index 574b6cf..e52e366 100644 --- a/engine/network/ReliableMsg.cpp +++ b/engine/network/ReliableMsg.cpp @@ -7,7 +7,7 @@ #include "../utils/Time.h" #include "config.h" -ReliableMsg::ReliableMsg(sf::Packet& packet, sf::IpAddress address, sf::Uint16 port) : packet(packet), address(address), port(port), lastTry(std::numeric_limits::min()), firstTry(Time::time()) {} +ReliableMsg::ReliableMsg(sf::Packet& packet, sf::IpAddress address, sf::Uint16 port) : packet(packet), address(address), port(port), lastTry(-std::numeric_limits::max()), firstTry(Time::time()) {} ReliableMsg::ReliableMsg(const ReliableMsg& msg) : packet(msg.packet), address(msg.address), port(msg.port), lastTry(msg.lastTry), firstTry(msg.firstTry) {} bool ReliableMsg::trySend(sf::UdpSocket& socket) diff --git a/engine/network/ServerUDP.cpp b/engine/network/ServerUDP.cpp index f794e2b..3c1afae 100644 --- a/engine/network/ServerUDP.cpp +++ b/engine/network/ServerUDP.cpp @@ -9,7 +9,7 @@ #include "../utils/Log.h" #include -ServerUDP::ServerUDP() : _lastBroadcast(std::numeric_limits::min()), _working(false) +ServerUDP::ServerUDP() : _lastBroadcast(-std::numeric_limits::max()), _working(false) { _socket.setTimeoutCallback(std::bind(&ServerUDP::timeout, this, std::placeholders::_1)); } diff --git a/engine/physics/RigidBody.cpp b/engine/physics/RigidBody.cpp index 2312b85..4bb3351 100644 --- a/engine/physics/RigidBody.cpp +++ b/engine/physics/RigidBody.cpp @@ -9,167 +9,171 @@ #include #include -Point4D RigidBody::_findFurthestPoint(const Point4D& direction) { - Point4D maxPoint = {}; - auto maxDistance = (double)-INFINITY; +Vec3D RigidBody::_findFurthestPoint(const Vec3D& direction) { + std::unique_ptr maxPoint = std::make_unique(Vec3D{0, 0, 0}); + auto maxDistance = -std::numeric_limits::max(); for(auto& tri : triangles()){ for(int i = 0; i < 3; i++){ - Point4D point = tri[i]; - - point = point + position(); + Vec3D point = Vec3D(tri[i] + position().makePoint4D()); double distance = point.dot(direction); if(distance > maxDistance) { maxDistance = distance; - maxPoint = point; + maxPoint = std::make_unique(point); } } } - return maxPoint; + return *maxPoint; } -Point4D RigidBody::_support(std::shared_ptr obj, const Point4D& direction) { - Point4D p1 = _findFurthestPoint(direction); - Point4D p2 = obj->_findFurthestPoint(-direction); +Vec3D RigidBody::_support(std::shared_ptr obj, const Vec3D& direction) { + Vec3D p1 = _findFurthestPoint(direction); + Vec3D p2 = obj->_findFurthestPoint(-direction); return p1 - p2; } -bool RigidBody::_nextSimplex(Simplex &points, Point4D &direction) { - switch (points.size()) { - case 2: return _line(points, direction); - case 3: return _triangle(points, direction); - case 4: return _tetrahedron(points, direction); - } +NextSimplex RigidBody::_nextSimplex(const Simplex &points) { + switch (points.type()) { + case SimplexType::Line: return _lineCase(points); + case SimplexType::Triangle: return _triangleCase(points); + case SimplexType::Tetrahedron: return _tetrahedronCase(points); - // never should be here - return false; + default: throw std::logic_error{"RigidBody::_nextSimplex: simplex is not Line, Triangle or Tetrahedron"}; + } } -bool RigidBody::_line(Simplex& points, Point4D& direction) { - Point4D a = points[0]; - Point4D b = points[1]; +NextSimplex RigidBody::_lineCase(const Simplex& points) { + std::unique_ptr newPoints = std::make_unique(points); + std::unique_ptr newDirection; - Point4D ab = b - a; - Point4D ao = - a; + Vec3D a = points[0]; + Vec3D b = points[1]; + + Vec3D ab = b - a; + Vec3D ao = - a; if (ab.dot(ao) > 0) { - direction = ab.cross3D(ao).cross3D(ab); + newDirection = std::make_unique(ab.cross(ao).cross(ab)); } else { - points = { a }; - direction = ao; + newPoints = std::make_unique(Simplex{a}); + newDirection = std::make_unique(ao); } - return false; + return NextSimplex{*newPoints, *newDirection, false}; } -bool RigidBody::_triangle(Simplex &points, Point4D &direction) { - Point4D a = points[0]; - Point4D b = points[1]; - Point4D c = points[2]; +NextSimplex RigidBody::_triangleCase(const Simplex &points) { + std::unique_ptr newPoints = std::make_unique(points); + std::unique_ptr newDirection; - Point4D ab = b - a; - Point4D ac = c - a; - Point4D ao = - a; + Vec3D a = points[0]; + Vec3D b = points[1]; + Vec3D c = points[2]; - Point4D abc = ab.cross3D(ac); + Vec3D ab = b - a; + Vec3D ac = c - a; + Vec3D ao = - a; - if (abc.cross3D(ac).dot(ao) > 0) { + Vec3D abc = ab.cross(ac); + + if (abc.cross(ac).dot(ao) > 0) { if (ac.dot(ao) > 0) { - points = { a, c }; - direction = ac.cross3D(ao).cross3D(ac); + newPoints = std::make_unique(Simplex{ a, c }); + newDirection = std::make_unique(ac.cross(ao).cross(ac)); } - else - { - return _line(points = { a, b }, direction); + else { + return _lineCase(Simplex { a, b }); } - } - else - { - if (ab.cross3D(abc).dot(ao) > 0) { - return _line(points = { a, b }, direction); + } else { + if (ab.cross(abc).dot(ao) > 0) { + return _lineCase(Simplex { a, b }); } - else - { + else { if (abc.dot(ao) > 0) { - direction = abc; + newDirection = std::make_unique(abc); } else { - points = { a, c, b }; - direction = -abc; + newPoints = std::make_unique(Simplex{ a, c, b }); + newDirection = std::make_unique(-abc); } } } - return false; + return NextSimplex{*newPoints, *newDirection, false}; } -bool RigidBody::_tetrahedron(Simplex &points, Point4D &direction) { - Point4D a = points[0]; - Point4D b = points[1]; - Point4D c = points[2]; - Point4D d = points[3]; +NextSimplex RigidBody::_tetrahedronCase(const Simplex &points) { + Vec3D a = points[0]; + Vec3D b = points[1]; + Vec3D c = points[2]; + Vec3D d = points[3]; - Point4D ab = b - a; - Point4D ac = c - a; - Point4D ad = d - a; - Point4D ao = - a; + Vec3D ab = b - a; + Vec3D ac = c - a; + Vec3D ad = d - a; + Vec3D ao = - a; - Point4D abc = ab.cross3D(ac); - Point4D acd = ac.cross3D(ad); - Point4D adb = ad.cross3D(ab); + Vec3D abc = ab.cross(ac); + Vec3D acd = ac.cross(ad); + Vec3D adb = ad.cross(ab); if (abc.dot(ao) > 0) { - return _triangle(points = { a, b, c }, direction); + return _triangleCase(Simplex{ a, b, c }); } if (acd.dot(ao) > 0) { - return _triangle(points = { a, c, d }, direction); + return _triangleCase(Simplex{ a, c, d }); } if (adb.dot(ao) > 0) { - return _triangle(points = { a, d, b }, direction); + return _triangleCase(Simplex{ a, d, b }); } - return true; + return NextSimplex{points, Vec3D(), true}; } std::pair RigidBody::checkGJKCollision(std::shared_ptr obj) { // Get initial support point in any direction - Point4D support = _support(obj, Point4D{1, 0, 0}); + std::unique_ptr support = std::make_unique(_support(obj, Vec3D{1, 0, 0})); // Simplex is an array of points, max count is 4 - Simplex points; - points.push_front(support); + std::unique_ptr points = std::make_unique(); + points->push_front(*support); // New direction is towards the origin - Point4D direction = -support; + std::unique_ptr direction = std::make_unique(-*support); int iterations = 0; - while (iterations < 50) { - support = _support(obj, direction); + while (iterations < Consts::GJK_MAX_ITERATIONS) { + support = std::make_unique(_support(obj, *direction)); - if (support.dot(direction) <= 0) - return std::make_pair(false, points); // no collision + if (support->dot(*direction) <= 0) + return std::make_pair(false, *points); // no collision - points.push_front(support); + points->push_front(*support); - if (_nextSimplex(points, direction)) { + NextSimplex nextSimplex = _nextSimplex(*points); + + direction = std::make_unique(nextSimplex.newDirection); + points = std::make_unique(nextSimplex.newSimplex); + + if (nextSimplex.finishSearching) { if(obj->isCollider()) _inCollision = true; - return std::make_pair(true, points); + return std::make_pair(true, *points); } iterations++; } - return std::make_pair(false, points); // no collision + return std::make_pair(false, *points); // no collision } CollisionPoint RigidBody::EPA(const Simplex& simplex, std::shared_ptr obj) { - std::vector polytope(simplex.begin(), simplex.end()); + std::vector polytope(simplex.begin(), simplex.end()); std::vector faces = { 0, 1, 2, 0, 3, 1, @@ -178,41 +182,39 @@ CollisionPoint RigidBody::EPA(const Simplex& simplex, std::shared_ptr }; // list: vector4(normal, distance), index: min distance - auto [normals, minFace] = _getFaceNormals(polytope, faces); + auto [normals, minFace] = std::move(_getFaceNormals(polytope, faces)); - Point4D minNormal; - double minDistance = INFINITY; + std::shared_ptr minNormal{}; + double minDistance = std::numeric_limits::max(); int iterations = 0; - while ((minDistance == INFINITY) && (iterations < 50)) { - minNormal = Point4D{normals[minFace].x(), normals[minFace].y(), normals[minFace].z()}; - minDistance = normals[minFace].w(); + while ((minDistance == std::numeric_limits::max()) && (iterations < Consts::GJK_MAX_ITERATIONS)) { + minNormal = std::make_shared(normals[minFace]->normal); + minDistance = normals[minFace]->distance; - Point4D support = _support(obj, minNormal); - double sDistance = minNormal.dot(support); + Vec3D support = _support(obj, *minNormal); + double sDistance = minNormal->dot(support); - if (std::abs(sDistance - minDistance) > 0.0001) { - minDistance = INFINITY; + if (std::abs(sDistance - minDistance) > Consts::EPA_EPS) { + minDistance = std::numeric_limits::max(); std::vector> uniqueEdges; for (size_t i = 0; i < normals.size(); i++) { - if (normals[i].dot(support) > 0) { + if (normals[i]->normal.dot(support) > 0) { size_t f = i * 3; - _addIfUniqueEdge(uniqueEdges, faces, f, f + 1); - _addIfUniqueEdge(uniqueEdges, faces, f + 1, f + 2); - _addIfUniqueEdge(uniqueEdges, faces, f + 2, f); + uniqueEdges = _addIfUniqueEdge(uniqueEdges, faces, f + 0, f + 1); + uniqueEdges = _addIfUniqueEdge(uniqueEdges, faces, f + 1, f + 2); + uniqueEdges = _addIfUniqueEdge(uniqueEdges, faces, f + 2, f + 0); - faces[f + 2] = faces.back(); faces.pop_back(); - faces[f + 1] = faces.back(); faces.pop_back(); - faces[f ] = faces.back(); faces.pop_back(); - - normals[i] = normals.back(); normals.pop_back(); - - i--; + faces.erase(faces.begin() + f); + faces.erase(faces.begin() + f); + faces.erase(faces.begin() + f); + normals.erase(normals.begin() + i--); } } + std::vector newFaces; for (auto [edgeIndex1, edgeIndex2] : uniqueEdges) { newFaces.push_back(edgeIndex1); @@ -227,15 +229,15 @@ CollisionPoint RigidBody::EPA(const Simplex& simplex, std::shared_ptr if(newNormals.empty()) break; - double oldMinDistance = INFINITY; + double oldMinDistance = std::numeric_limits::max(); for (size_t i = 0; i < normals.size(); i++) { - if (normals[i].w() < oldMinDistance) { - oldMinDistance = normals[i].w(); + if (normals[i]->distance < oldMinDistance) { + oldMinDistance = normals[i]->distance; minFace = i; } } - if (newNormals[newMinFace].w() < oldMinDistance) { + if (newNormals[newMinFace]->distance < oldMinDistance) { minFace = newMinFace + normals.size(); } @@ -244,79 +246,80 @@ CollisionPoint RigidBody::EPA(const Simplex& simplex, std::shared_ptr } iterations++; } - CollisionPoint point; - - point.normal = minNormal; - point.depth = minDistance + 0.0001; - point.hasCollision = minDistance < INFINITY; _collisionNormal = minNormal; - - return point; + return CollisionPoint{*minNormal, minDistance + Consts::EPA_EPS, minDistance < std::numeric_limits::max()}; } -std::pair, size_t> RigidBody::_getFaceNormals(const std::vector& polytope, const std::vector& faces) { - std::vector normals; - size_t minTriangle = 0; - double minDistance = INFINITY; +std::pair>, size_t> RigidBody::_getFaceNormals(const std::vector& polytope, const std::vector& faces) { + std::vector> normals; + size_t nearestFaceIndex = 0; + + double minDistance = std::numeric_limits::max(); for (size_t i = 0; i < faces.size(); i += 3) { - Point4D a = polytope[faces[i ]]; - Point4D b = polytope[faces[i + 1]]; - Point4D c = polytope[faces[i + 2]]; + Vec3D a = polytope[faces[i + 0]]; + Vec3D b = polytope[faces[i + 1]]; + Vec3D c = polytope[faces[i + 2]]; - Point4D normal = (b - a).cross3D(c - a).normalized(); - double distance = normal.dot(a); + std::shared_ptr normal = std::make_shared((b - a).cross(c - a).normalized()); + if(normal->sqrAbs() < Consts::EPS) + continue; + + double distance = normal->dot(a); if (distance < 0) { - normal = -normal; + normal = std::make_unique(-*normal); distance *= -1; } - normal = Point4D{normal.x(), normal.y(), normal.z(), distance}; - normals.emplace_back(normal); + normal = std::make_shared(Vec3D{normal->x(), normal->y(), normal->z()}); + normals.emplace_back(std::make_shared(FaceNormal{*normal, distance})); if (distance < minDistance) { - minTriangle = i / 3; + nearestFaceIndex = i / 3; minDistance = distance; } } - return { normals, minTriangle }; + return {normals, nearestFaceIndex}; } -void RigidBody::_addIfUniqueEdge(std::vector>& edges, const std::vector& faces, size_t a, size_t b) { +std::vector> RigidBody::_addIfUniqueEdge(const std::vector>& edges, const std::vector& faces, size_t a, size_t b) { - auto reverse = std::find( // 0--<--3 - edges.begin(), // / \ B / A: 2-0 - edges.end(), // / A \ / B: 0-2 - std::make_pair(faces[b], faces[a]) // 1-->--2 - ); + std::vector> newEdges = edges; - if (reverse != edges.end()) { - edges.erase(reverse); + // We are interested in reversed edge + // 0--<--3 + // / \ B / A: 2-0 + // / A \ / B: 0-2 + // 1-->--2 + auto reverse = std::find(newEdges.begin(), newEdges.end(), std::make_pair(faces[b], faces[a])); + + if (reverse != newEdges.end()) { + newEdges.erase(reverse); + } else { + newEdges.emplace_back(faces[a], faces[b]); } - else { - edges.emplace_back(faces[a], faces[b]); - } + return newEdges; } void RigidBody::updatePhysicsState() { - translate(_velocity * Time::deltaTime()); - _velocity = _velocity + _acceleration * Time::deltaTime(); + translate(*_velocity * Time::deltaTime()); + _velocity = std::make_unique(*_velocity + *_acceleration * Time::deltaTime()); } -void RigidBody::setVelocity(const Point4D& velocity) { - _velocity = velocity; +void RigidBody::setVelocity(const Vec3D& velocity) { + _velocity = std::make_unique(velocity); } -void RigidBody::addVelocity(const Point4D &velocity) { - _velocity = _velocity + velocity; +void RigidBody::addVelocity(const Vec3D &velocity) { + _velocity = std::make_unique(*_velocity + velocity); } -void RigidBody::setAcceleration(const Point4D& acceleration) { - _acceleration = acceleration; +void RigidBody::setAcceleration(const Vec3D& acceleration) { + _acceleration = std::make_unique(acceleration); } RigidBody::RigidBody(const Mesh &mesh) : Mesh(mesh) { diff --git a/engine/physics/RigidBody.h b/engine/physics/RigidBody.h index 13130b0..2442173 100644 --- a/engine/physics/RigidBody.h +++ b/engine/physics/RigidBody.h @@ -8,52 +8,60 @@ #include #include #include -#include "../utils/Point4D.h" #include "../Triangle.h" #include "Simplex.h" #include "../Mesh.h" struct CollisionPoint { - Point4D a; // Furthest point of a into b - Point4D b; // Furthest point of b into a - Point4D normal; // b – a normalized - double depth; // Length of b – a - bool hasCollision; + const Vec3D normal; + const double depth; + const bool hasCollision; +}; + +struct FaceNormal { + const Vec3D normal; + const double distance; +}; + +struct NextSimplex { + const Simplex newSimplex; + const Vec3D newDirection; + const bool finishSearching; }; class RigidBody : public Mesh { private: - Point4D _findFurthestPoint(const Point4D& direction); - Point4D _support(std::shared_ptr obj, const Point4D& direction); + Vec3D _findFurthestPoint(const Vec3D& direction); + Vec3D _support(std::shared_ptr obj, const Vec3D& direction); std::function)> _collisionCallBack; - static bool _nextSimplex(Simplex& points, Point4D& direction); - static bool _line(Simplex& points, Point4D& direction); - static bool _triangle(Simplex& points, Point4D& direction); - static bool _tetrahedron(Simplex& points, Point4D& direction); + static NextSimplex _nextSimplex(const Simplex& points); + static NextSimplex _lineCase(const Simplex& points); + static NextSimplex _triangleCase(const Simplex& points); + static NextSimplex _tetrahedronCase(const Simplex& points); - static std::pair, size_t> _getFaceNormals(const std::vector& polytope, const std::vector& faces); - static void _addIfUniqueEdge(std::vector>& edges, const std::vector& faces, size_t a, size_t b); + static std::pair>, size_t> _getFaceNormals(const std::vector& polytope, const std::vector& faces); + static std::vector> _addIfUniqueEdge(const std::vector>& edges, const std::vector& faces, size_t a, size_t b); protected: - Point4D _velocity; - Point4D _acceleration; + std::unique_ptr _velocity = std::make_unique(Vec3D{0, 0, 0});; + std::unique_ptr _acceleration = std::make_unique(Vec3D{0, 0, 0});; bool _collision = false; bool _isCollider = true; bool _inCollision = false; - Point4D _collisionNormal; + std::shared_ptr _collisionNormal = std::make_unique(Vec3D{0, 0, 0});; public: RigidBody() = default; explicit RigidBody(const Mesh& mesh); - std::pair checkGJKCollision(std::shared_ptr obj); - CollisionPoint EPA(const Simplex& simplex, std::shared_ptr obj); + [[nodiscard]] std::pair checkGJKCollision(std::shared_ptr obj); + [[nodiscard]] CollisionPoint EPA(const Simplex& simplex, std::shared_ptr obj); - [[nodiscard]] Point4D collisionNormal() const { return _collisionNormal; } + [[nodiscard]] Vec3D collisionNormal() const { return *_collisionNormal; } [[nodiscard]] bool isCollision() const { return _collision; } [[nodiscard]] bool inCollision() const {return _inCollision; } @@ -64,12 +72,12 @@ public: void updatePhysicsState(); - void setVelocity(const Point4D& velocity); - void addVelocity(const Point4D& velocity); - void setAcceleration(const Point4D& acceleration); + void setVelocity(const Vec3D& velocity); + void addVelocity(const Vec3D& velocity); + void setAcceleration(const Vec3D& acceleration); - [[nodiscard]] Point4D velocity() const { return _velocity; } - [[nodiscard]] Point4D acceleration() const { return _acceleration; } + [[nodiscard]] Vec3D velocity() const { return *_velocity; } + [[nodiscard]] Vec3D acceleration() const { return *_acceleration; } [[nodiscard]] const std::function)>& collisionCallBack() const { return _collisionCallBack; } void setCollisionCallBack(const std::function)>& f) { _collisionCallBack = f; } diff --git a/engine/physics/Simplex.h b/engine/physics/Simplex.h index 3049af4..cae6ce7 100644 --- a/engine/physics/Simplex.h +++ b/engine/physics/Simplex.h @@ -5,34 +5,45 @@ #ifndef ENGINE_SIMPLEX_H #define ENGINE_SIMPLEX_H -#include "../utils/Point4D.h" +#include "../Vec3D.h" +#include + +enum class SimplexType { + Zero, + Point, + Line, + Triangle, + Tetrahedron +}; struct Simplex { private: - std::array m_points{}; - unsigned m_size = 0; + std::deque _points{}; public: Simplex() = default; - Simplex& operator=(std::initializer_list list) { - for (auto v = list.begin(); v != list.end(); v++) { - m_points[std::distance(list.begin(), v)] = *v; + Simplex(std::initializer_list list) { + for (const auto & v : list) { + _points.push_back(v); + if(_points.size() > 4) + _points.pop_front(); } - m_size = list.size(); - return *this; } - void push_front(const Point4D& point) { - m_points = { point, m_points[0], m_points[1], m_points[2] }; - m_size = std::min(m_size + 1, 4u); + void push_front(const Vec3D& point) { + _points.push_front(point); + if(_points.size() > 4) + _points.pop_back(); } - Point4D& operator[](unsigned i) { return m_points[i]; } - [[nodiscard]] unsigned size() const { return m_size; } + Vec3D operator[](unsigned i) const { return _points[i]; } + [[nodiscard]] unsigned size() const { return _points.size(); } - [[nodiscard]] auto begin() const { return m_points.begin(); } - [[nodiscard]] auto end() const { return m_points.end() - (4 - m_size); } + [[nodiscard]] auto begin() const { return _points.begin(); } + [[nodiscard]] auto end() const { return _points.end(); } + + [[nodiscard]] SimplexType type() const { return static_cast(_points.size()); } }; #endif //INC_3DZAVR_SIMPLEX_H diff --git a/engine/physics/Solver.cpp b/engine/physics/Solver.cpp index e91850c..4c03cb9 100644 --- a/engine/physics/Solver.cpp +++ b/engine/physics/Solver.cpp @@ -9,14 +9,11 @@ void Solver::solveCollision(std::shared_ptr obj1, std::shared_ptrvelocity().dot(collision.normal); + Vec3D obj1_velocity_parallel = collision.normal * obj1->velocity().dot(collision.normal); + Vec3D obj1_velocity_perpendicular = obj1->velocity() - obj1_velocity_parallel; - obj1_velocity_parallel = Point4D{obj1_velocity_parallel.x(), obj1_velocity_parallel.y(), obj1_velocity_parallel.z(), 0}; - - Point4D obj1_velocity_perpendicular = obj1->velocity() - obj1_velocity_parallel; - - Point4D obj2_velocity_parallel = collision.normal * obj2->velocity().dot(collision.normal); - Point4D obj2_velocity_perpendicular = obj2->velocity() - obj2_velocity_parallel; + Vec3D obj2_velocity_parallel = collision.normal * obj2->velocity().dot(collision.normal); + Vec3D obj2_velocity_perpendicular = obj2->velocity() - obj2_velocity_parallel; if(obj1->isCollision()) { if(obj1->velocity().dot(collision.normal) > 0) { diff --git a/weapon/Ak47.cpp b/weapon/Ak47.cpp index 245ebdc..bf34126 100644 --- a/weapon/Ak47.cpp +++ b/weapon/Ak47.cpp @@ -7,7 +7,7 @@ using namespace std; -Ak47::Ak47(int ammo, const std::string& weaponName) : Weapon(weaponName, "obj/ak47.obj", "obj/ak47_mat.txt", Point4D{3, 3, 3}, Point4D{-0.8, 1.3, 0.3}, Point4D{0, Consts::PI, 0}) { +Ak47::Ak47(int ammo, const std::string& weaponName) : Weapon(weaponName, "obj/ak47.obj", "obj/ak47_mat.txt", Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) { fireSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/ak47.ogg")); reloadSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/reload_ak47.ogg")); diff --git a/weapon/Gold_Ak47.h b/weapon/Gold_Ak47.h index 8f6b5ec..28ddc60 100644 --- a/weapon/Gold_Ak47.h +++ b/weapon/Gold_Ak47.h @@ -9,7 +9,7 @@ class Gold_Ak47 : public Weapon { public: - explicit Gold_Ak47(int ammo = 200, const std::string& weaponName = "gold_ak47") : Weapon(weaponName, "obj/ak47.obj", "obj/gold_ak47_mat.txt", Point4D{3, 3, 3}, Point4D{-0.8, 1.3, 0.3}, Point4D{0, Consts::PI, 0}) { + explicit Gold_Ak47(int ammo = 200, const std::string& weaponName = "gold_ak47") : Weapon(weaponName, "obj/ak47.obj", "obj/gold_ak47_mat.txt", Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) { fireSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/ak47.ogg")); reloadSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/reload_ak47.ogg")); diff --git a/weapon/Gun.cpp b/weapon/Gun.cpp index 0704c96..3f18a88 100644 --- a/weapon/Gun.cpp +++ b/weapon/Gun.cpp @@ -7,7 +7,7 @@ using namespace std; -Gun::Gun(int ammo, const std::string& weaponName) : Weapon(weaponName, "obj/gun.obj", "obj/gun_mat.txt", Point4D{3, 3, 3}, Point4D{-0.8, 1.3, 0.3}, Point4D{0, Consts::PI, 0}) { +Gun::Gun(int ammo, const std::string& weaponName) : Weapon(weaponName, "obj/gun.obj", "obj/gun_mat.txt", Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) { fireSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/gun.ogg")); reloadSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/reload_gun.ogg")); diff --git a/weapon/Rifle.cpp b/weapon/Rifle.cpp index a104e16..862ed51 100644 --- a/weapon/Rifle.cpp +++ b/weapon/Rifle.cpp @@ -5,7 +5,7 @@ #include "../engine/ResourceManager.h" #include "Rifle.h" -Rifle::Rifle(int ammo, const std::string &weaponName) : Weapon(weaponName, "obj/rifle.obj", "obj/rifle_mat.txt", Point4D{3, 3, 3}, Point4D{-1.2, 1, 0.3}, Point4D{0, Consts::PI, 0}) { +Rifle::Rifle(int ammo, const std::string &weaponName) : Weapon(weaponName, "obj/rifle.obj", "obj/rifle_mat.txt", Vec3D{3, 3, 3}, Vec3D{-1.2, 1, 0.3}, Vec3D{0, Consts::PI, 0}) { fireSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/shotgun.ogg")); reloadSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/reload_ak47.ogg")); diff --git a/weapon/Shotgun.cpp b/weapon/Shotgun.cpp index 41792b2..8e190fa 100644 --- a/weapon/Shotgun.cpp +++ b/weapon/Shotgun.cpp @@ -9,7 +9,7 @@ using namespace std; -Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, "obj/shotgun.obj", "obj/shotgun_mat.txt", Point4D{3, 3, 3}, Point4D{-0.95, 1.3, -0.6}, Point4D{0, Consts::PI, 0}) { +Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, "obj/shotgun.obj", "obj/shotgun_mat.txt", Vec3D{3, 3, 3}, Vec3D{-0.95, 1.3, -0.6}, Vec3D{0, Consts::PI, 0}) { fireSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/shotgun.ogg")); reloadSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/reload_shotgun.ogg")); @@ -25,12 +25,12 @@ Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, " } std::map -Shotgun::processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& pos, const Point4D& direction) { +Shotgun::processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& pos, const Vec3D& direction) { std::map damagedPlayers; for(int i = 0; i < 15; i++) { //generate random vector - Point4D randV(10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX)); + Vec3D randV(10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX)); // damage player auto rayCast = rayCastFunction(pos, pos + direction * 1000 + randV); @@ -38,8 +38,8 @@ Shotgun::processFire(std::function(const Point4D damagedPlayers[rayCast.second] += _damage / (1.0 + (pos - rayCast.first).abs()); } - Point4D to = rayCast.first.w() == -1 ? pos + direction * 1000 + randV: rayCast.first; - Point4D from = position() + triangles().back()[0]; + Vec3D to = rayCast.first == Vec3D(0) ? pos + direction * 1000 + randV: rayCast.first; + Vec3D from = position() + Vec3D(triangles().back()[0]); _addTraceCallBack(from, to); } diff --git a/weapon/Shotgun.h b/weapon/Shotgun.h index ffeda22..e54d0ec 100644 --- a/weapon/Shotgun.h +++ b/weapon/Shotgun.h @@ -10,7 +10,7 @@ class Shotgun : public Weapon { public: explicit Shotgun(int ammo = 15, const std::string& weaponName = "shotgun"); - std::map processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction) override; + std::map processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) override; }; diff --git a/weapon/Weapon.cpp b/weapon/Weapon.cpp index 10bc4ac..260113c 100644 --- a/weapon/Weapon.cpp +++ b/weapon/Weapon.cpp @@ -12,7 +12,7 @@ using namespace std; -Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, const std::string& matFileName, const Point4D& scale, const Point4D& t, const Point4D& r) { +Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, const std::string& matFileName, const Vec3D& scale, const Vec3D& t, const Vec3D& r) { _name = weaponName; loadObj(objFileName, matFileName, scale); @@ -23,7 +23,7 @@ Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, co noAmmoSound.setBuffer(*ResourceManager::loadSoundBuffer("sound/weapons/no_ammo.ogg")); } -std::map Weapon::fire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction) { +std::map Weapon::fire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) { if(_clipAmmo == 0) { reload(); if(_clipAmmo == 0) @@ -58,11 +58,11 @@ void Weapon::reload() { _lastReloadTime = Time::time(); } -std::map Weapon::processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& pos, const Point4D& direction) { +std::map Weapon::processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& pos, const Vec3D& direction) { std::map damagedPlayers; //generate random vector - Point4D randV(10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX)); + Vec3D randV(10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX), 10.0*_spreading*(1.0 - 2.0*(double)rand()/RAND_MAX)); // damage player auto rayCast = rayCastFunction(pos, pos + direction * 1000 + randV); @@ -71,8 +71,8 @@ std::map Weapon::processFire(std::function _addTraceCallBack; + std::function _addTraceCallBack; - virtual std::map processFire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction); + virtual std::map processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction); public: - Weapon(const std::string& weaponName, const std::string& objFileName, const std::string& matFileName, const Point4D& scale, const Point4D& translate, const Point4D& rotate); + Weapon(const std::string& weaponName, const std::string& objFileName, const std::string& matFileName, const Vec3D& scale, const Vec3D& translate, const Vec3D& rotate); - std::map fire(std::function(const Point4D&, const Point4D&)> rayCastFunction, const Point4D& position, const Point4D& direction); + std::map fire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction); void reload(); [[nodiscard]] std::pair balance() const{ return std::make_pair(_clipAmmo, _stockAmmo); } - void setAddTraceCallBack(std::function add) { + void setAddTraceCallBack(std::function add) { _addTraceCallBack = std::move(add); }