物理引擎探究(7)---第一次碰撞
程序员文章站
2022-07-04 20:27:31
...
0.简介
碰撞是比较难写的部分,但是也不难写,掌握了规律就好办不少,这次实现一个最简单的碰撞判断。
1.圆圈与直线的碰撞
上一次实现了直线,严谨来说是线段,圆圈与一条线段的碰撞,方法有很多,不要拘泥于我接下来要介绍的一种方法。
首先我利用圆圈的圆心,将圆心O投影到线段所在直线上作为点C,线段的端点是A和B,如果C在AB之间,则向量CA与CB的夹角应该是180度,此时计算圆心到C点距离,如果比半径小就是相交了。如下图所示。
当然这还不够,如果C在AB之外,则CA与CB的夹角是0度,这个夹角就是体现在两个向量的COS值上。
接下来要计算圆心O与A和B两个端点的距离,如果小于半径则相交。
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.效果
3.源码
上一篇: 关于优质短视频我总结三点...
下一篇: activiti获取连线属性