From e471795290d605b6d4aac830c7dbc865a002b3cc Mon Sep 17 00:00:00 2001 From: Vectozavr <60608292+vectozavr@users.noreply.github.com> Date: Fri, 22 Oct 2021 23:42:32 +0700 Subject: [PATCH] OpenGL graphics acceleration support! --- CMakeLists.txt | 18 ++++++- Player.cpp | 10 ++-- Player.h | 8 +-- PlayerController.cpp | 18 ++++--- README.md | 1 + Shooter.cpp | 8 +-- engine/Camera.cpp | 34 ++++++++++-- engine/Camera.h | 6 ++- engine/Consts.h | 1 + engine/Engine.cpp | 45 ++++++++++------ engine/Engine.h | 2 + engine/Mesh.h | 2 +- engine/Screen.cpp | 125 ++++++++++++++++++++++++++++++++++++++++++- engine/Screen.h | 8 ++- engine/World.cpp | 33 ++++++++---- engine/World.h | 20 +++++-- weapon/Ak47.cpp | 2 +- weapon/Gold_Ak47.h | 2 +- weapon/Gun.cpp | 2 +- weapon/Rifle.cpp | 2 +- weapon/Shotgun.cpp | 4 +- weapon/Shotgun.h | 2 +- weapon/Weapon.cpp | 17 +++--- weapon/Weapon.h | 11 ++-- 24 files changed, 307 insertions(+), 74 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c27dae..4024f7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,4 +112,20 @@ if (SFML_FOUND) include_directories(${SFML_INCLUDE_DIR}) endif() -target_link_libraries(shooter sfml-audio sfml-network sfml-graphics sfml-window sfml-system) \ No newline at end of file +target_link_libraries(shooter sfml-audio sfml-network sfml-graphics sfml-window sfml-system) + +# OpenGL part +if (APPLE OR UNIX) + set(GLEW_H /usr/local/Cellar/glew/2.1.0/include/GL) + set(GLFW_H /usr/local/Cellar/glfw/3.2.1/include/GLFW) + include_directories(${GLEW_H} ${GLFW_H}) + + set(GLEW_LINK /usr/local/Cellar/glew/2.1.0/lib/libGLEW.2.1.dylib) + set(GLFW_LINK /usr/local/Cellar/glfw/3.2.1/lib/libglfw.3.dylib) + link_libraries(${OPENGL} ${GLEW_LINK} ${GLFW_LINK}) + + target_link_libraries(shooter "-framework OpenGL") + target_link_libraries(shooter "-framework GLUT") +else() + +endif() \ No newline at end of file diff --git a/Player.cpp b/Player.cpp index db28ad1..d51898f 100644 --- a/Player.cpp +++ b/Player.cpp @@ -8,7 +8,7 @@ #include "engine/utils/Log.h" Player::Player() { - loadObj(ShooterConsts::CUBE_OBJ, Vec3D{0.5, 1.9, 0.5}); + loadObj(ShooterConsts::CUBE_OBJ, Vec3D{1.5, 1.9, 1.5}); setAcceleration(Vec3D{0, -ShooterConsts::GRAVITY, 0}); setCollision(true); setVisible(false); @@ -109,15 +109,17 @@ void Player::previousWeapon() { } } -void Player::fire() { +bool Player::fire() { auto camera = attached(ObjectNameTag("Camera")); if(camera != nullptr) { - auto damagedPlayers = _weapons[_selectedWeapon]->fire(_rayCastFunction, camera->position(), camera->lookAt()); - for(auto& [damagedPlayerName, damage] : damagedPlayers) { + auto fireInfo = _weapons[_selectedWeapon]->fire(_rayCastFunction, camera->position(), camera->lookAt()); + for(auto& [damagedPlayerName, damage] : fireInfo.damagedPlayers) { sf::Uint16 targetId = std::stoi(damagedPlayerName.str().substr(6)); _damagePlayerCallBack(targetId, damage); } + return fireInfo.shot; } + return false; } void Player::reload() { diff --git a/Player.h b/Player.h index f73fe1b..6c58b15 100644 --- a/Player.h +++ b/Player.h @@ -37,7 +37,7 @@ private: std::function)> _addWeaponCallBack; std::function)> _removeWeaponCallBack; - std::function(const Vec3D&, const Vec3D&)> _rayCastFunction; + std::function _rayCastFunction; public: Player(); @@ -57,8 +57,10 @@ public: void nextWeapon(); void previousWeapon(); - void fire(); + bool fire(); void reload(); + [[nodiscard]] ObjectNameTag weaponName() const { return _weapons[_selectedWeapon]->name(); } + std::shared_ptr weapon() { return _weapons[_selectedWeapon]; } void rotateWeaponsRelativePoint(const Vec3D& point, const Vec3D& v, double val); @@ -83,7 +85,7 @@ public: void setRemoveWeaponCallBack(std::function)> removeWeapon) { _removeWeaponCallBack = std::move(removeWeapon); } - void setRayCastFunction(std::function(const Vec3D&, const Vec3D&)> rayCastFunction) { + void setRayCastFunction(std::function rayCastFunction) { _rayCastFunction = std::move(rayCastFunction); } diff --git a/PlayerController.cpp b/PlayerController.cpp index 73d8d89..6fe3081 100644 --- a/PlayerController.cpp +++ b/PlayerController.cpp @@ -9,6 +9,7 @@ #include "engine/animation/ATranslate.h" #include "engine/animation/ATranslateToPoint.h" #include "engine/animation/Timeline.h" +#include "engine/animation/ARotate.h" #include "ShooterConsts.h" PlayerController::PlayerController(std::shared_ptr player, @@ -107,15 +108,24 @@ void PlayerController::update() { SoundController::playSound(SoundTag("unSlowMo"), ShooterConsts::UN_SLOW_MO_SOUND); } + if (Mouse::isButtonPressed(sf::Mouse::Button::Left)) { + bool shot = _player->fire(); + + if(shot) { + if(!_player->inCollision() && (_player->weaponName() == ObjectNameTag("shotgun"))) + _player->addVelocity(-camera->lookAt() * 30 * coeff); + } + } + if (Keyboard::isKeyPressed(sf::Keyboard::Space) && _player->inCollision()) { // if we just want to jump, we have to add particular speed if (!_isSliding) _player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * ShooterConsts::JUMP_HEIGHT) * coeff, 0 }); // if we want to slide, we have to add speed * 60/fps to make it independent on frame rate else - _player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * ShooterConsts::JUMP_HEIGHT) * coeff * 60.0 / Time::fps(), 0 }); + _player->addVelocity(Vec3D{ 0, std::abs(_player->collisionNormal().y()) * sqrt(2 * -_player->acceleration().y() * ShooterConsts::JUMP_HEIGHT) * coeff * Time::deltaTime() * 60, 0 }); - _player->translate(Vec3D{ 0, Time::deltaTime() * ShooterConsts::WALK_SPEED * 2 * coeff * 60.0 / Time::fps(), 0 }); + _player->translate(Vec3D{ 0, Time::deltaTime() * ShooterConsts::WALK_SPEED * 2 * coeff, 0 }); _isSliding = true; } else { _isSliding = false; @@ -149,10 +159,6 @@ void PlayerController::update() { _player->previousWeapon(); } - if (Mouse::isButtonPressed(sf::Mouse::Button::Left)) { - _player->fire(); - } - if(Keyboard::isKeyPressed(sf::Keyboard::R)) { _player->reload(); } diff --git a/README.md b/README.md index ba740e1..aaa58d2 100644 --- a/README.md +++ b/README.md @@ -59,3 +59,4 @@ GamePlay: ![Project demonstration](img/gamePlay5.png) ![Project demonstration](img/gamePlay6.png) ![Project demonstration](img/gamePlay7.png) +![Project demonstration](img/opengl.png) diff --git a/Shooter.cpp b/Shooter.cpp index d28a9de..f4b2e09 100644 --- a/Shooter.cpp +++ b/Shooter.cpp @@ -81,7 +81,7 @@ void Shooter::start() { // TODO: encapsulate call backs inside Player player->setAddTraceCallBack([this](const Vec3D& from, const Vec3D& to){ client->addTrace(from, to); addFireTrace(from, to); }); player->setDamagePlayerCallBack([this] (sf::Uint16 targetId, double damage) { client->damagePlayer(targetId, damage); }); - player->setRayCastFunction([this](const Vec3D& from, const Vec3D& to) { return world->rayCast(from, to, "Enemy"); }); + player->setRayCastFunction([this](const Vec3D& from, const Vec3D& to) { return world->rayCast(from, to, "weapon Player"); }); player->setTakeBonusCallBack([this] (const string& bonusName) { client->takeBonus(bonusName); }); player->setAddWeaponCallBack([this](std::shared_ptr weapon){ addWeapon(std::move(weapon)); }); player->setRemoveWeaponCallBack([this](std::shared_ptr weapon){ removeWeapon(std::move(weapon)); }); @@ -246,7 +246,7 @@ void Shooter::addFireTrace(const Vec3D &from, const Vec3D &to) { world->addBody(std::make_shared(Mesh::LineTo(from, to, 0.05)), ObjectNameTag(traceName)); world->body(ObjectNameTag(traceName))->setCollider(false); - Timeline::animate(AnimationListTag(traceName + "_fadeOut"), new AColor(world->body(ObjectNameTag(traceName)), {255, 255, 255, 0})); + Timeline::animate(AnimationListTag(traceName + "_fadeOut"), new AColor(world->body(ObjectNameTag(traceName)), {150, 150, 150, 0})); Timeline::animate(AnimationListTag(traceName + "_delete"), new AFunction([this, traceName](){ removeFireTrace(ObjectNameTag(traceName)); }, 1, 2)); } @@ -266,7 +266,7 @@ void Shooter::removeBonus(const ObjectNameTag &bonusName) { } void Shooter::addWeapon(std::shared_ptr weapon) { - world->addBody(weapon, weapon->name()); + world->addBody(weapon, ObjectNameTag("weapon_" + weapon->name().str())); if(client != nullptr) client->changeWeapon(weapon->name().str()); @@ -294,5 +294,5 @@ void Shooter::changeEnemyWeapon(const std::string& weaponName, sf::Uint16 enemyI } void Shooter::removeWeapon(std::shared_ptr weapon) { - world->removeBody(ObjectNameTag(weapon->name())); + world->removeBody(ObjectNameTag("weapon_" + weapon->name().str())); } diff --git a/engine/Camera.cpp b/engine/Camera.cpp index a95f1fd..5fbb83b 100644 --- a/engine/Camera.cpp +++ b/engine/Camera.cpp @@ -6,7 +6,6 @@ #include "utils/Log.h" #include -#include "Consts.h" std::vector> Camera::project(std::shared_ptr mesh) { @@ -64,9 +63,9 @@ std::vector> Camera::project(std::shared_ptr mes Triangle clippedProjected = clipped * _SP; Triangle clippedProjectedNormalized = Triangle(clippedProjected[0] / clippedProjected[0].w(), - clippedProjected[1] / clippedProjected[1].w(), - clippedProjected[2] / clippedProjected[2].w(), - ambientColor); + clippedProjected[1] / clippedProjected[1].w(), + clippedProjected[2] / clippedProjected[2].w(), + ambientColor); _triangles.emplace_back(std::make_shared(clippedProjectedNormalized)); } @@ -128,3 +127,30 @@ void Camera::clear() { _triangles.clear(); _V = Matrix4x4::View(left(), up(), lookAt(), position()); } + +// OpenGL function +GLfloat *Camera::view() const { + auto* v = (GLfloat*)malloc(4*4*sizeof(GLfloat)); + + v[0] = -(GLfloat)left().x(); + v[4] = -(GLfloat)left().y(); + v[8] = -(GLfloat)left().z(); + v[12] = (GLfloat)position().dot(left()); + + v[1] = (GLfloat)up().x(); + v[5] = (GLfloat)up().y(); + v[9] = (GLfloat)up().z(); + v[13] = -(GLfloat)position().dot(up()); + + v[2] = -(GLfloat)lookAt().x(); + v[6] = -(GLfloat)lookAt().y(); + v[10] = -(GLfloat)lookAt().z(); + v[14] = (GLfloat)position().dot(lookAt()); + + v[3] = (GLfloat)0.0f; + v[7] = (GLfloat)0.0f; + v[11] = (GLfloat)0.0f; + v[15] = (GLfloat)1.0f; + + return v; +} diff --git a/engine/Camera.h b/engine/Camera.h index 95b66db..4fbba6f 100644 --- a/engine/Camera.h +++ b/engine/Camera.h @@ -6,9 +6,9 @@ #define ENGINE_CAMERA_H #include -#include "Screen.h" #include "Plane.h" #include "Mesh.h" +#include class Camera final : public Object{ private: @@ -24,6 +24,7 @@ private: bool _ready = false; double _aspect = 0; + public: Camera() = default; Camera(const Camera& camera) = delete; @@ -36,6 +37,9 @@ public: [[nodiscard]] int buffSize() const { return _triangles.size(); } std::vector> sorted(); + + // OpenGL function + [[nodiscard]] GLfloat* view() const; }; diff --git a/engine/Consts.h b/engine/Consts.h index 3b223eb..375728b 100644 --- a/engine/Consts.h +++ b/engine/Consts.h @@ -13,6 +13,7 @@ namespace Consts { const sf::Color BACKGROUND_COLOR = sf::Color(255, 255, 255); const std::string PROJECT_NAME = "engine"; const bool USE_LOG_FILE = true; + const bool USE_OPEN_GL = true; const double PI = 3.14159265358979323846264338327950288; const double EPS = 0.000001; diff --git a/engine/Engine.cpp b/engine/Engine.cpp index bc99ab1..04c5c3a 100644 --- a/engine/Engine.cpp +++ b/engine/Engine.cpp @@ -42,11 +42,6 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name, Time::update(); update(); - /* Project all mesh - * Here we project all _tris for each body from world._objects. - * When we call camera.project(m.second), - */ - // sometimes we dont need to update physics world // (for example in menu or while pause) // hence we can set '_updateWorld' equal to false in setUpdateWorld(bool): @@ -54,15 +49,30 @@ void Engine::create(int screenWidth, int screenHeight, const std::string &name, Timeline::update(); - camera->clear(); world->update(); - world->projectObjectsInCamera(camera); - // draw projected body - for (auto &t : camera->sorted()) - screen->drawTriangle(*t); + if(_useOpenGL) { + GLfloat* view = camera->view(); + for(auto & it : *world) { + if (it.second->isVisible()) { + GLfloat* geometry = Screen::glMeshToGLfloatArray(it.second, camera->position()); + screen->glDrawMesh(geometry, view, 3 * it.second->triangles().size()); + free(geometry); + } + } + free(view); + } else { + // clear triangles from previous frame + camera->clear(); + // project triangles to the camera plane + for(auto & it : *world) + camera->project(it.second); + // draw triangles on the screen + for (auto &t : camera->sorted()) + screen->drawTriangle(*t); - _triPerSec = camera->buffSize() * Time::fps(); + _triPerSec = camera->buffSize() * Time::fps(); + } printDebugText(); gui(); @@ -87,13 +97,18 @@ void Engine::exit() { void Engine::printDebugText() const { if (_debugText) { - screen->debugText(_name + "\n\n X: " + + std::string str = _name + "\n\n X: " + std::to_string((camera->position().x())) + "\n Y: " + std::to_string((camera->position().y())) + "\n Z: " + std::to_string((camera->position().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"); + std::to_string(screen->height()) + "\t" + + std::to_string(Time::fps()) + " fps"; + if(_useOpenGL) { + str += "\n Using OpenGL acceleration"; + } else { + str += "\n" + std::to_string((int) _triPerSec) + " tris/s"; + } + screen->debugText(str); } } diff --git a/engine/Engine.h b/engine/Engine.h index 1e5a60f..a994eaf 100644 --- a/engine/Engine.h +++ b/engine/Engine.h @@ -20,6 +20,7 @@ private: double _triPerSec = 0; bool _debugText = true; bool _updateWorld = true; + bool _useOpenGL = Consts::USE_OPEN_GL; void printDebugText() const; protected: @@ -35,6 +36,7 @@ protected: void setDebugText(bool value) { _debugText = value; } void setUpdateWorld(bool value) { _updateWorld = value; } + void setGlEnable(bool value) { _useOpenGL = value; } virtual void gui(){} public: diff --git a/engine/Mesh.h b/engine/Mesh.h index 7603195..ac733dc 100644 --- a/engine/Mesh.h +++ b/engine/Mesh.h @@ -52,7 +52,7 @@ public: ~Mesh() override; Mesh static Obj(const std::string& filename); - Mesh static LineTo(const Vec3D& from, const Vec3D& to, double line_width = 0.1, const sf::Color& color = {150, 150, 150, 255}); + Mesh static LineTo(const Vec3D& from, const Vec3D& to, double line_width = 0.1, const sf::Color& color = {150, 150, 150, 100}); }; #endif //INC_3DZAVR_MESH_H diff --git a/engine/Screen.cpp b/engine/Screen.cpp index f2df661..b2e4220 100644 --- a/engine/Screen.cpp +++ b/engine/Screen.cpp @@ -7,6 +7,9 @@ #include #include "utils/Log.h" #include "ResourceManager.h" +#include +#include + void Screen::open(int screenWidth, int screenHeight, const std::string &name, bool verticalSync, sf::Color background, sf::Uint32 style) { _title = name; @@ -15,6 +18,7 @@ void Screen::open(int screenWidth, int screenHeight, const std::string &name, bo _background = background; sf::ContextSettings settings; + settings.depthBits = 24; settings.antialiasingLevel = 8; _window = std::make_shared(); @@ -37,6 +41,9 @@ void Screen::display() { } void Screen::clear() { + // Clear the depth buffer + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + _window->clear(_background); } @@ -48,7 +55,10 @@ void Screen::drawTriangle(const Triangle& triangle) sf::Vertex(sf::Vector2f((float)triangle[1].x(), (float)triangle[1].y()), triangle.color()), sf::Vertex(sf::Vector2f((float)triangle[2].x(), (float)triangle[2].y()), triangle.color()) }; + + _window->pushGLStates(); _window->draw(tris, 3, sf::Triangles); + _window->popGLStates(); } void Screen::setTitle(const std::string& title) { @@ -71,9 +81,11 @@ void Screen::debugText(const std::string& text) { t.setString(text); t.setCharacterSize(30); t.setFillColor(sf::Color::Black); - t.setPosition(10, 10); + t.setPosition(10, 50); + _window->pushGLStates(); _window->draw(t); + _window->popGLStates(); } void Screen::drawTetragon(const Vec2D &p1, const Vec2D &p2, const Vec2D &p3, const Vec2D &p4, sf::Color color) { @@ -84,7 +96,10 @@ void Screen::drawTetragon(const Vec2D &p1, const Vec2D &p2, const Vec2D &p3, con polygon.setPoint(2, sf::Vector2f((float)p3.x(), (float)p3.y())); polygon.setPoint(3, sf::Vector2f((float)p4.x(), (float)p4.y())); polygon.setFillColor(color); + + _window->pushGLStates(); _window->draw(polygon); + _window->popGLStates(); } void Screen::drawText(const std::string& string, const Vec2D &position, int size, sf::Color color) { @@ -98,17 +113,125 @@ void Screen::drawText(const std::string& string, const Vec2D &position, int size text.setPosition((float)position.x(), (float)position.y()); text.setString(string); + + _window->pushGLStates(); _window->draw(text); + _window->popGLStates(); } void Screen::drawSprite(const sf::Sprite &sprite) { + _window->pushGLStates(); _window->draw(sprite); + _window->popGLStates(); } void Screen::drawText(const sf::Text &text) { + _window->pushGLStates(); _window->draw(text); + _window->popGLStates(); } void Screen::attachMouse(std::shared_ptr mouse) { mouse->setWindow(_window); } + +// OpenGL functions +void Screen::glDrawMesh(GLfloat* geometry, GLfloat* view, size_t count) { + // OpenGL: + // Make the window the active window for OpenGL calls + _window->setActive(true); + + glEnable(GL_CULL_FACE); // enable culling face + glCullFace(GL_BACK); // cull faces from back + glFrontFace(GL_CCW); // vertex order (counter clock wise) + + // Enable Z-buffer read and write + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); + glClearDepth(1.f); + + // Disable lighting + glDisable(GL_LIGHTING); + + // enable alpha channel: + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Configure the viewport (the same size as the window) + glViewport(0, 0, _window->getSize().x, _window->getSize().y); + + // Setup a perspective projection + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + GLfloat ratio = static_cast(_window->getSize().x) / _window->getSize().y; + glFrustum(-ratio, ratio, -1.f, 1.f, 1.0f, 500.f); + + // Enable position and texture coordinates vertex components + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(3, GL_FLOAT, 7 * sizeof(GLfloat), geometry); + glColorPointer(4, GL_FLOAT, 7 * sizeof(GLfloat), geometry + 3); + + // Disable normal and color vertex components + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + // Apply some transformations + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glLoadMatrixf(view); + + // Draw the mesh + glDrawArrays(GL_TRIANGLES, 0, count); + + // Make the window no longer the active window for OpenGL calls + _window->setActive(false); +} + +GLfloat* Screen::glMeshToGLfloatArray(std::shared_ptr mesh, const Vec3D& cameraPosition) { + Vec3D pos = mesh->position(); + std::vector& triangles = mesh->triangles(); + + auto* geometry = (GLfloat*)malloc(7*3*triangles.size()*sizeof(GLfloat)); + + for(int i = 0; i < triangles.size(); i++) { + int stride = 21*i; + + double dot = triangles[i].norm().dot((pos + Vec3D(triangles[i][0]) - cameraPosition).normalized()); + sf::Color color = triangles[i].color(); + sf::Color ambientColor = sf::Color((sf::Uint8)(color.r * (0.3 * std::abs(dot) + 0.7)), + (sf::Uint8)(color.g * (0.3 * std::abs(dot) + 0.7)), + (sf::Uint8)(color.b * (0.3 * std::abs(dot) + 0.7)), + (sf::Uint8)color.a); + + + geometry[stride + 0] = (GLfloat)triangles[i][0].x() + pos.x(); + geometry[stride + 1] = (GLfloat)triangles[i][0].y() + pos.y(); + geometry[stride + 2] = (GLfloat)triangles[i][0].z() + pos.z(); + + geometry[stride + 3] = (GLfloat)ambientColor.r/255.0f; + geometry[stride + 4] = (GLfloat)ambientColor.g/255.0f; + geometry[stride + 5] = (GLfloat)ambientColor.b/255.0f; + geometry[stride + 6] = (GLfloat)ambientColor.a/255.0f; + + geometry[stride + 7] = (GLfloat)triangles[i][1].x() + pos.x(); + geometry[stride + 8] = (GLfloat)triangles[i][1].y() + pos.y(); + geometry[stride + 9] = (GLfloat)triangles[i][1].z() + pos.z(); + + geometry[stride + 10] = (GLfloat)ambientColor.r/255.0f; + geometry[stride + 11] = (GLfloat)ambientColor.g/255.0f; + geometry[stride + 12] = (GLfloat)ambientColor.b/255.0f; + geometry[stride + 13] = (GLfloat)ambientColor.a/255.0f; + + geometry[stride + 14] = (GLfloat)triangles[i][2].x() + pos.x(); + geometry[stride + 15] = (GLfloat)triangles[i][2].y() + pos.y(); + geometry[stride + 16] = (GLfloat)triangles[i][2].z() + pos.z(); + + geometry[stride + 17] = (GLfloat)ambientColor.r/255.0f; + geometry[stride + 18] = (GLfloat)ambientColor.g/255.0f; + geometry[stride + 19] = (GLfloat)ambientColor.b/255.0f; + geometry[stride + 20] = (GLfloat)ambientColor.a/255.0f; + } + return geometry; +} diff --git a/engine/Screen.h b/engine/Screen.h index 9170c6c..9852dfd 100644 --- a/engine/Screen.h +++ b/engine/Screen.h @@ -13,6 +13,8 @@ #include "utils/Time.h" #include "Mouse.h" #include "Consts.h" +#include "Mesh.h" +#include "Camera.h" class Screen final { private: @@ -29,7 +31,7 @@ public: void display(); void clear(); - bool hasFocus() const { return _window->hasFocus(); } + [[nodiscard]] bool hasFocus() const { return _window->hasFocus(); } void drawTriangle(const Triangle& triangle); void drawTetragon(const Vec2D& p1, const Vec2D& p2, const Vec2D& p3, const Vec2D& p4, sf::Color color); @@ -50,6 +52,10 @@ public: void debugText(const std::string& text); void attachMouse(std::shared_ptr mouse); + + // OpenGL functions + void glDrawMesh(GLfloat* geometry, GLfloat* view, size_t count); + static GLfloat* glMeshToGLfloatArray(std::shared_ptr mesh, const Vec3D& cameraPosition); }; diff --git a/engine/World.cpp b/engine/World.cpp index ecd3a84..938b742 100644 --- a/engine/World.cpp +++ b/engine/World.cpp @@ -6,6 +6,8 @@ #include "utils/Log.h" #include "Plane.h" #include "ResourceManager.h" +#include +#include using namespace std; @@ -19,15 +21,28 @@ void World::loadBody(const ObjectNameTag& tag, const string &filename, const Vec Log::log("World::loadBody(): inserted body from " + filename + " with title '" + tag.str() + "' with " + std::to_string(_objects[tag]->triangles().size()) + " tris."); } -std::pair World::rayCast(const Vec3D& from, const Vec3D& to, const std::string& tag) { +IntersectionInformation World::rayCast(const Vec3D& from, const Vec3D& to, const std::string& skipTags) { - std::pair result; + // make vector of tags, that we are going to escape + vector tagsToSkip; + stringstream s(skipTags); + std::string t; + while (s >> t) tagsToSkip.push_back(t); + + bool intersected = false; std::unique_ptr point = std::make_unique(); + std::unique_ptr triangle = std::make_unique(); std::string bodyName; double minDistance = Consts::RAY_CAST_MAX_DISTANCE; + std::shared_ptr intersectedBody = nullptr; for(auto& [name, body] : _objects) { - if(!tag.empty() && name.str().find(tag) == std::string::npos) + + //for (auto& escapeTag : tagsToSkip) + // if(name.str().find(escapeTag) != std::string::npos) + // continue; + + if(name.str().find("Player") != std::string::npos || name.str().find("weapon") != std::string::npos) continue; for(auto& tri : body->triangles()) { @@ -39,11 +54,14 @@ std::pair World::rayCast(const Vec3D& from, const Vec3D& t if(intersection.second > 0 && distance < minDistance && tri_translated.isPointInside(intersection.first)) { minDistance = distance; point = std::make_unique(intersection.first); + triangle = std::make_unique(tri_translated); bodyName = name.str(); + intersected = true; + intersectedBody = body; } } } - return {*point, ObjectNameTag(bodyName)}; + return IntersectionInformation{*point, sqrt(minDistance), *triangle, ObjectNameTag(bodyName), intersectedBody, intersected}; } void World::loadMap(const std::string& filename, const Vec3D& scale) { @@ -53,6 +71,8 @@ void World::loadMap(const std::string& filename, const Vec3D& scale) { addBody(std::make_shared(*objs[i]), meshName); body(meshName)->scale(scale); } + + auto it = _objects.begin(); } void World::removeBody(const ObjectNameTag& tag) { @@ -95,11 +115,6 @@ void World::update() { } } -void World::projectObjectsInCamera(std::shared_ptr camera) { - for (auto &[name, body] : _objects) - camera->project(body); -} - std::shared_ptr World::body(const ObjectNameTag& tag) { if(_objects.count(tag) == 0) return nullptr; diff --git a/engine/World.h b/engine/World.h index 0d0c65b..1843359 100644 --- a/engine/World.h +++ b/engine/World.h @@ -7,8 +7,18 @@ #include #include "Camera.h" +#include "Screen.h" #include "physics/RigidBody.h" +struct IntersectionInformation final { + const Vec3D pointOfIntersection; + const double distanceToObject; + const Triangle intersectedTriangle; + const ObjectNameTag objectName; + const std::shared_ptr obj; + const bool intersected; +}; + class World final { private: std::map> _objects; @@ -17,19 +27,19 @@ public: void checkCollision(const ObjectNameTag& tag); void update(); - void projectObjectsInCamera(std::shared_ptr camera); void addBody(std::shared_ptr mesh, const ObjectNameTag& tag); std::shared_ptr body(const ObjectNameTag& tag); void removeBody(const ObjectNameTag& tag); void loadBody(const ObjectNameTag& tag, const std::string &filename, const Vec3D& scale = Vec3D{1, 1, 1}); - // rayCast returns pair of Point4D and std::string: - // 1) Point4D is point of collision - // 2) std::string - title of the object - std::pair rayCast(const Vec3D& from, const Vec3D& to, const std::string& tag = ""); + // std::string skipTags is a string that consist of all objects we want to skip in ray casting + IntersectionInformation rayCast(const Vec3D& from, const Vec3D& to, const std::string& skipTags = ""); void loadMap(const std::string& filename, const Vec3D & scale = Vec3D{1, 1, 1}); + + std::map>::iterator begin() { return _objects.begin(); } + std::map>::iterator end() { return _objects.end(); } }; diff --git a/weapon/Ak47.cpp b/weapon/Ak47.cpp index 9328120..c209f59 100644 --- a/weapon/Ak47.cpp +++ b/weapon/Ak47.cpp @@ -8,7 +8,7 @@ using namespace std; -Ak47::Ak47(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) { +Ak47::Ak47(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-2.2, 1.0, 1.3}, Vec3D{0, Consts::PI, 0}) { fireSound = ShooterConsts::AK47_FIRE_SOUND; reloadSound = ShooterConsts::AK47_RELOAD_SOUND; diff --git a/weapon/Gold_Ak47.h b/weapon/Gold_Ak47.h index fab8756..eabfed3 100644 --- a/weapon/Gold_Ak47.h +++ b/weapon/Gold_Ak47.h @@ -10,7 +10,7 @@ class Gold_Ak47 final : public Weapon { public: - explicit Gold_Ak47(int ammo = 200, const std::string& weaponName = "gold_ak47") : Weapon(weaponName, ShooterConsts::GOLD_AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) { + explicit Gold_Ak47(int ammo = 200, const std::string& weaponName = "gold_ak47") : Weapon(weaponName, ShooterConsts::GOLD_AK47_OBJ, Vec3D{3, 3, 3}, Vec3D{-2.2, 1.0, 1.3}, Vec3D{0, Consts::PI, 0}) { fireSound = ShooterConsts::GOLD_AK47_FIRE_SOUND; reloadSound = ShooterConsts::GOLD_AK47_RELOAD_SOUND; diff --git a/weapon/Gun.cpp b/weapon/Gun.cpp index 4adf379..aca908d 100644 --- a/weapon/Gun.cpp +++ b/weapon/Gun.cpp @@ -8,7 +8,7 @@ using namespace std; -Gun::Gun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::GUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.8, 1.3, 0.3}, Vec3D{0, Consts::PI, 0}) { +Gun::Gun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::GUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-1.8, 1.3, 1.8}, Vec3D{0, Consts::PI, 0}) { fireSound = ShooterConsts::GUN_FIRE_SOUND; reloadSound = ShooterConsts::GUN_RELOAD_SOUND; diff --git a/weapon/Rifle.cpp b/weapon/Rifle.cpp index 27c5fdc..97db0a1 100644 --- a/weapon/Rifle.cpp +++ b/weapon/Rifle.cpp @@ -6,7 +6,7 @@ #include "Rifle.h" #include "../ShooterConsts.h" -Rifle::Rifle(int ammo, const std::string &weaponName) : Weapon(weaponName, ShooterConsts::RIFLE_OBJ, Vec3D{3, 3, 3}, Vec3D{-1.2, 1, 0.3}, Vec3D{0, Consts::PI, 0}) { +Rifle::Rifle(int ammo, const std::string &weaponName) : Weapon(weaponName, ShooterConsts::RIFLE_OBJ, Vec3D{3, 3, 3}, Vec3D{-2.3, 1, 1.3}, Vec3D{0, Consts::PI, 0}) { fireSound = ShooterConsts::RIFLE_FIRE_SOUND; reloadSound = ShooterConsts::RIFLE_RELOAD_SOUND; diff --git a/weapon/Shotgun.cpp b/weapon/Shotgun.cpp index 59cd8ab..e7f96e3 100644 --- a/weapon/Shotgun.cpp +++ b/weapon/Shotgun.cpp @@ -9,7 +9,7 @@ using namespace std; -Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::SHOTGUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-0.95, 1.3, -0.6}, Vec3D{0, Consts::PI, 0}) { +Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, ShooterConsts::SHOTGUN_OBJ, Vec3D{3, 3, 3}, Vec3D{-1.95, 0.8, 1.5}, Vec3D{0, Consts::PI, 0}) { fireSound = ShooterConsts::SHOTGUN_FIRE_SOUND; reloadSound = ShooterConsts::SHOTGUN_RELOAD_SOUND; @@ -25,7 +25,7 @@ Shotgun::Shotgun(int ammo, const std::string& weaponName) : Weapon(weaponName, S } std::map -Shotgun::processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) { +Shotgun::processFire(std::function rayCastFunction, const Vec3D& position, const Vec3D& direction) { std::map damagedPlayers; for(int i = 0; i < 15; i++) { diff --git a/weapon/Shotgun.h b/weapon/Shotgun.h index 625f2af..ad5618d 100644 --- a/weapon/Shotgun.h +++ b/weapon/Shotgun.h @@ -10,7 +10,7 @@ class Shotgun final : public Weapon { public: explicit Shotgun(int ammo = 15, const std::string& weaponName = "shotgun"); - std::map processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) override; + std::map processFire(std::function rayCastFunction, const Vec3D& position, const Vec3D& direction) override; }; diff --git a/weapon/Weapon.cpp b/weapon/Weapon.cpp index 6f2c2aa..8895640 100644 --- a/weapon/Weapon.cpp +++ b/weapon/Weapon.cpp @@ -21,7 +21,7 @@ Weapon::Weapon(const std::string& weaponName, const std::string& objFileName, co translate(t); } -std::map Weapon::fire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) { +FireInformation Weapon::fire(std::function rayCastFunction, const Vec3D& position, const Vec3D& direction) { if(_clipAmmo == 0) { reload(); if(_clipAmmo == 0) @@ -29,7 +29,7 @@ std::map Weapon::fire(std::function(); + return FireInformation{std::map(), false}; _lastFireTime = Time::time(); _clipAmmo--; @@ -37,7 +37,7 @@ std::map Weapon::fire(std::function Weapon::processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction) { +std::map Weapon::processFire(std::function rayCastFunction, const Vec3D& position, const Vec3D& direction) { return addTrace(std::move(rayCastFunction), position, direction); } -std::map Weapon::addTrace(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& from, const Vec3D& directionTo) { +std::map Weapon::addTrace(std::function rayCastFunction, const Vec3D& from, const Vec3D& directionTo) { std::map damagedPlayers; double spreading = _spreading*ShooterConsts::FIRE_DISTANCE/100; @@ -70,13 +70,12 @@ std::map Weapon::addTrace(std::function damagedPlayers; + const bool shot; +}; + class Weapon : public RigidBody { protected: int _initialPack = 100; // how much ammo do you have when you find the weapon @@ -39,14 +44,14 @@ protected: std::function _addTraceCallBack; - std::map addTrace(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction); + std::map addTrace(std::function rayCastFunction, const Vec3D& position, const Vec3D& direction); - virtual std::map processFire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction); + virtual std::map processFire(std::function rayCastFunction, const Vec3D& position, const Vec3D& direction); public: Weapon(const std::string& weaponName, const std::string& objFileName, const Vec3D& scale, const Vec3D& translate, const Vec3D& rotate); - std::map fire(std::function(const Vec3D&, const Vec3D&)> rayCastFunction, const Vec3D& position, const Vec3D& direction); + FireInformation fire(std::function rayCastFunction, const Vec3D& position, const Vec3D& direction); void reload(); [[nodiscard]] std::pair balance() const{ return std::make_pair(_clipAmmo, _stockAmmo); }