latest version v1.9 - last update 10 Apr 2010 |
Even if we have tried to create simple ways to inherit the 3D manipulation functionality for 3D viewers, it is necessary to explain the steps required when creating new viewer classes.
All classes inherited from viewerBase3D contain three enclosed classes (which can of course be inherited from parent classes): viewerBase3D::parameters, viewerBase3D::configDialog and viewerBase3D::mainWindow
Usually, each new viewer will require new parameters that specify different display modalities (like show coordinate system, display data with lines or points, etc.), and the user usually wants to set them interactively using some dialogs. All new parameters added should be encapsulated in an enclosed class with the name "parameters" in your new viewer class. These parameters classes are similar to the lti::functor::parameters, but they include also some special attributes used to tranfer some information about the data being currently displayed to the configuration dialogs(see also method lti::viewerBase3D::mainWindow::prepareParameters() ). They will implement the typical parameters interface: (read, write, getTypeName, copy, clone, and so on).
The dialog used to set this parameters is implemented also in an enclosed class named "configDialog". One of the most important members in this class is lti::viewerBase3D::configDialog::insertPages, which will insert the a new settings page into the default dialog. You will usually want to add the common dialog with the line
appendPage(buildCommonPage());
For your own parameter configuration pages you can create methods like
configDialog::pageWidget buildMyOwnPage() { pageWidget pw; // this object will be returned pw.label = "my page"; // the name of the widget // create the GTK widget GtkWidget* theWidget = gtk_vbox_new (FALSE, 0); // ... pw.widget = theWidget; return pw; };
The other two methods will copy the data from the parameters into the dialog or otherwise. They are called lti::viewerBase3D::configDialog::getDialogData() and lti::viewerBase3D::configDialog::setDialogData().
Of course, you don't need to reimplement this two classes if you don't have any new parameters in your own viewer.
The main window administrates the real viewer, i.e. the window where all data is drawn. It also checks for all important events, like right-mouse button pressed to show the configuration dialog, and drag of mouse to change the 3D camera parameters.
The method lti::viewerBase3D::mainWindow::dataToImage() will draw the data using the internal lti::draw3D object (lti::viewerBase3D::mainWindow::drawTool) into the proper image. You can use here and in other methods the attributes lti::viewerBase3D::mainWindow::mouseButtonPressed and lti::viewerBase3D::mainWindow::lastMousePos in order to check if you want to draw your data in a way or another, depending on how the user interacts with the viewer. For example, if the user is dragging the camera position, zooming, etc. He has the mouse button pressed (mouseButtonPressed!=0), and you can draw a preview of the data to allow a faster interation.
When you request the configuration dialog (usually pressing the right mouse button), you will need to transfer some informational data from the main window to the configuration dialog. This is done through the informational attributes of the parameters-class, which can be filled within the method lti::viewerBase3D::mainWindow::prepareParameters().
The inheritance from viewerBase3D implies the implementation of following methods:
return new mainWindow()
.bool myViewerClass::show(const myDataType& data) { if (ensureMainWindowInstance()) { // cast wnd to the proper mainWindow class mainWindow* window = dynamic_cast<mainWindow*>(wnd); if (notNull(window)) { window->dolock(); // transfer your data to wnd window->putData(data); // assume your mainWindow class has a // method called putData window->unlock(); return viewerBase3D::show(); } } return false; }