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: 施加扭矩,第一个参数为扭矩的大小,第二个参数为扭矩的方向。

书洞笔记

相关推荐
烟话65 分钟前
vue3响应式基础
前端·javascript·vue.js
boombb7 分钟前
用户反馈入口
前端
im_AMBER9 分钟前
万字长文:手撕JS深浅拷贝完全指南
前端·javascript·面试
@大迁世界14 分钟前
20.“可复用组件”具体指的是什么?如何设计与产出这类组件?.
开发语言·前端·javascript·ecmascript
Bigger17 分钟前
第二章:我是如何剖析 Claude Code QueryEngine 与大模型交互机制的
前端·ai编程·源码阅读
FelixBitSoul22 分钟前
彻底吃透 React Hook:它背后的执行模型到底是什么? 🚀
前端
Huanzhi_Lin28 分钟前
Nginx本地资源服务器-常用脚本
服务器·前端·nginx·batch·静态资源服务器
weixin1997010801628 分钟前
《好看视频商品详情页前端性能优化实战》
前端·性能优化·音视频
有意义29 分钟前
深入理解浏览器存储方案:从Cookie到JWT登录认证
前端·面试·浏览器
jiayong2330 分钟前
第 6 课:第二轮真实重构,拆出任务表格组件
前端·重构