From 30d70e178eae7fb66d86c328a899cbd118b4e08d Mon Sep 17 00:00:00 2001 From: tovjemam Date: Sun, 10 Aug 2025 18:45:06 +0200 Subject: [PATCH] Non functional collision --- src/app.cpp | 138 +++++++++++++++++++++-- src/app.hpp | 15 ++- src/collision/capsule_triangle_sweep.cpp | 16 +-- src/collision/capsule_triangle_sweep.hpp | 19 ++++ src/game/entity.cpp | 6 + src/game/entity.hpp | 27 +++++ src/game/player_input.hpp | 18 +++ src/gfx/renderer.cpp | 2 +- src/gfx/renderer.hpp | 2 + src/main.cpp | 28 ++++- 10 files changed, 241 insertions(+), 30 deletions(-) create mode 100644 src/game/entity.cpp create mode 100644 src/game/player_input.hpp diff --git a/src/app.cpp b/src/app.cpp index 20769cb..f1fd25a 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1,6 +1,7 @@ #include "app.hpp" #include +#include "collision/capsule_triangle_sweep.hpp" App::App() { @@ -21,27 +22,140 @@ App::App() world_.LinkPortals(s1, "NDoor", s2, "WDoor"); world_.LinkPortals(s2, "NDoor", s2, "SDoor"); + + player_ = world_.Spawn(s1, glm::vec3(0.0f, 0.0f, 1.0f)); } void App::Frame() { - float aspect = static_cast(m_viewport_size.x) / static_cast(m_viewport_size.y); + float delta_time = time_ - prev_time_; + prev_time_ = time_; - renderer_.Begin(m_viewport_size.x, m_viewport_size.y); + if (delta_time < 0.0f) + { + delta_time = 0.0f; // Prevent negative delta time + } + else if (delta_time > 0.1f) + { + delta_time = 0.1f; // Cap delta time to avoid large jumps + } - float cameraDistance = 2.0f; - float angle = m_time * 0.1f; // Rotate over time + float aspect = static_cast(viewport_size_.x) / static_cast(viewport_size_.y); + + renderer_.Begin(viewport_size_.x, viewport_size_.y); + + //float cameraDistance = 2.0f; + //float angle = time_ * 0.1f; // Rotate over time + // + //glm::vec3 cameraPos = glm::vec3( + // cameraDistance * cos(angle), + // cameraDistance * sin(angle), + // cameraDistance * 0.13f + //); + + //glm::vec3 center(0.0f, 0.0f, 1.5f); + //glm::vec3 up(0.0f, 0.0f, 1.0f); + + //renderer_.DrawWorld(world_, 1, center + cameraPos, -cameraPos, up, aspect, 60.0f); + + static glm::vec3 position(0.0f, 0.0f, 1.5f); + + glm::vec3 velocity(0.0f); + if (input_ & game::PI_FORWARD) + velocity.y += 1.0f; + + if (input_ & game::PI_BACKWARD) + velocity.y -= 1.0f; + + if (input_ & game::PI_LEFT) + velocity.x -= 1.0f; + + if (input_ & game::PI_RIGHT) + velocity.x += 1.0f; + + if (input_ & game::PI_JUMP) + velocity.z += 1.0f; + + if (input_ & game::PI_CROUCH) + velocity.z -= 1.0f; + + + //velocity.z = -1.0f; + + + glm::vec3 cameraDir = glm::vec3(1.0f, 0.0f, 0.0f); + auto tris = world_.GetSector(0).GetMesh()->GetCollisionMesh()->GetTriangles(); - glm::vec3 cameraPos = glm::vec3( - cameraDistance * cos(angle), - cameraDistance * sin(angle), - cameraDistance * 0.13f - ); + glm::vec3 c0 = position; + c0.z -= 0.1f; + glm::vec3 c1 = position; + c1.z += 0.1f; - glm::vec3 center(0.0f, 0.0f, 1.5f); - glm::vec3 up(0.0f, 0.0f, 1.0f); - renderer_.DrawWorld(world_, 1, center + cameraPos, -cameraPos, up, aspect, 60.0f); + bool found = false; + + glm::vec3 u = velocity * delta_time; + + if (glm::length(velocity) > 0.001f) + { + //velocity = glm::normalize(velocity); + + //collision::ResolveCollisions( + // position, + // velocity, + // 0.5f, + // 0.2f, + // delta_time, + // tris + //); + + Sweep sweep; + + static std::vector sweep_tris; + sweep_tris.clear(); + + for (const auto& tri : tris) { + float dot = glm::dot(tri.verts[1] - tri.verts[0], tri.verts[2] - tri.verts[0]); + if (glm::abs(dot) < 0.001f) { + printf("degen!!!!!!!!!\n"); + continue; // Skip degenerate triangles + } + + //found = found || collision::SweepCapsuleTriangle( + // sweep, + // c0, + // c1, + // 0.2f, + // u, + // tri.verts[0], tri.verts[1], tri.verts[2] + //); + + sweep_tris.push_back(tri); + } + + collision::ResolveCollisions( + position, + velocity, + 0.5f, // Capsule radius + 0.2f, // Capsule height + delta_time, + sweep_tris + ); + } + + if (!found) + { + position += velocity * delta_time; + } + + printf("position: %.2f, %.2f, %.2f\n", position.x, position.y, position.z); + printf("found: %s\n", found ? "true" : "false"); + + renderer_.DrawWorld(world_, 0, position, cameraDir, glm::vec3(0.0f, 0.0f, 1.0f), aspect, 60.0f); +} + +void App::MouseMove(const glm::vec2& delta) +{ } diff --git a/src/app.hpp b/src/app.hpp index c8ee2f0..dffdd18 100644 --- a/src/app.hpp +++ b/src/app.hpp @@ -3,14 +3,19 @@ #include "assets/sectordef.hpp" #include "game/world.hpp" +#include "game/player_input.hpp" #include "gfx/renderer.hpp" class App { - float m_time = 0.0f; - glm::ivec2 m_viewport_size = { 800, 600 }; + float time_ = 0.0f; + glm::ivec2 viewport_size_ = { 800, 600 }; + game::PlayerInputFlags input_ = 0; + + float prev_time_ = 0.0f; game::World world_; + game::Entity* player_ = nullptr; gfx::Renderer renderer_; @@ -19,8 +24,10 @@ public: void Frame(); - void SetTime(float time) { m_time = time; } - void SetViewportSize(int width, int height) { m_viewport_size = { width, height }; } + void SetTime(float time) { time_ = time; } + void SetViewportSize(int width, int height) { viewport_size_ = { width, height }; } + void SetInput(game::PlayerInputFlags input) { input_ = input; } + void MouseMove(const glm::vec2& delta); ~App(); }; diff --git a/src/collision/capsule_triangle_sweep.cpp b/src/collision/capsule_triangle_sweep.cpp index 8cc1a3e..0264acb 100644 --- a/src/collision/capsule_triangle_sweep.cpp +++ b/src/collision/capsule_triangle_sweep.cpp @@ -2,14 +2,6 @@ #define EPSILON 1e-5f // Used to test if float is close to 0. Tweak this if you get problems. -struct Sweep -{ - float time; // Non-negative time of first contact. - float depth; // Non-negative penetration depth if objects start initially colliding. - glm::vec3 point; // Point of first-contact. Only updated when contact occurs. - glm::vec3 normal; // Unit-length collision normal. Only updated when contact occurs. -}; - // Return whether point P is contained inside 3D region delimited by triangle T0,T1,T2 edges. static bool PointInsideTriangle(const glm::vec3& p, const glm::vec3& t0, const glm::vec3& t1, const glm::vec3& t2) { @@ -59,8 +51,8 @@ static bool PointInsideTriangularPrism( glm::vec3 faces[5][3] = { { a0,a1,a2 }, { b0,b2,b1 }, { a0,b0,a1 }, { a1,b1,a2 }, { a2,b2,a0 } }; float sgn = 0; for (int i = 0; i < 5; i++) { - const glm::vec3& p0 = faces[i][0]; - const glm::vec3& p1 = faces[i][1]; + const glm::vec3& p0 = faces[i][1]; + const glm::vec3& p1 = faces[i][0]; const glm::vec3& p2 = faces[i][2]; // Check which side of plane point is in. If it's always on the same side, it's colliding. @@ -284,7 +276,7 @@ static bool SweepPointUncappedCylinder( // v capsule velocity // t0,t1,t2 3 triangle vertices // returns whether the capsule and triangle intersect -static bool SweepCapsuleTriangle( +bool collision::SweepCapsuleTriangle( Sweep& s, const glm::vec3& c0, const glm::vec3& c1, @@ -398,7 +390,7 @@ static bool SweepCapsuleTriangle( // r - capsule radius // dt - time-step length // triangles - list of triangles to collide with -void ResolveCollisions(glm::vec3& p, glm::vec3& v, float h, float r, float dt, std::span triangles) { +void collision::ResolveCollisions(glm::vec3& p, glm::vec3& v, float h, float r, float dt, std::span triangles) { // Store the leftover movement in this vector. glm::vec3 u = dt * v; diff --git a/src/collision/capsule_triangle_sweep.hpp b/src/collision/capsule_triangle_sweep.hpp index 8e4fe03..3f92a13 100644 --- a/src/collision/capsule_triangle_sweep.hpp +++ b/src/collision/capsule_triangle_sweep.hpp @@ -3,7 +3,26 @@ #include "capsule.hpp" #include "trianglemesh.hpp" +struct Sweep +{ + float time = 1.0f; // Non-negative time of first contact. + float depth = 0.0f; // Non-negative penetration depth if objects start initially colliding. + glm::vec3 point = glm::vec3(0.0f); // Point of first-contact. Only updated when contact occurs. + glm::vec3 normal = glm::vec3(0.0f); // Unit-length collision normal. Only updated when contact occurs. +}; + namespace collision { + bool SweepCapsuleTriangle( + Sweep& s, + const glm::vec3& c0, + const glm::vec3& c1, + float r, + const glm::vec3& v, + const glm::vec3& t0, + const glm::vec3& t1, + const glm::vec3& t2); + + void ResolveCollisions(glm::vec3& p, glm::vec3& v, float h, float r, float dt, std::span triangles); } \ No newline at end of file diff --git a/src/game/entity.cpp b/src/game/entity.cpp new file mode 100644 index 0000000..62f0bb6 --- /dev/null +++ b/src/game/entity.cpp @@ -0,0 +1,6 @@ +#include "entity.hpp" + +game::Entity::Entity(World* world, size_t sector_idx, const glm::vec3& position) +{ + +} diff --git a/src/game/entity.hpp b/src/game/entity.hpp index 5884bf7..54c6869 100644 --- a/src/game/entity.hpp +++ b/src/game/entity.hpp @@ -1,9 +1,36 @@ #pragma once +#include +#include "sector.hpp" + namespace game { + class World; + + class EntityOccurrence + { + const Sector* sector_; + + float radius_; + glm::vec3 position_; + glm::vec3 up_; + + glm::mat3 trans_; + glm::mat3 inv_trans_; + + }; + class Entity { + World* world_; + + std::unique_ptr occu_; + std::unique_ptr other_occu_; + + glm::vec3 velocity_; + + public: + Entity(World* world, size_t sector_idx, const glm::vec3& position); }; diff --git a/src/game/player_input.hpp b/src/game/player_input.hpp new file mode 100644 index 0000000..f09c576 --- /dev/null +++ b/src/game/player_input.hpp @@ -0,0 +1,18 @@ +#pragma once + +namespace game +{ + enum PlayerInput + { + PI_FORWARD = 1 << 0, + PI_BACKWARD = 1 << 1, + PI_LEFT = 1 << 2, + PI_RIGHT = 1 << 3, + PI_JUMP = 1 << 4, + PI_CROUCH = 1 << 5, + PI_USE = 1 << 6, + PI_ATTACK = 1 << 7, + }; + + using PlayerInputFlags = unsigned int; +} diff --git a/src/gfx/renderer.cpp b/src/gfx/renderer.cpp index 8027c79..95451fa 100644 --- a/src/gfx/renderer.cpp +++ b/src/gfx/renderer.cpp @@ -132,7 +132,7 @@ void gfx::Renderer::DrawSector(const DrawSectorParams& params) void gfx::Renderer::DrawPortal(const DrawSectorParams& params, const game::Portal& portal) { - if (params.recursion > 10) + if (params.recursion > max_portal_recursion_) { return; // Recursion limit reached } diff --git a/src/gfx/renderer.hpp b/src/gfx/renderer.hpp index b440ba9..b2699aa 100644 --- a/src/gfx/renderer.hpp +++ b/src/gfx/renderer.hpp @@ -42,6 +42,8 @@ namespace gfx std::shared_ptr portal_vao_; void SetupPortalVAO(); + size_t max_portal_recursion_ = 24; + glm::mat4 proj_; void DrawSector(const DrawSectorParams& params); diff --git a/src/main.cpp b/src/main.cpp index 6bfde5d..08bd590 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -94,7 +94,7 @@ static bool InitGL() glEnable(GL_DEBUG_OUTPUT); glDebugMessageCallback(GLDebugCallback, 0); - SDL_GL_SetSwapInterval(0); + SDL_GL_SetSwapInterval(1); #endif @@ -143,6 +143,32 @@ static void Frame() int width, height; SDL_GetWindowSize(s_window, &width, &height); s_app->SetViewportSize(width, height); + + game::PlayerInputFlags input = 0; + const uint8_t* state = SDL_GetKeyboardState(nullptr); + + if (state[SDL_GetScancodeFromKey(SDLK_w)]) + input |= game::PI_FORWARD; + + if (state[SDL_GetScancodeFromKey(SDLK_s)]) + input |= game::PI_BACKWARD; + + if (state[SDL_GetScancodeFromKey(SDLK_a)]) + input |= game::PI_LEFT; + + if (state[SDL_GetScancodeFromKey(SDLK_d)]) + input |= game::PI_RIGHT; + + if (state[SDL_GetScancodeFromKey(SDLK_SPACE)]) + input |= game::PI_JUMP; + + if (state[SDL_GetScancodeFromKey(SDLK_LCTRL)]) + input |= game::PI_CROUCH; + + if (state[SDL_GetScancodeFromKey(SDLK_e)]) + input |= game::PI_USE; + + s_app->SetInput(input); s_app->Frame(); SDL_GL_SwapWindow(s_window);