Placing Objects on the Globe
When using Cesium for Omniverse to include real-world tilesets like Cesium World Terrain in your Omniverse stage, you will likely want to add other objects from the standard Omniverse assets library: meshes, foliage, and more.
You’ll learn how to:
- Add Omniverse assets to a stage.
- Anchor those assets to real-world locations on Cesium tilesets.
- Know how to set up a basic Cesium for Omniverse stage in NVIDIA Omniverse USD Composer. Check out our Cesium for Omniverse Quickstart guide for instructions on starting with the Cesium for Omniverse extension.
- Cesium for Omniverse 0.17.0 or later.
- The USD that was created during the Quickstart, a copy of which can be found in the tutorials\00_quickstart folder in the Cesium for Omniverse samples repository.
Adding objects near the origin of the CesiumGeoreference is the same as adding them to any other Omniverse stage.
1Open the stage created during the Quickstart.
2From NVIDIA Assets > Vegetation, select a large tree, such as the Black_Oak, and drag it onto Cesium World Terrain.
3Using the transform, rotate and scale gizmos to adjust the location of the prim as desired.
Any normal Omniverse asset can be added to the level in the usual way. However, there are some details that will be useful to know more about, and they are discussed below.
Because of Earth’s curvature, the farther we move away from the CesiumGeoreference origin location, the less the Omniverse minus Y (or minus Z with the stage set to Z up) direction is an accurate representation of the local “down” direction. To be precise, the down direction changes by roughly 0.01 degrees for every kilometer we move from the origin. A hundred kilometers from the origin, the down direction will be “wrong” by about 1 degree. Although that might be acceptable for most applications, by the time we get to the opposite side of the globe, the down direction is 180 degrees from what we expect it to be. Objects placed on the opposite side of the globe and configured to obey Omniverse gravity will “fall” into space!
The roundness of Earth affects other Omniverse behavior, too, not just physics. Cameras usually maintain an upright orientation, but their notion of “upright” is incorrect for a round planet.
Dealing with the reality of a round planet requires employing one of the following techniques, in order from simplest to most complex:
- Stay within a relatively small area close to the stage origin, probably 100 kilometers or so.
- Use a Cesium Globe Anchor component to add limited globe-awareness to any Omniverse prim (see "We can turn regular prims into georeferenced prims" below).
- Custom scripting, action graphs, extension development, or other solutions to make your prims be fully aware of the round Earth.
When we place regular Omniverse prims, as we did with the tree above, we give them particular coordinates in the Omniverse stage.
However, the relationship between the stage coordinate system and the real world is not fixed. It is defined by the origin properties of the CesiumGeoreference actor, and it can be changed. The important thing to note is that, when the CesiumGeoreference origin changes, the entire globe rotates to align a new latitude, longitude, and height to the 0,0,0 coordinates of your stage. By default, all prims on your stage will remain fixed to the stage and will not move with the globe.
1Try this out by selecting the CesiumGeoreference and adjusting your Latitude value to 37.7769.
2You should see Cesium World Terrain move within the stage accordingly, along with Cesium OSM Buildings. However, the Black_Oak remains in exactly the same stage coordinates and will now appear to be placed in a different location on the globe.
3Return the Latitude value back to 37.7749; the tree should now be in its previous position.
The above is true for almost all prims in Omniverse, but there are some prims that obey a different set of rules. We call these georeferenced prims.
Unlike a regular prim, which is fixed to the stage, a georeferenced prim is fixed to the globe. It has a position expressed with double-precision, Earth-Centered, Earth-Fixed (ECEF) coordinates, or—equivalently—longitude, latitude, and height. If those coordinates put it next to the William Penn statue at the top of Philadelphia’s City Hall, for example, it will stay perched up there until we move it, even if we adjust the origin coordinates in the CesiumGeoreference so that our stage is now centered on the Sydney Opera House in Australia.
We can turn a regular prim into a georeferenced prim by adding a Cesium Globe Anchor to it:
1Right click the Black_Oak prim in the stage and select Add > Cesium > Globe Anchor.
Just by adding the Cesium Globe Anchor, we have converted the Black_Oak into a georeferenced prim. Now, if we change the CesiumGeoreference prim’s latitude, longitude, or height, the Black_Out prim will move along with the globe. We can also specify Longitude/Latitude/Height or Earth-Centered, Earth-Fixed coordinates directly on the Cesium Globe Anchor to place the object with precise numerical coordinates.
A Cesium Globe Anchor can be added to prims programmatically via a python helper function within the Cesium for Omniverse API. This example demonstrates placing trees within a stage using latitude, longitude, and height data.
1Open the Script Editor by clicking Window > Script Editor.
2Paste in the following Python script:
import omni.kit.commands
import omni.usd
from pxr import Sdf, UsdGeom, Usd
from cesium.usd.plugins.CesiumUsdSchemas import (
GlobeAnchorAPI as CesiumGlobeAnchorAPI
)
trees = [
{"name":"tree_01","latitude":37.79130, "longitude":-122.39032,"height":-28.88791},
{"name":"tree_02","latitude":37.79114, "longitude":-122.39018,"height":-28.88791},
{"name":"tree_03","latitude":37.79147, "longitude":-122.39042,"height":-28.88791},
{"name":"tree_04","latitude":37.79167, "longitude":-122.39053,"height":-28.88791},
]
context = omni.usd.get_context()
stage = context.get_stage()
for t in trees:
anchor_prim_path = "/World/"+t["name"]+"_anchor"
payload_prim_path = anchor_prim_path+"/"+t["name"]
anchor_prim: Usd.Prim = UsdGeom.Xform.Define(stage, Sdf.Path(anchor_prim_path)).GetPrim()
payload_prim: Usd.Prim = UsdGeom.Xform.Define(stage, Sdf.Path(payload_prim_path)).GetPrim()
omni.kit.commands.execute("AddPayload",
stage=stage,
prim_path = payload_prim_path,
payload=Sdf.Payload(
assetPath = "http://omniverse-content-production.s3-us-west-2.amazonaws.com/Assets/Vegetation/Plant_Tropical/Cuban_Royal_Palm.usd",
primPath = Sdf.Path.emptyPath
)
)
globe_anchor = CesiumGlobeAnchorAPI.Apply(anchor_prim)
globe_anchor.GetAnchorLatitudeAttr().Set(t["latitude"])
globe_anchor.GetAnchorLongitudeAttr().Set(t["longitude"])
globe_anchor.GetAnchorHeightAttr().Set(t["height"])
3Click the Run button to execute the script.
4Four palm trees with Cesium Globe Anchors should be placed on the stage using the latitude, longitude, and height specified in the script.
Experiment with using the concepts presented in this tutorial in more complex ways, such as simulating a plane flying across the globe by animating globe anchor properties, or automate placing objects on the globe from open spatial data sources.