物理引擎探究(10)---球碰撞旋转
程序员文章站
2022-07-04 20:06:01
...
0.简介
上次一我实现了球碰撞后的运动轨迹计算,这回要实现球的旋转。
1.角动量
我觉得这里应该用到角动量了,当球与球碰撞之后,球自身会因为碰撞点有摩擦力,导致球旋转的,主要就是来求这个旋转的速度,这里就是角速度,所以在形状类中我添加了两个新的属性。
//旋转速度
vec3 angular_velocity = vec3(0,0,0);
//旋转角度
vec3 angular = vec3(0, 0, 0);
然后就是计算角速度了,现在还没有引进摩擦力,所以现在就简要模拟有摩擦力的情况。然后利用物体相撞计算动量守恒的方法,计算角动量。
这里就暂且认为摩擦力会造成另一个物体旋转,来源于,若空间中一个圆圈,当受到一个非对心的推力的时候,会产生旋转。圆圈怎么能看出旋转呢,这里加了一个区分标记。并且利用旋转矩阵。同样在显示的时候也添加了矩阵变换。
void Object::update(float time)
{
updatePosition(time);
updateVelocity(time);
//修改旋转矩阵
angular += angular_velocity;
axis = EulerAngle::getMat(angular);
force = vec3(0,0,0);
}
计算角动量这里根据角动量公式来计算。
关于角动量公式的链接 角动量公式讲解
我是先将圆圈本身的角动量分离出线速度,然后再和圆圈运动方向的线速度叠加,之后将这个速度转换到角动量。由于假设有摩擦力,力的作用是相互的,所以输出的动量同样也会返回给自己,这里还可以考虑利用冲量来计算。
void generate()
{
//没有碰撞就不计算
if (A == nullptr || B == nullptr)
return;
//以下生成的都是碰撞产生的力
//两个物体都存在说明产生碰撞力
if (A != nullptr && B != nullptr)
{
vec3 vecA = normalize(A->obj->getPos() - cPoint);
vec3 vecB = normalize(B->obj->getPos() - cPoint);
//碰撞点在两个型心连线上
if (dot(vecA, vecB) < 0.0001)
{
float speedA = length(A->obj->velocity);
float speedB = length(B->obj->velocity);
float cosa = dot(vecA, normalize(A->obj->velocity));
float cosb = dot(vecB, normalize(B->obj->velocity));
if (speedA == 0)
cosa = 1;
if (speedB == 0)
cosb = 1;
//两个物体的速度分解,碰撞点到连心线上的分解
vec3 rA = momentumCalc(A->obj->mass, B->obj->mass, speedA * cosa*vecA, speedB * cosb*vecB);
vec3 rB = momentumCalc(B->obj->mass, A->obj->mass, speedB * cosb*vecB, speedA * cosa*vecA);
vec3 AC = vecA * speedA * cosa;
vec3 BC = vecB * speedB * cosb;
vec3 AR = A->obj->velocity - AC;
vec3 BR = B->obj->velocity - BC;
AC = rA;
BC = rB;
A->obj->velocity = (AC + AR);
B->obj->velocity = (BC + BR);
//先将物体原有旋转动量转换
float Ra = length(A->obj->getPos() - cPoint);
float Rb = length(B->obj->getPos() - cPoint);
vec3 roA = cross(A->obj->angular_velocity, vecA)*0.5f;//这里是损失的角动量
vec3 roB = cross(B->obj->angular_velocity, vecB)*0.5f;
//计算动量后并且将角速度转换成线速度
vec3 troA = momentumCalc(A->obj->mass, B->obj->mass, roA, roB)*A->obj->mass*Ra;
vec3 troB = momentumCalc(B->obj->mass, A->obj->mass, roB, roA)*B->obj->mass*Rb;
//将运动速度转换成动量,这里暂不明,就是效果好, 我推算一个公式看看的
rA = AR*A->obj->mass* A->obj->mass;
rB = BR*B->obj->mass* B->obj->mass;
vec3 all = rA - rB;
//计算A和B角动量
vec3 dA = (all+troA-troB);
vec3 dB = (-all+troB-troA);
A->obj->angular_velocity += -cross(dA, vecA * length(A->obj->getPos() - cPoint))/(A->obj->mass*Ra*Ra);
B->obj->angular_velocity += -cross(dB, vecB * length(B->obj->getPos() - cPoint))/(B->obj->mass*Rb*Rb);
}
}
}
这里去掉了受力计算,受力计算已经在速度update的之前计算好了,所以这里的受力计算是多余的。