2011-04-21 2 views
1

분리 축 정리를 구현하는 데 문제가 있습니다. 충돌 감지 부분이 제대로 작동하더라도 반환되는 최소 변환 벡터가 잘못되었습니다. 충돌하는 다각형을 이동하는 데 사용하려고하면 이전 위치 (다른 다각형과 교차하는 경우도 있음) 또는 화면에서 더 이상 보이지 않는 쪽까지 배치됩니다.충돌 응답 (SAT) 문제

코드를 수정하려고했지만 here에서 코드를 복사하려고했지만 그 중 하나도 작동하지 않았습니다. 그러나 내가 여러 번 모든 것을 재 작성했기 때문에 어떤 문제가 발생하는지 모르겠다. 어떤 오타도 있어서는 안된다.

나는 그것이 아마 명백한 무엇인가 알고있다. 그러나 나는 이것을 2 일 이상 꼼짝 않고 보았다. 그리고 나는 그것을 발견 할 수 없다.

많은 양의 코드에 대해 사과드립니다. 어디서 엉망인지 모르겠으므로 실제로 단축 할 수 없습니다.

ETA : 수정 됨.

if (dotProduct(d, move_axis) < 0.0f) move_axis = -move_axis;

실제로

if (dotProduct(d, move_axis) > 0.0f) move_axis = -move_axis;

void Polygon2d::calcEdges() 
{ 
    sf::Vector2f v1, v2; 
    edges.clear(); 

    for (unsigned int i = 0; i < vertices.size(); i++) 
    { 
     v1 = vertices[i]; 
     if ((i + 1) >= vertices.size()) v2 = vertices[0]; 
     else v2 = vertices[i + 1]; 

     edges.push_back(v2 - v1); 
    } 
} 

void Polygon2d::calcCenter() 
{ 
    float x = 0; 
    float y = 0; 

    for (unsigned int i = 0; i < vertices.size(); i++) 
    { 
     x += vertices[i].x; 
     y += vertices[i].y; 
    } 

    center.x = x/vertices.size(); 
    center.y = y/vertices.size(); 
} 

void Polygon2d::move(float x, float y) 
{ 
    for (unsigned int i = 0; i < vertices.size(); i++) 
    { 
     vertices[i].x += x; 
     vertices[i].y += y; 
    } 
    calcEdges(); 
    calcCenter(); 
} 

충돌 기능을해야한다 : 또한, 하나가 오류가 원래의 코드에 있었다 또는 좌표 시스템이 다른 것을 보인다

struct CollisionResult 
{ 
    bool collision; 
    sf::Vector2f move_axis; 
}; 

void normalise(sf::Vector2f& v) 
{ 
    float length = sqrt(v.x*v.x + v.y*v.y); 

    if (length != 0.0f) 
    { 
     v.x /= length; 
     v.y /= length; 
    } 
    else return; 
} 

float dotProduct(const sf::Vector2f a, const sf::Vector2f b) 
{ 
    float dp = a.x*b.x + a.y*b.y; 

    return dp; 
} 

void project(const sf::Vector2f axis, const Polygon2d& p, float& min, float& max) 
{ 
    float dp = dotProduct(axis, p.vertices[0]); 

    min = dp; 
    max = dp; 

    for (unsigned int i = 1; i < p.vertices.size(); i++) 
    { 
     dp = dotProduct(axis, p.vertices[i]); 

     if (dp < min) 
     { 
      min = dp; 
     } 

     else if (dp > max) 
     { 
      max = dp; 
     } 
    } 
} 

float distance(float minA, float maxA, float minB, float maxB) 
{ 
    if (minA < minB) return minB - maxA; 
    else return minA - maxB; 
} 


CollisionResult collision(const Polygon2d& p1, const Polygon2d& p2) 
{ 
    sf::Vector2f edge; 
    sf::Vector2f move_axis(0,0); 
    sf::Vector2f mtd(0,0); 

    float min_dist = FLT_MAX; 

    CollisionResult result; 

    for (unsigned int i = 0; i < p1.vertices.size() + p2.vertices.size(); i++) 
    { 
     if (i < p1.vertices.size()) // or <= 
     { 
      edge = p1.edges[i]; 
     } 
     else 
     { 
      edge = p2.edges[i - p1.vertices.size()]; 
     } 

     sf::Vector2f axis(-edge.y, edge.x); 
     normalise(axis); 

     float minA = 0; 
     float minB = 0; 
     float maxA = 0; 
     float maxB = 0; 

     project(axis, p1, minA, maxA); 
     project(axis, p2, minB, maxB); 

     if (distance(minA, maxA, minB, maxB) > 0.0f) 
     { 
      result.collision = false; 
      result.move_axis.x = 0.0f; 
      result.move_axis.y = 0.0f; 

      return result; 
     } 

     float dist = distance(minA, maxA, minB, maxB); 

     abs(dist); 

     if (dist < min_dist) 
     { 
      min_dist = dist; 
      move_axis = axis; 
     } 
    } 

    result.collision = true; 

    sf::Vector2f d = p1.center - p2.center; 
    if (dotProduct(d, move_axis) < 0.0f) move_axis = -move_axis; 
    result.move_axis = move_axis * min_dist; 

    return result; 
} 

답변

0

것 같다 당신의 상태 result.collision는 역방향 : 일부 축에 대한 거리가 긍정적 인 경우, 조건은 true로 설정하지만 코드에서해야합니다 또한

if (distance(minA, maxA, minB, maxB) > 0.0f) 
    { 
     result.collision = false; 
     result.move_axis.x = 0.0f; 
     result.move_axis.y = 0.0f; 

     return result; 
    } 

, 더 코드 :

abs(dist); 

나는 그것 때문에 이전 문제 (반대 논리)하지만 판단하기 어렵다

dist = abs(dist); 

해야한다 같아요.

+0

'dist = abs (dist);'이 문제가 수정되었습니다. 조금 일찍 이상하게 확인 했으므로 문제가없는 것으로 보입니다. 도와 주셔서 감사합니다. – grue

+0

그런데 조건에는 아무런 문제가 없습니다. 거리가 양수이면 다각형의 투영 사이에 간격이 있으며 중복 될 수 없습니다. – grue

+0

@grue 그래, 내 잘못이야. – anatolyg