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

物理引擎探究(7)---第一次碰撞

程序员文章站 2022-07-04 20:27:31
...

0.简介

碰撞是比较难写的部分,但是也不难写,掌握了规律就好办不少,这次实现一个最简单的碰撞判断。

1.圆圈与直线的碰撞

上一次实现了直线,严谨来说是线段,圆圈与一条线段的碰撞,方法有很多,不要拘泥于我接下来要介绍的一种方法。

首先我利用圆圈的圆心,将圆心O投影到线段所在直线上作为点C,线段的端点是A和B,如果C在AB之间,则向量CA与CB的夹角应该是180度,此时计算圆心到C点距离,如果比半径小就是相交了。如下图所示。

物理引擎探究(7)---第一次碰撞
示意图1

当然这还不够,如果C在AB之外,则CA与CB的夹角是0度,这个夹角就是体现在两个向量的COS值上。

接下来要计算圆心O与A和B两个端点的距离,如果小于半径则相交。

物理引擎探究(7)---第一次碰撞
示意图2
CollideInfo collide::LineAndCircle(Object * line,Object * circle)
{
	Line* linePtr = dynamic_cast<Line*>(line);
	Circle * circlePtr = dynamic_cast<Circle*>(circle);
	vec3 A = linePtr->A + linePtr->position;
	vec3 B = linePtr->B + linePtr->position;
	vec3 O = circlePtr->position;
	//C点是圆心到直线的投影
	vec3 AB = B - A;
	vec3 C = A + AB * (dot(AB, (O - A)) / dot(AB, AB));
	//判断投影点是否在点段内
	float distance = length(C - O);
	//如果投影点在线段内
	if (abs(dot(normalize(C - A), normalize(C - B))+1)<0.0001)
	{
		//若在的时候,判断两点距离是不是小于半径
		
		if (distance < circlePtr->radius)
		{
			while (1);
			return CollideInfo(line,circle,abs(circlePtr->radius - distance),normalize(C-O));
		}
		return CollideInfo(nullptr, nullptr, 0, vec3(0, 0, 0));
	}
	else
	{
		float disOA = length(O -A);
		float disOB = length(O -B);
		if (disOA < circlePtr->radius)
		{
			while (1);
			return CollideInfo(line, circle, abs(circlePtr->radius - disOA), normalize(O - A));
		}
		if (disOB < circlePtr->radius)
		{
			while (1);
			return CollideInfo(line, circle, abs(circlePtr->radius - disOB), normalize(O - B));
		}
	}
	return CollideInfo(nullptr, nullptr, 0, vec3(0,0,0));
}

目前碰撞还没有什么效果,我在碰撞位置加上一个死循环,这样一旦碰撞后程序就不动了。

2.效果

物理引擎探究(7)---第一次碰撞
两张情况

3.源码

release0.02

相关标签: 物理引擎