当前位置: 首页 > news >正文

初探 Threejs 物理引擎CANNON,解锁 3D 动态魅力

简介

Cannon.js 是一个基于 JavaScript 的物理引擎,它可以在浏览器中模拟物理效果。它支持碰撞检测、刚体动力学、约束等物理效果,可以用于创建逼真的物理场景和交互。

参考文档

官方示例

原理

Cannon.js 使用了欧拉角来表示物体的旋转,而不是四元数。这使得它在处理旋转时更加直观和易于理解。Cannon.js 还支持多种碰撞检测算法,包括离散碰撞检测和连续碰撞检测。

Cannon.js 还支持多种约束类型,包括固定约束、滑动约束和铰链约束等。这些约束可以用于限制物体的运动,例如将两个物体固定在一起,或者将一个物体限制在一个滑动路径上。这使得 Cannon.js 可以创建逼真的物理场景和交互。

安装

npm install cannon-es

使用

需要要使用 Cannon.js,首先需要创建一个物理世界,然后向其中添加物体和约束。接下来,在每个时间步长中更新物理世界,并使用物理世界中的物体和约束来计算物体的位置和旋转,由于在物理世界中创建的物体是看不到的,所以需要将这些位置和旋转应用到 Three.js 场景中的物体上。

引入

import * as CANNON from "cannon-es";

创建物理世界

const world = new CANNON.World();
world.gravity.set(0, -9.82, 0); // 设置重力

word.gravity: 属性用于设置物理世界的重力。

  • x: 重力的 x 分量。
  • y: 重力的 y 分量。
  • z: 重力的 z 分量。

创建物体

//物理世界物体
const sphereShape = new CANNON.Sphere(1); // 创建一个球体形状
const sphereBody = new CANNON.Body({
  mass: 1,
  shape: sphereShape,
  position: new CANNON.Vec3(0, 5, 0),
}); // 创建一个球体物体
world.addBody(sphereBody); // 将球体添加到物理世界中
//Three.js 场景中的物体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32); // 创建一个球体几何体
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 创建一个球体材质
const sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial); // 创建一个球体网格
scene.add(sphereMesh); // 将球体网格添加到场景中

CANNON.Sphere(): 方法用于创建一个球体形状。

  • radius: 球体的半径。

CANNON.Body(): 方法用于创建一个物体。

  • mass: 物体的质量。
  • shape: 物体的形状。
  • position: 物体的位置。

world.addBody(): 方法用于将物体添加到物理世界中。

更新物理世界

function animate() {
  requestAnimationFrame(animate);
  world.step(1 / 60); // 更新物理世界
  // 将物理世界中的球体位置应用到 Three.js 场景中的球体网格上
  sphereMesh.position.copy(sphereBody.position);
  // 将物理世界中的球体旋转应用到 Three.js 场景中的球体网格上
  sphereMesh.quaternion.copy(sphereBody.quaternion);
  renderer.render(scene, camera); // 渲染场景
}
animate();

world.step(): 方法用于更新物理世界中的物体和约束的状态。

  • dt: 时间步长,用于计算物体的运动和碰撞。
  • time: 当前时间,用于计算物体的运动和碰撞。
  • correction: 时间步长修正,用于修正时间步长导致的误差。

copy(): 方法用于将一个向量的值复制到另一个向量中。

  • v: 要复制的向量。

在这里插入图片描述

碰撞检测

Cannon.js 支持多种碰撞检测算法,包括离散碰撞检测和连续碰撞检测。离散碰撞检测是在每个时间步长中检查物体之间的碰撞,而连续碰撞检测则是在物体之间可能发生碰撞的路径上插入额外的检查点。这使得 Cannon.js 可以处理复杂的碰撞场景,例如物体之间的穿透和重叠。

const groundShape = new CANNON.Box(new CANNON.Vec3(5, 0.1, 5));
const groundBody = new CANNON.Body({
  shape: groundShape,
  position: new CANNON.Vec3(0, 0, 0),
  type: CANNON.Body.STATIC,
});
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), 0.1);
world.addBody(groundBody);

//创建一个平面的几何体
const groundGeometry = new THREE.BoxGeometry(10, 0.2, 10);
//创建一个平面的材质
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
//创建一个平面的网格
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
//设置平面的位置
ground.position.x = 0.1;
//将平面添加到场景中
scene.add(ground);

CANNON.Plane(): 方法用于创建一个平面形状。

CANNON.Box(): 方法用于创建一个盒子形状。

setFromAxisAngle(): 方法用于设置物体的旋转。

  • axis: 旋转轴。
  • angle: 旋转角度。

body.type: 物体的类型

  • CANNON.Body.KINEMATIC: 物体是动态的,可以移动和旋转。
  • CANNON.Body.STATIC: 物体是静态的,不能移动和旋转。
  • CANNON.Body.DYNAMIC: 物体是动态的,可以移动和旋转,并且受到物理世界的重力和其他力的作用。
const groundBody = new CANNON.Body({
  shape: groundShape,
  position: new CANNON.Vec3(0, 0, 0),
  type: CANNON.Body.STATIC, // 设置物体类型为静态
}); 

示例

import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
//引入CannonJS
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.z = 5;
camera.position.y = 5;
camera.position.x = -10;

// 创建渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// 创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);

// 创建一个球体
const sphereShape = new CANNON.Sphere(1);
const sphereBody = new CANNON.Body({
  mass: 1,
  shape: sphereShape,
  position: new CANNON.Vec3(0, 5, 0),
});
world.addBody(sphereBody);

// 创建一个平面
const groundShape = new CANNON.Box(new CANNON.Vec3(5, 0.1, 5));
const groundBody = new CANNON.Body({
  shape: groundShape,
  position: new CANNON.Vec3(0, 0, 0),
  type: CANNON.Body.STATIC,
});
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), 0.1);
world.addBody(groundBody);

//创建一个球体的几何体
const sphereGeometry = new THREE.SphereGeometry(0.5, 32, 32);
//创建一个球体的材质
const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
//创建一个球体的网格
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
//将球体添加到场景中
scene.add(sphere);

//创建一个平面的几何体
const groundGeometry = new THREE.BoxGeometry(10, 0.2, 10);
//创建一个平面的材质
const groundMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });
//创建一个平面的网格
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
//设置平面的位置
ground.position.x = 0.1;
//将平面添加到场景中
scene.add(ground);

//创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 启用阻尼效果
controls.enableDamping = true;

function animate() {
  requestAnimationFrame(animate);
  world.step(1 / 60);
  sphere.position.copy(sphereBody.position);
  sphere.quaternion.copy(sphereBody.quaternion);
  renderer.render(scene, camera);
}

animate();

//监听窗口大小变化
window.addEventListener("resize", () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});

在这里插入图片描述
书洞笔记

相关文章:

  • C语言实现堆结构及Top - K问题求解
  • C#opencv 遍历图像中所有点 不在圆范围内的点变为黑色,在圆范围内的保持原色
  • Gemini 2.0 Flash:AI 图像生成的革命性突破!
  • c++三级(枚举问题)
  • 练习题:87
  • Go vs Rust vs C++ vs Python vs Java:谁主后端沉浮
  • Mybatis——基础操作、动态SQL
  • 【STM32】USART串口收发HEX数据包收发文本数据包
  • 2024年12月CCF-GESP编程能力等级认证C++编程三级真题解析
  • Vue前端项目部署到宝塔面板的详细过程
  • VSCode通过SSH免密远程登录Windows服务器
  • 搭建Spring Boot Admin监控系统
  • 【SpringBoot】最佳实践——JWT结合Redis实现双Token无感刷新
  • 写时拷贝技术
  • 第三周日志-周末看书(3)
  • 计算机组成原理常用的计数单位(性能指标的计算)持续更新
  • 02自动化测试常用函数
  • 多页pdf转长图
  • 《重新审视深度部分标签学习中的一致性正则化》2022年ICML论文精读
  • 寄生虫仿生算法:基于寄生虫特征的算法设计
  • 上海青少年书法学习园开园:少年以巨笔书写《祖国万岁》
  • 创同期历史新高!1至4月全国铁路发送旅客14.6亿人次
  • 被前男友泼汽油致残后,一个女孩经历的双重灼烧
  • 汕头违建豪宅“英之园”将强拆,当地:将根据公告期内具体情况采取下一步措施
  • 75万买299元路由器后续:重庆市纪委、财政局、教委联合调查
  • 英国首相斯塔默住所起火,警方紧急调查情况