diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d626ef..f27d813 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ set(SRC_FILES "src/systems/transform.cpp" "src/systems/render.cpp" + "src/systems/physics.cpp" "src/resources/shader.cpp" "src/resources/material.cpp" @@ -43,6 +44,7 @@ set(INCLUDE_FILES "include/systems/transform.hpp" "include/systems/render.hpp" + "include/systems/physics.hpp" "include/resources/shader.hpp" "include/resources/material.hpp" @@ -66,6 +68,7 @@ set(INCLUDE_FILES "include/components/transform.hpp" "include/components/renderable.hpp" + "include/components/collider.hpp" ) add_library(${PROJECT_NAME} STATIC diff --git a/include/components/collider.hpp b/include/components/collider.hpp new file mode 100644 index 0000000..d96805c --- /dev/null +++ b/include/components/collider.hpp @@ -0,0 +1,22 @@ +#pragma once + +namespace engine { + + class PhysicsSystem; + + struct ColliderComponent { + friend PhysicsSystem; + + float r; + + bool getIsColliding() { return m_isColliding; } + bool getJustCollided() { return m_justCollided; } + bool getJustUncollided() { return m_justUncollided; } + + private: + bool m_isColliding; + bool m_justCollided; + bool m_justUncollided; + }; + +} diff --git a/include/components/renderable.hpp b/include/components/renderable.hpp index c4f6b6b..f1d44fc 100644 --- a/include/components/renderable.hpp +++ b/include/components/renderable.hpp @@ -12,6 +12,7 @@ namespace engine { struct RenderableComponent { std::shared_ptr mesh; std::shared_ptr material; + bool shown = true; }; } diff --git a/include/systems/physics.hpp b/include/systems/physics.hpp new file mode 100644 index 0000000..e04d88f --- /dev/null +++ b/include/systems/physics.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "ecs_system.hpp" + +namespace engine { + + class PhysicsSystem : public System { + + public: + PhysicsSystem(Scene* scene); + + void onUpdate(float ts) override; + + }; + +} + diff --git a/src/scene.cpp b/src/scene.cpp index 26cc73f..027eaf9 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -2,8 +2,10 @@ #include "components/transform.hpp" #include "components/renderable.hpp" +#include "components/collider.hpp" #include "systems/transform.hpp" #include "systems/render.hpp" +#include "systems/physics.hpp" namespace engine { @@ -12,7 +14,11 @@ namespace engine { { registerComponent(); registerComponent(); + registerComponent(); + + // Order here matters: registerSystem(); + registerSystem(); registerSystem(); } diff --git a/src/systems/physics.cpp b/src/systems/physics.cpp new file mode 100644 index 0000000..e702b38 --- /dev/null +++ b/src/systems/physics.cpp @@ -0,0 +1,97 @@ +#include "systems/physics.hpp" + +#include "components/transform.hpp" +#include "components/collider.hpp" +#include "components/renderable.hpp" +#include "scene.hpp" + +#include "log.hpp" + +namespace engine { + + PhysicsSystem::PhysicsSystem(Scene* scene) + : System(scene, { typeid(TransformComponent).hash_code(), typeid(ColliderComponent).hash_code() }) + { + + } + + void PhysicsSystem::onUpdate(float ts) + { + (void)ts; + + using glm::vec3; + + struct CollisionInfo { + uint32_t entity; + TransformComponent* t; + ColliderComponent* c; + + vec3 pos; + + bool wasColliding; + }; + + std::vector entityColliders(m_entities.size()); + + uint32_t i = 0; + for (uint32_t entity : m_entities) { + auto t = m_scene->getComponent(entity); + auto c = m_scene->getComponent(entity); + + entityColliders[i].entity = entity; + entityColliders[i].t = t; + entityColliders[i].c = c; + + entityColliders[i].wasColliding = c->getIsColliding(); + c->m_isColliding = false; + c->m_justCollided = false; + c->m_justUncollided = false; + + vec3 pos = reinterpret_cast(t->worldMatrix[3]); + entityColliders[i].pos = pos; + + i++; + } + + for (size_t i = 0; i < entityColliders.size(); i++) { + for (size_t j = i + 1; j < entityColliders.size(); j++) { + const vec3 v = entityColliders[i].pos - entityColliders[j].pos; + const float distanceSquared = v.x * v.x + v.y * v.y + v.z * v.z; + const float sumOfRadii = entityColliders[i].c->r + entityColliders[j].c->r; + const float sumOfRadiiSquared = sumOfRadii * sumOfRadii; + + if (distanceSquared < sumOfRadiiSquared) { + entityColliders[i].c->m_isColliding = true; + entityColliders[j].c->m_isColliding = true; + } + } + + if (entityColliders[i].wasColliding != entityColliders[i].c->getIsColliding()) { + if (entityColliders[i].c->getIsColliding()) { + entityColliders[i].c->m_justCollided = true; + } else { + entityColliders[i].c->m_justUncollided = true; + } + } + + if (entityColliders[i].c->getJustCollided()) { + TRACE("'{}' has collided!", entityColliders[i].t->tag); + auto r = m_scene->getComponent(entityColliders[i].entity); + if (r != nullptr) { + r->shown = true; + } + } + if (entityColliders[i].c->getJustUncollided()) { + TRACE("'{}' has stopped colliding!", entityColliders[i].t->tag); + auto r = m_scene->getComponent(entityColliders[i].entity); + if (r != nullptr) { + r->shown = false; + } + } + + } + + } + +} + diff --git a/src/systems/render.cpp b/src/systems/render.cpp index fc48b56..d5dc1d7 100644 --- a/src/systems/render.cpp +++ b/src/systems/render.cpp @@ -48,8 +48,10 @@ namespace engine { for (uint32_t entity : m_entities) { - auto t = m_scene->getComponent(entity); auto r = m_scene->getComponent(entity); + if (r->shown == false) continue; + + auto t = m_scene->getComponent(entity); assert(r->material != nullptr); assert(r->mesh != nullptr); diff --git a/test/src/game.cpp b/test/src/game.cpp index 66afffc..27475cb 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -10,6 +10,7 @@ #include "scene.hpp" #include "components/transform.hpp" +#include "components/collider.hpp" #include "components/renderable.hpp" #include "systems/transform.hpp" @@ -76,6 +77,9 @@ void playGame() + + // scene setup + auto myScene = app.sceneManager()->createEmptyScene(); myScene->registerComponent(); @@ -87,8 +91,13 @@ void playGame() myScene->registerResourceManager(); myScene->registerResourceManager(); + + + + auto camera = myScene->createEntity("camera"); myScene->addComponent(camera)->standingHeight = myScene->getComponent(camera)->position.y = 2.0f; + myScene->addComponent(camera)->r = 1.0f; myScene->getSystem()->setCameraEntity(camera); engine::resources::Shader::VertexParams vertParams{}; @@ -110,7 +119,22 @@ void playGame() auto keepShader = myScene->addResource("theShader", std::move(theShader)); // uint32_t astronaut = engine::util::loadMeshFromFile(myScene, app.getResourcePath("models/astronaut/astronaut.dae")); -// myScene->addComponent(astronaut); + + auto grassTexture = std::make_shared( + app.gfx(), + app.getResourcePath("textures/grass.jpg") + ); + + uint32_t enemy = myScene->createEntity("enemy"); + auto enemyRenderable = myScene->addComponent(enemy); + enemyRenderable->material = std::make_unique(keepShader); + enemyRenderable->material->m_texture = grassTexture; + enemyRenderable->mesh = genSphereMesh(app.gfx(), 2.0f, 30, false); + auto enemyT = myScene->getComponent(enemy); + enemyT->position.x += 5.0f; + enemyT->position.y += 2.0f; + enemyT->position.z += 3.0f; + myScene->addComponent(enemy)->r = 10.0f; uint32_t sphere = myScene->createEntity("sphere"); auto sphereRenderable = myScene->addComponent(sphere); @@ -122,19 +146,16 @@ void playGame() myScene->getComponent(light)->position = glm::vec3{-10.0f, 10.0f, 10.0f}; auto lightRenderable = myScene->addComponent(light); lightRenderable->material = sphereRenderable->material; - lightRenderable->mesh = genSphereMesh(app.gfx(), 0.5f, 10, false, true); + lightRenderable->mesh = genSphereMesh(app.gfx(), 0.5f, 40, false, true); uint32_t floor = myScene->createEntity("floor"); myScene->getComponent(floor)->position = glm::vec3{-50.0f, -0.1f, -50.0f}; auto floorRenderable = myScene->addComponent(floor); floorRenderable->material = std::make_shared(*sphereRenderable->material); - auto grassTexture = std::make_unique( - app.gfx(), - app.getResourcePath("textures/grass.jpg") - ); - floorRenderable->material->m_texture = std::move(grassTexture); + floorRenderable->material->m_texture = grassTexture; floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f); + app.gameLoop(); INFO("texture addr: {}, shader addr: {}", (void*)keepTexture->getHandle(), (void*)keepShader->getPipeline());