/** * @file sat.h * @brief SAT (Separating Axis Theorem) 碰撞检测 * * 基于分离轴定理的凸多面体相交检测。 * 若存在一条轴使得两形状投影不重叠,则不相交。 * * @ingroup collision */ #pragma once #include "vde/core/point.h" #include #include namespace vde::collision { using core::Point3D; /** * @brief SAT 凸多面体相交检测 * * 分离轴定理:两个凸多面体不相交,当且仅当存在一条分离轴, * 使得二者在该轴上的投影区间不重叠。 * * 待检测的分离轴集合: * - A 的每个面法线 * - B 的每个面法线 * - A 的每条边与 B 的每条边的叉积 * * 对每条候选轴,计算两个多面体投影区间的最小/最大值。 * 若某轴上投影区间无重叠 → 不相交(早停)。 * 所有轴都重叠 → 相交。 * * 最坏时间复杂度 O(n_a · n_b),其中 n_a, n_b 为面数。 * 对于凸多面体通常在遍历部分轴后即早停。 * * @param verts_a 多面体 A 的顶点数组 * @param faces_a 多面体 A 的面索引数组(每个面为 {v0, v1, v2}) * @param verts_b 多面体 B 的顶点数组 * @param faces_b 多面体 B 的面索引数组 * @return 相交返回 true * * @note 适用于任意凸多面体。对于胶囊/球等光滑形状,GJK 更合适。 * * @code{.cpp} * // 两个凸四面体相交检测 * std::vector va = {{0,0,0}, {1,0,0}, {0,1,0}, {0,0,1}}; * std::vector> fa = {{0,2,1}, {0,1,3}, {0,3,2}, {1,2,3}}; * std::vector vb = {{0.5,0.5,0.5}, {1.5,0.5,0.5}, ...}; * std::vector> fb = { ... }; * bool hit = sat_intersect(va, fa, vb, fb); * @endcode * * @see gjk_intersect, tri_tri_intersect */ bool sat_intersect(const std::vector& verts_a, const std::vector>& faces_a, const std::vector& verts_b, const std::vector>& faces_b); } // namespace vde::collision