three.js 之cannon.js物理引擎
今天郭先生说的是一个物理引擎,它十分小巧并且操作简单,没错他就是cannon.js。这些优点都源自于他是基于js编写的,对于js使用者来说cannon.js拥有其他物理引擎没有的纯粹性。从学习成本来看,cannon.js的学习成本比较低,对于新手来说比较友好,因为它有相对完善的api,学习cannon.js之前我们不妨来看看cannons.js的官方网站以及他的API,对于js学习者来说这是十分必要的。官网上面有一些example,他们十分典型并囊括了大多数的知识点,配合api一起学习是个不错的选择。在线案例请点击博客原文。效果如下图,接下来以一个小案例,简单的介绍一下cannon.js。
1. 初始化three场景
创建three场景(或者说three世界)来作为物理世界的载体,这一步很简单,主要就是添加渲染器、场景、相机和网格等three元素,没必要多说。
scene = new THREE.Scene();//step 1 创建场景 camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.y = 30;
camera.position.z = 20;
camera.lookAt(0,5,0);
scene.add( camera ); //step 2 场景中添加相机 scene.add(new THREE.AmbientLight(0x888888));
const light = new THREE.DirectionalLight(0xbbbbbb, 1);
light.position.set(6, 30, 6);
scene.add(light); //step 3 场景中添加另种光源 renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.shadowMap.enabled = true;
renderer.setClearColor(0xbfd1e5);
this.$refs.box.appendChild(renderer.domElement); //step 4 dom中添加渲染器 let groundGeom = new THREE.BoxBufferGeometry(40, 0.2, 40);
let groundMate = new THREE.MeshPhongMaterial({color: 0xdddddd, map: texture})
ground = new THREE.Mesh(groundGeom, groundMate);
ground.position.y = -0.1;
ground.receiveShadow = true;
scene.add(ground); //step 5 添加地面网格
2. 初始化物理世界
这里是初始化物理世界,我们详细的讲一下他们的用法。
initCannon() {
world = new CANNON.World(); //该方法初始化物理世界,里面包含着物理世界的相关数据(如刚体数据,世界中所受外力等等)
world.gravity.set(0,-9.8,0); //设置物理世界的重力为沿y轴向上-9.8米每二次方秒
world.broadphase = new CANNON.NaiveBroadphase();//NaiveBroadphase是默认的碰撞检测方式,该碰撞检测速度比较高
world.solver.iterations = 5;//解算器的迭代次数,更高的迭代次数意味着更加精确同时性能将会降低 bodyGround = new CANNON.Body({ //创建一个刚体(物理世界的刚体数据)
mass: 0, //刚体的质量,这里单位为kg
position: new CANNON.Vec3(0, -0.1, 0), //刚体的位置,单位是米
shape: new CANNON.Box(new CANNON.Vec3(20, 0.1, 20)), //刚体的形状(这里是立方体,立方体的参数是一个包含半长、半宽、半高的三维向量,具体我们以后会说)
material: new CANNON.Material({friction: 0.05, restitution: 0}) //材质数据,里面规定了摩擦系数和弹性系数
});
ground.userData = bodyGround; //将刚体的数据赋值给地面网格的userData属性
world.addBody(bodyGround); //物理世界添加地面刚体
},
3. 向场景中添加网格并向物理世界中添加刚体数据
这里我们通过setInterval函数我们定时向场景中添加网格并向物理世界中添加刚体数据,
interval = setInterval(() => {
this.createBox(); //创建网格和刚体的方法
}, 200);
下面是具体的方法
createBox() {
let x = Math.random() * 10 - 5;
let z = Math.random() * 10 - 5;
let box = new THREE.Mesh( geometry, this.createRandomMaterial() ); //createRandomMaterial创建随机颜色的材质
box.position.set(x, 20, z);
scene.add( box ); //创建box,并添加到场景 let bodyBox = new CANNON.Body({
mass: 1,
position: new CANNON.Vec3(x, 20, z),
shape: new CANNON.Box(new CANNON.Vec3(1,1,1)),
material: new CANNON.Material({friction: 0.1, restitution: 0})
});//创建一个质量为1kg,位置为(x,20,z),形状为halfSize为1,1,1的正方形刚体,材质中摩擦系数为0.1,弹性系数为0。
box.userData = bodyBox;//给box的userData属性添加刚体数据
world.addBody(bodyBox);//在物理世界中添加该刚体 setTimeout(() => { //10秒钟之后在场景中移除box,并在物理世界中移除该刚体
scene.remove(box);
box.material.dispose();
box.geometry.dispose();
world.removeBody(bodyBox);
}, 10000)
},
4. 根据物理引擎的数据更新three网格数据
这一步我们逐帧根据物理引擎的数据渲染three场景
animation() { //requestAnimationFrame动画中调用render方法
this.globalID = requestAnimationFrame(this.animation);
this.render();
},
render() { //更新性能插件,根据物理引擎数据更新网格数据,最后渲染场景
stats.update();
this.updatePhysics();
renderer.render( scene, camera );
},
updatePhysics() { // world.step
world.step(timeStep); //第一个参数是以固定步长更新物理世界参数(详情请看api)
scene.children.forEach(d => {//遍历场景中的子对象,如果对象的isMesh属性为true,我们就将更新改对象的position和quaternion属性(他们对应的刚体数据存在对应的userData中)。
if(d.isMesh == true) {
d.position.copy(d.userData.position);
d.quaternion.copy(d.userData.quaternion);
}
})
}
这样我们就将cannon.js物理引擎应用到了three中。不出意外的话,接下来我会讲解一下官方的examples。
转载请注明地址:郭先生的博客
three.js 之cannon.js物理引擎的更多相关文章
- 基于Babylon.js编写宇宙飞船模拟程序1——程序基础结构、物理引擎使用、三维罗盘
计划做一个宇宙飞船模拟程序,首先做一些技术准备. 可以访问https://ljzc002.github.io/test/Spacetest/HTML/PAGE/spacetestwp2.html查看测 ...
- 造个海洋球池来学习物理引擎【Three.js系列】
github地址:https://github.com/hua1995116/Fly-Three.js 大家好,我是秋风.继上一篇<Three.js系列: 游戏中的第一/三人称视角>今 ...
- three.js cannon.js物理引擎地形生成器和使用指针锁定控件
今天郭先生说一说使用cannon.js物理引擎绘制地形和使用指针锁定控件.效果如下图.线案例请点击博客原文. 这里面的生成地形的插件和指针锁定控件也是cannon.js的作者schteppe封装的,当 ...
- three.js cannon.js物理引擎之Heightfield
今天郭先生说一说cannon.js物理引擎之Heightfield高度场,学过场论的朋友都知道物理学中把某个物理量在空间的一个区域内的分布称为场,高度场就是与高度相关的场,而cannon.js物理引擎 ...
- three.js cannon.js物理引擎之制作拥有物理特性的汽车
今天郭先生说一说使用cannon.js的车辆辅助类让我们的汽车模型拥有物理特性.效果图如下,在线案例请点击博客原文. 下面我们说一下今天要使用的两个类,并简单的看看他们的物理意义 1. Raycast ...
- three.js cannon.js物理引擎制作一个保龄球游戏
关于cannon.js我们已经学习了一些知识,今天郭先生就使用已学的cannon.js物理引擎的知识配合three基础知识来做一个保龄球小游戏,效果如下图,在线案例请点击博客原文. 我们需要掌握的技能 ...
- three.js cannon.js物理引擎之ConvexPolyhedron多边形
年后第一天上班,郭先生来说一说cannon.js的ConvexPolyhedron(多边形),cannon.js是一个物理引擎,内部通过连续的计算得到各个时间点的数据的状态,three.js的模型可以 ...
- three.js cannon.js物理引擎之齿轮动画
郭先生今天继续说一说cannon.js物理引擎,并用之前已经学习过的知识实现一个小动画,知识点包括ConvexPolyhedron多边形.Shape几何体.Body刚体.HingeConstraint ...
- three.js cannon.js物理引擎之约束
今天郭先生继续说cannon.js,主演内容就是点对点约束和2D坐标转3D坐标.仍然以一个案例为例,场景由一个地面.若干网格组成的约束体和一些拥有初速度的球体组成,如下图.线案例请点击博客原文. 下面 ...
随机推荐
- STL——容器(Set & multiset)的查找
1. set.find(elem); //查找elem元素,返回指向elem元素的迭代器. 1 #include <iostream> 2 #include <set> 3 4 ...
- STL——容器(Set & multiset)的默认构造 & 带参构造 & 对象的拷贝构造与赋值
1. 默认构造 set<int> setInt; //一个存放int的set容器. set<float> setFloat; //一 ...
- 设置RAC DB归档
1.关闭集群数据库 srvctl stop database -d RAC 2.将节点一设置为归档模式 sqlplus / as sysdba startup mount alter database ...
- [水题日常]UVA1625 Color Length
来整理一下思路- 一句话题意:给两个大写字母的序列,每次取出其中一个数列的第一个元素放到新序列里面,对每个字母\(c\)记它的跨度\(L(c)\)为这个字母最后出现的位置-第一次出现的位置,求新序列所 ...
- Netty源码解析 -- PoolSubpage实现原理
前面文章说了PoolChunk如何管理Normal内存块,本文分享PoolSubpage如何管理Small内存块. 源码分析基于Netty 4.1.52 内存管理算法 PoolSubpage负责管理S ...
- python 字符串拼接 + 与 join 的区别
本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理 python在进行字符串的拼接时,一般有两种方法,一种是使用+直接相加,另一种是使用join a = ...
- java基础: ArrayList集合应用, ArrayList增删改查详解,综合java基础实现学生管理系统,
1.ArrayList 集合和数组的区别 : 共同点:都是存储数据的容器 不同点:数组的容量是固定的,集合的容量是可变的 1.1 -ArrayList的构造方法和添加方法 public ArrayLi ...
- 常见编译器EOP
delphi: 55 PUSH EBP 8BEC MOV EBP,ESP 83C4 F0 ADD ESP,-10 B8 A86F4B00 ...
- Amazing 2020
Amazing 2020 Intro 2020 转眼即逝,2020 是比较艰辛的一年,因为疫情原因,很多人的工作以及生活都多多少少受到了一些影响. 引用网上盛传的一句话--2020 实"鼠& ...
- linux零基础之--常用命令
linux: 用户命令 linux 目录切换命令 linux文件命令 linux : vi编辑器 linux:打包压缩