From 2e215cbd5cbf0ce7b865eea55ab306c3907a7cdc Mon Sep 17 00:00:00 2001 From: Notiooo Date: Thu, 14 Dec 2023 23:55:48 +0100 Subject: [PATCH] Add drawable colliders of AABB and ray Adds implementations of drawable colliders, which, in addition to acting like a collider, also have their own graphical representation --- .../Shaders/Graphics/Physics/AABB.fs | 8 +++ .../Shaders/Graphics/Physics/AABB.vs | 10 +++ .../resources/Shaders/Graphics/Physics/Ray.fs | 2 +- AimGL/src/CMakeLists_Sources.txt | 3 + AimGL/src/World/Physics/Drawable/AABB.cpp | 54 ++++++++++++++ AimGL/src/World/Physics/Drawable/AABB.h | 66 +++++++++++++++++ .../Physics/Drawable/DrawableCollider.cpp | 2 + .../World/Physics/Drawable/DrawableCollider.h | 70 +++++++++++++++++++ AimGL/src/World/Physics/Drawable/Ray.cpp | 29 ++++++++ AimGL/src/World/Physics/Drawable/Ray.h | 51 ++++++++++++++ 10 files changed, 294 insertions(+), 1 deletion(-) create mode 100644 AimGL/resources/Shaders/Graphics/Physics/AABB.fs create mode 100644 AimGL/resources/Shaders/Graphics/Physics/AABB.vs create mode 100644 AimGL/src/World/Physics/Drawable/AABB.cpp create mode 100644 AimGL/src/World/Physics/Drawable/AABB.h create mode 100644 AimGL/src/World/Physics/Drawable/DrawableCollider.cpp create mode 100644 AimGL/src/World/Physics/Drawable/DrawableCollider.h create mode 100644 AimGL/src/World/Physics/Drawable/Ray.cpp create mode 100644 AimGL/src/World/Physics/Drawable/Ray.h diff --git a/AimGL/resources/Shaders/Graphics/Physics/AABB.fs b/AimGL/resources/Shaders/Graphics/Physics/AABB.fs new file mode 100644 index 0000000..e4151f5 --- /dev/null +++ b/AimGL/resources/Shaders/Graphics/Physics/AABB.fs @@ -0,0 +1,8 @@ +#version 330 core +out vec4 FragColor; + +uniform vec3 aabbColor = vec3(0,0.8,0); + +void main() { + FragColor = vec4(aabbColor, 1.0); +} diff --git a/AimGL/resources/Shaders/Graphics/Physics/AABB.vs b/AimGL/resources/Shaders/Graphics/Physics/AABB.vs new file mode 100644 index 0000000..8a9fe20 --- /dev/null +++ b/AimGL/resources/Shaders/Graphics/Physics/AABB.vs @@ -0,0 +1,10 @@ +#version 330 core +layout (location = 0) in vec3 aPos; + +uniform mat4 model = mat4(1.0); +uniform mat4 view; +uniform mat4 projection; + +void main() { + gl_Position = projection * view * model * vec4(aPos, 1.0); +} diff --git a/AimGL/resources/Shaders/Graphics/Physics/Ray.fs b/AimGL/resources/Shaders/Graphics/Physics/Ray.fs index 36b19dc..b2b23b9 100644 --- a/AimGL/resources/Shaders/Graphics/Physics/Ray.fs +++ b/AimGL/resources/Shaders/Graphics/Physics/Ray.fs @@ -1,7 +1,7 @@ #version 330 core out vec4 FragColor; -uniform vec3 rayColor = vec3(0,1,0); +uniform vec3 rayColor = vec3(0,0.8,0); void main() { FragColor = vec4(rayColor, 1.0); diff --git a/AimGL/src/CMakeLists_Sources.txt b/AimGL/src/CMakeLists_Sources.txt index 091b284..97720dd 100644 --- a/AimGL/src/CMakeLists_Sources.txt +++ b/AimGL/src/CMakeLists_Sources.txt @@ -27,6 +27,9 @@ set(PROJECT_SOURCES World/Camera.cpp World/InfiniteGridFloor.cpp World/Scene/GameObjects/Rifle.cpp + World/Physics/Drawable/AABB.cpp + World/Physics/Drawable/Ray.cpp + World/Physics/Drawable/DrawableCollider.cpp World/Physics/Collider.cpp World/Physics/ColliderRegister.cpp World/Physics/RayCollider.cpp diff --git a/AimGL/src/World/Physics/Drawable/AABB.cpp b/AimGL/src/World/Physics/Drawable/AABB.cpp new file mode 100644 index 0000000..ec0aed0 --- /dev/null +++ b/AimGL/src/World/Physics/Drawable/AABB.cpp @@ -0,0 +1,54 @@ +#include "AABB.h" +#include "pch.h" + +#include "Renderer/Renderer.h" + +void AABB::updateBuffers() +{ + std::vector vertices = { + // 8 corners of the AABB + mMin.x, mMin.y, mMin.z,// 0: Bottom-back-left + mMax.x, mMin.y, mMin.z,// 1: Bottom-back-right + mMin.x, mMax.y, mMin.z,// 2: Top-back-left + mMax.x, mMax.y, mMin.z,// 3: Top-back-right + mMin.x, mMin.y, mMax.z,// 4: Bottom-front-left + mMax.x, mMin.y, mMax.z,// 5: Bottom-front-right + mMin.x, mMax.y, mMax.z,// 6: Top-front-left + mMax.x, mMax.y, mMax.z,// 7: Top-front-right + }; + + std::vector indices = { + // Each pair of indices represents one line segment + 0, 1, 1, 5, 5, 4, 4, 0,// Bottom rectangle + 2, 3, 3, 7, 7, 6, 6, 2,// Top rectangle + 0, 2, 1, 3, 4, 6, 5, 7 // Connecting edges + }; + + mVBO.setBuffer(vertices); + mEBO.setBuffer(indices); + mVAO.setBuffer(mVBO, mBufferLayout); +} + +AABB::AABB(ColliderRegister& colliderRegister, const glm::vec3& min, const glm::vec3& max) + : DrawableCollider(colliderRegister, min, max) + , mMin(mCollider.min) + , mMax(mCollider.max) + , mShader{{ShaderType::VertexShader, "resources/Shaders/Graphics/Physics/AABB.vs"}, + {ShaderType::FragmentShader, "resources/Shaders/Graphics/Physics/AABB.fs"}} +{ + mBufferLayout.push(3); + updateBuffers(); +} + +void AABB::draw(const Renderer& target, const Camera& camera) const +{ + target.draw3D(mVAO, mEBO, mShader, camera, Renderer::DrawMode::Lines); +} + +void AABB::setPosition(const glm::vec3& position) +{ + auto diff = mMax - mMin; + mMin = position; + mMax = mMin + diff; + updateBuffers(); +} diff --git a/AimGL/src/World/Physics/Drawable/AABB.h b/AimGL/src/World/Physics/Drawable/AABB.h new file mode 100644 index 0000000..a3ce5e5 --- /dev/null +++ b/AimGL/src/World/Physics/Drawable/AABB.h @@ -0,0 +1,66 @@ +#pragma once +#include "Renderer/Core/Buffers/BufferLayout.h" +#include "Renderer/Core/Buffers/IndexBuffer.h" +#include "Renderer/Core/Buffers/VertexBuffer.h" +#include "Renderer/Core/Shader.h" +#include "Renderer/Core/VertexArray.h" +#include "World/Physics/Drawable/DrawableCollider.h" +#include "World/Physics/RectangleCollider.h" + +class Camera; +class Renderer; +class ColliderRegister; + +/** + * \brief Axis-Aligned Bounding Box (AABB) with drawable and collision detection capabilities. + */ +class AABB : public DrawableCollider +{ +public: + /** + * \brief Constructs an Axis-Aligned Bounding Box (AABB) collider. + * \param colliderRegister Reference to the collision register for tracking this collider. + * \param min The minimum corner point of the AABB in 3D space. + * \param max The maximum corner point of the AABB in 3D space. + */ + AABB(ColliderRegister& colliderRegister, const glm::vec3& min, const glm::vec3& max); + AABB(AABB&&) noexcept = default; + + /** + * \brief Draws a AABB for a given target + * \param target The target to which the AABB is drawn + * \param camera A camera in 3D space that looks at this object + */ + void draw(const Renderer& target, const Camera& camera) const; + + /** + * Updates the AABB logic dependent, or independent of time, every rendered frame. + * \param deltaTime the time that has passed since the game was last updated. + */ + void update(const float& deltaTime); + + /** + * \brief Sets the new AABB position + * \param position new position + */ + void setPosition(const glm::vec3& position); + +private: + /** + * \brief Updates buffers (e.g., the position of vertices) + * + * TODO: The current update is rather pointless. + * It is better to pass transformations to the shader + */ + void updateBuffers(); + +private: + glm::vec3& mMin; + glm::vec3& mMax; + + VertexArray mVAO; + VertexBuffer mVBO; + IndexBuffer mEBO; + BufferLayout mBufferLayout; + Shader mShader; +}; diff --git a/AimGL/src/World/Physics/Drawable/DrawableCollider.cpp b/AimGL/src/World/Physics/Drawable/DrawableCollider.cpp new file mode 100644 index 0000000..112c076 --- /dev/null +++ b/AimGL/src/World/Physics/Drawable/DrawableCollider.cpp @@ -0,0 +1,2 @@ +#include "DrawableCollider.h" +#include "pch.h" \ No newline at end of file diff --git a/AimGL/src/World/Physics/Drawable/DrawableCollider.h b/AimGL/src/World/Physics/Drawable/DrawableCollider.h new file mode 100644 index 0000000..5e2f49a --- /dev/null +++ b/AimGL/src/World/Physics/Drawable/DrawableCollider.h @@ -0,0 +1,70 @@ +#pragma once +#include "World/Physics/Collider.h" +#include "World/Physics/ColliderTag.h" + + +/** + * \brief A template class for colliders that are both drawable and functional in collision + * detection. \tparam ColliderType The type of collider this class is templating (e.g., + * SphereCollider, RectangleCollider). + */ +template +class DrawableCollider +{ +public: + virtual ~DrawableCollider() = default; + + /** + * \brief Constructor that initializes the collider with provided parameters. + * \tparam Args The types of arguments to forward to the ColliderType's constructor. + * \param params Arguments to forward to the ColliderType's constructor. + */ + template + explicit DrawableCollider(Args&&... params); + + /** + * \brief Sets a callback function to be executed when a collision occurs. + * \param callbackFunction The function to be called upon collision detection. + */ + void callback(std::function callbackFunction); + + /** + * \brief Retrieves the tag of the collider. + * \return The tag that identifies the type of the collider. + */ + [[nodiscard]] ColliderTag colliderTag() const; + + /** + * \brief Sets the tag identifying the type of the collider. + * \param colliderTag The tag to assign to the collider. + */ + void colliderTag(ColliderTag colliderTag); + +protected: + ColliderType mCollider; +}; + +template +template +DrawableCollider::DrawableCollider(Args&&... params) + : mCollider(std::forward(params)...) +{ +} + +template +void DrawableCollider::callback(std::function callbackFunction) +{ + mCollider.callback(callbackFunction); +} + +template +ColliderTag DrawableCollider::colliderTag() const +{ + return mCollider.colliderTag(); +} + +template +void DrawableCollider::colliderTag(ColliderTag colliderTag) +{ + mCollider.colliderTag(colliderTag); +} diff --git a/AimGL/src/World/Physics/Drawable/Ray.cpp b/AimGL/src/World/Physics/Drawable/Ray.cpp new file mode 100644 index 0000000..df9862b --- /dev/null +++ b/AimGL/src/World/Physics/Drawable/Ray.cpp @@ -0,0 +1,29 @@ +#include "Ray.h" +#include "pch.h" + +#include "Renderer/Renderer.h" + +Ray::Ray(ColliderRegister& colliderRegister, const glm::vec3& origin, const glm::vec3& direction, + float length) + : DrawableCollider(colliderRegister, origin, direction, length) + , mOrigin(mCollider.origin) + , mDirection(mCollider.direction) + , mLength(mCollider.length) + , mShader{{ShaderType::VertexShader, "resources/Shaders/Graphics/Physics/Ray.vs"}, + {ShaderType::FragmentShader, "resources/Shaders/Graphics/Physics/Ray.fs"}} +{ + glm::vec3 endPoint = mOrigin + mDirection * mLength; + + std::vector vertices = {mOrigin.x, mOrigin.y, mOrigin.z, + endPoint.x, endPoint.y, endPoint.z}; + mBufferLayout.push(3); + + mVBO.setBuffer(vertices); + mVAO.setBuffer(mVBO, mBufferLayout); +} + +void Ray::draw(const Renderer& target, const Camera& camera) const +{ + constexpr auto numberOfVertices = 6; + target.draw3D(mVAO, numberOfVertices, mShader, camera, Renderer::DrawMode::Lines); +} diff --git a/AimGL/src/World/Physics/Drawable/Ray.h b/AimGL/src/World/Physics/Drawable/Ray.h new file mode 100644 index 0000000..5a8fad8 --- /dev/null +++ b/AimGL/src/World/Physics/Drawable/Ray.h @@ -0,0 +1,51 @@ +#pragma once +#include "Renderer/Core/Buffers/BufferLayout.h" +#include "Renderer/Core/Buffers/VertexBuffer.h" +#include "Renderer/Core/Shader.h" +#include "Renderer/Core/VertexArray.h" +#include "World/Physics/Drawable/DrawableCollider.h" +#include "World/Physics/RayCollider.h" + +class Camera; +class Renderer; +class ColliderRegister; + +/** + * \brief Represents a ray in 3D space, defined by an origin point, direction vector, and length. + */ +class Ray : public DrawableCollider +{ +public: + /** + * \brief Constructs a Ray object. + * \param colliderRegister Reference to the collision register for tracking this collider. + * \param origin The starting point of the ray in 3D space. + * \param direction The direction vector of the ray. This vector should be normalized. + * \param length (Optional) The length of the ray. Default is 100 units. + */ + Ray(ColliderRegister& colliderRegister, const glm::vec3& origin, const glm::vec3& direction, + float length = 100); + Ray(Ray&&) noexcept = default; + + /** + * \brief Draws a Ray for a given target + * \param target The target to which the model is drawn + * \param camera A camera in 3D space that looks at this object + */ + void draw(const Renderer& target, const Camera& camera) const; + + /** + * Updates the Ray logic dependent, or independent of time, every rendered frame. + * \param deltaTime the time that has passed since the game was last updated. + */ + void update(const float& deltaTime); + +private: + glm::vec3& mOrigin; + glm::vec3& mDirection; + float& mLength; + VertexArray mVAO; + VertexBuffer mVBO; + BufferLayout mBufferLayout; + Shader mShader; +};