在maptalks中加載三維模型obj,fbx,glb


 

  • maptalks 是一個基於WebGL的三維地圖js庫,基於maptalks可以快速建立web三維地圖,加載各種地圖數據,生成對應的圖層,加載三維模型等。

 

 

  •  地圖加載。maptalks支持標准的地圖數據類型,如GeoJson,TileServer等。

    GeoJson格式是一種地理信息對象描述文件,可以是本地的,也可以存儲在遠程服務器上,其基本格式如下:

    

{
"type": "FeatureCollection",
"name": "line0706",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "id": 26, "OID": 26, "PID": "1JS2036-1JS2037", "Shape_Length": 215.78135367381537, "linegj": 400.0, "linecz": "球墨鑄鐵" }, "geometry": { "type": "LineString", "coordinates": [ [ 117.139587450494673, 31.980963606892612 ], [ 117.141572764515146, 31.980002698897021 ] ] } },
{ "type": "Feature", "properties": { "id": 27, "OID": 27, "PID": "1JS2037-1JS2038", "Shape_Length": 174.33523286131555, "linegj": 400.0, "linecz": "球墨鑄鐵" }, "geometry": { "type": "LineString", "coordinates": [ [ 117.141572764515146, 31.980002698897021 ], [ 117.143128167657636, 31.979157606398935 ] ] } },
{ "type": "Feature", "properties": { "id": 28, "OID": 28, "PID": "1JS2038-AJS2720", "Shape_Length": 74.157593232456321, "linegj": 400.0, "linecz": "球墨鑄鐵" }, "geometry": { "type": "LineString", "coordinates": [ [ 117.143128167657636, 31.979157606398935 ], [ 117.143830270406454, 31.978859076104776 ] ] } },
{ "type": "Feature", "properties": { "id": 29, "OID": 29, "PID": "1JS2039-DJS504", "Shape_Length": 116.76683212772929, "linegj": 400.0, "linecz": "球墨鑄鐵" }, "geometry": { "type": "LineString", "coordinates": [ [ 117.146490176708213, 31.977233403153686 ], [ 117.147518501281553, 31.9766498062083 ] ] } },
{ "type": "Feature", "properties": { "id": 30, "OID": 30, "PID": "1JS2040-1JS2041", "Shape_Length": 346.5596390599348, "linegj": 400.0, "linecz": "球墨鑄鐵" }, "geometry": { "type": "LineString", "coordinates": [ [ 117.148207019802612, 31.976299944711535 ], [ 117.151189187226777, 31.974481644858205 ] ] } }
]
}

  

    可以看出,geoJson格式是在Json數據格式的基礎上增加了關於GIS的一些屬性描述信息,

    如type:Feature表示是一個地理對象,properties表示對象的屬性值,geometry表示要描述的地理對象,

    里面type:LineString表示類型是一個線段, coordinates 表示坐標,后面接着的數組表示一組坐標值,來表示起始點坐標位置。

  

  ArcGISTileLayer

     let ArcGIS_Layer = new maptalks.ArcGISTileLayer('line', {

          visible: true,

          urlTemplate: 'http://127.0.0.1:6080/server/rest/services/line/MapServer',

     });

    urlTemplate對應的值就是已經部署在ArcGIS服務器上的地圖服務地址。

  • 三維模型。基於maptalks 有一個使用threejs開發 maptalks.threeLayer 庫,可以在maptalks中直接引用,在maptalks中加載三維模型,其實就是使用threejs加載三維模型。

   常用的三維模型有以下幾種,obj,fbx,glb。使用同一個模型導出的三種文件格式大小如下圖:

  

 

  從文件大小看,fbx和glb更有優勢。

  使用Windows自帶的3D模型打開文件

 

   obj模型一般情況下包含2-3個文件,obj,mtl,jpg(png), obj 為模型文件,mtl 和 jpg文件為材質文件,obj文件可以通過文本編輯器打開,可以看到里面指定了該obj文件對應的材質文件的名稱。其余的是在三維空間中繪制的點位置。

    

 

 

   需要使用材質的位置則指定使用mtl文件中的材質名稱。

     

 

 

   在mtl文件中,則可以看到該材質的名稱對應的參數

    

 

 

 

  fbx文件和glb為二進制編碼后的文件,使用文本編輯器打開為亂碼。

  從可讀性看,obj文件更占優勢。

 

  • 使用maptalks.threelayer 加載三維模型

    threejs針對obj、fbx、glb三種格式的三維模型有專門的示例,針對threejs加載,可以在其官網 https://threejs.org/examples 查看,這里專門講解maptalks 地圖中的加載。

    首先,threejs 提供了用於專門解析模型的 js 文件,  

    

    需要注意的是:在使用的過程中,需要確認 maptalks.js, maptalks.threelayer.js, 與 OBJLoader.js,MTLLoader.js,FBXLoader.js,GLTFLoader.js所引用three.js 版本一致,否則會出現函數不兼容的情況,無法調用成功。

    加載obj的方法為:     

 new THREE.MTLLoader(manager)
                .setPath('/js/symap/lib/maptalks/models/obj/ws/')
                .load('gs.mtl', function (materials) {

                    materials.preload();

                    new THREE.OBJLoader(manager)
                        .setMaterials(materials)
                        .setPath('/js/symap/lib/maptalks/models/obj/ws/')
                        .load('gs.obj', function (object) {

                            object.traverse(function (child) {
                                if (child instanceof THREE.Mesh) {
                                    child.scale.set(0.01, 0.01, 0.01);
                                    child.rotation.set(Math.PI * 1 / 2, Math.PI * 1 / 8, 0);
                                }
                            });

                            _this.getObject3d().add(object);

                            const z = layer.distanceToVector3(50, 50).x;
                            const position = layer.coordinateToVector3(
                                coordinate,
                                z
                            );

                            _this.getObject3d().position.copy(position);

                        });
                });

    加載 fbx 的方法為:

var loader = new THREE.FBXLoader();
            loader.load('/js/symap/lib/maptalks/models/fbx/beng.fbx', function (object) {

                object.scale.set(0.002, 0.002, 0.002);
                object.rotation.set(-Math.PI * 1 / 2, -Math.PI * 1 / 2, 0);

                _this._mixer = new THREE.AnimationMixer(object);

                const action = _this._mixer.clipAction(object.animations[0]);

                if (title.indexOf("測試") > -1) { //速度不為0,顯示運轉
                    action.stop();
                } else {
                    action.play();
                }

                object.traverse(function (child) {

                    if (child.isMesh) {

                        if (child.name == "bengke") {

                            child.material.visible = false;

                        }

                        child.castShadow = true;
                        child.receiveShadow = true;

                    }

                });

                _this.getObject3d().add(object);

                const z = layer.distanceToVector3(150, 150).x;
                const position = layer.coordinateToVector3(
                    coordinate,
                    z
                );
                _this.getObject3d().position.copy(position);

            });

    加載 glb 文件的方法為:

var gltfLoader = new THREE.GLTFLoader(manager);

            const dracoLoader = new THREE.DRACOLoader(manager);

            gltfLoader.setDRACOLoader(dracoLoader);

            gltfLoader.setPath('/js/symap/lib/maptalks/models/gltf/');
            gltfLoader.load('gssb.glb', function (gltf) {

                var object = gltf.scene;
                object.scale.set(0.3, 0.3, 0.3);
                _this.getObject3d().add(object);

                object.traverse(function (child) {
                    if (child instanceof THREE.Mesh) {
                        //if (child.name == "bengke") {
                        //    child.material.visible = false;
                        //}
                        child.rotation.set(Math.PI * 1 / 2, 0, 0);
                        child.scale.set(0.1, 0.1, 0.1);
                    }
                });

                const z = layer.distanceToVector3(150, 150).x;
                const position = layer.coordinateToVector3(
                    coordinate,
                    z
                );

                _this.getObject3d().position.copy(position);

                _this._mixer = new THREE.AnimationMixer(object);
                var clip = gltf.animations[0];
                _this._mixer.clipAction(clip.optimize()).play();

            });

    在glb的加載中,另外引用了一個 DRACOLoader.js 這是一個js庫可以在模型加載的過程中對模型進行壓縮。

    踩坑記錄:

    在3D軟件設計模型時,將模型放在(0,0,0)的位置,否則模型加載后不能出現在Scene中,或者不在代碼設定的位置上。

    另外對比同一開發環境下單個模型的加載方式對比: 支持   不支持  待測

 

格式

大小

多文件

可讀性

加載速度

支持動畫

運行壓縮

預壓縮

備注

Obj

17.36M

     

30ms

       

 

fbx

6.3M

     

21ms

        

 

glb

8.3

     

25ms

        

 

 

    在此次測試中,從加載時間來看,fbx>glb>obj ,綜合網絡搜索結果,glb模型對其它三維GIS軟件(Cesium,CityEngine)的兼容性更好,所以在本項目中使用glb格式的三維模型文件。

    下圖為在maptalks中加載的三維模型:

     

 

 

    針對模型較大的問題,網上還有其它解決方法,比如DRACOLoader將模型壓縮為drc文件進行加載;大模型拆分小模型然后分別壓縮drc文件加載;精細模型減少內部結構,保留表面減少模型實際大小等,在開發中再進行測試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM