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

书洞笔记

相关推荐
在下千玦2 分钟前
#前端js发异步请求的几种方式
开发语言·前端·javascript
知否技术3 分钟前
面试官最爱问的Vue3响应式原理:我给你讲明白了!
前端·vue.js
小周同学:1 小时前
vue将页面导出成word
前端·vue.js·word
阿杰在学习1 小时前
基于OpenGL ES实现的Android人体热力图可视化库
android·前端·opengl
xfq1 小时前
[ai] cline使用总结(包括mcp)
前端·后端·ai编程
weiran19991 小时前
手把手的建站思路和dev-ops方案
前端·后端·架构
小刀飘逸1 小时前
子元素 margin-top 导致父元素下移问题的分析与解决方案
前端
Evrytos1 小时前
告别石器时代#2:ES6新数据类型
前端·javascript
Ody1 小时前
大屏开发适配方案全面解析
前端
java1234_小锋1 小时前
一周学会Flask3 Python Web开发-SQLAlchemy数据迁移migrate
开发语言·前端·python·flask·flask3