JoltPhysics3D: Add RaycastQuery and RaycastQueryFirst
This commit is contained in:
parent
707a486e74
commit
b3595178a1
|
|
@ -299,16 +299,21 @@ int main()
|
|||
Nz::Vector3f from = cameraComponent.Unproject({ float(event.x), float(event.y), 0.f });
|
||||
Nz::Vector3f to = cameraComponent.Unproject({ float(event.x), float(event.y), 1.f });
|
||||
|
||||
/*/Nz::Physics3DSystem::RaycastHit lastHitInfo;
|
||||
auto callback = [&](const Nz::Physics3DSystem::RaycastHit& hitInfo) -> std::optional<float>
|
||||
Nz::JoltPhysics3DSystem::RaycastHit lastHitInfo;
|
||||
auto callback = [&](const Nz::JoltPhysics3DSystem::RaycastHit& hitInfo) -> std::optional<float>
|
||||
{
|
||||
if (hitInfo.hitEntity == boxEntity)
|
||||
{
|
||||
Nz::Vector3f dirToCenter = Nz::Vector3f::Zero() - hitInfo.hitPosition;
|
||||
dirToCenter.Normalize();
|
||||
|
||||
#ifdef USE_JOLT
|
||||
if (Nz::Vector3f::DotProduct(dirToCenter, (hitInfo.hitPosition - from).Normalize()) < 0.f)
|
||||
return std::nullopt;
|
||||
#else
|
||||
if (Nz::Vector3f::DotProduct(dirToCenter, hitInfo.hitNormal) < 0.f)
|
||||
return std::nullopt;
|
||||
#endif
|
||||
}
|
||||
|
||||
lastHitInfo = hitInfo;
|
||||
|
|
@ -320,8 +325,8 @@ int main()
|
|||
{
|
||||
if (lastHitInfo.hitBody && lastHitInfo.hitEntity != boxEntity)
|
||||
{
|
||||
grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
||||
grabConstraint->SetImpulseClamp(30.f);
|
||||
//grabConstraint.emplace(*lastHitInfo.hitBody, lastHitInfo.hitPosition);
|
||||
//grabConstraint->SetImpulseClamp(30.f);
|
||||
|
||||
grabbedObjectMove.Connect(eventHandler.OnMouseMoved, [&, body = lastHitInfo.hitBody, distance = Nz::Vector3f::Distance(from, lastHitInfo.hitPosition)](const Nz::WindowEventHandler*, const Nz::WindowEvent::MouseMoveEvent& event)
|
||||
{
|
||||
|
|
@ -329,14 +334,14 @@ int main()
|
|||
Nz::Vector3f to = cameraComponent.Unproject({ float(event.x), float(event.y), 1.f });
|
||||
|
||||
Nz::Vector3f newPosition = from + (to - from).Normalize() * distance;
|
||||
grabConstraint->SetSecondAnchor(newPosition);
|
||||
//grabConstraint->SetSecondAnchor(newPosition);
|
||||
});
|
||||
}
|
||||
else
|
||||
cameraMove.Connect(eventHandler.OnMouseMoved, mouseMoveCallback);
|
||||
}
|
||||
else
|
||||
cameraMove.Connect(eventHandler.OnMouseMoved, mouseMoveCallback);*/
|
||||
cameraMove.Connect(eventHandler.OnMouseMoved, mouseMoveCallback);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ namespace Nz
|
|||
|
||||
inline bool IsBodyActive(UInt32 bodyIndex) const;
|
||||
|
||||
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo = nullptr);
|
||||
bool RaycastQuery(const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const RaycastHit& hitInfo)>& callback);
|
||||
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, const FunctionRef<void(const RaycastHit& hitInfo)>& callback);
|
||||
|
||||
void SetGravity(const Vector3f& gravity);
|
||||
void SetMaxStepCount(std::size_t maxStepCount);
|
||||
|
|
@ -63,7 +64,6 @@ namespace Nz
|
|||
float fraction;
|
||||
JoltRigidBody3D* hitBody = nullptr;
|
||||
Vector3f hitPosition;
|
||||
Vector3f hitNormal;
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@ namespace Nz
|
|||
inline JoltPhysWorld3D& GetPhysWorld();
|
||||
inline const JoltPhysWorld3D& GetPhysWorld() const;
|
||||
|
||||
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, RaycastHit* hitInfo = nullptr);
|
||||
bool RaycastQuery(const Vector3f& from, const Vector3f& to, const FunctionRef<std::optional<float>(const RaycastHit& hitInfo)>& callback);
|
||||
bool RaycastQueryFirst(const Vector3f& from, const Vector3f& to, const FunctionRef<void(const RaycastHit& hitInfo)>& callback);
|
||||
|
||||
void Update(Time elapsedTime);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue