gpt4 book ai didi

c++ - 许多圆圈的类似 Box2D 的碰撞

转载 作者:搜寻专家 更新时间:2023-10-31 02:13:04 24 4
gpt4 key购买 nike

我正在尝试编写一个非常精简、类似于 Box2D 的简单碰撞器——不包含所有物理、旋转等。我这样做既是为了保持代码占用空间小且易于理解,也是为了简单地了解内部这些事情个人的运作方式。

我想做的就是碰撞圆圈和线条,并防止它们嵌入彼此。

Box2D 几乎完美地做到了这一点——重叠量非常小!然而,当我编写自己的简单模拟器时,我得到了很多重叠:picture of overlapped circles .

当我使用 Box2D 运行相同的模拟时(这只是所有圆圈都在追逐屏幕中心的一个点),我根本看不到任何重叠。

在伪代码中,这就是我所做的:

For each Circle In List:
Determine who will collide with the circle in next step
Sort collisions by closest first
For each possible collision:
Add the unembed vector to the Circle's movement vector

...and then:

For each Circle In List:
At the movement to the circle

所以,如果圆圈没有被插入其他任何东西,这也很完美。但是,当事情堆积起来时,它就不起作用了,我知道为什么——未嵌入的东西简单地堆积起来,每个人都推挤和推挤,因为后来的圈子被解除嵌入到前面的圈子里,在模拟结束时,一些只是卡在其他圈子里.意义重大。

这是我感到困惑的地方:据我所知,Box2D 以完全相同的方式运行——获取可能的碰撞,相互取消嵌入,完成。但是 Box2D 永远不会像我的那样重叠(或者它让它们变得如此小以至于无关紧要)。

有人能告诉我我错过了什么步骤吗?我可以做一些调整来改进事情(比如迭代任何一次又一次碰撞的人......但是 Box2D 似乎没有这样做,我想在保持代码轻快的同时理解)。

谢谢!

相关真实代码如下:

aO->mPos = x,y of object
aO->mMove = x,y of movement this step
aO->mRadius = radius of object
aO->MovingBound() = bound of object including the move

void Step()
{
EnumList(MCObject,aO,mMovingObjectList)
{
mTree.GetAllNearbyObjects(aO->MovingBound().Expand(aO->mRadius/4),&aHitList);
aHitList-=aO; // Remove self from list
if (aHitList.GetCount()>0)
{
// Sort the collisions by closest first
if (mSortCollisions)
{
// Snip, took this out for clarity...
// It just sorts aHitList by who is closest
// to the current object
}
// Apply the unembedding
EnumList(MCObject,aO2,aHitList) CollideObjectObject(aO,aO2);
}
}

// Do the actual moves
EnumList(MCObject,aO,mMovingObjectList)
{
mTree.Move(aO->mProxy,aO->Bound(),aO->mMove);
aO->mPos+=aO->mMove;
aO->mMove=0;
}
}


void CollideObjectObject(MCObject* theO1, MCObject* theO2)
{
float aOverlap=gMath.DistanceSquared(theO1->mPos+theO1->mMove,theO2->mPos+theO2->mMove);
float aMixRadius=theO1->mRadius+theO2->mRadius;
if (aOverlap<=aMixRadius*aMixRadius)
{
Point aUnembed=(theO1->mPos-theO2->mPos);
float aUnembedLength=aMixRadius-sqrt(aOverlap);
aUnembed.SetLength(aUnembedLength);
float aMod=.5f;
if (theO2->mCollideFlags&COLLIDEFLAG_STATIONARY) aMod=1.0f;

theO1->mMove+=aUnembed*aMod;
}
}

最佳答案

解决许多对象之间的碰撞是一个相当困难的问题,因为除了碰撞的基本数学之外,您还必须更加努力地修复来自近似求解器(现实世界中的物理学工作基于要求无限小时间步长的积分;而在我们的模拟中,我们通常每秒只求解大约 60 次)。

我们来看看Box2D's constraint solver loop, located in b2island.cpp :在每个世界步骤中,碰撞解析器不仅运行一次。它会重复 velocityIterations 次,在官方测试用例中通常设置为 6 或 8 次。这也是您必须做的。

关于c++ - 许多圆圈的类似 Box2D 的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41902594/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com