Three.js引入Cannon.js及使用示例详解
随便起一个名字吧 人气:0引言
在开始之前,我们还是要解释下什么是 Cannon.js 以及它的作用。
Cannon.js 是一个 3D 物理引擎,通过为物体赋予真实的物理属性的方式来计算运动、旋转和碰撞检测。Cannon.js 相较于其他常见的物理引擎来说,比较轻量级而且完全通过 JavaScript 来实现。
Cannon.js 的官方文档地址为 schteppe.github.io/cannon.js/ ,从官方介绍中也可以看到很多有趣的例子,如下所示:
本篇,我们就尝试用 Three.js + Cannon.js 做一个简单的示例。
首先我们通过 Three.js 创建一个球及一个平面,前面已经介绍过很多关于 Three.js 如何使用,这里就不多做介绍了
大体代码及效果
const sphere = new THREE.Mesh( new THREE.SphereGeometry(1, 20, 20), new THREE.MeshStandardMaterial() ); scene.add(sphere); const floor = new THREE.Mesh( new THREE.PlaneGeometry(20, 20), new THREE.MeshStandardMaterial() ); floor.position.y = -5; floor.rotation.x = -Math.PI / 2; scene.add(floor);
在开始正式使用物理引擎之前,我们需要先弄清一些概念,Three.js 是渲染引擎,Cannon.js 是物理引擎。渲染引擎负责画 UI,而物理引擎负责运动。
我们通过物理引擎打造一个和当前 UI 一样的世界,然后让引擎运动起来,然后将运动物体的坐标实时反映到渲染引擎中,这样使得物理引擎和渲染引擎协同工作。
Cannon.js 打造当前 UI
所以第一步,利用 Cannon.js 打造和当前 UI 一样的物理世界
import * as CANNON from "cannon-es"; // 创建物理世界 const world = new CANNON.World(); world.gravity.set(0, -9.8, 0); // 创建物理小球形状 const sphereShape = new CANNON.Sphere(1); // 设置物体材质 const sphereWorldMaterial = new CANNON.Material(); // 创建物理世界的物体 const sphereBody = new CANNON.Body({ shape: sphereShape, // 位置 position: new CANNON.Vec3(0, 0, 0), // 小球质量 mass: 1, // 物体材质 material: sphereWorldMaterial, }); // 将物体添加至物理世界 world.addBody(sphereBody); // 创建地面 const floorShape = new CANNON.Plane(); const floorBody = new CANNON.Body(); // 当质量为0时,使得物体保持不动 floorBody.mass = 0; floorBody.addShape(floorShape); // 位置 floorBody.position.set(0, -5, 0); // 旋转 floorBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2); world.addBody(floorBody);
如此便打造了一个和 UI 一样的物理世界,代码很简单,相信通过注释就能明白做了什么事情。
下面就是让物理引擎“动起来”,并将物体的坐标同步赋值给渲染引擎中的物体。
从文档中可以看到,step
就是我们想要的方法,利用 step
更新物理引擎世界的物体,随后将 sphereBody
的 position
赋值给 Three.js 中的 sphere
。
const clock = new THREE.Clock(); function render() { // 更新物理引擎世界的物体 world.step(1 / 60, clock.getDelta()); sphere.position.copy(sphereBody.position); controls.update(); renderer.render(scene, camera); // 渲染下一帧的时候就会调用 render 函数 requestAnimationFrame(render); } render();
如此便实现了 Three.js 和 Cannon.js 的联动,最终效果如下图所示:
加载全部内容