2026-07-24 11:02:06 +00:00
|
|
|
/**
|
|
|
|
|
* @file tri_intersect.h
|
|
|
|
|
* @brief 三角形-三角形 / 三角形-AABB 相交检测
|
|
|
|
|
*
|
|
|
|
|
* 基于分离轴定理 (SAT) 的三角形间相交检测。
|
|
|
|
|
* 包括快速布尔测试和详细交点段提取。
|
|
|
|
|
*
|
|
|
|
|
* @ingroup collision
|
|
|
|
|
*/
|
|
|
|
|
|
2026-07-23 05:27:51 +00:00
|
|
|
#pragma once
|
|
|
|
|
#include "vde/core/triangle.h"
|
2026-07-23 12:36:39 +00:00
|
|
|
#include "vde/core/aabb.h"
|
2026-07-23 05:27:51 +00:00
|
|
|
|
|
|
|
|
namespace vde::collision {
|
2026-07-23 08:19:24 +00:00
|
|
|
using core::Triangle3D;
|
2026-07-23 12:36:39 +00:00
|
|
|
using core::AABB3D;
|
|
|
|
|
using core::Point3D;
|
2026-07-23 05:27:51 +00:00
|
|
|
|
2026-07-24 11:02:06 +00:00
|
|
|
/**
|
|
|
|
|
* @brief 三角形-三角形相交检测(布尔测试)
|
|
|
|
|
*
|
|
|
|
|
* 使用分离轴定理在两组三角形之间检测相交。
|
|
|
|
|
* 候选分离轴包括:
|
|
|
|
|
* - 每个三角形的面法线(2 轴)
|
|
|
|
|
* - 每对边的叉积(3×3 = 9 轴)
|
|
|
|
|
* - 共 11 轴(三角形退化为共面时可能有更多)
|
|
|
|
|
*
|
|
|
|
|
* 若存在一条轴使得两三角形投影区间不重叠 → 不相交。
|
|
|
|
|
*
|
|
|
|
|
* 复杂度 O(1)(固定 11+ 轴检测)。
|
|
|
|
|
*
|
|
|
|
|
* @param t1 三角形 1
|
|
|
|
|
* @param t2 三角形 2
|
|
|
|
|
* @return 相交返回 true
|
|
|
|
|
*
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
* Triangle3D t1 = {p0, p1, p2};
|
|
|
|
|
* Triangle3D t2 = {q0, q1, q2};
|
|
|
|
|
* if (tri_tri_intersect(t1, t2)) {
|
|
|
|
|
* // 处理碰撞
|
|
|
|
|
* }
|
|
|
|
|
* @endcode
|
|
|
|
|
*
|
|
|
|
|
* @see tri_tri_intersect_detailed, sat_intersect
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
bool tri_tri_intersect(const Triangle3D& t1, const Triangle3D& t2);
|
|
|
|
|
|
2026-07-24 11:02:06 +00:00
|
|
|
/**
|
|
|
|
|
* @brief 三角形-三角形相交线段
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
struct TriTriIntersection {
|
2026-07-24 11:02:06 +00:00
|
|
|
bool intersects; /**< 是否相交 */
|
|
|
|
|
Point3D p0; /**< 交点段起点 */
|
|
|
|
|
Point3D p1; /**< 交点段终点 */
|
2026-07-23 12:36:39 +00:00
|
|
|
};
|
2026-07-24 11:02:06 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 三角形-三角形详细相交检测
|
|
|
|
|
*
|
|
|
|
|
* 返回两三角形相交的交点线段(两个端点)。
|
|
|
|
|
* 适用于需要精确接触几何的场景,如:
|
|
|
|
|
* - 物理引擎的接触流形生成
|
|
|
|
|
* - CSG 构造体几何的精确分割线
|
|
|
|
|
* - 网格自交修复
|
|
|
|
|
*
|
|
|
|
|
* 算法:
|
|
|
|
|
* 1. 用平面方程计算各顶点到对方平面的有符号距离
|
|
|
|
|
* 2. 找到边-平面交点形成交集段
|
|
|
|
|
* 3. 限制交集段到两个三角形内部
|
|
|
|
|
*
|
|
|
|
|
* @param t1 三角形 1
|
|
|
|
|
* @param t2 三角形 2
|
|
|
|
|
* @return TriTriIntersection:相交标志 + 交点段端点
|
|
|
|
|
*
|
|
|
|
|
* @note 共面情况交集段可能退化为单点(p0 == p1)
|
|
|
|
|
*
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
* auto sect = tri_tri_intersect_detailed(t1, t2);
|
|
|
|
|
* if (sect.intersects) {
|
|
|
|
|
* Vector3D contact_normal = (t1.normal() + t2.normal()).normalized();
|
|
|
|
|
* Point3D midpoint = (sect.p0 + sect.p1) * 0.5;
|
|
|
|
|
* }
|
|
|
|
|
* @endcode
|
|
|
|
|
*
|
|
|
|
|
* @see tri_tri_intersect
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
TriTriIntersection tri_tri_intersect_detailed(const Triangle3D& t1,
|
|
|
|
|
const Triangle3D& t2);
|
|
|
|
|
|
2026-07-24 11:02:06 +00:00
|
|
|
/**
|
|
|
|
|
* @brief 三角形-AABB 快速相交测试
|
|
|
|
|
*
|
|
|
|
|
* 使用分离轴定理在三角形和轴对齐包围盒之间检测。
|
|
|
|
|
* 候选分离轴包括(共 13 轴):
|
|
|
|
|
* - 3 条 AABB 面法线
|
|
|
|
|
* - 1 条三角形面法线
|
|
|
|
|
* - 9 条边×边叉积(3 条 AABB 边 × 3 条三角形边)
|
|
|
|
|
*
|
|
|
|
|
* 复杂度 O(1)。
|
|
|
|
|
*
|
|
|
|
|
* @param tri 三角形
|
|
|
|
|
* @param box 轴对齐包围盒
|
|
|
|
|
* @return 相交返回 true
|
|
|
|
|
*
|
|
|
|
|
* @note AABB 碰撞比三角剖分后的三角-三角检测更高效,
|
|
|
|
|
* 常用于空间划分结构中的 rejection test。
|
|
|
|
|
*
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
* if (tri_aabb_overlap(tri, node_bounds)) {
|
|
|
|
|
* // 需要进一步检测节点内的三角形
|
|
|
|
|
* }
|
|
|
|
|
* @endcode
|
|
|
|
|
*
|
|
|
|
|
* @see tri_tri_intersect, ray_aabb_intersect
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
bool tri_aabb_overlap(const Triangle3D& tri, const AABB3D& box);
|
|
|
|
|
|
2026-07-23 05:27:51 +00:00
|
|
|
} // namespace vde::collision
|