Implemented a custom physics engine #316
|
@ -9,10 +9,10 @@
|
||||||
Scale: {x: 1, y: 1, z: 1}
|
Scale: {x: 1, y: 1, z: 1}
|
||||||
IsActive: true
|
IsActive: true
|
||||||
RigidBody Component:
|
RigidBody Component:
|
||||||
Type: Static
|
Type: Dynamic
|
||||||
Auto Mass: false
|
Auto Mass: false
|
||||||
Mass: 1
|
Mass: 1
|
||||||
Drag: 0
|
Drag: 1
|
||||||
Angular Drag: 0
|
Angular Drag: 0
|
||||||
Use Gravity: true
|
Use Gravity: true
|
||||||
Gravity Scale: 1
|
Gravity Scale: 1
|
||||||
|
@ -26,3 +26,20 @@
|
||||||
Freeze Rotation Z: false
|
Freeze Rotation Z: false
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
Scripts: ~
|
||||||
|
- EID: 1
|
||||||
|
Name: Default
|
||||||
|
IsActive: true
|
||||||
|
NumberOfChildren: 0
|
||||||
|
Components:
|
||||||
|
Camera Component:
|
||||||
|
Position: {x: 0, y: 2, z: 5}
|
||||||
|
Pitch: 0
|
||||||
|
Yaw: 0
|
||||||
|
Roll: 0
|
||||||
|
Width: 1920
|
||||||
|
Height: 1080
|
||||||
|
Near: 0.00999999978
|
||||||
|
Far: 10000
|
||||||
|
Perspective: true
|
||||||
|
IsActive: true
|
||||||
|
Scripts: ~
|
|
@ -162,7 +162,7 @@ namespace SHADE
|
||||||
|
|
||||||
//SHSceneNode* parentNode = entityVec[eIndex]->GetSceneNode()->GetParent();
|
//SHSceneNode* parentNode = entityVec[eIndex]->GetSceneNode()->GetParent();
|
||||||
|
|
||||||
//SHSceneGraph::RemoveChild(parentNode,entityVec[eIndex].get());
|
//SHSceneGraph::removeChild(parentNode,entityVec[eIndex].get());
|
||||||
|
|
||||||
//TODO remove from parent and recursively delete child.
|
//TODO remove from parent and recursively delete child.
|
||||||
|
|
||||||
|
|
|
@ -252,12 +252,13 @@ namespace SHADE
|
||||||
if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
|
if(rbType == SHRigidBodyComponent::Type::DYNAMIC) //Dynamic only fields
|
||||||
{
|
{
|
||||||
SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetIsGravityEnabled(value);}, "Gravity");
|
SHEditorWidgets::CheckBox("Use Gravity", [component]{return component->IsGravityEnabled();}, [component](bool const& value){component->SetIsGravityEnabled(value);}, "Gravity");
|
||||||
//SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
|
SHEditorWidgets::DragFloat("Gravity Scale", [component] { return component->GetGravityScale(); }, [component](float const& value) { component->SetGravityScale(value); }, "Gravity Scale", 0.1f, 0.0f);
|
||||||
|
SHEditorWidgets::DragFloat("Mass", [component] {return component->GetMass(); }, [component](float const& value) {component->SetMass(value); }, "Mass");
|
||||||
}
|
}
|
||||||
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag");
|
SHEditorWidgets::DragFloat("Drag", [component] {return component->GetDrag(); }, [component](float const& value) {component->SetDrag(value); }, "Drag", 0.1f, 0.0f);
|
||||||
SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag");
|
SHEditorWidgets::DragFloat("Angular Drag", [component] {return component->GetAngularDrag(); }, [component](float const& value) {component->SetAngularDrag(value); }, "Angular Drag", 0.1f, 0.0f);
|
||||||
|
|
||||||
SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate");
|
SHEditorWidgets::CheckBox("Interpolate", [component] {return component->IsInterpolating(); }, [component](bool const& value) {component->SetInterpolate(value); }, "Interpolate");
|
||||||
|
|
||||||
|
@ -284,8 +285,7 @@ namespace SHADE
|
||||||
//Debug Info (Read-Only)
|
//Debug Info (Read-Only)
|
||||||
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
|
if(ImGui::CollapsingHeader("Debug Information", ImGuiTreeNodeFlags_DefaultOpen))//Dynamic or Kinematic only fields
|
||||||
{
|
{
|
||||||
SHEditorWidgets::DragFloat("Mass", [component] { return component->GetMass(); }, [](float value){}, "Mass", 0.1f, 0.0f, std::numeric_limits<float>::infinity(), "%.3f", ImGuiSliderFlags_ReadOnly);
|
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
||||||
//SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [component] {return component->GetPosition(); }, [](SHVec3 const& value) {}, false, "Position", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
|
||||||
//SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
//SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" }, [component] {return component->GetRotation(); }, [](SHVec3 const& value) {}, false, "Rotation", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
||||||
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
if (rbType == SHRigidBodyComponent::Type::DYNAMIC || rbType == SHRigidBodyComponent::Type::KINEMATIC) //Dynamic or Kinematic only fields
|
||||||
{
|
{
|
||||||
|
|
|
@ -246,8 +246,6 @@ namespace SHADE
|
||||||
tf.world.position = SHVec3::Transform(tf.local.position, localToWorld);
|
tf.world.position = SHVec3::Transform(tf.local.position, localToWorld);
|
||||||
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
|
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (convertRotation)
|
if (convertRotation)
|
||||||
{
|
{
|
||||||
tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
|
tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHMotionState.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for a Motion State.
|
||||||
|
*
|
||||||
|
* \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 "SHMotionState.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
#include "Math/SHMathHelpers.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHMotionState::SHMotionState() noexcept
|
||||||
|
: hasMoved { false }
|
||||||
|
{}
|
||||||
|
|
||||||
|
SHMotionState::SHMotionState(const SHMotionState& rhs) noexcept
|
||||||
|
: hasMoved { rhs.hasMoved }
|
||||||
|
, position { rhs.position }
|
||||||
|
, prevPosition { rhs.prevPosition }
|
||||||
|
{}
|
||||||
|
|
||||||
|
SHMotionState::SHMotionState(SHMotionState&& rhs) noexcept
|
||||||
|
: hasMoved { rhs.hasMoved }
|
||||||
|
, position { rhs.position }
|
||||||
|
, prevPosition { rhs.prevPosition }
|
||||||
|
{}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overload Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHMotionState& SHMotionState::operator=(const SHMotionState& rhs) noexcept
|
||||||
|
{
|
||||||
|
if (this == &rhs)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
hasMoved = rhs.hasMoved;
|
||||||
|
position = rhs.position;
|
||||||
|
prevPosition = rhs.prevPosition;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHMotionState& SHMotionState::operator=(SHMotionState&& rhs) noexcept
|
||||||
|
{
|
||||||
|
hasMoved = rhs.hasMoved;
|
||||||
|
position = rhs.position;
|
||||||
|
prevPosition = rhs.prevPosition;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHMotionState::operator bool() const noexcept
|
||||||
|
{
|
||||||
|
return hasMoved;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Member Function Definition */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHMotionState::ForcePosition(const SHVec3& newPosition) noexcept
|
||||||
|
{
|
||||||
|
hasMoved = false;
|
||||||
|
|
||||||
|
prevPosition = newPosition;
|
||||||
|
position = newPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHMotionState::IntegratePosition(const SHVec3& velocity, float dt) noexcept
|
||||||
|
{
|
||||||
|
// Velocities are 0 when objects are static or sleeping. We do not want to integrate them here.
|
||||||
|
// This call should never reach here.
|
||||||
|
|
||||||
|
hasMoved = true;
|
||||||
|
|
||||||
|
prevPosition = position;
|
||||||
|
position += velocity * dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHVec3 SHMotionState::InterpolatePositions(float factor) const noexcept
|
||||||
|
{
|
||||||
|
return SHVec3::ClampedLerp(prevPosition, position, factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,93 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHMotionState.h
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Interface for a Motion State.
|
||||||
|
*
|
||||||
|
* \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 "Math/Vector/SHVec3.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Encapsulates the motion state of a rigid body in physics.
|
||||||
|
*/
|
||||||
|
struct SH_API SHMotionState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool hasMoved;
|
||||||
|
|
||||||
|
SHVec3 position;
|
||||||
|
SHVec3 prevPosition;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHMotionState () noexcept;
|
||||||
|
SHMotionState (const SHMotionState& rhs) noexcept;
|
||||||
|
SHMotionState (SHMotionState&& rhs) noexcept;
|
||||||
|
|
||||||
|
~SHMotionState() = default;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overloads */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHMotionState& operator= (const SHMotionState& rhs) noexcept;
|
||||||
|
SHMotionState& operator= (SHMotionState&& rhs) noexcept;
|
||||||
|
|
||||||
|
operator bool () const noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Forcefully sets the position. Meant to be used when transform overrides the rigid body
|
||||||
|
* positions.
|
||||||
|
* @param newPosition
|
||||||
|
* The new position to set.
|
||||||
|
*/
|
||||||
|
void ForcePosition (const SHVec3& newPosition) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Integrates the positions using velocity with respect to time.
|
||||||
|
* @param velocity
|
||||||
|
* The velocity to integrate.
|
||||||
|
* @param dt
|
||||||
|
* The delta time to integrate with respect to.
|
||||||
|
*/
|
||||||
|
void IntegratePosition (const SHVec3& velocity, float dt) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Interpolates the position between the previous and the last using a given factor.
|
||||||
|
* @param factor
|
||||||
|
* The factor to interpolate by. Should be between 0 & 1.
|
||||||
|
* @returns
|
||||||
|
* The interpolated position meant for rendering.
|
||||||
|
*/
|
||||||
|
SHVec3 InterpolatePositions (float factor) const noexcept;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace SHADE
|
|
@ -0,0 +1,122 @@
|
||||||
|
/****************************************************************************************
|
||||||
|
* \file SHPhysicsWorld.cpp
|
||||||
|
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||||
|
* \brief Implementation for a Physics World.
|
||||||
|
*
|
||||||
|
* \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 "SHPhysicsWorld.h"
|
||||||
|
|
||||||
|
// Project Headers
|
||||||
|
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsWorld::SHPhysicsWorld(const WorldSettings& worldSettings) noexcept
|
||||||
|
: settings { worldSettings }
|
||||||
|
{
|
||||||
|
rigidBodies.clear();
|
||||||
|
SHLOG_INFO_D("Creating Physics World")
|
||||||
|
}
|
||||||
|
|
||||||
|
SHPhysicsWorld::~SHPhysicsWorld() noexcept
|
||||||
|
{
|
||||||
|
rigidBodies.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Member Functions Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsWorld::AddRigidBody(SHRigidBody* rigidBody) noexcept
|
||||||
|
{
|
||||||
|
const bool INSERTED = rigidBodies.emplace(rigidBody->entityID, rigidBody).second;
|
||||||
|
if (!INSERTED)
|
||||||
|
{
|
||||||
|
SHLOG_WARNING_D("Attempting to add duplicate rigid body {} to the Physics World!", rigidBody->entityID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsWorld::RemoveRigidBody(SHRigidBody* rigidBody) noexcept
|
||||||
|
{
|
||||||
|
rigidBodies.erase(rigidBody->entityID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsWorld::Step(float dt)
|
||||||
|
{
|
||||||
|
for (auto* rigidBody : rigidBodies | std::views::values)
|
||||||
|
integrateForces(*rigidBody, dt);
|
||||||
|
|
||||||
|
for (auto* rigidBody : rigidBodies | std::views::values)
|
||||||
|
integrateVelocities(*rigidBody, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Private Member Functions Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void SHPhysicsWorld::integrateForces(SHRigidBody& rigidBody, float dt) const noexcept
|
||||||
|
{
|
||||||
|
if (rigidBody.bodyType != SHRigidBody::Type::DYNAMIC)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Integrate forces and gravity into linear velocity
|
||||||
|
const SHVec3 LINEAR_ACCELERATION = rigidBody.accumulatedForce * rigidBody.invMass;
|
||||||
|
const SHVec3 GRAVITATIONAL_ACCELERATION = rigidBody.IsGravityEnabled() ? settings.gravity * rigidBody.gravityScale : SHVec3::Zero;
|
||||||
|
|
||||||
|
rigidBody.linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * dt;
|
||||||
|
|
||||||
|
// Apply drag (exponentially applied)
|
||||||
|
rigidBody.linearVelocity *= 1.0f / (1.0f + dt * rigidBody.linearDrag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHPhysicsWorld::integrateVelocities(SHRigidBody& rigidBody, float dt) const noexcept
|
||||||
|
{
|
||||||
|
static const auto ENFORCE_CONSTRAINED_VELOCITIES = [](SHRigidBody& rigidBody)
|
||||||
|
{
|
||||||
|
// Enforce linear constraints
|
||||||
|
rigidBody.linearVelocity = SHVec3
|
||||||
|
{
|
||||||
|
rigidBody.GetFreezePositionX() ? 0.0f : rigidBody.linearVelocity.x
|
||||||
|
, rigidBody.GetFreezePositionY() ? 0.0f : rigidBody.linearVelocity.y
|
||||||
|
, rigidBody.GetFreezePositionZ() ? 0.0f : rigidBody.linearVelocity.z
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Enforce angular constraints
|
||||||
|
};
|
||||||
|
|
||||||
|
// Always reset movement flag
|
||||||
|
rigidBody.motionState.hasMoved = false;
|
||||||
|
|
||||||
|
// Set all velocities of static bodies to 0
|
||||||
|
if (rigidBody.bodyType == SHRigidBody::Type::STATIC)
|
||||||
|
{
|
||||||
|
rigidBody.linearVelocity = SHVec3::Zero;
|
||||||
|
}
|
||||||
|
else // Dynamic & Kinematic bodies
|
||||||
|
{
|
||||||
|
// Both dynamic and kinematic can sleep when their velocities are under the thresholds.
|
||||||
|
if (!rigidBody.IsSleeping())
|
||||||
|
{
|
||||||
|
ENFORCE_CONSTRAINED_VELOCITIES(rigidBody);
|
||||||
|
|
||||||
|
rigidBody.motionState.IntegratePosition(rigidBody.linearVelocity, dt);
|
||||||
|
// TODO: Integrate orientations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all forces
|
||||||
|
// We clear forces for static bodies as well for redundancy
|
||||||
|
rigidBody.ClearForces();
|
||||||
|
}
|
||||||
|
} // namespace SHADE
|
|
@ -10,7 +10,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
|
#include "SHRigidBody.h"
|
||||||
#include "Math/SHMath.h"
|
#include "Math/SHMath.h"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
|
|
||||||
|
@ -20,7 +23,7 @@ namespace SHADE
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
struct SH_API SHPhysicsWorldState
|
class SH_API SHPhysicsWorld
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -41,22 +44,55 @@ namespace SHADE
|
||||||
bool sleepingEnabled = true;
|
bool sleepingEnabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
/* Data Members */
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
WorldSettings settings;
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsWorldState() noexcept;
|
SHPhysicsWorld (const WorldSettings& worldSettings = WorldSettings{}) noexcept;
|
||||||
|
~SHPhysicsWorld () noexcept;
|
||||||
|
|
||||||
|
SHPhysicsWorld (const SHPhysicsWorld&) = delete;
|
||||||
|
SHPhysicsWorld (SHPhysicsWorld&&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Operator Overloads */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsWorld& operator=(const SHPhysicsWorld&) = delete;
|
||||||
|
SHPhysicsWorld& operator=(SHPhysicsWorld&&) = delete;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Function Members */
|
/* Function Members */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void AddRigidBody (SHRigidBody* rigidBody) noexcept;
|
||||||
|
void RemoveRigidBody (SHRigidBody* rigidBody) noexcept;
|
||||||
|
|
||||||
|
void Step (float dt);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
using RigidBodies = std::unordered_map<EntityID, SHRigidBody*>;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
WorldSettings settings;
|
||||||
|
|
||||||
|
RigidBodies rigidBodies;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Function Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void integrateForces (SHRigidBody& rigidBody, float dt) const noexcept;
|
||||||
|
void integrateVelocities (SHRigidBody& rigidBody, float dt) const noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace SHADE
|
||||||
: entityID { eid }
|
: entityID { eid }
|
||||||
, bodyType { type }
|
, bodyType { type }
|
||||||
, invMass { type == Type::DYNAMIC ? 1.0f : 0.0f }
|
, invMass { type == Type::DYNAMIC ? 1.0f : 0.0f }
|
||||||
, linearDrag { type != Type::STATIC ? 0.01f : 0.0f }
|
, linearDrag { 0.01f }
|
||||||
, gravityScale { 1.0f }
|
, gravityScale { 1.0f }
|
||||||
, flags { 0U }
|
, flags { 0U }
|
||||||
{
|
{
|
||||||
|
@ -45,6 +45,7 @@ namespace SHADE
|
||||||
, linearDrag { rhs.linearDrag }
|
, linearDrag { rhs.linearDrag }
|
||||||
, gravityScale { rhs.gravityScale }
|
, gravityScale { rhs.gravityScale }
|
||||||
, flags { rhs.flags }
|
, flags { rhs.flags }
|
||||||
|
, motionState { rhs.motionState }
|
||||||
{
|
{
|
||||||
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
||||||
}
|
}
|
||||||
|
@ -56,6 +57,7 @@ namespace SHADE
|
||||||
, linearDrag { rhs.linearDrag }
|
, linearDrag { rhs.linearDrag }
|
||||||
, gravityScale { rhs.gravityScale }
|
, gravityScale { rhs.gravityScale }
|
||||||
, flags { rhs.flags }
|
, flags { rhs.flags }
|
||||||
|
, motionState { std::move(rhs.motionState) }
|
||||||
{
|
{
|
||||||
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
||||||
}
|
}
|
||||||
|
@ -76,8 +78,12 @@ namespace SHADE
|
||||||
linearDrag = rhs.linearDrag;
|
linearDrag = rhs.linearDrag;
|
||||||
gravityScale = rhs.gravityScale;
|
gravityScale = rhs.gravityScale;
|
||||||
flags = rhs.flags;
|
flags = rhs.flags;
|
||||||
|
motionState = rhs.motionState;
|
||||||
|
|
||||||
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
||||||
|
accumulatedForce = SHVec3::Zero;
|
||||||
|
linearVelocity = SHVec3::Zero;
|
||||||
|
angularVelocity = SHVec3::Zero;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -90,8 +96,12 @@ namespace SHADE
|
||||||
linearDrag = rhs.linearDrag;
|
linearDrag = rhs.linearDrag;
|
||||||
gravityScale = rhs.gravityScale;
|
gravityScale = rhs.gravityScale;
|
||||||
flags = rhs.flags;
|
flags = rhs.flags;
|
||||||
|
motionState = std::move(rhs.motionState);
|
||||||
|
|
||||||
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
// All other properties are defaulted to 0 to not carry over any potential errors / invalid values.
|
||||||
|
accumulatedForce = SHVec3::Zero;
|
||||||
|
linearVelocity = SHVec3::Zero;
|
||||||
|
angularVelocity = SHVec3::Zero;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -203,6 +213,12 @@ namespace SHADE
|
||||||
return flags & (1U << FLAG_POS);
|
return flags & (1U << FLAG_POS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHMotionState& SHRigidBody::GetMotionState() noexcept
|
||||||
|
{
|
||||||
|
return motionState;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions Definitions */
|
/* Setter Functions Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -424,7 +440,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Member Function Definitions */
|
/* Public Member Function Definition */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void SHRigidBody::AddForce(const SHVec3& force, const SHVec3& pos) noexcept
|
void SHRigidBody::AddForce(const SHVec3& force, const SHVec3& pos) noexcept
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/SHECSMacros.h"
|
#include "ECS_Base/SHECSMacros.h"
|
||||||
#include "Math/Vector/SHVec3.h"
|
#include "Math/Vector/SHVec3.h"
|
||||||
#include "SH_API.h"
|
#include "SHMotionState.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,13 @@ namespace SHADE
|
||||||
*/
|
*/
|
||||||
class SH_API SHRigidBody
|
class SH_API SHRigidBody
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Friends */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
friend class SHPhysicsWorld;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Type Definitions */
|
/* Type Definitions */
|
||||||
|
@ -83,13 +90,16 @@ namespace SHADE
|
||||||
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
|
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
|
||||||
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
|
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] SHMotionState& GetMotionState () noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief
|
||||||
* Changing the type from non-Dynamic to Dynamic will set the default mass.
|
* Changing the type from non-Dynamic to Dynamic will set the default
|
||||||
|
* mass and drag values.
|
||||||
*/
|
*/
|
||||||
void SetType (Type newType) noexcept;
|
void SetType (Type newType) noexcept;
|
||||||
|
|
||||||
|
@ -111,7 +121,6 @@ namespace SHADE
|
||||||
|
|
||||||
|
|
||||||
void SetGravityScale (float newGravityScale) noexcept;
|
void SetGravityScale (float newGravityScale) noexcept;
|
||||||
|
|
||||||
void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept;
|
void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept;
|
||||||
|
|
||||||
// Flags
|
// Flags
|
||||||
|
@ -180,6 +189,8 @@ namespace SHADE
|
||||||
|
|
||||||
// aZ aY aX pZ pY pX 0 0 0 0 0 autoMass enableGravity enableSleeping sleeping active
|
// aZ aY aX pZ pY pX 0 0 0 0 0 autoMass enableGravity enableSleeping sleeping active
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
|
|
||||||
|
SHMotionState motionState;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
||||||
|
|
|
@ -44,7 +44,6 @@ namespace SHADE
|
||||||
delete rigidBody;
|
delete rigidBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Operator Overload Definitions */
|
/* Operator Overload Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -71,4 +70,14 @@ namespace SHADE
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Public Member Function Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool SHPhysicsObject::IsEmpty() const noexcept
|
||||||
|
{
|
||||||
|
return rigidBody == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -48,5 +48,11 @@ namespace SHADE
|
||||||
|
|
||||||
SHPhysicsObject& operator=(const SHPhysicsObject& rhs) noexcept;
|
SHPhysicsObject& operator=(const SHPhysicsObject& rhs) noexcept;
|
||||||
SHPhysicsObject& operator=(SHPhysicsObject&& rhs) noexcept;
|
SHPhysicsObject& operator=(SHPhysicsObject&& rhs) noexcept;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Member Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
bool IsEmpty() const noexcept;
|
||||||
};
|
};
|
||||||
} // namespace SHADE
|
} // namespace SHADE
|
|
@ -14,6 +14,7 @@
|
||||||
#include "SHPhysicsObjectManager.h"
|
#include "SHPhysicsObjectManager.h"
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Physics/Interface/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
#include "Physics/Interface/SHCollisionShape.h"
|
#include "Physics/Interface/SHCollisionShape.h"
|
||||||
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
|
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
|
||||||
|
@ -21,6 +22,15 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors & Destructor Definitions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
SHPhysicsObjectManager::~SHPhysicsObjectManager() noexcept
|
||||||
|
{
|
||||||
|
RemoveAllObjects();
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Getter Function Definitions */
|
/* Getter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -68,6 +78,17 @@ namespace SHADE
|
||||||
, static_cast<SHRigidBody::Type>(rigidBodyComponent->GetType())
|
, static_cast<SHRigidBody::Type>(rigidBodyComponent->GetType())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
SHMotionState& motionState = physicsObject->rigidBody->GetMotionState();
|
||||||
|
|
||||||
|
if (const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent<SHTransformComponent>(entityID); TRANSFORM_COMPONENT)
|
||||||
|
{
|
||||||
|
motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
motionState.ForcePosition(SHVec3::Zero);
|
||||||
|
}
|
||||||
|
|
||||||
// Link with the component
|
// Link with the component
|
||||||
rigidBodyComponent->SetRigidBody(physicsObject->rigidBody);
|
rigidBodyComponent->SetRigidBody(physicsObject->rigidBody);
|
||||||
|
|
||||||
|
@ -85,7 +106,7 @@ namespace SHADE
|
||||||
physicsObject->rigidBody = nullptr;
|
physicsObject->rigidBody = nullptr;
|
||||||
|
|
||||||
// Destroy empty physics objects
|
// Destroy empty physics objects
|
||||||
if (physicsObject->rigidBody == nullptr)
|
if (physicsObject->IsEmpty())
|
||||||
destroyPhysicsObject(entityID);
|
destroyPhysicsObject(entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +122,15 @@ namespace SHADE
|
||||||
|
|
||||||
void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept
|
void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept
|
||||||
{
|
{
|
||||||
// Unlink with the component
|
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
|
||||||
|
if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end())
|
||||||
|
{
|
||||||
|
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
|
||||||
|
|
||||||
|
// Destroy empty physics objects
|
||||||
|
if (physicsObject->IsEmpty())
|
||||||
|
destroyPhysicsObject(entityID);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Broadcast event
|
// TODO: Broadcast event
|
||||||
}
|
}
|
||||||
|
@ -120,6 +149,11 @@ namespace SHADE
|
||||||
// TODO: Broadcast event
|
// TODO: Broadcast event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHPhysicsObjectManager::RemoveAllObjects() noexcept
|
||||||
|
{
|
||||||
|
physicsObjects.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Private Member Function Definitions */
|
/* Private Member Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsObjectManager () noexcept = default;
|
SHPhysicsObjectManager () noexcept = default;
|
||||||
|
~SHPhysicsObjectManager () noexcept;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
|
@ -107,6 +108,13 @@ namespace SHADE
|
||||||
*/
|
*/
|
||||||
void RemoveCollisionShape (EntityID entityID, uint8_t shapeID) noexcept;
|
void RemoveCollisionShape (EntityID entityID, uint8_t shapeID) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Removes all physics object in the manager. This is only meant to be called when
|
||||||
|
* the world is being destroyed or the scene is being changed.
|
||||||
|
*/
|
||||||
|
void RemoveAllObjects () noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Data Members */
|
/* Data Members */
|
||||||
|
|
|
@ -182,6 +182,15 @@ namespace SHADE
|
||||||
return SHVec3::Zero;
|
return SHVec3::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHVec3 SHRigidBodyComponent::GetPosition() const noexcept
|
||||||
|
{
|
||||||
|
if (rigidBody)
|
||||||
|
return rigidBody->GetMotionState().position;
|
||||||
|
|
||||||
|
return SHVec3::Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions Definitions */
|
/* Setter Functions Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -97,6 +97,8 @@ namespace SHADE
|
||||||
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
|
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
|
||||||
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
|
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] SHVec3 GetPosition () const noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Setter Functions */
|
/* Setter Functions */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
/****************************************************************************************
|
|
||||||
* \file SHPhysicsWorld.cpp
|
|
||||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
|
||||||
* \brief Implementation for a Physics World.
|
|
||||||
*
|
|
||||||
* \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 "SHPhysicsWorld.h"
|
|
||||||
|
|
||||||
namespace SHADE
|
|
||||||
{
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Constructors & Destructor Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Public Function Members Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
} // namespace SHADE
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
// Project Headers
|
// Project Headers
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
|
#include "Math/Transform/SHTransformComponent.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,21 +43,37 @@ namespace SHADE
|
||||||
SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
|
SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interpolate transforms for rendering
|
const float FACTOR = static_cast<float>(physicsSystem->interpolationFactor);
|
||||||
|
|
||||||
|
// Interpolate transforms for rendering.
|
||||||
|
// Only rigid bodies can move due to physics, so we run through the rigid body component dense set.
|
||||||
|
const auto& RIGIDBODY_DENSE = SHComponentManager::GetDense<SHRigidBodyComponent>();
|
||||||
|
for (auto& rigidBodyComponent : RIGIDBODY_DENSE)
|
||||||
|
{
|
||||||
|
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(rigidBodyComponent.GetEID());
|
||||||
|
if (!transformComponent)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!rigidBodyComponent.rigidBody)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (const SHMotionState& MOTION_STATE = rigidBodyComponent.rigidBody->GetMotionState(); MOTION_STATE)
|
||||||
|
{
|
||||||
|
SHVec3 renderPosition = rigidBodyComponent.IsInterpolating()
|
||||||
|
? MOTION_STATE.InterpolatePositions(FACTOR)
|
||||||
|
: MOTION_STATE.position;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy.
|
||||||
|
*/
|
||||||
|
|
||||||
|
transformComponent->SetWorldPosition(renderPosition);
|
||||||
|
// TODO: SetOrientation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collision & Trigger messages
|
// Collision & Trigger messages
|
||||||
if (scriptingSystem != nullptr)
|
if (scriptingSystem != nullptr)
|
||||||
scriptingSystem->ExecuteCollisionFunctions();
|
scriptingSystem->ExecuteCollisionFunctions();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPostUpdate::syncTransforms(SHRigidBodyComponent* rbComponent) const noexcept
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,27 +36,27 @@ namespace SHADE
|
||||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||||
|
|
||||||
// Get all physics objects & sync transforms
|
// Get all physics objects & sync transforms
|
||||||
for (auto& physicsObject : physicsSystem->physicsObjectManager.GetPhysicsObjects() | std::views::values)
|
for (auto& [entityID, physicsObject] : physicsSystem->physicsObjectManager.GetPhysicsObjects())
|
||||||
syncTransforms(&physicsObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
/* Private Function Member Definitions */
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
void SHPhysicsSystem::PhysicsPreUpdate::syncTransforms(SHPhysicsObject* physicsObject) const noexcept
|
|
||||||
{
|
{
|
||||||
const EntityID EID = physicsObject->entityID;
|
const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||||
|
|
||||||
// Get relevant components: Transform, Rigidbody & Collider
|
// We assume that all engine components and physics object components have been successfully linked
|
||||||
const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s<SHTransformComponent>(EID);
|
|
||||||
|
|
||||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(EID);
|
|
||||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(EID);
|
|
||||||
|
|
||||||
if (TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged())
|
if (TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged())
|
||||||
{
|
{
|
||||||
// Sync the objects transforms
|
// Sync the objects transforms
|
||||||
|
const SHVec3 WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition();
|
||||||
|
|
||||||
|
if (physicsObject.rigidBody)
|
||||||
|
{
|
||||||
|
SHMotionState& motionState = physicsObject.rigidBody->GetMotionState();
|
||||||
|
|
||||||
|
motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition());
|
||||||
|
// TODO: Force Orientation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Sync Collider Transform with World Transform
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,11 @@ namespace SHADE
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while (accumulatedTime > FIXED_DT)
|
while (accumulatedTime > FIXED_DT)
|
||||||
{
|
{
|
||||||
|
if (scriptEngine)
|
||||||
|
scriptEngine->ExecuteFixedUpdates();
|
||||||
|
|
||||||
|
if (physicsSystem->physicsWorld)
|
||||||
|
physicsSystem->physicsWorld->Step(static_cast<float>(FIXED_DT));
|
||||||
|
|
||||||
accumulatedTime -= FIXED_DT;
|
accumulatedTime -= FIXED_DT;
|
||||||
++count;
|
++count;
|
||||||
|
|
|
@ -28,10 +28,11 @@ namespace SHADE
|
||||||
/* Constructors & Destructor Definitions */
|
/* Constructors & Destructor Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsSystem::SHPhysicsSystem()
|
SHPhysicsSystem::SHPhysicsSystem() noexcept
|
||||||
: worldUpdated { false }
|
: worldUpdated { false }
|
||||||
, interpolationFactor { 0.0 }
|
, interpolationFactor { 0.0 }
|
||||||
, fixedDT { DEFAULT_FIXED_STEP }
|
, fixedDT { DEFAULT_FIXED_STEP }
|
||||||
|
, physicsWorld { nullptr }
|
||||||
{
|
{
|
||||||
// Add more events here to register them
|
// Add more events here to register them
|
||||||
|
|
||||||
|
@ -45,6 +46,11 @@ namespace SHADE
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHPhysicsSystem::~SHPhysicsSystem() noexcept
|
||||||
|
{
|
||||||
|
delete physicsWorld;
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Getter Function Definitions */
|
/* Getter Function Definitions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -141,24 +147,66 @@ namespace SHADE
|
||||||
SHEventHandle SHPhysicsSystem::onSceneInit(SHEventPtr onSceneInitEvent)
|
SHEventHandle SHPhysicsSystem::onSceneInit(SHEventPtr onSceneInitEvent)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* TODO:
|
|
||||||
* If a world already exists, destroy it
|
* If a world already exists, destroy it
|
||||||
* Recreate the world
|
* Recreate the world.
|
||||||
*
|
*
|
||||||
* If there is an editor and editor mode is already playing, link all entities with the world immediately.
|
* If there is an editor and editor mode is already playing, link all entities with the world immediately.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Destroy an existing world if there is one.
|
||||||
|
//! This should almost never happen.
|
||||||
|
if (physicsWorld)
|
||||||
|
{
|
||||||
|
// Remove all references of physics objects from the world
|
||||||
|
for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values)
|
||||||
|
{
|
||||||
|
if (PHYSICS_OBJECT.rigidBody)
|
||||||
|
physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete physicsWorld;
|
||||||
|
physicsWorld = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the physics world
|
||||||
|
physicsWorld = new SHPhysicsWorld;
|
||||||
|
|
||||||
|
#ifdef SHEDITOR
|
||||||
|
|
||||||
|
// Link all entities with the world if editor is already playing.
|
||||||
|
// This is for handling scene changes while the editor is active.
|
||||||
|
|
||||||
|
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (EDITOR && EDITOR->editorState == SHEditor::State::PLAY)
|
||||||
|
{
|
||||||
|
for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values)
|
||||||
|
{
|
||||||
|
if (PHYSICS_OBJECT.rigidBody)
|
||||||
|
physicsWorld->AddRigidBody(PHYSICS_OBJECT.rigidBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
return onSceneInitEvent.get()->handle;
|
return onSceneInitEvent.get()->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::onSceneExit(SHEventPtr onSceneExitEvent)
|
SHEventHandle SHPhysicsSystem::onSceneExit(SHEventPtr onSceneExitEvent)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* TODO:
|
|
||||||
* Destroy the physics world.
|
* Destroy the physics world.
|
||||||
* Destroy all physics objects.
|
* Destroy all physics objects.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values)
|
||||||
|
{
|
||||||
|
if (PHYSICS_OBJECT.rigidBody)
|
||||||
|
physicsWorld->RemoveRigidBody(PHYSICS_OBJECT.rigidBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete physicsWorld;
|
||||||
|
physicsWorld = nullptr;
|
||||||
|
|
||||||
return onSceneExitEvent.get()->handle;
|
return onSceneExitEvent.get()->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,8 +229,17 @@ namespace SHADE
|
||||||
|
|
||||||
// Link engine components with physics object component
|
// Link engine components with physics object component
|
||||||
if (IS_RIGID_BODY)
|
if (IS_RIGID_BODY)
|
||||||
|
{
|
||||||
physicsObjectManager.AddRigidBody(EID);
|
physicsObjectManager.AddRigidBody(EID);
|
||||||
|
|
||||||
|
if (physicsWorld)
|
||||||
|
{
|
||||||
|
auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody;
|
||||||
|
physicsWorld->AddRigidBody(rigidBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (IS_COLLIDER)
|
if (IS_COLLIDER)
|
||||||
physicsObjectManager.AddCollider(EID);
|
physicsObjectManager.AddCollider(EID);
|
||||||
}
|
}
|
||||||
|
@ -209,7 +266,16 @@ namespace SHADE
|
||||||
|
|
||||||
// Link engine components with physics object component
|
// Link engine components with physics object component
|
||||||
if (IS_RIGID_BODY)
|
if (IS_RIGID_BODY)
|
||||||
|
{
|
||||||
|
if (physicsWorld)
|
||||||
|
{
|
||||||
|
auto* rigidBody = physicsObjectManager.GetPhysicsObject(EID)->rigidBody;
|
||||||
|
physicsWorld->RemoveRigidBody(rigidBody);
|
||||||
|
}
|
||||||
|
|
||||||
physicsObjectManager.RemoveRigidBody(EID);
|
physicsObjectManager.RemoveRigidBody(EID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (IS_COLLIDER)
|
if (IS_COLLIDER)
|
||||||
physicsObjectManager.RemoveCollider(EID);
|
physicsObjectManager.RemoveCollider(EID);
|
||||||
|
@ -222,10 +288,15 @@ namespace SHADE
|
||||||
|
|
||||||
SHEventHandle SHPhysicsSystem::onEditorPlay(SHEventPtr onEditorPlayEvent)
|
SHEventHandle SHPhysicsSystem::onEditorPlay(SHEventPtr onEditorPlayEvent)
|
||||||
{
|
{
|
||||||
/*
|
// Add all physics components to the physics world
|
||||||
* TODO:
|
for (const auto& PHYSICS_OBJECT : physicsObjectManager.GetPhysicsObjects() | std::views::values)
|
||||||
* Link all entities with the world.
|
{
|
||||||
*/
|
// Add rigid body if it exists
|
||||||
|
if (PHYSICS_OBJECT.rigidBody)
|
||||||
|
physicsWorld->AddRigidBody(PHYSICS_OBJECT.rigidBody);
|
||||||
|
|
||||||
|
// TODO: Add Collider if it exists
|
||||||
|
}
|
||||||
|
|
||||||
return onEditorPlayEvent.get()->handle;
|
return onEditorPlayEvent.get()->handle;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
||||||
#include "Events/SHEvent.h"
|
#include "Events/SHEvent.h"
|
||||||
|
|
||||||
|
#include "Physics/Dynamics/SHPhysicsWorld.h"
|
||||||
#include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h"
|
#include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h"
|
||||||
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
|
#include "Physics/Interface/RigidBodyComponent/SHRigidBodyComponent.h"
|
||||||
#include "Physics/Interface/SHColliderComponent.h"
|
#include "Physics/Interface/SHColliderComponent.h"
|
||||||
|
@ -34,7 +35,8 @@ namespace SHADE
|
||||||
/* Constructors & Destructor */
|
/* Constructors & Destructor */
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
SHPhysicsSystem();
|
SHPhysicsSystem () noexcept;
|
||||||
|
~SHPhysicsSystem() noexcept;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Getter Functions */
|
/* Getter Functions */
|
||||||
|
@ -75,9 +77,6 @@ namespace SHADE
|
||||||
public:
|
public:
|
||||||
PhysicsPreUpdate();
|
PhysicsPreUpdate();
|
||||||
void Execute(double dt) noexcept override;
|
void Execute(double dt) noexcept override;
|
||||||
|
|
||||||
private:
|
|
||||||
void syncTransforms(SHPhysicsObject* physicsObject) const noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -103,9 +102,6 @@ namespace SHADE
|
||||||
public:
|
public:
|
||||||
PhysicsPostUpdate();
|
PhysicsPostUpdate();
|
||||||
void Execute(double dt) noexcept override;
|
void Execute(double dt) noexcept override;
|
||||||
|
|
||||||
private:
|
|
||||||
void syncTransforms(SHRigidBodyComponent* rbComponent) const noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -136,6 +132,8 @@ namespace SHADE
|
||||||
|
|
||||||
// Sub-systems / managers
|
// Sub-systems / managers
|
||||||
|
|
||||||
|
SHPhysicsWorld* physicsWorld;
|
||||||
|
|
||||||
SHPhysicsObjectManager physicsObjectManager;
|
SHPhysicsObjectManager physicsObjectManager;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -52,5 +52,6 @@ namespace SHADE
|
||||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo () noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo () noexcept;
|
||||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo () noexcept;
|
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo () noexcept;
|
||||||
[[nodiscard]] static double GetFixedDT () noexcept;
|
[[nodiscard]] static double GetFixedDT () noexcept;
|
||||||
|
[[nodiscard]] static int GetFixedUpdateRate () noexcept;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue