eliemichel / MapsModelsImporter

A Blender add-on to import models from google maps
https://blog.exppad.com/article/importing-actual-3d-models-from-google-maps
GNU General Public License v3.0
2.36k stars 300 forks source link

[Potentially useful Info] Google 3D cities available as OGC 3D tiles #279

Open jo-chemla opened 1 year ago

jo-chemla commented 1 year ago

Probably useful at some point, Google just released all its 2500 cities datasets as OGC/Cesium 3D-tiles at its GoogleIO-May2023 conference. The 3D-tiles standard is made to stream datasets - rather than download offline/merged 3D models - and is compatible through cesium libs with UnrealEngine, Unity, CesiumJS, Nvidia OmniVerse, deck-gl etc.

Note:

jo-chemla commented 1 year ago

Proof-of-concept from @OmarShehata on twitter.

OmarShehata commented 1 year ago

This would be super useful for a lot of people! Some more details from my process if it helps:

t0stiman commented 9 months ago

Thanks to you I was able to create my own method of grabbing gmaps 3d tiles.

Downloading the tiles

  1. Follow these steps to create a Unity project: https://cesium.com/learn/unity/unity-photorealistic-3d-tiles/#step-1-add-photorealistic-3d-tiles-to-your-scene
  2. Create 2 scripts:

meshDownloader.cs

using System.Net;
using UnityEngine;

//attach this script to the Cesium3DTileset object
public class meshDownloader : MonoBehaviour
{
    public string outputFolder = @"D:\temp\maps\";

    public void idk()
    {
        // var baseObj = GameObject.Find("Cesium3DTileset");
        var baseObj = gameObject;
        int counter = 0;

        //if outputFolder doesnt end with a backslash, add one, 
        if (outputFolder[outputFolder.Length-1] != '\\')
        {
            outputFolder += @"\";
        }

        for (int i = 0; i < baseObj.transform.childCount; i++)
        {
            var tile = baseObj.transform.GetChild(i).gameObject;
            if (tile.activeSelf && tile.name.Contains(".glb"))
            {                
                //download
                using (var client = new WebClient())
                {
                    Debug.Log(counter+".glb");
                    client.DownloadFile(tile.name, outputFolder+counter+".glb");
                    counter++;
                }
            }
        }
    }
}

meshDownloaderButton.cs

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(meshDownloader))]
public class meshDownloaderButton : Editor
{
    public override void OnInspectorGUI()
    {
        DrawDefaultInspector();

        var myScript = (meshDownloader)target;
        if (GUILayout.Button("download"))
        {
            myScript.idk();
        }
    }
}
  1. Add the MeshDownloader script to the Cesium3DTileset object.
  2. On the Cesium 3D tileset component:
    • set maxium screen space error to 0 to get the highest quality tiles. This will take a heavy performance toll! It's better to use the default value if you want to make sure things work first.
    • set Show Tiles in Hierarchy (important)
  3. Enter an output folder in the Mesh Downloader component and click "download"

Merging the tiles

You can merge the GLB files to 1 file with glTF Transform https://gltf-transform.dev/

gltf-transform merge *

Moving the tiles to the center of the scene

  1. import the .glb files or the combined .glb into Blender (file -> import -> gltf 2.0)
  2. select all objects (a)
  3. shift-ctrl-alt-c -> origin to geometry
  4. shift-s -> selection to cursor (keep offset)

Rotating the objects so they're face-up

Example coordinates: 53.496306, 9.9503333

  1. Rotate on the Z axis: -longitude (-9.9503333)
  2. Rotate on the Y axis: -90+lattitude (-90+53.496306)
t0stiman commented 9 months ago

One problem I'm still trying to solve is these gaps:

afbeelding

My theory is that these gaps are there because the meshes in the glb files are so far from the center of the scene. Blender uses floating point values to store positions, so the further from the center of the scene the meshes are, the less precise their position is stored.
I haven't been able to find a solution for this problem yet so if anyone who reads this has an idea, I'd love to know