Skip to content

Commit

Permalink
Added the Cesium Omniverse Python API with a function to create anchors
Browse files Browse the repository at this point in the history
  • Loading branch information
weegeekps committed Oct 18, 2023
1 parent 9137f54 commit b5476c5
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 20 deletions.
Empty file.
14 changes: 14 additions & 0 deletions exts/cesium.omniverse/cesium/omniverse/api/globe_anchor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from pxr.Sdf import Path
from typing import Optional

from ..utils.cesium_interface import CesiumInterfaceManager


def anchor_xform_at_path(
path: Path, latitude: Optional[float] = None, longitude: Optional[float] = None, height: Optional[float] = None
):
with CesiumInterfaceManager() as interface:
if latitude is None and longitude is None and height is None:
interface.add_global_anchor_to_prim(str(path))
else:
interface.add_global_anchor_to_prim(str(path), latitude, longitude, height)
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ class Connection:

class ICesiumOmniverseInterface:
def __init__(self, *args, **kwargs) -> None: ...
@overload
def add_global_anchor_to_prim(self, arg0: str) -> None: ...
@overload
def add_global_anchor_to_prim(self, arg0: str, arg1: float, arg2: float, arg3: float) -> None: ...
def connect_to_ion(self) -> None: ...
def create_token(self, arg0: str) -> None: ...
def credits_available(self) -> bool: ...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from omni.kit.window.property import get_window as get_property_window
from pxr import Tf, UsdGeom
from cesium.usd.plugins.CesiumUsdSchemas import Tileset as CesiumTileset
from ..api.globe_anchor import anchor_xform_at_path
from ..bindings import ICesiumOmniverseInterface


Expand Down Expand Up @@ -33,7 +34,7 @@ def destroy(self):

def _add_globe_anchor_api(self, payload: PrimSelectionPayload):
for path in payload:
self._cesium_omniverse_interface.add_global_anchor_to_prim(str(path))
anchor_xform_at_path(path)
get_property_window().request_rebuild()

@staticmethod
Expand Down
14 changes: 14 additions & 0 deletions exts/cesium.omniverse/cesium/omniverse/utils/cesium_interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from ..bindings import acquire_cesium_omniverse_interface


class CesiumInterfaceManager:
def __init__(self):
# Acquires the interface. Is a singleton.
self.interface = acquire_cesium_omniverse_interface()

def __enter__(self):
return self.interface

def __exit__(self, exc_type, exc_val, exc_tb):
# We release the interface when we pull down the plugin.
pass
14 changes: 12 additions & 2 deletions include/cesium/omniverse/CesiumOmniverse.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,21 @@ class ICesiumOmniverseInterface {
virtual void creditsStartNextFrame() noexcept = 0;

/**
* @brief Given the provided sdf path (as a charstring), add a global anchor API to it and set it up.
* @brief Given the provided sdf path (as a charstring), add a globe anchor API to it and set it up.
*
* @param path A sdf path in the USD stage provided as a charstring.
*/
virtual void addGlobalAnchorToPrim(const char* path) noexcept = 0;
virtual void addGlobeAnchorToPrim(const char* path) noexcept = 0;

/**
* @brief Given the provided sdf path (as a charstring) and latitude, longitude, and height, add a globe anchor API to it and set it up.
*
* @param path A sdf path in the USD stage provided as a charstring.
* @param latitude The latitude provided as a double.
* @param longitude The longitude provided as a double.
* @param height The height provided as a double.
*/
virtual void addGlobeAnchorToPrim(const char* path, double latitude, double longitude, double height) noexcept = 0;
virtual bool isTracingEnabled() noexcept = 0;
};

Expand Down
4 changes: 3 additions & 1 deletion src/bindings/PythonBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <carb/BindingsPythonUtils.h>
#include <pxr/base/gf/matrix4d.h>
#include <pxr/base/gf/vec4d.h>
#include <pxr/usd/sdf/path.h>

// Needs to go after carb
#include "pyboost11.h"
Expand Down Expand Up @@ -57,7 +58,8 @@ PYBIND11_MODULE(CesiumOmniversePythonBindings, m) {
.def("get_credits", &ICesiumOmniverseInterface::getCredits)
.def("credits_start_next_frame", &ICesiumOmniverseInterface::creditsStartNextFrame)
.def("is_tracing_enabled", &ICesiumOmniverseInterface::isTracingEnabled)
.def("add_global_anchor_to_prim", &ICesiumOmniverseInterface::addGlobalAnchorToPrim);
.def("add_global_anchor_to_prim", py::overload_cast<const char*>(&ICesiumOmniverseInterface::addGlobeAnchorToPrim))
.def("add_global_anchor_to_prim", py::overload_cast<const char*, double, double, double>(&ICesiumOmniverseInterface::addGlobeAnchorToPrim));
// clang-format on

py::class_<CesiumIonSession, std::shared_ptr<CesiumIonSession>>(m, "CesiumIonSession")
Expand Down
1 change: 1 addition & 0 deletions src/core/include/cesium/omniverse/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class Context {
RenderStatistics getRenderStatistics() const;

void addGlobeAnchorToPrim(const pxr::SdfPath& path);
void addGlobeAnchorToPrim(const pxr::SdfPath& path, double latitude, double longitude, double height);

private:
void processPropertyChanged(const ChangedPrim& changedPrim);
Expand Down
29 changes: 28 additions & 1 deletion src/core/src/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,16 @@ void Context::processPrimAdded(const ChangedPrim& changedPrim) {
auto anchorApi = UsdUtil::getCesiumGlobeAnchor(changedPrim.path);
auto origin = UsdUtil::getCartographicOriginForAnchor(changedPrim.path);
assert(origin.has_value());
GeospatialUtil::updateAnchorByUsdTransform(origin.value(), anchorApi);
pxr::GfVec3d coordinates;
anchorApi.GetGeographicCoordinateAttr().Get(&coordinates);

if (coordinates == pxr::GfVec3d{0.0, 0.0, 10.0}) {
// Default geo coordinates. Place based on current USD position.
GeospatialUtil::updateAnchorByUsdTransform(origin.value(), anchorApi);
} else {
// Provided geo coordinates. Place at correct location.
GeospatialUtil::updateAnchorByLatLongHeight(origin.value(), anchorApi);
}
}
}

Expand Down Expand Up @@ -857,4 +866,22 @@ void Context::addGlobeAnchorToPrim(const pxr::SdfPath& path) {
globeAnchor.GetGeoreferenceBindingRel().AddTarget(georeferenceOrigin.GetPath());
}

void Context::addGlobeAnchorToPrim(const pxr::SdfPath& path, double latitude, double longitude, double height) {
if (UsdUtil::isCesiumData(path) || UsdUtil::isCesiumGeoreference(path) || UsdUtil::isCesiumImagery(path) ||
UsdUtil::isCesiumSession(path) || UsdUtil::isCesiumTileset(path)) {
_logger->warn("Cannot attach Globe Anchor to Cesium Tilesets, Imagery, Georeference, Session, or Data prims.");
return;
}

auto prim = UsdUtil::getUsdStage()->GetPrimAtPath(path);
auto globeAnchor = UsdUtil::defineGlobeAnchor(path);

// Until we support multiple georeference points, we should just use the default georeference object.
auto georeferenceOrigin = UsdUtil::getOrCreateCesiumGeoreference();
globeAnchor.GetGeoreferenceBindingRel().AddTarget(georeferenceOrigin.GetPath());

pxr::GfVec3d coordinates{latitude, longitude, height};
globeAnchor.GetGeographicCoordinateAttr().Set(coordinates);
}

} // namespace cesium::omniverse
37 changes: 23 additions & 14 deletions src/core/src/GeospatialUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,28 +102,37 @@ void updateAnchorByUsdTransform(
void updateAnchorByLatLongHeight(
const CesiumGeospatial::Cartographic& origin,
const pxr::CesiumGlobeAnchorAPI& anchorApi) {
std::shared_ptr<OmniGlobeAnchor> globeAnchor;
pxr::GfVec3d usdGeographicCoordinate;
anchorApi.GetGeographicCoordinateAttr().Get(&usdGeographicCoordinate);

std::optional<std::shared_ptr<OmniGlobeAnchor>> maybeGlobeAnchor =
GlobeAnchorRegistry::getInstance().getAnchor(anchorApi.GetPath());
if (maybeGlobeAnchor.has_value()) {
globeAnchor = maybeGlobeAnchor.value();

if (!maybeGlobeAnchor.has_value()) {
CESIUM_LOG_ERROR(
"Anchor does not exist in registry but exists in stage. Path: {}", anchorApi.GetPath().GetString());
auto cachedGeographicCoordinate = globeAnchor->getCachedGeographicCoordinate();

return;
}
double tolerance = 0.0000001;
if (pxr::GfIsClose(usdGeographicCoordinate, cachedGeographicCoordinate, tolerance)) {

std::shared_ptr<OmniGlobeAnchor> globeAnchor = maybeGlobeAnchor.value();

pxr::GfVec3d usdGeographicCoordinate;
anchorApi.GetGeographicCoordinateAttr().Get(&usdGeographicCoordinate);
// Short circuit if we don't need to do an actual update.
return;
}
} else {
// This really isn't ideal, but it's the easiest way to handle this.
auto anchorToFixed = UsdUtil::computeUsdLocalToEcefTransformForPrim(origin, anchorApi.GetPath());
globeAnchor = GlobeAnchorRegistry::getInstance().createAnchor(anchorApi.GetPath(), anchorToFixed);

auto cachedGeographicCoordinate = globeAnchor->getCachedGeographicCoordinate();
// We have to set the ECEF values and then cache them for the rest of the process to work.
auto fixedTransform = UsdUtil::glmToUsdMatrixDecomposed(globeAnchor->getAnchorToFixedTransform());

double tolerance = 0.0000001;
if (pxr::GfIsClose(usdGeographicCoordinate, cachedGeographicCoordinate, tolerance)) {
anchorApi.GetPositionAttr().Set(fixedTransform.position);
anchorApi.GetRotationAttr().Set(
pxr::GfVec3d(UsdUtil::getEulerAnglesFromQuaternion(fixedTransform.orientation)));
anchorApi.GetScaleAttr().Set(pxr::GfVec3d(fixedTransform.scale));

// Short circuit if we don't need to do an actual update.
return;
globeAnchor->updateCachedValues();
}

double usdLatitude = usdGeographicCoordinate[0];
Expand Down
6 changes: 5 additions & 1 deletion src/public/CesiumOmniverse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,14 @@ class CesiumOmniversePlugin final : public ICesiumOmniverseInterface {
return Context::instance().creditsStartNextFrame();
}

void addGlobalAnchorToPrim(const char* path) noexcept override {
void addGlobeAnchorToPrim(const char* path) noexcept override {
return Context::instance().addGlobeAnchorToPrim(pxr::SdfPath(path));
}

void addGlobeAnchorToPrim(const char* path, double latitude, double longitude, double height) noexcept override {
return Context::instance().addGlobeAnchorToPrim(pxr::SdfPath(path), latitude, longitude, height);
}

bool isTracingEnabled() noexcept override {
#if CESIUM_TRACING_ENABLED
return true;
Expand Down

0 comments on commit b5476c5

Please sign in to comment.