Cannonjs中applyLocalForce的用法

0 阅读3分钟

在物理引擎中,applyLocalForce 是一个非常重要的方法,用于对刚体施加局部力。结合代码,我将详细解释 applyLocalForce 的用法,并阐述如何通过调整参数和逻辑让运动最终停止。


1. applyLocalForce** 的用法**

定义

applyLocalForce 是 Cannon.js 提供的一个方法,用于在物体的局部坐标系中施加力。局部坐标系是指相对于物体自身的位置和方向的坐标系,而不是全局世界坐标系。

语法

body.applyLocalForce(force: Cannon.Vec3, relativePoint: Cannon.Vec3)
  • force:表示施加的力向量(Cannon.Vec3),它决定了力的大小和方向。
  • relativePoint:表示力的作用点相对于物体中心的位置(Cannon.Vec3)。如果设置为 (0, 0, 0),则力作用在物体的质心上。

示例

在代码中,applyLocalForce 用于给球体施加一个初始力,使其在场景中移动:

sphereBody.applyLocalForce(direction.scale(600), new Cannon.Vec3(0, 0, 0))
  • direction.scale(600)
    • direction 是一个单位向量,表示力的方向。
    • .scale(600) 将力的大小放大到 600。
  • new Cannon.Vec3(0, 0, 0)
    • 表示力作用在球体质心上。

这段代码的效果是:当用户点击鼠标时,会根据鼠标的方向生成一个力,并将其施加到球体上,使球体开始运动。


2. 让运动更符合实际

让运动更符合实际,可以从以下几个方面进行调整:

(1) 增加摩擦力 (friction)

摩擦力会减缓物体的运动速度,尤其是在接触地面时。你可以在创建接触材质时增加摩擦力值:

const contactMaterial = new Cannon.ContactMaterial(groundMaterial, sphereMaterial, {
  friction: 0.8, // 增加摩擦力
  restitution: 0.5,
})
  • 较高的摩擦力会使物体在地面上滑动时更快减速。

(2) 减少恢复系数 (restitution)

恢复系数控制碰撞后反弹的能量保留程度。较低的恢复系数可以减少反弹,使物体更快停止:

const contactMaterial = new Cannon.ContactMaterial(groundMaterial, sphereMaterial, {
  friction: 0.8,
  restitution: 0.1, // 减少反弹
})
  • 将恢复系数从 0.5 降低到 0.1,可以有效减少碰撞后的反弹。

(3) 添加阻尼 (linearDamping** 和 angularDamping)**

阻尼是一种模拟空气阻力或内部能量损耗的机制。可以通过设置线性阻尼和角阻尼来让物体逐渐减速:

sphereBody.linearDamping = 0.9 // 线性阻尼
sphereBody.angularDamping = 0.9 // 角阻尼
  • 线性阻尼 (linearDamping):控制直线运动的减速。
  • 角阻尼 (angularDamping):控制旋转运动的减速。
  • 阻尼值越接近 1,减速越快。

(4) 调整重力

物理世界的重力会影响物体的运动。确保重力设置合理,以避免物体漂浮或运动异常:

world.gravity.set(0, -9.82, 0) // 设置标准重力
  • 如果重力过小,物体可能不会自然停止。

(5) 控制时间步长

物理世界的更新频率也会影响运动行为。推荐使用固定时间步长更新物理世界:

const timeStep = 1 / 60 // 每秒 60 帧
world.step(timeStep)
  • 固定时间步长可以提高物理模拟的稳定性。

3. 综合实现

以下是一个完整的实现示例,展示了如何结合 applyLocalForce 和上述调整来创建一个物理运动系统,并让运动最终停止:

// 创建物理世界
world = new Cannon.World()
world.gravity.set(0, -9.82, 0)

// 创建接触材质
const groundMaterial = new Cannon.Material('groundMaterial')
const sphereMaterial = new Cannon.Material('sphereMaterial')
const contactMaterial = new Cannon.ContactMaterial(groundMaterial, sphereMaterial, {
  friction: 0.8, // 增加摩擦力
  restitution: 0.1, // 减少反弹
})
world.addContactMaterial(contactMaterial)

// 创建地面刚体
const groundBody = new Cannon.Body({
  mass: 0, // 质量为 0 表示静态物体
  shape: new Cannon.Plane(),
  material: groundMaterial,
})
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0)
world.addBody(groundBody)

// 创建球体
function createSphere(position: THREE.Vector3, direction: Cannon.Vec3) {
  // 可视球体
  const sphere = new THREE.Mesh(
    new THREE.SphereGeometry(2, 32, 32),
    new THREE.MeshBasicMaterial({ color: 0xff11ff }),
  )
  sphere.position.set(position.x, position.y, position.z)
  scene.add(sphere)

  // 物理球体
  const sphereBody = new Cannon.Body({
    mass: 1,
    shape: new Cannon.Sphere(2),
    position: new Cannon.Vec3(position.x, position.y, position.z),
    material: sphereMaterial,
  })
  sphereBody.linearDamping = 0.9 // 线性阻尼
  sphereBody.angularDamping = 0.9 // 角阻尼

  // 施加局部力
  sphereBody.applyLocalForce(direction.scale(600), new Cannon.Vec3(0, 0, 0))

  world.addBody(sphereBody)
}

// 更新物理世界
function updatePhysic() {
  world.step(1 / 60)
}

4. 总结

  • applyLocalForce:用于在物体的局部坐标系中施加力,通常用于初始化运动。
  • 让运动停止的关键
    • 增加摩擦力 (friction)。
    • 减少恢复系数 (restitution)。
    • 添加阻尼 (linearDampingangularDamping)。
    • 调整重力和时间步长。