首页 > 解决方案 > 保持两个旋转矩形碰撞检查的高精度 - SAT碰撞

问题描述

我实现了 SAT 来检查 2 个旋转矩形的碰撞。一切正常,但我注意到随着物体的移动,碰撞检查会失去精度。

我将正方形的速度设置为 (v * 5) * dt。在我的模拟中,我确定 5 是一米。

在某些时候,在对象的该位置检测到碰撞:

在此处输入图像描述

你能告诉我如何保持碰撞检查的高精度吗?我在某处发现了多重采样可以提供帮助的信息。你能给我解释一下它是什么,它是如何解决精度损失问题的以及如何实现的?

我在 fpc (pascal / lazarus) 中编写了我的解决方案,但这可能并不重要。下面是代码:

创建矩形角:

rectangle[0].x := position.x-15;
rectangle[0].y := position.y-35;
rectangle[1].x := position.x+15;
rectangle[1].y := position.y-35;
rectangle[2].x := position.x+15;
rectangle[2].y := position.y+26;
rectangle[3].x := position.x-15;
rectangle[3].y := position.y+26;

旋转矩形:

for i:= 0 to 3 do
begin
tempX := rectangle[i].x - position.x;
tempY := rectangle[i].y - position.y;

// now apply rotation
rotatedX := tempX * cos(DegToRad(ang)) - tempY * sin(DegToRad(ang));
rotatedY := tempX * sin(DegToRad(ang)) + tempY * cos(DegToRad(ang));

tempRectangle[i].x := position.x + rotatedX;
tempRetangle[i].y := position.y + rotatedY;

end;

rotatedRectangle:=tempRectangle;

和碰撞检查。这是这篇文章的解决方案:如何检查 2 个旋转矩形之间的交集? 移植到帕斯卡:

类型

TRectangle = array[0..3] of TMyPoint;

TMyPoint = record
x:real;
y:real;
end;

碰撞检查:

res:=true; 

for i := 0 to 1 do //2 cars
begin

    // for each polygon, look at each edge of the polygon, and determine if it separates
    // the two shapes
polygon := polygons[i];

    for i1 := 0 to Length(polygon)-1 do
    begin

        // grab 2 vertices to create an edge
        i2 := (i1 + 1) mod 4;
        p11 := polygon[i1];
        p22 := polygon[i2];

        // find the line perpendicular to this edge
        normal.x := p22.y - p11.y;
        normal.y := p11.x - p22.x;

        minA.assigned := false;
        maxA.assigned := false;
        // for each vertex in the first shape, project it onto the line perpendicular to the edge
        // and keep track of the min and max of these values
        for j := 0 to 3 do 
        begin
            projected := normal.x * rectangleA[j].x + normal.y * rectanglA[j].y;
            if ((minA.assigned = false) or (projected < minA.value)) then
                begin
                     minA.value := projected;
                     minA.assigned:=true;;
                end;
            if ((maxA.assigned = false) or (projected > maxA.value)) then
                begin
                     maxA.value := projected;
                     maxA.assigned := true;
                end;
        end;

        // for each vertex in the second shape, project it onto the line perpendicular to the edge
        // and keep track of the min and max of these values
        minB.assigned:=false;
        maxB.assigned:=false;
        for j := 0 to 3 do  
        begin
            projected := normal.x * rectanglB[j].x + normal.y * rectanglB[j].y;
            if ((minB.assigned = false) or (projected < minB.value)) then
                begin
                     minB.value := projected;
                     minB.assigned :=true;
                end;
            if ((maxB.assigned=false) or (projected > maxB.value)) then
                begin
                     maxB.value := projected;
                     maxB.assigned:=true;
                end;
        end;

        // if there is no overlap between the projects, the edge we are looking at separates the two
        // polygons, and we know there is no overlap
        if ((maxA.value < minB.value) or (maxB.value < minA.value)) then
            begin
                              res := false;

            end;
    end;
    end;

   result := res;

标签: collisionpascalrectangleslazarusfreepascal

解决方案


推荐阅读