本文介绍如何使用Three.js进行3D图形渲染,并结合Cannon.js实现物理模拟。通过引入库文件、创建场景与物理世界、关联对象及更新帧逻辑,构建一个包含重力影响的简单物理应用示例。
正文
Three.js与Cannon.js为构建3D游戏及交互式应用的主流JavaScript库,前者负责图形渲染,后者处理物理模拟。本文旨在演示结合二者构建简易物理模拟应用的方法。
在HTML文件中引入Three.js与Cannon.js库
首要步骤是在HTML中引入上述两个库,具体实现代码如下:
<script src="https://cdn.jsdelivr.net/npm/three@0.131.2/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/cannon@0.6.2/build/cannon.min.js"></script>
随后需构建Three.js场景及Cannon.js物理世界,相关代码如下:
// 创建 Three.js 场景
const scene = new THREE.Scene();
// 创建 Cannon.js 物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
创建并添加Three.js对象至场景
此时可生成若干Three.js对象并加入场景。
以创建一个立方体并添加至场景为例:
// 创建一个立方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
// 将立方体添加到场景中
scene.add(cube);
构建Cannon.js物体
接着需创建Cannon.js物体,并将其与Three.js对象建立关联。
实现代码如下:
// 创建 Cannon.js 物体
const shape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5));
const body = new CANNON.Body({ mass: 1 });
body.addShape(shape);
// 将 Cannon.js 物体与 Three.js 对象关联起来
const cubeBody = new THREE.Object3D();
cubeBody.position.copy(cube.position);
scene.add(cubeBody);
world.addBody(body);
每帧更新Three.js对象位置
通过每帧更新Three.js对象位置,以同步Cannon.js物理世界中的物体运动状态。
具体代码如下:
function animate() {
requestAnimationFrame(animate);
// 更新 Cannon.js 物理世界
world.step(1 / 60);
// 更新 Three.js 对象的位置
cube.position.copy(body.position);
cube.quaternion.copy(body.quaternion);
// 渲染场景
renderer.render(scene, camera);
}
animate();
至此,已成功利用Three.js与Cannon.js库构建简易物理模拟应用。可通过增加对象与物体数量来扩展应用,以构建更复杂的物理场景。
完整示例
下方展示一个完整示例:红色小球从高空坠落,并在3秒后生成一个新球。
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 100000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera.position.set(0, 15, 25)
scene.fog = new THREE.Fog(0xffffff, 0, 500);
// 创建 Cannon.js 物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
// 创建地面
const groundShape = new CANNON.Plane();
const groundBody = new CANNON.Body({ mass: 0 });
groundBody.addShape(groundShape);
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2);
// 将地面添加到场景中
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x999999 });
const groundGeometry = new THREE.PlaneGeometry(10000, 10000);
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
scene.add(ground);
// 将 Cannon.js 物体与 Three.js 对象关联起来
const groundBodyMesh = new THREE.Object3D();
groundBodyMesh.position.copy(ground.position);
scene.add(groundBodyMesh);
world.addBody(groundBody);
// 灯光
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 20, 10);
scene.add(light);
// 半球光
const light2 = new THREE.HemisphereLight(0xffffbb, 0x080820, 1);
scene.add(light2);
new THREE.OrbitControls(camera, renderer.domElement);
function createBall() {
// 创建小球
const radius = 5;
const segments = 32;
const geometry = new THREE.SphereGeometry(radius, segments, segments);
// phhong材质
const material = new THREE.MeshPhongMaterial({ color: 0xff0000 });
const ball = new THREE.Mesh(geometry, material);
// 设置小球的初始位置
// x z 位置随机
const x = Math.random() * 4 - 2;
const z = Math.random() * 4 - 2;
ball.position.set(x, 25, z);
// 将小球添加到场景中
scene.add(ball);
// 创建 Cannon.js 物体
const shape = new CANNON.Sphere(radius);
const body = new CANNON.Body({ mass: 1 });
body.addShape(shape);
// 设置小球的初始位置和速度
body.position.set(x, 25, z);
body.velocity.set(0, -9.82, 0);
// 将 Cannon.js 物体与 Three.js 对象关联起来
const ballBody = new THREE.Object3D();
ballBody.position.copy(ball.position);
scene.add(ballBody);
world.addBody(body);
function animateBall() {
// 更新 Cannon.js 物理世界
world.step(1 / 60);
// 更新 Three.js 对象的位置
ball.position.copy(body.position);
ball.quaternion.copy(body.quaternion);
if (body.position.y < 0) {
scene.remove(ball);
world.removeBody(body);
clearInterval(intervalId);
}
renderer.render(scene, camera);
}
const intervalId = setInterval(animateBall, 1000 / 60);
}
createBall();
setInterval(createBall, 3000);
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();以上为Three.js物理引擎Cannon.js创建简单应用程序的详细内容,欲了解更多Three.js物理引擎Cannon.js资料,敬请参阅本站其他文章!