JoltPhysics3D: Add RaycastQuery and RaycastQueryFirst
This commit is contained in:
committed by
Jérôme Leclercq
parent
707a486e74
commit
b3595178a1
@@ -11,6 +11,9 @@
|
||||
#include <NazaraUtils/StackVector.hpp>
|
||||
#include <Jolt/Jolt.h>
|
||||
#include <Jolt/Core/TempAllocator.h>
|
||||
#include <Jolt/Physics/Collision/CastResult.h>
|
||||
#include <Jolt/Physics/Collision/CollisionCollectorImpl.h>
|
||||
#include <Jolt/Physics/Collision/RayCast.h>
|
||||
#include <Jolt/Physics/Collision/ObjectLayer.h>
|
||||
#include <Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h>
|
||||
#include <Jolt/Physics/PhysicsSettings.h>
|
||||
@@ -157,6 +160,59 @@ namespace DitchMeAsap
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace NAZARA_ANONYMOUS_NAMESPACE
|
||||
{
|
||||
class CallbackHitResult : public JPH::RayCastBodyCollector
|
||||
{
|
||||
public:
|
||||
CallbackHitResult(const JPH::BodyLockInterface& bodyLockInterface, const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const JoltPhysWorld3D::RaycastHit& hitInfo)>& callback) :
|
||||
m_bodyLockInterface(bodyLockInterface),
|
||||
m_callback(callback),
|
||||
m_from(from),
|
||||
m_to(to),
|
||||
m_didHit(false)
|
||||
{
|
||||
}
|
||||
|
||||
void AddHit(const JPH::BroadPhaseCastResult& result) override
|
||||
{
|
||||
JoltPhysWorld3D::RaycastHit hitInfo;
|
||||
hitInfo.fraction = result.mFraction;
|
||||
hitInfo.hitPosition = Lerp(m_from, m_to, result.mFraction);
|
||||
|
||||
JPH::BodyLockWrite lock(m_bodyLockInterface, result.mBodyID);
|
||||
if (!lock.Succeeded())
|
||||
return; //< body was destroyed
|
||||
|
||||
hitInfo.hitBody = reinterpret_cast<JoltRigidBody3D*>(static_cast<std::uintptr_t>(lock.GetBody().GetUserData()));
|
||||
|
||||
if (auto fractionOpt = m_callback(hitInfo))
|
||||
{
|
||||
float fraction = fractionOpt.value();
|
||||
if (fraction > 0.f)
|
||||
{
|
||||
m_didHit = true;
|
||||
UpdateEarlyOutFraction(fraction);
|
||||
}
|
||||
else
|
||||
ForceEarlyOut();
|
||||
}
|
||||
}
|
||||
|
||||
bool DidHit() const
|
||||
{
|
||||
return m_didHit;
|
||||
}
|
||||
|
||||
private:
|
||||
const JPH::BodyLockInterface& m_bodyLockInterface;
|
||||
const FunctionRef<std::optional<float>(const JoltPhysWorld3D::RaycastHit& hitInfo)>& m_callback;
|
||||
Vector3f m_from;
|
||||
Vector3f m_to;
|
||||
bool m_didHit;
|
||||
};
|
||||
}
|
||||
|
||||
class JoltPhysWorld3D::BodyActivationListener : public JPH::BodyActivationListener
|
||||
{
|
||||
public:
|
||||
@@ -256,27 +312,40 @@ namespace Nz
|
||||
return m_stepSize;
|
||||
}
|
||||
|
||||
bool JoltPhysWorld3D::RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo)
|
||||
bool JoltPhysWorld3D::RaycastQuery(const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const RaycastHit& hitInfo)>& callback)
|
||||
{
|
||||
return false;
|
||||
/*
|
||||
btCollisionWorld::ClosestRayResultCallback callback(ToBullet(from), ToBullet(to));
|
||||
m_world->dynamicWorld.rayTest(ToBullet(from), ToBullet(to), callback);
|
||||
JPH::RayCast rayCast;
|
||||
rayCast.mDirection = ToJolt(to - from);
|
||||
rayCast.mOrigin = ToJolt(from);
|
||||
|
||||
if (!callback.hasHit())
|
||||
CallbackHitResult collector(m_world->physicsSystem.GetBodyLockInterface(), from, to, callback);
|
||||
m_world->physicsSystem.GetBroadPhaseQuery().CastRay(rayCast, collector);
|
||||
|
||||
return collector.DidHit();
|
||||
}
|
||||
|
||||
bool JoltPhysWorld3D::RaycastQueryFirst(const Vector3f& from, const Vector3f& to, const FunctionRef<void(const RaycastHit& hitInfo)>& callback)
|
||||
{
|
||||
JPH::RayCast rayCast;
|
||||
rayCast.mDirection = ToJolt(to - from);
|
||||
rayCast.mOrigin = ToJolt(from);
|
||||
|
||||
JPH::ClosestHitCollisionCollector<JPH::RayCastBodyCollector> collector;
|
||||
m_world->physicsSystem.GetBroadPhaseQuery().CastRay(rayCast, collector);
|
||||
|
||||
if (!collector.HadHit())
|
||||
return false;
|
||||
|
||||
if (hitInfo)
|
||||
{
|
||||
hitInfo->fraction = callback.m_closestHitFraction;
|
||||
hitInfo->hitNormal = FromBullet(callback.m_hitNormalWorld);
|
||||
hitInfo->hitPosition = FromBullet(callback.m_hitPointWorld);
|
||||
JPH::BodyLockWrite lock(m_world->physicsSystem.GetBodyLockInterface(), collector.mHit.mBodyID);
|
||||
if (!lock.Succeeded())
|
||||
return false; //< body was destroyed before lock
|
||||
|
||||
if (const btRigidBody* body = btRigidBody::upcast(callback.m_collisionObject))
|
||||
hitInfo->hitBody = static_cast<BulletRigidBody3D*>(body->getUserPointer());
|
||||
}
|
||||
RaycastHit hitInfo;
|
||||
hitInfo.fraction = collector.mHit.GetEarlyOutFraction();
|
||||
hitInfo.hitPosition = Lerp(from, to, hitInfo.fraction);
|
||||
hitInfo.hitBody = reinterpret_cast<JoltRigidBody3D*>(static_cast<std::uintptr_t>(lock.GetBody().GetUserData()));
|
||||
|
||||
return true;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoltPhysWorld3D::SetGravity(const Vector3f& gravity)
|
||||
|
||||
@@ -53,6 +53,8 @@ namespace Nz
|
||||
m_bodyIndex(object.m_bodyIndex),
|
||||
m_world(object.m_world)
|
||||
{
|
||||
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||
|
||||
object.m_body = nullptr;
|
||||
object.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
||||
}
|
||||
@@ -333,6 +335,8 @@ namespace Nz
|
||||
m_geom = std::move(object.m_geom);
|
||||
m_world = object.m_world;
|
||||
|
||||
m_body->SetUserData(SafeCast<UInt64>(reinterpret_cast<std::uintptr_t>(this)));
|
||||
|
||||
object.m_body = nullptr;
|
||||
object.m_bodyIndex = std::numeric_limits<UInt32>::max();
|
||||
|
||||
|
||||
@@ -46,19 +46,40 @@ namespace Nz
|
||||
m_updateTime = Time::Zero();
|
||||
}
|
||||
|
||||
bool JoltPhysics3DSystem::RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo)
|
||||
bool JoltPhysics3DSystem::RaycastQuery(const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const RaycastHit& hitInfo)>& callback)
|
||||
{
|
||||
if (!m_physWorld.RaycastQueryFirst(from, to, hitInfo))
|
||||
return false;
|
||||
|
||||
/*if (hitInfo->hitBody)
|
||||
return m_physWorld.RaycastQuery(from, to, [&](const JoltPhysWorld3D::RaycastHit& hitInfo)
|
||||
{
|
||||
std::size_t uniqueIndex = hitInfo->hitBody->GetUniqueIndex();
|
||||
if (uniqueIndex < m_physicsEntities.size())
|
||||
hitInfo->hitEntity = entt::handle(m_registry, m_physicsEntities[uniqueIndex]);
|
||||
}*/
|
||||
RaycastHit extendedHitInfo;
|
||||
static_cast<JoltPhysWorld3D::RaycastHit&>(extendedHitInfo) = hitInfo;
|
||||
|
||||
return true;
|
||||
if (extendedHitInfo.hitBody)
|
||||
{
|
||||
std::size_t bodyIndex = extendedHitInfo.hitBody->GetBodyIndex();
|
||||
if (bodyIndex < m_physicsEntities.size())
|
||||
extendedHitInfo.hitEntity = entt::handle(m_registry, m_physicsEntities[bodyIndex]);
|
||||
}
|
||||
|
||||
return callback(extendedHitInfo);
|
||||
});
|
||||
}
|
||||
|
||||
bool JoltPhysics3DSystem::RaycastQueryFirst(const Vector3f& from, const Vector3f& to, const FunctionRef<void(const RaycastHit& hitInfo)>& callback)
|
||||
{
|
||||
return m_physWorld.RaycastQueryFirst(from, to, [&](const JoltPhysWorld3D::RaycastHit& hitInfo)
|
||||
{
|
||||
RaycastHit extendedHitInfo;
|
||||
static_cast<JoltPhysWorld3D::RaycastHit&>(extendedHitInfo) = hitInfo;
|
||||
|
||||
if (extendedHitInfo.hitBody)
|
||||
{
|
||||
std::size_t bodyIndex = extendedHitInfo.hitBody->GetBodyIndex();
|
||||
if (bodyIndex < m_physicsEntities.size())
|
||||
extendedHitInfo.hitEntity = entt::handle(m_registry, m_physicsEntities[bodyIndex]);
|
||||
}
|
||||
|
||||
callback(extendedHitInfo);
|
||||
});
|
||||
}
|
||||
|
||||
void JoltPhysics3DSystem::Update(Time elapsedTime)
|
||||
|
||||
Reference in New Issue
Block a user