碰撞检测C ++分离轴定理

时间:2015-05-22 17:12:22

标签: c++ sfml

我正在开发一个用于与SFML一起使用的c ++简单碰撞引擎。我查看了一些教程并得出结论,SAT对我的计划来说已经足够了,并开始实施。它似乎部分起作用。在测试它时,外部最短路径的矢量有时似乎是正确的。 Here's an image showing all outcomes on two polygons

这是我的功能,是碰撞检测的一部分。

Range::Range(float mi, float ma) :
    min(mi), max(ma) {
}

Range Range::overlap(Range other) {
  Range r;
  r.min = min > other.min ? min : other.min;
  r.max = max < other.max ? max : other.max;
  return r;
}

Range CollisionShape::project(sf::Vector2f axis) {
  float d = dot(_vertices_t[0], axis);
  Range r(d, d);
  for (unsigned i = 0; i < _num_vertices; i++) {
    d = dot(_vertices_t[i], axis);
    r.min = d < r.min ? d : r.min;
    r.max = d > r.max ? d : r.max;
  }
  return r;
}

sf::Vector2f CollisionShape::sat(CollisionShape& other, bool own) {
  sf::Vector2f ret;
  bool first = true;
  // Separating Axis Theorem
  unsigned num = own ? _num_vertices : other._num_vertices;
  sf::Vector2f* vertices = own ? _vertices_t : other._vertices_t;
  for (unsigned i = 0; i < num; i++) {
    sf::Vector2f v = normalize(vertices[(i + 1) % num] - vertices[i]);
    sf::Vector2f n(v.y, -v.x);
    Range r1 = project(n);
    Range r2 = other.project(n);
    if (r1.max < r2.min || r1.min > r2.max) {
      return sf::Vector2f(0, 0);
    }
    Range overlap = r1.overlap(r2);
    if (first || (overlap.max - overlap.min) < length(ret)) {
      ret = -n * (overlap.max - overlap.min);
      first = false;
    }
  }
  return ret;
}

sf::Vector2f CollisionShape::collision(CollisionShape& other) {
  // Test shape's potential separating axes
  sf::Vector2f ret1 = sat(other, true);
  if (ret1 == sf::Vector2f(0, 0)) {
    return ret1;
  }
  // Test other shape's potential separating axes
  sf::Vector2f ret2 = sat(other, false);
  if (ret2 == sf::Vector2f(0, 0)) {
    return ret2;
  }
  return (length(ret1) < length(ret2) ? ret1 : ret2);
}

我无法确定问题出在哪里。 大编辑:我有点看到连接。如果它们沿着x或y轴(对于一个元素包含0),似乎向量是错误的。仍然不知道这是怎么发生的。

0 个答案:

没有答案