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

物理引擎探究(9)---球碰撞处理

程序员文章站 2022-07-04 20:06:37
...

0.简介

球的碰撞处理,之前想着会比较简单,但是实际上比想象的难一些。

1.球与球的碰撞

之所这么分类,所以因为球和球的碰撞比较特殊,目前暂时不考虑摩擦力的情况,球与球碰撞产生的碰撞交点是一定过两个球心的连线的,这样球就一定会因为碰撞产生位移。球的正碰是特殊情况,这里我们直接考虑球与球的斜碰,斜碰就是两个球碰撞时候,碰撞交点不在速度方向上。

关于斜碰后速度的变化可以看如下文章作为参考。

斜碰

我在这里也简要说明一下。

物理引擎探究(9)---球碰撞处理
两个球碰撞,(上球为球A,下球为球B)

假设一个球A以速度V运动,与另一个静止的球B碰撞,此时将速度根据两个圆心方向和对应垂直方向分解,得到V1和V2,V2就是与另一个球B进行动量守恒计算的速度,加入计算完毕后,V2方向在碰撞后的速度是V3,V1+V3则是A球最终的运动结果,同理球B也这样计算,最终求得两个球的运动速度。具体还可以看上面的链接,斜碰。

2.实现

class CollideInfo
{
public:
	CollideInfo() {}
	CollideInfo(Obj_Forces*_A, Obj_Forces*_B,float _deep,vec3 _cPoint):A(_A),B(_B),deep(_deep), cPoint(_cPoint) {}
	Obj_Forces* A;
	Obj_Forces* B;
	float deep;//相交最短距离
	vec3 cPoint;//碰撞点
	//生成力
	void generate()
	{
		//没有碰撞就不计算
		if (A == nullptr || B == nullptr)
			return;
		//以下生成的都是碰撞产生的力
		//两个物体都存在说明产生碰撞力
		if (A != nullptr && B != nullptr)
		{
			
			vec3 vecA = normalize(A->obj->position - cPoint);
			vec3 vecB = normalize(B->obj->position - 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;
				
			}
			//受力计算
			vec3 force(0,0,0);
			for (auto fa : A->forces)
			{
				force += fa->getForce();
			}
			A->addForce(new Elastic(-force,COLLIDEFORCE));
			force = vec3(0, 0, 0);
			for (auto fb : B->forces)
			{
				force += fb->getForce();
			}
			B->addForce(new Elastic(-force, COLLIDEFORCE));
		}
	}
	vec3 momentumCalc(float mA, float mB, vec3 vA, vec3 vB)
	{
		return ((mA-mB)*vA+2.0f*mB*vB)/(mA+mB);
	}
	~CollideInfo() {}
};

这里确实废了不小力气(找资料时间比较久),不过还好可以实现,后续再优化计算过程。当然,之前的直线与球碰撞代码就删除了,因为考虑的情况比较少,只是暂时测试碰撞信息处理模块用的。

3.效果

物理引擎探究(9)---球碰撞处理
一些碰撞效果
物理引擎探究(9)---球碰撞处理
碰撞效果

4.代码

release0.04

相关标签: 物理引擎