我尝试制作一个非常简单的2d物理函数来解决刚体,并将球体粒子作为碰撞器,
我有一个刚体和粒子类:
function _rigidBody () {
this._position = cc.p(0.0, 0.0);
this._angle = 0;
this._linearVelocity = cc.p(0.0, 0.0);
this._angularVelocity = 0.0;
this._force = cc.p(0.0, 0.0);
this._angularMoment = 0;
this._mass = 1.0;
this._particles = [];
}
function _particle () {
this._initialPosition = cc.p(0.0, 0.0);
this._relativePosition = cc.p(0.0, 0.0);
this._worldPosition = cc.p(0.0, 0.0);
this._linearVelocity = cc.p(0.0, 0.0);
this._force = cc.p(0.0, 0.0);
this._radius = 10.0;
}
基本上,每一帧我计算每个刚体中每个粒子存储的新位置,然后我检查粒子与粒子的碰撞,如果碰撞,我计算一个力来击退它们(基于半径和如何咬合)它们里面有),然后我将这个力存储在粒子中,
我计算了LinearVelocity和AngularVelocity,它通过向我的rigidBody添加和冲动它所包含的所有粒子上的所有力存储。
我的函数addImpulse(脉冲强制存储在粒子中并定位我粒子的世界位置):
this.AddImpulse = function(bodyIdx,impulse,position){
var b = g_Bodies[ bodyIdx ];
if(position == null){position = b._position;}
b._linearVelocity.x += (impulse.x/ b._mass);
b._linearVelocity.y += (impulse.y/ b._mass);
b._angularVelocity += ((position.x - b._position.x) * impulse.y -
(position.y - b._position.y) * impulse.x);
};
我的问题是,这个函数对于linearVelocity来说效果非常好,因为它的角速度在最小的碰撞中变得非常大, 现在,我不使用任何阻尼(线性或角度),我的angularVelocity没有惯性,
我想惯性错过是我的问题,但是当我在互联网上查看如何计算它时,我有点迷惑,
我在box2d中查看惯性是否存储它接缝是刚体的变量(质量)。
我在互联网上发现Inertia = mass *(r * r)
problem =>什么是......
-if是我的重力中心的距离(因此我的刚体的位置),显然一直等于0(body.position - body.position == 0)
我发现: this.m_I = massData.I - this.m_mass *(massData.center.x * massData.center.x + massData.center.y * massData.center.y); 并且massData.center接缝是刚体的形状的中心, 在我的情况下,我的形状是2个球体,一个在(0,10),一个在(0,-10),因此它的中心是(0,0)....
在另一个网站上我发现: for(i< numberOfParticle) I + =(massOfParticle(i)*(RelativePosOfParticle(i)* RelativePosOfParticle(i)) 在这种情况下更好,因为当我平方每个粒子的距离(而不是先搜索中心)时,我的大于0。 但所以我不确定使用正确的公式......
如果有人能以简单的方式解释我,如何计算惯性?如果我可以直接计算刚体的惯性(而不是粒子)?如果我可以存储惯性或者它是否加深了应用冲动的位置(我在其他网站上也读到了......)? 和/或为什么我的冲动函数能够做出如此大的角速度(可能是正常的,阻尼解决这个问题的是另一个物理引擎)。
如果有人能够回答(只是出于好奇心),box2d是否会使用惯性的简单版本,因为计算速度更快,结果足够好?或者Box2d的计算是否正确,当我阅读代码时我想念一些东西?
非常感谢^^,
的Marius。
答案 0 :(得分:1)
首先:你是对的,问题是你没有考虑惯性矩(这是质量的旋转模拟)。看一下代码:
b._linearVelocity.x += (impulse.x/ b._mass);
b._linearVelocity.y += (impulse.y/ b._mass);
b._angularVelocity += ((position.x - b._position.x) * impulse.y -
(position.y - b._position.y) * impulse.x);
计算线速度时,除以质量;你应该为角运动做类似的事情。
如果rigidBody
的位置是其重心,那么工作就很容易。
惯性矩是mr 2 ,对粒子求和。也就是说,每个粒子贡献m*r*r
,其中m
是粒子的质量,r
是粒子到重心的距离。
例如,如果你的形状是2个球体,一个在(0,10),一个在(0,-10),都是质量5 ,那么重心在< / p>
C = (5*(0,10)+5*(0,-10))/(5+5) = (0,0)
惯性矩
I = 5*10*10 + 5*(-10)*(-10) = 1000
角速度的变化将是
b._angularVelocity += (((position.x - b._position.x) * impulse.y -
(position.y - b._position.y) * impulse.x))/I;
如果你的形状是2个球体,一个在(0,10),质量为5,一个在(0,-10),质量为10,那么重心位于
C = (5*(0,10)+10*(0,-10))/(5+10) = (0,-10/3)
惯性矩
I = 5*(40/3)*(40/3) + 5*(-20/3)*(-20/3) = 10000/9
修改
在单个球体(或并置的球体)的特殊情况下会出现问题。这些球体被视为点质量,因此惯性矩(I
)将为零。并且所有脉冲都被引导通过球体的中心,因此扭矩(角度“力”)将为零。所以不应该有角速度,但通过上面的方法它将是0/0
。 一个解决方案:每个球体对惯性力矩做出一个小的恒定贡献(这意味着球体不是点质量 - 它有一个微小的范围,所以它可以旋转)。现在每个球体的贡献是m*r*r + d
,其中d
是,例如0.0001
。因此,孤独的球体具有正的惯性矩(并且不会旋转),并且所有其他物体仍然具有逼真的物理。