今天郭先生说一说使用cannon.js物理引擎绘制地形和使用指针锁定控件。效果如下图。线案例请点击博客原文。

这里面的生成地形的插件和指针锁定控件也是cannon.js的作者schteppe封装的,当然也可以自己写一个这样的小插件。好的我们先说说这两个插件的使用方法,然后结合一个小案例应该他们。

1. 地形生成插件

相信一些同学玩过我的世界这款游戏,它的地形就是由好多个规格相同的正方体组成。就像下面这样

那么VoxelLandscape.js能够很好的实现这样的地形生成,我们先来看看生成地形构造函数所需要的参数

voxels = new VoxelLandscape(world,nx,ny,nz,sx,sy,sz);
  • world —cannon.js中的CANNON.World()实例
  • nx — x方向上地形的块数
  • ny — y方向上地形的块数
  • nz — z方向上地形的块数
  • sx — 小矩形x方向上halfSize
  • sy — 小矩形y方向上halfSize
  • sz — 小矩形z方向上halfSize

这样就能构建出一个地形,由于我们还没有进行其他操作,它看起来就是一整块矩形,但是它为我们提供了很多方法,比如说setFilled方法(其他的方法可以自行测试),这个方法可以设置哪些矩形块需要填充,哪些不需要填充,使用方法如下

voxels.setFilled(i,j,k),filled);
  • i — x方向的第i个
  • j — y方向的第j个
  • k — z方向的第k个
  • filled — 是否需要填充

i,j,k可以确定具体是那一块,filled是一个布尔值,true表示填充,false表示不填充,下面是随机挖空5000次方块的例子。

voxels = new VoxelLandscape(world,58,58,58,0.5,0.5,0.5);
for(let i=0; i<5000; i++) {
var filled = false;
voxels.setFilled(Math.floor(Math.random() * 58),Math.floor(Math.random() * 8),Math.floor(Math.random() * 58),filled);
}

这样就可以随心所欲的设置地形了。

2. 指针锁定控件

对于指针锁定控件,three.js已经为我们提供了PointerLockControls方法,它是基于Pointer Lock API实现的,主要用到的方法有请求指针锁定requestPointerLock()、退出指针锁定exitPointerLock()等,下面来说一说这个用于cannon.js的PointerLockControls,他和three的版本又些许区别,看下面代码。

controls = new PointerLockControls( camera , sphereBody );//第一个参数是camera,第二个参数是刚体对象
scene.add( controls.getObject() );//将控制器加入到场景
if(controls) {//如果controls初始化成功
if(document.pointerLockElement === element || document.mozPointerLockElement === element || document.webkitPointerLockElement === element) {//如果element处于锁定中,则打开controls
controls.enabled = true;//因为默认enabled为false,所以一般都需要手动打开
this.$refs.info.style.display = 'none';
} else {
controls.enabled = false;
this.$refs.info.style.display = 'inline-block';
}
}
controls.update(clock.getDelta() * 1000);//在每次更新物理世界的时候调用controls.update()方法

指针锁定控件使用一个刚体作为camera的载体,可以往camera的移动看起来更加生动(拥有物理特性)。

3. 案例

下面直接上主要案例代码

initCannon() {
world = new CANNON.World();
world.quatNormalizeSkip = 0;
world.quatNormalizeFast = false;
world.gravity.set(0, -9.8, 0);
world.broadphase = new CANNON.NaiveBroadphase();
world.solver.iterations = 10; physicsMaterial = new CANNON.Material("slipperyMaterial");
var physicsContactMaterial = new CANNON.ContactMaterial(physicsMaterial, physicsMaterial, {friction: 0.3, restitution: 0.5});//规定相同的physicsMaterial材质之间的发生接触时的物理参数。
world.addContactMaterial(physicsContactMaterial); var nx = 58, ny = 8, nz = 58, sx = 0.5, sy = 0.5, sz = 0.5; const radius = 1.6; sphereBody = new CANNON.Body({ //使用球形刚体作为相机载体,让相机拥有质量属性
mass: 5,
position: new CANNON.Vec3(nx*sx*0.5,ny*sy+radius*2,nz*sz*0.5),
shape: new CANNON.Sphere(radius),
material: physicsMaterial
});
sphereBody.linearDamping = 0.9;
world.addBody(sphereBody); groundBody = new CANNON.Body({//地面
mass: 0,
position: new CANNON.Vec3(0, -0.1, 0),
shape: new CANNON.Box(new CANNON.Vec3(200, 0.1, 200)),
material: physicsMaterial
});
world.addBody(groundBody); voxels = new VoxelLandscape(world,nx,ny,nz,sx,sy,sz); for(var i=0; i<nx; i++){
for(var j=0; j<ny; j++){
for(var k=0; k<nz; k++){
var filled = true;
if(Math.abs(Math.sin(i / 6)) < j / 5) {
filled = false;
}
if(Math.abs(Math.sin(k / 6)) < j / 5) {
filled = false;
} voxels.setFilled(i,j,k,filled); }
}
}
voxels.update();
}, for(var i=0; i<voxels.boxes.length; i++){//创建地形相应的网格,该数据存储在voxels.boxes数组中
var b = voxels.boxes[i];
var voxelGeometry = new THREE.BoxBufferGeometry( voxels.sx*b.nx, voxels.sy*b.ny, voxels.sz*b.nz );
var voxelMesh = new THREE.Mesh( voxelGeometry, new THREE.MeshPhysicalMaterial({color: 0x666666}) );
voxelMesh.castShadow = true;
voxelMesh.receiveShadow = true;
scene.add( voxelMesh );
boxMeshes.push( voxelMesh );
}

以上就是地形生成器和使用指针锁定控件的使用方法

转载请注明地址:郭先生的博客

three.js cannon.js物理引擎地形生成器和使用指针锁定控件的更多相关文章

  1. three.js cannon.js物理引擎之ConvexPolyhedron多边形

    年后第一天上班,郭先生来说一说cannon.js的ConvexPolyhedron(多边形),cannon.js是一个物理引擎,内部通过连续的计算得到各个时间点的数据的状态,three.js的模型可以 ...

  2. three.js cannon.js物理引擎之Heightfield

    今天郭先生说一说cannon.js物理引擎之Heightfield高度场,学过场论的朋友都知道物理学中把某个物理量在空间的一个区域内的分布称为场,高度场就是与高度相关的场,而cannon.js物理引擎 ...

  3. three.js cannon.js物理引擎之制作拥有物理特性的汽车

    今天郭先生说一说使用cannon.js的车辆辅助类让我们的汽车模型拥有物理特性.效果图如下,在线案例请点击博客原文. 下面我们说一下今天要使用的两个类,并简单的看看他们的物理意义 1. Raycast ...

  4. three.js cannon.js物理引擎制作一个保龄球游戏

    关于cannon.js我们已经学习了一些知识,今天郭先生就使用已学的cannon.js物理引擎的知识配合three基础知识来做一个保龄球小游戏,效果如下图,在线案例请点击博客原文. 我们需要掌握的技能 ...

  5. three.js cannon.js物理引擎之齿轮动画

    郭先生今天继续说一说cannon.js物理引擎,并用之前已经学习过的知识实现一个小动画,知识点包括ConvexPolyhedron多边形.Shape几何体.Body刚体.HingeConstraint ...

  6. three.js cannon.js物理引擎之约束

    今天郭先生继续说cannon.js,主演内容就是点对点约束和2D坐标转3D坐标.仍然以一个案例为例,场景由一个地面.若干网格组成的约束体和一些拥有初速度的球体组成,如下图.线案例请点击博客原文. 下面 ...

  7. three.js cannon.js物理引擎之约束(二)

    今天郭先生继续讲cannon.js的物理约束,之前的一篇文章曾简单的提及过PointToPointConstraint约束,那么今天详细的说一说cannon.js的约束和使用方法.在线案例请点击博客原 ...

  8. 通过js子页面回写父页面,改变父页面控件的值

    [原]js中实现子页面向父页面中赋值 (方法一) 父页面:<input  id="input1" type="text"/><a href=& ...

  9. js获取服务器生成并返回客户端呈现给客户的控件id的方法

    var repeaterId = '<%=rpData.ClientID %>'; //Repeater的客户端IDvar rows = <%=rpData.Items.Count% ...

随机推荐

  1. 【Python】自动化测试的7个步骤

    我们对自动化测试充满了希望,然而,自动化测试却经常带给我们沮丧和失望.虽然,自动化测试可以把我们从困难的环境中解放出来,在实施自动化测试解决问题的同时,又带来同样多的问题.在开展自动化测试的工作中,关 ...

  2. AD PCB模块复用

    该文档为原创,转发需注明出处!https://www.cnblogs.com/brianblog/ 在画图的时候如果遇到PCB中有多个模块原理图是一模一样的时候,我们便会想能不能偷点懒,只画一个模块, ...

  3. $$ PHP 的含义

    php中两个$也就bai是$$用来定义可变变量. 所谓可变变量,就是一个变量的名,又是一个变量.

  4. Codis集群相关

    在大数据高并发场景下,单个 Redis 实例往往会显得捉襟见肘.首先体现在内存上,单个 Redis 的内存不宜过大,内存太大会导致 rdb 文件过大,进一步导致主从同步时全量同步时间过长,在实例重启恢 ...

  5. iframe高度自动随着子页面的高度变化而变化(不止要在iframe标签里加上this.height=this.contentWindow.document.body.scrollHeight)

    最近使用iframe整合页面遇到一些难题,走了很多弯路才解决,借此记录一下: 1 <!-- 页面主体内容 --> 2 <div class="iframe-wrapper& ...

  6. Python爬取跑男的评论,看看大家都在看谁吧

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 以下文章来源于菜J学Python,作者: J哥 Python爬取爬取腾讯视频弹幕视频讲解 http ...

  7. Redis基础篇(三)持久化:AOF日志

    Redis是内存数据库,但是一旦服务器宕机,内存中的数据将会全部丢失. 最简单的恢复方式是从后端数据库恢复,但这种方式有两个问题: 频繁访问数据库,会给数据库带来巨大的压力: 从数据库中读取相比从Re ...

  8. JAVA递归算法及经典递归例子 对于这个汉诺塔问题

    前言:递归(recursion):递归满足2个条件 1)有反复执行的过程(调用自身) 2)有跳出反复执行过程的条件(递归出口) 第一题:汉诺塔 对于这个汉诺塔问题,在写递归时,我们只需要确定两个条件: ...

  9. SQL数据库创建,创建表,增删改查

    创建数据库:create datebase数据库名 删除数据库:drop datebase 数据库名称 创建表格式: create table 表名(字段名1,字段类型1,字段名2,字段类型2) 查询 ...

  10. 【转载】Vue.nextTick 的原理和用途

    对于 Vue.nextTick 方法,自己有些疑惑.在查询了各种资料后,总结了一下其原理和用途,如有错误,请不吝赐教. 概览 官方文档说明: 用法: 在下次 DOM 更新循环结束之后执行延迟回调.在修 ...