循环直线碰撞C++(UE4)
您好,我正在尝试计算二维坐标空间中的圆-线段碰撞 我想在我的代理移动时检测碰撞,因此我正在分步执行它的移动->代理位置是代理现在所在的位置,而代理位置+agentDelta是它在此移动步骤中希望所在的位置 这条线的定义是FVertex是坏名字我知道testEdge它有2个点A和B 圆被定义为以agentPosition+agentDelta为中心,agentRadius为半径 我试图找到一个碰撞点,它是两个可能的交点的平均值,并计算所需的参数: 碰撞时间{0.0f,1.0f} 碰撞点碰撞时圆的位置 碰撞点碰撞的平均点 以下是我尝试过的,但我没有成功: 我得到负值或大于1.0f的时间,有时碰撞点位于线段和其他有趣的工件的另一侧 如果你能帮我找出我做错了什么,我将不胜感激循环直线碰撞C++(UE4),c++,geometry,collision-detection,C++,Geometry,Collision Detection,您好,我正在尝试计算二维坐标空间中的圆-线段碰撞 我想在我的代理移动时检测碰撞,因此我正在分步执行它的移动->代理位置是代理现在所在的位置,而代理位置+agentDelta是它在此移动步骤中希望所在的位置 这条线的定义是FVertex是坏名字我知道testEdge它有2个点A和B 圆被定义为以agentPosition+agentDelta为中心,agentRadius为半径 我试图找到一个碰撞点,它是两个可能的交点的平均值,并计算所需的参数: 碰撞时间{0.0f,1.0f} 碰撞点碰撞时圆的位
static bool CheckAgentEdgeCollision(FVertex testEdge, FVector agentPosition, FVector agentDelta, float agentRadius, FCollisionResult2Dplease& outCollisionResult, UWorld* world = nullptr)
{
agentPosition.Z = 0.0f;
agentDelta.Z = 0.0f;
testEdge.B.Z = 0.0f; testEdge.A.Z = 0.0f;
FVector D = testEdge.B - testEdge.A;
FVector d = testEdge.A - (agentPosition + agentDelta);
float a = D | D; // Operator | is Dot Product
float b = (d | D) * 2.0f;
float c = (d | d) - FMath::Square(agentRadius);
float disc = b * b - 4.0f * a * c;
if (disc < KINDA_SMALL_NUMBER)
{
return false;
}
float sqrtDisc = FastSQRoot(disc);
float invA = 1.0f / ( a * 2.0f );
float t0 = (-b - sqrtDisc) * invA;
float t1 = (-b + sqrtDisc) * invA;
FVector poin1 = FVector::ZeroVector;
FVector poin2 = FVector::ZeroVector;
poin1 = testEdge.A + t0 * D;
poin2 = testEdge.A + t1 * D;
bool p1 = true;
bool p2 = true;
if(t0 > 1.0f || t0 < 0.0f)
{
//disregard
p1 = false;
}
if (t1 > 1.0f || t1 < 0.0f)
{
p2 = false;
}
if(!p1 && !p2)
{
return false;
}
else if(!p1)
{
poin1 = poin2;
}
else if (!p2)
{
poin2 = poin1;
}
float invRadius = 1.0f / agentRadius;
agentRadius += 5.0f;
//Average the points:
FVector impactPoint = (poin1 + poin2) / 2.0f;
FVector directionToCircle = agentPosition - impactPoint;
FastNormalize(directionToCircle);
FVector collisionPoint = directionToCircle * agentRadius + impactPoint;
float distToCollision = FastSQRoot(agentPosition.DistSquared2D(agentPosition, collisionPoint));
float speed = FastSQRoot(agentDelta.SizeSquared2D());
float outTime = 0.0f;
if (speed != 0.0f)
{
outTime = distToCollision / speed;
}
outCollisionResult.m_bIsPawn = false;
outCollisionResult.m_edge = testEdge;
outCollisionResult.m_normal = directionToCircle;
outCollisionResult.m_collisionPoint = collisionPoint;
outCollisionResult.m_time = outTime;
outCollisionResult.m_bHit = true;
outCollisionResult.m_impactPoint = impactPoint;
outCollisionResult.m_binPenetration = outTime < 0.0f;
return true;
}
提示:
如果分段是固定的,则可以通过在对分段充气的同时对圆放气来重新预测问题,这将为您提供一个相对于胶囊的移动点。如您所见,碰撞发生在中心轨迹和胶囊轮廓之间的交点处,该交点可以沿直边或圆边发生
通过旋转场景使片段到达X轴,计算将变得更容易。片段是否固定?请回答我的问题。@Yves Daoust fixed的意思是:不移动?喜欢静电吗?然后是的。我不确定如何从技术上膨胀线段,但这个想法非常有趣:。现在,我正在尝试将圆投影到直线上-获取线段上最近的点-然后确保碰撞确实在线段中-并检查从点到所需位置的半径与距离。我认为这和你的想法有点相似。@ColdSteel:你只需要将两条线或线+圆相交即可