A reorganized (and hopefully better) version of my sample framework.
Pressing h
displays a help window that contains all the necessary information.
If you want to use this as a base for your own project, examine the source code
and read the documentation of the various libraries (see "Dependencies" below).
Dependencies:
- C++20
- CMake >= 3.20
- libQGLViewer >= 2.9
- OpenMesh >= 8.1
- Qt >= 6.4
Optional dependencies:
Standard CMake compilation should work. Note that the libQGLViewer library needs to be compiled with Qt6.
In this guide we will create a debug build using the MinGW compiler and Qt's Creator IDE, but it should work with other configurations, as well.
-
Download Qt:
Select "Download Qt for open source use", and download the online installer tool. You will need to register an email address (free). For installation type, select "Qt 6.4 for desktop development" (with MinGW toolchain). This will install the MinGW compiler, the CMake build tool, and the Qt Creator IDE. (If you already have a C++ compiler and want to use that, consider downloading a smaller package by selecting "Custom".)
-
Download the source of libQGLViewer.
Extract it to a suitable folder. Start Qt Creator, and open the project file inside the
QGLViewer
folder (so its path should be something likelibQGLViewer-2.9.1/QGLViewer/QGLViewer.pro
). Build for Debug. Close the project. -
Download the source of OpenMesh.
Extract it to a suitable folder. Open the
CMakeLists.txt
file in the root directory with Qt Creator. Some errors may appear.Press the "Project" button on the left sidebar, and go to "Initial configuration". Press the "Add..." button, select "Boolean", and enter "BUILD_APPS". Leave its value as "OFF", and press the "Re-configure with Initial Parameters" button. Check the "OPENMESH_BUILD_SHARED" checkbox, press "Run CMake", and then build.
(If you get a "file too big" error, go back to the initial configuration, press "Add...", select "String", enter "CMAKE_CXX_FLAGS", and set the value "-Wa,-mbig-obj", and try to re-configure and build.)
Close the project.
-
Clone this project with git.
Open the
CMakeLists.txt
file. Some errors may appear.Press the "Project" button on the left sidebar, and go to "Initial configuration". Set the following variables:
-
OPENMESH_INCLUDE_DIR
: should be set to thesrc
folder of OpenMesh -
OPENMESH_LIBRARIES
: should be set to the full path to thelibOpenMeshCored.dll
file (which was generated in thesrc/OpenMesh/Core
subdirectory of the OpenMesh build) -
QGLVIEWER_INCLUDE_DIR
: should be set to the libQGLViewer source directory (something likelibQGLViewer-2.9.1
) -
QGLVIEWER_LIBRARY
: should be set to the full path to theQGLViewerd2.dll
file (which was generated in theQGLViewer
subdirectory of the libQGLViewer source)
Re-configure and build.
-
To generate a release build, compile both libQGLViewer and OpenMesh in Release mode,
and in the configuration of this framework, change the library filenames to
libOpenMeshCore.dll
and QGLViewer2.dll
, respectively.
-
Download OpenMesh, Qt6 and libQGLViewer.
-
Compile OpenMesh with CMake, with the
BUILD_APPS
variable set toOFF
. -
Compile libQGLViewer with Qt Creator (similarly as in Windows).
-
Finally, compile this project with CMake. Note the following settings:
-
OPENMESH_LIBRARY_DEBUG
:<OpenMesh build path>/Build/lib/libOpenMeshCore.dylib
-
Qt6_DIR
:<Qt6 install dir>/<version>/macos/lib/cmake/Qt6
-
QGLVIEWER_LIBRARY_DEBUG
:<libQGLViewer source path>/QGLViewer/QGLViewer.framework
-
Since the libQGLViewer framework is local, you should put a symlink beside the executable for it to work, i.e.
[/path/to/geo-framework/build] ln -s <libQGLViewer source path>/QGLViewer/QGLViewer.framework .
A common use-case is to add a new object type that can be (i) read from file, and (ii) triangulated to form a mesh. By default it will compute normal vectors and curvatures approximated from the underlying mesh, but these can be overridden.
Bézier surfaces are supplied as an example, new object types are to be created in a similar fashion:
-
Create a new class that inherits from Object.
-
Override the triangulating function
updateBaseMesh()
: this is the main function, where a mesh representation of the surface should be created. The variable for this is calledmesh
. Also, at the end of the function, you should callObject::updateBaseMesh(false, false)
. Supplytrue
arguments when you have special handlers for the normal or mean curvature, respectively. -
Optionally override the
normal()
and/ormeanCurvature()
functions. -
Override the main drawing function
draw()
; the surface itself is drawn based on the triangulation; here you should only draw extra things, such as the control points etc. -
Override the file input function
reload()
; it loads the file given in thefilename
variable. In the end of the function, you should callupdateBaseMesh()
to generate the surface. -
In
Window::open()
, add your own file format to the list of extensions. -
In
Viewer::open()
, add a conditional of the typeelse if (filename.ends_with(".your_extension")) surface = std::make_shared<YourObjectType>(filename);
so that your class will be invoked when a file of the added type is opened. (Naturally the
YourObjectType.hh
header should also be included.) -
Override the modification functions:
-
drawWithNames()
: Here you should draw only those things that you can click on (e.g. control points). Each object is associated with a name (an integer). -
postSelection()
: returns the position of the selected object (selected
is the name of the object the user clicked on) -
movement()
: sets the position of the selected object
-
Changes compared to sample framework
Added features:
-
More extensible interface
-
Handling multiple objects
-
Better toolchain (CMake integration, Qt 6, OpenMesh 8)
Removed features:
-
Mesh fairing
-
Face-based curvature approximation
-
Saving Bézier surfaces