Hello everyone! After reading around the forum, I think it’s time to ask my own question.
We are trying to:
- Draw a (flat) 3D model on the globe at a given position and orientation (done), of a specific colour (also done). This has been done using a ModelGraphic with custom shader.
- Take an SVG icon and draw that so that it appears to be flat on top of that model (which is itself flat on the globe), with the orientation of the SVG matching the orientation of the model. This is giving us some issues.
As I see it, this isn’t a job for Billboards, which are designed for orienting things relative to the user viewing the screen. This seems to be more a job for an ellipse/rectangle (which will conform to the globe surface) with a custom material specified to handle displaying the SVG. This works to an extent, but the problem with both of these approaches is that these shapes are specified (sensibly, it seems) using real world dimensions. The model, however, uses pixel/scale properties to handle it’s size, so the big question is how do we create an icon that we can scale with the model that still conforms to the surface of the globe?
The gold plated solution here feels to me like we should be doing something like:
- get the ModelGraphic, put it in the world
- find the bounding sphere of this model
- from this bounding sphere, use the radius to draw an ellipse with a custom material, then we have managed to couple the size of the model (pixels) to a real world measurement (the radius) and the task is closer to being complete
In the above, it’s the step of going from ModelGraphic → bounding sphere that seems the most unclear to me at the moment.
Any suggestions on the above ideas/approaches or general advice for other approaches much appreciated!
Hi @artcodespace, welcome to the forums!
If you’re able to provide a sample sandcastle or even just an example model + svg, that might help me understand exactly what you’re trying to do. I’m a little confused by “flat model” and how that differs from a custom polygon or even just an image.
I’m also wondering if you can just bake your SVG into your flat model, or if it has to be dynamic (i.e. same model, but swapping out the SVG on top at runtime).
Lastly, what do you mean when you say that the model uses pixel/scale properties? If you’re using glTF, its units are measured in meters, which matches Cesium’s internal units.
I’ll look out for your response.
Best,
Matt
Hello Matt, thanks very much for taking the time to respond!
I’ll work on trying to put a representative sandcastle together now. In the meantime I’ll try and clarify some of your questions.
We use a model that I think has extremely low height. It always sits on the surface of the globe and as we pan around, it always appears flat. I believe we do this (over using an SVG) to allow us to get around heading problems that we had when placing SVG representations of the entities on the globe. The entity represents a vehicle that has a heading, so it is important that the heading is accurate (we were having issues where rotating the camera was throwing the heading of the SVG off).
The SVG that we want to draw on top of the model is generated dynamically by a library. Effectively there’s a large icon set (approx 100 at the moment, but it will be growing soon), you pass the generator an identifier and it spits out an svg icon. So ideally we would be putting an SVG on top at runtime, otherwise I suppose it’s starting to look like baking the svg into the model would necessitate producing n models for n different SVG.
On the pixel/scale properties, sorry that wasn’t very clear. Our model is defined in a .glb file but I meant the ModelGraphics
in @cesium/engine/Source/DataSources/ModelGraphics.js is where you can set minimumPixelSize
and maximumScale
. So when we set the minimumPixelSize
on the ModelGraphics
and we hit that size, it’s not clear to me how we could figure out a way to size an ellipse or rectangle to fit inside the external limits of the model at that size. Even if I could figure out the bounding sphere stuff, there are notes in the bounding sphere documentation saying that it doesn’t consider minumumPixelSize
.
(The sandcastle post is just pending approval).
Please find attached a representative sandcastle:
Thanks for the example - very clear! Unfortunately, after playing around with it for a bit, I wasn’t able to reproduce exactly what you want, but I have three ideas that maybe you’d want to explore:
- The vehicle in the example is an instance of Cesium.ModelGraphics, which has a property
nodeTransformations
containing transformation / rotation / scale values. Maybe you can apply these to a rectangle displaying the SVG to have it match the vehicle.
- Create a plane in your modeling software of choice, and bake the SVG onto it as a texture. Load it into Cesium as an entity / modelgraphics, and use the same
minimumPixelSize
/ maximumScale
properties as on the vehicle. You’d have to do this for every SVG, but at least you wouldn’t have to do it for every SVG-model-combination.
- Building on 2 ^ you might be able to just create one plane (again, populating the
minimumPixelSize
/ maximumScale
properties), and use the model’s customShader
property to sample an image texture.
Hopefully one of those can work out for you!