2021-09-13 15:53:43 +03:00
|
|
|
//
|
|
|
|
// Created by Иван Ильин on 05.02.2021.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef ENGINE_RIGIDBODY_H
|
|
|
|
#define ENGINE_RIGIDBODY_H
|
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
#include <utility>
|
2021-09-13 15:53:43 +03:00
|
|
|
#include <vector>
|
|
|
|
#include <memory>
|
2021-10-03 08:38:10 +03:00
|
|
|
#include <functional>
|
2021-10-31 11:39:08 +03:00
|
|
|
|
2021-09-13 15:53:43 +03:00
|
|
|
#include "../Triangle.h"
|
|
|
|
#include "Simplex.h"
|
2021-10-09 13:41:12 +03:00
|
|
|
#include "../Mesh.h"
|
2021-11-03 22:57:48 +03:00
|
|
|
#include "HitBox.h"
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-17 11:41:58 +03:00
|
|
|
struct CollisionPoint final {
|
2021-10-12 17:12:47 +03:00
|
|
|
const Vec3D normal;
|
|
|
|
const double depth;
|
|
|
|
};
|
|
|
|
|
2021-10-17 11:41:58 +03:00
|
|
|
struct FaceNormal final {
|
2021-10-12 17:12:47 +03:00
|
|
|
const Vec3D normal;
|
|
|
|
const double distance;
|
|
|
|
};
|
|
|
|
|
2021-10-17 11:41:58 +03:00
|
|
|
struct NextSimplex final {
|
2021-10-12 17:12:47 +03:00
|
|
|
const Simplex newSimplex;
|
|
|
|
const Vec3D newDirection;
|
|
|
|
const bool finishSearching;
|
2021-09-13 15:53:43 +03:00
|
|
|
};
|
|
|
|
|
2021-09-19 11:25:10 +03:00
|
|
|
class RigidBody : public Mesh {
|
|
|
|
private:
|
2021-10-31 19:01:06 +03:00
|
|
|
Vec3D _velocity{0, 0, 0};
|
|
|
|
Vec3D _acceleration{0, 0, 0};
|
|
|
|
|
2021-11-03 22:57:48 +03:00
|
|
|
bool _hasCollision = false;
|
2021-10-31 19:01:06 +03:00
|
|
|
bool _isCollider = true;
|
2021-11-03 22:57:48 +03:00
|
|
|
bool _isTrigger = false;
|
|
|
|
|
|
|
|
HitBox _hitBox{};
|
2021-10-31 19:01:06 +03:00
|
|
|
|
|
|
|
bool _inCollision = false;
|
|
|
|
Vec3D _collisionNormal{0, 0, 0};
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
Vec3D _findFurthestPoint(const Vec3D &direction);
|
|
|
|
Vec3D _support(std::shared_ptr<RigidBody> obj, const Vec3D &direction);
|
|
|
|
std::function<void(const ObjectNameTag &, std::shared_ptr<RigidBody>)> _collisionCallBack;
|
|
|
|
|
|
|
|
static NextSimplex _nextSimplex(const Simplex &points);
|
|
|
|
static NextSimplex _lineCase(const Simplex &points);
|
|
|
|
static NextSimplex _triangleCase(const Simplex &points);
|
|
|
|
static NextSimplex _tetrahedronCase(const Simplex &points);
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
static std::pair<std::vector<FaceNormal>, size_t>
|
|
|
|
_getFaceNormals(const std::vector<Vec3D> &polytope, const std::vector<size_t> &faces);
|
|
|
|
|
|
|
|
static std::vector<std::pair<size_t, size_t>>
|
|
|
|
_addIfUniqueEdge(const std::vector<std::pair<size_t, size_t>> &edges, const std::vector<size_t> &faces, size_t a,
|
|
|
|
size_t b);
|
2021-09-13 15:53:43 +03:00
|
|
|
public:
|
2021-10-28 16:58:02 +03:00
|
|
|
explicit RigidBody(ObjectNameTag nameTag) : Mesh(std::move(nameTag)) {};
|
2021-10-31 11:39:08 +03:00
|
|
|
RigidBody(const RigidBody &rigidBody) = default;
|
2021-11-09 22:54:20 +03:00
|
|
|
explicit RigidBody(const Mesh &mesh, bool useSimpleBox = true);
|
|
|
|
RigidBody(ObjectNameTag nameTag, const std::string &filename, const Vec3D &scale = Vec3D{1, 1, 1}, bool useSimpleBox = true);
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-12 17:12:47 +03:00
|
|
|
[[nodiscard]] std::pair<bool, Simplex> checkGJKCollision(std::shared_ptr<RigidBody> obj);
|
2021-10-31 11:39:08 +03:00
|
|
|
[[nodiscard]] CollisionPoint EPA(const Simplex &simplex, std::shared_ptr<RigidBody> obj);
|
|
|
|
void solveCollision(const CollisionPoint &collision);
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
[[nodiscard]] Vec3D collisionNormal() const { return _collisionNormal; }
|
2021-11-03 22:57:48 +03:00
|
|
|
[[nodiscard]] bool hasCollision() const { return _hasCollision; }
|
2021-10-31 11:39:08 +03:00
|
|
|
[[nodiscard]] bool inCollision() const { return _inCollision; }
|
|
|
|
[[nodiscard]] bool isCollider() const { return _isCollider; }
|
2021-11-03 22:57:48 +03:00
|
|
|
[[nodiscard]] bool isTrigger() const { return _isTrigger; }
|
|
|
|
|
2021-09-13 15:53:43 +03:00
|
|
|
void setInCollision(bool c) { _inCollision = c; }
|
2021-11-03 22:57:48 +03:00
|
|
|
void setCollision(bool c) { _hasCollision = c; }
|
2021-09-13 15:53:43 +03:00
|
|
|
void setCollider(bool c) { _isCollider = c; }
|
2021-11-03 22:57:48 +03:00
|
|
|
void setTrigger(bool t) { _isTrigger = t; }
|
|
|
|
|
2021-09-13 15:53:43 +03:00
|
|
|
void updatePhysicsState();
|
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
void setVelocity(const Vec3D &velocity);
|
|
|
|
void addVelocity(const Vec3D &velocity);
|
|
|
|
void setAcceleration(const Vec3D &acceleration);
|
2021-09-13 15:53:43 +03:00
|
|
|
|
2021-10-28 16:58:02 +03:00
|
|
|
[[nodiscard]] Vec3D velocity() const { return _velocity; }
|
|
|
|
[[nodiscard]] Vec3D acceleration() const { return _acceleration; }
|
2021-09-19 11:25:10 +03:00
|
|
|
|
2021-10-31 11:39:08 +03:00
|
|
|
[[nodiscard]] const std::function<void(const ObjectNameTag &, std::shared_ptr<RigidBody>)> &
|
|
|
|
collisionCallBack() const { return _collisionCallBack; }
|
|
|
|
|
|
|
|
void setCollisionCallBack(const std::function<void(const ObjectNameTag &tag,
|
|
|
|
std::shared_ptr<RigidBody>)> &f) { _collisionCallBack = f; }
|
2021-10-16 20:22:55 +03:00
|
|
|
|
|
|
|
~RigidBody() override = default;
|
2021-09-13 15:53:43 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif //INC_3DZAVR_RIGIDBODY_H
|