Added ghost body on character controllers to trigger sensors bodies

This commit is contained in:
Antoine Pilote
2024-04-01 13:05:02 -04:00
parent 7b53e7baaa
commit 72e2b6984e

View File

@@ -74,26 +74,8 @@ namespace Nuake
static constexpr uint8_t KINEMATIC = 2;
static constexpr uint8_t CHARACTER_GHOST = 3;
static constexpr uint8_t CHARACTER = 4;
static constexpr uint8_t NUM_LAYERS = 5;
};
// Function that determines if two object layers can collide
static bool MyObjectCanCollide(JPH::ObjectLayer inObject1, JPH::ObjectLayer inObject2)
{
switch (inObject1)
{
case Layers::NON_MOVING:
return inObject2 == Layers::MOVING || inObject2 == Layers::KINEMATIC || inObject2 == Layers::CHARACTER; // Non moving only collides with moving
case Layers::MOVING:
return true; // Moving collides with everything
case Layers::KINEMATIC:
return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING || inObject2 == Layers::CHARACTER; // Only collides with non moving
case Layers::CHARACTER:
return true;
default:
//JPH_ASSERT(false);
return false;
}
static constexpr uint8_t SENSORS = 5;
static constexpr uint8_t NUM_LAYERS = 6;
};
// Each broadphase layer results in a separate bounding volume tree in the broad phase. You at least want to have
@@ -120,6 +102,7 @@ namespace Nuake
mObjectToBroadPhase[Layers::MOVING] = BroadPhaseLayers::MOVING;
mObjectToBroadPhase[Layers::CHARACTER] = BroadPhaseLayers::MOVING;
mObjectToBroadPhase[Layers::CHARACTER_GHOST] = BroadPhaseLayers::MOVING;
mObjectToBroadPhase[Layers::SENSORS] = BroadPhaseLayers::MOVING;
}
virtual JPH::uint GetNumBroadPhaseLayers() const override
@@ -134,38 +117,10 @@ namespace Nuake
return mObjectToBroadPhase[inLayer];
}
#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
virtual const char* GetBroadPhaseLayerName(BroadPhaseLayer inLayer) const override
{
switch ((BroadPhaseLayer::Type)inLayer)
{
case (BroadPhaseLayer::Type)BroadPhaseLayers::NON_MOVING: return "NON_MOVING";
case (BroadPhaseLayer::Type)BroadPhaseLayers::MOVING: return "MOVING";
default: JPH_ASSERT(false); return "INVALID";
}
}
#endif // JPH_EXTERNAL_PROFILE || JPH_PROFILE_ENABLED
private:
JPH::BroadPhaseLayer mObjectToBroadPhase[Layers::NUM_LAYERS];
};
// Function that determines if two broadphase layers can collide
static bool MyBroadPhaseCanCollide(JPH::ObjectLayer inLayer1, JPH::BroadPhaseLayer inLayer2)
{
using namespace JPH;
switch (inLayer1)
{
case Layers::NON_MOVING:
return inLayer2 == BroadPhaseLayers::MOVING;
case Layers::MOVING:
return true;
default:
JPH_ASSERT(false);
return false;
}
}
// An example contact listener
class MyContactListener : public JPH::ContactListener
{
@@ -230,8 +185,9 @@ namespace Nuake
return inLayer2 == BroadPhaseLayers::MOVING;
case Layers::MOVING:
return true;
case Layers::SENSORS:
return inLayer2 == BroadPhaseLayers::MOVING;;
default:
return false;
}
}
@@ -245,13 +201,15 @@ namespace Nuake
switch (inObject1)
{
case Layers::NON_MOVING:
return inObject2 == Layers::MOVING || Layers::CHARACTER_GHOST; // Non moving only collides with moving
return inObject2 == Layers::MOVING || inObject2 == Layers::CHARACTER_GHOST || inObject2 == Layers::CHARACTER; // Non moving only collides with moving
case Layers::MOVING:
return true; // Moving collides with everything
case Layers::CHARACTER_GHOST:
return true;// inObject2 != Layers::CHARACTER;
return inObject2 != Layers::CHARACTER;
case Layers::CHARACTER:
return inObject2 != Layers::CHARACTER_GHOST;
case Layers::SENSORS:
return inObject2 == Layers::MOVING || inObject2 == Layers::CHARACTER_GHOST;
default:
return false;
@@ -328,14 +286,30 @@ namespace Nuake
layer = Layers::MOVING;
}
if (rb->IsTrigger())
{
layer = Layers::SENSORS;
motionType = JPH::EMotionType::Kinematic;
}
const auto& startPos = rb->GetPosition();
const Quat& bodyRotation = rb->GetRotation();
const auto& joltRotation = JPH::Quat(bodyRotation.x, bodyRotation.y, bodyRotation.z, bodyRotation.w);
const auto& joltPos = JPH::Vec3(startPos.x, startPos.y, startPos.z);
auto joltShape = GetJoltShape(rb->GetShape());
JPH::Ref<JPH::Shape> joltShape = GetJoltShape(rb->GetShape());
if (!joltShape)
{
return;
}
JPH::BodyCreationSettings bodySettings(joltShape, joltPos, joltRotation, motionType, layer);
bodySettings.mIsSensor = rb->IsTrigger();
if (bodySettings.mIsSensor)
{
bodySettings.mCollideKinematicVsNonDynamic = true;
}
bodySettings.mAllowedDOFs = (JPH::EAllowedDOFs::All);
if (rb->GetLockXAxis())
@@ -375,7 +349,6 @@ namespace Nuake
// Create the actual rigid body
JPH::BodyID body = _JoltBodyInterface->CreateAndAddBody(bodySettings, JPH::EActivation::Activate); // Note that if we run out of bodies this can return nullptr
uint32_t bodyIndex = (uint32_t)body.GetIndexAndSequenceNumber();
auto userData = _JoltBodyInterface->GetUserData(body);
_registeredBodies.push_back(bodyIndex);
}
@@ -402,8 +375,8 @@ namespace Nuake
// add ghost kinematic body to respond to hit test as the virtual char are not present in the world.
JPH::BodyInterface& bodyInterface = _JoltPhysicsSystem->GetBodyInterface();
const float mass = 0.1f;
JPH::EMotionType motionType = JPH::EMotionType::Kinematic;
const float mass = 0.0f;
JPH::EMotionType motionType = JPH::EMotionType::Dynamic;
JPH::ObjectLayer layer = Layers::CHARACTER_GHOST;
const auto& startPos = joltPosition;
@@ -416,7 +389,7 @@ namespace Nuake
Logger::Log("ERROR");
}
//bodySettings.mUserData = entityId;
bodySettings.mUserData = 1337;
// Create the actual rigid body
JPH::BodyID body = _JoltBodyInterface->CreateAndAddBody(bodySettings, JPH::EActivation::Activate); // Note that if we run out of bodies this can return nullptr
@@ -506,6 +479,15 @@ namespace Nuake
glm::decompose(transform, scale, rotation, pos, skew, pesp);
auto entId = static_cast<int>(bodyInterface.GetUserData(bodyId));
if (entId == 1337)
{
Entity entity = Engine::GetCurrentScene()->GetEntity("Gizmo");
auto& transformComponent = entity.GetComponent<TransformComponent>();
transformComponent.SetLocalPosition(pos);
transformComponent.SetLocalRotation(Quat(bodyRotation.GetW(), bodyRotation.GetX(), bodyRotation.GetY(), bodyRotation.GetZ()));
transformComponent.SetLocalTransform(transform);
transformComponent.Dirty = true;
}
if (entId != 0)
{
Entity entity = Engine::GetCurrentScene()->GetEntityByID(entId);
@@ -573,7 +555,7 @@ namespace Nuake
if(ts > minStepDuration)
{
#ifdef NK_DEBUG
Logger::Log("Large step detected: " + std::to_string(ts), "physics", WARNING);
//Logger::Log("Large step detected: " + std::to_string(ts), "physics", WARNING);
#endif
collisionSteps = static_cast<float>(ts) / minStepDuration;
}
@@ -624,6 +606,27 @@ namespace Nuake
{
c.second.Character->Update(ts, joltGravity, broadPhaseLayerFilter, LayerFilter, {}, {}, tempAllocatorPtr);
}
uint32_t ghostId = c.second.Ghost;
JPH::Mat44 joltTransform = c.second.Character->GetWorldTransform();
const auto bodyRotation = c.second.Character->GetRotation();
Matrix4 transform = glm::mat4(
joltTransform(0, 0), joltTransform(1, 0), joltTransform(2, 0), joltTransform(3, 0),
joltTransform(0, 1), joltTransform(1, 1), joltTransform(2, 1), joltTransform(3, 1),
joltTransform(0, 2), joltTransform(1, 2), joltTransform(2, 2), joltTransform(3, 2),
joltTransform(0, 3), joltTransform(1, 3), joltTransform(2, 3), joltTransform(3, 3)
);
Vector3 scale = Vector3();
Quat rotation = Quat();
Vector3 pos = Vector3();
Vector3 skew = Vector3();
Vector4 pesp = Vector4();
glm::decompose(transform, scale, rotation, pos, skew, pesp);
//auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterfaceNoLock();
_JoltBodyInterface->MoveKinematic(static_cast<JPH::BodyID>(ghostId), JPH::Vec3{ pos.x, pos.y, pos.z }, { rotation.x, rotation.y, rotation.z, rotation.w }, ts);
}
}
@@ -636,26 +639,7 @@ namespace Nuake
for (auto& c : _registeredCharacters)
{
uint32_t ghostId = c.second.Ghost;
JPH::Mat44 joltTransform = c.second.Character->GetWorldTransform();
const auto bodyRotation = c.second.Character->GetRotation();
Matrix4 transform = glm::mat4(
joltTransform(0, 0), joltTransform(1, 0), joltTransform(2, 0), joltTransform(3, 0),
joltTransform(0, 1), joltTransform(1, 1), joltTransform(2, 1), joltTransform(3, 1),
joltTransform(0, 2), joltTransform(1, 2), joltTransform(2, 2), joltTransform(3, 2),
joltTransform(0, 3), joltTransform(1, 3), joltTransform(2, 3), joltTransform(3, 3)
);
Vector3 scale = Vector3();
Quat rotation = Quat();
Vector3 pos = Vector3();
Vector3 skew = Vector3();
Vector4 pesp = Vector4();
glm::decompose(transform, scale, rotation, pos, skew, pesp);
//auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterfaceNoLock();
_JoltBodyInterface->MoveKinematic(static_cast<JPH::BodyID>(ghostId), JPH::Vec3{ pos.x, pos.y, pos.z }, { rotation.x, rotation.y, rotation.z, rotation.w }, 1.0);
}
SyncEntitiesTranforms();
@@ -693,6 +677,11 @@ namespace Nuake
characterController->SetLinearVelocity(joltVelocity);
auto& ghost = _registeredCharacters[entityHandle].Ghost;
auto ghostPos = _JoltBodyInterface->GetPosition(static_cast<JPH::BodyID>(ghost));
//std::cout << "Ghost pos: " << ghostPos.GetX() << ", " << ghostPos.GetY() << ", " << ghostPos.GetZ() << std::endl;
auto charPos = characterController->GetPosition();
//std::cout << "Char pos: " << charPos.GetX() << ", " << charPos.GetY() << ", " << charPos.GetZ() << std::endl;
//_JoltBodyInterface->SetLinearVelocity(static_cast<JPH::BodyID>(ghost), joltVelocity);
}
}
@@ -800,6 +789,14 @@ namespace Nuake
break;
}
if (!result.IsValid())
{
const std::string errorMessage = std::string("Failed to create physics shape: ") + result.GetError().c_str();
Logger::Log(errorMessage, "physics", WARNING);
return nullptr;
}
return result.Get();
}
}