What on earth is going on with BillboardGraphics sizeInMeters?

I made this Sandcastle to try to illustrate a problem I’m having, but it turned out crazier than the original issue.

Let me back up for a minute. I wanted to make a “label” that stays at a fixed size while zooming, so I thought I could create an image of the text in question and use it as a billboard with sizeInMeters: true. This mostly worked, but the “text image” wound up a bit smaller than I expected it to be – if I told it to be 55km across, it would measure out at maybe 43km. I couldn’t figure out why, so I put together a simpler version, in the sandcastle I linked above. I just made a simple rectangle, then drew a box on a canvas with the same aspect ratio and attached it to a billboard in the same entity with the same dimensions.

I expected the billboard to be a little smaller than the rectangle, same as in my project, but I got this:

WAT.

That skinny purple rectangle is a billboard with a width twice its height. The original image has the correct aspect ratio (400x200 px), which you can see by going to the console and looking at canvas.toDataURL() – in Chrome, at least, you can right-click the resulting data: link and Open in New Tab. I have no idea how it’s rendering at an aspect ratio of maybe 1:4 instead of 2:1. Am I using the properties incorrectly? Is there some fundamental thing I don’t understand? Or is the feature just totally broken?

Note: I am aware that my measurement for the meter-width of the rectangle is approximate. They’re not supposed to line up exactly, I’m just trying to provide rough numbers to illustrate the issue.

“Totally broken” is a bit harsh. It usually works, but this seems like a bug. With

width: 65536,
height: 32768,

the image is not distorted.

With

width: 80000,
height: 40000,

the image is slightly distorted.

I sunk some time with debugging that, and eventually, it seems to boil down to the imageWidth being clamped to 65536 at https://github.com/CesiumGS/cesium/blob/d49c0c3b208e406e984039b03c4b96a3ab07bf8b/Source/Scene/BillboardCollection.js#L1095 for some sort of compressed storage.

(Sorry, no idea for a fix/workaround, but maybe the pointer is helpful)

2 Likes

Thanks, it is definitely helpful! It never even occurred to me that the size of the billboard would be a factor. I made my own drawing tools in the project I’m working on, so I was just kind of doodling on the globe, not really thinking about the real-world implications of a 400km shape.

With this, I can put together a repro and file an issue on their tracker to get it addressed.

A vague gut feeling is that the reason for the error (and thus a possible path of tackling this and fixing the bug) is that the imageWidth is assumed to be the actual image size - and there’s hardly a point of having images that are more than 65536 pixels wide.

So it might be that one “only” has to change some code from

process(billboard) {
    writeCompressedData(billboard.width);
    ...
}

to

process(billboard) {
    widthInPixels = billboard.sizeInMeters ? 
        convertToPixels(billboard.width) : 
        billboard.width;
    writeCompressedData(widthInPixels);
    ...
}

But spotting the right place for this (and not breaking other configurations when fixing it) might not be so trivial.

I’m glad you replied because I actually forgot to file the issue this morning. I just opened this.