Topic: Buildings plugin

I'm working with the Buildings plugin and I've noticed that some of them aren't being drawn, even though they are defined in OpenStreetMaps.

34.16985, -118.5 is the area I'm testing at zoom level 18, and it's got a few buildings visible there that, unlike all the rest around them, don't show up.

I'm also using that plugin with the elevation turned on and I notice that due to the slopes on the map, some of the buildings don't reach all the way to the ground. Is there a way to fix that? Maybe making them extend further down than the map?

Thanks.

Re: Buildings plugin

Hello.

For some reason, OSM Overpass API sometimes does not return buildings that are marked on OSM.
Honestly, I do not know why this happens.
In Online Maps v2.6 it is planned to add generation of buildings based on Mapbox and Mapzen.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

Ok. I might look into that. I'll let you know if I come up with anything. Have you an idea as to when we might see v2.6? That'll give me an idea as to how hard I might want to look into the OSM stuff.

Regarding buildings, I've noticed that upon launch, you first see the tileset, then the elevation kicks in, and then the buildings appear. Is there some way to determine if the buildings (if any) have been loaded without changing the buildings plugin code? There's code I want to run, but only after the map is fully loaded.

Thanks!

Re: Buildings plugin

We plan to release Online Maps v2.6 in the summer.
But it is quite possible it will be Online Maps v3, because it will have a lot of changes.

OnlineMapsBuildings.OnBuildingCreated
http://infinity-code.com/doxygen/online … 72246c0d9e

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

Thanks! That's helpful, but wouldn't that trigger after the first building is created? I want a way to know when they've all been created and I know I'm working with everything that's going to be drawn.

Re: Buildings plugin

This event is called for each building.

You can do it this way:
After the first call of this event, you wait for the frame when this event is not called.
This means that all buildings have already been created.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

Thanks, but I'm not sure how I'd implement that without modifying the code in the event itself, causing me headache if you update it on your end.

Also, if the map is in an area that doesn't have any buildings, the event would never get called. I want to know when it's done displaying all the buildings, even if there are none to display.

Re: Buildings plugin

Example:

using System;
using System.Reflection;
using UnityEngine;

public class WaitingBuildingsCreation:MonoBehaviour
{
    private bool hasBuildingCreated = false;
    private bool firstBuildingCreated = false;
    private OnlineMapsBuildings buildings;

    private void Start()
    {
        buildings = OnlineMapsBuildings.instance;

        if (buildings.zoomRange.InRange(OnlineMaps.instance.zoom))
        {
            buildings.OnBuildingCreated += OnBuildingCreated;
            buildings.OnRequestSent += OnRequestSent;
        }
        else OnFinish();
    }

    private void OnRequestSent()
    {
        // Dirty hack to find out that the map does not have buildings.
        Type btype = typeof(OnlineMapsBuildings);
        FieldInfo field = btype.GetField("osmRequest", BindingFlags.Instance | BindingFlags.NonPublic);
        OnlineMapsOSMAPIQuery request = field.GetValue(buildings) as OnlineMapsOSMAPIQuery;
        request.OnComplete += OnRequestComplete;

        buildings.OnRequestSent -= OnRequestSent;
    }

    private void OnRequestComplete(string s)
    {
        if (s.Length < 300) OnFinish();
    }

    private void OnBuildingCreated(OnlineMapsBuildingBase building)
    {
        firstBuildingCreated = true;
        hasBuildingCreated = true;
    }

    private void OnFinish()
    {
        buildings.OnBuildingCreated -= OnBuildingCreated;

        Debug.Log("All buildings are created.");
        Destroy(this);
    }

    private void Update()
    {
        if (!firstBuildingCreated) return;
        if (hasBuildingCreated)
        {
            hasBuildingCreated = false;
            return;
        }

        OnFinish();
    }
}
Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

Awesome, thanks for the example code. I'll try it out and let you know if I run into any snags.

Really appreciate how responsive you are.

Re: Buildings plugin

That did the trick perfectly, thanks.

One thing I mentioned that you didn't respond to, though, is the fact that when you have both elevation and buildings turned on, the slope of the map (especially when you use an elevation multiplier to exaggerate the terrain features) causes the bottom of the building to not reach the surface of the map mesh, causing a visible gap to appear.

Not sure if that's something you'd want to tweak in your code so it doesn't happen, or if there's a way for me to vertically stretch the buildings during/after the creation process so they extend through the surface of the map. Anything the sticks out past the bottom won't be visible, and the building will reach the surface of the lowest elevations of its footprint, keeping any gaps from showing up.

Let me know if I'm not explaining myself clearly and I'll give you some coordinates and properties so you can see it for yourself.

Thanks a heap! smile

Re: Buildings plugin

You can fix it this way.
Example:

using System;
using UnityEngine;

public class FixBuildingBottomPoints:MonoBehaviour
{
    public float newBottomY = -10;

    private void Start()
    {
        OnlineMapsBuildings.instance.OnBuildingCreated += OnBuildingCreated;
    }

    private void OnBuildingCreated(OnlineMapsBuildingBase building)
    {
        MeshFilter meshFilter = building.GetComponent<MeshFilter>();
        Mesh mesh = meshFilter.sharedMesh;
        Vector3[] vertices = mesh.vertices;
        for (int i = 0; i < vertices.Length; i++)
        {
            Vector3 v = vertices[i];
            if (Math.Abs(v.y) < float.Epsilon)
            {
                v.y = newBottomY;
                vertices[i] = v;
            }
        }
        mesh.vertices = vertices;
    }
}
Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

Thanks!

Looks like I might need to mess with it a bit, as I'm noticing that not only are there gaps at the bottom when there's a significant elevation change, but sometimes the tops of the building disappear under the terrain if it rises too high. I could just make all the buildings higher in the settings for the Buildings component in the Inspector, but I don't want it to affect buildings it doesn't need to.

What I'm trying to aim for is all buildings being the same height above the highest elevation point and reaching all the way down (or past and through) their lowest elevation point. If it's easy for you to make that adjustment in the code you provided above, that'd be great, otherwise I'll see what I can do and let you know if I need assistance.

Re: Buildings plugin

Good news! I did some research on why sometimes the buildings aren't showing up and got a response:

https://forum.openstreetmap.org/viewtopic.php?id=57749

I make a couple of quick attempts at implementing the suggested change, but didn't have any luck. I thought you might be interested in seeing if you could make more sense of it and get all the buildings working with the OSM code you've got, making the Mapbox and Mapzen changes you were talking about a bit less urgent.

Re: Buildings plugin

You have several ways:
1. The easiest way is increase "Min Building Height".
2. When updating elevation data, you check the elevation for key points (for example, center + middle of bounding box edges), and update the roof points. It will be very similar to the example above (post 11), and I think you will do it without problems.
3. When updating elevation data, you check the elevation for center and all bottom points, and update the roof points. Not recommended, because it will be very slow.

Yes, it makes sense, but it's not so simple.
I foresee that when trying to generate relations (outer way + inner ways) this will have many artifacts due to triangulation.
If only generate outer way, the building will not look as marked on OSM.
It's a pretty difficult dilemma. Let me think about this a little.
In any case, thanks for the information.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

Thanks for the suggestions, I'll start looking into them.

I see what you mean, but I hope it doesn't end up being more trouble than it's worth, as it'd be nice to have a fully functional buildings component before the next major revision. If you don't end up implementing it and I find a way, I'll be sure to share it with the community.

Re: Buildings plugin

After poking at it a bit more, I've decided to use the following code for the time being.

requestData = String.Format("(way[{4}]({0},{1},{2},{3});relation[{4}]({0},{1},{2},{3}););out;>;out skel qt;", bry, tlx, tly, brx, "'building'");

It doesn't cut out the holes by implementing the inner ways, but for my purposes at the moment that's acceptable. At some point later I'll want to revisit the issue if you haven't fixed it by then, but just having the exterior borders of every building defined is worth the loss of the interior spaces.

I'd rather have all the buildings be there with some of them being imperfect than the ones that would be imperfect not there at all.

Thanks again!

Re: Buildings plugin

Using that line of code in post 16, I get meshes for the building, but also ones for the negative space inside them. I'm wondering if the best way to achieve the goal might be through an implementation of Constructive Solid Geometry, taking the negative space meshes and subtracting them from the main building mesh. I found a free asset that looks like it might do the trick, but I thought I'd pass the idea along to you before I got too far into it.

https://www.assetstore.unity3d.com/en/#!/content/47418

Re: Buildings plugin

Wondering if you've had a chance to think on this more. As it stands, any time you update I need to keep replacing your code with the line I mentioned in post 16 so that there aren't buildings that don't show up at all.

You said, "If only generate outer way, the building will not look as marked on OSM." To me, at least, that would be preferable to the building now showing up at all. I haven't had a chance to mess with the CSG asset I mentioned yet, and hopefully I won't have to if your team can come up with a workable solution. Please let me know your thoughts on the matter.

Thanks!

Re: Buildings plugin

First of all, you do not need to modify the code to change the request.
Use OnlineMapsBuildings.OnPrepareRequest.
Example:

using System;
using UnityEngine;

public class OnPrepareBuildingRequestExample
{
    private void Start()
    {
        OnlineMapsBuildings.instance.OnPrepareRequest += OnPrepareRequest;
    }

    private string OnPrepareRequest(string originalRequest, Vector2 topLeftCoords, Vector2 bottomRightCoords)
    {
        return String.Format("(way[{4}]({0},{1},{2},{3});relation[{4}]({0},{1},{2},{3}););out;>;out skel qt;", bottomRightCoords.y, topLeftCoords.x, topLeftCoords.y, bottomRightCoords.x, "'building'");
    }
}

If you use this request directly, you will have a rather strange result.
I tested the map in Rome (near to coliseum), and it looks a pretty bad.

We have made changes to the code, and now it works correctly with relations, but uses only the outer ways.
The new version will be available later this week.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

That's great, thanks. I'll hold off then on implementing the code you provided above, since a better version is due later this week. I appreciate the example, though, as it shows me how to modify such calls should I need to.

I'm actually considering adapting the building code to allow me to draw lines on the map to represent ways and relations found in OSM- the border of a playground, for example, or a golf course, or some other feature that isn't a building. If you have any examples or suggestions on how to do it more easily, I'd love to see them. If not, I'll work on it myself and if I get to the point where I've got something I think the community would find useful, I'll be sure to share it here.

Re: Buildings plugin

Unfortunately, we does not have examples for generating objects based on OSM data.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

I have the code you provided for detecting when all the building have been rendered working, but don't get exactly how you're using it. As I'm working more in the initialization routines of my scene, I find myself wanting to be sure I understand it. Could I ask you to explain it a bit? I'm adding in some comments to explain my confusion and what I think's going on. Thanks!

Alex Vertax wrote:

Example:

using System;
using System.Reflection;
using UnityEngine;

public class WaitingBuildingsCreation:MonoBehaviour
{
    private bool hasBuildingCreated = false;
    private bool firstBuildingCreated = false;
    private OnlineMapsBuildings buildings;

    private void Start()
    {
        buildings = OnlineMapsBuildings.instance;

        if (buildings.zoomRange.InRange(OnlineMaps.instance.zoom))
        {
            buildings.OnBuildingCreated += OnBuildingCreated;
            buildings.OnRequestSent += OnRequestSent;
        }
        else OnFinish();
    }

    private void OnRequestSent()
    {
        // Dirty hack to find out that the map does not have buildings.
        Type btype = typeof(OnlineMapsBuildings);
        FieldInfo field = btype.GetField("osmRequest", BindingFlags.Instance | BindingFlags.NonPublic);
        OnlineMapsOSMAPIQuery request = field.GetValue(buildings) as OnlineMapsOSMAPIQuery;
        request.OnComplete += OnRequestComplete;

        buildings.OnRequestSent -= OnRequestSent;

// my understanding here is that because a lack of building on the map means we won't get an event saying when one's created, so we can't know when they're done being created. We tie into the request so if it comes back and is too small, we know there aren't any buildings.

    }

    private void OnRequestComplete(string s)
    {
        if (s.Length < 300) OnFinish();
    }

    private void OnBuildingCreated(OnlineMapsBuildingBase building)
    {
        firstBuildingCreated = true;
        hasBuildingCreated = true;
    }

    private void OnFinish()
    {
        buildings.OnBuildingCreated -= OnBuildingCreated;

        Debug.Log("All buildings are created.");
        Destroy(this);
    }

    private void Update()
    {

// while this line makes sense to me
        if (!firstBuildingCreated) return;

// it's here where I get confused. it seems to me that this is relying on a building being created every frame, otherwise this update loop my execute on the next frame without the building creation triggering hasBuildingCreated. Is this so? Can this be relied upon? Is there any other way to determine the number of building to be displayed on the map so we know when we've shown them all?

        if (hasBuildingCreated)
        {
            hasBuildingCreated = false;
            return;
        }

        OnFinish();
    }
}

Re: Buildings plugin

First of all, starting from Online Maps v2.5.12 you can use OnlineMapsBuildings.OnAllBuildingsCreated.

How it works in the current script:
OnRequestSent is needed to get an instance of the request, and handle the situation when the map has no buildings. For example, there are no buildings in the sea, or it could just be a server error. In any case, this behavior must be handled.
The request is a private field, so you can get an instance of request only using reflection.

Online Maps take time to generate buildings.
An average of 1 millisecond per building.
But the map can contain hundreds and thousands of buildings at the same time (for example, New York or Moscow).
If you generate this number of buildings at the same time, it will just freeze your application for a few seconds.
Therefore, the map splits the generation of buildings into several frames (50 milliseconds per frame).

OnBuildingCreated will be invoked in each frame at least once.
In the frame when this action is not invoked, the generation of buildings was completed.

Kind Regards,
Infinity Code Team.

Boost your productivity a lot and immediately using Ultimate Editor Enhancer. Trial and non-commerce versions available.

Re: Buildings plugin

Awesome, that makes sense. I appreciate the explanation.

I'll also be sure to go ahead and implement OnlineMapsBuildings.OnAllBuildingsCreated. Does this trigger if there are no buildings to create, or must the code in OnRequestSent still be run?

Also, on another note earlier in this thread, and since I missed some of the updates more recently, has there been any change in the way donut-shaped buildings are handled? Last I heard I think it was just the outer way defining the building, so at least they were showing up somewhat properly.

Re: Buildings plugin

OnAllBuildingsCreated doesn't seem to be working for me. I drop a debug in there and in OnBuildingCreated and I'm getting notifications of buildings being created after being notified that they all already have been.

Am I missing something?