Implemented a custom physics engine #316

Merged
direnbharwani merged 95 commits from SHPhysics into main 2023-01-23 15:55:45 +08:00
9 changed files with 304 additions and 123 deletions
Showing only changes of commit d98d6a9e06 - Show all commits

View File

@ -18,19 +18,6 @@
#include "Math/SHMatrix.h"
#include "Physics/Collision/SHCollider.h"
/*
* Local box vertices, faces & half-edges
*
* Vertices (Front/Back Face):
*
* 3/7 ---------- 2/6
* | |
* | |
* | |
* 0/4 ---------- 1/5
*
*/
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
@ -38,20 +25,19 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/
SHBoxCollisionShape::SHBoxCollisionShape(SHCollisionShapeID id) noexcept
: SHCollisionShape (id, SHCollisionShape::Type::BOX)
: SHConvexPolyhedronCollisionShape (id, SHCollisionShape::Type::BOX)
, SHBox ()
, relativeExtents { SHVec3::One }
, scale { SHVec3::One }
, polyhedron { nullptr }
{}
SHBoxCollisionShape::SHBoxCollisionShape(const SHBoxCollisionShape& rhs) noexcept
: SHCollisionShape (rhs.id, SHCollisionShape::Type::BOX)
: SHConvexPolyhedronCollisionShape (rhs.id, SHCollisionShape::Type::BOX)
, SHBox (rhs.Center, rhs.Extents, rhs.Orientation)
, relativeExtents { rhs.relativeExtents }
, scale { rhs.scale }
, polyhedron { rhs.polyhedron }
{
halfEdgeStructure = rhs.halfEdgeStructure;
material = rhs.material;
collider = rhs.collider;
@ -63,12 +49,12 @@ namespace SHADE
}
SHBoxCollisionShape::SHBoxCollisionShape(SHBoxCollisionShape&& rhs) noexcept
: SHCollisionShape (rhs.id, SHCollisionShape::Type::BOX)
: SHConvexPolyhedronCollisionShape (rhs.id, SHCollisionShape::Type::BOX)
, SHBox (rhs.Center, rhs.Extents, rhs.Orientation)
, relativeExtents { rhs.relativeExtents }
, scale { rhs.scale }
, polyhedron { rhs.polyhedron }
{
halfEdgeStructure = rhs.halfEdgeStructure;
material = rhs.material;
collider = rhs.collider;
@ -109,7 +95,7 @@ namespace SHADE
relativeExtents = rhs.relativeExtents;
scale = rhs.scale;
polyhedron = rhs.polyhedron;
halfEdgeStructure = rhs.halfEdgeStructure;
return *this;
}
@ -137,7 +123,7 @@ namespace SHADE
relativeExtents = rhs.relativeExtents;
scale = rhs.scale;
polyhedron = rhs.polyhedron;
halfEdgeStructure = rhs.halfEdgeStructure;
return *this;
}
@ -166,6 +152,28 @@ namespace SHADE
return Orientation;
}
SHVec3 SHBoxCollisionShape::GetVertex(int index) const
{
static constexpr int NUM_VERTICES = 8;
if (index < 0 || index >= NUM_VERTICES)
throw std::invalid_argument("Index out-of-range!");
// DirectX already puts vertex 0 - 4 on the front face for our case.
// Otherwise, it would need to be wrapped around for the correct vertex.
return GetVertices()[index];
}
SHVec3 SHBoxCollisionShape::GetNormal(int faceIndex) const
{
// Get local normal
const SHVec3& LOCAL_NORMAL = halfEdgeStructure->GetFace(faceIndex).normal;
// Rotate normal into world space
return SHVec3::Rotate(LOCAL_NORMAL, Orientation);
}
/*-----------------------------------------------------------------------------------*/
/* Setter Function Definitions */
/*-----------------------------------------------------------------------------------*/
@ -191,12 +199,6 @@ namespace SHADE
Extents = relativeExtents * scale * 0.5f;
}
void SHBoxCollisionShape::SetOrientation(const SHQuaternion& newOrientation) noexcept
{
Orientation = newOrientation;
}
void SHBoxCollisionShape::SetScale(const SHVec3& newScale) noexcept
{
scale = SHVec3::Abs(newScale);
@ -219,6 +221,7 @@ namespace SHADE
const SHQuaternion FINAL_ROT = PARENT_TRANSFORM.orientation * transform.orientation;
const SHMatrix TRS = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(PARENT_TRANSFORM.position);
Orientation = FINAL_ROT;
Center = SHVec3::Transform(transform.position, TRS);
}

View File

@ -12,8 +12,7 @@
// Project Headers
#include "Math/Geometry/SHBox.h"
#include "SHCollisionShape.h"
#include "SHConvexPolyhedron.h"
#include "SHConvexPolyhedronCollisionShape.h"
namespace SHADE
{
@ -37,9 +36,9 @@ namespace SHADE
/**
* @brief
* Encapsulate a Box Collision Shape used for Physics Simulations.
* Encapsulate a Box Shape used for Physics Simulations.
*/
class SH_API SHBoxCollisionShape final : public SHCollisionShape
class SH_API SHBoxCollisionShape final : public SHConvexPolyhedronCollisionShape
, private SHBox
{
private:
@ -49,7 +48,6 @@ namespace SHADE
friend class SHCollider;
friend class SHCollision;
friend class SHCompositeCollider;
friend class SHCollisionShapeLibrary;
public:
@ -79,6 +77,9 @@ namespace SHADE
[[nodiscard]] SHVec3 GetRelativeExtents () const noexcept;
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
[[nodiscard]] SHVec3 GetVertex (int index) const override;
[[nodiscard]] SHVec3 GetNormal (int faceIndex) const override;
/*---------------------------------------------------------------------------------*/
/* Setter Functions */
/*---------------------------------------------------------------------------------*/
@ -86,7 +87,6 @@ namespace SHADE
void SetCenter (const SHVec3& newCenter) noexcept;
void SetWorldExtents (const SHVec3& newWorldExtents) noexcept;
void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept;
void SetOrientation (const SHQuaternion& newOrientation) noexcept;
void SetScale (const SHVec3& newScale) noexcept;
/*---------------------------------------------------------------------------------*/
@ -153,7 +153,6 @@ namespace SHADE
SHVec3 relativeExtents;
SHVec3 scale; // Intended to be passed in by the base collider.
SHConvexPolyhedron* polyhedron; // Defines the polyhedron by it's half edges.
};

View File

@ -70,8 +70,8 @@ namespace SHADE
box->Orientation = createInfo.Orientation;
box->scale = createInfo.Scale;
// Set convex polyhedron for the box
box->polyhedron = &boxPolyhedron;
// Set halfEdge data structure for the box
box->halfEdgeStructure = &boxHalfEdgeDS;
return box;
}
@ -159,16 +159,16 @@ namespace SHADE
for (int i = 0; i < NUM_FACES; ++i)
{
SHConvexPolyhedron::Face newFace;
SHHalfEdgeDS::Face newFace;
newFace.normal = FACE_NORMALS[i];
for (int j = 0; j < NUM_VERTICES_PER_FACE; ++j)
newFace.vertexIndices.emplace_back(FACE_VERTICES[i][j]);
boxPolyhedron.AddFace(newFace);
boxHalfEdgeDS.AddFace(newFace);
}
boxPolyhedron.BuildPolyhedron();
boxHalfEdgeDS.BuildPolyhedron();
}
} // namespace SHADE

View File

@ -92,7 +92,7 @@ namespace SHADE
/* Data Members */
/*---------------------------------------------------------------------------------*/
SHConvexPolyhedron boxPolyhedron;
SHHalfEdgeDS boxHalfEdgeDS;
Spheres spheres;
Boxes boxes;

View File

@ -0,0 +1,100 @@
/****************************************************************************************
* \file SHConvexPolyhedronCollisionShape.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a convex polyhedron collision shape.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#include <SHpch.h>
// Primary Header
#include "SHConvexPolyhedronCollisionShape.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHConvexPolyhedronCollisionShape::SHConvexPolyhedronCollisionShape(SHCollisionShapeID id,Type polyhedronType) noexcept
: SHCollisionShape (id, polyhedronType)
, halfEdgeStructure { nullptr }
{}
SHConvexPolyhedronCollisionShape::SHConvexPolyhedronCollisionShape(const SHConvexPolyhedronCollisionShape& rhs) noexcept
: SHCollisionShape (rhs.id, rhs.GetType())
, halfEdgeStructure { nullptr }
{
material = rhs.material;
collider = rhs.collider;
transform = rhs.transform;
rotationOffset = rhs.rotationOffset;
flags = rhs.flags;
// Since all collision tags are taken from the matrix, we do not need to do a deep copy here.
collisionTag = rhs.collisionTag;
}
SHConvexPolyhedronCollisionShape::SHConvexPolyhedronCollisionShape(SHConvexPolyhedronCollisionShape&& rhs) noexcept
: SHCollisionShape (rhs.id, rhs.GetType())
, halfEdgeStructure { nullptr }
{
material = rhs.material;
collider = rhs.collider;
transform = rhs.transform;
rotationOffset = rhs.rotationOffset;
flags = rhs.flags;
// Since all collision tags are taken from the matrix, we do not need to do a deep copy here.
collisionTag = rhs.collisionTag;
}
/*-----------------------------------------------------------------------------------*/
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHConvexPolyhedronCollisionShape& SHConvexPolyhedronCollisionShape::operator=(const SHConvexPolyhedronCollisionShape& rhs) noexcept
{
if (this == &rhs)
return *this;
material = rhs.material;
collider = rhs.collider;
transform = rhs.transform;
rotationOffset = rhs.rotationOffset;
flags = rhs.flags;
// Since all collision tags are taken from the matrix, we do not need to do a deep copy here.
collisionTag = rhs.collisionTag;
// Local Properties
halfEdgeStructure = rhs.halfEdgeStructure;
return *this;
}
SHConvexPolyhedronCollisionShape& SHConvexPolyhedronCollisionShape::operator=(SHConvexPolyhedronCollisionShape&& rhs) noexcept
{
material = rhs.material;
collider = rhs.collider;
transform = rhs.transform;
rotationOffset = rhs.rotationOffset;
flags = rhs.flags;
// Since all collision tags are taken from the matrix, we do not need to do a deep copy here.
collisionTag = rhs.collisionTag;
// Local Properties
halfEdgeStructure = rhs.halfEdgeStructure;
return *this;
}
/*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
const SHHalfEdgeDS* SHConvexPolyhedronCollisionShape::GetHalfEdgeStructure() const noexcept
{
return halfEdgeStructure;
}
} // namespace SHADE

View File

@ -0,0 +1,78 @@
/****************************************************************************************
* \file SHConvexPolyhedronCollisionShape.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a convex polyhedron collision shape.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
* of DigiPen Institute of Technology is prohibited.
****************************************************************************************/
#pragma once
// Project Headers
#include "SHCollisionShape.h"
#include "SHHalfEdgeDS.h"
namespace SHADE
{
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/**
* @brief
* Encapsulates a convex polyhedron shape used for Physics Simulations..
*/
class SH_API SHConvexPolyhedronCollisionShape : public SHCollisionShape
{
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHCollider;
friend class SHCollision;
friend class SHCollisionShapeLibrary;
public:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
static constexpr float RADIUS = 0.1f;
/*---------------------------------------------------------------------------------*/
/* Constructors & Destructor */
/*---------------------------------------------------------------------------------*/
SHConvexPolyhedronCollisionShape (SHCollisionShapeID id, Type polyhedronType) noexcept;
SHConvexPolyhedronCollisionShape (const SHConvexPolyhedronCollisionShape& rhs) noexcept;
SHConvexPolyhedronCollisionShape (SHConvexPolyhedronCollisionShape&& rhs) noexcept;
~SHConvexPolyhedronCollisionShape () override = default;
/*---------------------------------------------------------------------------------*/
/* Operator Overloads */
/*---------------------------------------------------------------------------------*/
SHConvexPolyhedronCollisionShape& operator=(const SHConvexPolyhedronCollisionShape& rhs) noexcept;
SHConvexPolyhedronCollisionShape& operator=(SHConvexPolyhedronCollisionShape&& rhs) noexcept;
/*---------------------------------------------------------------------------------*/
/* Getter Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] const SHHalfEdgeDS* GetHalfEdgeStructure () const noexcept;
[[nodiscard]] virtual SHVec3 GetVertex (int index) const = 0;
[[nodiscard]] virtual SHVec3 GetNormal (int faceIndex) const = 0;
protected:
/*---------------------------------------------------------------------------------*/
/* Data Members */
/*---------------------------------------------------------------------------------*/
SHHalfEdgeDS* halfEdgeStructure; // Defines the polyhedron by it's half edges.
};
} // namespace SHADE

View File

@ -1,7 +1,7 @@
/****************************************************************************************
* \file SHConvexPolyhedron.cpps
* \file SHHalfEdgeDS.cpp
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Implementation for a convex polyhedron structure.
* \brief Implementation for a half-edge data structure to represent polyhedra.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
@ -11,7 +11,7 @@
#include <SHpch.h>
// Primary Header
#include "SHConvexPolyhedron.h"
#include "SHHalfEdgeDS.h"
// Helper Macros
@ -23,7 +23,7 @@ namespace SHADE
/* Constructors & Destructor Definitions */
/*-----------------------------------------------------------------------------------*/
SHConvexPolyhedron::HalfEdge::HalfEdge() noexcept
SHHalfEdgeDS::HalfEdge::HalfEdge() noexcept
: tailVertexIndex { -1 }
, headVertexIndex { -1 }
, edgeIndex { -1 }
@ -31,7 +31,7 @@ namespace SHADE
, faceIndex { -1 }
{}
SHConvexPolyhedron::HalfEdge::HalfEdge(const HalfEdge& rhs) noexcept
SHHalfEdgeDS::HalfEdge::HalfEdge(const HalfEdge& rhs) noexcept
: tailVertexIndex { rhs.tailVertexIndex }
, headVertexIndex { rhs.headVertexIndex }
, edgeIndex { rhs.edgeIndex }
@ -39,7 +39,7 @@ namespace SHADE
, faceIndex { rhs.faceIndex }
{}
SHConvexPolyhedron::HalfEdge::HalfEdge(HalfEdge&& rhs) noexcept
SHHalfEdgeDS::HalfEdge::HalfEdge(HalfEdge&& rhs) noexcept
: tailVertexIndex { rhs.tailVertexIndex }
, headVertexIndex { rhs.headVertexIndex }
, edgeIndex { rhs.edgeIndex }
@ -47,13 +47,13 @@ namespace SHADE
, faceIndex { rhs.faceIndex }
{}
SHConvexPolyhedron::Face::Face(const Face& rhs) noexcept
SHHalfEdgeDS::Face::Face(const Face& rhs) noexcept
: normal { rhs.normal }
{
std::ranges::copy(rhs.vertexIndices.begin(), rhs.vertexIndices.end(), std::back_inserter(vertexIndices));
}
SHConvexPolyhedron::Face::Face(Face&& rhs) noexcept
SHHalfEdgeDS::Face::Face(Face&& rhs) noexcept
: normal { rhs.normal }
{
std::ranges::copy(rhs.vertexIndices.begin(), rhs.vertexIndices.end(), std::back_inserter(vertexIndices));
@ -63,7 +63,7 @@ namespace SHADE
/* Operator Overload Definitions */
/*-----------------------------------------------------------------------------------*/
SHConvexPolyhedron::HalfEdge& SHConvexPolyhedron::HalfEdge::operator=(const HalfEdge& rhs) noexcept
SHHalfEdgeDS::HalfEdge& SHHalfEdgeDS::HalfEdge::operator=(const HalfEdge& rhs) noexcept
{
if (this == &rhs)
return *this;
@ -77,7 +77,7 @@ namespace SHADE
return *this;
}
SHConvexPolyhedron::HalfEdge& SHConvexPolyhedron::HalfEdge::operator=(HalfEdge&& rhs) noexcept
SHHalfEdgeDS::HalfEdge& SHHalfEdgeDS::HalfEdge::operator=(HalfEdge&& rhs) noexcept
{
tailVertexIndex = rhs.tailVertexIndex;
headVertexIndex = rhs.headVertexIndex;
@ -88,7 +88,7 @@ namespace SHADE
return *this;
}
SHConvexPolyhedron::Face& SHConvexPolyhedron::Face::operator=(const Face& rhs) noexcept
SHHalfEdgeDS::Face& SHHalfEdgeDS::Face::operator=(const Face& rhs) noexcept
{
if (this == &rhs)
return *this;
@ -101,7 +101,7 @@ namespace SHADE
return *this;
}
SHConvexPolyhedron::Face& SHConvexPolyhedron::Face::operator=(Face&& rhs) noexcept
SHHalfEdgeDS::Face& SHHalfEdgeDS::Face::operator=(Face&& rhs) noexcept
{
normal = rhs.normal;
@ -115,17 +115,17 @@ namespace SHADE
/* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/
int32_t SHConvexPolyhedron::GetFaceCount() const noexcept
int32_t SHHalfEdgeDS::GetFaceCount() const noexcept
{
return static_cast<int32_t>(faces.size());
}
int32_t SHConvexPolyhedron::GetHalfEdgeCount() const noexcept
int32_t SHHalfEdgeDS::GetHalfEdgeCount() const noexcept
{
return static_cast<int32_t>(halfEdges.size());
}
const SHConvexPolyhedron::Face& SHConvexPolyhedron::GetFace(int32_t index) const
const SHHalfEdgeDS::Face& SHHalfEdgeDS::GetFace(int32_t index) const
{
if (index < 0 || index >= static_cast<int32_t>(faces.size()))
throw std::invalid_argument("Index out-of-range!");
@ -133,7 +133,7 @@ namespace SHADE
return faces[index];
}
const SHConvexPolyhedron::HalfEdge& SHConvexPolyhedron::GetHalfEdge(int32_t index) const
const SHHalfEdgeDS::HalfEdge& SHHalfEdgeDS::GetHalfEdge(int32_t index) const
{
if (index < 0 || index >= static_cast<int32_t>(halfEdges.size()))
throw std::invalid_argument("Index out-of-range!");
@ -145,12 +145,12 @@ namespace SHADE
/* Public Member Function Definitions */
/*-----------------------------------------------------------------------------------*/
void SHConvexPolyhedron::AddFace(const Face& face)
void SHHalfEdgeDS::AddFace(const Face& face)
{
faces.emplace_back(face);
}
void SHConvexPolyhedron::BuildPolyhedron() noexcept
void SHHalfEdgeDS::BuildPolyhedron() noexcept
{
// We use the pair of vertex IDs on a half-edge to prevent duplicates
std::unordered_map<uint64_t, HalfEdge> edgeMap;

View File

@ -1,7 +1,7 @@
/****************************************************************************************
* \file SHConvexPolyhedron.h
* \file SHHalfEdgeDS.h
* \author Diren D Bharwani, diren.dbharwani, 390002520
* \brief Interface for a convex polyhedron structure.
* \brief Interface for a half-edge data structure to represent polyhedra.
*
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
* disclosure of this file or its contents without the prior written consent
@ -25,7 +25,7 @@ namespace SHADE
* @brief
* Encapsulates data for a convex polyhedron's geometry represented as faces & half edges.
*/
class SH_API SHConvexPolyhedron
class SH_API SHHalfEdgeDS
{
public:
/*---------------------------------------------------------------------------------*/
@ -77,6 +77,8 @@ namespace SHADE
/* Data Members */
/*-------------------------------------------------------------------------------*/
// TODO: Store face offset
SHVec3 normal;
std::vector<int32_t> vertexIndices; // Must be in CCW order

View File

@ -35,7 +35,7 @@ namespace SHADE
/**
* @brief
* Encapsulate a Sphere Collision Shape used for Physics Simulations.
* Encapsulate a Sphere Shape used for Physics Simulations.
*/
class SH_API SHSphereCollisionShape final : public SHCollisionShape
, private SHSphere
@ -47,7 +47,6 @@ namespace SHADE
friend class SHCollider;
friend class SHCollision;
friend class SHCompositeCollider;
friend class SHCollisionShapeLibrary;
public: