diff --git a/examples/viewer.py b/examples/viewer.py index 9db670393e..3a4aca69d7 100644 --- a/examples/viewer.py +++ b/examples/viewer.py @@ -917,10 +917,24 @@ def navmesh_config_and_recompute(self) -> None: self.navmesh_settings.agent_height = self.cfg.agents[self.agent_id].height self.navmesh_settings.agent_radius = self.cfg.agents[self.agent_id].radius self.navmesh_settings.include_static_objects = True + self.navmesh_settings.cell_height = 0.01 + + cached_motion_types = {} + aom = self.sim.get_articulated_object_manager() + for ao in aom.get_objects_by_handle_substring().values(): + cached_motion_types[ao.handle] = ao.motion_type + ao.motion_type = habitat_sim.physics.MotionType.STATIC + self.sim.recompute_navmesh( self.sim.pathfinder, self.navmesh_settings, ) + navmesh_path = self.sim_settings["scene"] + ".navmesh" + self.sim.pathfinder.save_nav_mesh(navmesh_path) + print(f"Saved navmesh to {navmesh_path}") + + for ao in aom.get_objects_by_handle_substring().values(): + ao.motion_type = cached_motion_types[ao.handle] def exit_event(self, event: Application.ExitEvent): """ diff --git a/src/esp/assets/RenderAssetInstanceCreationInfo.h b/src/esp/assets/RenderAssetInstanceCreationInfo.h index 4c35191c8c..419a82b0eb 100644 --- a/src/esp/assets/RenderAssetInstanceCreationInfo.h +++ b/src/esp/assets/RenderAssetInstanceCreationInfo.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -46,6 +47,10 @@ struct RenderAssetInstanceCreationInfo { std::string filepath; // see also AssetInfo::filepath Corrade::Containers::Optional scale; + // NOTE: the following allows for a predefined offset transformation for a + // visual shape from its parent frame. + Corrade::Containers::Optional translation; + Corrade::Containers::Optional rotation; Flags flags; std::string lightSetupKey; int rigId = ID_UNDEFINED; diff --git a/src/esp/assets/ResourceManager.cpp b/src/esp/assets/ResourceManager.cpp index 83b476f7fb..0f2abf7e27 100644 --- a/src/esp/assets/ResourceManager.cpp +++ b/src/esp/assets/ResourceManager.cpp @@ -1663,15 +1663,6 @@ scene::SceneNode* ResourceManager::createRenderAssetInstanceGeneralPrimitive( auto& visNodeCache = userVisNodeCache ? *userVisNodeCache : dummyVisNodeCache; scene::SceneNode& newNode = parent->createChild(); - if (creation.scale) { - // need a new node for scaling because motion state will override scale - // set at the physical node - // perf todo: avoid this if unit scale - newNode.setScaling(*creation.scale); - - // legacy quirky behavior: only add this node to viscache if using scaling - visNodeCache.push_back(&newNode); - } std::vector staticDrawableInfo; @@ -1705,8 +1696,29 @@ scene::SceneNode* ResourceManager::createRenderAssetInstanceGeneralPrimitive( } } + scene::SceneNode* attachTo = &newNode; + if (creation.scale || creation.translation || creation.rotation) { + scene::SceneNode& tform_node = newNode.createChild(); + attachTo = &tform_node; + if (creation.scale) { + // need a new node for scaling because motion state will override scale + // set at the physical node + // perf todo: avoid this if unit scale + tform_node.MagnumObject::setScaling(*creation.scale); + } + // the following represent fixed offsets from the rigid parent frame for + // this visual subtree + if (creation.translation) { + tform_node.MagnumObject::setTranslation(*creation.translation); + } + if (creation.rotation) { + tform_node.MagnumObject::setRotation(*creation.rotation); + } + visNodeCache.push_back(&tform_node); + // legacy quirky behavior: only add this node to viscache if using scaling + } addComponent(meshMetaData, // mesh metadata - newNode, // parent scene node + *attachTo, // parent scene node creation.lightSetupKey, // lightSetup key drawables, // drawable group meshMetaData.root, // mesh transform node diff --git a/src/esp/bindings/SimBindings.cpp b/src/esp/bindings/SimBindings.cpp index 67cf910fc2..c3fee85bfc 100644 --- a/src/esp/bindings/SimBindings.cpp +++ b/src/esp/bindings/SimBindings.cpp @@ -182,6 +182,8 @@ void initRenderInstanceHelperBindings(py::module& m) { .def("add_instance", &RenderInstanceHelper::AddInstance, py::arg("asset_filepath"), py::arg("semantic_id"), py::arg("scale") = Mn::Vector3(1.0, 1.0, 1.0), + py::arg("translation") = Mn::Vector3(0.0, 0.0, 0.0), + py::arg("rotation") = Mn::Quaternion(), "R(Add an instance of a render asset to the scene. The asset can be " "for example a .glb or .obj 3D model file. The instance gets an " "identity pose; change it later using set_world_poses.)") @@ -256,6 +258,9 @@ void initSimBindings(py::module& m) { R"(Use gfx_replay_manager for replay recording and playback.)") .def("seed", &Simulator::seed, "new_seed"_a) .def("reconfigure", &Simulator::reconfigure, "configuration"_a) + .def("load_semantic_scene_descriptor", + &Simulator::loadSemanticSceneDescriptor, + "semantic_scene_descriptor_file"_a) .def("reset", [](Simulator& self) { self.reset(false); }) .def( "close", &Simulator::close, "destroy"_a = true, diff --git a/src/esp/io/JsonEspTypes.h b/src/esp/io/JsonEspTypes.h index 5e4a182ce4..108c2b1761 100644 --- a/src/esp/io/JsonEspTypes.h +++ b/src/esp/io/JsonEspTypes.h @@ -79,6 +79,8 @@ inline JsonGenericValue toJsonValue( JsonGenericValue obj(rapidjson::kObjectType); addMember(obj, "filepath", x.filepath, allocator); addMember(obj, "scale", x.scale, allocator); + addMember(obj, "rotation", x.rotation, allocator); + addMember(obj, "translation", x.translation, allocator); addMember(obj, "isStatic", x.isStatic(), allocator); addMember(obj, "isRGBD", x.isRGBD(), allocator); addMember(obj, "isSemantic", x.isSemantic(), allocator); @@ -92,6 +94,8 @@ inline bool fromJsonValue(const JsonGenericValue& obj, esp::assets::RenderAssetInstanceCreationInfo& x) { readMember(obj, "filepath", x.filepath); readMember(obj, "scale", x.scale); + readMember(obj, "rotation", x.rotation); + readMember(obj, "translation", x.translation); bool isStatic = false; readMember(obj, "isStatic", isStatic); bool isRGBD = false; diff --git a/src/esp/sim/RenderInstanceHelper.cpp b/src/esp/sim/RenderInstanceHelper.cpp index 01744c3769..6e3a548595 100644 --- a/src/esp/sim/RenderInstanceHelper.cpp +++ b/src/esp/sim/RenderInstanceHelper.cpp @@ -20,7 +20,9 @@ RenderInstanceHelper::RenderInstanceHelper(Simulator& sim, int RenderInstanceHelper::AddInstance(const std::string& assetFilepath, int semanticId, - const Magnum::Vector3& scale) { + const Magnum::Vector3& scale, + const Magnum::Vector3& translation, + const Magnum::Quaternion& rotation) { esp::assets::AssetInfo assetInfo; assetInfo.filepath = assetFilepath; assetInfo.forceFlatShading = false; @@ -32,6 +34,8 @@ int RenderInstanceHelper::AddInstance(const std::string& assetFilepath, assets::RenderAssetInstanceCreationInfo creation(assetFilepath, scale, flags, DEFAULT_LIGHTING_KEY); + creation.translation = translation; + creation.rotation = rotation; auto* node = sim_->loadAndCreateRenderAssetInstance(assetInfo, creation); instances_.push_back(node); diff --git a/src/esp/sim/RenderInstanceHelper.h b/src/esp/sim/RenderInstanceHelper.h index 980e41f0df..210e65118f 100644 --- a/src/esp/sim/RenderInstanceHelper.h +++ b/src/esp/sim/RenderInstanceHelper.h @@ -5,6 +5,7 @@ #ifndef ESP_SIM_RENDERINSTANCEHELPER_H_ #define ESP_SIM_RENDERINSTANCEHELPER_H_ +#include #include #include #include @@ -50,12 +51,18 @@ class RenderInstanceHelper { * * @param assetFilepath can be for example a .glb or .obj 3D model file * @param semanticId used for semantic rendering + * @param scale An optional local scaling vector applied to this render + * instance. + * @param translation An optional local translation vector offset applied to + * this render instance. + * @param rotation An optional local rotation vector offset applied to this + * render instance. */ int AddInstance(const std::string& assetFilepath, int semanticId, - const Magnum::Vector3& scale = Magnum::Vector3(1.0, - 1.0, - 1.0)); + const Magnum::Vector3& scale = Magnum::Vector3(1.0, 1.0, 1.0), + const Magnum::Vector3& translation = Magnum::Vector3(0), + const Magnum::Quaternion& rotation = Magnum::Quaternion()); /** * @brief Remove all instances from the scene. diff --git a/src/esp/sim/Simulator.cpp b/src/esp/sim/Simulator.cpp index 31c935e6a2..412de0a435 100644 --- a/src/esp/sim/Simulator.cpp +++ b/src/esp/sim/Simulator.cpp @@ -225,6 +225,23 @@ void Simulator::reconfigure(const SimulatorConfiguration& cfg) { } // Simulator::reconfigure +void Simulator::loadSemanticSceneDescriptor( + const std::string& semSceneFilename) { + // first check if the semantic attributes is already loaded + std::shared_ptr semanticAttr = + (semSceneFilename != "") + ? metadataMediator_->getSemanticAttributesManager() + ->getFirstMatchingObjectCopyByHandle(semSceneFilename) + : nullptr; + + if (semanticAttr == nullptr) { + semanticAttr = metadataMediator_->getSemanticAttributesManager() + ->createObjectFromJSONFile(semSceneFilename, true); + } + + resourceManager_->loadSemanticScene(semanticAttr, semSceneFilename); +} + bool Simulator::createSceneInstance(const std::string& activeSceneName) { getRenderGLContext(); diff --git a/src/esp/sim/Simulator.h b/src/esp/sim/Simulator.h index 9beec97d77..1820022938 100644 --- a/src/esp/sim/Simulator.h +++ b/src/esp/sim/Simulator.h @@ -67,6 +67,13 @@ class Simulator { void reconfigure(const SimulatorConfiguration& cfg); + /** + * @brief Allows side-loading semantic scene metadata from a semantic json + * without loading the connected scene instance. + * + */ + void loadSemanticSceneDescriptor(const std::string& semSceneFilename); + /** * @brief Reset the simulation state including the state of all physics * objects and the default light setup.