From 0a0f4758b1fca505960613fac06de618d8cc2819 Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Thu, 9 Feb 2023 20:44:37 +0000 Subject: [PATCH] add cubez --- include/components/collider.hpp | 7 +---- src/systems/collisions.cpp | 54 ++++++++++++++++++++++++++++----- test/src/camera_controller.cpp | 25 ++++++++------- test/src/camera_controller.hpp | 5 +++ test/src/game.cpp | 34 ++++++++++++++++++++- 5 files changed, 97 insertions(+), 28 deletions(-) diff --git a/include/components/collider.hpp b/include/components/collider.hpp index e52cb25..40ee905 100644 --- a/include/components/collider.hpp +++ b/include/components/collider.hpp @@ -15,14 +15,9 @@ namespace engine { struct ColliderComponent { friend PhysicsSystem; - ColliderComponent() - { - - } - bool isStatic = true; bool isTrigger = false; // entity receives an event on collision enter and exit - AABB aabb{}; + AABB aabb{}; // broad phase bool getIsColliding() { return isColliding; } diff --git a/src/systems/collisions.cpp b/src/systems/collisions.cpp index f7ba7b6..a5c0b08 100644 --- a/src/systems/collisions.cpp +++ b/src/systems/collisions.cpp @@ -13,13 +13,6 @@ namespace engine { static bool checkCollisionFast(AABB a, AABB b) { - if (a.pos1.x > a.pos2.x) std::swap(a.pos1.x, a.pos2.x); - if (a.pos1.y > a.pos2.y) std::swap(a.pos1.y, a.pos2.y); - if (a.pos1.z > a.pos2.z) std::swap(a.pos1.z, a.pos2.z); - if (b.pos1.x > b.pos2.x) std::swap(b.pos1.x, b.pos2.x); - if (b.pos1.y > b.pos2.y) std::swap(b.pos1.y, b.pos2.y); - if (b.pos1.z > b.pos2.z) std::swap(b.pos1.z, b.pos2.z); - return ( a.pos1.x <= b.pos2.x && a.pos2.x >= b.pos1.x && @@ -30,6 +23,44 @@ namespace engine { ); } + static glm::vec3 getAABBNormal(AABB subject, AABB object) + { + // get centre position of static entity: + glm::vec3 subjectCentre = subject.pos1 + ((subject.pos2 - subject.pos1) / glm::vec3{ 2.0f, 2.0f, 2.0f }); + // find which face the centre is closest to: + const float PXdistance = glm::abs(subjectCentre.x - object.pos2.x); + const float NXdistance = glm::abs(subjectCentre.x - object.pos1.x); + const float PYdistance = glm::abs(subjectCentre.y - object.pos2.y); + const float NYdistance = glm::abs(subjectCentre.y - object.pos1.y); + const float PZdistance = glm::abs(subjectCentre.z - object.pos2.z); + const float NZdistance = glm::abs(subjectCentre.z - object.pos1.z); + const std::array distances { PXdistance, NXdistance, PYdistance, NYdistance, PZdistance, NZdistance }; + const auto maxDistance = std::max_element(distances.begin(), distances.end()); + const int index = maxDistance - distances.begin(); + switch (index) { + case 0: + // P_X + return {1.0f, 0.0f, 0.0f}; + case 1: + // N_X + return {-1.0f, 0.0f, 0.0f}; + case 2: + // P_Y + return {0.0f, 1.0f, 0.0f}; + case 3: + // N_Y + return {0.0f, -1.0f, 0.0f}; + case 4: + // P_Z + return {0.0f, 0.0f, 1.0f}; + case 5: + // N_Z + return {0.0f, 0.0f, -1.0f}; + default: + throw std::runtime_error("wtf"); + } + } + // class methods PhysicsSystem::PhysicsSystem(Scene* scene) @@ -68,6 +99,11 @@ namespace engine { globalBoundingBox.pos1 = globalPosition + localBoundingBox.pos1; globalBoundingBox.pos2 = globalPosition + localBoundingBox.pos2; + auto& a = globalBoundingBox; + if (a.pos1.x > a.pos2.x) std::swap(a.pos1.x, a.pos2.x); + if (a.pos1.y > a.pos2.y) std::swap(a.pos1.y, a.pos2.y); + if (a.pos1.z > a.pos2.z) std::swap(a.pos1.z, a.pos2.z); + if (c->isStatic) { m_staticAABBs.emplace_back(std::make_tuple(entity, globalBoundingBox, c->isTrigger)); } else { @@ -98,18 +134,20 @@ namespace engine { CollisionEvent info{}; info.isCollisionEnter = true; info.collidedEntity = possibleCollision.dynamicEntity; + info.normal = getAABBNormal(possibleCollision.staticAABB, possibleCollision.dynamicAABB); m_collisionInfos.emplace_back(possibleCollision.staticEntity, info); } if (possibleCollision.dynamicTrigger) { CollisionEvent info{}; info.isCollisionEnter = true; info.collidedEntity = possibleCollision.staticEntity; + info.normal = getAABBNormal(possibleCollision.dynamicAABB, possibleCollision.staticAABB); m_collisionInfos.emplace_back(possibleCollision.dynamicEntity, info); } } for (auto [entity, info] : m_collisionInfos) { - m_scene->events()->queueEvent(EventSubscriberKind::ENTITY, entity, info); + m_scene->events()->queueEvent(EventSubscriberKind::ENTITY, entity, info); } } diff --git a/test/src/camera_controller.cpp b/test/src/camera_controller.cpp index 12b3105..cdb9f0f 100644 --- a/test/src/camera_controller.cpp +++ b/test/src/camera_controller.cpp @@ -23,19 +23,17 @@ CameraControllerSystem::CameraControllerSystem(engine::Scene* scene) void CameraControllerSystem::onUpdate(float ts) { - engine::TransformComponent* t = nullptr; - engine::ColliderComponent* col = nullptr; - CameraControllerComponent* c = nullptr; - for (uint32_t entity : m_entities) { - t = m_scene->getComponent(entity); - col = m_scene->getComponent(entity); - c = m_scene->getComponent(entity); - break; + if (t == nullptr || c == nullptr || col == nullptr) { + for (uint32_t entity : m_entities) { + t = m_scene->getComponent(entity); + col = m_scene->getComponent(entity); + c = m_scene->getComponent(entity); + break; + } + if (t == nullptr) return; + if (c == nullptr) return; + if (col == nullptr) return; } - if (t == nullptr) return; - if (c == nullptr) return; - if (col == nullptr) return; - // calculate new position // use one unit per meter @@ -177,5 +175,6 @@ void CameraControllerSystem::onUpdate(float ts) // called once per frame void CameraControllerSystem::onEvent(engine::PhysicsSystem::CollisionEvent info) { - (void)info; + INFO("NORMAL X: {}, Y: {}, Z: {}", info.normal.x, info.normal.y, info.normal.z); + t->position += info.normal; } diff --git a/test/src/camera_controller.hpp b/test/src/camera_controller.hpp index f1cbfd7..8b62cfc 100644 --- a/test/src/camera_controller.hpp +++ b/test/src/camera_controller.hpp @@ -3,6 +3,7 @@ #include "ecs_system.hpp" #include "event_system.hpp" +#include "components/transform.hpp" #include "systems/collisions.hpp" struct CameraControllerComponent { @@ -30,4 +31,8 @@ public: // engine::EventHandler overrides void onEvent(engine::PhysicsSystem::CollisionEvent info) override; + + engine::TransformComponent* t = nullptr; + engine::ColliderComponent* col = nullptr; + CameraControllerComponent* c = nullptr; }; diff --git a/test/src/game.cpp b/test/src/game.cpp index c177be2..f866e1c 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -87,7 +87,7 @@ void playGame(bool enableFrameLimiter) ); /* skybox */ - if (0) { + { uint32_t skybox = myScene->createEntity("skybox"); auto skyboxRenderable = myScene->addComponent(skybox); skyboxRenderable->material = std::make_unique(app.getResource("engine.skybox")); @@ -126,6 +126,38 @@ void playGame(bool enableFrameLimiter) floorCollider->aabb = { { 0.0f, 0.0f, 0.0f }, { 100.0f, 0.1f, 100.0f } }; } + // cubes! + { + constexpr int SIZE = 10; + + const uint32_t cubeParent = myScene->createEntity("cubeParent"); + myScene->getComponent(cubeParent)->position = { 10.0f, 5.0f, 10.0f }; + + std::shared_ptr cubeMesh = genCuboidMesh(app.gfx(), 0.1f, 0.1f, 0.1f); + const auto cubeMaterial = std::make_shared(app.getResource("engine.textured")); + cubeMaterial->m_texture = app.getResource("engine.white"); + + uint32_t cubes[SIZE][SIZE][SIZE]; + for (int x = 0; x < SIZE; x++) { + for (int y = 0; y < SIZE; y++) { + for (int z = 0; z < SIZE; z++) { + const uint32_t cube = myScene->createEntity("cube" + std::to_string(x * 100 + y * 10 + z), cubeParent); + + auto transform = myScene->getComponent(cube); + auto renderable = myScene->addComponent(cube); + + transform->position = { (float)x, (float)y, (float)z }; + renderable->mesh = cubeMesh; + renderable->material = cubeMaterial; + + cubes[x][y][z] = cube; + } + } + } + + (void)cubes; + } + app.gameLoop(); }