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

Examples and tutorial on using rendering API from plugins #596

Merged
merged 8 commits into from
Feb 12, 2021
Merged
Show file tree
Hide file tree
Changes from 5 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
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ ign_find_package(ignition-tools
REQUIRED
PKGCONFIG "ignition-tools")

#--------------------------------------
# Find ignition-utils
ign_find_package(ignition-utils1 REQUIRED)
set(IGN_UTILS_VER ${ignition-utils1_VERSION_MAJOR})

#--------------------------------------
# Find protobuf
# Module is needed to use the PROTOBUF_GENERATE_CPP
Expand Down
11 changes: 11 additions & 0 deletions Migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ release will remove the deprecated code.
`const std::vector<Entity> &` instead of forcing a copy. The calling code
should create a copy if it needs to modify the vector in some way.

* Various `GuiEvent`s were deprecated in favor of their Ignition GUI
equivalents.
* **Deprecated** `ignition::gazebo::gui::SnapIntervals`
* **Replacement** `ignition::gui::SnapIntervals`
* **Deprecated** `ignition::gazebo::gui::Render`
* **Replacement** `ignition::gui::Render`
* **Deprecated** `ignition::gazebo::gui::SpawnPreviewModel`
* **Replacement** `ignition::gui::SpawnFromDescription`
* **Deprecated** `ignition::gazebo::gui::SnapPreviewPath`
* **Replacement** `ignition::gui::SnapFromPath`

## Ignition Gazebo 4.0.0 to 4.X.X

* Ignition Gazebo 4.0.0 enabled double sided material by default but this
Expand Down
44 changes: 44 additions & 0 deletions examples/plugin/rendering_plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
cmake_minimum_required(VERSION 3.10.2 FATAL_ERROR)

if(POLICY CMP0100)
cmake_policy(SET CMP0100 NEW)
endif()

project(RenderingPlugins)

# Common to both plugins
find_package(ignition-rendering5 REQUIRED)

# GUI plugin
set(GUI_PLUGIN RenderingGuiPlugin)

set(CMAKE_AUTOMOC ON)

find_package(ignition-gui5 REQUIRED)

QT5_ADD_RESOURCES(resources_RCC ${GUI_PLUGIN}.qrc)

add_library(${GUI_PLUGIN} SHARED
${GUI_PLUGIN}.cc
${resources_RCC}
)
target_link_libraries(${GUI_PLUGIN}
PRIVATE
ignition-gui5::ignition-gui5
ignition-rendering5::ignition-rendering5
)

# Server plugin
set(SERVER_PLUGIN RenderingServerPlugin)

find_package(ignition-plugin1 REQUIRED COMPONENTS register)
find_package(ignition-gazebo5 REQUIRED)

add_library(${SERVER_PLUGIN} SHARED ${SERVER_PLUGIN}.cc)
set_property(TARGET ${SERVER_PLUGIN} PROPERTY CXX_STANDARD 17)
target_link_libraries(${SERVER_PLUGIN}
PRIVATE
ignition-plugin1::ignition-plugin1
ignition-gazebo5::ignition-gazebo5
ignition-rendering5::ignition-rendering5
)
38 changes: 38 additions & 0 deletions examples/plugin/rendering_plugins/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Rendering plugins

Demo of 2 plugins that use Ignition Rendering, one for the server and one for the client.

## Build

From the root of the `ign-gazebo` repository, do the following to build the example:

~~~
cd ign-gazebo/examples/plugins/rendering_plugins
chapulina marked this conversation as resolved.
Show resolved Hide resolved
mkdir build
cd build
cmake ..
make
~~~

This will generate the `RenderingGuiPlugin` and `RenderingServerPlugin` libraries under `build`.

## Run

Add the libraries to the correct paths:

~~~
cd ign-gazebo/examples/plugins/rendering_plugins
chapulina marked this conversation as resolved.
Show resolved Hide resolved
export IGN_GUI_PLUGIN_PATH=`pwd`/build
export IGN_GAZEBO_SYSTEM_PLUGIN_PATH=`pwd`/build
~~~

Run the example world

~~~
cd ign-gazebo/examples/plugins/rendering_plugins
ign gazebo -v 4 rendering_plugins.sdf
chapulina marked this conversation as resolved.
Show resolved Hide resolved
~~~

The ambient light on the server scene, visible from the camera sensor, will change every 2 seconds.

The ambient light on the client scene, visible from the GUI, will change every time the button is pressed.
145 changes: 145 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2021 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 <ignition/gui/Application.hh>
//! [includeGuiEvents]
#include <ignition/gui/GuiEvents.hh>
//! [includeGuiEvents]
#include <ignition/gui/MainWindow.hh>
#include <ignition/math/Rand.hh>
#include <ignition/plugin/Register.hh>
#include <ignition/rendering/RenderEngine.hh>
#include <ignition/rendering/RenderingIface.hh>
#include <ignition/rendering/Scene.hh>

#include "RenderingGuiPlugin.hh"

/////////////////////////////////////////////////
void RenderingGuiPlugin::LoadConfig(const tinyxml2::XMLElement * /*_pluginElem*/)
{
// This is necessary to receive the Render event on eventFilter
//! [connectToGuiEvent]
ignition::gui::App()->findChild<
ignition::gui::MainWindow *>()->installEventFilter(this);
//! [connectToGuiEvent]
}

/////////////////////////////////////////////////
void RenderingGuiPlugin::RandomColor()
{
this->dirty = true;
}

/////////////////////////////////////////////////
//! [eventFilter]
bool RenderingGuiPlugin::eventFilter(QObject *_obj, QEvent *_event)
{
if (_event->type() == ignition::gui::events::Render::kType)
{
// This event is called in the render thread, so it's safe to make
// rendering calls here
this->PerformRenderingOperations();
}

// Standard event processing
return QObject::eventFilter(_obj, _event);
}
//! [eventFilter]

/////////////////////////////////////////////////
//! [performRenderingOperations]
void RenderingGuiPlugin::PerformRenderingOperations()
{
if (!this->dirty)
{
return;
}

if (nullptr == this->scene)
{
this->FindScene();
}

if (nullptr == this->scene)
return;

this->scene->SetAmbientLight({
static_cast<float>(ignition::math::Rand::DblUniform(0.0, 1.0)),
static_cast<float>(ignition::math::Rand::DblUniform(0.0, 1.0)),
static_cast<float>(ignition::math::Rand::DblUniform(0.0, 1.0)),
1.0});

this->dirty = false;
}
//! [performRenderingOperations]

/////////////////////////////////////////////////
void RenderingGuiPlugin::FindScene()
{
auto loadedEngNames = ignition::rendering::loadedEngines();
if (loadedEngNames.empty())
{
igndbg << "No rendering engine is loaded yet" << std::endl;
return;
}

// assume there is only one engine loaded
auto engineName = loadedEngNames[0];
if (loadedEngNames.size() > 1)
{
igndbg << "More than one engine is available. "
<< "Using engine [" << engineName << "]" << std::endl;
}
auto engine = ignition::rendering::engine(engineName);
if (!engine)
{
ignerr << "Internal error: failed to load engine [" << engineName
<< "]. Grid plugin won't work." << std::endl;
return;
}

if (engine->SceneCount() == 0)
{
igndbg << "No scene has been created yet" << std::endl;
return;
}

// Get first scene
auto scenePtr = engine->SceneByIndex(0);
if (nullptr == scenePtr)
{
ignerr << "Internal error: scene is null." << std::endl;
return;
}

if (engine->SceneCount() > 1)
{
igndbg << "More than one scene is available. "
<< "Using scene [" << scene->Name() << "]" << std::endl;
}

if (!scenePtr->IsInitialized() || nullptr == scenePtr->RootVisual())
{
return;
}

this->scene = scenePtr;
}

// Register this plugin
IGNITION_ADD_PLUGIN(RenderingGuiPlugin,
ignition::gui::Plugin)
57 changes: 57 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (C) 2021 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.
*
*/

#ifndef RENDERING_GUI_PLUGIN_HH_
#define RENDERING_GUI_PLUGIN_HH_

#include <ignition/gui/qt.h>
#include <ignition/gui/Plugin.hh>
#include <ignition/rendering/Scene.hh>

/// \brief Example of a GUI plugin that uses Ignition Rendering.
/// This plugin works with either Ignition GUI's Scene3D or Ignition Gazebo's
/// Scene3D.
class RenderingGuiPlugin : public ignition::gui::Plugin
{
Q_OBJECT

///\brief Called once at startup.
public: void LoadConfig(const tinyxml2::XMLElement *) override;

/// \brief Callback when user clicks button.
public slots: void RandomColor();

/// \brief Callback for all installed event filders.
chapulina marked this conversation as resolved.
Show resolved Hide resolved
/// \param[in] _obj Object that received the event
/// \param[in] _event Event
private: bool eventFilter(QObject *_obj, QEvent *_event) override;

/// \brief All rendering operations must happen within this call
private: void PerformRenderingOperations();

/// \brief Encapsulates the logic to find the rendering scene through the
/// render engine singleton.
private: void FindScene();

/// \brief Marks when a new change has been requested.
private: bool dirty{false};

/// \brief Pointer to the rendering scene.
private: ignition::rendering::ScenePtr scene{nullptr};
};

#endif
34 changes: 34 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2021 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.
*
*/
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3

Rectangle {
color: "transparent"
anchors.fill: parent
Layout.minimumWidth: 250
Layout.minimumHeight: 100
Button {
text: qsTr("Random GUI color!")
onClicked: {
RenderingGuiPlugin.RandomColor();
}
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
5 changes: 5 additions & 0 deletions examples/plugin/rendering_plugins/RenderingGuiPlugin.qrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="RenderingGuiPlugin/">
<file>RenderingGuiPlugin.qml</file>
</qresource>
</RCC>
Loading