【问题标题】:Calculating 2D resultant forces for vehicles in games计算游戏中车辆的 2D 合力
【发布时间】:2012-03-23 11:43:38
【问题描述】:

我正在尝试计算在发生碰撞时作用在圆形物体上的力。不幸的是,我的机械装置有点生锈,所以我遇到了一些麻烦。

我有一个有成员的代理类

vector position // (x,y)
vector velocity // (x,y)
vector forward // (x,y)  
float radius   // radius of the agent (all circles)
float mass     

所以如果我们有 A,B:Agent,并且在下一个时间步,速度将改变位置。如果要发生碰撞,我想计算出作用在物体上的力。

我知道需要 Line1 = (B.position-A.position) 来计算合力的角度,但是当我必须考虑车辆的当前速度以及碰撞角度。

arctan(L1.y,L1.x) 是力的角度(方向可以确定) sin/cos 是组件的高度/宽度

我也知道计算我需要使用的旋转轴 x = cos(T)*vel.x + sin(T)*vel.y y = cos(T)*vel.y + sin(T)*vel.x

这是我的大脑无法再应付的地方了。任何帮助将不胜感激。

正如我所说,目标是计算出施加到对象上的矢量力,因为我已经考虑了基本物理学。

添加了一些伪代码来显示我开始使用它的地方..

A,B:Agent 

Agent {
    vector position, velocity, front;
    float radius,mass;
}

vector dist = B.position - A.position;
float distMag = dist.magnitude();

if (distMag < A.radius + B.radius) { // collision 
    float theta = arctan(dist.y,dist.x);
    flost sine = sin(theta);
    float cosine = cos(theta);

    vector newAxis = new vector; 
      newAxis.x  = cosine * dist .x + sine * dist .y;
      newAxis.y  = cosine * dist .y - sine * dist .x;

    // Converted velocities
    vector[] vTemp = { 
         new vector(), new vector()         };
    vTemp[0].x  = cosine * agent.velocity.x + sine * agent.velocity.y;
    vTemp[0].y  = cosine * agent.velocity.y - sine * agent.velocity.x;
    vTemp[1].x  = cosine * current.velocity.x + sine * current.velocity.y;
    vTemp[1].y  = cosine * current.velocity.y - sine * current.velocity.x;        

希望堆栈上有一个好奇的数学极客..

【问题讨论】:

  • 也许研究像box2dchipmunk这样的物理引擎?
  • 我已经把所有东西都设置好了,我缺少的东西应该是相对容易的角度。转换后的轴意味着碰撞发生在我知道的角度,我需要对此做些什么..
  • 你确定 force 是你想要的吗?在“刚性”物体的碰撞中,力是巨大的,但很短暂。重要的是效果,碰撞后物体的速度。我认为这些是刚性的、非旋转的圆圈。有弹性还是无弹性?
  • 它们确实是非旋转圆,我试图先进行弹性碰撞,我确实通过改变速度来稍微改变一下,但它没有按预期工作。如果我可以计算力,那么我可以使用我必须计算出给定方向上的加速度的物理原理。
  • 强制不是解决这个问题的好方法。从碰撞前的一帧到碰撞后的一帧,力作用的时间(换句话说,所有的加速度)已经发生。相反,保持动量和能量。

标签: physics trigonometry collision


【解决方案1】:

不失一般性,假设我们在碰撞前处于第二个对象的参考系中。

动量守恒:

m1*vx1 = m1*vx1' + m2*vx2'
m1*vy1 = m1*vy1' + m2*vy2'

求解 vx1', vy1':

vx1' = vx1 - (m2/m1)*vx2'
vy1' = vy1 - (m2/m1)*vy2'

秘密地,我会记住vx1'*vx1' + vy1'*vy1' = v1'*v1'这一事实。

能量守恒(弹性碰撞给我们的一件事是入射角就是反射角):

m1*v1*v1 = m1*v1'*v1' + m2*v2'+v2'

求解 v1' 平方:

v1'*v1' = v1*v1 - (m2/m1)v2'*v2'

结合消除v1':

(1-m2/m1)*v2'*v2' = 2*(vx2'*vx1+vy2'*vy1)

现在,如果您曾经见过静止的台球被击中,您就会知道它会朝接触法线的方向飞走(这与您的 theta 相同)。

v2x' = v2'cos(theta)
v2y' = v2'sin(theta)

因此:

v2' = 2/(1-m2/m1)*(vx1*sin(theta)+vy1*cos(theta))

现在您可以求解 v1'(使用 v1'=sqrt(v1*v1-(m2/m1)*v2'*v2') 或根据输入变量求解整个问题)。

让我们致电phi = arctan(vy1/vx1)。在交点处相对于圆切线的入射角为90-phi-theta(如果您愿意,pi/2-phi-theta)。再次添加反射,然后转换回相对于水平的角度。我们称入射角为psi = 180-phi-2*theta (pi-phi-2*theta)。或者,

psi = (180 or pi) - (arctan(vy1/vx1))-2*(arctan(dy/dx))

所以:

vx1' = v1'sin(psi)
vy1' = v1'cos(psi)

考虑:如果这些圆应该是实心 3D 球体,则为每个圆使用与半径立方成比例的质量(请注意,比例常数抵消了)。如果它们应该是圆盘状,则使用与半径平方成比例的质量。如果它们是环,只需使用半径。

要考虑的下一点:由于计算机在离散时间事件中更新,因此您实际上有重叠的对象。在计算每个对象的新位置之前,您应该退出对象,以便它们不会重叠。为了获得额外的功劳,请找出它们应该相交的时间,然后在这段时间内将它们移向新的方向。请注意,这次只是重叠/旧速度。这很重要的原因是您可能会想象计算出的碰撞会导致对象仍然重叠(导致它们再次碰撞)。

下一点要考虑:要将原始问题转化为这个问题,只需从对象 1 中减去对象 2 的速度(按分量计算)。计算完记得加回来。

要考虑的最后一点:我可能在某个地方犯了一个代数错误。你应该认真考虑检查我的工作。

【讨论】:

  • 谢谢,看来我有点矫枉过正了。我会检查并告诉你我的进展情况!
  • @Blue42:我已经很久没有做过任何刚体(碰撞)模拟了。否则,我只会找到我的代码并将其提供给您。另外,我在写它的时候把它搞砸了3次。画图,使速度的角度不同于连接两个中心形成的角度(位置角)。图片很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 2017-07-16
  • 1970-01-01
  • 2021-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多