Implemented a custom physics engine #316

Merged
direnbharwani merged 95 commits from SHPhysics into main 2023-01-23 15:55:45 +08:00
20 changed files with 468 additions and 167 deletions
Showing only changes of commit 53edffebac - Show all commits

View File

@ -286,7 +286,14 @@ namespace SHADE
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::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]
{
// Convert it to degrees...
auto rot = component->GetRotation();
for (size_t i = 0; i < SHVec3::SIZE; ++i)
rot[i] = SHMath::RadiansToDegrees(rot[i]);
return rot;
}, [](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
{ {
SHEditorWidgets::DragVec3("Velocity", { "X", "Y", "Z" }, [component] {return component->GetLinearVelocity(); }, [](SHVec3 const& value) {}, false, "Linear Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly); SHEditorWidgets::DragVec3("Velocity", { "X", "Y", "Z" }, [component] {return component->GetLinearVelocity(); }, [](SHVec3 const& value) {}, false, "Linear Velocity", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);

View File

@ -203,9 +203,9 @@ namespace SHADE
drawCube(points, color, pos, size); drawCube(points, color, pos, size);
} }
void SHDebugDrawSystem::DrawSphere(const SHVec4& color, const SHVec3& pos, double radius) void SHDebugDrawSystem::DrawSphere(const SHVec4& color, const SHVec3& pos, const SHVec3& rot, double radius)
{ {
drawSphere(points, color, pos, radius); drawSphere(points, color, pos, rot, radius);
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -238,7 +238,7 @@ namespace SHADE
void SHDebugDrawSystem::DrawPersistentSphere(const SHVec4& color, const SHVec3& pos, double radius) void SHDebugDrawSystem::DrawPersistentSphere(const SHVec4& color, const SHVec3& pos, double radius)
{ {
drawSphere(persistentPoints, color, pos, radius); drawSphere(persistentPoints, color, pos, SHVec3::Zero, radius);
} }
void SHDebugDrawSystem::ClearPersistentDraws() void SHDebugDrawSystem::ClearPersistentDraws()
@ -315,7 +315,7 @@ namespace SHADE
); );
} }
void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius) void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& rot, double radius)
{ {
//if (spherePoints.empty()) //if (spherePoints.empty())
{ {
@ -324,7 +324,9 @@ namespace SHADE
static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere(); static const SHMeshData SPHERE = SHPrimitiveGenerator::Sphere();
for (const auto& idx : SPHERE.Indices) for (const auto& idx : SPHERE.Indices)
{ {
spherePoints.emplace_back(SPHERE.VertexPositions[idx] * radius + pos); SHVec3 SCALE { static_cast<float>(radius) };
const SHMatrix TRS = SHMatrix::Transform(pos, rot, { static_cast<float>(radius) });
spherePoints.emplace_back(SHVec3::Transform(SPHERE.VertexPositions[idx], TRS));
} }
} }
drawLineSet(storage, color, spherePoints.begin(), spherePoints.end()); drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());

View File

@ -123,8 +123,9 @@ namespace SHADE
/// </summary> /// </summary>
/// <param name="color">Colour of the sphere.</param> /// <param name="color">Colour of the sphere.</param>
/// <param name="pos">Position where the sphere wil be centered at.</param> /// <param name="pos">Position where the sphere wil be centered at.</param>
/// <param name="rot">Rotation of the sphere. </param>
/// <param name="size">Size of the rendered sphere.</param> /// <param name="size">Size of the rendered sphere.</param>
void DrawSphere(const SHVec4& color, const SHVec3& pos, double radius); void DrawSphere(const SHVec4& color, const SHVec3& pos, const SHVec3& rot, double radius);
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Persistent Draw Functions */ /* Persistent Draw Functions */
@ -246,7 +247,7 @@ namespace SHADE
template<typename IterType> template<typename IterType>
void drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd); void drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
void drawCube(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& size); void drawCube(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& size);
void drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius); void drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& rot, double radius);
}; };
} }

View File

@ -111,6 +111,12 @@ namespace SHADE
void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept; void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept;
/*---------------------------------------------------------------------------------*/
/* Member Functions */
/*---------------------------------------------------------------------------------*/
[[nodiscard]] virtual SHMatrix GetInertiaTensor (float mass) const noexcept = 0;
protected: protected:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */

View File

@ -13,6 +13,9 @@
// Primary Header // Primary Header
#include "SHSphereCollisionShape.h" #include "SHSphereCollisionShape.h"
// Project Headers
#include "Math/SHMatrix.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -179,5 +182,17 @@ namespace SHADE
return SHSphere::Raycast(ray); return SHSphere::Raycast(ray);
} }
SHMatrix SHSphereCollisionShape::GetInertiaTensor(float mass) const noexcept
{
static constexpr float TWO_OVER_FIVE = 2.0f / 5.0f;
const float DIAGONAL = TWO_OVER_FIVE * mass * (Radius * Radius);
SHMatrix result;
result.m[0][0] = result.m[1][1] = result.m[2][2] = DIAGONAL;
return result;
}
} // namespace SHADE } // namespace SHADE

View File

@ -96,7 +96,7 @@ namespace SHADE
* @return * @return
* True if the point is inside the sphere. * True if the point is inside the sphere.
*/ */
bool TestPoint (const SHVec3& point) const noexcept override; [[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override;
/** /**
* @brief * @brief
@ -107,9 +107,19 @@ namespace SHADE
* An object holding the results of the raycast. <br/> * An object holding the results of the raycast. <br/>
* See the corresponding header for the contents of the object. * See the corresponding header for the contents of the object.
*/ */
SHRaycastResult Raycast (const SHRay& ray) const noexcept override; [[nodiscard]] SHRaycastResult Raycast (const SHRay& ray) const noexcept override;
// TODO: Compute Moment of Inertia /**
* @brief
* Computes the inertia tensor of the sphere.
* @param mass
* The mass of the sphere.
* @return
* The inertia tensor of the sphere.
*/
[[nodiscard]] SHMatrix GetInertiaTensor (float mass) const noexcept override;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -80,6 +80,15 @@ namespace SHADE
position = newPosition; position = newPosition;
} }
void SHMotionState::ForceOrientation(const SHQuaternion& newOrientation) noexcept
{
hasMoved = true;
prevOrientation = newOrientation;
orientation = newOrientation;
}
void SHMotionState::IntegratePosition(const SHVec3& velocity, float dt) noexcept 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. // Velocities are 0 when objects are static or sleeping. We do not want to integrate them here.
@ -91,10 +100,32 @@ namespace SHADE
position += velocity * dt; position += velocity * dt;
} }
void SHMotionState::IntegrateOrientation(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;
prevOrientation = orientation;
SHQuaternion qv{ velocity.x * dt, velocity.y * dt, velocity.z * dt, 0.0f };
qv *= orientation;
orientation += qv * 0.5f;
orientation = SHQuaternion::Normalise(orientation);
}
SHVec3 SHMotionState::InterpolatePositions(float factor) const noexcept SHVec3 SHMotionState::InterpolatePositions(float factor) const noexcept
{ {
return SHVec3::ClampedLerp(prevPosition, position, factor); return SHVec3::ClampedLerp(prevPosition, position, factor);
} }
SHQuaternion SHMotionState::InterpolateOrientations(float factor) const noexcept
{
return SHQuaternion::ClampedSlerp(prevOrientation, orientation, factor);
}
} // namespace SHADE } // namespace SHADE

View File

@ -11,8 +11,10 @@
#pragma once #pragma once
// Project Headers // Project Headers
#include "Math/SHQuaternion.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
namespace SHADE namespace SHADE
{ {
/*-------------------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------------------*/
@ -30,10 +32,13 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool hasMoved; bool hasMoved;
SHVec3 position; SHVec3 position;
SHVec3 prevPosition; SHVec3 prevPosition;
SHQuaternion orientation;
SHQuaternion prevOrientation;
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Constructors & Destructor */ /* Constructors & Destructor */
@ -65,17 +70,36 @@ namespace SHADE
* @param newPosition * @param newPosition
* The new position to set. * The new position to set.
*/ */
void ForcePosition (const SHVec3& newPosition) noexcept; void ForcePosition (const SHVec3& newPosition) noexcept;
/** /**
* @brief * @brief
* Integrates the positions using velocity with respect to time. * Forcefully sets the orientation. Meant to be used when transform overrides the rigid body
* orientations
* @param newOrientation
* The new orientation to set.
*/
void ForceOrientation (const SHQuaternion& newOrientation) noexcept;
/**
* @brief
* Integrates the positions using linear velocity with respect to time.
* @param velocity * @param velocity
* The velocity to integrate. * The linear velocity to integrate.
* @param dt * @param dt
* The delta time to integrate with respect to. * The delta time to integrate with respect to.
*/ */
void IntegratePosition (const SHVec3& velocity, float dt) noexcept; void IntegratePosition (const SHVec3& velocity, float dt) noexcept;
/**
* @brief
* Integrates the orientation using angular velocity with respect to time.
* @param velocity
* The angular velocity to integrate.
* @param dt
* The delta time to integrate with respect to.
*/
void IntegrateOrientation (const SHVec3& velocity, float dt) noexcept;
/** /**
* @brief * @brief
@ -85,7 +109,17 @@ namespace SHADE
* @returns * @returns
* The interpolated position meant for rendering. * The interpolated position meant for rendering.
*/ */
SHVec3 InterpolatePositions (float factor) const noexcept; SHVec3 InterpolatePositions (float factor) const noexcept;
/**
* @brief
* Interpolates the orientation 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 orientation meant for rendering.
*/
SHQuaternion InterpolateOrientations (float factor) const noexcept;
}; };

View File

@ -74,7 +74,10 @@ namespace SHADE
void SHPhysicsWorld::Step(float dt) void SHPhysicsWorld::Step(float dt)
{ {
for (auto* rigidBody : rigidBodies) for (auto* rigidBody : rigidBodies)
{
rigidBody->ComputeWorldData();
integrateForces(*rigidBody, dt); integrateForces(*rigidBody, dt);
}
for (auto* rigidBody : rigidBodies) for (auto* rigidBody : rigidBodies)
integrateVelocities(*rigidBody, dt); integrateVelocities(*rigidBody, dt);
@ -93,10 +96,14 @@ namespace SHADE
const SHVec3 LINEAR_ACCELERATION = rigidBody.accumulatedForce * rigidBody.invMass; const SHVec3 LINEAR_ACCELERATION = rigidBody.accumulatedForce * rigidBody.invMass;
const SHVec3 GRAVITATIONAL_ACCELERATION = rigidBody.IsGravityEnabled() ? settings.gravity * rigidBody.gravityScale : SHVec3::Zero; const SHVec3 GRAVITATIONAL_ACCELERATION = rigidBody.IsGravityEnabled() ? settings.gravity * rigidBody.gravityScale : SHVec3::Zero;
rigidBody.linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * dt; rigidBody.linearVelocity += (LINEAR_ACCELERATION + GRAVITATIONAL_ACCELERATION) * dt;
// Integrate torque into angular velocity
rigidBody.angularVelocity += rigidBody.worldInvInertia * (rigidBody.accumulatedTorque * dt);
// Apply drag (exponentially applied) // Apply drag (exponentially applied)
rigidBody.linearVelocity *= 1.0f / (1.0f + dt * rigidBody.linearDrag); rigidBody.linearVelocity *= 1.0f / (1.0f + dt * rigidBody.linearDrag);
rigidBody.angularVelocity *= 1.0f / (1.0f + dt * rigidBody.angularDrag);
} }
void SHPhysicsWorld::integrateVelocities(SHRigidBody& rigidBody, float dt) const noexcept void SHPhysicsWorld::integrateVelocities(SHRigidBody& rigidBody, float dt) const noexcept
@ -111,7 +118,13 @@ namespace SHADE
, rigidBody.GetFreezePositionZ() ? 0.0f : rigidBody.linearVelocity.z , rigidBody.GetFreezePositionZ() ? 0.0f : rigidBody.linearVelocity.z
}; };
// TODO: Enforce angular constraints // Enforce angular constraints
rigidBody.angularVelocity = SHVec3
{
rigidBody.GetFreezeRotationX() ? 0.0f : rigidBody.angularVelocity.x
, rigidBody.GetFreezeRotationY() ? 0.0f : rigidBody.angularVelocity.y
, rigidBody.GetFreezeRotationZ() ? 0.0f : rigidBody.angularVelocity.z
};
}; };
// Always reset movement flag // Always reset movement flag
@ -129,13 +142,13 @@ namespace SHADE
ENFORCE_CONSTRAINED_VELOCITIES(rigidBody); ENFORCE_CONSTRAINED_VELOCITIES(rigidBody);
rigidBody.motionState.IntegratePosition(rigidBody.linearVelocity, dt); rigidBody.motionState.IntegratePosition(rigidBody.linearVelocity, dt);
// TODO: Integrate orientations rigidBody.motionState.IntegrateOrientation(rigidBody.angularVelocity, dt);
// Sync with collider transforms if a collider is present // Sync with collider transforms if a collider is present
if (rigidBody.collider) if (rigidBody.collider)
{ {
rigidBody.collider->SetPosition(rigidBody.motionState.position); rigidBody.collider->SetPosition(rigidBody.motionState.position);
// TODO: Sync orientations rigidBody.collider->SetOrientation(rigidBody.motionState.orientation);
rigidBody.collider->RecomputeShapes(); rigidBody.collider->RecomputeShapes();
} }

View File

@ -27,9 +27,10 @@ namespace SHADE
: entityID { eid } : entityID { eid }
, collider { nullptr } , collider { nullptr }
, bodyType { type } , bodyType { type }
, gravityScale { 1.0f }
, invMass { type == Type::DYNAMIC ? 1.0f : 0.0f } , invMass { type == Type::DYNAMIC ? 1.0f : 0.0f }
, linearDrag { 0.01f } , linearDrag { 0.01f }
, gravityScale { 1.0f } , angularDrag { 0.01f }
, flags { 0U } , flags { 0U }
{ {
// Set default flags // Set default flags
@ -41,14 +42,19 @@ namespace SHADE
} }
SHRigidBody::SHRigidBody(const SHRigidBody& rhs) noexcept SHRigidBody::SHRigidBody(const SHRigidBody& rhs) noexcept
: entityID { rhs.entityID } : entityID { rhs.entityID }
, collider { nullptr } , collider { nullptr }
, bodyType { rhs.bodyType } , bodyType { rhs.bodyType }
, invMass { rhs.invMass } , gravityScale { rhs.gravityScale }
, linearDrag { rhs.linearDrag } , invMass { rhs.invMass }
, gravityScale { rhs.gravityScale } , linearDrag { rhs.linearDrag }
, flags { rhs.flags } , angularDrag { rhs.angularDrag }
, motionState { rhs.motionState } , localInvInertia { rhs.localInvInertia }
, worldInvInertia { rhs.worldInvInertia }
, localCentroid { rhs.localCentroid }
, worldCentroid { rhs.worldCentroid }
, 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.
} }
@ -57,9 +63,14 @@ namespace SHADE
: entityID { rhs.entityID } : entityID { rhs.entityID }
, collider { nullptr } , collider { nullptr }
, bodyType { rhs.bodyType } , bodyType { rhs.bodyType }
, gravityScale { rhs.gravityScale }
, invMass { rhs.invMass } , invMass { rhs.invMass }
, linearDrag { rhs.linearDrag } , linearDrag { rhs.linearDrag }
, gravityScale { rhs.gravityScale } , angularDrag { rhs.angularDrag }
, localInvInertia { rhs.localInvInertia }
, worldInvInertia { rhs.worldInvInertia }
, localCentroid { rhs.localCentroid }
, worldCentroid { rhs.worldCentroid }
, flags { rhs.flags } , flags { rhs.flags }
, motionState { std::move(rhs.motionState) } , motionState { std::move(rhs.motionState) }
{ {
@ -77,17 +88,24 @@ namespace SHADE
return *this; return *this;
entityID = rhs.entityID; entityID = rhs.entityID;
// Deep copy the collider // Deep copy the collider
*collider = *rhs.collider; *collider = *rhs.collider;
bodyType = rhs.bodyType; bodyType = rhs.bodyType;
invMass = rhs.invMass; gravityScale = rhs.gravityScale;
linearDrag = rhs.linearDrag; invMass = rhs.invMass;
gravityScale = rhs.gravityScale; linearDrag = rhs.linearDrag;
flags = rhs.flags; angularDrag = rhs.angularDrag;
motionState = rhs.motionState; localInvInertia = rhs.localInvInertia;
worldInvInertia = rhs.worldInvInertia;
localCentroid = rhs.localCentroid;
worldCentroid = rhs.worldCentroid;
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; accumulatedForce = SHVec3::Zero;
accumulatedTorque = SHVec3::Zero;
linearVelocity = SHVec3::Zero; linearVelocity = SHVec3::Zero;
angularVelocity = SHVec3::Zero; angularVelocity = SHVec3::Zero;
@ -97,17 +115,24 @@ namespace SHADE
SHRigidBody& SHRigidBody::operator=(SHRigidBody&& rhs) noexcept SHRigidBody& SHRigidBody::operator=(SHRigidBody&& rhs) noexcept
{ {
entityID = rhs.entityID; entityID = rhs.entityID;
// Deep copy the collider // Deep copy the collider
*collider = *rhs.collider; *collider = *rhs.collider;
bodyType = rhs.bodyType; bodyType = rhs.bodyType;
gravityScale = rhs.gravityScale;
invMass = rhs.invMass; invMass = rhs.invMass;
linearDrag = rhs.linearDrag; linearDrag = rhs.linearDrag;
gravityScale = rhs.gravityScale; angularDrag = rhs.angularDrag;
localInvInertia = rhs.localInvInertia;
worldInvInertia = rhs.worldInvInertia;
localCentroid = rhs.localCentroid;
worldCentroid = rhs.worldCentroid;
flags = rhs.flags; flags = rhs.flags;
motionState = std::move(rhs.motionState); 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; accumulatedForce = SHVec3::Zero;
accumulatedTorque = SHVec3::Zero;
linearVelocity = SHVec3::Zero; linearVelocity = SHVec3::Zero;
angularVelocity = SHVec3::Zero; angularVelocity = SHVec3::Zero;
@ -123,6 +148,11 @@ namespace SHADE
return bodyType; return bodyType;
} }
float SHRigidBody::GetGravityScale() const noexcept
{
return gravityScale;
}
float SHRigidBody::GetMass() const noexcept float SHRigidBody::GetMass() const noexcept
{ {
return 1.0f/ invMass; return 1.0f/ invMass;
@ -133,16 +163,41 @@ namespace SHADE
return linearDrag; return linearDrag;
} }
float SHRigidBody::GetGravityScale() const noexcept float SHRigidBody::GetAngularDrag() const noexcept
{ {
return gravityScale; return angularDrag;
} }
const SHVec3& SHRigidBody::GetAccumulatedForce() const noexcept const SHMatrix& SHRigidBody::GetLocalInvInertia() const noexcept
{
return localInvInertia;
}
const SHMatrix& SHRigidBody::GetWorldInvInertia() const noexcept
{
return worldInvInertia;
}
const SHVec3& SHRigidBody::GetLocalCentroid() const noexcept
{
return localCentroid;
}
const SHVec3& SHRigidBody::GetWorldCentroid() const noexcept
{
return worldCentroid;
}
const SHVec3& SHRigidBody::GetForce() const noexcept
{ {
return accumulatedForce; return accumulatedForce;
} }
const SHVec3& SHRigidBody::GetTorque() const noexcept
{
return accumulatedTorque;
}
const SHVec3& SHRigidBody::GetLinearVelocity() const noexcept const SHVec3& SHRigidBody::GetLinearVelocity() const noexcept
{ {
return linearVelocity; return linearVelocity;
@ -226,7 +281,6 @@ namespace SHADE
return motionState; return motionState;
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Functions Definitions */ /* Setter Functions Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -245,6 +299,11 @@ namespace SHADE
invMass = newType == Type::DYNAMIC ? 1.0f : 0.0f; invMass = newType == Type::DYNAMIC ? 1.0f : 0.0f;
} }
void SHRigidBody::SetGravityScale(float newGravityScale) noexcept
{
gravityScale = newGravityScale;
}
void SHRigidBody::SetMass(float newMass) noexcept void SHRigidBody::SetMass(float newMass) noexcept
{ {
if (bodyType != Type::DYNAMIC) if (bodyType != Type::DYNAMIC)
@ -261,7 +320,7 @@ namespace SHADE
invMass = 1.0f / newMass; invMass = 1.0f / newMass;
// TODO: Recompute inertia tensor ComputeMassData();
} }
void SHRigidBody::SetLinearDrag(float newLinearDrag) noexcept void SHRigidBody::SetLinearDrag(float newLinearDrag) noexcept
@ -281,16 +340,45 @@ namespace SHADE
linearDrag = newLinearDrag; linearDrag = newLinearDrag;
} }
void SHRigidBody::SetGravityScale(float newGravityScale) noexcept void SHRigidBody::SetAngularDrag(float newAngularDrag) noexcept
{ {
gravityScale = newGravityScale; if (bodyType == Type::STATIC)
{
SHLOG_WARNING("Cannot set angular drag of a Static Body {}", entityID)
return;
}
if (newAngularDrag < 0.0f)
{
SHLOG_WARNING("Cannot set drag below 0. Object {}'s angular drag will remain unchanged.", entityID)
return;
}
angularDrag = newAngularDrag;
} }
void SHRigidBody::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept void SHRigidBody::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
{ {
if (bodyType == Type::STATIC)
{
SHLOG_WARNING("Cannot set linear velocity of a Static Body {}", entityID)
return;
}
linearVelocity = newLinearVelocity; linearVelocity = newLinearVelocity;
} }
void SHRigidBody::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
{
if (bodyType == Type::STATIC)
{
SHLOG_WARNING("Cannot set angular velocity of a Static Body {}", entityID)
return;
}
angularVelocity = newAngularVelocity;
}
void SHRigidBody::SetIsActive(bool isActive) noexcept void SHRigidBody::SetIsActive(bool isActive) noexcept
{ {
static constexpr unsigned int FLAG_POS = 0; static constexpr unsigned int FLAG_POS = 0;
@ -304,7 +392,18 @@ namespace SHADE
static constexpr unsigned int FLAG_POS = 1; static constexpr unsigned int FLAG_POS = 1;
static constexpr uint16_t VALUE = 1U << FLAG_POS; static constexpr uint16_t VALUE = 1U << FLAG_POS;
isSleeping ? flags |= VALUE : flags &= ~VALUE; if (isSleeping)
{
flags |= VALUE;
ClearForces();
linearVelocity = SHVec3::Zero;
angularVelocity = SHVec3::Zero;
}
else
{
flags &= ~VALUE;
}
} }
void SHRigidBody::SetSleepingEnabled(bool enableSleeping) noexcept void SHRigidBody::SetSleepingEnabled(bool enableSleeping) noexcept
@ -411,6 +510,8 @@ namespace SHADE
flags |= VALUE; flags |= VALUE;
// Reset angular velocity along X-axis // Reset angular velocity along X-axis
angularVelocity.x = 0.0f; angularVelocity.x = 0.0f;
// Set inertia tensor on the x-axis to 0
localInvInertia.m[0][0] = worldInvInertia.m[0][0] = 0.0f;
} }
else else
{ {
@ -428,6 +529,8 @@ namespace SHADE
flags |= VALUE; flags |= VALUE;
// Reset angular velocity along Y-axis // Reset angular velocity along Y-axis
angularVelocity.y = 0.0f; angularVelocity.y = 0.0f;
// Set inertia tensor on the y-axis to 0
localInvInertia.m[1][1] = worldInvInertia.m[1][1] = 0.0f;
} }
else else
{ {
@ -445,6 +548,8 @@ namespace SHADE
flags |= VALUE; flags |= VALUE;
// Reset angular velocity along Z-axis // Reset angular velocity along Z-axis
angularVelocity.z = 0.0f; angularVelocity.z = 0.0f;
// Set inertia tensor on the z-axis to 0
localInvInertia.m[2][2] = worldInvInertia.m[2][2] = 0.0f;
} }
else else
{ {
@ -461,21 +566,60 @@ namespace SHADE
if (bodyType != Type::DYNAMIC) if (bodyType != Type::DYNAMIC)
return; return;
accumulatedForce += force; accumulatedForce += force;
// Compute torque when force is offset accumulatedTorque += SHVec3::Cross(pos, force);
} }
void SHRigidBody::AddImpulse(const SHVec3& impulse, const SHVec3& pos) noexcept void SHRigidBody::AddImpulse(const SHVec3& impulse, const SHVec3& pos) noexcept
{ {
if (bodyType != Type::DYNAMIC) if (bodyType != Type::DYNAMIC)
return; return;
linearVelocity += impulse * invMass; linearVelocity += impulse * invMass;
angularVelocity += worldInvInertia * SHVec3::Cross(pos, impulse);
}
void SHRigidBody::AddTorque(const SHVec3& torque) noexcept
{
if (bodyType != Type::DYNAMIC)
return;
accumulatedTorque += torque;
} }
void SHRigidBody::ClearForces() noexcept void SHRigidBody::ClearForces() noexcept
{ {
accumulatedForce = SHVec3::Zero; accumulatedForce = SHVec3::Zero;
accumulatedTorque = SHVec3::Zero;
}
void SHRigidBody::ComputeWorldData() noexcept
{
const SHMatrix ROTATION = SHMatrix::Rotate(motionState.orientation);
// Compute world inertia
worldInvInertia = ROTATION * localInvInertia * SHMatrix::Transpose(ROTATION);
// Compute world centroid
worldCentroid = (ROTATION * localCentroid) + motionState.position;
}
void SHRigidBody::ComputeMassData() noexcept
{
// TODO: Compute total inertia and centroid from composited colliders using the Parallel Axis Theorem.
// TODO: If auto mass in enabled, compute total mass based from each collider.
// TODO: If auto mass disabled, compute inertia tensor for each shape using the ratio of its mass / total mass by comparing the volume / total volume.
if (collider && !collider->GetCollisionShapes().empty())
{
// HACK: For now, take only the first shape as we are testing with non-composited colliders. We are using the center as the centroid.
const auto* FIRST_SHAPE = collider->GetCollisionShape(0);
localInvInertia = SHMatrix::Inverse(FIRST_SHAPE->GetInertiaTensor(1.0f / invMass));
}
else
{
localInvInertia.m[0][0] = localInvInertia.m[1][1] = localInvInertia.m[2][2] = invMass;
}
} }
} // namespace SHADE } // namespace SHADE

View File

@ -12,6 +12,7 @@
// Project Headers // Project Headers
#include "ECS_Base/Entity/SHEntity.h" #include "ECS_Base/Entity/SHEntity.h"
#include "Math/SHMatrix.h"
#include "Math/Vector/SHVec3.h" #include "Math/Vector/SHVec3.h"
#include "SHMotionState.h" #include "SHMotionState.h"
@ -73,12 +74,20 @@ namespace SHADE
[[nodiscard]] Type GetType () const noexcept; [[nodiscard]] Type GetType () const noexcept;
[[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetLinearDrag () const noexcept;
[[nodiscard]] float GetGravityScale () const noexcept; [[nodiscard]] float GetGravityScale () const noexcept;
[[nodiscard]] const SHVec3& GetAccumulatedForce () const noexcept; [[nodiscard]] float GetMass () const noexcept;
[[nodiscard]] float GetLinearDrag () const noexcept;
[[nodiscard]] float GetAngularDrag () const noexcept;
[[nodiscard]] const SHMatrix& GetLocalInvInertia () const noexcept;
[[nodiscard]] const SHMatrix& GetWorldInvInertia () const noexcept;
[[nodiscard]] const SHVec3& GetLocalCentroid () const noexcept;
[[nodiscard]] const SHVec3& GetWorldCentroid () const noexcept;
[[nodiscard]] const SHVec3& GetForce () const noexcept;
[[nodiscard]] const SHVec3& GetTorque () const noexcept;
[[nodiscard]] const SHVec3& GetLinearVelocity () const noexcept; [[nodiscard]] const SHVec3& GetLinearVelocity () const noexcept;
[[nodiscard]] const SHVec3& GetAngularVelocity () const noexcept; [[nodiscard]] const SHVec3& GetAngularVelocity () const noexcept;
@ -111,6 +120,8 @@ namespace SHADE
*/ */
void SetType (Type newType) noexcept; void SetType (Type newType) noexcept;
void SetGravityScale (float newGravityScale) noexcept;
/** /**
* @brief * @brief
* Mass is only modifiable for Dynamic bodies. * Mass is only modifiable for Dynamic bodies.
@ -127,9 +138,16 @@ namespace SHADE
*/ */
void SetLinearDrag (float newLinearDrag) noexcept; void SetLinearDrag (float newLinearDrag) noexcept;
/**
* @brief
* Drag is only modifiable for non-Static bodies.
* @param newAngularDrag
* The new drag to set. Values below 0 will be ignored.
*/
void SetAngularDrag (float newAngularDrag) noexcept;
void SetGravityScale (float newGravityScale) noexcept;
void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept; void SetLinearVelocity (const SHVec3& newLinearVelocity) noexcept;
void SetAngularVelocity (const SHVec3& newAngularVelocity)noexcept;
// Flags // Flags
@ -151,29 +169,55 @@ namespace SHADE
/** /**
* @brief * @brief
* Adds a force to the body with an offset from it's center of mass. * Adds a force to the body with an offset from it's center of mass. <br/>
* Non-dynamic bodies will be ignored.
* @param force * @param force
* The force to add to the body. * The force to add to the body.
* @param pos * @param pos
* The position from the center of mass to offset the force. Defaults to zero. * The position from the center of mass to offset the force. Defaults to zero.
*/ */
void AddForce (const SHVec3& force, const SHVec3& pos = SHVec3::Zero) noexcept; void AddForce (const SHVec3& force, const SHVec3& pos = SHVec3::Zero) noexcept;
/** /**
* @brief * @brief
* Adds an impulse to the body with an offset from it's center of mass. * Adds an impulse to the body with an offset from it's center of mass. <br/>
* Non-dynamic bodies will be ignored.
* @param impulse * @param impulse
* The impulse to add to the body. * The impulse to add to the body.
* @param pos * @param pos
* The position from the center of mass to offset the impulse. Defaults to zero. * The position from the center of mass to offset the impulse. Defaults to zero.
*/ */
void AddImpulse (const SHVec3& impulse, const SHVec3& pos = SHVec3::Zero) noexcept; void AddImpulse (const SHVec3& impulse, const SHVec3& pos = SHVec3::Zero) noexcept;
/**
* @brief
* Adds torque to rotate the body about it's centroid. <br/>
* Non-dynamic bodies will be ignored.
* @param torque
* The torque to add to the body.
*/
void AddTorque (const SHVec3& torque) noexcept;
/** /**
* @brief * @brief
* Removes all the forces from the body. * Removes all the forces from the body.
*/ */
void ClearForces () noexcept; void ClearForces () noexcept;
/**
* @brief
* Computes the centroid and invInertia in world space.
*/
void ComputeWorldData () noexcept;
/**
* @brief
* Computes the centroid and inertia of the object. <br/>
* If auto-mass is enabled, computes the mass. <br/>
* If auto-mass is disabled, the inertia is computed based on the ratio each shape's volume over the total volume.
*
*/
void ComputeMassData () noexcept;
private: private:
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -186,12 +230,20 @@ namespace SHADE
Type bodyType; Type bodyType;
float gravityScale;
float invMass; float invMass;
float linearDrag; float linearDrag;
float angularDrag;
float gravityScale; SHMatrix localInvInertia;
SHMatrix worldInvInertia;
SHVec3 localCentroid;
SHVec3 worldCentroid;
SHVec3 accumulatedForce; SHVec3 accumulatedForce;
SHVec3 accumulatedTorque;
SHVec3 linearVelocity; SHVec3 linearVelocity;
SHVec3 angularVelocity; SHVec3 angularVelocity;

View File

@ -36,18 +36,12 @@ namespace SHADE
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->IsGravityEnabled() : false;
return rigidBody->IsGravityEnabled();
return false;
} }
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->IsSleepingEnabled() : false;
return rigidBody->IsSleepingEnabled();
return false;
} }
bool SHRigidBodyComponent::IsInterpolating() const noexcept bool SHRigidBodyComponent::IsInterpolating() const noexcept
@ -57,131 +51,93 @@ namespace SHADE
bool SHRigidBodyComponent::IsSleeping() const noexcept bool SHRigidBodyComponent::IsSleeping() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->IsSleeping() : false;
return rigidBody->IsSleeping();
return false;
} }
bool SHRigidBodyComponent::GetAutoMass() const noexcept bool SHRigidBodyComponent::GetAutoMass() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->IsAutoMassEnabled() : false;
return rigidBody->IsAutoMassEnabled();
return false;
} }
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetFreezePositionX() : false;
return rigidBody->GetFreezePositionX();
return false;
} }
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetFreezePositionY() : false;
return rigidBody->GetFreezePositionY();
return false;
} }
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetFreezePositionZ() : false;
return rigidBody->GetFreezePositionZ();
return false;
} }
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetFreezeRotationX() : false;
return rigidBody->GetFreezeRotationX();
return false;
} }
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetFreezeRotationY() : false;
return rigidBody->GetFreezeRotationY();
return false;
} }
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetFreezeRotationZ() : false;
return rigidBody->GetFreezeRotationZ();
return false;
} }
float SHRigidBodyComponent::GetGravityScale() const noexcept float SHRigidBodyComponent::GetGravityScale() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetGravityScale() : 0.0f;
return rigidBody->GetGravityScale();
return 0.0f;
} }
float SHRigidBodyComponent::GetMass() const noexcept float SHRigidBodyComponent::GetMass() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetMass() : -1.0f;
return rigidBody->GetMass();
return -1.0f;
} }
float SHRigidBodyComponent::GetDrag() const noexcept float SHRigidBodyComponent::GetDrag() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetLinearDrag() : -1.0f;
return rigidBody->GetLinearDrag();
return -1.0f;
} }
float SHRigidBodyComponent::GetAngularDrag() const noexcept float SHRigidBodyComponent::GetAngularDrag() const noexcept
{ {
return 0.0f; return rigidBody ? rigidBody->GetAngularDrag() : -1.0f;
} }
SHVec3 SHRigidBodyComponent::GetForce() const noexcept SHVec3 SHRigidBodyComponent::GetForce() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetForce() : SHVec3::Zero;
return rigidBody->GetAccumulatedForce();
return SHVec3::Zero;
} }
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
{ {
return SHVec3::Zero; return rigidBody ? rigidBody->GetTorque() : SHVec3::Zero;
} }
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetLinearVelocity() : SHVec3::Zero;
return rigidBody->GetLinearVelocity();
return SHVec3::Zero;
} }
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
{ {
return SHVec3::Zero; return rigidBody ? rigidBody->GetAngularVelocity() : SHVec3::Zero;
} }
SHVec3 SHRigidBodyComponent::GetPosition() const noexcept SHVec3 SHRigidBodyComponent::GetPosition() const noexcept
{ {
if (rigidBody) return rigidBody ? rigidBody->GetMotionState().position : SHVec3::Zero;
return rigidBody->GetMotionState().position;
return SHVec3::Zero;
} }
SHVec3 SHRigidBodyComponent::GetRotation() const noexcept
{
return rigidBody ? rigidBody->GetMotionState().orientation.ToEuler() : SHVec3::Zero;
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Setter Functions Definitions */ /* Setter Functions Definitions */
@ -282,7 +238,8 @@ namespace SHADE
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
{ {
if (rigidBody)
rigidBody->SetAngularDrag(newAngularDrag);
} }
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
@ -293,7 +250,8 @@ namespace SHADE
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
{ {
if (rigidBody)
rigidBody->SetAngularVelocity(newAngularVelocity);
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -308,38 +266,67 @@ namespace SHADE
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
{ {
if (rigidBody)
rigidBody->AddForce(force, localPos);
} }
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
{ {
if (rigidBody) if (rigidBody)
rigidBody->AddForce(force, worldPos); {
// Convert world pos into local space of the body
const SHVec3 LOCAL_POS = worldPos - rigidBody->GetWorldCentroid();
rigidBody->AddForce(force, LOCAL_POS);
}
} }
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
{ {
if (rigidBody)
{
// Rotate force into world space
const SHVec3 FORCE = SHVec3::Rotate(relativeForce, rigidBody->GetMotionState().orientation);
rigidBody->AddForce(FORCE);
}
} }
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
{ {
if (rigidBody)
{
// Rotate force into world space
const SHVec3 FORCE = SHVec3::Rotate(relativeForce, rigidBody->GetMotionState().orientation);
rigidBody->AddForce(FORCE, localPos);
}
} }
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
{ {
if (rigidBody)
{
// Rotate force into world space
const SHVec3 FORCE = SHVec3::Rotate(relativeForce, rigidBody->GetMotionState().orientation);
// Convert world pos into local space of the body
const SHVec3 LOCAL_POS = worldPos - rigidBody->GetWorldCentroid();
rigidBody->AddForce(FORCE, LOCAL_POS);
}
} }
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
{ {
if (rigidBody)
rigidBody->AddTorque(torque);
} }
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
{ {
if (rigidBody)
{
// Rotate force into world space
const SHVec3 TORQUE = SHVec3::Rotate(relativeTorque, rigidBody->GetMotionState().orientation);
rigidBody->AddTorque(TORQUE);
}
} }
void SHRigidBodyComponent::ClearForces() const noexcept void SHRigidBodyComponent::ClearForces() const noexcept
@ -348,11 +335,6 @@ namespace SHADE
rigidBody->ClearForces(); rigidBody->ClearForces();
} }
void SHRigidBodyComponent::ClearTorque() const noexcept
{
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Public Function Member Definitions */ /* Public Function Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/

View File

@ -93,6 +93,7 @@ namespace SHADE
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept; [[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
[[nodiscard]] SHVec3 GetPosition () const noexcept; [[nodiscard]] SHVec3 GetPosition () const noexcept;
[[nodiscard]] SHVec3 GetRotation () const noexcept;
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Setter Functions */ /* Setter Functions */
@ -138,7 +139,6 @@ namespace SHADE
void AddRelativeTorque (const SHVec3& relativeTorque) const noexcept; void AddRelativeTorque (const SHVec3& relativeTorque) const noexcept;
void ClearForces () const noexcept; void ClearForces () const noexcept;
void ClearTorque () const noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -62,15 +62,23 @@ namespace SHADE
if (!MOTION_STATE) if (!MOTION_STATE)
continue; continue;
SHVec3 renderPosition = rigidBodyComponent.IsInterpolating() ? MOTION_STATE.InterpolatePositions(FACTOR) : MOTION_STATE.position; if (rigidBodyComponent.IsInterpolating())
{
const SHVec3 RENDER_POSITION = MOTION_STATE.InterpolatePositions(FACTOR);
const SHQuaternion RENDER_ORIENTATION = MOTION_STATE.InterpolateOrientations(FACTOR);
transformComponent->SetWorldPosition(RENDER_POSITION);
transformComponent->SetWorldOrientation(RENDER_ORIENTATION);
}
else
{
transformComponent->SetWorldPosition(MOTION_STATE.position);
transformComponent->SetWorldOrientation(MOTION_STATE.orientation);
}
/* /*
* TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy. * 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

View File

@ -54,7 +54,7 @@ namespace SHADE
SHMotionState& motionState = physicsObject.rigidBody->GetMotionState(); SHMotionState& motionState = physicsObject.rigidBody->GetMotionState();
motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition()); motionState.ForcePosition(TRANSFORM_COMPONENT->GetWorldPosition());
// TODO: Force Orientation motionState.ForceOrientation(TRANSFORM_COMPONENT->GetWorldOrientation());
} }
if (physicsObject.collider) if (physicsObject.collider)

View File

@ -120,7 +120,10 @@ namespace SHADE
case SHCollisionShape::Type::SPHERE: case SHCollisionShape::Type::SPHERE:
{ {
const SHSphereCollisionShape* SPHERE = dynamic_cast<const SHSphereCollisionShape*>(SHAPE); const SHSphereCollisionShape* SPHERE = dynamic_cast<const SHSphereCollisionShape*>(SHAPE);
drawSphere(debugDrawSystem, *SPHERE);
// Compute rotation of sphere
const SHVec3 ROTATION = collider.GetOrientation().ToEuler() + SPHERE->GetRotationOffset();
drawSphere(debugDrawSystem, *SPHERE, ROTATION);
break; break;
} }
@ -137,10 +140,10 @@ namespace SHADE
} }
} }
void SHPhysicsDebugDrawSystem::drawSphere(SHDebugDrawSystem* debugDrawSystem, const SHSphereCollisionShape& sphere) noexcept void SHPhysicsDebugDrawSystem::drawSphere(SHDebugDrawSystem* debugDrawSystem, const SHSphereCollisionShape& sphere, const SHVec3& rotation) noexcept
{ {
const SHColour& DRAW_COLOUR = DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(sphere.IsTrigger() ? Colours::TRIGGER : Colours::COLLIDER)]; const SHColour& DRAW_COLOUR = DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(sphere.IsTrigger() ? Colours::TRIGGER : Colours::COLLIDER)];
debugDrawSystem->DrawSphere(DRAW_COLOUR, sphere.GetCenter(), sphere.GetWorldRadius()); debugDrawSystem->DrawSphere(DRAW_COLOUR, sphere.GetCenter(), rotation, sphere.GetWorldRadius());
} }
void SHPhysicsDebugDrawSystem::drawContact(SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Contact& contactInfo) noexcept void SHPhysicsDebugDrawSystem::drawContact(SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Contact& contactInfo) noexcept

View File

@ -138,8 +138,8 @@ namespace SHADE
SHEventHandle onColliderDraw(SHEventPtr onColliderDrawEvent); SHEventHandle onColliderDraw(SHEventPtr onColliderDrawEvent);
static void drawCollider (SHDebugDrawSystem* debugDrawSystem, const SHCollider& collider) noexcept; static void drawCollider (SHDebugDrawSystem* debugDrawSystem, const SHCollider& collider) noexcept;
static void drawSphere (SHDebugDrawSystem* debugDrawSystem, const SHSphereCollisionShape& sphere) noexcept; static void drawSphere (SHDebugDrawSystem* debugDrawSystem, const SHSphereCollisionShape& sphere, const SHVec3& rotation) noexcept;
static void drawContact (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Contact& contactInfo) noexcept; static void drawContact (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Contact& contactInfo) noexcept;
static void drawRaycast (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Raycast& raycastInfo) noexcept; static void drawRaycast (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Raycast& raycastInfo) noexcept;

View File

@ -68,7 +68,7 @@ namespace SHADE
void SHDebugDraw::Sphere(const SHVec4& color, const SHVec3& pos, double radius) void SHDebugDraw::Sphere(const SHVec4& color, const SHVec3& pos, double radius)
{ {
dbgDrawSys->DrawSphere(color, pos, radius); dbgDrawSys->DrawSphere(color, pos, SHVec3::Zero, radius);
} }
void SHDebugDraw::PersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt) void SHDebugDraw::PersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)

View File

@ -217,10 +217,4 @@ namespace SHADE
{ {
return Convert::ToCLI(GetNativeComponent()->GetTorque()); return Convert::ToCLI(GetNativeComponent()->GetTorque());
} }
void RigidBody::ClearTorque()
{
GetNativeComponent()->ClearTorque();
}
} }

View File

@ -155,7 +155,6 @@ namespace SHADE
void AddRelativeTorque(Vector3 relativeForce); void AddRelativeTorque(Vector3 relativeForce);
Vector3 GetTorque(); Vector3 GetTorque();
void ClearTorque();
}; };
} }