Merge remote-tracking branch 'refs/remotes/origin/master' into reflection-mapping
This commit is contained in:
@@ -142,13 +142,15 @@ namespace Nz
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Wait until any registered socket switches to a ready state
|
||||
* \brief Wait until any registered socket switches to a ready state.
|
||||
*
|
||||
* Waits a specific/undetermined amount of time until at least one socket part of the SocketPoller becomes ready.
|
||||
* To query the ready state of the registered socket, use the IsReady function.
|
||||
*
|
||||
* \param msTimeout Maximum time to wait in milliseconds, 0 for infinity
|
||||
*
|
||||
* \return True if at least one socket registered to the poller is ready.
|
||||
*
|
||||
* \remark It is an error to try to unregister a non-registered socket from a SocketPoller.
|
||||
*
|
||||
* \see IsReady
|
||||
|
||||
@@ -13,9 +13,12 @@ namespace Nz
|
||||
|
||||
std::vector<cpShape*> Collider2D::GenerateShapes(RigidBody2D* body) const
|
||||
{
|
||||
cpShapeFilter filter = cpShapeFilterNew(m_collisionGroup, m_categoryMask, m_collisionMask);
|
||||
|
||||
std::vector<cpShape*> shapes = CreateShapes(body);
|
||||
for (cpShape* shape : shapes)
|
||||
{
|
||||
cpShapeSetFilter(shape, filter);
|
||||
cpShapeSetCollisionType(shape, m_collisionId);
|
||||
cpShapeSetSensor(shape, (m_trigger) ? cpTrue : cpFalse);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,102 @@ namespace Nz
|
||||
return m_stepSize;
|
||||
}
|
||||
|
||||
bool PhysWorld2D::NearestBodyQuery(const Vector2f & from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RigidBody2D** nearestBody)
|
||||
{
|
||||
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||
|
||||
if (cpShape* shape = cpSpacePointQueryNearest(m_handle, {from.x, from.y}, maxDistance, filter, nullptr))
|
||||
{
|
||||
if (nearestBody)
|
||||
*nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PhysWorld2D::NearestBodyQuery(const Vector2f& from, float maxDistance, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, NearestQueryResult* result)
|
||||
{
|
||||
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||
|
||||
if (result)
|
||||
{
|
||||
cpPointQueryInfo queryInfo;
|
||||
|
||||
if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, &queryInfo))
|
||||
{
|
||||
result->closestPoint.Set(queryInfo.point.x, queryInfo.point.y);
|
||||
result->distance = queryInfo.distance;
|
||||
result->fraction.Set(queryInfo.gradient.x, queryInfo.gradient.y);
|
||||
result->nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpShape* shape = cpSpacePointQueryNearest(m_handle, { from.x, from.y }, maxDistance, filter, nullptr))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool PhysWorld2D::RaycastQuery(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, std::vector<RaycastHit>* hitInfos)
|
||||
{
|
||||
auto callback = [](cpShape* shape, cpVect point, cpVect normal, cpFloat alpha, void* data)
|
||||
{
|
||||
std::vector<RaycastHit>* results = reinterpret_cast<std::vector<RaycastHit>*>(data);
|
||||
|
||||
RaycastHit hitInfo;
|
||||
hitInfo.fraction = alpha;
|
||||
hitInfo.hitNormal.Set(normal.x, normal.y);
|
||||
hitInfo.hitPos.Set(point.x, point.y);
|
||||
hitInfo.nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(shape));
|
||||
|
||||
results->emplace_back(std::move(hitInfo));
|
||||
};
|
||||
|
||||
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||
|
||||
std::size_t previousSize = hitInfos->size();
|
||||
cpSpaceSegmentQuery(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, callback, hitInfos);
|
||||
|
||||
return hitInfos->size() != previousSize;
|
||||
}
|
||||
|
||||
bool PhysWorld2D::RaycastQueryFirst(const Nz::Vector2f& from, const Nz::Vector2f& to, float radius, Nz::UInt32 collisionGroup, Nz::UInt32 categoryMask, Nz::UInt32 collisionMask, RaycastHit* hitInfo)
|
||||
{
|
||||
cpShapeFilter filter = cpShapeFilterNew(collisionGroup, categoryMask, collisionMask);
|
||||
|
||||
if (hitInfo)
|
||||
{
|
||||
cpSegmentQueryInfo queryInfo;
|
||||
|
||||
if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, &queryInfo))
|
||||
{
|
||||
hitInfo->fraction = queryInfo.alpha;
|
||||
hitInfo->hitNormal.Set(queryInfo.normal.x, queryInfo.normal.y);
|
||||
hitInfo->hitPos.Set(queryInfo.point.x, queryInfo.point.y);
|
||||
hitInfo->nearestBody = static_cast<Nz::RigidBody2D*>(cpShapeGetUserData(queryInfo.shape));
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpShape* shape = cpSpaceSegmentQueryFirst(m_handle, { from.x, from.y }, { to.x, to.y }, radius, filter, nullptr))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void PhysWorld2D::RegisterCallbacks(unsigned int collisionId, const Callback& callbacks)
|
||||
{
|
||||
InitCallbacks(cpSpaceAddWildcardHandler(m_handle, collisionId), callbacks);
|
||||
@@ -63,7 +159,22 @@ namespace Nz
|
||||
|
||||
while (m_timestepAccumulator >= m_stepSize)
|
||||
{
|
||||
OnPhysWorld2DPreStep(this);
|
||||
|
||||
cpSpaceStep(m_handle, m_stepSize);
|
||||
|
||||
OnPhysWorld2DPostStep(this);
|
||||
if (!m_rigidPostSteps.empty())
|
||||
{
|
||||
for (const auto& pair : m_rigidPostSteps)
|
||||
{
|
||||
for (const auto& step : pair.second.funcs)
|
||||
step(pair.first);
|
||||
}
|
||||
|
||||
m_rigidPostSteps.clear();
|
||||
}
|
||||
|
||||
m_timestepAccumulator -= m_stepSize;
|
||||
}
|
||||
}
|
||||
@@ -162,4 +273,41 @@ namespace Nz
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void PhysWorld2D::OnRigidBodyMoved(RigidBody2D* oldPointer, RigidBody2D* newPointer)
|
||||
{
|
||||
auto it = m_rigidPostSteps.find(oldPointer);
|
||||
if (it == m_rigidPostSteps.end())
|
||||
return; //< Shouldn't happen
|
||||
|
||||
m_rigidPostSteps.emplace(std::make_pair(newPointer, std::move(it->second)));
|
||||
m_rigidPostSteps.erase(oldPointer);
|
||||
}
|
||||
|
||||
void PhysWorld2D::OnRigidBodyRelease(RigidBody2D* rigidBody)
|
||||
{
|
||||
m_rigidPostSteps.erase(rigidBody);
|
||||
}
|
||||
|
||||
void PhysWorld2D::RegisterPostStep(RigidBody2D* rigidBody, PostStep&& func)
|
||||
{
|
||||
// If space isn't locked, no need to wait
|
||||
if (!cpSpaceIsLocked(m_handle))
|
||||
{
|
||||
func(rigidBody);
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = m_rigidPostSteps.find(rigidBody);
|
||||
if (it == m_rigidPostSteps.end())
|
||||
{
|
||||
PostStepContainer postStep;
|
||||
postStep.onMovedSlot.Connect(rigidBody->OnRigidBody2DMove, this, &PhysWorld2D::OnRigidBodyMoved);
|
||||
postStep.onReleaseSlot.Connect(rigidBody->OnRigidBody2DRelease, this, &PhysWorld2D::OnRigidBodyRelease);
|
||||
|
||||
it = m_rigidPostSteps.insert(std::make_pair(rigidBody, std::move(postStep))).first;
|
||||
}
|
||||
|
||||
it->second.funcs.emplace_back(std::move(func));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,8 @@ namespace Nz
|
||||
m_mass(object.m_mass)
|
||||
{
|
||||
cpBodySetUserData(m_handle, this);
|
||||
for (cpShape* shape : m_shapes)
|
||||
cpShapeSetUserData(shape, this);
|
||||
|
||||
object.m_handle = nullptr;
|
||||
|
||||
@@ -93,6 +95,25 @@ namespace Nz
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody2D::AddImpulse(const Vector2f& impulse, CoordSys coordSys)
|
||||
{
|
||||
return AddImpulse(impulse, GetCenterOfGravity(coordSys), coordSys);
|
||||
}
|
||||
|
||||
void RigidBody2D::AddImpulse(const Vector2f& impulse, const Vector2f& point, CoordSys coordSys)
|
||||
{
|
||||
switch (coordSys)
|
||||
{
|
||||
case CoordSys_Global:
|
||||
cpBodyApplyImpulseAtWorldPoint(m_handle, cpv(impulse.x, impulse.y), cpv(point.x, point.y));
|
||||
break;
|
||||
|
||||
case CoordSys_Local:
|
||||
cpBodyApplyImpulseAtLocalPoint(m_handle, cpv(impulse.x, impulse.y), cpv(point.x, point.y));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RigidBody2D::AddTorque(float torque)
|
||||
{
|
||||
cpBodySetTorque(m_handle, cpBodyGetTorque(m_handle) + torque);
|
||||
@@ -210,7 +231,10 @@ namespace Nz
|
||||
|
||||
cpSpace* space = m_world->GetHandle();
|
||||
for (cpShape* shape : m_shapes)
|
||||
{
|
||||
cpShapeSetUserData(shape, this);
|
||||
cpSpaceAddShape(space, shape);
|
||||
}
|
||||
|
||||
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
|
||||
}
|
||||
@@ -221,20 +245,26 @@ namespace Nz
|
||||
{
|
||||
if (mass > 0.f)
|
||||
{
|
||||
cpBodySetMass(m_handle, mass);
|
||||
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
|
||||
m_world->RegisterPostStep(this, [mass](Nz::RigidBody2D* body)
|
||||
{
|
||||
cpBodySetMass(body->GetHandle(), mass);
|
||||
cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass));
|
||||
});
|
||||
}
|
||||
else
|
||||
cpBodySetType(m_handle, CP_BODY_TYPE_STATIC);
|
||||
m_world->RegisterPostStep(this, [](Nz::RigidBody2D* body) { cpBodySetType(body->GetHandle(), CP_BODY_TYPE_STATIC); } );
|
||||
}
|
||||
else if (mass > 0.f)
|
||||
{
|
||||
if (cpBodyGetType(m_handle) == CP_BODY_TYPE_STATIC)
|
||||
m_world->RegisterPostStep(this, [mass](Nz::RigidBody2D* body)
|
||||
{
|
||||
cpBodySetType(m_handle, CP_BODY_TYPE_DYNAMIC);
|
||||
cpBodySetMass(m_handle, mass);
|
||||
cpBodySetMoment(m_handle, m_geom->ComputeInertialMatrix(m_mass));
|
||||
}
|
||||
if (cpBodyGetType(body->GetHandle()) == CP_BODY_TYPE_STATIC)
|
||||
{
|
||||
cpBodySetType(body->GetHandle(), CP_BODY_TYPE_DYNAMIC);
|
||||
cpBodySetMass(body->GetHandle(), mass);
|
||||
cpBodySetMoment(body->GetHandle(), body->GetGeom()->ComputeInertialMatrix(mass));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
m_mass = mass;
|
||||
@@ -290,6 +320,8 @@ namespace Nz
|
||||
m_world = object.m_world;
|
||||
|
||||
cpBodySetUserData(m_handle, this);
|
||||
for (cpShape* shape : m_shapes)
|
||||
cpShapeSetUserData(shape, this);
|
||||
|
||||
object.m_handle = nullptr;
|
||||
|
||||
@@ -302,6 +334,7 @@ namespace Nz
|
||||
{
|
||||
m_handle = cpBodyNew(mass, moment);
|
||||
cpBodySetUserData(m_handle, this);
|
||||
|
||||
cpSpaceAddBody(m_world->GetHandle(), m_handle);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user