Cannon.js 物理引擎入门(Three.js 结合 Cannon.js)

server/2025/3/25 21:01:38/

Cannon.js 是一个基于 JavaScript 的 3D 物理引擎,通常与 Three.js 结合使用,来实现刚体碰撞、重力、弹跳、关节约束等物理效果


1️⃣ 安装 Cannon.js

如果使用 npm

npm install cannon-es

如果用 CDN 方式,可以在 HTML 文件中引入:

<script src="https://cdn.jsdelivr.net/npm/cannon-es@0.20.0/dist/cannon-es.js"></script>

2️⃣ 创建 Cannon.js 物理世界

在 Cannon.js 中,物理世界 (CANNON.World) 负责管理所有物体的物理行为:

import * as CANNON from 'cannon-es';// 创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.81, 0); // 设置重力(Y 轴方向向下)

3️⃣ 创建刚体(Rigid Body)

物理世界中的刚体 ≠ Three.js 的 Mesh

  • CANNON.Body 负责物理行为
  • THREE.Mesh 负责渲染

🔹 创建一个立方体刚体

// 创建刚体的形状(Cannon 只支持基础形状)
const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1)); // 立方体大小 (1,1,1)// 创建刚体
const boxBody = new CANNON.Body({mass: 1,  // 质量(0 = 静态,>0 = 可移动)shape: boxShape
});// 设置刚体初始位置
boxBody.position.set(0, 5, 0);// 将刚体添加到物理世界
world.addBody(boxBody);

4️⃣ 创建静态地面

地面是一个Plane(不可移动的静态物体)

// 创建地面形状
const groundShape = new CANNON.Plane();// 创建地面刚体
const groundBody = new CANNON.Body({mass: 0,  // 质量为 0,表示不会受重力影响(静态)shape: groundShape
});// 旋转地面,使其水平
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0);// 添加到世界
world.addBody(groundBody);

5️⃣ 连接 Three.js

import * as THREE from 'three';// 创建 Three.js 场景
const scene = new THREE.Scene();// 创建 Three.js 立方体
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
const boxMaterial = new THREE.MeshStandardMaterial({ color: 'blue' });
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
scene.add(boxMesh);// 创建 Three.js 地面
const groundGeometry = new THREE.PlaneGeometry(10, 10);
const groundMaterial = new THREE.MeshStandardMaterial({ color: 'green' });
const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
groundMesh.rotation.x = -Math.PI / 2;
scene.add(groundMesh);

6️⃣ 物理世界更新

每一帧都需要 更新物理世界同步刚体位置 到 Three.js:

const clock = new THREE.Clock();const tick = () => {// 计算时间步长const deltaTime = clock.getDelta();// 让物理世界前进一小步world.step(1 / 60, deltaTime, 3);// 更新 Three.js 物体位置boxMesh.position.copy(boxBody.position);boxMesh.quaternion.copy(boxBody.quaternion);// 渲染renderer.render(scene, camera);requestAnimationFrame(tick);
};tick();

7️⃣ 添加弹性(Restitution)

让物体具有弹性(反弹效果)

boxBody.material = new CANNON.Material();
groundBody.material = new CANNON.Material();// 创建接触材质
const contactMaterial = new CANNON.ContactMaterial(boxBody.material, groundBody.material, {friction: 0.1,   // 摩擦力restitution: 0.7 // 弹性(0 = 无弹性,1 = 完全弹性)
});// 添加到物理世界
world.addContactMaterial(contactMaterial);

8️⃣ 物理约束(关节、连接)

🔹 让两个刚体连接在一起

const pivotA = new CANNON.Vec3(0, 1, 0);
const pivotB = new CANNON.Vec3(0, -1, 0);
const constraint = new CANNON.PointToPointConstraint(boxBody, pivotA, anotherBody, pivotB);
world.addConstraint(constraint);

9️⃣ 触发事件

可以监听物体的 碰撞事件

boxBody.addEventListener('collide', (event) => {console.log('碰撞发生!', event);
});

🔟 完整代码示例

import * as THREE from 'three';
import * as CANNON from 'cannon-es';// 创建 Three.js 场景
const scene = new THREE.Scene();// 创建 Three.js 立方体
const boxGeometry = new THREE.BoxGeometry(2, 2, 2);
const boxMaterial = new THREE.MeshStandardMaterial({ color: 'blue' });
const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);
scene.add(boxMesh);// 创建 Three.js 地面
const groundGeometry = new THREE.PlaneGeometry(10, 10);
const groundMaterial = new THREE.MeshStandardMaterial({ color: 'green' });
const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial);
groundMesh.rotation.x = -Math.PI / 2;
scene.add(groundMesh);// 创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.81, 0);// 创建物理立方体
const boxShape = new CANNON.Box(new CANNON.Vec3(1, 1, 1));
const boxBody = new CANNON.Body({ mass: 1, shape: boxShape });
boxBody.position.set(0, 5, 0);
world.addBody(boxBody);// 创建物理地面
const groundShape = new CANNON.Plane();
const groundBody = new CANNON.Body({ mass: 0, shape: groundShape });
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0);
world.addBody(groundBody);// 渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);// 相机
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 100);
camera.position.set(0, 3, 10);// 动画循环
const clock = new THREE.Clock();
const tick = () => {const deltaTime = clock.getDelta();world.step(1 / 60, deltaTime, 3);boxMesh.position.copy(boxBody.position);boxMesh.quaternion.copy(boxBody.quaternion);renderer.render(scene, camera);requestAnimationFrame(tick);
};tick();

💡 总结

功能

代码示例

创建物理世界

const world = new CANNON.World();

设置重力

world.gravity.set(0, -9.81, 0);

创建刚体

new CANNON.Body({ mass, shape })

添加刚体到世界

world.addBody(body);

创建地面

new CANNON.Plane()

同步到 Three.js

mesh.position.copy(body.position);

添加碰撞事件

body.addEventListener('collide', callback);

🚀 Cannon.js 适用于刚体模拟,比如小球弹跳、物体掉落等,适合游戏和交互应用!


http://www.ppmy.cn/server/178517.html

相关文章

Redis安装与配置:从萌新入门到生产环境搭建

各位即将踏入Redis世界的新手司机们&#xff01;今天我们来手把手教你把Redis这辆超跑开上路&#xff0c;从零安装到生产级配置&#xff0c;全程无尿点&#xff01;准备好你的终端&#xff0c;咱们直接开干&#xff01; &#x1f4bb; 一、安装篇&#xff1a;多平台征服指南 1…

【愚公系列】《高效使用DeepSeek》024-儿童教育

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…

当了5年牛马,我开始划水了。。。

我现在的这份工作&#xff0c;比上一份要好很多&#xff0c;首先薪资直接涨了一倍&#xff0c;7k到16.5k&#xff0c;13薪&#xff0c;朝九晚六&#xff0c;从不加班&#xff0c;项目也简单&#xff0c;包括我在内测试组一共有6个同事&#xff0c;但是每个人分到的任务真的很少…

数据结构二叉树进阶

1.根据二叉树创建字符串 1.题目 2. 分析原理 要把二叉树元素按照前序顺序取出来&#xff0c;并且以字符串的形式返回&#xff0c;还要添加括号对于左子树和右子树&#xff0c;那么第一步就是向定义一个string类型来接收取出的元素&#xff0c;需要用到to_string函数把整型变成…

基于Python+Django的二手房信息管理系统

项目介绍 PythonDjango二手房信息管理系统(Pycharm Django Vue Mysql) 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 整个平台包括前台和后台两个部分。 - 前台功能包括&#xff1a;首页、二手房信息、公告管理、…

第七节 MATLAB数据类型

默认情况下&#xff0c;MATLAB 存储所有数值变量为双精度浮点值。其他数据类型存储文本&#xff0c;整数或单精度值或单个变量中相关数据的组合。 MATLAB不需要任何类型声明或维度语句。当MATLAB遇到新的变量名称时&#xff0c;它将创建变量并分配适当的内存空间。 如果变量已…

计算机的基本组合和工作原理

计算机的基本组成和工作原理可以概括为以下几个核心部分&#xff1a; 一、计算机的基本组成&#xff08;冯诺依曼体系结构&#xff09; 现代计算机基于冯诺依曼体系结构&#xff0c;主要由以下五大部件组成&#xff1a; 控制器&#xff08;Control Unit, CU&#xff09; 功能&…

【JavaEE】网络编程socket

1.❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; Hello, Hello~ 亲爱的朋友们&#x1f44b;&#x1f44b;&#xff0c;这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章&#xff0c;请别吝啬你的点赞❤️❤️和收藏&#x1f4d6;&#x1f4d6;。如果你对我的…