Merge remote-tracking branch 'refs/remotes/origin/master' into reflection-mapping

This commit is contained in:
Lynix
2017-03-18 17:23:12 +01:00
23 changed files with 427 additions and 39 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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));
}
}

View File

@@ -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);
}