欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

物理引擎探究(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);
}
物理引擎探究(10)---球碰撞旋转
标记

计算角动量这里根据角动量公式来计算。

关于角动量公式的链接 角动量公式讲解

我是先将圆圈本身的角动量分离出线速度,然后再和圆圈运动方向的线速度叠加,之后将这个速度转换到角动量。由于假设有摩擦力,力的作用是相互的,所以输出的动量同样也会返回给自己,这里还可以考虑利用冲量来计算。

	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.效果

物理引擎探究(10)---球碰撞旋转
一些效果
物理引擎探究(10)---球碰撞旋转
一些效果

3.源码

release0.05

相关标签: 物理引擎