Refactored Raycasting, Added Layers for Raycasting to C#, Fixed Collision Tag Panel #331

Merged
direnbharwani merged 10 commits from SP3-2-Physics into main 2023-02-03 16:26:07 +08:00
15 changed files with 499 additions and 92 deletions
Showing only changes of commit b6d91d5492 - Show all commits

View File

@ -1,16 +1,16 @@
0 1 0 1 3
1 2 1 2 65535
2 3 2 3 65534
3 4 3 4 65534
4 5 4 5 65534
5 6 5 6 65534
6 7 6 7 65534
7 8 7 8 65534
8 9 8 9 65534
9 10 9 10 65534
10 11 10 11 65534
11 12 11 12 65534
12 13 12 13 65534
13 14 13 14 65534
14 15 14 15 65534
15 16 15 16 65534

File diff suppressed because it is too large Load Diff

View File

@ -4,8 +4,8 @@
NumberOfChildren: 0 NumberOfChildren: 0
Components: Components:
Transform Component: Transform Component:
Translate: {x: 2, y: 0, z: 0} Translate: {x: 2, y: 2, z: 0}
Rotate: {x: 0, y: 0, z: 0} Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1} Scale: {x: 1, y: 1, z: 1}
IsActive: true IsActive: true
RigidBody Component: RigidBody Component:
@ -58,8 +58,8 @@
NumberOfChildren: 0 NumberOfChildren: 0
Components: Components:
Transform Component: Transform Component:
Translate: {x: 0, y: -3, z: 0} Translate: {x: 0, y: 0, z: 0}
Rotate: {x: 0, y: 0, z: 0} Rotate: {x: -0, y: 0, z: -0}
Scale: {x: 1, y: 1, z: 1} Scale: {x: 1, y: 1, z: 1}
IsActive: true IsActive: true
RigidBody Component: RigidBody Component:
@ -79,7 +79,7 @@
Collider Component: Collider Component:
Colliders: Colliders:
- Is Trigger: false - Is Trigger: false
Collision Tag: 1 Collision Tag: 3
Type: Sphere Type: Sphere
Radius: 1 Radius: 1
Friction: 0.400000006 Friction: 0.400000006
@ -88,7 +88,7 @@
Position Offset: {x: 0, y: 0, z: 0} Position Offset: {x: 0, y: 0, z: 0}
Rotation Offset: {x: 0, y: 0, z: 0} Rotation Offset: {x: 0, y: 0, z: 0}
- Is Trigger: false - Is Trigger: false
Collision Tag: 1 Collision Tag: 2
Type: Box Type: Box
Half Extents: {x: 1, y: 1, z: 1} Half Extents: {x: 1, y: 1, z: 1}
Friction: 0.400000006 Friction: 0.400000006

View File

@ -14,18 +14,36 @@
// Primary Header // Primary Header
#include "SHCollisionTagMatrix.h" #include "SHCollisionTagMatrix.h"
#include "Tools/Utilities/SHUtilities.h"
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Data Member Definitions */ /* Static Data Member Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHCollisionTagMatrix::dirty = true;
SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS]; SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS];
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHCollisionTagMatrix::IsDirty() noexcept
{
// Check if any collision tag is dirty
for (auto& tag : collisionTags)
{
if (tag.IsDirty())
{
dirty = true;
break;
}
}
return dirty;
}
const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex) const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex)
{ {
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
@ -91,6 +109,8 @@ namespace SHADE
if (collisionTag.GetName() != tagName) if (collisionTag.GetName() != tagName)
continue; continue;
dirty = true;
collisionTag = newTag; collisionTag = newTag;
return; return;
} }
@ -105,6 +125,8 @@ namespace SHADE
if (collisionTag.GetName() != tagName) if (collisionTag.GetName() != tagName)
continue; continue;
dirty = true;
collisionTag.SetMask(mask); collisionTag.SetMask(mask);
return; return;
} }
@ -125,6 +147,8 @@ namespace SHADE
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!"); throw std::invalid_argument("Index out of range!");
dirty = true;
collisionTags[tagIndex] = newTag; collisionTags[tagIndex] = newTag;
} }
@ -133,6 +157,8 @@ namespace SHADE
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS) if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
throw std::invalid_argument("Index out of range!"); throw std::invalid_argument("Index out of range!");
dirty = true;
collisionTags[tagIndex].SetMask(mask); collisionTags[tagIndex].SetMask(mask);
} }
@ -145,8 +171,9 @@ namespace SHADE
/** /**
* I HATE FILE IO * I HATE FILE IO
* *
* Each line in the file should be "index<space>tag name". * Each line in the file should be "index<space>tag name<space>mask".
* If the line fails to follow this format, use the default tag name (index + 1) * If the line fails to follow this format, use the default tag name (index + 1) and default mask.
* If no mask was read, use a default mask.
*/ */
// Populate tag names with default // Populate tag names with default
@ -187,18 +214,40 @@ namespace SHADE
{ {
SHLOG_ERROR SHLOG_ERROR
( (
"Collision tag file line {} does not match the required format of 'index<space>tag name'. Default tag used for index {}" "Collision tag file line {} does not match the required format of 'index<space>tag name<space>mask'. Default tag used for index {}"
, linesRead + 1 , linesRead + 1
, tagIndex , tagIndex
) )
// Use default // Use default
collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1)); collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1));
collisionTags[tagIndex].SetMask(SHUtilities::ConvertEnum(SHCollisionTag::Layer::ALL));
continue; continue;
} }
collisionTags[tagIndex].SetName(tagName); collisionTags[tagIndex].SetName(tagName);
// Next element is the mask value
std::string maskString;
ss >> maskString;
uint16_t mask = std::numeric_limits<uint16_t>::max();
if (maskString.empty())
{
SHLOG_ERROR
(
"Collision tag file line {} does not match the required format of 'index<space>tag name<space>mask'. Default mask used for index {}"
, linesRead + 1
, tagIndex
)
}
else
{
mask = static_cast<uint16_t>(std::stoi(maskString));
}
collisionTags[tagIndex].SetMask(mask);
ss.clear(); ss.clear();
} }
@ -215,9 +264,19 @@ namespace SHADE
return; return;
} }
// Index Name Mask
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i) for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
collisionTagNamesFile << i << " " << collisionTags[i].GetName() << std::endl; collisionTagNamesFile << i << " " << collisionTags[i].GetName() << " " << collisionTags[i].GetMask() << std::endl;
collisionTagNamesFile.close(); collisionTagNamesFile.close();
} }
void SHCollisionTagMatrix::Clear() noexcept
{
dirty = false;
for (auto& tag : collisionTags)
tag.dirty = false;
}
} // namespace SHADE } // namespace SHADE

View File

@ -29,6 +29,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] static bool IsDirty () noexcept;
[[nodiscard]] static const std::string& GetTagName (int tagIndex); [[nodiscard]] static const std::string& GetTagName (int tagIndex);
[[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept; [[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept;
@ -57,11 +58,18 @@ namespace SHADE
static void Init (const std::filesystem::path& tagNameFilePath) noexcept; static void Init (const std::filesystem::path& tagNameFilePath) noexcept;
static void Exit (const std::filesystem::path& tagNameFilePath) noexcept; static void Exit (const std::filesystem::path& tagNameFilePath) noexcept;
/**
* @brief
* Clears the dirty flag.
*/
static void Clear () noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
static bool dirty;
static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS]; static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS];
}; };
} }

View File

@ -23,15 +23,18 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
SHCollisionTag::SHCollisionTag() noexcept SHCollisionTag::SHCollisionTag() noexcept
: mask { SHUtilities::ConvertEnum(Layer::ALL) } : dirty { true }
, mask { SHUtilities::ConvertEnum(Layer::ALL) }
{} {}
SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept
: mask { _mask } : dirty { true }
, mask { _mask }
{} {}
SHCollisionTag::SHCollisionTag(Layer layer) noexcept SHCollisionTag::SHCollisionTag(Layer layer) noexcept
: mask { SHUtilities::ConvertEnum(layer) } : dirty { true }
, mask { SHUtilities::ConvertEnum(layer) }
{} {}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -57,6 +60,11 @@ namespace SHADE
/* Getter Function Definitions */ /* Getter Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
bool SHCollisionTag::IsDirty() const noexcept
{
return dirty;
}
uint16_t SHCollisionTag::GetMask() const noexcept uint16_t SHCollisionTag::GetMask() const noexcept
{ {
return mask; return mask;
@ -86,6 +94,7 @@ namespace SHADE
void SHCollisionTag::SetMask(uint16_t newMask) noexcept void SHCollisionTag::SetMask(uint16_t newMask) noexcept
{ {
dirty = true;
mask = newMask; mask = newMask;
} }
@ -96,6 +105,8 @@ namespace SHADE
void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept
{ {
dirty = true;
const auto VALUE = SHUtilities::ConvertEnum(layer); const auto VALUE = SHUtilities::ConvertEnum(layer);
state ? mask |= VALUE : mask &= ~(VALUE); state ? mask |= VALUE : mask &= ~(VALUE);
} }
@ -105,6 +116,8 @@ namespace SHADE
if (layerIndex < 0 || layerIndex > NUM_LAYERS) if (layerIndex < 0 || layerIndex > NUM_LAYERS)
throw std::invalid_argument("Index out of range!"); throw std::invalid_argument("Index out of range!");
dirty = true;
const auto VALUE = 1U << layerIndex; const auto VALUE = 1U << layerIndex;
state ? mask |= (VALUE) : mask &= ~(VALUE); state ? mask |= (VALUE) : mask &= ~(VALUE);
} }

View File

@ -23,6 +23,13 @@ namespace SHADE
class SH_API SHCollisionTag class SH_API SHCollisionTag
{ {
private:
/*---------------------------------------------------------------------------------*/
/* Friends */
/*---------------------------------------------------------------------------------*/
friend class SHCollisionTagMatrix;
public: public:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -82,6 +89,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
[[nodiscard]] bool IsDirty () const noexcept;
[[nodiscard]] uint16_t GetMask () const noexcept; [[nodiscard]] uint16_t GetMask () const noexcept;
[[nodiscard]] const std::string& GetName () const noexcept; [[nodiscard]] const std::string& GetName () const noexcept;
[[nodiscard]] bool GetLayerState (Layer layer) const noexcept; [[nodiscard]] bool GetLayerState (Layer layer) const noexcept;
@ -101,6 +109,7 @@ namespace SHADE
/* Data Members */ /* Data Members */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
bool dirty;
uint16_t mask; uint16_t mask;
std::string name; std::string name;
}; };

View File

@ -102,11 +102,7 @@ namespace SHADE
const SHTransform& PARENT_TRANSFORM = collider->GetTransform(); const SHTransform& PARENT_TRANSFORM = collider->GetTransform();
SetScale(PARENT_TRANSFORM.scale); SetScale(PARENT_TRANSFORM.scale);
if (rp3dCollider) SHCollisionShape::Update();
{
const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) };
rp3dCollider->setLocalToBodyTransform(OFFSETS);
}
} }

View File

@ -118,6 +118,9 @@ namespace SHADE
void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept
{ {
collisionTag = newCollisionTag; collisionTag = newCollisionTag;
if (rp3dCollider)
rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask());
} }
void SHCollisionShape::SetFriction(float friction) noexcept void SHCollisionShape::SetFriction(float friction) noexcept
@ -184,6 +187,13 @@ namespace SHADE
/* Public Member Function Definitions */ /* Public Member Function Definitions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
void SHCollisionShape::UpdateCollisionTags() noexcept
{
if (collisionTag->IsDirty())
rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask());
}
void SHCollisionShape::Update() noexcept void SHCollisionShape::Update() noexcept
{ {
if (rp3dCollider) if (rp3dCollider)

View File

@ -123,6 +123,12 @@ namespace SHADE
/* Member Functions */ /* Member Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/**
* @brief
* Re-sets the collision tags if it is dirty.
*/
void UpdateCollisionTags() noexcept;
/** /**
* @brief * @brief
* Computes the transform of the shape. * Computes the transform of the shape.

View File

@ -105,11 +105,7 @@ namespace SHADE
const float SPHERE_SCALE = std::fabs(SHMath::Max({ PARENT_TRANSFORM.scale.x, PARENT_TRANSFORM.scale.y, PARENT_TRANSFORM.scale.z })); const float SPHERE_SCALE = std::fabs(SHMath::Max({ PARENT_TRANSFORM.scale.x, PARENT_TRANSFORM.scale.y, PARENT_TRANSFORM.scale.z }));
SetScale(SPHERE_SCALE); SetScale(SPHERE_SCALE);
if (rp3dCollider) SHCollisionShape::Update();
{
const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) };
rp3dCollider->setLocalToBodyTransform(OFFSETS);
}
} }

View File

@ -15,6 +15,7 @@
// Project Headers // Project Headers
#include "Math/Transform/SHTransformComponent.h" #include "Math/Transform/SHTransformComponent.h"
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
#include "Physics/Collision/Shapes/SHSphere.h" #include "Physics/Collision/Shapes/SHSphere.h"
#include "Physics/Collision/Shapes/SHBox.h" #include "Physics/Collision/Shapes/SHBox.h"
#include "Physics/Interface/SHColliderComponent.h" #include "Physics/Interface/SHColliderComponent.h"
@ -385,6 +386,11 @@ namespace SHADE
} }
default: break; default: break;
} }
collisionShape->SetMaterial(collisionShape->GetMaterial());
const auto& COLLISION_TAG = collisionShape->GetCollisionTag();
collisionShape->SetCollisionTag(SHCollisionTagMatrix::GetTag(COLLISION_TAG.GetName()));
} }
physicsObject->body->updateMassPropertiesFromColliders(); physicsObject->body->updateMassPropertiesFromColliders();

View File

@ -272,6 +272,12 @@ namespace SHADE
shape->Update(); shape->Update();
} }
void SHColliderComponent::UpdateCollisionTags() noexcept
{
for (auto& shape : shapes)
shape->UpdateCollisionTags();
}
} // namespace SHADE } // namespace SHADE

View File

@ -158,6 +158,12 @@ namespace SHADE
*/ */
void Update () noexcept; void Update () noexcept;
/**
* @brief
* Re-sets any dirty collision tags on collision shapes.
*/
void UpdateCollisionTags () noexcept;
private: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/

View File

@ -36,6 +36,9 @@ namespace SHADE
{ {
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem()); auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
// Update colliders since collision tag has changed
const bool UPDATE_COLLISION_TAGS = SHCollisionTagMatrix::IsDirty();
// Get all physics objects & sync transforms // Get all physics objects & sync transforms
auto& physicsObjects = physicsSystem->objectManager.GetPhysicsObjects(); auto& physicsObjects = physicsSystem->objectManager.GetPhysicsObjects();
for (auto& [entityID, physicsObject] : physicsObjects) for (auto& [entityID, physicsObject] : physicsObjects)
@ -44,14 +47,16 @@ namespace SHADE
// Assume transform is always active // Assume transform is always active
const bool UPDATE_TRANSFORM = TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged(); const bool UPDATE_TRANSFORM = TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged();
if (!UPDATE_TRANSFORM)
continue;
// We assume that all engine components and physics object components have been successfully linked // We assume that all engine components and physics object components have been successfully linked
if (!physicsObject.body) if (!physicsObject.body)
continue; continue;
auto* shadeBody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
auto* shadeCollider = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
if (UPDATE_TRANSFORM)
{
// Set body transform // Set body transform
const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition(); const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition();
const SHQuaternion& WORLD_ROT = TRANSFORM_COMPONENT->GetWorldOrientation(); const SHQuaternion& WORLD_ROT = TRANSFORM_COMPONENT->GetWorldOrientation();
@ -60,7 +65,7 @@ namespace SHADE
physicsObject.body->setTransform(NEW_TRANSFORM); physicsObject.body->setTransform(NEW_TRANSFORM);
// Sync rigid body active states if one exists // Sync rigid body active states if one exists
if (auto* shadeBody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID); shadeBody) if (shadeBody)
{ {
const bool SHADE_BODY_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID); const bool SHADE_BODY_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID);
const bool RP3D_BODY_ACTIVE = physicsObject.body->isActive(); const bool RP3D_BODY_ACTIVE = physicsObject.body->isActive();
@ -73,7 +78,7 @@ namespace SHADE
} }
// Sync collider active states if one exists // Sync collider active states if one exists
if (auto* shadeCollider = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID); shadeCollider) if (shadeCollider)
{ {
const bool SHADE_COLLIDER_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(entityID); const bool SHADE_COLLIDER_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(entityID);
const bool RP3D_COLLIDERS_ACTIVE = shadeCollider->flags & SHColliderComponent::ACTIVE_FLAG; const bool RP3D_COLLIDERS_ACTIVE = shadeCollider->flags & SHColliderComponent::ACTIVE_FLAG;
@ -90,6 +95,13 @@ namespace SHADE
shadeCollider->Update(); shadeCollider->Update();
} }
} }
if (UPDATE_COLLISION_TAGS && shadeCollider)
shadeCollider->UpdateCollisionTags();
}
// Clear collision tag dirty flags
SHCollisionTagMatrix::Clear();
} }
} // namespace SHADE } // namespace SHADE