俗话的好工欲善其事,必先利其器,有一个好的工具可以让项目开发更为高效。
这里说下常配合threejs使用的物理引擎库[cannon-es](GitHub - pmndrs/cannon-es:💣一个用JavaScript编写的轻量级3D物理引擎。)。
cannon-es是一个3d物理引擎,它能实现常见的碰撞检测,各种体形,接触,摩擦和约束功能。
在这里我将一步一步使用cannon-es配合threejs
前提基于umi4框架基础上实现,在这里假设你已使用了[umi框架](快速上手 | UmiJS)
- 首先初始化threejs,且引入cannon-es
import * as CANNON from "cannon-es";
...
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
// 设置相机位置
camera.position.set(0, 0, 15);
scene.add(camera);
// 渲染器
const renderer = new THREE.WebGLRenderer({
alpha: true,
});
// 设置渲染大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置渲染器透明
dom.appendChild(renderer.domElement);
renderer.render(scene, camera);
let clock = new THREE.Clock();
const render = () => {
renderer.render(scene, camera);
requestAnimationFrame(render);
};
render();
- threejs与cannon结合,模拟小球受重力影响向下坠落
// 首先我们在场景中创建一个小球
const sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
const sphereMater = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(sphereGeometry, sphereMater);
sphere.castShadow = true;
scene.add(sphere);
// 然后创建一个平面用于后续接收小球
const floor = new THREE.Mesh(
new THREE.PlaneGeometry(20, 20),
new THREE.MeshStandardMaterial()
);
floor.position.set(0, -5, 0);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);
// cannon 使用 ------------------------
// 首先先创建物理世界
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 ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// 平行光
const dirLight = new THREE.DirectionalLight(0xffffff, 0.5);
dirLight.castShadow = true;
scene.add(dirLight);
...
//同时在render函数中不断更新物理世界中的物体
config.World.step(1 / 120, deltaTime);
// 将物理世界中的位置同步到threejs场景中 我们就可以模拟受重力物体向下运动了
config.sphere.position.copy(config.sphereBody.position);
- 实现小球落地面上停下来
// 我们只需要在物理世界中也创建地面,同时将地面添加到物理世界中,在物理世界中小球遇到面物体后会停止下落。
const floorShape = new CANNON.Plane();
const floorBody = new CANNON.Body({
// 设置为0时保证地面不动
mass: 0,
shape: floorShape,
// 需要与threejs中地面位置同步
position: new CANNON.Vec3(0, -5, 0),
});
floorBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2);
World.addBody(floorBody);