判断球体关系的核心是球心距离平方与半径和、差的平方比较:distSq ≤ (r1+r2)² 为相交或接触,distSq < (r1−r2)²(r1≥r2)为内含,distSq > (r1+r2)² 为分离。

怎么算两个球心距离
判断球体关系的核心是球心距离与半径之和、半径之差的比较。先得准确算出两球心 p1 和 p2 的欧氏距离,别直接开方——能用平方就用平方,避免浮点误差和 sqrt 开销。
- 定义球体结构体时,确保坐标成员是
float或double,别混用int导致截断 - 距离平方计算写成
(p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) + (p1.z - p2.z) * (p1.z - p2.z),别漏项或括号错位 - 如果用
glm::distance2(p1, p2)(需包含<glm/gtc/constants.hpp>),注意它返回的是平方距离,正好省去手动开方
碰撞与相交的判定条件怎么写
“碰撞”在几何中通常指外表面接触(即距离等于半径和),“相交”指有重叠体积(距离小于半径和)。实际代码里常合并为“是否相交或接触”,用一个阈值判断更稳妥。
- 设球 A 半径
r1,球 B 半径r2,球心距平方为distSq,则相交/接触条件是:distSq - 若需严格区分“相交”(内部重叠)和“接触”(仅一点相切),加一个 epsilon 判断:
distSq 表示相交;<code>abs(distSq - (r1 + r2) * (r1 + r2)) 表示接触 - 注意:当
r1或r2为 0 时,该公式仍成立(退化为点与球的关系),但需确认业务逻辑是否允许零半径
怎么判断一个球完全包含另一个球
小球被大球完全包含,意味着小球所有点都在大球内部,等价于球心距加上小球半径 ≤ 大球半径。同样优先用平方形式避免开方。
- 假设
r1 >= r2,则完全包含条件是:distSq - 如果不预先比较半径大小,可统一写成:
distSq + min(r1, r2) * min(r1, r2) ,但计算稍多 - 特别注意:当
distSq == 0(球心重合)时,只要r1 != r2就满足包含关系;若r1 == r2,则是完全重合,属于“包含”的边界情况,按需归类
容易忽略的边界和精度问题
看似简单的公式,在实际工程中常因浮点精度和特殊输入翻车。
立即学习“C++免费学习笔记(深入)”;
- 当球心距离极小(如
1e-15)而半径较大时,distSq可能因舍入误差变成负数(虽然数学上不可能),建议加max(distSq, 0.0)防御 - 若球半径可能为负(比如数据解析错误),先做校验:
if (r1 ,否则 <code>(r1 - r2) * (r1 - r2)仍为正,逻辑被扭曲 - 在物理引擎或帧间连续检测中,单帧判定不够——得结合运动矢量做 swept sphere 检测,否则高速小球会“穿模”
球体关系判定本身很稳,真正复杂的是你怎么把 distSq、半径、epsilon 这几个数在特定场景下对齐精度和语义。写完别只测 r=1、r=2 的整数案例,塞几个 1.9999999 和 2.0000001 进去跑跑。


















