Skip to content

Commit

Permalink
Implmented collision detection functions but box on box has issues wi…
Browse files Browse the repository at this point in the history
…th rotation.
  • Loading branch information
FraserConnolly committed May 9, 2024
1 parent 76c055c commit 4499c6f
Show file tree
Hide file tree
Showing 15 changed files with 908 additions and 58 deletions.
12 changes: 12 additions & 0 deletions Lab1/ColliderBase.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,13 @@
#include "ColliderBase.h"
#include "CollisionManager.h"


void Collider::Awake ( )
{
CollisionManager::RegisterCollider ( this );
}

void Collider::OnDestroy ( )
{
CollisionManager::DeregisterCollider ( this );
}
3 changes: 3 additions & 0 deletions Lab1/ColliderBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class Collider : public Component

virtual const glm::vec3 & GetCentre ( ) const = 0;

void Awake ( ) override;
void OnDestroy ( ) override;

protected:

Collider ( GameObject & hostObject, ComponentTypes type )
Expand Down
5 changes: 5 additions & 0 deletions Lab1/ColliderBox.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
#include "ColliderBox.h"
#include "Transform.h"

ColliderBox::ColliderBox ( GameObject & hostObject ) :
Collider ( hostObject, ComponentTypes::BOX_COLIDER ),
m_extents ( 1.0f )
{ }

const glm::vec3 & ColliderBox::GetCentre ( ) const
{
return m_transform.GetPosition ( );
Expand Down
4 changes: 1 addition & 3 deletions Lab1/ColliderBox.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ class ColliderBox :

friend class GameObject;

ColliderBox ( GameObject & hostObject ) :
Collider ( hostObject, ComponentTypes::BOX_COLIDER )
{ }
ColliderBox ( GameObject & hostObject );

public:

Expand Down
7 changes: 6 additions & 1 deletion Lab1/ColliderSphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

#include "Transform.h"

ColliderSphere::ColliderSphere ( GameObject & hostObject ) :
Collider ( hostObject, ComponentTypes::SPHERE_COLIDER ),
m_radious ( 1.0f )
{ }

const glm::vec3 & ColliderSphere::GetCentre ( ) const
{
return m_transform.GetPosition ( );
Expand All @@ -12,7 +17,7 @@ const float ColliderSphere::GetRadious ( ) const
return m_radious;
}

void ColliderSphere::SetRadious ( const float radious )
inline void ColliderSphere::SetRadious ( const float radious )
{
if ( radious < 0.0f )
{
Expand Down
4 changes: 1 addition & 3 deletions Lab1/ColliderSphere.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ class ColliderSphere :

friend class GameObject;

ColliderSphere ( GameObject & hostObject ) :
Collider ( hostObject, ComponentTypes::SPHERE_COLIDER )
{ }
ColliderSphere ( GameObject & hostObject );

public:

Expand Down
182 changes: 132 additions & 50 deletions Lab1/CollisionManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
#include "Transform.h"
#include "GameObject.h"
#include "ColliderBase.h"
#include "ColliderSphere.h"
#include "ColliderBox.h"
#include "Time.h"

#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/quaternion.hpp>
#include "Time.h"

struct TranslationData
{
Expand Down Expand Up @@ -81,9 +83,15 @@ struct ColliderData
const Collider & m_collider;
const Transform & m_transform;
bool m_isActive;

// cache of the position, rotation, and scale
TranslationData m_translation;

// the last frame in which this collider moved, scaled, rotated, or was enabled/disabled.
unsigned int m_lastFrameMoved;
std::vector<ColliderData *> m_currentCollisions;

// note that a collision record will only exist in the ColliderData for one of the two participants in the collision!
std::vector<ColliderData *> m_currentCollisions;

ColliderData ( const Collider & collider )
: m_collider ( collider ), m_transform ( collider.GetGameObject ( ).GetTransform ( ) ), m_lastFrameMoved ( 0 )
Expand All @@ -105,6 +113,11 @@ struct ColliderData

bool IsCurrentlyCollidingWith ( const ColliderData * pColliderData, std::vector<ColliderData *>::iterator & itorator )
{
if ( m_currentCollisions.size ( ) == 0 )
{
return false;
}

itorator = std::find (
m_currentCollisions.begin ( ),
m_currentCollisions.end ( ),
Expand Down Expand Up @@ -168,66 +181,65 @@ void CollisionManager::Service ( )
{
pColliderData->m_lastFrameMoved = currentFrameIndex;
}

}

// perform a pair wise collision detection.
// perform a pair wise collision detection.
auto numberOfColliders = s_instance->m_collisionWorld.size ( );

for ( int i = 0; i < numberOfColliders - 1; ++i )
{
auto & pColliderData = s_instance->m_collisionWorld [ i ];

auto numberOfColliders = s_instance->m_collisionWorld.size ( );
// can we skip this collider
if ( !pColliderData->m_isActive )
{
continue;
}

for ( int i = 0; i < numberOfColliders - 1; ++i )
// check this collider against the others
for ( int j = i + 1; j < numberOfColliders; ++j )
{
auto & pColliderData = s_instance->m_collisionWorld [ i ];
auto pOtherCollider = s_instance->m_collisionWorld [ j ];

// can we skip this collider
if ( ! pColliderData->m_isActive )
// check to see if neither collider moved this frame.
if ( pColliderData->m_lastFrameMoved != currentFrameIndex && pOtherCollider->m_lastFrameMoved != currentFrameIndex )
{
continue;
}

// check this collider against the others
for ( int j = i + 1; j < numberOfColliders; ++j )
{
auto pOtherCollider = s_instance->m_collisionWorld [ j ];

// check to see if neither collider moved this frame.
if ( pColliderData->m_lastFrameMoved != currentFrameIndex && pOtherCollider->m_lastFrameMoved != currentFrameIndex )
{
continue;
}
auto collided = AreIntersecting ( &pColliderData->m_collider, &pOtherCollider->m_collider );

auto collided = AreIntersecting ( &pColliderData->m_collider, &pOtherCollider->m_collider );
std::vector<ColliderData *>::iterator itorator;

std::vector<ColliderData *>::iterator itorator;

// check if we have previously collided.
bool previouslyCollided = pColliderData->IsCurrentlyCollidingWith ( pOtherCollider, itorator );
// check if we have previously collided.
bool previouslyCollided = pColliderData->IsCurrentlyCollidingWith ( pOtherCollider, itorator );

if ( collided && !previouslyCollided )
{
// this is a new collision so raise the enter event
pColliderData->m_transform.GetGameObject ( ).OnCollisionEnter ( pOtherCollider->m_collider );
pOtherCollider->m_transform.GetGameObject ( ).OnCollisionEnter ( pColliderData->m_collider );
if ( collided && !previouslyCollided )
{
// this is a new collision so raise the enter event
pColliderData->m_transform.GetGameObject ( ).OnCollisionEnter ( pOtherCollider->m_collider );
pOtherCollider->m_transform.GetGameObject ( ).OnCollisionEnter ( pColliderData->m_collider );

pColliderData->m_currentCollisions.push_back ( pOtherCollider );
}
else if ( !collided && previouslyCollided )
{
// check if we have previously collided.
if ( pColliderData->IsCurrentlyCollidingWith(pOtherCollider, itorator ) )
{
// we had previously collided but aren't now so raise the exit event.
pColliderData->m_transform.GetGameObject ( ).OnCollisionEnter ( pOtherCollider->m_collider );
pOtherCollider->m_transform.GetGameObject ( ).OnCollisionEnter ( pColliderData->m_collider );

pColliderData->m_currentCollisions.erase ( itorator );
}
}
else
pColliderData->m_currentCollisions.push_back ( pOtherCollider );
}
else if ( !collided && previouslyCollided )
{
// check if we have previously collided.
if ( pColliderData->IsCurrentlyCollidingWith ( pOtherCollider, itorator ) )
{
// do nothing the state is the same.
// we had previously collided but aren't now so raise the exit event.
pColliderData->m_transform.GetGameObject ( ).OnCollisionExit ( pOtherCollider->m_collider );
pOtherCollider->m_transform.GetGameObject ( ).OnCollisionExit ( pColliderData->m_collider );

pColliderData->m_currentCollisions.erase ( itorator );
}
}
else
{
// do nothing the state is the same.
}
}
}
}

Expand Down Expand Up @@ -336,22 +348,92 @@ bool CollisionManager::AreIntersecting ( const Collider * pCollider, const Colli

bool CollisionManager::AreIntersecting ( const ColliderSphere * pCollider, const ColliderSphere * pOtherCollider )
{
return false;
float distanceSquared = glm::distance2 ( pCollider->GetGameObject().GetTransform().GetPosition(),
pOtherCollider->GetGameObject ( ).GetTransform ( ).GetPosition ( ) );

auto & pColliderScale = pCollider->GetGameObject ( ).GetTransform ( ).GetScale ( );
float pColliderScaleMultiplyer = fmax ( fmax ( pColliderScale.x, pColliderScale.y ), pColliderScale.z );

auto & pColliderOtherScale = pCollider->GetGameObject ( ).GetTransform ( ).GetScale ( );
float pColliderOtherScaleMultiplyer = fmax ( fmax ( pColliderOtherScale.x, pColliderOtherScale.y ), pColliderOtherScale.z );

float sumOfRadiuses = ( pCollider->GetRadious ( ) * pColliderScaleMultiplyer )
+ ( pOtherCollider->GetRadious ( ) * pColliderOtherScaleMultiplyer );

float sumRadiusesSquared = ( sumOfRadiuses ) * ( sumOfRadiuses );

return distanceSquared <= sumRadiusesSquared;
}

bool CollisionManager::AreIntersecting ( const ColliderBox * pCollider, const ColliderBox * pOtherCollider )
{
return false;
glm::vec3 axes [ 3 ] = { glm::vec3 ( 1, 0, 0 ), glm::vec3 ( 0, 1, 0 ), glm::vec3 ( 0, 0, 1 ) };
for ( int i = 0; i < 3; ++i )
{
glm::vec3 axis = glm::normalize ( pCollider->GetGameObject().GetTransform().GetRotation() * axes [ i ] );
float projectionA = glm::dot ( axis, pCollider->GetExtents() );
float projectionB = glm::dot ( axis, pOtherCollider->GetExtents() );
float distance = glm::abs ( glm::dot ( axis, pOtherCollider->GetGameObject ( ).GetTransform ( ).GetPosition ( ) - pCollider->GetGameObject ( ).GetTransform ( ).GetPosition ( ) ) );

if ( distance > projectionA + projectionB )
return false;
}

for ( int i = 0; i < 3; ++i )
{
glm::vec3 axis = glm::normalize ( pOtherCollider->GetGameObject ( ).GetTransform ( ).GetRotation ( ) * axes [ i ] );
float projectionA = glm::dot ( axis, pCollider->GetExtents ( ) );
float projectionB = glm::dot ( axis, pOtherCollider->GetExtents ( ) );
float distance = glm::abs ( glm::dot ( axis, pCollider->GetGameObject ( ).GetTransform ( ).GetPosition ( ) - pOtherCollider->GetGameObject ( ).GetTransform ( ).GetPosition ( ) ) );

if ( distance > projectionA + projectionB )
return false;
}

return true;
}

bool CollisionManager::AreIntersecting ( const ColliderSphere * pCollider, const ColliderBox * pOtherCollider )
{
return false;
auto & sphereTransform = pCollider->GetGameObject ( ).GetTransform ( );

glm::vec3 closestPoint = ClosestPointOnBox ( sphereTransform.GetPosition(), *pOtherCollider );

auto & sphereScale = pCollider->GetGameObject ( ).GetTransform ( ).GetScale ( );
float sphereScaleMultiplyer = fmax ( fmax ( sphereScale.x, sphereScale.y ), sphereScale.z );
float radius = sphereScaleMultiplyer * pCollider->GetRadious ( );
float radiusSquared = radius * radius;

float distanceSquared = glm::distance2 ( sphereTransform.GetPosition( ), closestPoint );

return distanceSquared <= radiusSquared;
}

bool CollisionManager::AreIntersecting ( const ColliderBox * pCollider, const ColliderSphere * pOtherCollider )
{
return false;
return AreIntersecting ( pOtherCollider, pCollider );
}

// Function to transform a point from world space to local space of a rotated box
glm::vec3 CollisionManager::TransformToLocalSpace ( const glm::vec3 & point, const ColliderBox & box )
{
return glm::inverse ( box.GetGameObject ( ).GetTransform ( ).GetRotation ( ) ) * ( point - box.GetGameObject ( ).GetTransform ( ).GetPosition ( ) );
}

// Function to find the closest point on a box to a given point
glm::vec3 CollisionManager::ClosestPointOnBox ( const glm::vec3 & point, const ColliderBox & box )
{
glm::vec3 localPoint = TransformToLocalSpace ( point, box );

glm::vec3 closestPoint;

auto & scale = box.GetGameObject ( ).GetTransform ( ).GetScale ( );

closestPoint.x = glm::clamp ( localPoint.x, -box.GetExtents ( ).x * scale.x, box.GetExtents ( ).x * scale.x );
closestPoint.y = glm::clamp ( localPoint.y, -box.GetExtents ( ).y * scale.y, box.GetExtents ( ).y * scale.y );
closestPoint.z = glm::clamp ( localPoint.z, -box.GetExtents ( ).z * scale.z, box.GetExtents ( ).z * scale.z );

return box.GetGameObject ( ).GetTransform ( ).GetRotation ( ) * closestPoint + box.GetGameObject ( ).GetTransform ( ).GetPosition ( );
}

ColliderData * CollisionManager::GetColliderDataFor ( const Collider * pCollider )
Expand Down
5 changes: 5 additions & 0 deletions Lab1/CollisionManager.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include <vector>
#include <glm/glm.hpp>

#define COLLIDER_DEFAULT_CAPACITY 100

Expand Down Expand Up @@ -38,6 +40,9 @@ class CollisionManager
static bool AreIntersecting ( const ColliderSphere * pCollider, const ColliderBox * pOtherCollider );
static bool AreIntersecting ( const ColliderBox * pCollider, const ColliderSphere * pOtherCollider );

static glm::vec3 ClosestPointOnBox ( const glm::vec3 & point, const ColliderBox & box );
static glm::vec3 TransformToLocalSpace ( const glm::vec3 & point, const ColliderBox & box );

static ColliderData * GetColliderDataFor ( const Collider * pCollider );
static void EndAllCollisionsWith ( ColliderData * pColliderData );

Expand Down
11 changes: 10 additions & 1 deletion Lab1/GameEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <iostream>
#include <string>
#include "GameObjectManager.h"
#include "CollisionManager.h"
#include "GameObject.h"

#include "Time.h"
Expand Down Expand Up @@ -36,6 +37,7 @@ void GameEngine::initSystems ( )
Input::StartUp ( );
Renderer::Startup ( );
Audio::Startup ( );
CollisionManager::Startup ( );
GameObjectManager::Startup ( );

Input::RegisterKey ( SDLK_ESCAPE ); // escape
Expand Down Expand Up @@ -174,6 +176,12 @@ void GameEngine::initSystems ( )
{
obj->GetTransform ( ).SetPosition ( points [ i ] );
obj->GetTransform ( ).SetScale ( 1.0f );
obj->AddComponent ( BOX_COLIDER );
}
else
{
// arrow
obj->AddComponent ( BOX_COLIDER );
}

// create a mesh object
Expand Down Expand Up @@ -255,7 +263,7 @@ void GameEngine::gameLoop ( )
Time::Service ( _gameDisplay.getTime ( ) );

processInput ( );

CollisionManager::Service ( );
GameObjectManager::Service ( );
Audio::Service ( );

Expand All @@ -273,6 +281,7 @@ void GameEngine::shutdown ( )
delete _shaderProgram;
delete _texture;
GameObjectManager::Shutdown ( );
CollisionManager::Shutdown ( );
Audio::Shutdown ( );
Renderer::Shutdown ( );
Input::Shutdown ( );
Expand Down
Loading

0 comments on commit 4499c6f

Please sign in to comment.