iTowns / itowns

A Three.js-based framework written in Javascript/WebGL for visualizing 3D geospatial data
http://www.itowns-project.org
Other
1.11k stars 303 forks source link

OGC3DTilesLayer loading 3dtiles model position adjustment and scaling adjustment? #2406

Open liangyuan1 opened 2 months ago

liangyuan1 commented 2 months ago

Manual modeling of data fbx is required to slice and convert it into 3dtiles. Use cesiumLab (download link: https://www.bjxbsj.cn/downcenter.html )This tool can be converted to 3dtiles1.1 (gltf) and 3dtiles1.0 (b3dm), where 3dtiles1.1 cannot load with an error message, while 3dtiles1.0 can load normally, but cannot change the model display position and scaling ratio as Cesium does, resulting in incorrect model position and scale after loading. What do I need to do to correctly place the model in the specified position(需要人工建模数据fbx 进行切片转化成3dtiles。使用cesiumLab(下载地址:https://www.bjxbsj.cn/downcenter.html),该工具可以转成3dtiles1.1(gltf)和3dtiles1.0(b3dm),其中3dtiles1.1无法加载报错,3dtiles1.0可以正常加载,但是无法像cesium加载完成更改模型显示位置和以及缩放比例,导致我加载后的模型位置和比例不对,我需要怎么做可以正确放到指定位置上

result

image

AnthonyGlt commented 2 months ago

Are you using OGC3DTilesLayer to load it ? Example : 3dtiles_loader.html You should be able to edit the position using something like:


view.addLayer(layer).then((layer) => {
     layer.object3d.position.set( X, X, X );
                    layer.object3d.updateMatrixWorld( true );

})
liangyuan1 commented 2 months ago
 layer.object3d.position.set( X, X, X );

export function add3dTilesData(view) { const source = new itowns.OGC3DTilesSource({ url: '/2/tileset.json', }) console.log(source)

const layer = new itowns.OGC3DTilesLayer('3DTiles', { source, })

// Add the layer to our view view.addLayer(layer).then((layer) => { console.log('-000000000000000', layer, layer.object3d) // 等待图层加载完成 layer.object3d.scale.set(3, 3, 3) // layer.object3d.position.set(113.249257, 28.408089, 0) layer.object3d.updateMatrixWorld(true) // 更新视图以反映更改 view.notifyChange() zoomToLayer(view, layer) }) } The above is my implementation method. When I scale, I use layer.ort3d.scale. set (3, 3, 3) When layer. object3d. updateMatrixWorld (true) is set, the model cannot find where it is, but layer. object3d. scale. set (1, 1, 1) is the same as before. In addition, when I only set layer. object3d. position. set (113.249257, 28.408089, 0), the zoom ToLayer (view, layer) is still executed in its original position, and the model cannot be found when changing the coordinate position

jailln commented 2 months ago

You need to set the layer position in the same coordinate system as the view (that you can access with view.referenceCrs. If you are using a GlobeView for instance, the position must be in the EPSG:4978 coordinate system.

113.249257, 28.408089, 0 seems like EPSG:4326 coordinates. If that's the case, you must convert them first. To do that, you can use the Coordinates class:

var geographicPos = new itowns.Coordinates('EPSG:4326', 113.249257, 28.408089, 0);
var viewerCrsPos = geographicPos.as(view.referenceCrs);
layer.object3d.position.copy(viewerCrsPos.toVector3());
layer.object3d.updateMatrixWorld():
jailln commented 1 month ago

@liangyuan1 have you been able to test the solution from my previous comment ?

liangyuan1 commented 1 month ago

@liangyuan1 have you been able to test the solution from my previous comment ?

Itowns - 3D Tiles loader
Specify the URL of a tileset to load:

Feature Information:

liangyuan1 commented 1 month ago

@liangyuan1 have you been able to test the solution from my previous comment ?

@jailln https://github.com/hiwxy95/Hanged-brother.git ,3dtiles model

jailln commented 1 month ago

@liangyuan1 I managed to display it:

image

There was three reasons why it was hard to see your tileset:

            function addElevationLayerFromConfig(config) {
                config.source = new itowns.WMTSSource(config.source);
                var elevationLayer = new itowns.ElevationLayer(config.id, config);
                view.addLayer(elevationLayer);
            }
            itowns.Fetcher.json('./layers/JSONLayers/IGN_MNT_HIGHRES.json').then(addElevationLayerFromConfig);
            itowns.Fetcher.json('./layers/JSONLayers/WORLD_DTM.json').then(addElevationLayerFromConfig);

You can comment these lines to remove the terrain (or update the altitude of your model, similarly to what is done here)

view.addLayer(window.layer).then((layer) => {
                    layer.addEventListener('load-model', (m) => {
                        m.scene.scale.set(10, 10, 10);
                        m.scene.updateMatrixWorld();
                    });
                    zoomToLayer(view, layer);
                    window.addEventListener('click',
                        (event) => fillHTMLWithPickingInfo(event, pickingArgs), false);
                });

Note that the zoomToLayer util zooms to the 3D Tiles tileset bounding box which does not consider the position/rotation/scale updates applied to the model after loading, so zooming might be broken when you update the position or rotation or scale. To fix that, you can zoom to the layer.object3d bounding box that you can for instance compute with Box3.setFromObject.

            const view = new GlobeView(viewerDiv, placement, {
                controls: {
                    minDistance: 10, // Update the value here
                }
            });
liangyuan1 commented 1 month ago

@jailln Thank you very much, but I still want to modify the model position. I tried using the following code, but I was not successful. In addition, how to automatically locate the model after I modify the model position? I don't quite understand what you said about Box3. setFromObject. Can you provide a demo? Thank you

code

const source = new itowns.C3DTilesSource({ url: '/data/2/tileset.json' // url: 'https://raw.githubusercontent.com/CesiumGS/3d-tiles-samples/master/1.0/TilesetWithRequestVolume/tileset.json' }); const layer = new itowns.OGC3DTilesLayer('3DTiles', { source });

    // Add the layer to our view
    view.addLayer(layer).then(layer => {
      console.log('-0-0-0-0-0-0-0-0', layer);
      layer.addEventListener('load-model', m => {
        m.scene.scale.set(100, 100, 100);
        m.scene.rotation.z = Math.PI;
        const coord = new itowns.Coordinates(
          'EPSG:4326',
          113.052834960937517,
          28.466879577636721,
          0
        );
        m.scene.position.copy(coord.as(view.referenceCrs));
        console.log('-----坐标转化--dsdssssss--', m.scen);
        m.scene.updateMatrixWorld();
      });
    });