tutorial2.docu 8.34 KB
Newer Older
Mike Kremer's avatar
Mike Kremer committed
1
2
3
4
5
6
7
8
/*! \page ex2 Implementing a mesh smoother plugin
 *
 * The last section dealt with the implementation of a first plugin without any functionality at all. This section
 * will show you how to progam a simple mesh smoother. We are assuming that you have read \ref ex1 and will only
 * explain parts that have to be added in order to include new functionality.
 *
 * \subsection ex2Header Definition of the header
 *
9
 * To start off we first have to add two additional header files. The first one is the \c ToolboxInterface.
Mike Kremer's avatar
Mike Kremer committed
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
 * We need this interface because we want to add a Toolbox to our plugin in order to be able to set parameters.
 * Additionally, we want to use the \c LoggingInterface so that we can inform the user of our plugin when something
 * went wrong.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline #include <OpenFlipper/BasePlugin/ToolboxInterface.hh>
 * \skipline #include <OpenFlipper/BasePlugin/LoggingInterface.hh>
 *
 * In order to work with the Interfaces we have to define that the plugin will implement the additional interfaces.
 * The class definition then looks as follows:
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline class SmootherPlugin
 *
 * Furthermore we have to insert the \c Q_INTERFACES macro. This makes the signals and slots from both interfaces available.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline Q_INTERFACES(ToolboxInterface)
 * \skipline Q_INTERFACES(LoggingInterface)
 *
 * Now that we have defined which Interfaces to implement, we can look at which signals and slots we want to implement.
 * Firstly, we need two additional signals from the \c BaseInterface :
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline void updateView()
 * \skipline void updatedObject(
 *
 * The first signal updateView() is emitted when we have finished computing the smoothed mesh. The signal tells OpenFlipper
 * to redraw its viewer(s). The second signal updatedObjects() is emitted to inform all other plugins that an object
 * has changed and therfore allows each plugin to react on this change.
 *
 * Since we also want to use the \c LoggingInterface we have to define the following signals which allow us to send
 * log messages to the OpenFlipper Loggers.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline void log(
 * \skipline void log(
 *
Mike Kremer's avatar
Mike Kremer committed
48
 * The last Interface that's left over is the \c ToolboxInterface from which we are only implementing one signal:
Mike Kremer's avatar
Mike Kremer committed
49
50
 *
 * \dontinclude example/SmootherPlugin.hh
Mike Kremer's avatar
Mike Kremer committed
51
 * \skipline void addToolbox( QString _name, QWidget* _widget );
Mike Kremer's avatar
Mike Kremer committed
52
 *
53
54
 * As we will see later, this function is used to add a ToolBox (i.e. a \c QWidget ) to
 * the OpenFlipper user interface.
Mike Kremer's avatar
Mike Kremer committed
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
 *
 * As a last step we have to add to include additional class members to control the parameter for the smoothing and
 * to actually compute the smoothed mesh.
 *
 * \dontinclude example/SmootherPlugin.hh
 * \skipline private:
 * \until Laplace();
 *
 * That's it for the header of the plugin. The complete header looks like this:
 *
 * \include example/SmootherPlugin.hh 
 *
 *
 * \subsection ex2Implemenation1 Implemention of the GUI
 *
70
71
72
 * As we have already mentioned in \ref ex2Header, the tool box is generated inside the pluginsInitialized() function
 * and then added by the addToolbox() signal passing a reference to our toolbox.
 * So we begin by creating the elements of the ToolBox:
Mike Kremer's avatar
Mike Kremer committed
73
74
75
 * 
 * \dontinclude example/SmootherPlugin.cc
 * \skipline QWidget
76
 * \until QLabel* label = new QLabel("Iterations:");
Mike Kremer's avatar
Mike Kremer committed
77
78
79
80
81
82
83
84
85
86
87
88
89
 *
 * Later, the smoothButton is used to start the mesh smoothing and the iterationsSpinbox_ allows the user to control
 * the number of smoothing iterations that should be performed.
 *
 * The created Toolbox elements are then combined into a Layout
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline QGridLayout
 * \until 2,0,1,2);
 *
 * Here, the SpacerItem, which is added last, only helps aligning the elements at the top of the toolbox.
 *
 * We have to connect the smoothButton to the simpleLaplace() slot of our class, so that after clicking
90
91
 * the button the slot is called.  Finally, when the tool box has been
 * entirely created, we emit the signal to add the tool box to OpenFlipper:
Mike Kremer's avatar
Mike Kremer committed
92
93
94
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline connect
95
 * \until emit addToolbox( tr("Smoother") , toolBox );
Mike Kremer's avatar
Mike Kremer committed
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
 *
 *
 * \subsection ex2Implemenation2 Implemention of the Smoother
 *
 * Now that the Toolbox is completely setup, we can start implementing the smoother. We begin with searching objects
 * on which we have to compute the smoothing. The algorithm takes all objects marked as target and tries to apply the
 * smoothing.
 *
 * To find all these Objects we use an ObjectIterator. This iterator can be found in the PluginFunctions. Every
 * communication between OpenFlipper and its Plugins is accomplished through either an interface or the PluginFunctions.
 * So these are the places to look for if you want to add additional functionality and therefore need to communicate
 * with OpenFlipper.
 *
 * We initialize the PluginFunctions::ObjectIterator with PluginFunctions::TARGET_OBJECTS and thereby make sure that
 * the iteration is restricted to target objects only.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline void SmootherPlugin::simpleLaplace() {
 * \until ++o_it) {
 *
 * In the next line we test if we have to deal with a triangle mesh. Since computation on triangle meshes
 * is in many cases more efficient than on arbitrary polygonal meshes OpenMesh treats them seperately
 * (see OpenMesh documentation for further information on this topic). See also \ref OpenFlipper/common/Types.hh
 * for data types in OpenFlipper.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline if ( o_it->dataType( DATA_TRIANGLE_MESH ) ) {
 *
 * First off, we backup the current vertex positions by adding a custom property to our mesh.
 * We assume that you already made yourself familiar with OpenMesh. Otherwise we recommend you to
 * read the OpenMesh documentation first since we use many of OpenMeshes's core functions in this tutorial. 
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline // Get the mesh to work on
 * \until mesh->add_property( origPositions, "SmootherPlugin_Original_Positions" );
 * 
 * The smoothing algorithm itself depends on the number of iterations that one can adjust
 * in the plugin's toolbox.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline for ( int i = 0 ; i < iterationsSpinbox_->value() ; ++i ) {
 * \until }// Iterations end
 *
 * In a few words the algorithm iterates over each vertex of the mesh, accumulates the positions of it's neighboring
 * vertices, devides the sum by it's valence and updates it's position to the computed value.
 * If the current vertex is a boundary vertex, we skip over to the next one without updating the position.
 *
 * Now that the smoothing operation is done, we want to get rid of the original vertex positions.
 * Since we changed vertices, we also have to update the normals.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline  // Remove the propert
 * \until mesh->update_normals();
 *
150
151
152
153
154
155
156
 * We now implement the same procedure for arbitrary polygonal meshes using the
 * template types of OpenMesh. Starting at line (see \ref com_src_ex2 for the complete
 * source code of this example plugin):
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline } else if ( o_it->dataType( DATA_POLY_MESH ) ) {
 *
Mike Kremer's avatar
Mike Kremer committed
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
 * The next step is to tell the OpenFlipper core that our plugin has updated an object in the scene.
 * The affected object will then be redrawn. See \ref geometryData for information on how to handle geometry data in a plugin.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline emit updatedObject( o_it->id() );
 *
 * The smoothing algorithm on arbitrary polygonal meshes in this case works analogously.
 * See \ref com_src_ex2 for the complete source code.
 *
 * If the object's type is neither triangle nor polygonal mesh, we make use of the implemented
 * \ref LoggingInterface by dumping an error log message to OpenFlipper's log widget.
 *
 * \dontinclude example/SmootherPlugin.cc
 * \skipline } else {
 * \until } // Switch data type
 *
 * \section com_src_ex2 The complete source code of the example
 *
 * SmootherPlugin.hh
 * \include example/SmootherPlugin.hh
 *
 * SmootherPlugin.cc
 * \include example/SmootherPlugin.cc
 * 
181
182
 * We use the cmake project file presented in \ref ex1c to build this plugin.
 * (Or you can also use the obsolete qmake project file presented in \ref ex1b.)
Mike Kremer's avatar
Mike Kremer committed
183
 */