toge's diary

コンピュータ関連の趣味をつらつらと。

衝突判定に手を出すか

うーん、やっとこさ衝突判定のための仕組みを入れられました。
なんとも下らんクラスを作ってしまいました。
もっと良い方法があればいいんだけどなぁ。

objectとobjectの型を示すid、そのobjectのAABB(Axis Aligned Bounding Box)だけを持つクラスを作り、AABB同士での衝突判定をした後に、双方のidをindexにして関数ポインタのテーブルCoolideTableから、詳細な衝突判定と衝突処理を行う関数を呼び出す・・・という手筈。

class CollideTarget {
public:
  explicit CollideTarget(void* object, unsigned int id, const Rect& bbox)
    : object_(object), id_(id), bbox_(bbox), collide_(false) {}

public:
  void* object() {return object_;}
  const void* object() const {return object_;}
  
  Rect bbox() {return bbox_;}
  const Rect& bbox() const {return bbox_;}

  unsigned int id() const {return id_;}

  /* 衝突したかどうか */
  void collide() {collide_ = true;}
  bool isCollide() const {return collide_;}

private:
  void* object_;                // 衝突対象
  unsigned int id_;             // 型を示すID
  Rect bbox_;                   // AABB
  bool collide_;                // 既に衝突したかどうか
};

// 衝突処理上の関数
typedef bool (*Collide)(CollideTarget& lhs, CollideTarget& rhs);

// 関数ポインタのテーブル
extern Collide CollideTable[]; 

// 衝突処理関数・・・の一部
void collide() {
  typedef std::vector< CollideTarget >::iterator Iterator;
  for (Iterator p = collideList_.begin(), pend = collideList_.end(); p != pend - 1; ++p) {
    // 衝突している場合は除く
    if (p->isCollide() == true)
      continue;

    Rect p_rect = p->bbox();
    unsigned int p_id = p->id();

    for (Iterator q = p + 1; q != pend; ++q) {
      // 既に衝突している場合は次へ
      if (q->isCollide() == true)
        continue;

      Rect q_rect = q->bbox();
      unsigned int q_id = q->id();

      // 衝突していないなら次へ
      if (p_rect.overlap(q_rect) == false)
        continue;

      // 衝突関数を見つけ処理
      bool result;
      if (p_id <= q_id)
        result = CollideTable[p_id * ID_END + q_id](*p, *q);
      else
        result = CollideTable[q_id * ID_END + p_id](*q, *p);

      // 実際に衝突していた場合には後の処理中止
      if (result == true) {
        p->collide();
        q->collide();
        break;
      }
    }
  }
} 

さてと今はN x Nの衝突判定を行っていますがさすがに遅くなりそうなので、まともな枝刈りをしないとね。
最初はRDC(Recursive Dimension Clustering)を試そうと思ったけれど、GameDevで調べる限りあんまり速くないみたいなので、sort-and-sweepでも勉強しますか。