From 0347de78cd89dffe9eb04bf9300df3d443fba690 Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Wed, 23 Sep 2020 14:29:36 -0700 Subject: [PATCH 01/13] Add unversioned symlinks for engine plugins Signed-off-by: John Shepherd --- CMakeLists.txt | 5 +++++ ogre/src/CMakeLists.txt | 16 +++++++++++++++- ogre2/src/CMakeLists.txt | 17 ++++++++++++++++- optix/src/CMakeLists.txt | 16 +++++++++++++++- 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 223871957..88b2f1187 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,6 +87,11 @@ if (OGRE2_FOUND) set(HAVE_OGRE2 TRUE) endif() +# Plugin install dirs +set(IGNITION_RENDERING_ENGINE_INSTALL_DIR + ${CMAKE_INSTALL_PREFIX}/${IGN_LIB_INSTALL_DIR}/ign-${IGN_DESIGNATION}-${PROJECT_VERSION_MAJOR}/engine-plugins +) + #-------------------------------------- # Find dependencies that we ignore for Visual Studio if(NOT MSVC) diff --git a/ogre/src/CMakeLists.txt b/ogre/src/CMakeLists.txt index 6814a17d6..026a66c42 100644 --- a/ogre/src/CMakeLists.txt +++ b/ogre/src/CMakeLists.txt @@ -2,7 +2,9 @@ # "gtest_sources" variable. ign_get_libsources_and_unittests(sources gtest_sources) -ign_add_component(ogre SOURCES ${sources} GET_TARGET_NAME ogre_target) +set(engine_name "ogre") + +ign_add_component(${engine_name} SOURCES ${sources} GET_TARGET_NAME ogre_target) if(OGRE_VERSION VERSION_LESS 1.10.3) add_definitions(-DOGRE_VERSION_LT_1_10_3) @@ -35,6 +37,9 @@ target_link_libraries(${ogre_target} # Build the unit tests ign_build_tests(TYPE UNIT SOURCES ${gtest_sources} LIB_DEPS ${ogre_target}) +# Note that plugins are currently being installed in 2 places: /lib and the engine-plugins dir +install(TARGETS ${ogre_target} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) + if(WIN32) # tests needs .dll in the same directory add_custom_command(TARGET ${ogre_target} POST_BUILD @@ -42,5 +47,14 @@ if(WIN32) $ ${CMAKE_CURRENT_BINARY_DIR}) endif() +set (versioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) +set (unversioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_NO_VERSION_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) + +if (WIN32) + # create_symlink requires cmake 3.13 on windows + cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +endif() +EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) +INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) add_subdirectory(media) diff --git a/ogre2/src/CMakeLists.txt b/ogre2/src/CMakeLists.txt index 5db050db2..ff77817b1 100644 --- a/ogre2/src/CMakeLists.txt +++ b/ogre2/src/CMakeLists.txt @@ -2,7 +2,9 @@ # "gtest_sources" variable. ign_get_libsources_and_unittests(sources gtest_sources) -ign_add_component(ogre2 SOURCES ${sources} GET_TARGET_NAME ogre2_target) +set(engine_name "ogre2") + +ign_add_component(${engine_name} SOURCES ${sources} GET_TARGET_NAME ogre2_target) find_package(OpenGL) @@ -22,6 +24,19 @@ target_link_libraries(${ogre2_target} ${OPENGL_LIBRARIES} IgnOGRE2::IgnOGRE2) +set (versioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) +set (unversioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_NO_VERSION_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) + +# Note that plugins are currently being installed in 2 places: /lib and the engine-plugins dir +install(TARGETS ${ogre2_target} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) + +if (WIN32) + # create_symlink requires cmake 3.13 on windows + cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +endif() +EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) +INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) + # Build the unit tests ign_build_tests(TYPE UNIT SOURCES ${gtest_sources} LIB_DEPS ${ogre2_target}) diff --git a/optix/src/CMakeLists.txt b/optix/src/CMakeLists.txt index 33a8e646f..a765e83a1 100644 --- a/optix/src/CMakeLists.txt +++ b/optix/src/CMakeLists.txt @@ -9,7 +9,9 @@ link_directories(${CUDA_LIBRARY_DIRS}) include_directories("${PROJECT_SOURCE_DIR}/optix/include") include_directories(SYSTEM ${OptiX_INCLUDE_DIRS}) -ign_add_component(optix SOURCES ${sources} GET_TARGET_NAME optix_target) +set(engine_name optix) + +ign_add_component(${engine_name} SOURCES ${sources} GET_TARGET_NAME optix_target) set(cuda_sources OptixBox.cu @@ -43,6 +45,18 @@ target_link_libraries(${optix_target} # Build the unit tests ign_build_tests(TYPE UNIT SOURCES ${gtest_sources}) +# Note that plugins are currently being installed in 2 places: /lib and the engine-plugins dir +install(TARGETS ${optix_target} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) + +set (versioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) +set (unversioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_NO_VERSION_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) + +if (WIN32) + # create_symlink requires cmake 3.13 on windows + cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +endif() +EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) +INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) if("${CUDA_VERSION}" VERSION_LESS "9") set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-gencode arch=compute_20,code=sm_20) From 876f706d98290e4380d20cfe1ff99edbeeadb8b6 Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Wed, 23 Sep 2020 18:44:38 -0700 Subject: [PATCH 02/13] Add init attempt at custom render engine Signed-off-by: John Shepherd --- src/RenderEngineManager.cc | 107 ++++++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 18 deletions(-) diff --git a/src/RenderEngineManager.cc b/src/RenderEngineManager.cc index 4720691da..4a2737b1b 100644 --- a/src/RenderEngineManager.cc +++ b/src/RenderEngineManager.cc @@ -28,6 +28,13 @@ #include "ignition/rendering/RenderEngineManager.hh" #include "ignition/rendering/RenderEnginePlugin.hh" +/// \brief Holds information about an engine +struct EngineInfo +{ + std::string name; + ignition::rendering::RenderEngine *engine; +}; + /// \brief Private implementation of the RenderEngineManager class class ignition::rendering::RenderEngineManagerPrivate { @@ -40,7 +47,7 @@ class ignition::rendering::RenderEngineManagerPrivate /// \brief Get a pointer to the render engine from an EngineMap iterator /// \param[in] _iter EngineMap iterator /// \param[in] _path Another search path for rendering engine plugin. - public: RenderEngine *Engine(EngineIter _iter, + public: RenderEngine *Engine(EngineInfo _info, const std::map &_params, const std::string &_path); @@ -75,8 +82,8 @@ class ignition::rendering::RenderEngineManagerPrivate /// \brief Engines that have been registered public: EngineMap engines; - /// \brief A map of default engine name to its plugin library name - public: std::map defaultEngines; + /// \brief A map of engine names to their plugin library name + public: std::map engineLibraries; /// \brief A map of loaded engine plugins to its plugin name public: std::map enginePlugins; @@ -84,6 +91,8 @@ class ignition::rendering::RenderEngineManagerPrivate /// \brief Plugin loader for managing render engine plugin libraries public: ignition::plugin::Loader pluginLoader; + public: std::string pluginPathEnv = "IGN_GAZEBO_RENDER_ENGINE_PATH"; + /// \brief Mutex to protect the engines map. public: std::recursive_mutex enginesMutex; }; @@ -151,17 +160,34 @@ RenderEngine *RenderEngineManager::Engine(const std::string &_name, const std::map &_params, const std::string &_path) { + EngineInfo info{_name, nullptr}; + ignwarn << "name before is " << info.name << std::endl; + ignwarn << "engine count is " << this->EngineCount() << std::endl; + std::lock_guard lock(this->dataPtr->enginesMutex); // check in the list of available engines - auto iter = this->dataPtr->engines.find(_name); + //auto iter = this->dataPtr->engines.find(_name); - if (iter == this->dataPtr->engines.end()) + //if (iter == this->dataPtr->engines.end()) + // Check in the list of registered engines + auto iter = this->dataPtr->engines.find(_name); + if (iter != this->dataPtr->engines.end()) { - ignerr << "No render-engine registered with name: " << _name << std::endl; - return nullptr; + //ignerr << "No render-engine registered with name: " << _name << std::endl; + //return nullptr; + info.name = iter->first; + info.engine = iter->second; + ignwarn << "Found engine" << std::endl; + ignwarn << "default engine name is " << this->dataPtr->engineLibraries[info.name] << std::endl; + } + else + { + } - return this->dataPtr->Engine(iter, _params, _path); + ignwarn << "name is " << info.name << std::endl; + //return this->dataPtr->Engine(iter, _params, _path); + return this->dataPtr->Engine(info, _params, _path); } ////////////////////////////////////////////////// @@ -178,13 +204,14 @@ RenderEngine *RenderEngineManager::EngineAt(unsigned int _index, std::lock_guard lock(this->dataPtr->enginesMutex); auto iter = this->dataPtr->engines.begin(); std::advance(iter, _index); - return this->dataPtr->Engine(iter, _params, _path); + return this->dataPtr->Engine({iter->first, iter->second}, _params, _path); } ////////////////////////////////////////////////// bool RenderEngineManager::UnloadEngine(const std::string &_name) { std::lock_guard lock(this->dataPtr->enginesMutex); + // check in the list of available engines auto iter = this->dataPtr->engines.find(_name); @@ -231,6 +258,7 @@ void RenderEngineManager::RegisterEngine(const std::string &_name, } std::lock_guard lock(this->dataPtr->enginesMutex); + std::cout << "Registering engine " << _name << std::endl; this->dataPtr->engines[_name] = _engine; } @@ -284,32 +312,72 @@ void RenderEngineManager::UnregisterEngineAt(unsigned int _index) ////////////////////////////////////////////////// // RenderEngineManagerPrivate ////////////////////////////////////////////////// -RenderEngine *RenderEngineManagerPrivate::Engine(EngineIter _iter, +RenderEngine *RenderEngineManagerPrivate::Engine(EngineInfo _info, const std::map &_params, const std::string &_path) { - RenderEngine *engine = _iter->second; + RenderEngine *engine = _info.engine; if (!engine) { // check if it's an engine in the list of default engines provided by // ign-rendering. If so, load it - auto defaultIt = this->defaultEngines.find(_iter->first); - if (defaultIt != this->defaultEngines.end()) + //auto defaultIt = this->engineLibraries.find(_iter->first); + auto defaultIt = this->engineLibraries.find(_info.name); + if (defaultIt != this->engineLibraries.end()) { std::string libName = defaultIt->second; if (this->LoadEnginePlugin(libName, _path)) { std::lock_guard lock(this->enginesMutex); - auto engineIt = this->engines.find(_iter->first); + //auto engineIt = this->engines.find(_iter->first); + auto engineIt = this->engines.find(_info.name); if (engineIt != this->engines.end()) engine = engineIt->second; } } + else + { + ignwarn << "Searching other paths" << std::endl; + std::string libName = _info.name; + if (this->LoadEnginePlugin(libName, _path)) + { + ignwarn << "Found engine" << std::endl; + std::lock_guard lock(this->enginesMutex); + //auto engineIt = this->engines.find(_iter->first); + ignwarn << "name is " << _info.name << std::endl; + ignwarn << "Searching for name " << this->engineLibraries[_info.name] << std::endl; + auto engineIt = this->engines.find(this->engineLibraries[_info.name]); + if (engineIt != this->engines.end()) + engine = engineIt->second; + else + ignwarn << "engine not found in engine map " << std::endl; + } + } + } + // Otherwise, try to load as a shared library + else + { + // TODO + // TODO search env var IGN_GAZEBO_RENDER_ENGINE_PATH + ignwarn << "Searching other paths" << std::endl; + std::string libName = _info.name; + if (this->LoadEnginePlugin(libName, _path)) + { + // Register engine? + ignwarn << "Found engine" << std::endl; + } } if (!engine) + { + ignwarn << "engine is null" << std::endl; return nullptr; + } + else + { + ignwarn << "engine is not null" << std::endl; + } if (!engine->IsInitialized()) { @@ -348,19 +416,19 @@ void RenderEngineManagerPrivate::RegisterDefaultEngines() std::lock_guard lock(this->enginesMutex); #if HAVE_OGRE engineName = "ogre"; - this->defaultEngines[engineName] = libName + engineName; + this->engineLibraries[engineName] = libName + engineName; if (this->engines.find(engineName) == this->engines.end()) this->engines[engineName] = nullptr; #endif #if HAVE_OGRE2 engineName = "ogre2"; - this->defaultEngines[engineName] = libName + engineName; + this->engineLibraries[engineName] = libName + engineName; if (this->engines.find(engineName) == this->engines.end()) this->engines[engineName] = nullptr; #endif #if HAVE_OPTIX engineName = "optix"; - this->defaultEngines[engineName] = libName + engineName; + this->engineLibraries[engineName] = libName + engineName; if (this->engines.find(engineName) == this->engines.end()) this->engines[engineName] = nullptr; #endif @@ -374,7 +442,8 @@ bool RenderEngineManagerPrivate::LoadEnginePlugin( ignition::common::SystemPaths systemPaths; - // Add default install folder. + // Add env var path and default install folder. + systemPaths.SetPluginPathEnv(std::string(this->pluginPathEnv)); systemPaths.AddPluginPaths(std::string(IGN_RENDERING_PLUGIN_PATH)); // Add extra search path. systemPaths.AddPluginPaths(_path); @@ -430,10 +499,12 @@ bool RenderEngineManagerPrivate::LoadEnginePlugin( { std::lock_guard lock(this->enginesMutex); this->engines[engineName] = plugin->Engine(); + ignwarn << "Registering engine under name " << engineName << std::endl; } // store engine plugin data so plugin can be unloaded later this->enginePlugins[engineName] = pluginName; + this->engineLibraries[engineName] = _filename; return true; } From 970c09cd5c03ded79a89adc0722455e56f07b759 Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Thu, 24 Sep 2020 12:37:22 -0700 Subject: [PATCH 03/13] Refactor Signed-off-by: John Shepherd --- include/ignition/rendering/config.hh.in | 2 + src/RenderEngineManager.cc | 125 ++++++++++-------------- 2 files changed, 51 insertions(+), 76 deletions(-) diff --git a/include/ignition/rendering/config.hh.in b/include/ignition/rendering/config.hh.in index d554aa9c0..fd052ebf6 100644 --- a/include/ignition/rendering/config.hh.in +++ b/include/ignition/rendering/config.hh.in @@ -14,6 +14,8 @@ #define IGN_RENDERING_RESOURCE_PATH "${IGN_RENDERING_RESOURCE_PATH}" +#define IGNITION_RENDERING_ENGINE_INSTALL_DIR "${IGNITION_RENDERING_ENGINE_INSTALL_DIR}" + #cmakedefine BUILD_TYPE_PROFILE 1 #cmakedefine BUILD_TYPE_DEBUG 1 #cmakedefine BUILD_TYPE_RELEASE 1 diff --git a/src/RenderEngineManager.cc b/src/RenderEngineManager.cc index 4a2737b1b..1b82698d1 100644 --- a/src/RenderEngineManager.cc +++ b/src/RenderEngineManager.cc @@ -82,8 +82,8 @@ class ignition::rendering::RenderEngineManagerPrivate /// \brief Engines that have been registered public: EngineMap engines; - /// \brief A map of engine names to their plugin library name - public: std::map engineLibraries; + /// \brief A map of default engine library names to their plugin names. + public: std::map defaultEngines; /// \brief A map of loaded engine plugins to its plugin name public: std::map enginePlugins; @@ -161,31 +161,28 @@ RenderEngine *RenderEngineManager::Engine(const std::string &_name, const std::string &_path) { EngineInfo info{_name, nullptr}; - ignwarn << "name before is " << info.name << std::endl; - ignwarn << "engine count is " << this->EngineCount() << std::endl; - + ignwarn << "iin engine\n" << std::endl; std::lock_guard lock(this->dataPtr->enginesMutex); // check in the list of available engines //auto iter = this->dataPtr->engines.find(_name); - //if (iter == this->dataPtr->engines.end()) // Check in the list of registered engines auto iter = this->dataPtr->engines.find(_name); + for (auto &elem : this->dataPtr->engines) + ignwarn << elem.first << std::endl; if (iter != this->dataPtr->engines.end()) { - //ignerr << "No render-engine registered with name: " << _name << std::endl; - //return nullptr; info.name = iter->first; info.engine = iter->second; - ignwarn << "Found engine" << std::endl; - ignwarn << "default engine name is " << this->dataPtr->engineLibraries[info.name] << std::endl; + ignwarn << "Render-engine registered with name: " << info.name << std::endl; + if (!info.engine) + ignwarn << "engine is null" << std::endl; } else { - + ignwarn << "Did not find it" << std::endl; } - ignwarn << "name is " << info.name << std::endl; //return this->dataPtr->Engine(iter, _params, _path); return this->dataPtr->Engine(info, _params, _path); } @@ -211,7 +208,6 @@ RenderEngine *RenderEngineManager::EngineAt(unsigned int _index, bool RenderEngineManager::UnloadEngine(const std::string &_name) { std::lock_guard lock(this->dataPtr->enginesMutex); - // check in the list of available engines auto iter = this->dataPtr->engines.find(_name); @@ -258,7 +254,7 @@ void RenderEngineManager::RegisterEngine(const std::string &_name, } std::lock_guard lock(this->dataPtr->enginesMutex); - std::cout << "Registering engine " << _name << std::endl; + ignwarn << "Registering " << _name << std::endl; this->dataPtr->engines[_name] = _engine; } @@ -322,62 +318,30 @@ RenderEngine *RenderEngineManagerPrivate::Engine(EngineInfo _info, { // check if it's an engine in the list of default engines provided by // ign-rendering. If so, load it - //auto defaultIt = this->engineLibraries.find(_iter->first); - auto defaultIt = this->engineLibraries.find(_info.name); - if (defaultIt != this->engineLibraries.end()) - { - std::string libName = defaultIt->second; - if (this->LoadEnginePlugin(libName, _path)) - { - std::lock_guard lock(this->enginesMutex); - //auto engineIt = this->engines.find(_iter->first); - auto engineIt = this->engines.find(_info.name); - if (engineIt != this->engines.end()) - engine = engineIt->second; - } - } - else + + ignwarn << "name is " << _info.name << std::endl; + std::string libName = _info.name; + auto defaultIt = this->defaultEngines.find(_info.name); + if (defaultIt != this->defaultEngines.end()) { - ignwarn << "Searching other paths" << std::endl; - std::string libName = _info.name; - if (this->LoadEnginePlugin(libName, _path)) - { - ignwarn << "Found engine" << std::endl; - std::lock_guard lock(this->enginesMutex); - //auto engineIt = this->engines.find(_iter->first); - ignwarn << "name is " << _info.name << std::endl; - ignwarn << "Searching for name " << this->engineLibraries[_info.name] << std::endl; - auto engineIt = this->engines.find(this->engineLibraries[_info.name]); - if (engineIt != this->engines.end()) - engine = engineIt->second; - else - ignwarn << "engine not found in engine map " << std::endl; - } + libName = defaultIt->second; } - } - // Otherwise, try to load as a shared library - else - { - // TODO - // TODO search env var IGN_GAZEBO_RENDER_ENGINE_PATH - ignwarn << "Searching other paths" << std::endl; - std::string libName = _info.name; + + // Check regular engine map if (this->LoadEnginePlugin(libName, _path)) { - // Register engine? - ignwarn << "Found engine" << std::endl; + std::lock_guard lock(this->enginesMutex); + auto engineIt = this->engines.find(libName); + if (engineIt != this->engines.end()) + engine = engineIt->second; + } + else{ + ignwarn << "Failed to load engine plugin" << std::endl; } } if (!engine) - { - ignwarn << "engine is null" << std::endl; return nullptr; - } - else - { - ignwarn << "engine is not null" << std::endl; - } if (!engine->IsInitialized()) { @@ -407,8 +371,9 @@ void RenderEngineManagerPrivate::RegisterDefaultEngines() // TODO(anyone): Find a cleaner way to get the default engine library name // cppcheck-suppress unreadVariable - std::string libName = "ignition-rendering" + - std::to_string(IGNITION_RENDERING_MAJOR_VERSION) + "-"; + //std::string libName = "ignition-rendering" + + // std::to_string(IGNITION_RENDERING_MAJOR_VERSION) + "-"; + std::string libName = "ignition-rendering-"; // cppcheck-suppress unusedVariable std::string engineName; @@ -416,21 +381,28 @@ void RenderEngineManagerPrivate::RegisterDefaultEngines() std::lock_guard lock(this->enginesMutex); #if HAVE_OGRE engineName = "ogre"; - this->engineLibraries[engineName] = libName + engineName; - if (this->engines.find(engineName) == this->engines.end()) - this->engines[engineName] = nullptr; + this->defaultEngines[engineName] = libName + engineName; + if (this->engines.find(libName + engineName) == this->engines.end()) + this->engines[libName + engineName] = nullptr; + //this->defaultEngines[engineName] = libName + engineName; + //if (this->engines.find(engineName) == this->engines.end()) + // this->engines[engineName] = nullptr; #endif #if HAVE_OGRE2 engineName = "ogre2"; - this->engineLibraries[engineName] = libName + engineName; - if (this->engines.find(engineName) == this->engines.end()) - this->engines[engineName] = nullptr; + //this->defaultEngines[engineName] = libName + engineName; + this->defaultEngines[engineName] = libName + engineName; + if (this->engines.find(libName + engineName) == this->engines.end()) + this->engines[libName + engineName] = nullptr; #endif #if HAVE_OPTIX engineName = "optix"; - this->engineLibraries[engineName] = libName + engineName; - if (this->engines.find(engineName) == this->engines.end()) - this->engines[engineName] = nullptr; + this->defaultEngines[engineName] = libName + engineName; + if (this->engines.find(libName + engineName) == this->engines.end()) + this->engines[libName + engineName] = nullptr; + //this->defaultEngines[engineName] = libName + engineName; + //if (this->engines.find(engineName) == this->engines.end()) + // this->engines[engineName] = nullptr; #endif } @@ -442,9 +414,11 @@ bool RenderEngineManagerPrivate::LoadEnginePlugin( ignition::common::SystemPaths systemPaths; - // Add env var path and default install folder. + // Add default install folder. + ignwarn << "ign rendering plugin path is " << IGN_RENDERING_PLUGIN_PATH << std::endl; systemPaths.SetPluginPathEnv(std::string(this->pluginPathEnv)); systemPaths.AddPluginPaths(std::string(IGN_RENDERING_PLUGIN_PATH)); + systemPaths.AddPluginPaths({IGNITION_RENDERING_ENGINE_INSTALL_DIR}); // Add extra search path. systemPaths.AddPluginPaths(_path); @@ -498,13 +472,12 @@ bool RenderEngineManagerPrivate::LoadEnginePlugin( std::string engineName = plugin->Name(); { std::lock_guard lock(this->enginesMutex); - this->engines[engineName] = plugin->Engine(); - ignwarn << "Registering engine under name " << engineName << std::endl; + this->engines[_filename] = plugin->Engine(); + ignwarn << "Adding to engine map: " << _filename << std::endl; } // store engine plugin data so plugin can be unloaded later this->enginePlugins[engineName] = pluginName; - this->engineLibraries[engineName] = _filename; return true; } From 248a4840c61f53fda63b18a39dca6c6316d74f83 Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Thu, 24 Sep 2020 12:51:12 -0700 Subject: [PATCH 04/13] Clean up Signed-off-by: John Shepherd --- src/RenderEngineManager.cc | 61 ++++++++++---------------------------- 1 file changed, 16 insertions(+), 45 deletions(-) diff --git a/src/RenderEngineManager.cc b/src/RenderEngineManager.cc index 1b82698d1..6e1e7aeca 100644 --- a/src/RenderEngineManager.cc +++ b/src/RenderEngineManager.cc @@ -35,16 +35,16 @@ struct EngineInfo ignition::rendering::RenderEngine *engine; }; -/// \brief Private implementation of the RenderEngineManager class +/// \brief Private implementation of the RenderEngineManager class. class ignition::rendering::RenderEngineManagerPrivate { - /// \brief EngineMap that maps engine name to an engine pointer + /// \brief EngineMap that maps engine name to an engine pointer. typedef std::map EngineMap; - /// \brief EngineMap iterator + /// \brief EngineMap iterator. typedef EngineMap::iterator EngineIter; - /// \brief Get a pointer to the render engine from an EngineMap iterator + /// \brief Get a pointer to the render engine from an EngineMap iterator. /// \param[in] _iter EngineMap iterator /// \param[in] _path Another search path for rendering engine plugin. public: RenderEngine *Engine(EngineInfo _info, @@ -67,7 +67,7 @@ class ignition::rendering::RenderEngineManagerPrivate /// \param[in] _iter EngineMap iterator public: void UnregisterEngine(EngineIter _iter); - /// \brief Load a render engine plugin + /// \brief Load a render engine plugin. /// \param[in] _filename Filename of plugin shared library /// \param[in] _path Another search path for rendering engine plugin. /// \return True if the plugin is loaded successfully @@ -85,12 +85,13 @@ class ignition::rendering::RenderEngineManagerPrivate /// \brief A map of default engine library names to their plugin names. public: std::map defaultEngines; - /// \brief A map of loaded engine plugins to its plugin name + /// \brief A map of loaded engine plugins to its plugin name. public: std::map enginePlugins; - /// \brief Plugin loader for managing render engine plugin libraries + /// \brief Plugin loader for managing render engine plugin libraries. public: ignition::plugin::Loader pluginLoader; + /// \brief Environment variable which holds paths to look for engine plugins. public: std::string pluginPathEnv = "IGN_GAZEBO_RENDER_ENGINE_PATH"; /// \brief Mutex to protect the engines map. @@ -161,29 +162,17 @@ RenderEngine *RenderEngineManager::Engine(const std::string &_name, const std::string &_path) { EngineInfo info{_name, nullptr}; - ignwarn << "iin engine\n" << std::endl; std::lock_guard lock(this->dataPtr->enginesMutex); // check in the list of available engines - //auto iter = this->dataPtr->engines.find(_name); // Check in the list of registered engines auto iter = this->dataPtr->engines.find(_name); - for (auto &elem : this->dataPtr->engines) - ignwarn << elem.first << std::endl; if (iter != this->dataPtr->engines.end()) { info.name = iter->first; info.engine = iter->second; - ignwarn << "Render-engine registered with name: " << info.name << std::endl; - if (!info.engine) - ignwarn << "engine is null" << std::endl; - } - else - { - ignwarn << "Did not find it" << std::endl; } - //return this->dataPtr->Engine(iter, _params, _path); return this->dataPtr->Engine(info, _params, _path); } @@ -254,7 +243,6 @@ void RenderEngineManager::RegisterEngine(const std::string &_name, } std::lock_guard lock(this->dataPtr->enginesMutex); - ignwarn << "Registering " << _name << std::endl; this->dataPtr->engines[_name] = _engine; } @@ -316,18 +304,15 @@ RenderEngine *RenderEngineManagerPrivate::Engine(EngineInfo _info, if (!engine) { - // check if it's an engine in the list of default engines provided by - // ign-rendering. If so, load it - - ignwarn << "name is " << _info.name << std::endl; std::string libName = _info.name; + + // Check if the provided name is a name of a default engine, if so, + // translate the name to the shared library name auto defaultIt = this->defaultEngines.find(_info.name); if (defaultIt != this->defaultEngines.end()) - { libName = defaultIt->second; - } - - // Check regular engine map + + // Load the engine plugin if (this->LoadEnginePlugin(libName, _path)) { std::lock_guard lock(this->enginesMutex); @@ -335,9 +320,6 @@ RenderEngine *RenderEngineManagerPrivate::Engine(EngineInfo _info, if (engineIt != this->engines.end()) engine = engineIt->second; } - else{ - ignwarn << "Failed to load engine plugin" << std::endl; - } } if (!engine) @@ -371,8 +353,6 @@ void RenderEngineManagerPrivate::RegisterDefaultEngines() // TODO(anyone): Find a cleaner way to get the default engine library name // cppcheck-suppress unreadVariable - //std::string libName = "ignition-rendering" + - // std::to_string(IGNITION_RENDERING_MAJOR_VERSION) + "-"; std::string libName = "ignition-rendering-"; // cppcheck-suppress unusedVariable @@ -384,13 +364,9 @@ void RenderEngineManagerPrivate::RegisterDefaultEngines() this->defaultEngines[engineName] = libName + engineName; if (this->engines.find(libName + engineName) == this->engines.end()) this->engines[libName + engineName] = nullptr; - //this->defaultEngines[engineName] = libName + engineName; - //if (this->engines.find(engineName) == this->engines.end()) - // this->engines[engineName] = nullptr; #endif #if HAVE_OGRE2 engineName = "ogre2"; - //this->defaultEngines[engineName] = libName + engineName; this->defaultEngines[engineName] = libName + engineName; if (this->engines.find(libName + engineName) == this->engines.end()) this->engines[libName + engineName] = nullptr; @@ -400,9 +376,6 @@ void RenderEngineManagerPrivate::RegisterDefaultEngines() this->defaultEngines[engineName] = libName + engineName; if (this->engines.find(libName + engineName) == this->engines.end()) this->engines[libName + engineName] = nullptr; - //this->defaultEngines[engineName] = libName + engineName; - //if (this->engines.find(engineName) == this->engines.end()) - // this->engines[engineName] = nullptr; #endif } @@ -415,10 +388,10 @@ bool RenderEngineManagerPrivate::LoadEnginePlugin( ignition::common::SystemPaths systemPaths; // Add default install folder. - ignwarn << "ign rendering plugin path is " << IGN_RENDERING_PLUGIN_PATH << std::endl; systemPaths.SetPluginPathEnv(std::string(this->pluginPathEnv)); systemPaths.AddPluginPaths(std::string(IGN_RENDERING_PLUGIN_PATH)); systemPaths.AddPluginPaths({IGNITION_RENDERING_ENGINE_INSTALL_DIR}); + // Add extra search path. systemPaths.AddPluginPaths(_path); @@ -468,16 +441,14 @@ bool RenderEngineManagerPrivate::LoadEnginePlugin( return false; } - // this triggers the engine to be instantiated - std::string engineName = plugin->Name(); + // This triggers the engine to be instantiated { std::lock_guard lock(this->enginesMutex); this->engines[_filename] = plugin->Engine(); - ignwarn << "Adding to engine map: " << _filename << std::endl; } // store engine plugin data so plugin can be unloaded later - this->enginePlugins[engineName] = pluginName; + this->enginePlugins[_filename] = pluginName; return true; } From fb2db1bd6179da42724a9736f67063eb5cc5603e Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Wed, 30 Sep 2020 18:18:29 -0700 Subject: [PATCH 05/13] Add init attempt Signed-off-by: John Shepherd --- examples/hello_world_plugin/CMakeLists.txt | 20 +++++ .../hello_world_plugin/HelloWorldPlugin.cc | 84 +++++++++++++++++++ examples/hello_world_plugin/README.md | 28 +++++++ 3 files changed, 132 insertions(+) create mode 100644 examples/hello_world_plugin/CMakeLists.txt create mode 100644 examples/hello_world_plugin/HelloWorldPlugin.cc create mode 100644 examples/hello_world_plugin/README.md diff --git a/examples/hello_world_plugin/CMakeLists.txt b/examples/hello_world_plugin/CMakeLists.txt new file mode 100644 index 000000000..d95c8b796 --- /dev/null +++ b/examples/hello_world_plugin/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.5 FATAL_ERROR) + +set(IGN_PLUGIN_VER 1) +set(IGN_COMMON_VER 3) +#find_package(ignition-plugin${IGN_PLUGIN_VER} 1.1 REQUIRED COMPONENTS all) + +#set(IGN_PHYSICS_VER 3) +#find_package(ignition-physics${IGN_PHYSICS_VER} REQUIRED) + +find_package(ignition-rendering3 REQUIRED) +find_package(ignition-plugin1 REQUIRED COMPONENTS all) + +add_library(HelloWorldPlugin SHARED HelloWorldPlugin.cc) +target_link_libraries(HelloWorldPlugin + PUBLIC + ${IGNITION-RENDERING_LIBRARIES} + ${ignition-common${IGN_COMMON_VER}_LIBRARIES} + PRIVATE + ignition-plugin${IGN_PLUGIN_VER}::register +) diff --git a/examples/hello_world_plugin/HelloWorldPlugin.cc b/examples/hello_world_plugin/HelloWorldPlugin.cc new file mode 100644 index 000000000..e47dbbdee --- /dev/null +++ b/examples/hello_world_plugin/HelloWorldPlugin.cc @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2020 Open Source Robotics Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include "ignition/rendering/RenderEnginePlugin.hh" +#include "ignition/rendering/base/BaseRenderEngine.hh" +#include "ignition/rendering/base/BaseRenderTypes.hh" + +namespace mock +{ + class HelloWorldRenderEngine : + public virtual ignition::rendering::BaseRenderEngine, + public ignition::common::SingletonT + { + // Documentation Inherited. + public: virtual bool IsEnabled() const override + { + return true; + } + + // Documentation Inherited. + public: virtual std::string Name() const override + { + return "test2"; + } + + protected: virtual bool LoadImpl(const std::map &_params) override + { + return true; + } + + protected: virtual bool InitImpl() override + { + return true; + } + + protected: virtual ignition::rendering::SceneStorePtr Scenes() const override + { + return nullptr; + } + + protected: virtual ignition::rendering::ScenePtr CreateSceneImpl(unsigned int _id, + const std::string &_name) override + { + return nullptr; + } + + private: friend class ignition::common::SingletonT; + }; + + class HelloWorldPlugin : + public ignition::rendering::RenderEnginePlugin + { + public: std::string Name() const + { + return "test"; + } + public: ignition::rendering::RenderEngine *Engine() const + { + return HelloWorldRenderEngine::Instance(); + } + }; +} + +// Register this plugin +IGNITION_ADD_PLUGIN(mock::HelloWorldPlugin, + ignition::rendering::RenderEnginePlugin) diff --git a/examples/hello_world_plugin/README.md b/examples/hello_world_plugin/README.md new file mode 100644 index 000000000..64c2b6317 --- /dev/null +++ b/examples/hello_world_plugin/README.md @@ -0,0 +1,28 @@ +# Engine plugin + +This example shows how to create a plugin that integrates a rendering engine with +Ignition Rendering. + +## Build + +From the root of the `ign-rendering` repository, do the following to build the example: + +~~~ +cd examples/hello_world_plugin +mkdir build +cd build +cmake .. +make +~~~ + +This will generate the `HelloWorldPlugin` library under `build`. +The exact name of the library file depends on the operating system +such as `libHelloWorldPlugin.so` on Linux, `libHelloWorldPlugin.dylib` on macOS, +and `HelloWorldPlugin.dll` on Windows. + +## Run + +The resulting plugin can be loaded by any plugin loader that requests the +features implemented by the plugin. See an example loader at +`examples/hello_world_loader`. + From ec4d189372e2241a3c78518c19239bd05b1e930b Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Wed, 30 Sep 2020 18:22:33 -0700 Subject: [PATCH 06/13] Clean Signed-off-by: John Shepherd --- examples/hello_world_plugin/CMakeLists.txt | 4 ---- examples/hello_world_plugin/README.md | 7 ------- 2 files changed, 11 deletions(-) diff --git a/examples/hello_world_plugin/CMakeLists.txt b/examples/hello_world_plugin/CMakeLists.txt index d95c8b796..6ce1034c2 100644 --- a/examples/hello_world_plugin/CMakeLists.txt +++ b/examples/hello_world_plugin/CMakeLists.txt @@ -2,10 +2,6 @@ cmake_minimum_required(VERSION 3.5 FATAL_ERROR) set(IGN_PLUGIN_VER 1) set(IGN_COMMON_VER 3) -#find_package(ignition-plugin${IGN_PLUGIN_VER} 1.1 REQUIRED COMPONENTS all) - -#set(IGN_PHYSICS_VER 3) -#find_package(ignition-physics${IGN_PHYSICS_VER} REQUIRED) find_package(ignition-rendering3 REQUIRED) find_package(ignition-plugin1 REQUIRED COMPONENTS all) diff --git a/examples/hello_world_plugin/README.md b/examples/hello_world_plugin/README.md index 64c2b6317..29e7362bb 100644 --- a/examples/hello_world_plugin/README.md +++ b/examples/hello_world_plugin/README.md @@ -19,10 +19,3 @@ This will generate the `HelloWorldPlugin` library under `build`. The exact name of the library file depends on the operating system such as `libHelloWorldPlugin.so` on Linux, `libHelloWorldPlugin.dylib` on macOS, and `HelloWorldPlugin.dll` on Windows. - -## Run - -The resulting plugin can be loaded by any plugin loader that requests the -features implemented by the plugin. See an example loader at -`examples/hello_world_loader`. - From 12ec382b2064a2f4129cd103e1ae6e1fccb0e092 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 1 Oct 2020 12:10:30 -0700 Subject: [PATCH 07/13] Add null checks when loading example render engine (#156) Add null checks and docs Signed-off-by: Ian Chen Co-authored-by: John Shepherd --- .../hello_world_plugin/HelloWorldPlugin.cc | 19 ++++++- examples/hello_world_plugin/README.md | 22 ++++++++ src/base/BaseRenderEngine.cc | 50 ++++++++++++++++--- 3 files changed, 82 insertions(+), 9 deletions(-) diff --git a/examples/hello_world_plugin/HelloWorldPlugin.cc b/examples/hello_world_plugin/HelloWorldPlugin.cc index e47dbbdee..bc1e82082 100644 --- a/examples/hello_world_plugin/HelloWorldPlugin.cc +++ b/examples/hello_world_plugin/HelloWorldPlugin.cc @@ -38,40 +38,55 @@ namespace mock // Documentation Inherited. public: virtual std::string Name() const override { - return "test2"; + return "HelloWorldPlugin"; } + // Documentation Inherited. protected: virtual bool LoadImpl(const std::map &_params) override { return true; } + /// \brief Initialize the render engine. + /// \return True if the operation is successful protected: virtual bool InitImpl() override { return true; } + /// \brief Get a pointer to the list of scenes managed by the render + /// engine. + /// \return list of scenes protected: virtual ignition::rendering::SceneStorePtr Scenes() const override { return nullptr; } + /// \brief Create a scene. + /// \param[in] _id Unique scene Id + /// \parampin] _name Name of scene protected: virtual ignition::rendering::ScenePtr CreateSceneImpl(unsigned int _id, const std::string &_name) override { return nullptr; } + /// \brief Singelton setup. private: friend class ignition::common::SingletonT; }; class HelloWorldPlugin : public ignition::rendering::RenderEnginePlugin { + /// \brief Get the name of the render engine loaded by this plugin. + /// \return Name of render engine public: std::string Name() const { - return "test"; + return HelloWorldRenderEngine::Instance()->Name(); } + + /// \brief Get a pointer to the render engine loaded by this plugin. + /// \return Render engine instance public: ignition::rendering::RenderEngine *Engine() const { return HelloWorldRenderEngine::Instance(); diff --git a/examples/hello_world_plugin/README.md b/examples/hello_world_plugin/README.md index 29e7362bb..5f81c8215 100644 --- a/examples/hello_world_plugin/README.md +++ b/examples/hello_world_plugin/README.md @@ -19,3 +19,25 @@ This will generate the `HelloWorldPlugin` library under `build`. The exact name of the library file depends on the operating system such as `libHelloWorldPlugin.so` on Linux, `libHelloWorldPlugin.dylib` on macOS, and `HelloWorldPlugin.dll` on Windows. + +## Run + +Be sure to have the `IGN_GAZEBO_RENDER_ENGINE_PATH` environment variable set to the path +where your plugin is located. From within the `build` directory of this example, you can run + +~~~ +export IGN_GAZEBO_RENDER_ENGINE_PATH=$PWD +~~~ + +to set the environment variable accordingly. + + +Now you can run `ign gazebo` with the name of the resultant library file (without the `lib` prefix +or the file extension, i.e., libHelloWorldPlugin.so -> HelloWorldPlugin): + +~~~ +ign gazebo --render-engine HelloWorldPlugin +~~~ + +You should see a blank screen within the Ignition GUI, as this mocked plugin provides no implementation +for the scene. diff --git a/src/base/BaseRenderEngine.cc b/src/base/BaseRenderEngine.cc index bc5047f12..2a47f74c3 100644 --- a/src/base/BaseRenderEngine.cc +++ b/src/base/BaseRenderEngine.cc @@ -94,72 +94,108 @@ bool BaseRenderEngine::IsEnabled() const ////////////////////////////////////////////////// unsigned int BaseRenderEngine::SceneCount() const { - return this->Scenes()->Size(); + auto scenes = this->Scenes(); + if (scenes) + return scenes->Size(); + return 0u; } ////////////////////////////////////////////////// bool BaseRenderEngine::HasScene(ConstScenePtr _scene) const { - return this->Scenes()->Contains(_scene); + auto scenes = this->Scenes(); + if (scenes) + return scenes->Contains(_scene); + return false; } ////////////////////////////////////////////////// bool BaseRenderEngine::HasSceneId(unsigned int _id) const { - return this->Scenes()->ContainsId(_id); + auto scenes = this->Scenes(); + if (scenes) + return scenes->ContainsId(_id); + return false; } ////////////////////////////////////////////////// bool BaseRenderEngine::HasSceneName(const std::string &_name) const { - return this->Scenes()->ContainsName(_name); + auto scenes = this->Scenes(); + if (scenes) + return scenes->ContainsName(_name); + return false; } ////////////////////////////////////////////////// ScenePtr BaseRenderEngine::SceneById(unsigned int _id) const { - return this->Scenes()->GetById(_id); + auto scenes = this->Scenes(); + if (scenes) + return scenes->GetById(_id); + return ScenePtr(); } ////////////////////////////////////////////////// ScenePtr BaseRenderEngine::SceneByName(const std::string &_name) const { - return this->Scenes()->GetByName(_name); + auto scenes = this->Scenes(); + if (scenes) + return scenes->GetByName(_name); + return ScenePtr(); } ////////////////////////////////////////////////// ScenePtr BaseRenderEngine::SceneByIndex(unsigned int _index) const { - return this->Scenes()->GetByIndex(_index); + auto scenes = this->Scenes(); + if (scenes) + return scenes->GetByIndex(_index); + return ScenePtr(); } ////////////////////////////////////////////////// void BaseRenderEngine::DestroyScene(ScenePtr _scene) { + auto scenes = this->Scenes(); + if (!scenes) + return; this->Scenes()->Destroy(_scene); } ////////////////////////////////////////////////// void BaseRenderEngine::DestroySceneById(unsigned int _id) { + auto scenes = this->Scenes(); + if (!scenes) + return; this->Scenes()->DestroyById(_id); } ////////////////////////////////////////////////// void BaseRenderEngine::DestroySceneByName(const std::string &_name) { + auto scenes = this->Scenes(); + if (!scenes) + return; this->Scenes()->DestroyByName(_name); } ////////////////////////////////////////////////// void BaseRenderEngine::DestroySceneByIndex(unsigned int _index) { + auto scenes = this->Scenes(); + if (!scenes) + return; this->Scenes()->DestroyByIndex(_index); } ////////////////////////////////////////////////// void BaseRenderEngine::DestroyScenes() { + auto scenes = this->Scenes(); + if (!scenes) + return; this->Scenes()->DestroyAll(); } From f532ca79bea41df72e13abd8f84eb981366b0e37 Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Thu, 1 Oct 2020 12:51:25 -0700 Subject: [PATCH 08/13] Add windows build rules Signed-off-by: John Shepherd --- ogre/src/CMakeLists.txt | 12 ++++++++---- ogre2/src/CMakeLists.txt | 12 ++++++++---- optix/src/CMakeLists.txt | 12 ++++++++---- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/ogre/src/CMakeLists.txt b/ogre/src/CMakeLists.txt index 026a66c42..9ef018b6b 100644 --- a/ogre/src/CMakeLists.txt +++ b/ogre/src/CMakeLists.txt @@ -51,10 +51,14 @@ set (versioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_LOWER}-${engine_name set (unversioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_NO_VERSION_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) if (WIN32) - # create_symlink requires cmake 3.13 on windows - cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + # disable MSVC inherit via dominance warning + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4250") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy + ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}\/${versioned} + ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}\/${unversioned})") +else() + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) + INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) endif() -EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) -INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) add_subdirectory(media) diff --git a/ogre2/src/CMakeLists.txt b/ogre2/src/CMakeLists.txt index ff77817b1..420a071df 100644 --- a/ogre2/src/CMakeLists.txt +++ b/ogre2/src/CMakeLists.txt @@ -31,11 +31,15 @@ set (unversioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_NO_VERSION_LOWER}- install(TARGETS ${ogre2_target} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) if (WIN32) - # create_symlink requires cmake 3.13 on windows - cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + # disable MSVC inherit via dominance warning + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4250") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy + ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}\/${versioned} + ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}\/${unversioned})") +else() + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) + INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) endif() -EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) -INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) # Build the unit tests ign_build_tests(TYPE UNIT SOURCES ${gtest_sources} LIB_DEPS ${ogre2_target}) diff --git a/optix/src/CMakeLists.txt b/optix/src/CMakeLists.txt index a765e83a1..abf802c31 100644 --- a/optix/src/CMakeLists.txt +++ b/optix/src/CMakeLists.txt @@ -52,11 +52,15 @@ set (versioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_LOWER}-${engine_name set (unversioned ${CMAKE_SHARED_LIBRARY_PREFIX}${PROJECT_NAME_NO_VERSION_LOWER}-${engine_name}${CMAKE_SHARED_LIBRARY_SUFFIX}) if (WIN32) - # create_symlink requires cmake 3.13 on windows - cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + # disable MSVC inherit via dominance warning + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4250") + INSTALL(CODE "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E copy + ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}\/${versioned} + ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}\/${unversioned})") +else() + EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) + INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) endif() -EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E create_symlink ${versioned} ${unversioned}) -INSTALL(FILES ${PROJECT_BINARY_DIR}/${unversioned} DESTINATION ${IGNITION_RENDERING_ENGINE_INSTALL_DIR}) if("${CUDA_VERSION}" VERSION_LESS "9") set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS};-gencode arch=compute_20,code=sm_20) From 179eb5aca5266c0aaa957b1c116457ff59b1422a Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Thu, 1 Oct 2020 14:41:14 -0700 Subject: [PATCH 09/13] Take in paths from ign gazebo Signed-off-by: John Shepherd --- include/ignition/rendering/RenderEngineManager.hh | 5 +++++ include/ignition/rendering/RenderingIface.hh | 6 ++++++ src/RenderEngineManager.cc | 15 ++++++++++++--- src/RenderingIface.cc | 6 ++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/include/ignition/rendering/RenderEngineManager.hh b/include/ignition/rendering/RenderEngineManager.hh index 3d0d996bd..0d16334e6 100644 --- a/include/ignition/rendering/RenderEngineManager.hh +++ b/include/ignition/rendering/RenderEngineManager.hh @@ -17,6 +17,7 @@ #ifndef IGNITION_RENDERING_RENDERENGINEMANAGER_HH_ #define IGNITION_RENDERING_RENDERENGINEMANAGER_HH_ +#include #include #include #include @@ -130,6 +131,10 @@ namespace ignition /// \param[in] _index Index of the render-engine to unregister public: void UnregisterEngineAt(unsigned int _index); + /// \brief Set the plugin path from which render engines can be loaded. + /// \param[in] _path The name of the environment variable + public: void SetPluginPaths(const std::list &_paths); + IGN_COMMON_WARN_IGNORE__DLL_INTERFACE_MISSING /// \brief private implementation details private: std::unique_ptr dataPtr; diff --git a/include/ignition/rendering/RenderingIface.hh b/include/ignition/rendering/RenderingIface.hh index a0eecd2a9..313398cb4 100644 --- a/include/ignition/rendering/RenderingIface.hh +++ b/include/ignition/rendering/RenderingIface.hh @@ -17,6 +17,7 @@ #ifndef IGNITION_RENDERING_RENDERINGIFACE_HH_ #define IGNITION_RENDERING_RENDERINGIFACE_HH_ +#include #include #include #include @@ -125,6 +126,11 @@ namespace ignition /// \param[in] _index Index of the render-engine to unregister IGNITION_RENDERING_VISIBLE void unregisterEngine(const unsigned int _index); + + /// \brief Set the plugin path from which render engines can be loaded. + /// \param[in] _path The name of the environment variable + IGNITION_RENDERING_VISIBLE + void setPluginPaths(const std::list &_paths); } } } diff --git a/src/RenderEngineManager.cc b/src/RenderEngineManager.cc index 6e1e7aeca..c1d93c70f 100644 --- a/src/RenderEngineManager.cc +++ b/src/RenderEngineManager.cc @@ -91,8 +91,8 @@ class ignition::rendering::RenderEngineManagerPrivate /// \brief Plugin loader for managing render engine plugin libraries. public: ignition::plugin::Loader pluginLoader; - /// \brief Environment variable which holds paths to look for engine plugins. - public: std::string pluginPathEnv = "IGN_GAZEBO_RENDER_ENGINE_PATH"; + /// \brief List which holds paths to look for engine plugins. + public: std::list pluginPaths; /// \brief Mutex to protect the engines map. public: std::recursive_mutex enginesMutex; @@ -293,6 +293,12 @@ void RenderEngineManager::UnregisterEngineAt(unsigned int _index) this->dataPtr->UnregisterEngine(iter); } +////////////////////////////////////////////////// +void RenderEngineManager::SetPluginPaths(const std::list &_paths) +{ + this->dataPtr->pluginPaths = _paths; +} + ////////////////////////////////////////////////// // RenderEngineManagerPrivate ////////////////////////////////////////////////// @@ -388,10 +394,13 @@ bool RenderEngineManagerPrivate::LoadEnginePlugin( ignition::common::SystemPaths systemPaths; // Add default install folder. - systemPaths.SetPluginPathEnv(std::string(this->pluginPathEnv)); systemPaths.AddPluginPaths(std::string(IGN_RENDERING_PLUGIN_PATH)); systemPaths.AddPluginPaths({IGNITION_RENDERING_ENGINE_INSTALL_DIR}); + // Add any preset plugin paths. + for (const auto &path : this->pluginPaths) + systemPaths.AddPluginPaths(path); + // Add extra search path. systemPaths.AddPluginPaths(_path); diff --git a/src/RenderingIface.cc b/src/RenderingIface.cc index 58815b2a4..f43163468 100644 --- a/src/RenderingIface.cc +++ b/src/RenderingIface.cc @@ -114,6 +114,12 @@ void unregisterEngine(const unsigned int _index) { RenderEngineManager::Instance()->UnregisterEngineAt(_index); } + +////////////////////////////////////////////////// +void setPluginPaths(const std::list &_paths) +{ + RenderEngineManager::Instance()->SetPluginPaths(_paths); +} } } } From 0dd768276f5742bd222ca33340f1035a413542aa Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Tue, 6 Oct 2020 12:28:24 -0700 Subject: [PATCH 10/13] Update docs Signed-off-by: John Shepherd --- examples/hello_world_plugin/HelloWorldPlugin.cc | 17 +++++++++++------ examples/hello_world_plugin/README.md | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/hello_world_plugin/HelloWorldPlugin.cc b/examples/hello_world_plugin/HelloWorldPlugin.cc index bc1e82082..361b43e3f 100644 --- a/examples/hello_world_plugin/HelloWorldPlugin.cc +++ b/examples/hello_world_plugin/HelloWorldPlugin.cc @@ -25,6 +25,7 @@ namespace mock { + /// \brief The render engine class which implements a render engine. class HelloWorldRenderEngine : public virtual ignition::rendering::BaseRenderEngine, public ignition::common::SingletonT @@ -42,7 +43,8 @@ namespace mock } // Documentation Inherited. - protected: virtual bool LoadImpl(const std::map &_params) override + protected: virtual bool LoadImpl(const std::map &_params) override { return true; } @@ -57,7 +59,8 @@ namespace mock /// \brief Get a pointer to the list of scenes managed by the render /// engine. /// \return list of scenes - protected: virtual ignition::rendering::SceneStorePtr Scenes() const override + protected: virtual ignition::rendering::SceneStorePtr Scenes() + const override { return nullptr; } @@ -65,8 +68,9 @@ namespace mock /// \brief Create a scene. /// \param[in] _id Unique scene Id /// \parampin] _name Name of scene - protected: virtual ignition::rendering::ScenePtr CreateSceneImpl(unsigned int _id, - const std::string &_name) override + protected: virtual ignition::rendering::ScenePtr + CreateSceneImpl(unsigned int _id, + const std::string &_name) override { return nullptr; } @@ -75,19 +79,20 @@ namespace mock private: friend class ignition::common::SingletonT; }; + /// \brief Plugin for loading the HelloWorld render engine. class HelloWorldPlugin : public ignition::rendering::RenderEnginePlugin { /// \brief Get the name of the render engine loaded by this plugin. /// \return Name of render engine - public: std::string Name() const + public: std::string Name() const override { return HelloWorldRenderEngine::Instance()->Name(); } /// \brief Get a pointer to the render engine loaded by this plugin. /// \return Render engine instance - public: ignition::rendering::RenderEngine *Engine() const + public: ignition::rendering::RenderEngine *Engine() const override { return HelloWorldRenderEngine::Instance(); } diff --git a/examples/hello_world_plugin/README.md b/examples/hello_world_plugin/README.md index 5f81c8215..0e6e58428 100644 --- a/examples/hello_world_plugin/README.md +++ b/examples/hello_world_plugin/README.md @@ -1,7 +1,7 @@ # Engine plugin This example shows how to create a plugin that integrates a rendering engine with -Ignition Rendering. +Ignition Rendering and how to load it with Ignition Gazebo. ## Build From 688d3f451ce408a876c5078bf3b377ad5cd0e046 Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Thu, 8 Oct 2020 15:29:25 -0700 Subject: [PATCH 11/13] Add init attempt at rendering plugin tutorial Signed-off-by: John Shepherd --- tutorials.md.in | 1 + tutorials/03_rendering_plugins.md | 39 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tutorials/03_rendering_plugins.md diff --git a/tutorials.md.in b/tutorials.md.in index 8ae37358c..98aef7abc 100644 --- a/tutorials.md.in +++ b/tutorials.md.in @@ -8,6 +8,7 @@ Ignition @IGN_DESIGNATION_CAP@ library and how to use the library effectively. 1. \subpage introduction "Introduction" 2. \subpage installation "Installation" +3. \subpage renderingplugin "Understanding the Rendering Plugin" ## License diff --git a/tutorials/03_rendering_plugins.md b/tutorials/03_rendering_plugins.md new file mode 100644 index 000000000..5fac10bed --- /dev/null +++ b/tutorials/03_rendering_plugins.md @@ -0,0 +1,39 @@ +\page renderingplugin Understanding the Rendering Plugin + +This is an introduction to different rendering engines and how they are integrated into the Ignition Physics library. + +## Ignition Rendering + +The \ref ignition::rendering "Ignition Rendering" library integrates external rendering engines into the Ignition Simulation eco-system. +It allows users to select from multiple supported rendering engines based on their simulation needs. +Its plugin interface loads rendering engines at runtime. +It is also possible to integrate your own selected rendering engine by writing a compatible plugin interface. + +#### How to Write Your Own Rendering Plugin + +A mocked example of a custom rendering engine plugin can be found [here](https://github.com/ignitionrobotics/ign-rendering/tree/ign-rendering3/examples/hello_world_plugin). In order +to make your own custom rendering engine, this example is a good starting point. There are a few key things which will need to be done in order for a custom rendering engine to function: + + * A singleton Render Engine class which implements the pure virtual functions in [`ignition::rendering::BaseRenderEngine`](https://github.com/ignitionrobotics/ign-rendering/blob/main/include/ignition/rendering/base/BaseRenderEngine.hh). + * A plugin class which implements the pure virtual functions in [`ignition::rendering::RenderEnginePlugin`](https://github.com/ignitionrobotics/ign-rendering/blob/main/include/ignition/rendering/RenderEnginePlugin.hh) + * Registering the plugin, this line can be seen at the bottom of the [`HelloWorldPlugin`](https://github.com/ignitionrobotics/ign-rendering/tree/ign-rendering3/examples/hello_world_plugin/HelloWorldPlugin.cc) example + +Finally, for your custom rendering engine to actually have any functionality, you will need to implement your own `Scene` class, which inherits from and implements the pure virtual functions of [`ignition::rendering::Scene`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/include/ignition/rendering/Scene.hh). The mocked example simply returns `nullptr` for its `CreateSceneImpl(...)` function, so it may be useful to look at the current `Scene` implementations for the other rendering engines within `ignition::rendering` such as [`ogre`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre/src/OgreScene.cc) or [`optix`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/optix/src/OptixScene.cc). + +#### Building and Running Your Rendering Plugin + +Once you have your own rendering plugin written, you can build it similarly to how the example is built. It may be helpful to look at the [`CMakeLists.txt`](https://github.com/ignitionrobotics/ign-rendering/tree/ign-rendering3/examples/hello_world_plugin) from the example as it contains the boilerplate code needed to get a custom rendering engine plugin built. + +After you have your plugin built, you will need to set the `IGN_GAZEBO_RENDER_ENGINE_PATH` environment variable to the path in which your built shared library resides. Note that you will need to do this for every command line instance unless you add the line to your startup shell script (`.bashrc`, `.zshrc`, etc.). + +From here, you should be able to reference your rendering plugin within Ignition Gazebo by the name of the generated shared library file (without the `lib` prefix or the file extension, i.e., libHelloWorldPlugin.so -> HelloWorldPlugin). + +\note You can use the `--render-engine`, `--render-engine-server`, and `--render-engine-gui` flags to specify any supported or custom rendering engine at runtime, this flag will override any other pre-existing rendering engine specifications (such as in an `.sdf` file). The command line call would look something like: + +~~~ +ign gazebo --render-engine HelloWorldPlugin shapes.sdf +~~~ + +#### Feature Comparison + +Do we want to fill this out for ogre, ogre2, and optix? From 86be9fc553ccaa6a7994609c581be9d3e3b7e649 Mon Sep 17 00:00:00 2001 From: John Shepherd Date: Mon, 12 Oct 2020 16:13:27 -0700 Subject: [PATCH 12/13] Requested fixes Signed-off-by: John Shepherd --- tutorials/03_rendering_plugins.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/tutorials/03_rendering_plugins.md b/tutorials/03_rendering_plugins.md index 5fac10bed..ed0a24527 100644 --- a/tutorials/03_rendering_plugins.md +++ b/tutorials/03_rendering_plugins.md @@ -1,6 +1,6 @@ \page renderingplugin Understanding the Rendering Plugin -This is an introduction to different rendering engines and how they are integrated into the Ignition Physics library. +This is an introduction to different rendering engines and how they are integrated into the Ignition Rendering library. ## Ignition Rendering @@ -9,7 +9,7 @@ It allows users to select from multiple supported rendering engines based on the Its plugin interface loads rendering engines at runtime. It is also possible to integrate your own selected rendering engine by writing a compatible plugin interface. -#### How to Write Your Own Rendering Plugin +#### How to Write Your Own Rendering Engine Plugin with Ignition Gazebo A mocked example of a custom rendering engine plugin can be found [here](https://github.com/ignitionrobotics/ign-rendering/tree/ign-rendering3/examples/hello_world_plugin). In order to make your own custom rendering engine, this example is a good starting point. There are a few key things which will need to be done in order for a custom rendering engine to function: @@ -18,7 +18,7 @@ to make your own custom rendering engine, this example is a good starting point. * A plugin class which implements the pure virtual functions in [`ignition::rendering::RenderEnginePlugin`](https://github.com/ignitionrobotics/ign-rendering/blob/main/include/ignition/rendering/RenderEnginePlugin.hh) * Registering the plugin, this line can be seen at the bottom of the [`HelloWorldPlugin`](https://github.com/ignitionrobotics/ign-rendering/tree/ign-rendering3/examples/hello_world_plugin/HelloWorldPlugin.cc) example -Finally, for your custom rendering engine to actually have any functionality, you will need to implement your own `Scene` class, which inherits from and implements the pure virtual functions of [`ignition::rendering::Scene`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/include/ignition/rendering/Scene.hh). The mocked example simply returns `nullptr` for its `CreateSceneImpl(...)` function, so it may be useful to look at the current `Scene` implementations for the other rendering engines within `ignition::rendering` such as [`ogre`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre/src/OgreScene.cc) or [`optix`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/optix/src/OptixScene.cc). +Finally, for your custom rendering engine to actually have any functionality and at minimum, display something in a window, you will need to implement your own `Scene` and `Camera` classes, which inherit from and implement the pure virtual functions of [`ignition::rendering::Scene`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/include/ignition/rendering/Scene.hh) and [`ignition::rendering::Camera`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/include/ignition/rendering/Camera.hh), respectively. The mocked example simply returns `nullptr` for its `CreateSceneImpl(...)` function, so it may be useful to look at the current `Scene` implementations for the other rendering engines within `ignition::rendering` such as [`OGRE`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre/src/OgreScene.cc) or [`OGRE2`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre2/src/Ogre2Scene.cc). Likewise, it may be helpful to look at the `Camera` implementations from [`OGRE`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre/src/OgreCamera.cc) and [`OGRE2`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre2/src/Ogre2Camera.cc) #### Building and Running Your Rendering Plugin @@ -33,7 +33,3 @@ From here, you should be able to reference your rendering plugin within Ignition ~~~ ign gazebo --render-engine HelloWorldPlugin shapes.sdf ~~~ - -#### Feature Comparison - -Do we want to fill this out for ogre, ogre2, and optix? From 128638f6ff657889a0b029cf3c03c25c0b256278 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Mon, 12 Oct 2020 16:59:27 -0700 Subject: [PATCH 13/13] minor tweak to heading Signed-off-by: Ian Chen --- tutorials/03_rendering_plugins.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tutorials/03_rendering_plugins.md b/tutorials/03_rendering_plugins.md index ed0a24527..23ac53fda 100644 --- a/tutorials/03_rendering_plugins.md +++ b/tutorials/03_rendering_plugins.md @@ -9,7 +9,7 @@ It allows users to select from multiple supported rendering engines based on the Its plugin interface loads rendering engines at runtime. It is also possible to integrate your own selected rendering engine by writing a compatible plugin interface. -#### How to Write Your Own Rendering Engine Plugin with Ignition Gazebo +#### How to Write Your Own Rendering Engine Plugin A mocked example of a custom rendering engine plugin can be found [here](https://github.com/ignitionrobotics/ign-rendering/tree/ign-rendering3/examples/hello_world_plugin). In order to make your own custom rendering engine, this example is a good starting point. There are a few key things which will need to be done in order for a custom rendering engine to function: @@ -20,7 +20,7 @@ to make your own custom rendering engine, this example is a good starting point. Finally, for your custom rendering engine to actually have any functionality and at minimum, display something in a window, you will need to implement your own `Scene` and `Camera` classes, which inherit from and implement the pure virtual functions of [`ignition::rendering::Scene`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/include/ignition/rendering/Scene.hh) and [`ignition::rendering::Camera`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/include/ignition/rendering/Camera.hh), respectively. The mocked example simply returns `nullptr` for its `CreateSceneImpl(...)` function, so it may be useful to look at the current `Scene` implementations for the other rendering engines within `ignition::rendering` such as [`OGRE`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre/src/OgreScene.cc) or [`OGRE2`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre2/src/Ogre2Scene.cc). Likewise, it may be helpful to look at the `Camera` implementations from [`OGRE`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre/src/OgreCamera.cc) and [`OGRE2`](https://github.com/ignitionrobotics/ign-rendering/blob/ign-rendering3/ogre2/src/Ogre2Camera.cc) -#### Building and Running Your Rendering Plugin +#### Building and Running Your Rendering Engine Plugin with Ignition Gazebo Once you have your own rendering plugin written, you can build it similarly to how the example is built. It may be helpful to look at the [`CMakeLists.txt`](https://github.com/ignitionrobotics/ign-rendering/tree/ign-rendering3/examples/hello_world_plugin) from the example as it contains the boilerplate code needed to get a custom rendering engine plugin built.