《权力的游戏》3d地图-基于Mapbox customlayer

栏目: JavaScript · 发布时间: 7年前

内容简介:权力游戏最终季正在热播,本人为了追剧果断买了腾讯会员,跳广告。不过说真的权游的所以才有了下面的 3d 地形图层,在线把玩地址:其实在几年前,我就借助Threejs 复现过谷歌一款精美的中土地图,那个app做得太精致了,开场动效、音效,都很“中土”,原汁原味的托尔金味道。其实技术也很简单,就是一个bufferPlane + texture图 + 高程图,根据高程图去修改bufferPlane 对应顶点的 z 值。在线地址
《权力的游戏》3d地图-基于Mapbox customlayer

权力游戏最终季正在热播,本人为了追剧果断买了腾讯会员,跳广告。不过说真的权游的 架空世界确实很令人着迷,广袤寒冷的北境,温暖富饶的多恩,面朝黑水湾的君临城 。巧了么,前段时间正好看到一个 github项目 是权游的地理要素和 mbtile数据,是广大爱好者和官方合力贡献且维护的。作为热心观众,必须得添砖加瓦啊。

所以才有了下面的 3d 地形图层,在线把玩地址:

《权力的游戏》3d地图-基于Mapbox customlayer

其实在几年前,我就借助Threejs 复现过谷歌一款精美的中土地图,那个app做得太精致了,开场动效、音效,都很“中土”,原汁原味的托尔金味道。其实技术也很简单,就是一个bufferPlane + texture图 + 高程图,根据高程图去修改bufferPlane 对应顶点的 z 值。在线地址

概述技术过程

类似于上一篇 mapbox extrude 文章中描述的类似,我们用到的数据就一张地表影像和一张高程图(权游的这个高程图是我自己先根据影像图波段运算之后ps 修正过的,具体过程有点意思)

《权力的游戏》3d地图-基于Mapbox customlayer

首先我们利用 Threejs 建立一个和影像图宽高一致的bufferPlaneGeometry,然后拿到这个bufferPlane 的所有顶点,这时候我们要通过一个canvas去读取高程图中对应像素的高度,从红波段读取高度,set 给bufferPlane 顶点的position.z,这就可以把平面设置为高低起伏的地形了(如下图)

《权力的游戏》3d地图-基于Mapbox customlayer
// geometry is bufferPlaneGeometry in THREEJS
// position flatArray [x,y,z,x1,y1,z1...] in geometry
  var flatArray = geometry.attributes.position.array;
  var verticesCount = flatArray.length / 3.0;
    console.warn('bufferGeom Vertices Array length: '+ verticesCount);
    for ( var i = 0, j = 0; i < verticesCount; i ++, j += 3 ) {
        if (data[i] === undefined) {
            console.warn(`data[${i}] is  undefined..`);
            break;
        } else {
            // set each vertice z-depth value with height
            flatArray[ j-1 ] = data[i] * extrusionRatio;
        }
    }

复制代码

与 mapbox 集成

为了给三维地形加入文字标注以及兴趣点 icon 等要素,我们直接把这个Threejs 图层集成为 mapbox 的customlayer。customlayer是 mapbox 开放给webgl 开发者的一个重要接口,可以在原有的 图层列表中插入customlayer 。 构造customlayer最重要的api就俩,可以参考官方文档

  • onAdd(map, gl),初始化 webgl
  • render(gl, matrix), 每一帧都会call 这个render函数,可以在这里注入需要在 webgl 上下文中渲染的操作
// configuration of the custom layer for a 3D model per the CustomLayerInterface
var customLayer = {
    id: '3d-terrain',
    type: 'custom',  // 指定是自定义图层,不然就是 fill,symbol 等图层.
    renderingMode: '3d',
    onAdd: function (map, gl) {
        this.camera = new THREE.Camera();
        this.scene = new THREE.Scene();
        this.map = map;

        // use the Mapbox GL JS map canvas for three.js
        this.renderer = new THREE.WebGLRenderer({
            canvas: map.getCanvas(),
            context: gl // 用mapbox 的webgl作为threejs 的上下文.
        });

        // 把Threejs 的scene,camera以及renderer 传入自定义的terrainLoader中,以便add(bufferPlaneMesh)
        this.terrainLoader = new TerrainLoader({
            scene: this.scene,
            camera: this.camera,
            renderer: this.renderer
        });
    },
    render: function (gl, matrix) {
        // ..省略部分 以下是将mapbox的matrix 参数同步给threejs 实例
        // sync mapbox matrix with THREE camera Matrix. 
        var m = new THREE.Matrix4().fromArray(matrix);
        var l = new THREE.Matrix4().makeTranslation(modelTransform.translateX, modelTransform.translateY, modelTransform.translateZ)
            .scale(new THREE.Vector3(modelTransform.scale, -modelTransform.scale, modelTransform.scale))
            .multiply(rotationX)
            .multiply(rotationY)
            .multiply(rotationZ);

        // sync mapbox matrix with THREE camera. 更新threejs camera的投影矩阵,重新渲染,再强制触发下mapbox 的repaint,这样动画就可以继续进行了
        this.camera.projectionMatrix.elements = matrix;
        this.camera.projectionMatrix = m.multiply(l);
        this.renderer.state.reset();
        this.renderer.render(this.scene, this.camera);
        this.map.triggerRepaint();
    }
}
// 把customlayer 加入label 之下,这样文字标注就可以浮在地形图层之上
map.on('style.load', function () {
    map.addLayer(customLayer, 'roads labels');
}); 

复制代码

github项目地址 后续有空的话,会加上权力游戏部分文档和 故事线动画 ,这个比较有趣一点。欢迎继续完善3d地形的范畴,一定得会photoshop...


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

认知盈余

认知盈余

[美] 克莱·舍基 / 胡泳、哈丽丝 / 中国人民大学出版社 / 2011-12 / 49.80元

“互联网革命最伟大的思考者”克莱•舍基 继《未来是湿的》之后最新力作 看自由时间如何变革世界的未来 如果说《未来是湿的》揭示的是“无组织的组织力量”, 那么《认知盈余》揭示的就是 “无组织的时间力量”。 腾讯董事会主席兼首席执行官马化腾首度亲笔作序倾情推荐 克莱•舍基说,美国人一年花在看电视上的时间大约2 000亿个小时,而这几乎是2 000个维基百科项目一年所需要的......一起来看看 《认知盈余》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具