Threejs 物理引擎高阶:作用力、休眠与组合体奥秘

休眠

当一个物体在小范围内移动时,物理引擎会认为它是静止的,此时物体就会进入休眠状态,不再受到物理引擎的影响。休眠状态可以减少物理引擎的计算量,提高性能。

  • 设置物理世界休眠
js 复制代码
const world = new CANNON.World();
world.allowSleep = true;

allowSleep: 是否允许休眠,默认为 false。

  • 设置物体休眠
js 复制代码
const boxBody = new CANNON.Body({
  shape: new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5)),
  position: new CANNON.Vec3(-2, 5, 0),
  mass: 1,
  material: boxMaterialCon,
  collisionFilterGroup: GROUP1,
  collisionFilterMask: GROUP1 | GROUP2 | GROUP3 | GROUP4,
});
boxBody.allowSleep = true; // 允许休眠
boxBody.sleepSpeedLimit = 0.5; //速度小于0.5时休眠
boxBody.sleepTimeLimit = 1; // 休眠时间超过1秒
world.addBody(boxBody);

sleepSpeedLimit: 速度小于该值时,物体进入休眠状态。

sleepTimeLimit: 休眠时间超过该值时,物体从休眠状态恢复。

休眠事件

当物体从运动状态到休眠状态,会触发很多事件,我们可以监听这些事件,做一些操作。

  • 监听物体休眠事件
js 复制代码
boxBody.addEventListener("sleep", () => {
  console.log("休眠");
});
  • 监听即将休眠事件
js 复制代码
boxBody.addEventListener("sleepy", () => {
  console.log("即将休眠");
});

物体组合

将多个物体组合成一个物体,可以减少物理引擎的计算量,提高性能。

js 复制代码
// 创建一个物理组合体
const capsuleBody = new CANNON.Body({
  mass: 1,
  position: new CANNON.Vec3(0, 4, 0),
  material: boxMaterialCon,
  collisionFilterGroup: GROUP2,
  collisionFilterMask: GROUP1 | GROUP2 | GROUP3,
});
//创建球体
const sphereShape = new CANNON.Sphere(0.5);
//创建圆柱体
const cylinderShape = new CANNON.Cylinder(0.5, 0.5, 1.5, 20);
//创建胶囊体
capsuleBody.addShape(sphereShape, new CANNON.Vec3(0, 0.75, 0));
capsuleBody.addShape(cylinderShape, new CANNON.Vec3(0, 0, 0));
capsuleBody.addShape(sphereShape, new CANNON.Vec3(0, -0.75, 0));
capsuleBody.velocity.set(2, 0, 0); //设置速度
world.addBody(capsuleBody);

//创建胶囊体网格
const capsuleGeometry = new THREE.CylinderGeometry(0.5, 0.5, 1.5, 20);
const capsuleMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const capsule = new THREE.Mesh(capsuleGeometry, capsuleMaterial);
capsule.position.copy(capsuleBody.position);
capsule.quaternion.copy(capsuleBody.quaternion);
scene.add(capsule);
//创建球体网格
const sphereGeometry = new THREE.SphereGeometry(0.5, 20, 20);
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(0, 0.75, 0);
capsule.add(sphere);
const sphere2 = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere2.position.set(0, -0.75, 0);
capsule.add(sphere2);

addShape: 添加形状,第一个参数为形状,第二个参数为形状相对于物体的位置。

施加力

给物体施加力,可以让物体运动。

applyForce

js 复制代码
//创建物理球
const sphereBody = new CANNON.Body({
  mass: 1,
  shape: new CANNON.Sphere(0.5),
  position: new CANNON.Vec3(0, 5, 0),
  material: boxMaterialCon,
  collisionFilterGroup: GROUP2,
  collisionFilterMask: GROUP1 | GROUP2 | GROUP3,
});
world.addBody(sphereBody);

//创建3D球
const sphereGeometry = new THREE.SphereGeometry(0.5, 8, 8);
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
scene.add(sphere);

//监听鼠标点击事件
window.addEventListener("click", () => {
  console.log("点击了:", sphereBody.position);
  sphereBody.applyForce(new CANNON.Vec3(10, 0, 0), sphereBody.position);
});

applyForce: 施加力,第一个参数为力的大小,第二个参数为力的方向。

applyLocalForce

js 复制代码
sphereBody.quaternion.setFromAxisAngle(new CANNON.Vec3(0, 0, 1), Math.PI / 2); //设置旋转

window.addEventListener("click", () => {
  console.log("点击了:", sphereBody.position);
  sphereBody.applyLocalForce(new CANNON.Vec3(10, 0, 0), new CANNON.Vec3(0, -0.5, 0));
});

applyLocalForce: 施加局部力,第一个参数为力的大小,第二个参数为力的方向。

这个是相对物体自身的力,物体自身旋转后,力的方向也会跟着旋转。就会出现向后滚动的效果。

applyImpulse

js 复制代码
sphereBody.applyImpulse(new CANNON.Vec3(10, 0, 0), sphereBody.position);

applyImpulse: 施加冲量,第一个参数为冲量的大小,第二个参数为冲量的方向。

冲量是力的积累,力的作用时间越长,冲量越大。所以如果想达到上面的效果,就需要修改冲量的大小。如果是 60 帧,那么就需要将冲量的大小改为 new CANNON.Vec3(10*(1/60), 0, 0)

applyTorque

js 复制代码
sphereBody.applyTorque(new CANNON.Vec3(0, 0, 10));

applyTorque: 施加扭矩,第一个参数为扭矩的大小,第二个参数为扭矩的方向。

书洞笔记

相关推荐
爱吃鱼的锅包肉6 分钟前
Flutter路由模块化管理方案
前端·javascript·flutter
风清扬雨33 分钟前
Vue3具名插槽用法全解——从零到一的详细指南
前端·javascript·vue.js
大熊猫今天吃什么1 小时前
【一天一坑】空数组,使用 allMatch 默认返回true
前端·数据库
!win !1 小时前
Tailwind CSS一些你需要记住的原子类
前端·tailwindcss
前端极客探险家1 小时前
打造一个 AI 面试助手:输入岗位 + 技术栈 → 自动生成面试问题 + 标准答案 + 技术考点图谱
前端·人工智能·面试·职场和发展·vue
橘子味的冰淇淋~2 小时前
【解决】Vue + Vite + TS 配置路径别名成功仍爆红
前端·javascript·vue.js
利刃之灵2 小时前
03-HTML常见元素
前端·html
kidding7232 小时前
gitee新的仓库,Vscode创建新的分支详细步骤
前端·gitee·在仓库创建新的分支
听风吹等浪起2 小时前
基于html实现的课题随机点名
前端·html
leluckys2 小时前
flutter 专题 六十三 Flutter入门与实战作者:xiangzhihong8Fluter 应用调试
前端·javascript·flutter