逆质量:质量的倒数(inverse mass, 1/mass)
1. 为什么要用逆质量(Inverse Mass)?
(1)避免重复除法计算
在实时物理系统中,经常需要计算 F/m
(例如加速度 a = F_net / m
)。如果每次计算都做除法,当物体数量较大时会显著增加计算开销。而用逆质量后:
a = F_net * inv_mass; // inv_mass = 1/mass,提前预计算一次
- 除法变乘法:除法运算在多数CPU架构中代价更高,替换为乘法可提升性能。
(2)数学表达更简洁
许多物理公式(如碰撞冲击响应、约束力求解)涉及 1/mass
的项。例如动量守恒中的相对速度修正:
\(\Delta v = \frac{J}{m}\)
如果预先存入逆质量 inv_mass
,可直接调用乘积,避免公式中出现除法符号。
(3)特殊情况的统一处理
- 无限大质量(静态物体):设置
inv_mass = 0
,表示静态物体(质量极大,无法移动)。 - 零质量(非法值):不允许设置为零,通过
inv_mass
的参数设计提前杜绝除以零的风险。
2. 逆质量的代码实现
(1)基础实现
为 Particle
类添加逆质量成员,并确保与 mass
的参数同步:
class Particle {
public:
Vector2 position;
Vector2 velocity;
Vector2 force;
float inv_mass; // 关键变化:用逆质量代替质量
// 设置初始质量
void SetMass(float mass) {
// 质量必须严格大于零
if (mass <= 0.0f) {
inv_mass = 0.0f; // 默认为静态物体
return;
}
inv_mass = 1.0f / mass;
}
// 外力累加逻辑不变
void ApplyForce(Vector2 f) {
force += f;
}
void Update(float dt) {
// 关键不同点:直接用逆质量计算加速度
Vector2 acceleration = force * inv_mass;
velocity += acceleration * dt;
position += velocity * dt;
force = Vector2(0, 0);
}
};
(2)静态物体的标识
例如设置一堵墙的质量为无穷大,对应的 inv_mass = 0
:
Particle static_obstacle;
static_obstacle.SetMass(0.0f); // inv_mass 设为0,永远不受力
(3)动态调整质量
修改质量后需要更新 inv_mass
(如爆炸后物体质量变化):
void Particle::ChangeMass(float new_mass) {
SetMass(new_mass); // 更新 inv_mass 值
}
3. 逆质量在物理引擎中的应用
(1)力-加速度类计算
所有需要计算 a=F/m
的地方直接替换为 a=F*inv_mass
。
例如全局重力应用:
Vector2 gravity(0, 9.8f);
void ApplyGravity(Particle& p) {
Vector2 force = gravity * (p.inv_mass > 0.0f ? (1.0f / p.inv_mass) : 0.0f);
p.ApplyForce(force);
}
更优化的写法:根据
inv_mass
是否为0区分静态物体,避免判断mass
有效性。
(2)碰撞响应中的冲量(Impulse)计算
碰撞处理中冲量公式的核心是:
\(J = \frac{-(1 + e) \cdot v_{\text{rel}} \cdot n}{n \cdot n \cdot (inv\_mass_A + inv\_mass_B)}\)
代码中直接使用 inv_mass
可以让表达式更短且无除法:
Vector2 normal = GetCollisionNormal();
float inv_mass_sum = bodyA.inv_mass + bodyB.inv_mass;
float impulse = -(1.0f + restitution) * dot(relative_velocity, normal);
impulse /= dot(normal, normal) * inv_mass_sum;
bodyA.velocity += impulse * bodyA.inv_mass * normal;
bodyB.velocity -= impulse * bodyB.inv_mass * normal;
4. 深度优化:Scalar Inv_Mass 的扩展
一些引擎会引入 标量逆质量(scalar inverse mass),用于处理旋转惯性矩:
struct RigidBody {
Vector2 position;
float rotation;
Vector2 velocity;
float angular_velocity;
float inv_mass;
float inv_inertia; // 标量逆转动惯量
// 动力学方程中扭矩到角加速度的转换:
// angular_acceleration = torque * inv_inertia
};
用统一模式处理平动和旋转的动力学计算,提升代码一致性。
总结
逆质量是工业级物理系统的核心优化方向之一,其价值贯穿于以下三点:
- 加速计算:除法转乘法优化高频代码路径。
- 代码清晰:消弭公式中的除法干扰,易于阅读。
- 逻辑统一:无缝支持动态/静态物体区分。