物理引擎探究(10)—球碰撞旋转

 

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的之前计算好了,所以这里的受力计算是多余的。

2.效果

一些效果
一些效果

3.源码

release0.05


版权声明:本文为ARTELE原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
THE END
< <上一篇
下一篇>>