ViewDesignEngine  3.1.0
高性能 CAD 计算几何引擎
vde::collision 命名空间参考

struct  GJKResult
 GJK 完整检测结果 更多...
 
struct  RayTriResult
 射线-三角形求交结果 更多...
 
struct  RaySphereResult
 射线-球体求交结果 更多...
 
struct  TriTriIntersection
 三角形-三角形相交线段 更多...
 

类型定义

using SupportFunc = std::function< Point3D(const Vector3D &)>
 支撑函数类型 更多...
 

函数

bool gjk_intersect (const SupportFunc &shape_a, const SupportFunc &shape_b)
 GJK 相交检测(仅判断是否碰撞) 更多...
 
double gjk_distance (const SupportFunc &shape_a, const SupportFunc &shape_b)
 GJK 最近距离查询 更多...
 
GJKResult gjk_full (const SupportFunc &shape_a, const SupportFunc &shape_b)
 GJK 完整检测:碰撞状态、距离、最近点对 更多...
 
std::optional< RayTriResultray_triangle_intersect (const Point3D &origin, const Vector3D &dir, const Triangle3D &tri)
 射线-三角形求交(Möller-Trumbore 算法) 更多...
 
std::optional< RayTriResultray_triangle_intersect (const Ray3Dd &ray, const Triangle3D &tri)
 射线-三角形求交(Ray3Dd 重载) 更多...
 
bool ray_aabb_intersect (const Ray3Dd &ray, const AABB3D &box, double &tmin_out, double &tmax_out)
 射线-AABB 求交(slab 方法) 更多...
 
std::optional< RaySphereResultray_sphere_intersect (const Point3D &origin, const Vector3D &dir, const Point3D &center, double radius)
 射线-球体求交(解析法) 更多...
 
std::optional< RaySphereResultray_sphere_intersect (const Ray3Dd &ray, const Point3D &center, double radius)
 射线-球体求交(Ray3Dd 重载) 更多...
 
std::optional< double > ray_plane_intersect (const Point3D &origin, const Vector3D &dir, const Point3D &plane_point, const Vector3D &plane_normal)
 射线-平面求交 更多...
 
std::optional< double > ray_plane_intersect (const Ray3Dd &ray, const Point3D &plane_point, const Vector3D &plane_normal)
 射线-平面求交(Ray3Dd 重载) 更多...
 
std::optional< RayTriResultray_mesh_intersect (const Point3D &origin, const Vector3D &dir, const std::vector< Triangle3D > &triangles)
 射线-网格求交(暴力遍历) 更多...
 
std::optional< RayTriResultray_mesh_intersect (const Ray3Dd &ray, const std::vector< Triangle3D > &triangles)
 射线-网格求交(Ray3Dd 重载) 更多...
 
bool sat_intersect (const std::vector< Point3D > &verts_a, const std::vector< std::array< int, 3 >> &faces_a, const std::vector< Point3D > &verts_b, const std::vector< std::array< int, 3 >> &faces_b)
 SAT 凸多面体相交检测 更多...
 
bool tri_tri_intersect (const Triangle3D &t1, const Triangle3D &t2)
 三角形-三角形相交检测(布尔测试) 更多...
 
TriTriIntersection tri_tri_intersect_detailed (const Triangle3D &t1, const Triangle3D &t2)
 三角形-三角形详细相交检测 更多...
 
bool tri_aabb_overlap (const Triangle3D &tri, const AABB3D &box)
 三角形-AABB 快速相交测试 更多...
 

类型定义说明

◆ SupportFunc

using vde::collision::SupportFunc = typedef std::function<Point3D(const Vector3D&)>

支撑函数类型

给定方向向量 d,返回形状在该方向上最远点的坐标:

Point3D support(const Vector3D& d) {
return argmax_{v ∈ shape} dot(v, d);
}
foundation::Vector3D Vector3D
双精度三维向量(重新导出)
Definition: point.h:49
foundation::Point3D Point3D
双精度三维点(重新导出)
Definition: point.h:31

支撑函数是 GJK / EPA 算法的核心抽象。 只要实现了支撑函数,即可用于任意凸形状的碰撞检测。

在文件 gjk.h33 行定义.

函数说明

◆ gjk_distance()

double vde::collision::gjk_distance ( const SupportFunc shape_a,
const SupportFunc shape_b 
)

GJK 最近距离查询

在 gjk_intersect 基础上,不相交时额外调用 EPA (Expanding Polytope Algorithm) 计算两形状之间的精确最近距离。

参数
shape_a形状 A 的支撑函数
shape_b形状 B 的支撑函数
返回
最近距离(相交时返回 0),始终 ≥ 0
参见
gjk_intersect, gjk_full

◆ gjk_full()

GJKResult vde::collision::gjk_full ( const SupportFunc shape_a,
const SupportFunc shape_b 
)

GJK 完整检测:碰撞状态、距离、最近点对

融合 gjk_intersect 和 gjk_distance,一次调用返回 碰撞状态、最近距离及两形状上的最近点。

参数
shape_a形状 A 的支撑函数
shape_b形状 B 的支撑函数
返回
GJKResult 包含碰撞状态、距离、最近点对
注解
对于连续碰撞检测 (CCD) 或需要分离向量的场景, 使用此函数可同时获取碰撞信息和穿透深度方向。
auto result = gjk_full(a_support, b_support);
if (result.intersect) {
// 穿透,分离方向 = (point_b - point_a).normalized()
} else {
double gap = result.distance; // 间隙
}
GJKResult gjk_full(const SupportFunc &shape_a, const SupportFunc &shape_b)
GJK 完整检测:碰撞状态、距离、最近点对
参见
gjk_intersect, gjk_distance

◆ gjk_intersect()

bool vde::collision::gjk_intersect ( const SupportFunc shape_a,
const SupportFunc shape_b 
)

GJK 相交检测(仅判断是否碰撞)

构造 Minkowski 差 A − B,在原点附近迭代构建单纯形。 若原点在 Minkowski 差内 → 碰撞。

算法流程:

  1. 取初始方向(如 a.center − b.center)
  2. 计算支撑点并加入单纯形
  3. 判断单纯形是否包含原点
  4. 若不包含,更新搜索方向并迭代
  5. 若方向无法收敛 → 不相交

时间复杂度 O(n),其中 n 为迭代次数(通常 < 20 对于紧凑形状)。

参数
shape_a形状 A 的支撑函数
shape_b形状 B 的支撑函数
返回
相交返回 true
auto sphere_support = [&](const Vector3D& d) {
return center + radius * d.normalized();
};
auto box_support = [&](const Vector3D& d) {
return center + Vector3D{
half_extent.x * (d.x > 0 ? 1 : -1),
half_extent.y * (d.y > 0 ? 1 : -1),
half_extent.z * (d.z > 0 ? 1 : -1)
};
};
if (gjk_intersect(sphere_support, box_support)) { ... }
bool gjk_intersect(const SupportFunc &shape_a, const SupportFunc &shape_b)
GJK 相交检测(仅判断是否碰撞)
参见
gjk_distance, gjk_full, SupportFunc

◆ ray_aabb_intersect()

bool vde::collision::ray_aabb_intersect ( const Ray3Dd &  ray,
const AABB3D &  box,
double &  tmin_out,
double &  tmax_out 
)

射线-AABB 求交(slab 方法)

分别检测射线与三个坐标轴方向 slab(平板块)的交点, 取最大 t_min 和最小 t_max。若 t_min ≤ t_max 且 t_max ≥ 0,则命中。

复杂度 O(1)。

参数
ray射线
box轴对齐包围盒
tmin_out[输出] 进入包围盒的参数 t
tmax_out[输出] 离开包围盒的参数 t
返回
命中返回 true
注解
常用于 BVH 遍历节点的快速 rejection test
参见
ray_triangle_intersect

◆ ray_mesh_intersect() [1/2]

std::optional<RayTriResult> vde::collision::ray_mesh_intersect ( const Point3D &  origin,
const Vector3D &  dir,
const std::vector< Triangle3D > &  triangles 
)

射线-网格求交(暴力遍历)

遍历所有三角形,对每个三角形调用 ray_triangle_intersect, 跟踪最小 t 值返回最近命中。

复杂度 O(n),n 为三角形数量。

参数
origin射线起点
dir射线方向
triangles三角形列表
返回
最近命中结果;无命中返回空
注解
对于大型网格建议配合 BVH 使用:
BVH bvh;
bvh.build(triangles);
auto hit = bvh.query_ray_nearest(ray); // O(log n)
参见
ray_tri_intersect.h, query_ray_nearest (BVH)

被这些函数引用 ray_mesh_intersect().

◆ ray_mesh_intersect() [2/2]

std::optional<RayTriResult> vde::collision::ray_mesh_intersect ( const Ray3Dd &  ray,
const std::vector< Triangle3D > &  triangles 
)
inline

射线-网格求交(Ray3Dd 重载)

参数
ray射线
triangles三角形列表
返回
最近命中结果;无命中返回空

在文件 ray_intersect.h210 行定义.

引用了 ray_mesh_intersect().

◆ ray_plane_intersect() [1/2]

std::optional<double> vde::collision::ray_plane_intersect ( const Point3D &  origin,
const Vector3D &  dir,
const Point3D &  plane_point,
const Vector3D &  plane_normal 
)

射线-平面求交

解 t = dot(plane_point − origin, plane_normal) / dot(dir, plane_normal)。 若分母 ≈ 0(射线平行于平面)→ 无交点。

参数
origin射线起点
dir射线方向
plane_point平面上一点
plane_normal平面法线(需归一化以获得正确 t)
返回
命中返回参数 t;未命中(平行或反向)返回空

被这些函数引用 ray_plane_intersect().

◆ ray_plane_intersect() [2/2]

std::optional<double> vde::collision::ray_plane_intersect ( const Ray3Dd &  ray,
const Point3D &  plane_point,
const Vector3D &  plane_normal 
)
inline

射线-平面求交(Ray3Dd 重载)

参数
ray射线
plane_point平面上一点
plane_normal平面法线
返回
命中返回参数 t;未命中返回空

在文件 ray_intersect.h170 行定义.

引用了 ray_plane_intersect().

◆ ray_sphere_intersect() [1/2]

std::optional<RaySphereResult> vde::collision::ray_sphere_intersect ( const Point3D &  origin,
const Vector3D &  dir,
const Point3D &  center,
double  radius 
)

射线-球体求交(解析法)

解二次方程 |origin + t*dir − center|² = r²。 通过判别式 Δ = b² − 4ac 判断:

  • Δ < 0 → 无交点
  • Δ = 0 → 切点(一个交点)
  • Δ > 0 → 两个交点(返回较近的)

复杂度 O(1)。

参数
origin射线起点
dir射线方向
center球心
radius球半径
返回
命中返回 RaySphereResult(最近交点);未命中返回空
参见
ray_sphere_intersect(ray, center, radius)

被这些函数引用 ray_sphere_intersect().

◆ ray_sphere_intersect() [2/2]

std::optional<RaySphereResult> vde::collision::ray_sphere_intersect ( const Ray3Dd &  ray,
const Point3D &  center,
double  radius 
)
inline

射线-球体求交(Ray3Dd 重载)

参数
ray射线
center球心
radius球半径
返回
命中返回 RaySphereResult;未命中返回空

在文件 ray_intersect.h141 行定义.

引用了 ray_sphere_intersect().

◆ ray_triangle_intersect() [1/2]

std::optional<RayTriResult> vde::collision::ray_triangle_intersect ( const Point3D &  origin,
const Vector3D &  dir,
const Triangle3D &  tri 
)

射线-三角形求交(Möller-Trumbore 算法)

标准 MT 算法,直接计算重心坐标 u, v 和参数 t。 不预先计算平面方程,一步到位检测。

算法:

  1. 计算两个边向量 e1 = v1−v0, e2 = v2−v0
  2. 计算 pvec = dir × e2, det = dot(e1, pvec)
  3. 若 |det| < ε → 射线平行于三角形(无命中)
  4. 计算 tvec = origin−v0, u, v, t
  5. 验证 u≥0, v≥0, u+v≤1, t>0 → 命中

复杂度 O(1)。

参数
origin射线起点
dir射线方向(需归一化以获得正确 t 值)
tri三角形
返回
命中返回 RayTriResult;未命中返回空
if (auto hit = ray_triangle_intersect(origin, dir, tri)) {
std::cout << "Hit at t=" << hit->t
<< " barycentric=(" << hit->u << "," << hit->v << ")\n";
}
std::optional< RayTriResult > ray_triangle_intersect(const Point3D &origin, const Vector3D &dir, const Triangle3D &tri)
射线-三角形求交(Möller-Trumbore 算法)
参见
ray_mesh_intersect

被这些函数引用 ray_triangle_intersect().

◆ ray_triangle_intersect() [2/2]

std::optional<RayTriResult> vde::collision::ray_triangle_intersect ( const Ray3Dd &  ray,
const Triangle3D &  tri 
)
inline

射线-三角形求交(Ray3Dd 重载)

参数
ray射线
tri三角形
返回
命中返回 RayTriResult;未命中返回空
参见
ray_triangle_intersect(origin, dir, tri)

在文件 ray_intersect.h76 行定义.

引用了 ray_triangle_intersect().

◆ sat_intersect()

bool vde::collision::sat_intersect ( const std::vector< Point3D > &  verts_a,
const std::vector< std::array< int, 3 >> &  faces_a,
const std::vector< Point3D > &  verts_b,
const std::vector< std::array< int, 3 >> &  faces_b 
)

SAT 凸多面体相交检测

分离轴定理:两个凸多面体不相交,当且仅当存在一条分离轴, 使得二者在该轴上的投影区间不重叠。

待检测的分离轴集合:

  • A 的每个面法线
  • B 的每个面法线
  • A 的每条边与 B 的每条边的叉积

对每条候选轴,计算两个多面体投影区间的最小/最大值。 若某轴上投影区间无重叠 → 不相交(早停)。 所有轴都重叠 → 相交。

最坏时间复杂度 O(n_a · n_b),其中 n_a, n_b 为面数。 对于凸多面体通常在遍历部分轴后即早停。

参数
verts_a多面体 A 的顶点数组
faces_a多面体 A 的面索引数组(每个面为 {v0, v1, v2})
verts_b多面体 B 的顶点数组
faces_b多面体 B 的面索引数组
返回
相交返回 true
注解
适用于任意凸多面体。对于胶囊/球等光滑形状,GJK 更合适。
// 两个凸四面体相交检测
std::vector<Point3D> va = {{0,0,0}, {1,0,0}, {0,1,0}, {0,0,1}};
std::vector<std::array<int,3>> fa = {{0,2,1}, {0,1,3}, {0,3,2}, {1,2,3}};
std::vector<Point3D> vb = {{0.5,0.5,0.5}, {1.5,0.5,0.5}, ...};
std::vector<std::array<int,3>> fb = { ... };
bool hit = sat_intersect(va, fa, vb, fb);
bool sat_intersect(const std::vector< Point3D > &verts_a, const std::vector< std::array< int, 3 >> &faces_a, const std::vector< Point3D > &verts_b, const std::vector< std::array< int, 3 >> &faces_b)
SAT 凸多面体相交检测
参见
gjk_intersect, tri_tri_intersect

◆ tri_aabb_overlap()

bool vde::collision::tri_aabb_overlap ( const Triangle3D &  tri,
const AABB3D &  box 
)

三角形-AABB 快速相交测试

使用分离轴定理在三角形和轴对齐包围盒之间检测。 候选分离轴包括(共 13 轴):

  • 3 条 AABB 面法线
  • 1 条三角形面法线
  • 9 条边×边叉积(3 条 AABB 边 × 3 条三角形边)

复杂度 O(1)。

参数
tri三角形
box轴对齐包围盒
返回
相交返回 true
注解
AABB 碰撞比三角剖分后的三角-三角检测更高效, 常用于空间划分结构中的 rejection test。
if (tri_aabb_overlap(tri, node_bounds)) {
// 需要进一步检测节点内的三角形
}
bool tri_aabb_overlap(const Triangle3D &tri, const AABB3D &box)
三角形-AABB 快速相交测试
参见
tri_tri_intersect, ray_aabb_intersect

◆ tri_tri_intersect()

bool vde::collision::tri_tri_intersect ( const Triangle3D &  t1,
const Triangle3D &  t2 
)

三角形-三角形相交检测(布尔测试)

使用分离轴定理在两组三角形之间检测相交。 候选分离轴包括:

  • 每个三角形的面法线(2 轴)
  • 每对边的叉积(3×3 = 9 轴)
  • 共 11 轴(三角形退化为共面时可能有更多)

若存在一条轴使得两三角形投影区间不重叠 → 不相交。

复杂度 O(1)(固定 11+ 轴检测)。

参数
t1三角形 1
t2三角形 2
返回
相交返回 true
Triangle3D t1 = {p0, p1, p2};
Triangle3D t2 = {q0, q1, q2};
if (tri_tri_intersect(t1, t2)) {
// 处理碰撞
}
bool tri_tri_intersect(const Triangle3D &t1, const Triangle3D &t2)
三角形-三角形相交检测(布尔测试)
Triangle< double > Triangle3D
双精度三维三角形
Definition: triangle.h:105
参见
tri_tri_intersect_detailed, sat_intersect

◆ tri_tri_intersect_detailed()

TriTriIntersection vde::collision::tri_tri_intersect_detailed ( const Triangle3D &  t1,
const Triangle3D &  t2 
)

三角形-三角形详细相交检测

返回两三角形相交的交点线段(两个端点)。 适用于需要精确接触几何的场景,如:

  • 物理引擎的接触流形生成
  • CSG 构造体几何的精确分割线
  • 网格自交修复

算法:

  1. 用平面方程计算各顶点到对方平面的有符号距离
  2. 找到边-平面交点形成交集段
  3. 限制交集段到两个三角形内部
参数
t1三角形 1
t2三角形 2
返回
TriTriIntersection:相交标志 + 交点段端点
注解
共面情况交集段可能退化为单点(p0 == p1)
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;
}
TriTriIntersection tri_tri_intersect_detailed(const Triangle3D &t1, const Triangle3D &t2)
三角形-三角形详细相交检测
参见
tri_tri_intersect