Add basic sphere collision testing

This commit is contained in:
Bailey Harrison 2023-01-18 14:42:09 +00:00
parent 17f513d30f
commit 0a39baea20
8 changed files with 177 additions and 8 deletions

View File

@ -16,6 +16,7 @@ set(SRC_FILES
"src/systems/transform.cpp" "src/systems/transform.cpp"
"src/systems/render.cpp" "src/systems/render.cpp"
"src/systems/physics.cpp"
"src/resources/shader.cpp" "src/resources/shader.cpp"
"src/resources/material.cpp" "src/resources/material.cpp"
@ -43,6 +44,7 @@ set(INCLUDE_FILES
"include/systems/transform.hpp" "include/systems/transform.hpp"
"include/systems/render.hpp" "include/systems/render.hpp"
"include/systems/physics.hpp"
"include/resources/shader.hpp" "include/resources/shader.hpp"
"include/resources/material.hpp" "include/resources/material.hpp"
@ -66,6 +68,7 @@ set(INCLUDE_FILES
"include/components/transform.hpp" "include/components/transform.hpp"
"include/components/renderable.hpp" "include/components/renderable.hpp"
"include/components/collider.hpp"
) )
add_library(${PROJECT_NAME} STATIC add_library(${PROJECT_NAME} STATIC

View File

@ -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;
};
}

View File

@ -12,6 +12,7 @@ namespace engine {
struct RenderableComponent { struct RenderableComponent {
std::shared_ptr<resources::Mesh> mesh; std::shared_ptr<resources::Mesh> mesh;
std::shared_ptr<resources::Material> material; std::shared_ptr<resources::Material> material;
bool shown = true;
}; };
} }

View File

@ -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;
};
}

View File

@ -2,8 +2,10 @@
#include "components/transform.hpp" #include "components/transform.hpp"
#include "components/renderable.hpp" #include "components/renderable.hpp"
#include "components/collider.hpp"
#include "systems/transform.hpp" #include "systems/transform.hpp"
#include "systems/render.hpp" #include "systems/render.hpp"
#include "systems/physics.hpp"
namespace engine { namespace engine {
@ -12,7 +14,11 @@ namespace engine {
{ {
registerComponent<TransformComponent>(); registerComponent<TransformComponent>();
registerComponent<RenderableComponent>(); registerComponent<RenderableComponent>();
registerComponent<ColliderComponent>();
// Order here matters:
registerSystem<TransformSystem>(); registerSystem<TransformSystem>();
registerSystem<PhysicsSystem>();
registerSystem<RenderSystem>(); registerSystem<RenderSystem>();
} }

97
src/systems/physics.cpp Normal file
View File

@ -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<CollisionInfo> entityColliders(m_entities.size());
uint32_t i = 0;
for (uint32_t entity : m_entities) {
auto t = m_scene->getComponent<TransformComponent>(entity);
auto c = m_scene->getComponent<ColliderComponent>(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<vec3&>(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<RenderableComponent>(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<RenderableComponent>(entityColliders[i].entity);
if (r != nullptr) {
r->shown = false;
}
}
}
}
}

View File

@ -48,8 +48,10 @@ namespace engine {
for (uint32_t entity : m_entities) { for (uint32_t entity : m_entities) {
auto t = m_scene->getComponent<TransformComponent>(entity);
auto r = m_scene->getComponent<RenderableComponent>(entity); auto r = m_scene->getComponent<RenderableComponent>(entity);
if (r->shown == false) continue;
auto t = m_scene->getComponent<TransformComponent>(entity);
assert(r->material != nullptr); assert(r->material != nullptr);
assert(r->mesh != nullptr); assert(r->mesh != nullptr);

View File

@ -10,6 +10,7 @@
#include "scene.hpp" #include "scene.hpp"
#include "components/transform.hpp" #include "components/transform.hpp"
#include "components/collider.hpp"
#include "components/renderable.hpp" #include "components/renderable.hpp"
#include "systems/transform.hpp" #include "systems/transform.hpp"
@ -76,6 +77,9 @@ void playGame()
// scene setup
auto myScene = app.sceneManager()->createEmptyScene(); auto myScene = app.sceneManager()->createEmptyScene();
myScene->registerComponent<RotateComponent>(); myScene->registerComponent<RotateComponent>();
@ -87,8 +91,13 @@ void playGame()
myScene->registerResourceManager<engine::resources::Shader>(); myScene->registerResourceManager<engine::resources::Shader>();
myScene->registerResourceManager<engine::resources::Texture>(); myScene->registerResourceManager<engine::resources::Texture>();
auto camera = myScene->createEntity("camera"); auto camera = myScene->createEntity("camera");
myScene->addComponent<CameraControllerComponent>(camera)->standingHeight = myScene->getComponent<engine::TransformComponent>(camera)->position.y = 2.0f; myScene->addComponent<CameraControllerComponent>(camera)->standingHeight = myScene->getComponent<engine::TransformComponent>(camera)->position.y = 2.0f;
myScene->addComponent<engine::ColliderComponent>(camera)->r = 1.0f;
myScene->getSystem<engine::RenderSystem>()->setCameraEntity(camera); myScene->getSystem<engine::RenderSystem>()->setCameraEntity(camera);
engine::resources::Shader::VertexParams vertParams{}; engine::resources::Shader::VertexParams vertParams{};
@ -110,7 +119,22 @@ void playGame()
auto keepShader = myScene->addResource<engine::resources::Shader>("theShader", std::move(theShader)); auto keepShader = myScene->addResource<engine::resources::Shader>("theShader", std::move(theShader));
// uint32_t astronaut = engine::util::loadMeshFromFile(myScene, app.getResourcePath("models/astronaut/astronaut.dae")); // uint32_t astronaut = engine::util::loadMeshFromFile(myScene, app.getResourcePath("models/astronaut/astronaut.dae"));
// myScene->addComponent<RotateComponent>(astronaut);
auto grassTexture = std::make_shared<engine::resources::Texture>(
app.gfx(),
app.getResourcePath("textures/grass.jpg")
);
uint32_t enemy = myScene->createEntity("enemy");
auto enemyRenderable = myScene->addComponent<engine::RenderableComponent>(enemy);
enemyRenderable->material = std::make_unique<engine::resources::Material>(keepShader);
enemyRenderable->material->m_texture = grassTexture;
enemyRenderable->mesh = genSphereMesh(app.gfx(), 2.0f, 30, false);
auto enemyT = myScene->getComponent<engine::TransformComponent>(enemy);
enemyT->position.x += 5.0f;
enemyT->position.y += 2.0f;
enemyT->position.z += 3.0f;
myScene->addComponent<engine::ColliderComponent>(enemy)->r = 10.0f;
uint32_t sphere = myScene->createEntity("sphere"); uint32_t sphere = myScene->createEntity("sphere");
auto sphereRenderable = myScene->addComponent<engine::RenderableComponent>(sphere); auto sphereRenderable = myScene->addComponent<engine::RenderableComponent>(sphere);
@ -122,19 +146,16 @@ void playGame()
myScene->getComponent<engine::TransformComponent>(light)->position = glm::vec3{-10.0f, 10.0f, 10.0f}; myScene->getComponent<engine::TransformComponent>(light)->position = glm::vec3{-10.0f, 10.0f, 10.0f};
auto lightRenderable = myScene->addComponent<engine::RenderableComponent>(light); auto lightRenderable = myScene->addComponent<engine::RenderableComponent>(light);
lightRenderable->material = sphereRenderable->material; 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"); uint32_t floor = myScene->createEntity("floor");
myScene->getComponent<engine::TransformComponent>(floor)->position = glm::vec3{-50.0f, -0.1f, -50.0f}; myScene->getComponent<engine::TransformComponent>(floor)->position = glm::vec3{-50.0f, -0.1f, -50.0f};
auto floorRenderable = myScene->addComponent<engine::RenderableComponent>(floor); auto floorRenderable = myScene->addComponent<engine::RenderableComponent>(floor);
floorRenderable->material = std::make_shared<engine::resources::Material>(*sphereRenderable->material); floorRenderable->material = std::make_shared<engine::resources::Material>(*sphereRenderable->material);
auto grassTexture = std::make_unique<engine::resources::Texture>( floorRenderable->material->m_texture = grassTexture;
app.gfx(),
app.getResourcePath("textures/grass.jpg")
);
floorRenderable->material->m_texture = std::move(grassTexture);
floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f); floorRenderable->mesh = genCuboidMesh(app.gfx(), 100.0f, 0.1f, 100.0f);
app.gameLoop(); app.gameLoop();
INFO("texture addr: {}, shader addr: {}", (void*)keepTexture->getHandle(), (void*)keepShader->getPipeline()); INFO("texture addr: {}, shader addr: {}", (void*)keepTexture->getHandle(), (void*)keepShader->getPipeline());