ebeaufay / threedtiles

3DTiles viewer for three.js
MIT License
270 stars 32 forks source link

LOD for the Google Maps 3D TileSet #14

Closed c4b4d4 closed 1 year ago

c4b4d4 commented 1 year ago

Hello!

I'm trying to navigate thru a 3D TileSet of Google (https://tile.googleapis.com/v1/3dtiles/root.json) using this library.

I've managed to run the index.js on my three.js engine and it does load the map correctly, but I only get the detail as a whole Earth Globe:



No matter if my camera is close to a surface, it does not activate the LOD and does not load better quality tiles. I don't know if there's one implemented here.

So, how should I approach this? How could I just load higher-quality as I get closer?

Also... it was pretty hard to find the mesh of the globe, ended up finding by luck. How could I transform Lat/Lng/Altitude coordinates to 3D coordinates for this glob.

This is how I'm loading the tiles:

const tileLoader = new TileLoader({
    renderer,
    maxCachedItems: 1000,
    meshCallback: mesh => {
        mesh.material.wireframe = false;
        mesh.material.side = THREE.DoubleSide;
    },
    pointsCallback: points => {
        points.material.size = Math.min(1.0, 0.1 * Math.sqrt(points.geometricError));
        points.material.sizeAttenuation = true;
    }
});

const ogc3DTile = new OGC3DTile({
    url: "https://tile.googleapis.com/v1/3dtiles/root.json",
    queryParams: { key: GOOGLE_MAPS_API_KEY },
    geometricErrorMultiplier: 0.3,
    loadOutsideView: true,
    tileLoader: tileLoader,
    static: false,
    centerModel: false,
    renderer,
    yUp : true,
    onLoadCallback: tileset => {
        console.log(tileset.json.boundingVolume);
    },
    displayErrors: true,
    displayCopyright: false
});

ogc3DTile.scale.set(0.001, 0.001, 0.001);
ogc3DTile.rotateOnAxis(new THREE.Vector3(1, 0, 0), Math.PI * -0.5);

scene.add(ogc3DTile);

I'm also running this every frame:

ogc3DTile.update(camera);

Thanks :)

ebeaufay commented 1 year ago

Code looks ok, are you sure no tiles are loading? Check the network tab of the dev console to see if any "glb" files are coming in. you can also increase the "geometric error multiplier". The higher the value the more data is loaded

For some help with controls, you can check the UltraGlobe project https://github.com/ebeaufay/UltraGlobe.

With that project you'll have some controls already implemented

c4b4d4 commented 1 year ago

Thank you! I got it, had to do with the Geometric Error Multiplier. Higher value was indeed needed.

For the controls, I found that there is a method called: transformWGS84ToCartesian in the OGC3DTile class... https://github.com/ebeaufay/threedtiles/blob/38dd4d119f790e32c34331e1327de64d6da4a6c9/src/tileset/OGC3DTile.js#L808

But it seems inaccurate. I tried moving to Manhattan, NYC with coordinates: 40.7197344,-74.0014917, and the point was off by a lot. I ended up finding Manhattan at coordinate: 47.1065,-72.1336

I don't know if it's something to do with decimal points, but it it's a long distance off.

ebeaufay commented 1 year ago

The method takes arguments (lon, lat, height, sfct) where sfct is a side effect object.

You put the values in the wrong order, (lat-lon vs lon-lat). Also, the longitude and latitude must be in radians, (multiply by Pi/180)

ebeaufay commented 1 year ago

Just an update on this because the function might be broken. In the other project, I use the "proj4" and "epsg-index" to do the conversion between reference systems.

This is more accurate:

import as epsg from 'epsg-index/all.json'; import as proj4 from 'proj4';

const fromEPSG = epsg[4326] //lon lat height with wgs84 ellipsoid (same as google map tiles) const toEPSG = epsg[4978] // cartesian const transform = proj4.default(fromEPSG.proj4, toEPSG.proj4)

let geo = {x:-72.1336, y:47.1065, z:0}; const cartesian = transform.forward(geo); geo = transform.inverse(cartesian );

c4b4d4 commented 1 year ago

I see!! Amazing, will use this method instead. Thank you!