《權力的遊戲》3d地圖-基於Mapbox customlayer

寫在前面

最終季!!轉自豆瓣,如侵權請聯繫... https://movie.douban.com/photos/photo/2549876231/

權力遊戲最終季正在熱播,本人爲了追劇果斷買了騰訊會員,跳廣告。不過說真的權遊的架空世界確實很使人着迷,廣袤寒冷的北境,溫暖富饒的多恩,面朝黑水灣的君臨城。巧了麼,前段時間正好看到一個 github項目 是權遊的地理要素和 mbtile數據,是廣大愛好者和官方協力貢獻且維護的。做爲熱心觀衆,必須得添磚加瓦啊。html

因此纔有了下面的<權力的遊戲3d地圖導覽>,在線把玩地址git

screenshot

其實在幾年前,我就藉助Threejs 復現過谷歌一款精美的中土地圖,那個app作得太精緻了,開場動效、音效,都很「中土」,原汁原味的托爾金味道。其實技術也很簡單,就是一個bufferPlane + texture圖 + 高程圖,根據高程圖去修改bufferPlane 對應頂點的 z 值。在線地址github

概述技術過程

相似於上一篇 mapbox extrude 文章中描述的相似,咱們用到的數據就一張地表影像和一張高程圖(權遊的這個高程圖是我本身先根據影像圖波段運算以後ps 修正過的,具體過程有點意思) web

左邊高程圖+右邊影像圖

首先咱們利用 Threejs 創建一個和影像圖寬高一致的bufferPlaneGeometry,而後拿到這個bufferPlane 的全部頂點,這時候咱們要經過一個canvas去讀取高程圖中對應像素的高度,從紅波段讀取高度,set 給bufferPlane 頂點的position.z,這就能夠把平面設置爲高低起伏的地形了(以下圖)canvas

根據高程圖設置bufferPlane 的頂點高度

// 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就倆,能夠參考官方文檔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...bash

最近更新

  • 根據GOT wiki,在界面左上角增長了故事線面板
  • 增長了事件點的動畫效果
  • 各位想加故事線的同窗,只要clone下來並增補timelines.js 就能夠自動增長故事點。
var timelines = [{
    "id": "1",
    "title": "White Walkers Emerge",
    "description": "已經數千年未見蹤影的異鬼在北境出現, 他們攻擊了守夜人軍團的一隊遊騎兵以及野人",
    "location": 'Castle Black',
    "camera": {
        center: [18.853961295738596, 34.89038102283956],
        zoom: 5.21,
        pitch: 41,
        bearing: 0
    }
}
// ...
];
複製代碼

參考資源

github.com/mapbox/GOT-…app

custom layer官方文檔dom

Game_of_Thrones_Wiki 資源hin 豐富,包括地圖影像函數

相關文章
相關標籤/搜索