1

分離軸定理 (SAT) に基づいて、凸型 2d ポリゴンと凸型 2d ポリゴンの衝突テストを行っています。

私の質問は、MTV の方向を何らかの形で修正せずにこのアルゴリズムを実装することは可能でしょうか? (巻く順序、外向きの法線、または私が間違っている可能性のあるその他の詳細に注意を払うことによって)。

SAT は最小の翻訳ベクトルを生成します。約半分の時間で間違った方向を指していたため、MTV の方向を正しく取得するのが難しいことがわかりました (ポリゴン A と B が衝突検出機能に渡された場合、MTV は常に A の方向になるはずです)。2 つの投影が重なるかどうかだけでなく、2 つの投影間の重なりの方向をチェックするコードを追加した後にのみ、正しく機能し始めました。

pub struct Projection {
    min: f64,
    max: f64,
}

impl Projection {
   // omitted some other functions not relevant to the question

   /// Calculates the direction of overlap between two projections.
   /// In case of no overlap, None is returned
   pub fn overlap(&self, other: &Self) -> Option<f64> {
        let sum = (self.max - self.min) + (other.max - other.min);    
        let extent = self.max.max(other.max) - self.min.min(other.min);
        if (sum - extent).is_sign_negative() {
            None
        }
        else if self.max - other.min < other.max - self.min {
            Some(self.max - other.min)
        } else { 
            Some(self.min - other.max)
        }
    }
}

しかし、私が読んだ SAT に関するさまざまな記事やコメントでは、外向きのポリゴン法線について言及されており、MTV 方向のトピックは比較的ほとんど注目されていないため、重要な詳細を見逃している可能性があります、私にとってはそれが最も難しい部分でした)。

私の SAT 実装の中核は、2 回呼び出されるこの関数です。関数が引数の順序を逆にして 2 回目に呼び出されると、MTV の方向に影響しますが、私はこれを十分に認識しています。

fn find_mtv(a: &Convex, b: &Convex) -> Option<MtvComponents> {   
    let mut comps = MtvComponents::new();
    for axis in a.iter_normals().map(Vector::normalize) {
        let proj_a = Projection::new(a.iter_vertices(), axis);
        let proj_b = Projection::new(b.iter_vertices(), axis);
        if let Some(overlap) = proj_a.overlap(&proj_b) {
            comps.store_min(overlap, axis);
        } else {
            return None
        }
    }
    Some(comps)
}
4

0 に答える 0