目录

1.物理引擎介绍(Physics)

1.1 类库介绍

1.2 实现原理

2. Cannon.js物理引擎

2.1 Cannon安装

3. 案例:点击屏幕向外弹出立方体


1.物理引擎介绍(Physics)

在我们日常生活中,物体之间是存在相互作用力的,他们之间存在弹力、摩擦力等相关系数,物体自身也存在重力等属性,因此并不是简单的碰撞。在Three中,物理引擎主要依赖于第三方插件进行实现,例如Cannon.js,Ammo.js,Oimo.js。

1.1 类库介绍

1.三维库

1)Ammo.js

GitHub - kripken/ammo.js: Direct port of the Bullet physics engine to JavaScript using EmscriptenDirect port of the Bullet physics engine to JavaScript using Emscripten - GitHub - kripken/ammo.js: Direct port of the Bullet physics engine to JavaScript using Emscriptenhttps://github.com/kripken/ammo.js2)Cannon.js

受three.js和ammo.js的启发,以及 web 缺乏物理引擎这一事实的驱动,cannon.js 出现了。刚体物理引擎包括简单的碰撞检测、各种身体形状、接触、摩擦和约束。GitHub - schteppe/cannon.js: A lightweight 3D physics engine written in JavaScript.A lightweight 3D physics engine written in JavaScript. - GitHub - schteppe/cannon.js: A lightweight 3D physics engine written in JavaScript.https://github.com/schteppe/cannon.js官网:

schteppe/cannon.js @ GitHubA lightweight and simple 3D physics engine for the web.http://schteppe.github.io/cannon.js/3)Oimo.js

Oimo.jshttps://lo-th.github.io/Oimo.js/#basicGitHub - lo-th/Oimo.js: Lightweight 3d physics engine for javascriptLightweight 3d physics engine for javascript. Contribute to lo-th/Oimo.js development by creating an account on GitHub.https://github.com/lo-th/Oimo.js

2.二维库

当使用时,仅涉及水平方向时,可以将三维交互转换为二维交互,使用以下二维类库进行实现。

Matter.js
P2.js
Planck.js
Box2D.js

1.2 实现原理

使用中,我们会创建一个Three.js世界和一个Physics物理世界,虽然我们看不见后者但它是真实存在的,每当我们往Three.js世界添加对象时,相应的物理世界也会添加相同对象。物理世界在每一帧更新时都会相应更新到Three.js世界中(通过实体的.position.copy方法获取物理世界实体的位置)。
例如物理世界中的球体在平面上进行真实弹跳效果时,我们会取其每一帧更新后的坐标并将坐标应用到Three.js世界中的对应球体。

2. Cannon.js物理引擎

2.1 Cannon安装

1)安装

cnpm install cannon --save

2)导入

 import * as CANNON from "cannon";

3)使用

创建球和平面:

// 创建球和平面
const sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
const sphereMaterial = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.castShadow = true;
scene.add(sphere);const floor = new THREE.Mesh(new THREE.PlaneBufferGeometry(20, 20),new THREE.MeshStandardMaterial()
);floor.position.set(0, -5, 0);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);

创建Cannon物理世界

//start
// 创建物理世界
const world = new CANNON.World();
world.gravity.set(0, -9.8, 0);//9.8重力加速度
// 创建物理小球形状
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);//按x轴旋转
world.addBody(floorBody);
//end

Three世界获取物理世界坐标

world.step(1 / 120, deltaTime);
sphere.position.copy(sphereBody.position);

实现效果:

全部代码(main.js):

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入connon引擎
import * as CANNON from "cannon-es";console.log(CANNON);
// 1、创建场景
const scene = new THREE.Scene();// 2、创建相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,300
);
// 设置相机位置
camera.position.set(0, 0, 18);
scene.add(camera);// 创建球和平面
const sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
const sphereMaterial = new THREE.MeshStandardMaterial();
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.castShadow = true;
scene.add(sphere);const floor = new THREE.Mesh(new THREE.PlaneBufferGeometry(20, 20),new THREE.MeshStandardMaterial()
);floor.position.set(0, -5, 0);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);// 创建物理世界
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);//按x轴旋转
world.addBody(floorBody);//添加环境光和平行光
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);// 初始化渲染器
// 渲染器透明
const renderer = new THREE.WebGLRenderer({ alpha: true });
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;// console.log(renderer);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);// // 使用渲染器,通过相机将场景渲染进来
// renderer.render(scene, camera);// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 设置时钟
const clock = new THREE.Clock();function render() {//   let time = clock.getElapsedTime();let deltaTime = clock.getDelta();// 更新物理引擎里世界的物体world.step(1 / 120, deltaTime);sphere.position.copy(sphereBody.position);renderer.render(scene, camera);//   渲染下一帧的时候就会调用render函数requestAnimationFrame(render);
}render();// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {//   console.log("画面变化了");// 更新摄像头camera.aspect = window.innerWidth / window.innerHeight;//   更新摄像机的投影矩阵camera.updateProjectionMatrix();//   更新渲染器renderer.setSize(window.innerWidth, window.innerHeight);//   设置渲染器的像素比renderer.setPixelRatio(window.devicePixelRatio);
});

3. 案例:点击屏幕向外弹出立方体

import * as THREE from "three";
// 导入轨道控制器
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// 导入connon引擎
import * as CANNON from "cannon-es";// 目标:设置cube跟着旋转
console.log(CANNON);// 1、创建场景
const scene = new THREE.Scene();// 2、创建相机
const camera = new THREE.PerspectiveCamera(75,window.innerWidth / window.innerHeight,0.1,300
);// 设置相机位置
camera.position.set(0, 0, 18);
scene.add(camera);const cubeArr = [];
//设置物体材质
const cubeWorldMaterial = new CANNON.Material("cube");function createCube() {// 创建立方体和平面const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);const cubeMaterial = new THREE.MeshStandardMaterial();const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);cube.castShadow = true;scene.add(cube);// 创建物理cube形状const cubeShape = new CANNON.Box(new CANNON.Vec3(0.5, 0.5, 0.5));// 创建物理世界的物体const cubeBody = new CANNON.Body({shape: cubeShape,position: new CANNON.Vec3(0, 0, 0),//   小球质量mass: 1,//   物体材质material: cubeWorldMaterial,});cubeBody.applyLocalForce(new CANNON.Vec3(300, 0, 0), //添加的力的大小和方向new CANNON.Vec3(0, 0, 0) //施加的力所在的位置);// 将物体添加至物理世界world.addBody(cubeBody);// 添加监听碰撞事件function HitEvent(e) {// 获取碰撞的强度//   console.log("hit", e);const impactStrength = e.contact.getImpactVelocityAlongNormal();console.log(impactStrength);if (impactStrength > 2) {//   重新从零开始播放hitSound.currentTime = 0;hitSound.volume = impactStrength / 12;hitSound.play();}}cubeBody.addEventListener("collide", HitEvent);cubeArr.push({mesh: cube,body: cubeBody,});
}window.addEventListener("click", createCube);const floor = new THREE.Mesh(new THREE.PlaneBufferGeometry(20, 20),new THREE.MeshStandardMaterial()
);floor.position.set(0, -5, 0);
floor.rotation.x = -Math.PI / 2;
floor.receiveShadow = true;
scene.add(floor);// 创建物理世界
// const world = new CANNON.World({ gravity: 9.8 });
const world = new CANNON.World();
world.gravity.set(0, -9.8, 0);// 创建击打声音
const hitSound = new Audio("assets/metalHit.mp3");// 物理世界创建地面
const floorShape = new CANNON.Plane();
const floorBody = new CANNON.Body();
const floorMaterial = new CANNON.Material("floor");
floorBody.material = floorMaterial;
// 当质量为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);// 设置2种材质碰撞的参数
const defaultContactMaterial = new CANNON.ContactMaterial(cubeWorldMaterial,floorMaterial,{//   摩擦力friction: 0.1,// 弹性restitution: 0.7,}
);// 将材料的关联设置添加的物理世界
world.addContactMaterial(defaultContactMaterial);// 设置世界碰撞的默认材料,如果材料没有设置,都用这个
world.defaultContactMaterial = defaultContactMaterial;//添加环境光和平行光
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);// 初始化渲染器
// 渲染器透明
const renderer = new THREE.WebGLRenderer({ alpha: true });
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true;// console.log(renderer);
// 将webgl渲染的canvas内容添加到body
document.body.appendChild(renderer.domElement);// // 使用渲染器,通过相机将场景渲染进来
// renderer.render(scene, camera);// 创建轨道控制器
const controls = new OrbitControls(camera, renderer.domElement);
// 设置控制器阻尼,让控制器更有真实效果,必须在动画循环里调用.update()。
controls.enableDamping = true;// 添加坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
// 设置时钟
const clock = new THREE.Clock();function render() {//   let time = clock.getElapsedTime();let deltaTime = clock.getDelta();// 更新物理引擎里世界的物体world.step(1 / 120, deltaTime);//   cube.position.copy(cubeBody.position);cubeArr.forEach((item) => {item.mesh.position.copy(item.body.position);// 设置渲染的物体跟随物理的物体旋转item.mesh.quaternion.copy(item.body.quaternion);});renderer.render(scene, camera);//   渲染下一帧的时候就会调用render函数requestAnimationFrame(render);
}render();// 监听画面变化,更新渲染画面
window.addEventListener("resize", () => {//   console.log("画面变化了");// 更新摄像头camera.aspect = window.innerWidth / window.innerHeight;//   更新摄像机的投影矩阵camera.updateProjectionMatrix();//   更新渲染器renderer.setSize(window.innerWidth, window.innerHeight);//   设置渲染器的像素比renderer.setPixelRatio(window.devicePixelRatio);
});

实现效果:

Three.js-物理引擎(Physics)相关推荐

  1. JS物理引擎p2.js中文文档

    本文复制于Github p2.js项目的中文维基页面,鉴于国内访问Github网速不稳定,特粘贴到CSDN,促进知识更快传播,也希望有能力者继续完善此文档. 以下是原文,更新内容请查阅Github p ...

  2. 【Canvas】HTML5游戏开发的基本流程+P2.js物理引擎实战开发

    <HTML5游戏开发的基本流程> * 1. HTML5的简述 * 2. HTML5游戏开发所需的环境与工具 * 2.1. 开发环境 * 2.1.1. 浏览器 * 2.1.2. 开发语言 * ...

  3. cocos2d - JS 物理引擎 - chipmunk

    物理引擎 - chipmunk : 生成物理世界 : 第一步 : 新建项目打开 project.json 将chipmunk模块导入 . "modules" : ["co ...

  4. (十三)Flax Engine游戏引擎物理引擎 physics(2)

    2021SC@SDUSC 上篇我们进行flax Engine游戏引擎中物理引擎中physics(物理)内容的部分分析.讲述了光线和模拟物理系统中的一些函数定义和变量的源代码,本次我们紧接着上次的内容继 ...

  5. (十二)Flax Engine游戏引擎物理引擎 physics

    2021SC@SDUSC 最后我们进行flax Engine游戏引擎中物理引擎中physics(物理)的分析,这个包中含有所有用到的物理系统的相关应用,包括四个大类的定义:1:物理对撞机 2:铰链 3 ...

  6. Three.js物理引擎与物体的相互作用——关联材质对摩擦力弹性影响、物体运动方式、作用力相关

    vetor new CANNON.ContactMaterial构造方法用于设置Three.物理世界两种材质碰撞的参数 const defaultContactMaterial = new CANNO ...

  7. 一篇上手LayaAir的3D物理引擎

    昨天,我们分享了一篇2D物理文档<LayaAirIDE的可视化2D物理使用文档>. 今天,我们针对LayaAir引擎的初学者,以及对物理引擎使用不熟悉的开发者,再来分享一篇3D物理文档,本 ...

  8. unity 下一帧执行_Unity中的Havok Physics物理引擎

    在GDC 2019上,我们宣布将Havok Physics作为预览版资源包加入到Unity资源包管理器,这意味着所有Unity开发者都可以使用这款知名的物理引擎.在当今主机平台中,Havok Phys ...

  9. Cannon.js -- 3d物理引擎

    文章目录 前言 一.关于Cannon.js 二.Cannon.js的使用 最后 注意点: 优化 事件 其他 本文完整代码下载: 相关链接: 前言 本篇将介绍Cannon.js -- 3d物理引擎的基础 ...

  10. 初见物理引擎库Cannon.js:使用dat.gui修改物体属性

    0 前言 本文是"初见物理引擎库Cannon.js"系列的第二篇文章,在本文中主要讲解dat.gui的使用. 1 dat.gui简介 熟悉Three.js的读者肯定对dat.gui ...

最新文章

  1. python 03 字符串详解
  2. 测度论与概率论有什么关系?为什么要学习测度论?
  3. CxImage图像处理类库说明3(转载)
  4. 科技业务同比增长超20%,中国平安“金融+科技”成了吗?
  5. OpenGL Tessellation and Geometry Shaders镶嵌和几何着色器的实例
  6. xp关无线配置服务器,xp系统怎么关闭无线功能
  7. dev layoutview 怎么显示大小_「转」磁盘满了,为啥du却显示还有很大空间?
  8. CentOS Linux 下的 vim 无法使用系统剪贴板,怎么解决呢?
  9. 数论 —— 线性同余方程
  10. OpenShift 4 之AMQ Streams(3) - 用Kafka MirrorMaker在Kafka集群间复制数据
  11. Hibernate常用查询
  12. mem考试能用计算机吗,东华大学计算机学院MEM难考吗
  13. action评测 osmo_Osmo Action与GoPro 7的七大对决,评测谁是运动相机王者?
  14. EL表达式和jstl的简单应用
  15. matlab逆滤波、维纳滤波、最小二乘滤波
  16. 晶振-电路中的心脏起搏器
  17. BPF BTF 详细介绍
  18. win10计算机快捷键设置,win10计算器快捷键设置_w10电脑计算器快捷键怎么添加-win7之家...
  19. 腾讯微博qq说说备份导出工具_腾讯微博停止运营,赶紧申请备份吧
  20. MOS管开启过程中VGS的台阶——米勒平台?

热门文章

  1. 西南交通大学matlab实验任务,西南交通大学实验竞赛月——数学建模竞赛安排
  2. MagicDraw-活动图
  3. MagicDraw 18.5 SP4
  4. Chango的数学Shader世界(十六)RayTrace三维分形(一)—— ue4中最简单的RayMarch
  5. nutch2.3.1 mysql_Nutch-NewsClassify
  6. Sniffer Pro 4.7.530 SP5下载地址
  7. 【经验分享】数学建模论文格式要求及常见问题汇总
  8. Date类与DateFormat类
  9. Python后端实现苹果ID登陆
  10. PPT,我的视频制作利器