From fce32b13201f371a37cf56bc1994d49f40f53a32 Mon Sep 17 00:00:00 2001 From: bailwillharr Date: Thu, 26 Jan 2023 23:52:25 +0000 Subject: [PATCH] get wall collisions kind of working --- include/components/collider.hpp | 13 ++++++-- src/systems/physics.cpp | 11 +++++-- test/src/camera_controller.cpp | 57 +++++++++++++++++++-------------- test/src/game.cpp | 4 +-- 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/include/components/collider.hpp b/include/components/collider.hpp index e37de02..65318bc 100644 --- a/include/components/collider.hpp +++ b/include/components/collider.hpp @@ -1,5 +1,8 @@ #pragma once +#include +#include + namespace engine { class PhysicsSystem; @@ -20,14 +23,18 @@ namespace engine { } sphereCollider; } colliders; - bool getIsColliding() { return m_isColliding; } - bool getJustCollided() { return m_justCollided; } - bool getJustUncollided() { return m_justUncollided; } + auto getIsColliding() { return m_isColliding; } + auto getJustCollided() { return m_justCollided; } + auto getJustUncollided() { return m_justUncollided; } + auto getLastEntityCollided() { return m_lastEntityCollided; } + auto getLastCollisionNormal() { return m_lastCollisionNormal; } private: bool m_isColliding; bool m_justCollided; bool m_justUncollided; + uint32_t m_lastEntityCollided; + glm::vec3 m_lastCollisionNormal; }; } diff --git a/src/systems/physics.cpp b/src/systems/physics.cpp index 988cd7b..13b791a 100644 --- a/src/systems/physics.cpp +++ b/src/systems/physics.cpp @@ -53,6 +53,7 @@ namespace engine { i++; } + // compares every entity to every other entity, but pairs are never repeated for (size_t i = 0; i < entityColliders.size(); i++) { auto* ec1 = &entityColliders[i]; @@ -62,15 +63,18 @@ namespace engine { if ( ec1->c->colliderType == ColliderType::SPHERE && ec2->c->colliderType == ColliderType::SPHERE ) { - const vec3 v = ec1->pos - ec2->pos; + const vec3 v = ec2->pos - ec1->pos; const float distanceSquared = v.x * v.x + v.y * v.y + v.z * v.z; const float sumOfRadii = ec1->c->colliders.sphereCollider.r + ec2->c->colliders.sphereCollider.r; const float sumOfRadiiSquared = sumOfRadii * sumOfRadii; if (distanceSquared < sumOfRadiiSquared) { ec1->c->m_isColliding = true; + ec1->c->m_lastEntityCollided = ec2->entity; + ec1->c->m_lastCollisionNormal = glm::normalize(v); ec2->c->m_isColliding = true; + ec2->c->m_lastEntityCollided = ec1->entity; + ec2->c->m_lastCollisionNormal = -ec1->c->m_lastCollisionNormal; } - } else if ( (ec1->c->colliderType == ColliderType::PLANE && ec2->c->colliderType == ColliderType::SPHERE) || (ec1->c->colliderType == ColliderType::SPHERE && @@ -87,7 +91,10 @@ namespace engine { if (distance < 0.0f) distance = -distance; // make positive if (distance < sphere->c->colliders.sphereCollider.r) { plane->c->m_isColliding = true; + plane->c->m_lastEntityCollided = sphere->entity; sphere->c->m_isColliding = true; + sphere->c->m_lastEntityCollided = plane->entity; + sphere->c->m_lastCollisionNormal = {0.0f, 1.0f, 0.0f}; } } else { throw std::runtime_error("Collision combination not supported!"); diff --git a/test/src/camera_controller.cpp b/test/src/camera_controller.cpp index 94a9a12..613b61a 100644 --- a/test/src/camera_controller.cpp +++ b/test/src/camera_controller.cpp @@ -42,34 +42,37 @@ void CameraControllerSystem::onUpdate(float ts) const float dt = ts; - // jumping constexpr float G = 9.8f; -// constexpr float JUMPHEIGHT = 16.0f * 25.4f / 1000.0f; // 16 inches - constexpr float JUMPVEL = (float)2.82231110971133017648; //std::sqrt(2 * G * JUMPHEIGHT); - //constexpr float JUMPDURATION = 0.5f; - //constexpr float JUMPVEL = G * JUMPDURATION / 2.0f; + constexpr float MAX_SLOPE_ANGLE = glm::radians(20.0f); - if (m_scene->app()->inputManager()->getButton("jump") && c->isJumping == false) { - c->isJumping = true; - c->dy = JUMPVEL; - - } + glm::vec3 norm = col->getLastCollisionNormal(); - if (c->isJumping) { - c->dy -= G * dt; - if (col->getIsColliding()) { - c->isJumping = false; + norm.y = 0.0f; + + glm::vec3 dir = glm::normalize(glm::rotateY(glm::vec3{ 1.0f, 0.0f, 0.0f }, c->m_yaw) + glm::rotateY(glm::vec3{ 0.0f, 0.0f, 1.0f }, c->m_yaw)); + const float slope = glm::half_pi() - glm::acos(glm::dot(dir, norm)); + + bool isSliding = false; + + if (col->getIsColliding()) { + if (c->dy != 0.0f && slope <= MAX_SLOPE_ANGLE) { + t->position.y = m_scene->getComponent(col->getLastEntityCollided())->worldMatrix[3][1] + 1.8f; c->dy = 0.0f; + } else { + // slide across wall + isSliding = true; } } else { - if (col->getIsColliding()) { - c->dy = -c->dy; - } + c->dy -= G * dt; } - if (col->getJustUncollided()) { - c->isJumping = true; + + + // jumping + constexpr float JUMPVEL = (float)2.82231110971133017648; //std::sqrt(2 * G * JUMPHEIGHT); + if (m_scene->app()->inputManager()->getButton("jump") && c->isJumping == false) { + if (col->getIsColliding()) + c->dy = JUMPVEL; } -// c->dy -= c->dy * dt; // damp velocity if (m_scene->app()->window()->getButton(engine::inputs::MouseButton::M_LEFT)) { c->dy += dt * c->thrust; @@ -81,8 +84,8 @@ void CameraControllerSystem::onUpdate(float ts) float SPEED = c->walk_speed; if (m_scene->app()->inputManager()->getButton("sprint")) SPEED *= 10.0f; - const float dx = m_scene->app()->inputManager()->getAxis("movex") * SPEED; - const float dz = (-m_scene->app()->inputManager()->getAxis("movey")) * SPEED; + float dx = m_scene->app()->inputManager()->getAxis("movex"); + float dz = (-m_scene->app()->inputManager()->getAxis("movey")); // calculate new pitch and yaw @@ -99,7 +102,12 @@ void CameraControllerSystem::onUpdate(float ts) // update position relative to camera direction in xz plane const glm::vec3 d2xRotated = glm::rotateY(glm::vec3{ dx, 0.0f, 0.0f }, c->m_yaw); const glm::vec3 d2zRotated = glm::rotateY(glm::vec3{ 0.0f, 0.0f, dz }, c->m_yaw); - t->position += (d2xRotated + d2zRotated) * dt; + glm::vec3 hVel = (d2xRotated + d2zRotated); + if (isSliding) { + hVel = glm::vec3{norm.z, 0.0f, norm.x}; + } + hVel *= SPEED; + t->position += hVel * dt; t->position.y += c->dy * dt; constexpr float MAX_DISTANCE_FROM_ORIGIN = 1000.0f; @@ -141,7 +149,8 @@ void CameraControllerSystem::onUpdate(float ts) " y: " + std::to_string(t->position.y) + " z: " + std::to_string(t->position.z) }; - m_scene->app()->window()->infoBox("POSITION", pos_string); +// m_scene->app()->window()->infoBox("POSITION", pos_string); + m_scene->app()->window()->infoBox("POSITION", std::to_string(slope)); INFO("position: " + pos_string); } diff --git a/test/src/game.cpp b/test/src/game.cpp index eb7dee7..9f9aa97 100644 --- a/test/src/game.cpp +++ b/test/src/game.cpp @@ -79,9 +79,9 @@ void playGame() enemyRenderable->material->m_texture = app.getResource("engine.white"); enemyRenderable->mesh = genSphereMesh(app.gfx(), 5.0f, 500, false); auto enemyT = myScene->getComponent(enemy); - enemyT->position.x += 5.0f; + enemyT->position.x += 10.0f; enemyT->position.y += 2.0f; - enemyT->position.z += 3.0f; + enemyT->position.z += 14.0f; auto enemyCollider = myScene->addComponent(enemy); enemyCollider->colliderType = engine::ColliderType::SPHERE; enemyCollider->colliders.sphereCollider.r = 5.0f;