From 6bc5c7dd1fc0840dc8b69c621f0c10a304e1a0be Mon Sep 17 00:00:00 2001 From: Vectozavr <60608292+vectozavr@users.noreply.github.com> Date: Thu, 4 Nov 2021 02:57:48 +0700 Subject: [PATCH] HitBox added. acceleration of collision detection in 20 times. --- CMakeLists.txt | 2 +- Player.cpp | 6 ++- Shooter.cpp | 6 ++- Shooter.h | 2 +- ShooterConsts.h | 2 +- Source.cpp | 2 +- engine/World.cpp | 25 ++++++------ engine/animation/AFunction.h | 2 +- engine/physics/HitBox.cpp | 76 ++++++++++++++++++++++++++++++++++++ engine/physics/HitBox.h | 26 ++++++++++++ engine/physics/RigidBody.cpp | 28 +++++++++++-- engine/physics/RigidBody.h | 17 ++++++-- 12 files changed, 168 insertions(+), 26 deletions(-) create mode 100644 engine/physics/HitBox.cpp create mode 100644 engine/physics/HitBox.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c18d8e6..67bfc6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,7 +91,7 @@ add_executable(shooter engine/network/UDPConnection.h engine/network/UDPSocket.cpp engine/network/UDPSocket.h - engine/SoundController.cpp engine/SoundController.h ShooterMsgType.h ShooterMsgType.cpp engine/animation/AAttractToPoint.h engine/animation/ARotateRelativePoint.h engine/animation/ARotateLeft.h engine/utils/Timer.cpp engine/utils/Timer.h) + engine/SoundController.cpp engine/SoundController.h ShooterMsgType.h ShooterMsgType.cpp engine/animation/AAttractToPoint.h engine/animation/ARotateRelativePoint.h engine/animation/ARotateLeft.h engine/utils/Timer.cpp engine/utils/Timer.h engine/physics/HitBox.cpp engine/physics/HitBox.h) if(APPLE OR UNIX) include_directories(/usr/local/include) diff --git a/Player.cpp b/Player.cpp index 38812e6..6b1f5a9 100644 --- a/Player.cpp +++ b/Player.cpp @@ -3,17 +3,19 @@ // #include "Player.h" + +#include #include "engine/Screen.h" #include "engine/utils/Log.h" #include "engine/animation/Timeline.h" #include "engine/animation/ARotateLeft.h" -Player::Player(ObjectNameTag name) : RigidBody(name) { - loadObj(ShooterConsts::CUBE_OBJ, Vec3D{0.5, 1.9, 0.5}); +Player::Player(ObjectNameTag name) : RigidBody(std::move(name), ShooterConsts::CUBE_OBJ,Vec3D{0.5, 1.9, 0.5}) { setAcceleration(Vec3D{0, -ShooterConsts::GRAVITY, 0}); setCollision(true); setVisible(false); + setSimpleHitBox(true); Vec3D randColor = Vec3D::Random(); setColor({static_cast(randColor.x() * 255), static_cast(randColor.y() * 255), diff --git a/Shooter.cpp b/Shooter.cpp index 11f762b..0bccd1e 100644 --- a/Shooter.cpp +++ b/Shooter.cpp @@ -300,7 +300,7 @@ void Shooter::addFireTrace(const Vec3D &from, const Vec3D &to) { std::make_shared(world->body(ObjectNameTag(traceName)), sf::Color{150, 150, 150, 0})); Timeline::animate(AnimationListTag(traceName + "_delete"), std::make_shared([this, traceName]() { removeFireTrace(ObjectNameTag(traceName)); }, 1, - 2)); + 1)); } void Shooter::removeFireTrace(const ObjectNameTag &traceName) { @@ -315,6 +315,8 @@ void Shooter::addBonus(const string &bonusName, const Vec3D &position) { world->addBody(std::make_shared(ObjectNameTag(bonusName), "obj/" + name + ".obj", Vec3D{3, 3, 3})); world->body(ObjectNameTag(bonusName))->translateToPoint(position); world->body(ObjectNameTag(bonusName))->setCollider(false); + world->body(ObjectNameTag(bonusName))->setSimpleHitBox(true); + world->body(ObjectNameTag(bonusName))->setTrigger(true); Timeline::animate(AnimationListTag(bonusName + "_rotation"), std::make_shared(world->body(ObjectNameTag(bonusName)), Vec3D{0, 2 * Consts::PI, 0}, 4, Animation::LoopOut::Continue, Animation::InterpolationType::Linear)); @@ -346,7 +348,7 @@ void Shooter::changeEnemyWeapon(const std::string &weaponName, sf::Uint16 enemyI world->body(weaponTag)->setCollider(false); world->body(weaponTag)->scale(Vec3D(3, 3, 3)); - world->body(weaponTag)->translateToPoint(head->position() - enemy->left()*2 - enemy->up()*0.5); + world->body(weaponTag)->translateToPoint(head->position() - enemy->left() * 2 - enemy->up() * 0.5); world->body(weaponTag)->rotate(Vec3D(0, Consts::PI + enemy->angle().y(), 0)); world->body(weaponTag)->rotateLeft(-head->angleLeftUpLookAt().x()); diff --git a/Shooter.h b/Shooter.h index 452e4bb..1c4f829 100644 --- a/Shooter.h +++ b/Shooter.h @@ -17,7 +17,7 @@ class Shooter final : public Engine { private: - std::shared_ptr player = std::make_shared(ObjectNameTag("Player"));; + std::shared_ptr player = std::make_shared(ObjectNameTag("Player")); std::shared_ptr playerController = std::make_shared(player, keyboard, mouse); Window mainMenu; diff --git a/ShooterConsts.h b/ShooterConsts.h index 56e23f3..ff18227 100644 --- a/ShooterConsts.h +++ b/ShooterConsts.h @@ -38,7 +38,7 @@ namespace ShooterConsts { const std::string SHOTGUN_RELOAD_SOUND = "sound/weapons/reload_shotgun.ogg"; const std::string CUBE_OBJ = "obj/cube.obj"; - const std::string MAP_OBJ = "maps/map2.obj"; + const std::string MAP_OBJ = "maps/map1.obj"; const std::string MAIN_MENU_BACK = "textures/back.png"; const std::string MAIN_MENU_GUI = "textures/gui.png"; diff --git a/Source.cpp b/Source.cpp index 372c41c..209e3f4 100644 --- a/Source.cpp +++ b/Source.cpp @@ -13,7 +13,7 @@ int main() { game.create(1280, 720, ShooterConsts::PROJECT_NAME); //game.create(1920, 1080, ShooterConsts::PROJECT_NAME, true, Consts::BACKGROUND_COLOR, sf::Style::Fullscreen); - //game.create(2048, 1152, ShooterConsts::PROJECT_NAME, true); + //game.create(2048, 1152, ShooterConsts::PROJECT_NAME, false); //game.create(3072, 1920, ShooterConsts::PROJECT_NAME, true, Consts::BACKGROUND_COLOR, sf::Style::Fullscreen); return 0; diff --git a/engine/World.cpp b/engine/World.cpp index 88a7b55..05ce512 100644 --- a/engine/World.cpp +++ b/engine/World.cpp @@ -93,7 +93,7 @@ void World::removeBody(const ObjectNameTag &tag) { } void World::checkCollision(const ObjectNameTag &tag) { - if (_objects[tag]->isCollision()) { + if (_objects[tag]->hasCollision()) { _objects[tag]->setInCollision(false); @@ -102,18 +102,21 @@ void World::checkCollision(const ObjectNameTag &tag) { ObjectNameTag name = it->first; it++; - if (name != tag) { - std::pair gjk = _objects[tag]->checkGJKCollision(obj); - if (gjk.first) { - if (obj->isCollider()) { - CollisionPoint epa = _objects[tag]->EPA(gjk.second, obj); - _objects[tag]->solveCollision(epa); - } - if (_objects[tag]->collisionCallBack() != nullptr) { - _objects[tag]->collisionCallBack()(name, obj); - } + if ((name == tag) || !(obj->isCollider() || obj->isTrigger())) { + continue; + } + + std::pair gjk = _objects[tag]->checkGJKCollision(obj); + if (gjk.first) { + if (obj->isCollider()) { + CollisionPoint epa = _objects[tag]->EPA(gjk.second, obj); + _objects[tag]->solveCollision(epa); + } + if (_objects[tag]->collisionCallBack() != nullptr) { + _objects[tag]->collisionCallBack()(name, obj); } } + } } } diff --git a/engine/animation/AFunction.h b/engine/animation/AFunction.h index e282fcc..f94d8ad 100644 --- a/engine/animation/AFunction.h +++ b/engine/animation/AFunction.h @@ -16,7 +16,7 @@ private: const std::function _callBack; void update() override { - if (_allCalls != 0 && progress() > (double) _callsCounter / _allCalls) { + if (_allCalls != 0 && progress() >= (double) (_callsCounter + 1) / _allCalls) { _callsCounter++; _callBack(); } diff --git a/engine/physics/HitBox.cpp b/engine/physics/HitBox.cpp new file mode 100644 index 0000000..54eaf72 --- /dev/null +++ b/engine/physics/HitBox.cpp @@ -0,0 +1,76 @@ +// +// Created by Иван Ильин on 04.11.2021. +// + +#include "HitBox.h" +#include "../Consts.h" + +HitBox::HitBox(const Mesh &mesh) { + for(const auto& t : mesh.triangles()) { + for(int i = 0; i < 3; i++) { + // we dont need to add the same points in hit box + _addIfUnique(Vec3D(t[i])); + } + } +} + +void HitBox::_addIfUnique(const Vec3D &point) { + bool addPoint = true; + for(const auto& p : _hitBox) { + if((p - point).sqrAbs() < Consts::EPS) { + addPoint = false; + } + } + if(addPoint) { + _hitBox.push_back(point); + } +} + +HitBox HitBox::Box(const Mesh &mesh) { + HitBox result; + + double maxX = -std::numeric_limits::max(); + double maxY = -std::numeric_limits::max(); + double maxZ = -std::numeric_limits::max(); + + double minX = std::numeric_limits::max(); + double minY = std::numeric_limits::max(); + double minZ = std::numeric_limits::max(); + + for(const auto& t : mesh.triangles()) { + for(int i = 0; i < 3; i++) { + Vec3D point = Vec3D(t[i]); + if(point.x() > maxX) { + maxX = point.x(); + } + if(point.y() > maxY) { + maxY = point.y(); + } + if(point.z() > maxZ) { + maxZ = point.z(); + } + + if(point.x() < minX) { + minX = point.x(); + } + if(point.y() < minY) { + minY = point.y(); + } + if(point.z() < minZ) { + minZ = point.z(); + } + } + } + + result._hitBox.emplace_back(minX, minY, minZ); + result._hitBox.emplace_back(minX, maxY, minZ); + result._hitBox.emplace_back(maxX, minY, minZ); + result._hitBox.emplace_back(maxX, maxY, minZ); + + result._hitBox.emplace_back(minX, minY, maxZ); + result._hitBox.emplace_back(minX, maxY, maxZ); + result._hitBox.emplace_back(maxX, minY, maxZ); + result._hitBox.emplace_back(maxX, maxY, maxZ); + + return result; +} diff --git a/engine/physics/HitBox.h b/engine/physics/HitBox.h new file mode 100644 index 0000000..d7df40c --- /dev/null +++ b/engine/physics/HitBox.h @@ -0,0 +1,26 @@ +// +// Created by Иван Ильин on 04.11.2021. +// + +#ifndef SHOOTER_HITBOX_H +#define SHOOTER_HITBOX_H + +#include "../Mesh.h" + +class HitBox { +private: + std::vector _hitBox; + + void _addIfUnique(const Vec3D& point); +public: + HitBox() = default; + explicit HitBox(const Mesh& mesh); + + std::vector::iterator begin() { return _hitBox.begin(); } + std::vector::iterator end() { return _hitBox.end(); } + + HitBox static Box(const Mesh& mesh); +}; + + +#endif //SHOOTER_HITBOX_H diff --git a/engine/physics/RigidBody.cpp b/engine/physics/RigidBody.cpp index 0428e1f..2150016 100644 --- a/engine/physics/RigidBody.cpp +++ b/engine/physics/RigidBody.cpp @@ -11,7 +11,8 @@ #include "../Consts.h" RigidBody::RigidBody(ObjectNameTag nameTag, const std::string &filename, const Vec3D &scale) : Mesh(std::move(nameTag), - filename, scale) { + filename, scale), + _hitBox(*this) { } Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) { @@ -21,6 +22,7 @@ Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) { Vec3D transformedDirection = (view() * direction).normalized(); + /* for (auto &tri : triangles()) { for (int i = 0; i < 3; i++) { Vec3D point = Vec3D(tri[i]); @@ -32,8 +34,19 @@ Vec3D RigidBody::_findFurthestPoint(const Vec3D &direction) { } } } + */ - return model()*maxPoint + position(); + for(auto & it : _hitBox) { + auto point = Vec3D(it); + double distance = point.dot(transformedDirection); + + if (distance > maxDistance) { + maxDistance = distance; + maxPoint = point; + } + } + + return model() * maxPoint + position(); } Vec3D RigidBody::_support(std::shared_ptr obj, const Vec3D &direction) { @@ -346,5 +359,14 @@ void RigidBody::setAcceleration(const Vec3D &acceleration) { _acceleration = acceleration; } -RigidBody::RigidBody(const Mesh &mesh) : Mesh(mesh) { +RigidBody::RigidBody(const Mesh &mesh) : Mesh(mesh), _hitBox(mesh) { +} + +void RigidBody::setSimpleHitBox(bool b) { + _simpleHitBox = b; + if (_simpleHitBox) { + _hitBox = HitBox::Box(*this); + } else { + _hitBox = HitBox(*this); + } } diff --git a/engine/physics/RigidBody.h b/engine/physics/RigidBody.h index ebe9909..2eace34 100644 --- a/engine/physics/RigidBody.h +++ b/engine/physics/RigidBody.h @@ -13,6 +13,7 @@ #include "../Triangle.h" #include "Simplex.h" #include "../Mesh.h" +#include "HitBox.h" struct CollisionPoint final { const Vec3D normal; @@ -35,8 +36,12 @@ private: Vec3D _velocity{0, 0, 0}; Vec3D _acceleration{0, 0, 0}; - bool _collision = false; + bool _hasCollision = false; bool _isCollider = true; + bool _isTrigger = false; + + HitBox _hitBox{}; + bool _simpleHitBox = false; bool _inCollision = false; Vec3D _collisionNormal{0, 0, 0}; @@ -78,18 +83,24 @@ public: [[nodiscard]] Vec3D collisionNormal() const { return _collisionNormal; } - [[nodiscard]] bool isCollision() const { return _collision; } + [[nodiscard]] bool hasCollision() const { return _hasCollision; } [[nodiscard]] bool inCollision() const { return _inCollision; } [[nodiscard]] bool isCollider() const { return _isCollider; } + [[nodiscard]] bool isTrigger() const { return _isTrigger; } + void setInCollision(bool c) { _inCollision = c; } - void setCollision(bool c) { _collision = c; } + void setCollision(bool c) { _hasCollision = c; } void setCollider(bool c) { _isCollider = c; } + void setSimpleHitBox(bool b); + + void setTrigger(bool t) { _isTrigger = t; } + void updatePhysicsState(); void setVelocity(const Vec3D &velocity);