Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the Cesium Omniverse Python API with a function to create anchors #496

Merged
merged 2 commits into from
Oct 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to go through the old codebase and make sure we're grabbing the singleton elsewhere as a different quick PR?

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