Made Triangle immutable

Correct inheritance (Objects -> Mesh & Camera -> RigidBody)
Small code refactor
master
Vectozavr 2021-09-19 15:25:10 +07:00
parent 17a307c45e
commit be42d4d9bc
32 changed files with 569 additions and 685 deletions

View File

@ -8,7 +8,7 @@
#include "World.h" #include "World.h"
#include "Player.h" #include "Player.h"
class Bonus : public Mesh { class Bonus : public RigidBody {
protected: protected:
std::string _name; std::string _name;
public: public:

View File

@ -15,27 +15,27 @@ void Client::updatePacket() {
void Client::spawnPlayer(sf::Uint16 id) { void Client::spawnPlayer(sf::Uint16 id) {
std::string name = "Player_" + std::to_string(id); std::string name = "Player_" + std::to_string(id);
_players.insert({ id, std::make_shared<Player>() }); _players.insert({ id, std::make_shared<Player>() });
(*_world).addMesh(_players[id], name); (*_world).addBody(_players[id], name);
_players[id]->setVisible(true); _players[id]->setVisible(true);
_players[id]->setAcceleration(Point4D{0, 0, 0}); _players[id]->setAcceleration(Point4D{0, 0, 0});
// add head and other stuff: // add head and other stuff:
_world->loadObj(name + "_head", "../obj/cube.obj", "",Point4D{0.7, 0.7, 0.7}); _world->loadBody(name + "_head", "../obj/cube.obj", "", Point4D{0.7, 0.7, 0.7});
(*_world)[name + "_head"]->translate(Point4D{0, 2, 0}); _world->body(name + "_head")->translate(Point4D{0, 2, 0});
(*_world)[name + "_head"]->setCollider(false); _world->body(name + "_head")->setCollider(false);
_players[id]->attach((*_world)[name + "_head"]); _players[id]->attach(_world->body(name + "_head"));
_world->loadObj(name + "_eye1", "../obj/cube.obj", "",Point4D{0.2, 0.2, 0.05}); _world->loadBody(name + "_eye1", "../obj/cube.obj", "", Point4D{0.2, 0.2, 0.05});
(*_world)[name + "_eye1"]->translate(Point4D{0.3, 2.1, 0.7}); _world->body(name + "_eye1")->translate(Point4D{0.3, 2.1, 0.7});
(*_world)[name + "_eye1"]->setCollider(false); _world->body(name + "_eye1")->setCollider(false);
(*_world)[name + "_eye1"]->setColor({147, 159, 255}); _world->body(name + "_eye1")->setColor({147, 159, 255});
(*_world)[name + "_head"]->attach((*_world)[name + "_eye1"]); _world->body(name + "_head")->attach(_world->body(name + "_eye1"));
_world->loadObj(name + "_eye2", "../obj/cube.obj", "",Point4D{0.2, 0.2, 0.05}); _world->loadBody(name + "_eye2", "../obj/cube.obj", "", Point4D{0.2, 0.2, 0.05});
(*_world)[name + "_eye2"]->translate(Point4D{-0.3, 2.1, 0.7}); _world->body(name + "_eye2")->translate(Point4D{-0.3, 2.1, 0.7});
(*_world)[name + "_eye2"]->setCollider(false); _world->body(name + "_eye2")->setCollider(false);
(*_world)[name + "_eye2"]->setColor({147, 159, 255}); _world->body(name + "_eye2")->setColor({147, 159, 255});
(*_world)[name + "_head"]->attach((*_world)[name + "_eye2"]); _world->body(name + "_head")->attach(_world->body(name + "_eye2"));
} }
void Client::processInit(sf::Packet& packet) { void Client::processInit(sf::Packet& packet) {
@ -64,7 +64,7 @@ void Client::processUpdate(sf::Packet& packet) {
_players[targetId]->setHealth(buf[3]); _players[targetId]->setHealth(buf[3]);
_players[targetId]->rotateToAngle(Point4D{0, buf[4], 0}); _players[targetId]->rotateToAngle(Point4D{0, buf[4], 0});
(*_world)[name + "_head"]->rotate(Matrix4x4::RotationY(buf[4]) * Point4D{1, 0, 0}, _world->body(name + "_head")->rotate(Matrix4x4::RotationY(buf[4]) * Point4D{1, 0, 0},
buf[5] - _players[targetId]->headAngle()); buf[5] - _players[targetId]->headAngle());
_players[targetId]->setHeadAngle(buf[5]); _players[targetId]->setHeadAngle(buf[5]);
} else if (targetId == _socket.ownId()) { } else if (targetId == _socket.ownId()) {
@ -84,10 +84,10 @@ void Client::processNewClient(sf::Packet& packet) {
void Client::processDisconnect(sf::Uint16 targetId) { void Client::processDisconnect(sf::Uint16 targetId) {
if (targetId != _socket.ownId() && _players.count(targetId)) { if (targetId != _socket.ownId() && _players.count(targetId)) {
std::string name = "Player_" + std::to_string(targetId); std::string name = "Player_" + std::to_string(targetId);
_world->removeMesh(name); _world->removeBody(name);
_world->removeMesh(name + "_head"); _world->removeBody(name + "_head");
_world->removeMesh(name + "_eye1"); _world->removeBody(name + "_eye1");
_world->removeMesh(name + "_eye2"); _world->removeBody(name + "_eye2");
_players.erase(targetId); _players.erase(targetId);
} }
@ -128,18 +128,19 @@ void Client::processCustomPacket(MsgType type, sf::Packet& packet) {
p2 = Point4D(dbuff[3], dbuff[4], dbuff[5]); p2 = Point4D(dbuff[3], dbuff[4], dbuff[5]);
tmp = "Client_fireTraces_" + std::to_string(fireTraces++); tmp = "Client_fireTraces_" + std::to_string(fireTraces++);
_world->addMesh(std::make_shared<Mesh>(Mesh::LineTo(p1, p2, 0.05)), tmp); _world->addBody(std::make_shared<RigidBody>(RigidBody(Mesh::LineTo(p1, p2, 0.05))), tmp);
(*_world)[tmp]->setCollider(false); _world->body(tmp)->setCollider(false);
(*_world)[tmp]->a_color(tmp + "_fadeOut", {255, 255, 255, 0}, 1, Animation::None, Animation::linear); _world->body(tmp)->a_color(tmp + "_fadeOut", {255, 255, 255, 0}, 1, Animation::None, Animation::linear);
(*_world)["Player_im"]->a_function(tmp + "delete", [this, tmp](){ deleteTrace(_world, tmp); }, 1, 2); _world->body("Player_im")->a_function(tmp + "delete", [this, tmp](){ deleteTrace(_world, tmp); }, 1, 2);
break; break;
case MsgType::InitBonuses: case MsgType::InitBonuses:
while (packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]) { while (packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]) {
tmp2 = tmp.substr(6, tmp.size()-3-5); tmp2 = tmp.substr(6, tmp.size()-3-5);
_world->addMesh(std::make_shared<Bonus>(tmp, "../obj/" + tmp2 + ".obj", "../obj/" + tmp2 + "_mat.txt", Point4D{3, 3, 3}), tmp); _world->addBody(std::make_shared<Bonus>(tmp, "../obj/" + tmp2 + ".obj", "../obj/" + tmp2 + "_mat.txt",
(*_world)[tmp]->translateToPoint(Point4D(dbuff[0], dbuff[1], dbuff[2])); Point4D{3, 3, 3}), tmp);
_world->body(tmp)->translateToPoint(Point4D(dbuff[0], dbuff[1], dbuff[2]));
} }
break; break;
@ -147,13 +148,14 @@ void Client::processCustomPacket(MsgType type, sf::Packet& packet) {
packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2]; packet >> tmp >> dbuff[0] >> dbuff[1] >> dbuff[2];
tmp2 = tmp.substr(6, tmp.size()-3-5); tmp2 = tmp.substr(6, tmp.size()-3-5);
_world->addMesh(std::make_shared<Bonus>(tmp, "../obj/" + tmp2 + ".obj", "../obj/" + tmp2 + "_mat.txt", Point4D{3, 3, 3}), tmp); _world->addBody(std::make_shared<Bonus>(tmp, "../obj/" + tmp2 + ".obj", "../obj/" + tmp2 + "_mat.txt",
(*_world)[tmp]->translateToPoint(Point4D(dbuff[0], dbuff[1], dbuff[2])); Point4D{3, 3, 3}), tmp);
_world->body(tmp)->translateToPoint(Point4D(dbuff[0], dbuff[1], dbuff[2]));
break; break;
case MsgType::RemoveBonus: case MsgType::RemoveBonus:
packet >> tmp; packet >> tmp;
_world->removeMesh(tmp); _world->removeBody(tmp);
break; break;
} }
} }
@ -162,10 +164,10 @@ void Client::processDisconnected() {
for (auto it = _players.begin(); it != _players.end();) { for (auto it = _players.begin(); it != _players.end();) {
std::string name = "Player_" + std::to_string(it->first); std::string name = "Player_" + std::to_string(it->first);
_world->removeMesh(name); _world->removeBody(name);
_world->removeMesh(name + "_head"); _world->removeBody(name + "_head");
_world->removeMesh(name + "_eye1"); _world->removeBody(name + "_eye1");
_world->removeMesh(name + "_eye2"); _world->removeBody(name + "_eye2");
_players.erase(it++); _players.erase(it++);
} }
} }
@ -187,7 +189,7 @@ void Client::addTrace(const Point4D& from, const Point4D& to) {
} }
void Client::deleteTrace(std::shared_ptr<World> world, const std::string &traceName) { void Client::deleteTrace(std::shared_ptr<World> world, const std::string &traceName) {
world->removeMesh(traceName); world->removeBody(traceName);
} }
void Client::takeBonus(const std::string& bonusName) { void Client::takeBonus(const std::string& bonusName) {

View File

@ -21,7 +21,7 @@ private:
void spawnPlayer(sf::Uint16 id); void spawnPlayer(sf::Uint16 id);
public: public:
Client(std::shared_ptr<Player> player, std::shared_ptr<World> world) : _player(std::move(player)), _world(std::move(world)) {}; Client(std::shared_ptr<Player> player, std::shared_ptr<World> world) : _player(player), _world(world) {};
void updatePacket() override; void updatePacket() override;

View File

@ -11,28 +11,28 @@ void Player::update() {
// friction // friction
if(inCollision()) if(inCollision())
p_velocity = p_velocity - p_velocity*Time::deltaTime()*2; _velocity = _velocity - _velocity * Time::deltaTime() * 2;
if(isInSlowMo) { if(_isInSlowMo) {
if(_ability > 0) if(_ability > 0)
_ability -= Time::deltaTime(); _ability -= Time::deltaTime();
else { else {
_ability = 0; _ability = 0;
isInSlowMo = false; _isInSlowMo = false;
setVelocity(velocity()*slowMoCoefficient); setVelocity(velocity() * _slowMoCoefficient);
setAcceleration(p_acceleration*slowMoCoefficient*slowMoCoefficient); setAcceleration(_acceleration * _slowMoCoefficient * _slowMoCoefficient);
slowMoSound.stop(); _slowMoSound.stop();
unSlowMoSound.play(); _unSlowMoSound.play();
} }
} }
double coeff = isInSlowMo ? 1.0/slowMoCoefficient : 1.0; double coeff = _isInSlowMo ? 1.0 / _slowMoCoefficient : 1.0;
bool inRunning_old = inRunning; bool inRunning_old = _inRunning;
inRunning = _screen != nullptr && (Screen::isKeyPressed(sf::Keyboard::A) || Screen::isKeyPressed(sf::Keyboard::D) ||Screen::isKeyPressed(sf::Keyboard::W) || Screen::isKeyPressed(sf::Keyboard::S)); _inRunning = _screen != nullptr && (Screen::isKeyPressed(sf::Keyboard::A) || Screen::isKeyPressed(sf::Keyboard::D) || Screen::isKeyPressed(sf::Keyboard::W) || Screen::isKeyPressed(sf::Keyboard::S));
// in case when the camera is attached we make some animation during running // in case when the camera is attached we make some animation during running
if(_camera != nullptr && inRunning && !_camera->isInAnim()) { if(_camera != nullptr && _inRunning && !_camera->isInAnim()) {
_camera->a_translate("hor_oscil", -_camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_translate("hor_oscil", -_camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos);
_camera->a_wait("hor_oscil", 0); _camera->a_wait("hor_oscil", 0);
_camera->a_translate("hor_oscil", _camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos); _camera->a_translate("hor_oscil", _camera->left()/12, 0.3/coeff, Animation::LoopOut::None, Animation::cos);
@ -47,7 +47,7 @@ void Player::update() {
_camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.3/coeff, Animation::None, Animation::cos); _camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.3/coeff, Animation::None, Animation::cos);
} else if(_camera != nullptr && inRunning_old && !inRunning) { } else if(_camera != nullptr && inRunning_old && !_inRunning) {
_camera->a_stopAllAnimations(); _camera->a_stopAllAnimations();
_camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.15/coeff, Animation::None, Animation::cos); _camera->a_translateToPoint("init", position() + Point4D{0, 1.8, 0}, 0.15/coeff, Animation::None, Animation::cos);
@ -58,55 +58,55 @@ void Player::update() {
if(_world != nullptr && _screen != nullptr && _camera != nullptr) { if(_world != nullptr && _screen != nullptr && _camera != nullptr) {
// Left and right // Left and right
if (Screen::isKeyPressed(sf::Keyboard::A)) { if (Screen::isKeyPressed(sf::Keyboard::A)) {
translate(_camera->left() * Time::deltaTime() * walkSpeed * coeff); translate(_camera->left() * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision()) if(inCollision())
setVelocity(Point4D{0,0,0}); setVelocity(Point4D{0,0,0});
} }
if (Screen::isKeyPressed(sf::Keyboard::D)) { if (Screen::isKeyPressed(sf::Keyboard::D)) {
translate(-_camera->left() * Time::deltaTime() * walkSpeed * coeff); translate(-_camera->left() * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision()) if(inCollision())
setVelocity(Point4D{0,0,0}); setVelocity(Point4D{0,0,0});
} }
// Forward and backward // Forward and backward
if (Screen::isKeyPressed(sf::Keyboard::W)) { if (Screen::isKeyPressed(sf::Keyboard::W)) {
translate(_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * walkSpeed * coeff); translate(_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision()) if(inCollision())
setVelocity(Point4D{0,0,0}); setVelocity(Point4D{0,0,0});
} }
if (Screen::isKeyPressed(sf::Keyboard::S)) { if (Screen::isKeyPressed(sf::Keyboard::S)) {
translate(-_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * walkSpeed * coeff); translate(-_camera->left().cross3D(Point4D{0, 1, 0}) * Time::deltaTime() * _walkSpeed * coeff);
if(inCollision()) if(inCollision())
setVelocity(Point4D{0,0,0}); setVelocity(Point4D{0,0,0});
} }
if (_ability > 0 && !isInSlowMo && Screen::isKeyPressed(sf::Keyboard::LShift)) { if (_ability > 0 && !_isInSlowMo && Screen::isKeyPressed(sf::Keyboard::LShift)) {
// slow mo // slow mo
isInSlowMo = true; _isInSlowMo = true;
setVelocity(velocity()/slowMoCoefficient); setVelocity(velocity() / _slowMoCoefficient);
setAcceleration(p_acceleration/(slowMoCoefficient*slowMoCoefficient)); setAcceleration(_acceleration / (_slowMoCoefficient * _slowMoCoefficient));
unSlowMoSound.stop(); _unSlowMoSound.stop();
slowMoSound.play(); _slowMoSound.play();
} else if (isInSlowMo && !Screen::isKeyPressed(sf::Keyboard::LShift)) { } else if (_isInSlowMo && !Screen::isKeyPressed(sf::Keyboard::LShift)) {
isInSlowMo = false; _isInSlowMo = false;
setVelocity(velocity()*slowMoCoefficient); setVelocity(velocity() * _slowMoCoefficient);
setAcceleration(p_acceleration*slowMoCoefficient*slowMoCoefficient); setAcceleration(_acceleration * _slowMoCoefficient * _slowMoCoefficient);
slowMoSound.stop(); _slowMoSound.stop();
unSlowMoSound.play(); _unSlowMoSound.play();
} }
if (Screen::isKeyPressed(sf::Keyboard::Space) && inCollision()) { if (Screen::isKeyPressed(sf::Keyboard::Space) && inCollision()) {
addVelocity(Point4D{0, std::abs(_collisionNormal.y())*sqrt(2 * g * jumpHeight)*coeff, 0}); addVelocity(Point4D{0, std::abs(_collisionNormal.y()) * sqrt(2 * _g * _jumpHeight) * coeff, 0});
translate(Point4D{0, Time::deltaTime() * walkSpeed * 2 * coeff, 0}); translate(Point4D{0, Time::deltaTime() * _walkSpeed * 2 * coeff, 0});
} }
// Mouse movement // Mouse movement
Point4D disp = _screen->getMouseDisplacement(); Point4D disp = _screen->getMouseDisplacement();
rotate(Point4D{0, -disp.x() / 1000.0, 0}); rotate(Point4D{0, -disp.x() / 1000.0, 0});
p_velocity = Matrix4x4::RotationY(-disp.x() / 1000.0)*p_velocity; _velocity = Matrix4x4::RotationY(-disp.x() / 1000.0) * _velocity;
double rotationLeft = disp.y() / 1000.0; double rotationLeft = disp.y() / 1000.0;
@ -126,7 +126,7 @@ void Player::update() {
_selectedWeapon = (_selectedWeapon + 1) % _weapons.size(); _selectedWeapon = (_selectedWeapon + 1) % _weapons.size();
_weapons[_selectedWeapon]->addToWorld(_world); _weapons[_selectedWeapon]->addToWorld(_world);
Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon)); Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon));
changeWeaponSound.play(); _changeWeaponSound.play();
} }
} }
@ -140,7 +140,7 @@ void Player::update() {
_selectedWeapon = _weapons.size() - 1; _selectedWeapon = _weapons.size() - 1;
_weapons[_selectedWeapon]->addToWorld(_world); _weapons[_selectedWeapon]->addToWorld(_world);
Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon)); Log::log("selected _selectedWeapon " + std::to_string(_selectedWeapon));
changeWeaponSound.play(); _changeWeaponSound.play();
} }
} }
@ -148,7 +148,7 @@ void Player::update() {
auto damagedPlayers = _weapons[_selectedWeapon]->fire(_world, _camera); auto damagedPlayers = _weapons[_selectedWeapon]->fire(_world, _camera);
for(auto& damagedPlayer : damagedPlayers) { for(auto& damagedPlayer : damagedPlayers) {
sf::Uint16 targetId = std::stoi(damagedPlayer.first.substr(7)); sf::Uint16 targetId = std::stoi(damagedPlayer.first.substr(7));
damagePlayerCallBack(targetId, damagedPlayer.second); _damagePlayerCallBack(targetId, damagedPlayer.second);
} }
} }
@ -156,11 +156,11 @@ void Player::update() {
_weapons[_selectedWeapon]->reload(); _weapons[_selectedWeapon]->reload();
} }
if (inRunning && inCollision() && walkSound.getStatus() != sf::Sound::Status::Playing) { if (_inRunning && inCollision() && _walkSound.getStatus() != sf::Sound::Status::Playing) {
if ((position() - rayToFloor.first).abs() < 2) { if ((position() - rayToFloor.first).abs() < 2) {
int soundNum = round((double) rand() / RAND_MAX * 5) + 1; int soundNum = round((double) rand() / RAND_MAX * 5) + 1;
walkSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/stonestep" + std::to_string(soundNum) + ".ogg")); _walkSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/stonestep" + std::to_string(soundNum) + ".ogg"));
walkSound.play(); _walkSound.play();
} }
} }
} }
@ -248,7 +248,7 @@ void Player::drawStats() {
text_ammo2.setFillColor(sf::Color(0, 0, 0, 70)); text_ammo2.setFillColor(sf::Color(0, 0, 0, 70));
_screen->window.draw(text_ammo2); _screen->window.draw(text_ammo2);
// text killSound/deathSound stats // text _killSound/_deathSound stats
sf::Text text_kills(text_health); sf::Text text_kills(text_health);
text_kills.setStyle(sf::Text::Bold); text_kills.setStyle(sf::Text::Bold);
text_kills.setString("KILLS: " + std::to_string((int)_kills) + " | " + "DEATHS: " + std::to_string((int)_deaths)); text_kills.setString("KILLS: " + std::to_string((int)_kills) + " | " + "DEATHS: " + std::to_string((int)_deaths));
@ -267,16 +267,16 @@ void Player::drawStats() {
} }
void Player::playDeath() { void Player::playDeath() {
deathSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/classic_hurt.ogg")); _deathSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/classic_hurt.ogg"));
deathSound.play(); _deathSound.play();
} }
void Player::playKill() { void Player::playKill() {
killSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/kill.ogg")); _killSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/kill.ogg"));
killSound.play(); _killSound.play();
} }
void Player::collisionWithObject(const std::string &objName, std::shared_ptr<Mesh> obj) { void Player::collisionWithObject(const std::string &objName, std::shared_ptr<RigidBody> obj) {
if(objName.find("Bonus_gun") != std::string::npos) if(objName.find("Bonus_gun") != std::string::npos)
addWeapon(std::make_shared<Gun>()); addWeapon(std::make_shared<Gun>());
@ -299,13 +299,13 @@ void Player::collisionWithObject(const std::string &objName, std::shared_ptr<Mes
setFullAbility(); setFullAbility();
if(objName.find("Bonus") != std::string::npos) { if(objName.find("Bonus") != std::string::npos) {
_world->removeMesh(objName); _world->removeBody(objName);
takeBonusCallBack(objName); _takeBonusCallBack(objName);
} }
} }
void Player::addWeapon(std::shared_ptr<Weapon> weapon) { void Player::addWeapon(std::shared_ptr<Weapon> weapon) {
changeWeaponSound.play(); _changeWeaponSound.play();
if(!_weapons.empty()) { if(!_weapons.empty()) {
for(auto& w : _weapons) { for(auto& w : _weapons) {
@ -320,11 +320,11 @@ void Player::addWeapon(std::shared_ptr<Weapon> weapon) {
_weapons.back()->attachToPlayer(*this); _weapons.back()->attachToPlayer(*this);
_weapons.back()->translate(position()); _weapons.back()->translate(position());
_weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, Point4D{0, 1, 0}, p_angle.y()); _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, Point4D{0, 1, 0}, _angle.y());
_weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, _camera->left(), _camera->angleLeftUpLookAt().x()); _weapons.back()->rotateRelativePoint(position() + Point4D{0, 1.8, 0}, _camera->left(), _camera->angleLeftUpLookAt().x());
_weapons.back()->setAddTraceCallBack(addTraceCallBack); _weapons.back()->setAddTraceCallBack(_addTraceCallBack);
changeWeaponSound.play(); _changeWeaponSound.play();
} }
void Player::initWeapons() { void Player::initWeapons() {

View File

@ -8,7 +8,6 @@
#include <SFML/Audio/Sound.hpp> #include <SFML/Audio/Sound.hpp>
#include <utility> #include <utility>
#include <ResourceManager.h> #include <ResourceManager.h>
#include "Mesh.h"
#include "Camera.h" #include "Camera.h"
#include "World.h" #include "World.h"
#include "weapon/Ak47.h" #include "weapon/Ak47.h"
@ -17,7 +16,7 @@
#include "weapon/Gold_Ak47.h" #include "weapon/Gold_Ak47.h"
#include "weapon/Rifle.h" #include "weapon/Rifle.h"
class Player : public Mesh{ class Player : public RigidBody{
private: private:
double _healthMax = 100; double _healthMax = 100;
double _health = _healthMax; double _health = _healthMax;
@ -25,80 +24,80 @@ private:
double _abilityMax = 10; double _abilityMax = 10;
double _ability = _abilityMax; double _ability = _abilityMax;
double jumpHeight = 3; double _jumpHeight = 3;
double walkSpeed = 10; double _walkSpeed = 10;
double _headAngle = 0; double _headAngle = 0;
unsigned _kills = 0; unsigned _kills = 0;
unsigned _deaths = 0; unsigned _deaths = 0;
double g = 35; double _g = 35;
double slowMoCoefficient = 5; double _slowMoCoefficient = 5;
bool isInSlowMo = false; bool _isInSlowMo = false;
std::shared_ptr<Camera> _camera; std::shared_ptr<Camera> _camera;
std::shared_ptr<Screen> _screen; std::shared_ptr<Screen> _screen;
std::shared_ptr<World> _world; std::shared_ptr<World> _world;
bool inRunning = false; bool _inRunning = false;
// sounds // sounds
sf::Sound killSound; sf::Sound _killSound;
sf::Sound deathSound; sf::Sound _deathSound;
sf::Sound walkSound; sf::Sound _walkSound;
sf::Sound changeWeaponSound; sf::Sound _changeWeaponSound;
sf::Sound slowMoSound; sf::Sound _slowMoSound;
sf::Sound unSlowMoSound; sf::Sound _unSlowMoSound;
sf::Sound fullHealthSound; sf::Sound _fullHealthSound;
sf::Sound fullAbilitySound; sf::Sound _fullAbilitySound;
std::string _name = "im"; std::string _name = "im";
std::vector<std::shared_ptr<Weapon>> _weapons; std::vector<std::shared_ptr<Weapon>> _weapons;
uint8_t _selectedWeapon = 0; uint8_t _selectedWeapon = 0;
std::function<void(sf::Uint16 targetId, double)> damagePlayerCallBack; std::function<void(sf::Uint16 targetId, double)> _damagePlayerCallBack;
std::function<void(const Point4D&, const Point4D&)> addTraceCallBack; std::function<void(const Point4D&, const Point4D&)> _addTraceCallBack;
std::function<void(const std::string&)> takeBonusCallBack; std::function<void(const std::string&)> _takeBonusCallBack;
public: public:
Player() { Player() {
loadObj("../obj/cube.obj", "", Point4D{0.5, 1.9, 0.5}); loadObj("../obj/cube.obj", "", Point4D{0.5, 1.9, 0.5});
setAcceleration(Point4D{0, -g, 0}); setAcceleration(Point4D{0, -_g, 0});
setCollision(true); setCollision(true);
setVisible(false); setVisible(false);
setColor({240, 168, 168}); setColor({240, 168, 168});
_changeWeaponSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/change_weapon.ogg"));
_slowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/slow_mo.ogg"));
_unSlowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/unslow_mo.ogg"));
_fullHealthSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/fullHealth.ogg"));
_fullAbilitySound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/fullAbility.ogg"));
setCollisionCallBack([this](const std::string& objName, std::shared_ptr<RigidBody> obj) {collisionWithObject(objName, obj);});
}; };
void update(); void update();
void attachCamera(std::shared_ptr<Camera> camera, std::shared_ptr<Screen> screen) { void attachCamera(std::shared_ptr<Camera> camera, std::shared_ptr<Screen> screen) {
_camera = std::move(camera); _camera = camera;
_screen = std::move(screen); _screen = screen;
_camera->translateToPoint(position() + Point4D{0, 1.8, 0}); _camera->translateToPoint(position() + Point4D{0, 1.8, 0});
this->attach(_camera); this->attach(_camera);
} }
void attachWorld(std::shared_ptr<World> world, const Point4D& pos = Point4D{0, 30, 0}) { void attachWorld(std::shared_ptr<World> world, const Point4D& pos = Point4D{0, 30, 0}) {
_world = std::move(world); _world = world;
translate(pos); translate(pos);
initWeapons(); initWeapons();
changeWeaponSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/change_weapon.ogg"));
slowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/slow_mo.ogg"));
unSlowMoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/unslow_mo.ogg"));
fullHealthSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/fullHealth.ogg"));
fullAbilitySound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/fullAbility.ogg"));
setCollisionCallBack([this](const std::string& objName, std::shared_ptr<Mesh> obj) {collisionWithObject(objName, std::move(obj));});
} }
void setHealth(double h) { void setHealth(double h) {
@ -110,24 +109,24 @@ public:
void setFullHealth() { void setFullHealth() {
_health = _healthMax; _health = _healthMax;
fullHealthSound.play(); _fullHealthSound.play();
} }
void setFullAbility() { void setFullAbility() {
_ability = _abilityMax; _ability = _abilityMax;
fullAbilitySound.play(); _fullAbilitySound.play();
} }
void setDamagePlayerCallBack(std::function<void(sf::Uint16 targetId, double)> hit) { void setDamagePlayerCallBack(std::function<void(sf::Uint16 targetId, double)> hit) {
damagePlayerCallBack = std::move(hit); _damagePlayerCallBack = std::move(hit);
} }
void setAddTraceCallBack(std::function<void(const Point4D&, const Point4D&)> add) { void setAddTraceCallBack(std::function<void(const Point4D&, const Point4D&)> add) {
addTraceCallBack = std::move(add); _addTraceCallBack = std::move(add);
} }
void setTakeBonusCallBack(std::function<void(const std::string&)> take) { void setTakeBonusCallBack(std::function<void(const std::string&)> take) {
takeBonusCallBack = std::move(take); _takeBonusCallBack = std::move(take);
} }
[[nodiscard]] double health() const { return _health; } [[nodiscard]] double health() const { return _health; }
@ -151,7 +150,7 @@ public:
void playDeath(); void playDeath();
void playKill(); void playKill();
void collisionWithObject(const std::string& objName, std::shared_ptr<Mesh> obj); void collisionWithObject(const std::string& objName, std::shared_ptr<RigidBody> obj);
void addWeapon(std::shared_ptr<Weapon> weapon); void addWeapon(std::shared_ptr<Weapon> weapon);

View File

@ -5,25 +5,25 @@
#include "Camera.h" #include "Camera.h"
#include "utils/Log.h" #include "utils/Log.h"
std::vector<Triangle> &Camera::project(Mesh& mesh, Screen::ViewMode mode) { std::vector<Triangle> &Camera::project(std::shared_ptr<Mesh> mesh) {
if(!ready) { if(!_ready) {
Log::log("Camera::project(): cannot project tris without camera initialization ( Camera::init() ) "); Log::log("Camera::project(): cannot project _tris without camera initialization ( Camera::init() ) ");
return this->triangles; return this->_triangles;
} }
if(!mesh.isVisible()) if(!mesh->isVisible())
return this->triangles; return this->_triangles;
// Model transform matrix: translate tris in the origin of mesh. // Model transform matrix: translate _tris in the origin of body.
Matrix4x4 M = Matrix4x4::Translation(mesh.position()); Matrix4x4 M = Matrix4x4::Translation(mesh->position());
VM = V * M; Matrix4x4 VM = _V * M;
// We don't want to waste time re-allocating memory every time // We don't want to waste time re-allocating memory every time
std::vector<Triangle> clippedTriangles, tempBuffer; std::vector<Triangle> clippedTriangles, tempBuffer;
for(auto& t : mesh.triangles()) { for(auto& t : mesh->triangles()) {
double dot = t.norm().dot((mesh.position() + t[0] - p_position).normalized()); double dot = t.norm().dot((mesh->position() + t[0] - _position).normalized());
if(dot > 0) if(dot > 0)
continue; continue;
@ -32,10 +32,10 @@ std::vector<Triangle> &Camera::project(Mesh& mesh, Screen::ViewMode mode) {
// It needs to be cleared because it's reused through iterations. Usually it doesn't free memory. // It needs to be cleared because it's reused through iterations. Usually it doesn't free memory.
clippedTriangles.clear(); clippedTriangles.clear();
// In the beginning we need to to translate triangle from world coordinate to our camera system: // In the beginning we need to to translate drawTriangle from world coordinate to our camera system:
// After that we apply clipping for all planes from clipPlanes // After that we apply clipping for all planes from _clipPlanes
clippedTriangles.emplace_back(t * VM); clippedTriangles.emplace_back(t * VM);
for(auto& plane : clipPlanes) for(auto& plane : _clipPlanes)
{ {
while(!clippedTriangles.empty()) while(!clippedTriangles.empty())
{ {
@ -51,60 +51,59 @@ std::vector<Triangle> &Camera::project(Mesh& mesh, Screen::ViewMode mode) {
} }
for(auto& clippedTriangle : clippedTriangles) { for(auto& clippedTriangle : clippedTriangles) {
if(mode != Screen::ViewMode::Clipped) { sf::Color color = clippedTriangle.color();
clippedTriangle.color = sf::Color(clippedTriangle.color.r * (0.3 * std::abs(dot) + 0.7), sf::Color ambientColor = sf::Color(color.r * (0.3 * std::abs(dot) + 0.7),
clippedTriangle.color.g * (0.3 * std::abs(dot) + 0.7), color.g * (0.3 * std::abs(dot) + 0.7),
clippedTriangle.color.b * (0.3 * std::abs(dot) + 0.7), color.b * (0.3 * std::abs(dot) + 0.7),
(mode == Screen::ViewMode::Transparency || color.a);
mode == Screen::ViewMode::Normals) ? 100 : clippedTriangle.color.a);
}
// Finally its time to project our clipped colored triangle from 3D -> 2D // Finally its time to project our clipped colored drawTriangle from 3D -> 2D
// and transform it's coordinate to screen space (in pixels): // and transform it's coordinate to screen space (in pixels):
clippedTriangle *= SP; clippedTriangle = clippedTriangle * _SP;
clippedTriangle[0] = clippedTriangle[0] / clippedTriangle[0].w(); clippedTriangle = Triangle(clippedTriangle[0] / clippedTriangle[0].w(),
clippedTriangle[1] = clippedTriangle[1] / clippedTriangle[1].w(); clippedTriangle[1] / clippedTriangle[1].w(),
clippedTriangle[2] = clippedTriangle[2] / clippedTriangle[2].w(); clippedTriangle[2] / clippedTriangle[2].w(),
ambientColor);
triangles.emplace_back(clippedTriangle); _triangles.emplace_back(clippedTriangle);
} }
} }
return this->triangles; return this->_triangles;
} }
void Camera::init(int width, int height, double fov, double ZNear, double ZFar) { void Camera::init(int width, int height, double fov, double ZNear, double ZFar) {
// We need to init camera only after creation or changing width, height, fov, ZNear or ZFar. // We need to init camera only after creation or changing width, height, fov, ZNear or ZFar.
// Because here we calculate matrix that does not change during the motion of _objects or camera // Because here we calculate matrix that does not change during the motion of _objects or camera
w = width; h = height; _w = width; _h = height;
aspect = (double)width / (double)height; _aspect = (double)width / (double)height;
P = Matrix4x4::Projection(fov, aspect, ZNear, ZFar); _P = Matrix4x4::Projection(fov, _aspect, ZNear, ZFar);
S = Matrix4x4::ScreenSpace(width, height); _S = Matrix4x4::ScreenSpace(width, height);
SP = S * P; // screen-space-projections matrix _SP = _S * _P; // screen-space-projections matrix
// This is planes for clipping tris. // This is planes for clipping _tris.
// Motivation: we are not interest in tris that we cannot see. // 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, ZNear})); // near plane
clipPlanes.emplace_back(Plane(Point4D{0, 0, -1}, Point4D{0, 0, ZFar})); // far plane _clipPlanes.emplace_back(Plane(Point4D{0, 0, -1}, Point4D{0, 0, ZFar})); // far plane
double thetta1 = M_PI*fov*0.5/180.0; double thetta1 = M_PI*fov*0.5/180.0;
double thetta2 = atan(aspect*tan(thetta1)); 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})); // left plane
clipPlanes.emplace_back(Plane(Point4D{cos(thetta2), 0, sin(thetta2)}, Point4D{0, 0, 0})); // right 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})); // down plane
clipPlanes.emplace_back(Plane(Point4D{0, -cos(thetta1), sin(thetta1)},Point4D{0, 0, 0})); // up plane _clipPlanes.emplace_back(Plane(Point4D{0, -cos(thetta1), sin(thetta1)}, Point4D{0, 0, 0})); // up plane
ready = true; _ready = true;
Log::log("Camera::init(): camera successfully initialized."); Log::log("Camera::init(): camera successfully initialized.");
} }
std::vector<Triangle> &Camera::sorted() { std::vector<Triangle> &Camera::sorted() {
// Sort tris from back to front // Sort _tris from back to front
// This is some replacement for Z-buffer // This is some replacement for Z-buffer
std::sort(triangles.begin(), triangles.end(), [](Triangle &t1, Triangle &t2) std::sort(_triangles.begin(), _triangles.end(), [](Triangle &t1, Triangle &t2)
{ {
std::vector<double> v_z1({t1[0].z(), t1[1].z(), t1[2].z()}); std::vector<double> v_z1({t1[0].z(), t1[1].z(), t1[2].z()});
std::vector<double> v_z2({t2[0].z(), t2[1].z(), t2[2].z()}); std::vector<double> v_z2({t2[0].z(), t2[1].z(), t2[2].z()});
@ -118,44 +117,44 @@ std::vector<Triangle> &Camera::sorted() {
return z1 > z2; return z1 > z2;
}); });
return triangles; return _triangles;
} }
void Camera::record() { void Camera::clear() {
// Cleaning all tris and recalculation of View matrix // Cleaning all _tris and recalculation of View matrix
// That is like preparation for new camera shot: we need to set // That is like preparation for new camera shot: we need to set
// the position of camera and insert new cartridge for photo. // the position of camera and insert new cartridge for photo.
triangles.clear(); _triangles.clear();
V = Matrix4x4::View(p_left, p_up, p_lookAt, p_position); _V = Matrix4x4::View(_left, _up, _lookAt, _position);
} }
void Camera::rotateX(double rx) { void Camera::rotateX(double rx) {
p_angle = Point4D{p_angle.x() + rx, p_angle.y(), p_angle.z()}; _angle = Point4D{_angle.x() + rx, _angle.y(), _angle.z()};
p_left = Matrix4x4::RotationX(rx) * p_left; _left = Matrix4x4::RotationX(rx) * _left;
p_up = Matrix4x4::RotationX(rx) * p_up; _up = Matrix4x4::RotationX(rx) * _up;
p_lookAt = Matrix4x4::RotationX(rx) * p_lookAt; _lookAt = Matrix4x4::RotationX(rx) * _lookAt;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), Point4D{rx, 0, 0}); attached->rotateRelativePoint(position(), Point4D{rx, 0, 0});
} }
void Camera::rotateY(double ry) { void Camera::rotateY(double ry) {
p_angle = Point4D{p_angle.x(), p_angle.y() + ry, p_angle.z()}; _angle = Point4D{_angle.x(), _angle.y() + ry, _angle.z()};
p_left = Matrix4x4::RotationY(ry) * p_left; _left = Matrix4x4::RotationY(ry) * _left;
p_up = Matrix4x4::RotationY(ry) * p_up; _up = Matrix4x4::RotationY(ry) * _up;
p_lookAt = Matrix4x4::RotationY(ry) * p_lookAt; _lookAt = Matrix4x4::RotationY(ry) * _lookAt;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), Point4D{0, ry, 0}); attached->rotateRelativePoint(position(), Point4D{0, ry, 0});
} }
void Camera::rotateZ(double rz) { void Camera::rotateZ(double rz) {
p_angle = Point4D{p_angle.x(), p_angle.y(), p_angle.z() + rz}; _angle = Point4D{_angle.x(), _angle.y(), _angle.z() + rz};
p_left = Matrix4x4::RotationZ(rz) * p_left; _left = Matrix4x4::RotationZ(rz) * _left;
p_up = Matrix4x4::RotationZ(rz) * p_up; _up = Matrix4x4::RotationZ(rz) * _up;
p_lookAt = Matrix4x4::RotationZ(rz) * p_lookAt; _lookAt = Matrix4x4::RotationZ(rz) * _lookAt;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), Point4D{0, 0, rz}); attached->rotateRelativePoint(position(), Point4D{0, 0, rz});
} }
@ -167,69 +166,69 @@ void Camera::rotate(const Point4D& r) {
void Camera::rotate(const Point4D& v, double rv) { void Camera::rotate(const Point4D& v, double rv) {
p_left = Matrix4x4::Rotation(v, rv) * p_left; _left = Matrix4x4::Rotation(v, rv) * _left;
p_up = Matrix4x4::Rotation(v, rv) * p_up; _up = Matrix4x4::Rotation(v, rv) * _up;
p_lookAt = Matrix4x4::Rotation(v, rv) * p_lookAt; _lookAt = Matrix4x4::Rotation(v, rv) * _lookAt;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), v, rv); attached->rotateRelativePoint(position(), v, rv);
} }
void Camera::rotateLeft(double rl) { void Camera::rotateLeft(double rl) {
p_angleLeftUpLookAt = Point4D{p_angleLeftUpLookAt.x() + rl, p_angleLeftUpLookAt.y(), p_angleLeftUpLookAt.z()}; _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x() + rl, _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z()};
rotate(p_left, rl); rotate(_left, rl);
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), p_left, rl); attached->rotateRelativePoint(position(), _left, rl);
} }
void Camera::rotateUp(double ru) { void Camera::rotateUp(double ru) {
p_angleLeftUpLookAt = Point4D{p_angleLeftUpLookAt.x(), p_angleLeftUpLookAt.y() + ru, p_angleLeftUpLookAt.z()}; _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y() + ru, _angleLeftUpLookAt.z()};
rotate(p_up, ru); rotate(_up, ru);
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), p_up, ru); attached->rotateRelativePoint(position(), _up, ru);
} }
void Camera::rotateLookAt(double rlAt) { void Camera::rotateLookAt(double rlAt) {
p_angleLeftUpLookAt = Point4D{p_angleLeftUpLookAt.x(), p_angleLeftUpLookAt.y(), p_angleLeftUpLookAt.z() + rlAt}; _angleLeftUpLookAt = Point4D{_angleLeftUpLookAt.x(), _angleLeftUpLookAt.y(), _angleLeftUpLookAt.z() + rlAt};
rotate(p_lookAt, rlAt); rotate(_lookAt, rlAt);
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), p_lookAt, rlAt); attached->rotateRelativePoint(position(), _lookAt, rlAt);
} }
void Camera::rotateRelativePoint(const Point4D &s, const Point4D &r) { void Camera::rotateRelativePoint(const Point4D &s, const Point4D &r) {
p_angle = p_angle + r; _angle = _angle + r;
// Translate XYZ by vector r1 // Translate XYZ by vector r1
Point4D r1 = p_position - s; Point4D r1 = _position - s;
// In translated coordinate system we rotate camera and position // In translated coordinate system we rotate camera and position
Point4D r2 = Matrix4x4::Rotation(r)*r1; Point4D r2 = Matrix4x4::Rotation(r)*r1;
rotate(r); rotate(r);
// After rotation we translate XYZ by vector -r2 and recalculate position // After rotation we translate XYZ by vector -r2 and recalculate position
p_position = s + r2; _position = s + r2;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(s, r); attached->rotateRelativePoint(s, r);
} }
void Camera::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) { void Camera::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) {
// Translate XYZ by vector r1 // Translate XYZ by vector r1
Point4D r1 = p_position - s; Point4D r1 = _position - s;
// In translated coordinate system we rotate camera and position // In translated coordinate system we rotate camera and position
Point4D r2 = Matrix4x4::Rotation(v, r)*r1; Point4D r2 = Matrix4x4::Rotation(v, r)*r1;
rotate(v, r); rotate(v, r);
// After rotation we translate XYZ by vector -r2 and recalculate position // After rotation we translate XYZ by vector -r2 and recalculate position
p_position = s + r2; _position = s + r2;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(s, v, r); attached->rotateRelativePoint(s, v, r);
} }
void Camera::translateToPoint(const Point4D &point) { void Camera::translateToPoint(const Point4D &point) {
translate(point - p_position); translate(point - _position);
} }

View File

@ -12,29 +12,28 @@
class Camera : public Object, public Animatable{ class Camera : public Object, public Animatable{
private: private:
Point4D p_angleLeftUpLookAt; Point4D _angleLeftUpLookAt;
Point4D p_left = Point4D{1, 0, 0, 0}; // internal X Point4D _left = Point4D{1, 0, 0, 0}; // internal X
Point4D p_up = Point4D{0, 1, 0, 0}; // internal Y Point4D _up = Point4D{0, 1, 0, 0}; // internal Y
Point4D p_lookAt = Point4D{0, 0, 1, 0}; // internal Z Point4D _lookAt = Point4D{0, 0, 1, 0}; // internal Z
Matrix4x4 S; // screen space matrix Matrix4x4 _S; // screen space matrix
Matrix4x4 P; // projections matrix Matrix4x4 _P; // projections matrix
Matrix4x4 V; // camera matrix Matrix4x4 _V; // camera matrix
double aspect = 0; double _aspect = 0;
// To accelerate calculations we can use precalculated matrix that does not chance // To accelerate calculations we can use precalculated matrix that does not chance
Matrix4x4 SP; // screen-space-projections matrix Matrix4x4 _SP; // screen-space-projections matrix
Matrix4x4 VM; // camera-model-animation matrix
std::vector<Triangle> triangles; std::vector<Triangle> _triangles;
std::vector<Plane> clipPlanes; std::vector<Plane> _clipPlanes;
bool ready = false; bool _ready = false;
double w = 0; double _w = 0;
double h = 0; double _h = 0;
public: public:
Camera() = default; Camera() = default;
Camera(const Camera& camera) = delete; Camera(const Camera& camera) = delete;
@ -42,28 +41,28 @@ public:
void init(int width, int height, double fov = 110.0, double ZNear = 0.1, double ZFar = 5000.0); void init(int width, int height, double fov = 110.0, double ZNear = 0.1, double ZFar = 5000.0);
std::vector<Triangle>& project(Mesh& mesh, Screen::ViewMode mode); std::vector<Triangle>& project(std::shared_ptr<Mesh> mesh);
void record(); void clear();
[[nodiscard]] int buffSize() const { return triangles.size(); } [[nodiscard]] int buffSize() const { return _triangles.size(); }
std::vector<Triangle>& sorted(); std::vector<Triangle>& sorted();
[[nodiscard]] Point4D position() const override { return p_position; } [[nodiscard]] Point4D position() const override { return _position; }
[[nodiscard]] Point4D angle() const override { return p_angle; } [[nodiscard]] Point4D angle() const override { return _angle; }
[[nodiscard]] Point4D angleLeftUpLookAt() const { return p_angleLeftUpLookAt; } [[nodiscard]] Point4D angleLeftUpLookAt() const { return _angleLeftUpLookAt; }
[[nodiscard]] Point4D eye() const { return p_position; } [[nodiscard]] Point4D eye() const { return _position; }
[[nodiscard]] Point4D left() const { return p_left; } [[nodiscard]] Point4D left() const { return _left; }
[[nodiscard]] Point4D right() const { return -p_left; } [[nodiscard]] Point4D right() const { return -_left; }
[[nodiscard]] Point4D up() const { return p_up; } [[nodiscard]] Point4D up() const { return _up; }
[[nodiscard]] Point4D down() const { return -p_up; } [[nodiscard]] Point4D down() const { return -_up; }
[[nodiscard]] Point4D lookAt() const { return p_lookAt; } [[nodiscard]] Point4D lookAt() const { return _lookAt; }
void translate(const Point4D& dv) override { void translate(const Point4D& dv) override {
p_position = p_position + dv; _position = _position + dv;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->translate(dv); attached->translate(dv);
} }
@ -80,9 +79,9 @@ public:
void rotateUp(double ru); void rotateUp(double ru);
void rotateLookAt(double rlAt); void rotateLookAt(double rlAt);
// Rotate mesh around XYZ by (r.x, r.y, r.z) radians relative val 'point4D' // Rotate body around XYZ by (r.x, r.y, r.z) radians relative val 'point4D'
void rotateRelativePoint(const Point4D& s, const Point4D& r) override; void rotateRelativePoint(const Point4D& s, const Point4D& r) override;
// Rotate mesh around normalised vector 'v' by 'r' radians relative val 'point4D' // Rotate body around normalised vector 'v' by 'r' radians relative val 'point4D'
void rotateRelativePoint(const Point4D& s, const Point4D& v, double r) override; void rotateRelativePoint(const Point4D& s, const Point4D& v, double r) override;
}; };

View File

@ -15,6 +15,8 @@ Engine::Engine() {
} }
void Engine::create(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) { void Engine::create(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) {
_name = name;
screen->open(screenWidth, screenHeight, name, verticalSync, background, style); screen->open(screenWidth, screenHeight, name, verticalSync, background, style);
Log::log("Engine::create(): started engine (" + std::to_string(screenWidth) + " x " + std::to_string(screenHeight) + ") with name '" + name + "'."); Log::log("Engine::create(): started engine (" + std::to_string(screenWidth) + " x " + std::to_string(screenHeight) + ") with name '" + name + "'.");
@ -28,67 +30,35 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name,
screen->clear(); screen->clear();
Time::update(); Time::update();
screen->keyboardControl(); update();
update(Time::deltaTime());
world->garbageCollector(); world->garbageCollector();
/* Project all mesh /* Project all mesh
* Here we project all tris for each mesh from world._objects. * Here we project all _tris for each body from world._objects.
* When we call camera.project(m.second), * When we call camera.project(m.second),
*/ */
// sometimes we dont need to update physics world // sometimes we dont need to update physics world
// (for example in menu or while pause) // (for example in menu or while pause)
// hence we can set 'b_updateWorld' equal to false in setUpdateWorld(bool): // hence we can set '_updateWorld' equal to false in setUpdateWorld(bool):
if(b_updateWorld) { if(_updateWorld) {
camera->record();
for (auto &m : world->objects()) {
m.second->a_update();
camera->project(*m.second, screen->mode());
m.second->updatePhysicsState();
// isCollision detection:
if (m.second->isCollision()) {
m.second->setInCollision(false);
m.second->setCollisionNormal(Point4D{0, 0, 0});
for (auto &obj : world->objects()) {
if(obj.first != m.first) {
std::pair<bool, Simplex> gjk = m.second->checkGJKCollision(obj.second);
if (gjk.first) {
if (obj.second->isCollider()) {
CollisionPoint epa = m.second->EPA(gjk.second, obj.second);
Solver::solveCollision(m.second, obj.second, epa);
}
if (m.second->collisionCallBack() != nullptr)
m.second->collisionCallBack()(obj.first, obj.second);
}
}
}
}
}
// draw projected mesh
for (auto &t : camera->sorted())
screen->triangle(t);
camera->a_update(); camera->a_update();
camera->clear();
triPerSec = camera->buffSize() * Time::fps(); world->update();
world->projectObjectsInCamera(camera);
if (b_debugText) { // draw projected body
screen->debugText(name + "\n\n X: " + for (auto &t : camera->sorted())
std::to_string((camera->eye().x())) + "\n Y: " + screen->drawTriangle(t);
std::to_string((camera->eye().y())) + "\n Z: " +
std::to_string((camera->eye().z())) + "\n\n" + _triPerSec = camera->buffSize() * Time::fps();
std::to_string(screen->width()) + "x" +
std::to_string(screen->height()) + "\n" + printDebugText();
std::to_string(Time::fps()) + gui();
" fps \n" + std::to_string((int) triPerSec) + " tris/s");
}
} }
gui();
screen->display(); screen->display();
} }
exit(); exit();
@ -99,5 +69,18 @@ void Engine::exit() {
screen->close(); screen->close();
} }
ResourceManager::unloadAllResources(); ResourceManager::unloadAllResources();
Log::log("Engine::exit(): exit engine (" + std::to_string(screen->width()) + " x " + std::to_string(screen->height()) + ") with name '" + screen->title() + "'."); Log::log("Engine::exit(): exit engine (" + std::to_string(screen->width()) + " x " + std::to_string(screen->height()) + ") with name '" + screen->name() + "'.");
}
void Engine::printDebugText() const {
if (_debugText) {
screen->debugText(_name + "\n\n X: " +
std::to_string((camera->eye().x())) + "\n Y: " +
std::to_string((camera->eye().y())) + "\n Z: " +
std::to_string((camera->eye().z())) + "\n\n" +
std::to_string(screen->width()) + "x" +
std::to_string(screen->height()) + "\n" +
std::to_string(Time::fps()) +
" fps \n" + std::to_string((int) _triPerSec) + " _tris/s");
}
} }

View File

@ -11,15 +11,19 @@
#include "utils/Log.h" #include "utils/Log.h"
class Engine { class Engine {
private:
std::string _name;
double _triPerSec = 0;
bool _debugText = true;
bool _updateWorld = true;
void printDebugText() const;
protected: protected:
std::shared_ptr<Screen> screen; std::shared_ptr<Screen> screen;
std::shared_ptr<World> world; std::shared_ptr<World> world;
std::shared_ptr<Camera> camera; std::shared_ptr<Camera> camera;
double triPerSec = 0;
bool b_debugText = true;
bool b_updateWorld = true;
public: public:
Engine(); Engine();
@ -28,10 +32,11 @@ public:
void create(int screenWidth = 1920, int screenHeight = 1080, const std::string& name = "engine", bool verticalSync = true, sf::Color background = sf::Color(255, 255, 255), sf::Uint32 style = sf::Style::Default); void create(int screenWidth = 1920, int screenHeight = 1080, const std::string& name = "engine", bool verticalSync = true, sf::Color background = sf::Color(255, 255, 255), sf::Uint32 style = sf::Style::Default);
virtual void start() {}; virtual void start() {};
virtual void update(double elapsedTime) {}; virtual void update() {};
void exit(); void exit();
void debugText(bool value) { b_debugText = value; }
void setUpdateWorld(bool value) { b_updateWorld = value; } void setDebugText(bool value) { _debugText = value; }
void setUpdateWorld(bool value) { _updateWorld = value; }
virtual void gui(){} virtual void gui(){}
}; };

View File

@ -11,13 +11,9 @@
using namespace std; using namespace std;
Mesh Mesh::operator*(const Matrix4x4 &matrix4X4) const {
return Mesh(*this) *= matrix4X4;
}
Mesh &Mesh::operator*=(const Matrix4x4 &matrix4X4) { Mesh &Mesh::operator*=(const Matrix4x4 &matrix4X4) {
for (auto& t : tris) for (auto& t : _tris)
t *= matrix4X4; t = t * matrix4X4;
return *this; return *this;
} }
@ -27,7 +23,7 @@ Mesh &Mesh::loadObj(const std::string& filename, const std::string &materials, c
auto objects = Mesh::LoadObjects(filename, materials, scale); auto objects = Mesh::LoadObjects(filename, materials, scale);
for(auto& obj : objects) { for(auto& obj : objects) {
for (auto &tri : obj->triangles()) { for (auto &tri : obj->triangles()) {
tris.push_back(tri); _tris.push_back(tri);
} }
} }
return *this; return *this;
@ -38,10 +34,10 @@ Mesh::Mesh(const std::string& filename, const std::string &materials, const Poin
} }
Mesh::Mesh(const vector<Triangle> &tries){ Mesh::Mesh(const vector<Triangle> &tries){
tris = tries; _tris = tries;
} }
Mesh::Mesh(const Mesh& mesh) : Animatable(mesh) { Mesh::Mesh(const Mesh& mesh) {
*this = mesh; *this = mesh;
} }
@ -50,17 +46,17 @@ Mesh Mesh::Obj(const std::string& filename) {
} }
void Mesh::rotate(const Point4D &r) { void Mesh::rotate(const Point4D &r) {
p_angle = p_angle + r; _angle = _angle + r;
*this *= Matrix4x4::Rotation(r); *this *= Matrix4x4::Rotation(r);
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), r); attached->rotateRelativePoint(position(), r);
} }
void Mesh::rotate(const Point4D &v, double r) { void Mesh::rotate(const Point4D &v, double r) {
*this *= Matrix4x4::Rotation(v, r); *this *= Matrix4x4::Rotation(v, r);
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(position(), v, r); attached->rotateRelativePoint(position(), v, r);
} }
@ -71,72 +67,71 @@ void Mesh::scale(const Point4D &s) {
} }
void Mesh::translate(const Point4D &t) { void Mesh::translate(const Point4D &t) {
p_position = p_position + t; _position = _position + t;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->translate(t); attached->translate(t);
} }
Mesh &Mesh::operator=(const Mesh &mesh) { Mesh &Mesh::operator=(const Mesh &mesh) {
tris = mesh.tris; _tris = mesh._tris;
p_position = mesh.p_position; _position = mesh._position;
c_color = mesh.c_color; _color = mesh._color;
return *this; return *this;
} }
void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &r) { void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &r) {
p_angle = p_angle + r; _angle = _angle + r;
// Translate XYZ by vector r1 // Translate XYZ by vector r1
Point4D r1 = p_position - s; Point4D r1 = _position - s;
*this *= Matrix4x4::Translation(r1); *this *= Matrix4x4::Translation(r1);
// In translated coordinate system we rotate mesh and position // In translated coordinate system we rotate body and position
Matrix4x4 rotationMatrix = Matrix4x4::Rotation(r); Matrix4x4 rotationMatrix = Matrix4x4::Rotation(r);
Point4D r2 = rotationMatrix*r1; Point4D r2 = rotationMatrix*r1;
*this *= rotationMatrix; *this *= rotationMatrix;
// After rotation we translate XYZ by vector -r2 and recalculate position // After rotation we translate XYZ by vector -r2 and recalculate position
*this *= Matrix4x4::Translation(-r2); *this *= Matrix4x4::Translation(-r2);
p_position = s + r2; _position = s + r2;
if(v_attached.empty()) if(_attachedObjects.empty())
return; return;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(s, r); attached->rotateRelativePoint(s, r);
} }
void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) { void Mesh::rotateRelativePoint(const Point4D &s, const Point4D &v, double r) {
// Translate XYZ by vector r1 // Translate XYZ by vector r1
Point4D r1 = p_position - s; Point4D r1 = _position - s;
*this *= Matrix4x4::Translation(r1); *this *= Matrix4x4::Translation(r1);
// In translated coordinate system we rotate mesh and position // In translated coordinate system we rotate body and position
Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, r); Matrix4x4 rotationMatrix = Matrix4x4::Rotation(v, r);
Point4D r2 = rotationMatrix*r1; Point4D r2 = rotationMatrix*r1;
*this *= rotationMatrix; *this *= rotationMatrix;
// After rotation we translate XYZ by vector -r2 and recalculate position // After rotation we translate XYZ by vector -r2 and recalculate position
*this *= Matrix4x4::Translation(-r2); *this *= Matrix4x4::Translation(-r2);
p_position = s + r2; _position = s + r2;
for(auto attached : v_attached) for(auto attached : _attachedObjects)
attached->rotateRelativePoint(s, v, r); attached->rotateRelativePoint(s, v, r);
} }
void Mesh::translateToPoint(const Point4D &point) { void Mesh::translateToPoint(const Point4D &point) {
translate(point - p_position); translate(point - _position);
} }
void Mesh::setColor(sf::Color c) { void Mesh::setColor(sf::Color c) {
c_color = c; _color = c;
for (auto& t : tris) for (auto& t : _tris)
t.color = c_color; t = Triangle(t[0], t[1], t[2], _color);
} }
std::vector<std::shared_ptr<Mesh>> std::vector<std::shared_ptr<Mesh>> Mesh::LoadObjects(const string &filename, const string &materials, const Point4D &scale) {
Mesh::LoadObjects(const string &filename, const string &materials, const Point4D &scale) {
std::vector<std::shared_ptr<Mesh>> objects; std::vector<std::shared_ptr<Mesh>> objects;
map<string, sf::Color> maters; map<string, sf::Color> maters;
@ -209,8 +204,7 @@ Mesh::LoadObjects(const string &filename, const string &materials, const Point4D
{ {
int f[3]; int f[3];
s >> junk >> f[0] >> f[1] >> f[2]; s >> junk >> f[0] >> f[1] >> f[2];
tris.emplace_back(verts[f[0] - 1], verts[f[1] - 1], verts[f[2] - 1] ); tris.emplace_back(verts[f[0] - 1], verts[f[1] - 1], verts[f[2] - 1], currentColor);
tris.back().color = currentColor;
} }
} }
@ -225,6 +219,7 @@ Mesh::LoadObjects(const string &filename, const string &materials, const Point4D
} }
Mesh Mesh::LineTo(const Point4D& from, const Point4D& to, double line_width, sf::Color color) { Mesh Mesh::LineTo(const Point4D& from, const Point4D& to, double line_width, sf::Color color) {
Mesh line; Mesh line;
Point4D v1 = (to - from).normalized(); Point4D v1 = (to - from).normalized();
@ -242,7 +237,7 @@ Mesh Mesh::LineTo(const Point4D& from, const Point4D& to, double line_width, sf:
Point4D p7 = 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 p8 = to + v2 * line_width/2.0 - v3 * line_width/2.0;
line.tris = { line._tris = {
{ p2, p4, p1 }, { p2, p4, p1 },
{ p2, p3, p4 }, { p2, p3, p4 },
{ p1, p6, p2 }, { p1, p6, p2 },
@ -259,5 +254,10 @@ Mesh Mesh::LineTo(const Point4D& from, const Point4D& to, double line_width, sf:
line.setColor(color); 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; return line;
} }

View File

@ -8,24 +8,16 @@
#include <vector> #include <vector>
#include "Triangle.h" #include "Triangle.h"
#include "animation/Animatable.h" #include "animation/Animatable.h"
#include "physics/RigidBody.h"
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
#include "Object.h" #include "Object.h"
class Mesh : public Object, public Animatable, public RigidBody { class Mesh : public Object, public Animatable {
private: private:
// Operations with Matrix4x4 std::vector<Triangle> _tris;
[[nodiscard]] Mesh operator*(const Matrix4x4& matrix4X4) const; sf::Color _color = sf::Color(255, 245, 194);
Mesh& operator*=(const Matrix4x4& matrix4X4);
protected:
std::vector<Triangle> tris;
bool _visible = true; bool _visible = true;
sf::Color c_color = sf::Color(255, 245, 194); Mesh& operator*=(const Matrix4x4& matrix4X4);
std::function<void(const std::string&, std::shared_ptr<Mesh>)> _collisionCallBack;
public: public:
Mesh() = default; Mesh() = default;
@ -37,29 +29,29 @@ public:
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 Point4D& scale = Point4D{1, 1, 1});
[[nodiscard]] std::vector<Triangle>const &triangles() const { return tris; } [[nodiscard]] std::vector<Triangle>const &triangles() const { return _tris; }
[[nodiscard]] std::vector<Triangle>& triangles() override { return tris; } [[nodiscard]] std::vector<Triangle>& triangles() override { return _tris; }
void setTriangles(const std::vector<Triangle>& t) override { tris = t; } void setTriangles(const std::vector<Triangle>& t) override { _tris = t; }
// Translate mesh // Translate body
void translate(const Point4D& t) override; void translate(const Point4D& t) override;
void translateToPoint(const Point4D& point); void translateToPoint(const Point4D& point);
// Rotate mesh around XYZ axes // Rotate body around XYZ axes
void rotate(const Point4D& r) override; void rotate(const Point4D& r) override;
// Rotate mesh around normalised vector 'v' by 'r' radians // Rotate body around normalised vector 'v' by 'r' radians
void rotate(const Point4D& v, double r) override; void rotate(const Point4D& v, double r) override;
// Rotate mesh around XYZ by (r.x, r.y, r.z) radians relative val 'point4D' // 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 Point4D& point4D, const Point4D& r) override;
// Rotate mesh around normalised vector 'v' by 'r' radians relative val 'point4D' // Rotate body around normalised vector 'v' by 'r' radians relative val 'point4D'
void rotateRelativePoint(const Point4D& point4D, const Point4D& v, double r) override; void rotateRelativePoint(const Point4D& point4D, const Point4D& v, double r) override;
void scale(const Point4D& s); void scale(const Point4D& s);
void rotateToAngle(const Point4D& v) { rotate(v - p_angle); } void rotateToAngle(const Point4D& v) { rotate(v - _angle); }
[[nodiscard]] Point4D position() const override { return p_position; } [[nodiscard]] Point4D position() const override { return _position; }
[[nodiscard]] Point4D angle() const override { return p_angle; } [[nodiscard]] Point4D angle() const override { return _angle; }
[[nodiscard]] sf::Color color() const override { return c_color; } [[nodiscard]] sf::Color color() const override { return _color; }
void setColor(sf::Color c) override; void setColor(sf::Color c) override;
Mesh static Obj(const std::string& filename); Mesh static Obj(const std::string& filename);
@ -69,9 +61,6 @@ public:
[[nodiscard]] bool isVisible() const { return _visible; } [[nodiscard]] bool isVisible() const { return _visible; }
std::vector<std::shared_ptr<Mesh>> static LoadObjects(const std::string& filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1}); std::vector<std::shared_ptr<Mesh>> static LoadObjects(const std::string& filename, const std::string &materials = "", const Point4D& scale = Point4D{1, 1, 1});
[[nodiscard]] const std::function<void(const std::string&, std::shared_ptr<Mesh>)>& collisionCallBack() const { return _collisionCallBack; }
void setCollisionCallBack(const std::function<void(const std::string&, std::shared_ptr<Mesh>)>& f) { _collisionCallBack = f; }
}; };

View File

@ -11,10 +11,10 @@
class Object { class Object {
protected: protected:
std::vector<std::shared_ptr<Object>> v_attached; std::vector<std::shared_ptr<Object>> _attachedObjects;
Point4D p_position; Point4D _position;
Point4D p_angle; Point4D _angle;
public: public:
Object() = default; Object() = default;
@ -24,11 +24,11 @@ public:
virtual void rotate(const Point4D& v, double rv) {} virtual void rotate(const Point4D& v, double rv) {}
virtual void rotateRelativePoint(const Point4D& s, const Point4D& v, double r) {} virtual void rotateRelativePoint(const Point4D& s, const Point4D& v, double r) {}
[[nodiscard]] Point4D position() const { return p_position; } [[nodiscard]] Point4D position() const { return _position; }
[[nodiscard]] Point4D angle() const { return p_angle; } [[nodiscard]] Point4D angle() const { return _angle; }
void attach(std::shared_ptr<Object> object) { void attach(std::shared_ptr<Object> object) {
v_attached.push_back(std::move(object)); _attachedObjects.push_back(object);
} }
}; };

View File

@ -5,35 +5,34 @@
#include "Plane.h" #include "Plane.h"
Plane::Plane(const Triangle& tri) { Plane::Plane(const Triangle& tri) {
triangle = tri; _triangle = tri;
n = tri.norm(); _n = tri.norm();
p = tri[0]; _p = tri[0];
} }
Plane::Plane(const Point4D &N, const Point4D &P) { Plane::Plane(const Point4D &N, const Point4D &P) {
n = N; _n = N.normalized();
p = P; _p = P;
} }
Plane::Plane(const Plane &plane) { Plane::Plane(const Plane &plane) {
triangle = plane.triangle; _triangle = plane._triangle;
n = plane.n; _n = plane._n;
p = plane.p; _p = plane._p;
} }
double Plane::distance(const Point4D &point4D) const { double Plane::distance(const Point4D &point4D) const {
return point4D.dot(n) - p.dot(n); return point4D.dot(_n) - _p.dot(_n);
} }
std::pair<Point4D, double> Plane::intersection(const Point4D &start, const Point4D &end) { std::pair<Point4D, double> Plane::intersection(const Point4D &start, const Point4D &end) const {
double s_dot_n = start.dot(n); double s_dot_n = start.dot(_n);
double k = (s_dot_n - p.dot(n))/(s_dot_n - end.dot(n)); double k = (s_dot_n - _p.dot(_n)) / (s_dot_n - end.dot(_n));
Point4D res = start + (end - start)*k; Point4D res = start + (end - start)*k;
return std::make_pair(res, k); return std::make_pair(res, k);
} }
int Plane::clip(Triangle &tri, Triangle &additional_tri) { int Plane::clip(Triangle &tri, Triangle &additional_tri) const {
n = n.normalized();
Point4D insidePoints[3]; int inside = 0; Point4D insidePoints[3]; int inside = 0;
Point4D outsidePoints[3]; int outside = 0; Point4D outsidePoints[3]; int outside = 0;
@ -49,20 +48,14 @@ int Plane::clip(Triangle &tri, Triangle &additional_tri) {
} }
if(inside == 0) { if(inside == 0) {
tri.clip = Triangle::Skipped;
return 0; return 0;
} }
if(inside == 1) { if(inside == 1) {
std::pair<Point4D, double> intersect1 = intersection(insidePoints[0], outsidePoints[0]); std::pair<Point4D, double> intersect1 = intersection(insidePoints[0], outsidePoints[0]);
std::pair<Point4D, double> intersect2 = intersection(insidePoints[0], outsidePoints[1]); std::pair<Point4D, double> intersect2 = intersection(insidePoints[0], outsidePoints[1]);
tri[0] = insidePoints[0];
tri[1] = intersect1.first; tri = Triangle(insidePoints[0], intersect1.first, intersect2.first, tri.color());
tri[2] = intersect2.first;
tri.clip = Triangle::Cropped;
return 1; return 1;
} }
@ -71,20 +64,8 @@ int Plane::clip(Triangle &tri, Triangle &additional_tri) {
std::pair<Point4D, double> intersect1 = intersection(insidePoints[0], outsidePoints[0]); std::pair<Point4D, double> intersect1 = intersection(insidePoints[0], outsidePoints[0]);
std::pair<Point4D, double> intersect2 = intersection(insidePoints[1], outsidePoints[0]); std::pair<Point4D, double> intersect2 = intersection(insidePoints[1], outsidePoints[0]);
tri[0] = insidePoints[0]; tri = Triangle(insidePoints[0], intersect1.first, insidePoints[1], tri.color());
additional_tri = Triangle(intersect1.first, intersect2.first, insidePoints[1], tri.color());
tri[1] = intersect1.first;
tri[2] = insidePoints[1];
additional_tri[0] = intersect1.first;
additional_tri[1] = intersect2.first;
additional_tri[2] = insidePoints[1];
tri.clip = Triangle::Doubled;
additional_tri.clip = Triangle::Doubled;
return 2; return 2;
} }

View File

@ -11,24 +11,24 @@
class Plane { class Plane {
private: private:
// You can define plane by defining the points in 3D space // You can define plane by defining the points in 3D space
Triangle triangle; Triangle _triangle;
// Or by defining normal vector and one val laying on the plane // Or by defining normal vector and one val laying on the plane
Point4D n = Point4D{0, 0, 1, 0}; Point4D _n = Point4D{0, 0, 1, 0};
Point4D p{}; Point4D _p{};
public: public:
// A plain with normal vector 'n' and val 'p' lays on the plane // A plain with normal vector '_n' and val '_p' lays on the plane
Plane() = default; Plane() = default;
Plane(const Point4D& N, const Point4D& P); Plane(const Point4D& N, const Point4D& P);
Plane(const Plane& plane); Plane(const Plane& plane);
explicit Plane(const Triangle& tri); explicit Plane(const Triangle& tri);
[[nodiscard]] double distance(const Point4D& point4D) const; [[nodiscard]] double distance(const Point4D& point4D) const;
// Point4D in space where line ('start' to 'end') intersects plain with normal vector 'n' and val 'p' lays on the plane // Point4D in space where line ('start' to 'end') intersects plain with normal vector '_n' and val '_p' lays on the plane
std::pair<Point4D, double> intersection(const Point4D& start, const Point4D& end); [[nodiscard]] std::pair<Point4D, double> intersection(const Point4D& start, const Point4D& end) const;
int clip(Triangle& tri, Triangle& additional_tri); int clip(Triangle& tri, Triangle& additional_tri) const;
[[nodiscard]] Point4D N() const { return n; } [[nodiscard]] Point4D N() const { return _n; }
[[nodiscard]] Point4D P() const { return p; } [[nodiscard]] Point4D P() const { return _p; }
}; };

View File

@ -5,7 +5,7 @@
#include "ResourceManager.h" #include "ResourceManager.h"
#include <map> #include <map>
#include <memory> #include <memory>
#include <iostream>
namespace ResourceManager namespace ResourceManager
{ {
namespace namespace
@ -13,7 +13,6 @@ namespace ResourceManager
std::map<std::string, std::shared_ptr<sf::Texture>> _textures; std::map<std::string, std::shared_ptr<sf::Texture>> _textures;
std::map<std::string, std::shared_ptr<sf::Font>> _fonts; std::map<std::string, std::shared_ptr<sf::Font>> _fonts;
std::map<std::string, std::shared_ptr<sf::SoundBuffer>> _soundBuffers; std::map<std::string, std::shared_ptr<sf::SoundBuffer>> _soundBuffers;
std::map<std::string, std::shared_ptr<sf::Shader>> _shaders;
} }
void unloadTextures() void unloadTextures()
@ -36,18 +35,11 @@ namespace ResourceManager
_fonts.clear(); _fonts.clear();
} }
void unloadShaders() {
for (auto& shader : _shaders)
shader.second.reset();
_shaders.clear();
}
void unloadAllResources() void unloadAllResources()
{ {
unloadTextures(); unloadTextures();
unloadSoundBuffers(); unloadSoundBuffers();
unloadFonts(); unloadFonts();
unloadShaders();
} }
std::shared_ptr<sf::Texture> loadTexture(const std::string& filename) std::shared_ptr<sf::Texture> loadTexture(const std::string& filename)
@ -103,21 +95,4 @@ namespace ResourceManager
return font; return font;
} }
std::shared_ptr<sf::Shader> loadShader(const std::string& filename, sf::Shader::Type type) {
// If Shader is already loaded - return pointer to it
auto it = _shaders.find(filename);
if (it != _shaders.end())
return it->second;
// Otherwise - try to load it. If failure - return zero
std::shared_ptr<sf::Shader> shader(new sf::Shader);
if (!shader->loadFromFile(filename, type))
return nullptr;
// If success - remember and return texture pointer
_shaders.emplace(filename, shader);
return shader;
}
} }

View File

@ -25,7 +25,6 @@ namespace ResourceManager
std::shared_ptr<sf::Texture> loadTexture(const std::string& filename); std::shared_ptr<sf::Texture> loadTexture(const std::string& filename);
std::shared_ptr<sf::Font> loadFont(const std::string& filename); std::shared_ptr<sf::Font> loadFont(const std::string& filename);
std::shared_ptr<sf::SoundBuffer> loadSoundBuffer(const std::string& filename); std::shared_ptr<sf::SoundBuffer> loadSoundBuffer(const std::string& filename);
std::shared_ptr<sf::Shader> loadShader(const std::string& filename, sf::Shader::Type type);
}; };

View File

@ -11,15 +11,15 @@
void Screen::open(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) { void Screen::open(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) {
this->name = name; _name = name;
w = screenWidth; _w = screenWidth;
h = screenHeight; _h = screenHeight;
this->background = background; _background = background;
sf::ContextSettings settings; sf::ContextSettings settings;
settings.antialiasingLevel = 8; settings.antialiasingLevel = 8;
window.create(sf::VideoMode(w, h), name, style, settings); window.create(sf::VideoMode(_w, _h), name, style, settings);
window.setVerticalSyncEnabled(verticalSync); window.setVerticalSyncEnabled(verticalSync);
} }
@ -31,44 +31,29 @@ void Screen::display() {
} }
} }
std::string title = name + " (" + std::to_string(Time::fps()) + " fps)"; std::string title = _name + " (" + std::to_string(Time::fps()) + " fps)";
window.setTitle(title); window.setTitle(title);
window.display(); window.display();
} }
void Screen::clear() { void Screen::clear() {
window.clear(background); window.clear(_background);
} }
void Screen::triangle(const Triangle& triangle) void Screen::drawTriangle(const Triangle& triangle)
{ {
if(vm == Frame || vm == Borders || vm == Xray || vm == Clipped || vm == Transparency || vm == Normals) {
sf::Vertex lines[4] =
{
sf::Vertex(sf::Vector2f(triangle[0].x(), triangle[0].y()), sf::Color(0, 0, 0, 255)),
sf::Vertex(sf::Vector2f(triangle[1].x(), triangle[1].y()), sf::Color(0, 0, 0, 255)),
sf::Vertex(sf::Vector2f(triangle[2].x(), triangle[2].y()), sf::Color(0, 0, 0, 255)),
sf::Vertex(sf::Vector2f(triangle[0].x(), triangle[0].y()), sf::Color(0, 0, 0, 255))
};
window.draw(lines, 4, sf::LineStrip);
}
if(vm == Frame || vm == Xray)
return; // no texture when we turn on Frame or Xray mode
sf::Vertex tris[3] = sf::Vertex tris[3] =
{ {
sf::Vertex(sf::Vector2f(triangle[0].x(), triangle[0].y()), triangle.color), sf::Vertex(sf::Vector2f(triangle[0].x(), triangle[0].y()), triangle.color()),
sf::Vertex(sf::Vector2f(triangle[1].x(), triangle[1].y()), triangle.color), sf::Vertex(sf::Vector2f(triangle[1].x(), triangle[1].y()), triangle.color()),
sf::Vertex(sf::Vector2f(triangle[2].x(), triangle[2].y()), triangle.color) sf::Vertex(sf::Vector2f(triangle[2].x(), triangle[2].y()), triangle.color())
}; };
window.draw(tris, 3, sf::Triangles); window.draw(tris, 3, sf::Triangles);
} }
void Screen::title(const std::string& title) void Screen::setName(const std::string& title) {
{ _name = title;
name = title;
} }
bool Screen::isOpen() { bool Screen::isOpen() {
@ -89,49 +74,28 @@ Point4D Screen::getMousePosition() const {
} }
Point4D Screen::getMouseDisplacement() const { Point4D Screen::getMouseDisplacement() const {
sf::Vector2<int> disp = sf::Mouse::getPosition(window) - sf::Vector2<int>(w/2, h/2); sf::Vector2<int> disp = sf::Mouse::getPosition(window) - sf::Vector2<int>(_w/2, _h/2);
setMouseInCenter(); setMouseInCenter();
return Point4D(disp.x, disp.y, 0, 0); return Point4D(disp.x, disp.y, 0, 0);
} }
void Screen::setMouseInCenter() const { void Screen::setMouseInCenter() const {
sf::Mouse::setPosition({ w / 2, h / 2 }, window); sf::Mouse::setPosition({ _w / 2, _h / 2 }, window);
} }
void Screen::setMouseCursorVisible(bool visible) { void Screen::setMouseCursorVisible(bool visible) {
window.setMouseCursorVisible(visible); window.setMouseCursorVisible(visible);
} }
void Screen::keyboardControl() {
// Check all input after this condition please
if (!window.hasFocus())
return;
if(isKeyTapped(sf::Keyboard::Num1))
setMode(ViewMode::Default);
if(isKeyTapped(sf::Keyboard::Num2))
setMode(ViewMode::Borders);
if(isKeyTapped(sf::Keyboard::Num3))
setMode(ViewMode::Transparency);
if(isKeyTapped(sf::Keyboard::Num4))
setMode(ViewMode::Frame);
if(isKeyTapped(sf::Keyboard::Num5))
setMode(ViewMode::Xray);
if(isKeyTapped(sf::Keyboard::Num6))
setMode(ViewMode::Clipped);
if(isKeyTapped(sf::Keyboard::Num7))
setMode(ViewMode::Normals);
}
bool Screen::isKeyTapped(sf::Keyboard::Key key) { bool Screen::isKeyTapped(sf::Keyboard::Key key) {
if (!Screen::isKeyPressed(key)) if (!Screen::isKeyPressed(key))
return false; return false;
if(tappedKeys.count(key) == 0) { if(_tappedKeys.count(key) == 0) {
tappedKeys.emplace(key, Time::time()); _tappedKeys.emplace(key, Time::time());
return true; return true;
} else if((Time::time() - tappedKeys[key]) > 0.2) { } else if((Time::time() - _tappedKeys[key]) > 0.2) {
tappedKeys[key] = Time::time(); _tappedKeys[key] = Time::time();
return true; return true;
} }
return false; return false;
@ -145,11 +109,11 @@ bool Screen::isButtonTapped(sf::Mouse::Button button) {
if (!Screen::isButtonPressed(button)) if (!Screen::isButtonPressed(button))
return false; return false;
if(tappedButtons.count(button) == 0) { if(_tappedButtons.count(button) == 0) {
tappedButtons.emplace(button, Time::time()); _tappedButtons.emplace(button, Time::time());
return true; return true;
} else if((Time::time() - tappedButtons[button]) > 0.2) { } else if((Time::time() - _tappedButtons[button]) > 0.2) {
tappedButtons[button] = Time::time(); _tappedButtons[button] = Time::time();
return true; return true;
} }
return false; return false;
@ -159,7 +123,7 @@ bool Screen::isButtonTapped(sf::Mouse::Button button) {
void Screen::debugText(const std::string& text) { void Screen::debugText(const std::string& text) {
sf::Text t; sf::Text t;
t.setFont(*ResourceManager::loadFont(font)); t.setFont(*ResourceManager::loadFont(_font));
t.setString(text); t.setString(text);
t.setCharacterSize(30); t.setCharacterSize(30);
t.setFillColor(sf::Color::Black); t.setFillColor(sf::Color::Black);

View File

@ -13,33 +13,18 @@
#include "utils/Time.h" #include "utils/Time.h"
class Screen { class Screen {
public:
enum ViewMode {
Default = 0,
Frame,
Borders,
Xray,
Clipped,
Transparency,
Normals
};
private: private:
int w = 1920; int _w = 1920;
int h = 1080; int _h = 1080;
std::string name; std::string _name;
sf::Color background; sf::Color _background;
Screen::ViewMode vm = Screen::ViewMode::Default; std::map<sf::Keyboard::Key, double> _tappedKeys;
std::map<sf::Mouse::Button, double> _tappedButtons;
std::map<sf::Keyboard::Key, double> tappedKeys; std::string _font = "../engine/fonts/Roboto-Thin.ttf";
std::map<sf::Mouse::Button, double> tappedButtons;
std::string font = "../engine/fonts/Roboto-Thin.ttf";
int frame = 0;
int scene = 0; // the number of scene
public: public:
sf::RenderWindow window; sf::RenderWindow window;
@ -49,10 +34,10 @@ public:
void display(); void display();
void clear(); void clear();
void triangle(const Triangle& triangle ); void drawTriangle(const Triangle& triangle);
void title(const std::string& title); void setName(const std::string& title);
std::string title() const { return name; }; std::string name() const { return _name; };
bool isOpen(); bool isOpen();
@ -72,11 +57,6 @@ public:
void setMouseInCenter() const; void setMouseInCenter() const;
void setMouseCursorVisible(bool visible); void setMouseCursorVisible(bool visible);
void setMode(ViewMode mode) { vm = mode; }
[[nodiscard]] ViewMode mode() const { return vm; }
void keyboardControl();
void debugText(const std::string& text); void debugText(const std::string& text);
}; };

View File

@ -5,76 +5,55 @@
#include "Triangle.h" #include "Triangle.h"
Triangle::Triangle () { Triangle::Triangle () {
p[0] = Point4D{0,0,0,1}; _p[0] = Point4D{0, 0, 0, 1};
p[1] = Point4D{0,0,0,1}; _p[1] = Point4D{0, 0, 0, 1};
p[2] = Point4D{0,0,0,1}; _p[2] = Point4D{0, 0, 0, 1};
} }
Triangle::Triangle(const Point4D& p1, const Point4D& p2, const Point4D& p3, double w) { Triangle::Triangle(const Point4D& p1, const Point4D& p2, const Point4D& p3, sf::Color color) {
p[0] = Point4D{p1.x(), p1.y(), p1.z(), w}; _p[0] = p1;
p[1] = Point4D{p2.x(), p2.y(), p2.z(), w}; _p[1] = p2;
p[2] = Point4D{p3.x(), p3.y(), p3.z(), w}; _p[2] = p3;
_color = color;
} }
Triangle Triangle::operator*(const Matrix4x4 &matrix4X4) const { Triangle Triangle::operator*(const Matrix4x4 &matrix4X4) const {
return Triangle(*this) *= matrix4X4; Triangle res(*this);
}
Triangle &Triangle::operator*=(const Matrix4x4 &matrix4X4) { res._p[0] = matrix4X4 * _p[0];
p[0] = matrix4X4 * p[0]; res._p[1] = matrix4X4 * _p[1];
p[1] = matrix4X4 * p[1]; res._p[2] = matrix4X4 * _p[2];
p[2] = matrix4X4 * p[2];
return *this; return res;
} }
Point4D Triangle::norm() const { Point4D Triangle::norm() const {
Point4D v1 = p[1] - p[0]; Point4D v1 = _p[1] - _p[0];
Point4D v2 = p[2] - p[0]; Point4D v2 = _p[2] - _p[0];
return v1.cross3D(v2).normalized(); return v1.cross3D(v2).normalized();
} }
Point4D Triangle::operator[](int i) const { Point4D Triangle::operator[](int i) const {
return p[i]; return _p[i];
}
Point4D &Triangle::operator[](int i) {
return p[i];
}
Point4D Triangle::pos() const {
return (p[0] + p[1] + p[2])/3.0;
} }
Triangle::Triangle(const Triangle &triangle) { Triangle::Triangle(const Triangle &triangle) {
clip = triangle.clip; _color = triangle._color;
color = triangle.color; _p[0] = triangle[0];
p[0] = triangle[0]; _p[1] = triangle[1];
p[1] = triangle[1]; _p[2] = triangle[2];
p[2] = triangle[2];
} }
bool Triangle::isPointInside(const Point4D &point) const { bool Triangle::isPointInside(const Point4D &point) const {
Point4D triangleNorm = norm(); Point4D triangleNorm = norm();
double dot1 = (point - p[0]).cross3D(p[1] - p[0]).dot(triangleNorm); 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 dot2 = (point - _p[1]).cross3D(_p[2] - _p[1]).dot(triangleNorm);
double dot3 = (point - p[2]).cross3D(p[0] - p[2]).dot(triangleNorm); double dot3 = (point - _p[2]).cross3D(_p[0] - _p[2]).dot(triangleNorm);
if((dot1 >= 0 && dot2 >= 0 && dot3 >= 0) || (dot1 <= 0 && dot2 <= 0 && dot3 <= 0)) if((dot1 >= 0 && dot2 >= 0 && dot3 >= 0) || (dot1 <= 0 && dot2 <= 0 && dot3 <= 0))
return true; return true;
return false; return false;
} }
Triangle &Triangle::operator=(const Triangle &triangle) {
if(&triangle != this) {
clip = triangle.clip;
color = triangle.color;
p[0] = triangle[0];
p[1] = triangle[1];
p[2] = triangle[2];
}
return *this;
}

View File

@ -10,34 +10,25 @@
#include <SFML/Graphics.hpp> #include <SFML/Graphics.hpp>
class Triangle { class Triangle {
private:
sf::Color _color;
Point4D _p[3];
public: public:
// This is for clipping debug: you can distinguish how this triangle was clipped
enum ClipMode {
None = 0,
Cropped,
Doubled,
Skipped
};
ClipMode clip = None;
sf::Color color;
Point4D p[3];
Triangle (); Triangle ();
Triangle (const Triangle& triangle); Triangle (const Triangle& triangle);
Triangle (const Point4D& p1, const Point4D& p2, const Point4D& p3, double w = 1); Triangle (const Point4D& p1, const Point4D& p2, const Point4D& p3, sf::Color color = {0, 0, 0});
Triangle& operator=(const Triangle& triangle);
[[nodiscard]] Point4D operator[] (int i) const; [[nodiscard]] Point4D operator[] (int i) const;
[[nodiscard]] Point4D& operator[] (int i);
[[nodiscard]] Point4D norm() const; [[nodiscard]] Point4D norm() const;
// Operations with Matrix4x4 // Operations with Matrix4x4
[[nodiscard]] Triangle operator*(const Matrix4x4& matrix4X4) const; [[nodiscard]] Triangle operator*(const Matrix4x4& matrix4X4) const;
Triangle& operator*=(const Matrix4x4& matrix4X4);
[[nodiscard]] Point4D pos() const;
[[nodiscard]] bool isPointInside(const Point4D& point) const; [[nodiscard]] bool isPointInside(const Point4D& point) const;
[[nodiscard]] sf::Color color() const { return _color; }
}; };

View File

@ -2,35 +2,27 @@
// Created by Иван Ильин on 13.01.2021. // Created by Иван Ильин on 13.01.2021.
// //
#include <fstream>
#include <sstream>
#include "World.h" #include "World.h"
#include "utils/Log.h" #include "utils/Log.h"
#include "Plane.h" #include "Plane.h"
#include "physics/Solver.h"
using namespace std; using namespace std;
void World::addMesh(std::shared_ptr<Mesh> mesh, const string &name) { void World::addBody(std::shared_ptr<RigidBody> body, const string &name) {
_objects.emplace(name, mesh); _objects.emplace(name, body);
Log::log("World::addMesh(): inserted mesh '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " tris."); Log::log("World::addBody(): inserted body '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " _tris.");
} }
void World::loadObj(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 Point4D& scale) {
_objects.emplace(name, std::make_shared<Mesh>(filename, materials, scale)); _objects.emplace(name, std::make_shared<RigidBody>(Mesh(filename, materials, scale)));
Log::log("World::loadObj(): inserted mesh from " + filename + " with name '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " tris."); Log::log("World::loadBody(): inserted body from " + filename + " with name '" + name + "' with " + std::to_string(_objects[name]->triangles().size()) + " _tris.");
} }
void World::removeMesh(const string &name) { void World::removeBody(const string &name) {
_objToRemove.push_back(name); _objToRemove.push_back(name);
} }
std::shared_ptr<Mesh> World::operator[](const string &name) {
if(_objects.count(name) == 0)
Log::log("World::operator[]: mesh '" + name + "' does not exist.");
return _objects.find(name)->second;
}
std::pair<Point4D, string> World::rayCast(const Point4D& from, const Point4D& to) { std::pair<Point4D, string> World::rayCast(const Point4D& from, const Point4D& to) {
std::pair<Point4D, string> result{Point4D{0, 0,0, -1}, ""}; std::pair<Point4D, string> result{Point4D{0, 0,0, -1}, ""};
@ -41,7 +33,7 @@ std::pair<Point4D, string> World::rayCast(const Point4D& from, const Point4D& to
continue; continue;
for(auto& tri : object.second->triangles()) { for(auto& tri : object.second->triangles()) {
Triangle tri_translated(tri[0] + object.second->position(), tri[1] + object.second->position(), tri[2] + object.second->position(), 0); Triangle tri_translated(tri[0] + object.second->position(), tri[1] + object.second->position(), tri[2] + object.second->position());
Plane plane(tri_translated); Plane plane(tri_translated);
auto intersection = plane.intersection(from, to); auto intersection = plane.intersection(from, to);
@ -59,23 +51,63 @@ void World::loadMap(const string &filename, const string &name, const Point4D &s
auto objs = Mesh::LoadObjects(filename, materials, scale); auto objs = Mesh::LoadObjects(filename, materials, scale);
for(int i = 0; i < objs.size(); i++) { for(int i = 0; i < objs.size(); i++) {
string meshName = name + "_" + to_string(i); string meshName = name + "_" + to_string(i);
addMesh(objs[i], meshName); addBody(std::make_shared<RigidBody>(*objs[i]), meshName);
} }
} }
void World::garbageCollector() { void World::garbageCollector() {
for(auto& obj : _objToRemove) { for(auto& obj : _objToRemove) {
if(_objects.erase(obj) > 0) if(_objects.erase(obj) > 0)
Log::log("World::garbageCollector(): removed mesh '" + obj + "'"); Log::log("World::garbageCollector(): removed body '" + obj + "'");
else else
Log::log("World::garbageCollector(): cannot remove mesh '" + obj + "': mesh does not exist."); Log::log("World::garbageCollector(): cannot remove body '" + obj + "': body does not exist.");
} }
_objToRemove.clear(); _objToRemove.clear();
} }
void World::removeMeshInstantly(const string &name) { void World::removeBodyInstantly(const string &name) {
if(_objects.erase(name) > 0) if(_objects.erase(name) > 0)
Log::log("World::removeMeshInstantly(): removed mesh '" + name + "'"); Log::log("World::removeBodyInstantly(): removed body '" + name + "'");
else else
Log::log("World::removeMeshInstantly(): cannot remove mesh '" + name + "': mesh does not exist."); Log::log("World::removeBodyInstantly(): cannot remove body '" + name + "': body does not exist.");
}
void World::checkCollision(const std::string& body) {
if (_objects[body]->isCollision()) {
_objects[body]->setInCollision(false);
for (auto &obj : _objects) {
if(obj.first != body) {
std::pair<bool, Simplex> gjk = _objects[body]->checkGJKCollision(obj.second);
if (gjk.first) {
if (obj.second->isCollider()) {
CollisionPoint epa = _objects[body]->EPA(gjk.second, obj.second);
Solver::solveCollision(_objects[body], obj.second, epa);
}
if (_objects[body]->collisionCallBack() != nullptr)
_objects[body]->collisionCallBack()(obj.first, obj.second);
}
}
}
}
}
void World::update() {
for (auto &m : _objects) {
m.second->a_update();
m.second->updatePhysicsState();
checkCollision(m.first);
}
}
void World::projectObjectsInCamera(std::shared_ptr<Camera> camera) {
for (auto &m : _objects)
camera->project(m.second);
}
std::shared_ptr<RigidBody> World::body(const string &name) {
if(_objects.count(name) == 0)
Log::log("World::body: mesh '" + name + "' does not exist.");
return _objects.find(name)->second;
} }

View File

@ -6,25 +6,26 @@
#define ENGINE_WORLD_H #define ENGINE_WORLD_H
#include <map> #include <map>
#include "Mesh.h" #include "Camera.h"
#include "physics/RigidBody.h"
class World { class World {
private: private:
std::map<std::string, std::shared_ptr<Mesh>> _objects; std::map<std::string, std::shared_ptr<RigidBody>> _objects;
std::vector<std::string> _objToRemove; std::vector<std::string> _objToRemove;
public: public:
World() = default; World() = default;
[[nodiscard]] std::shared_ptr<Mesh> operator[] (const std::string& name); void checkCollision(const std::string& body);
void update();
void projectObjectsInCamera(std::shared_ptr<Camera> camera);
[[nodiscard]] std::map<std::string, std::shared_ptr<Mesh>>& objects() { return _objects; } void addBody(std::shared_ptr<RigidBody> mesh, const std::string& name = "");
std::shared_ptr<RigidBody> body(const std::string& name);
void addMesh(std::shared_ptr<Mesh> mesh, const std::string& name = ""); void removeBody(const std::string& name);
void removeMesh(const std::string& name); void removeBodyInstantly(const std::string& name);
void removeMeshInstantly(const std::string& name);
void garbageCollector(); void garbageCollector();
void loadObj(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 Point4D& scale = Point4D{1, 1, 1});
// rayCast returns pair of Point4D and std::string: // 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 (the last coordinate is -1 if there are no collisions)

View File

@ -34,7 +34,7 @@ protected:
double _duration = 0; double _duration = 0;
bool _started = false; bool _started = false;
LoopOut _looped = None; LoopOut _looped = None;
// p - animation progress // _p - animation progress
double _p = 0; double _p = 0;
double _dp = 0; double _dp = 0;

View File

@ -16,7 +16,7 @@ void Window::addButton(int x, int y, int w, int h, std::function<void()> click,
void Window::update(std::shared_ptr<Screen> screen) { void Window::update(std::shared_ptr<Screen> screen) {
screen->title(s_name); screen->setName(s_name);
screen->window.draw(back); screen->window.draw(back);
Point4D mousePos = screen->getMousePosition(); Point4D mousePos = screen->getMousePosition();

View File

@ -21,7 +21,7 @@ private:
Point4D prevMousePosition; Point4D prevMousePosition;
public: public:
explicit Window(std::string name = "Menu", std::string backTexture = "") : s_name(std::move(name)), s_backTexture(std::move(backTexture)){} explicit Window(std::string name = "Menu", std::string backTexture = "") : s_name(std::move(name)), s_backTexture(std::move(backTexture)){}
void addButton(int x, int y, int w, int h, void addButton(int x, int y, int w, int h,
std::function<void()> click, std::function<void()> click,

View File

@ -13,7 +13,8 @@ Point4D RigidBody::_findFurthestPoint(const Point4D& direction) {
Point4D maxPoint = {}; Point4D maxPoint = {};
auto maxDistance = (double)-INFINITY; auto maxDistance = (double)-INFINITY;
for(auto& tri : triangles()){ for(auto& tri : triangles()){
for(auto point : tri.p){ for(int i = 0; i < 3; i++){
Point4D point = tri[i];
point = point + position(); point = point + position();
@ -302,18 +303,22 @@ void RigidBody::AddIfUniqueEdge(std::vector<std::pair<size_t, size_t>>& edges, c
} }
void RigidBody::updatePhysicsState() { void RigidBody::updatePhysicsState() {
translate(p_velocity * Time::deltaTime()); translate(_velocity * Time::deltaTime());
p_velocity = p_velocity + p_acceleration * Time::deltaTime(); _velocity = _velocity + _acceleration * Time::deltaTime();
} }
void RigidBody::setVelocity(const Point4D& velocity) { void RigidBody::setVelocity(const Point4D& velocity) {
p_velocity = velocity; _velocity = velocity;
} }
void RigidBody::addVelocity(const Point4D &velocity) { void RigidBody::addVelocity(const Point4D &velocity) {
p_velocity = p_velocity + velocity; _velocity = _velocity + velocity;
} }
void RigidBody::setAcceleration(const Point4D& acceleration) { void RigidBody::setAcceleration(const Point4D& acceleration) {
p_acceleration = acceleration; _acceleration = acceleration;
}
RigidBody::RigidBody(const Mesh &mesh) : Mesh(mesh) {
} }

View File

@ -10,6 +10,7 @@
#include "../utils/Point4D.h" #include "../utils/Point4D.h"
#include "../Triangle.h" #include "../Triangle.h"
#include "Simplex.h" #include "Simplex.h"
#include "Mesh.h"
struct CollisionPoint { struct CollisionPoint {
Point4D a; // Furthest point of a into b Point4D a; // Furthest point of a into b
@ -19,20 +20,13 @@ struct CollisionPoint {
bool hasCollision; bool hasCollision;
}; };
class RigidBody { class RigidBody : public Mesh {
protected: private:
Point4D p_velocity;
Point4D p_acceleration;
bool _collision = false;
bool _isCollider = true;
bool _inCollision = false;
Point4D _collisionNormal;
Point4D _findFurthestPoint(const Point4D& direction); Point4D _findFurthestPoint(const Point4D& direction);
Point4D _support(std::shared_ptr<RigidBody> obj, const Point4D& direction); Point4D _support(std::shared_ptr<RigidBody> obj, const Point4D& direction);
std::function<void(const std::string&, std::shared_ptr<RigidBody>)> _collisionCallBack;
static bool _nextSimplex(Simplex& points, Point4D& direction); static bool _nextSimplex(Simplex& points, Point4D& direction);
static bool _line(Simplex& points, Point4D& direction); static bool _line(Simplex& points, Point4D& direction);
static bool _triangle(Simplex& points, Point4D& direction); static bool _triangle(Simplex& points, Point4D& direction);
@ -41,9 +35,19 @@ protected:
static std::pair<std::vector<Point4D>, size_t> GetFaceNormals(const std::vector<Point4D>& polytope, const std::vector<size_t>& faces); static std::pair<std::vector<Point4D>, size_t> GetFaceNormals(const std::vector<Point4D>& polytope, const std::vector<size_t>& faces);
static void AddIfUniqueEdge(std::vector<std::pair<size_t, size_t>>& edges, const std::vector<size_t>& faces, size_t a, size_t b); static void AddIfUniqueEdge(std::vector<std::pair<size_t, size_t>>& edges, const std::vector<size_t>& faces, size_t a, size_t b);
protected:
Point4D _velocity;
Point4D _acceleration;
bool _collision = false;
bool _isCollider = true;
bool _inCollision = false;
Point4D _collisionNormal;
public: public:
RigidBody() = default; RigidBody() = default;
virtual ~RigidBody() = default; explicit RigidBody(const Mesh& mesh);
std::pair<bool, Simplex> checkGJKCollision(std::shared_ptr<RigidBody> obj); std::pair<bool, Simplex> checkGJKCollision(std::shared_ptr<RigidBody> obj);
CollisionPoint EPA(const Simplex& simplex, std::shared_ptr<RigidBody> obj); CollisionPoint EPA(const Simplex& simplex, std::shared_ptr<RigidBody> obj);
@ -56,19 +60,16 @@ public:
void setCollision(bool c) { _collision= c; } void setCollision(bool c) { _collision= c; }
void setCollider(bool c) { _isCollider = c; } void setCollider(bool c) { _isCollider = c; }
[[nodiscard]] virtual std::vector<Triangle>& triangles() = 0;
[[nodiscard]] virtual Point4D position() const = 0;
virtual void translate(const Point4D& dv) = 0;
virtual void rotate(const Point4D& r) = 0;
void updatePhysicsState(); void updatePhysicsState();
void setVelocity(const Point4D& velocity); void setVelocity(const Point4D& velocity);
void addVelocity(const Point4D& velocity); void addVelocity(const Point4D& velocity);
void setAcceleration(const Point4D& acceleration); void setAcceleration(const Point4D& acceleration);
[[nodiscard]] Point4D velocity() const { return p_velocity; } [[nodiscard]] Point4D velocity() const { return _velocity; }
[[nodiscard]] const std::function<void(const std::string&, std::shared_ptr<RigidBody>)>& collisionCallBack() const { return _collisionCallBack; }
void setCollisionCallBack(const std::function<void(const std::string&, std::shared_ptr<RigidBody>)>& f) { _collisionCallBack = f; }
}; };

View File

@ -46,7 +46,7 @@ Point4D Point4D::operator-(const Point4D& point4D) const {
double Point4D::dot(const Point4D& point4D) const double Point4D::dot(const Point4D& point4D) const
{ {
return point4D.x() * x() + point4D.y() * y() + point4D.z() * z() + point4D.w() * w(); return point4D.x() * x() + point4D.y() * y() + point4D.z() * z();
} }
[[nodiscard]] Point4D Point4D::cross3D(const Point4D& point4D) const { [[nodiscard]] Point4D Point4D::cross3D(const Point4D& point4D) const {
return Point4D {y() * point4D.z() - point4D.y() * z(), return Point4D {y() * point4D.z() - point4D.y() * z(),

View File

@ -75,7 +75,7 @@ public:
Shooter() = default; Shooter() = default;
void start() override; void start() override;
void update(double elapsedTime) override; void update() override;
void gui() override; void gui() override;
@ -84,7 +84,7 @@ public:
void Shooter::start() { void Shooter::start() {
// This code executed once in the beginning: // This code executed once in the beginning:
debugText(false); setDebugText(false);
screen->setMouseCursorVisible(true); screen->setMouseCursorVisible(true);
@ -100,7 +100,7 @@ void Shooter::start() {
setUpdateWorld(false); setUpdateWorld(false);
world->addMesh(player, player->name()); world->addBody(player, player->name());
player->setDamagePlayerCallBack([this] (sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); }); player->setDamagePlayerCallBack([this] (sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); });
player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); }); player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); });
@ -132,7 +132,7 @@ void Shooter::start() {
} }
} }
void Shooter::update(double elapsedTime) { void Shooter::update() {
// This code executed every time step: // This code executed every time step:
server->update(); server->update();
@ -148,7 +148,7 @@ void Shooter::update(double elapsedTime) {
} }
if(inGame) { if(inGame) {
screen->title("Shooter"); screen->setName("Shooter");
player->update(); player->update();
} else { } else {
mainMenu.update(screen); mainMenu.update(screen);
@ -166,19 +166,16 @@ void Shooter::update(double elapsedTime) {
void Shooter::gui() { void Shooter::gui() {
if(inGame) { sf::Sprite sprite;
// aim sprite.setTexture(*ResourceManager::loadTexture("../textures/gui.png"));
sf::Sprite sprite; sprite.setTextureRect(sf::IntRect(243, 3, 9, 9));
sprite.setTexture(*ResourceManager::loadTexture("../textures/gui.png")); sprite.scale(3, 3);
sprite.setTextureRect(sf::IntRect(243, 3, 9, 9)); sprite.setPosition(screen->width() / 2.0 - 27.0/2.0, screen->height() / 2 - 27.0/2.0);
sprite.scale(3, 3); sprite.setColor(sf::Color(0,0,0, 200));
sprite.setPosition(screen->width() / 2.0 - 27.0/2.0, screen->height() / 2 - 27.0/2.0); screen->window.draw(sprite);
sprite.setColor(sf::Color(0,0,0, 200));
screen->window.draw(sprite);
// health player stats // health player stats
player->drawStats(); player->drawStats();
}
} }
void Shooter::play() { void Shooter::play() {

View File

@ -41,13 +41,13 @@ Shotgun::processFire(std::shared_ptr<World> world, std::shared_ptr<Camera> camer
string traceName = _name + "_trace_nr_" + std::to_string(fireTraces++); string traceName = _name + "_trace_nr_" + std::to_string(fireTraces++);
Point4D from = _objects[_name + "_" + to_string(9)]->position() + Point4D from = _objects[_name + "_" + to_string(9)]->position() +
_objects[_name + "_" + to_string(9)]->triangles()[0][0]; _objects[_name + "_" + to_string(9)]->triangles()[0][0];
world->addMesh(make_shared<Mesh>(Mesh::LineTo(from, to, 0.05)), traceName); world->addBody(make_shared<RigidBody>(Mesh::LineTo(from, to, 0.05)), traceName);
(*world)[traceName]->setCollider(false); world->body(traceName)->setCollider(false);
// remove trace line after some time // remove trace line after some time
(*world)[traceName]->a_color("color_trace", {255, 255, 255, 0}, 1, Animation::None, Animation::linear); world->body(traceName)->a_color("color_trace", {255, 255, 255, 0}, 1, Animation::None, Animation::linear);
(*world)["map_0"]->a_function(traceName + "delete", [world, traceName]() { deleteTrace(world, traceName); }, world->body("map_0")->a_function(traceName + "delete", [world, traceName]() { deleteTrace(world, traceName); },
1, 2); 1, 2);
addTraceCallBack(from, to); addTraceCallBack(from, to);
} }

View File

@ -14,13 +14,16 @@ Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, co
auto objs = Mesh::LoadObjects(objFileName, matFileName, scale); auto objs = Mesh::LoadObjects(objFileName, matFileName, scale);
for(int i = 0; i < objs.size(); i++) { for(int i = 0; i < objs.size(); i++) {
string meshName = _name + "_" + to_string(i); string meshName = _name + "_" + to_string(i);
objs[i]->setCollider(false);
RigidBody obj(*objs[i]);
obj.setCollider(false);
//transforms //transforms
objs[i]->rotate(rotate); obj.rotate(rotate);
objs[i]->translate(translate); obj.translate(translate);
_objects.insert({meshName, objs[i]}); _objects.insert({meshName, std::make_shared<RigidBody>(obj)});
} }
noAmmoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/no_ammo.ogg")); noAmmoSound.setBuffer(*ResourceManager::loadSoundBuffer("../sound/weapons/no_ammo.ogg"));
} }
@ -62,13 +65,13 @@ void Weapon::reload() {
void Weapon::addToWorld(shared_ptr<World> world) { void Weapon::addToWorld(shared_ptr<World> world) {
for(auto& obj : _objects) { for(auto& obj : _objects) {
world->addMesh(obj.second, obj.first); world->addBody(obj.second, obj.first);
} }
} }
void Weapon::removeFromWorld(shared_ptr<World> world) { void Weapon::removeFromWorld(shared_ptr<World> world) {
for(auto& obj : _objects) { for(auto& obj : _objects) {
world->removeMeshInstantly(obj.first); world->removeBodyInstantly(obj.first);
} }
} }
@ -90,7 +93,7 @@ void Weapon::translate(const Point4D &point4D) {
} }
void Weapon::deleteTrace(shared_ptr<World> world, const std::string& traceName) { void Weapon::deleteTrace(shared_ptr<World> world, const std::string& traceName) {
world->removeMesh(traceName); world->removeBody(traceName);
} }
void Weapon::rotateRelativePoint(const Point4D &point4D, const Point4D &v, double val) { void Weapon::rotateRelativePoint(const Point4D &point4D, const Point4D &v, double val) {
@ -114,12 +117,12 @@ std::map<std::string, double> Weapon::processFire(shared_ptr<World> world, share
Point4D to = rayCast.first.w() == -1 ? camera->position() + camera->lookAt() * 1000 + randV: rayCast.first; Point4D to = rayCast.first.w() == -1 ? camera->position() + camera->lookAt() * 1000 + randV: rayCast.first;
string traceName = _name + "_trace_nr_" + std::to_string(fireTraces++); string traceName = _name + "_trace_nr_" + std::to_string(fireTraces++);
Point4D from = _objects[_name + "_" + to_string(_objects.size()-1)]->position() + _objects[_name + "_" + to_string(_objects.size()-1)]->triangles()[0][0]; Point4D from = _objects[_name + "_" + to_string(_objects.size()-1)]->position() + _objects[_name + "_" + to_string(_objects.size()-1)]->triangles()[0][0];
world->addMesh(make_shared<Mesh>(Mesh::LineTo(from, to, 0.05)), traceName); world->addBody(make_shared<RigidBody>(Mesh::LineTo(from, to, 0.05)), traceName);
(*world)[traceName]->setCollider(false); world->body(traceName)->setCollider(false);
// remove trace line after some time // remove trace line after some time
(*world)[traceName]->a_color("color_trace", {255, 255, 255, 0}, 1, Animation::None, Animation::linear); world->body(traceName)->a_color("color_trace", {255, 255, 255, 0}, 1, Animation::None, Animation::linear);
(*world)["Player_im"]->a_function(traceName + "delete", [world, traceName](){deleteTrace(world, traceName); }, 1, 2); world->body("Player_im")->a_function(traceName + "delete", [world, traceName](){deleteTrace(world, traceName); }, 1, 2);
addTraceCallBack(from, to); addTraceCallBack(from, to);

View File

@ -28,7 +28,7 @@ protected:
double _spreading = 2.0; double _spreading = 2.0;
std::string _name = "Weapon_name"; std::string _name = "Weapon_name";
std::map<std::string, std::shared_ptr<Mesh>> _objects; std::map<std::string, std::shared_ptr<RigidBody>> _objects;
double _lastFireTime = -INFINITY; double _lastFireTime = -INFINITY;
double _lastReloadTime = -INFINITY; double _lastReloadTime = -INFINITY;