A Customizable Architecture for 3D Graphics Applications - CodeProject
The present article contains the information and building artefacts to create a base architecture for 3D graphics applications. Its main goal is to be useful as a starting point for the construction of a great variety of CAD applications, reusing the explained architecture as a design pattern for your graphics software.
The intended audience of this article are Software Analysts and Software Engineers with a strong background in C++ programming and software methodologies. Thus, for a good understanding of this article it is desirable that you are proficient in the following topics topics:
- UML 2.0.
- Software methodologies.
- Design patterns.
- ANSI/ISO C++ Object Oriented Programming.
- GUI programming and design.
- Basic maths for 3D graphics.
The main idea that this article tries to transmit is the concept of a set of classes that facilitate the construction of 3D graphics software in an Object Oriented paradigm independently of the language or frameworks used.
The ISSIGraph project is conceived as a base prototype for surface modeller assignment. It has been developed for the Software Engineering and Computer Systems department from the National University of Distance Education (UNED). The latest changes and updates result in the work you can see here. For the design and implementation of the tool I followed a tiny methodology similar to RUP (Rational Unified Process). In the following sections you will be able to observe the main Software Engineering Life Cycle used to code ISSIGraph.
When I conceived the ISSIGraph application I tried to fulfil to the following functional and non-functional requirements.
The ISSIGraph application should allow the easy drawing of Bezier and NURBS surfaces in a wireframe fashion, as well as any other surfaces like spheres, cones, cylinders, teapots, toroids, etc. In addition, it must be possible to render 3D text. All these objects must be moved, rotated and resized over the scene in an easy and straightforward way.
The application should support the BMP, JPEG and PNG file format exportation with the possibility of changing the background colour, as well as the XML exportation of in-screen models.
Like any other custom graphics application, the user should be free to do copy, paste and cut operations, as well as undo/redo actions. Finally the application should allow moving, rotating and zooming the 3D objects across the virtual space outside the initial 1024 x 768 window, by using a a controller panel.
In the following list, some of the most important performance and environmental requirements are enumerated:
- High performance at the lowest CPU cost.
- Algorithms of O(n) maximum complexity.
- OpenGL as 3D library.
- Cross-platform: Windows, Linux and Mac OS X.
- Using the wxWidgets 2.9.3 framework.
- Low memory overhead.
- Attractive design.
- Easy to install and use.
- Secure system.
- Legible code.
- Released as Open Source.
The use case diagram is useful for the requirement capture needed to implement the ISSIGraph application. On the left of the diagram below is the main actor that interacts with the system; on the right side are the main use cases:
Fig. 1. Use case diagram
The fundamental architecture of ISSIGraph is based on a three-tier application. As shown below, the bottom-up layer performs user interface management, while the middle layer performs business logic and the lower layer, handles the graphics and hardware libraries. Finally, all these tiers lay on the platform implementation.
Fig. 2. Architecture layout
As in  the intended goals for the users interface were:
A) Give the control to user
- Define interaction modes so that the user does not have to perform unnecessary actions.
- Have in mind a flexible interaction.
- User interaction must be interruptible and undoable.
- Hide technical complexity to user.
- Direct interaction with screen objects.
B) Reduce user memory overload
- Reduce short-term memory demand.
- Use default values.
- Use short-cuts.
- The visual format must be a world's metaphor.
- Use nested menus.
C) Build a consistent interface
- Allow the user to perform a task in the suitable context. i.e. objects selector.
- Maintain the consistence across the family of applications.
- Use mnemonic rules.
Fig. 3. The user interface
In order to implement persistence I didn't use serialization, because this is not suitable for information interchange. To perform persistence with interoperability and information portability I opted to use XML file format with UTF-8 encoding. XML is a well structured specification that allows you to organize and exchange data for a later use. You can see a XML example to store 3D models in ISSIGraph here.
This subsystem is the responsible for managing the user interaction through the wxWidgets user interface framework. The
IssiFrame class contains a reference to a
IssiGLCanvas which is a suitable context to render OpenGL primitives. This class starts-up and handles OnPaint events. This subsystem interoperates with the World subsystem sending messages to the business domain objects.
Fig. 4. Presentation subsystem
This subsystem is the core base class for the rest of objects inherited in the application. The
Box abstract class allows you to manage and implement the subsequent inherited class behaviour; but it is overridden in the
VertexBox core base classes.
Fig. 5. Base classes
This is the first inherited subsystem from the
Box class. The
VertexBox core class allows you to implement 3D math special requirements for NURBS, Beziers and Control Points.
Fig. 6. Surface subsystem
As the Surface subsystem, this one allows you to implement basic 3D surfaces like cubes, teapots, spheres, cones and so on. The final inherited classes like
Torus, etc. implements the virtual behaviour defined at the top core classes like
Quadric. Note that the classes
TwoDimension implements the facilities to change volume dimensions such as height and width.
Fig. 7. Quadrics subsystem
World class which is the receptacle object that receives all the messages from events generated by the wxWidgets framework in the Presentation subsystem. This subsystem implements all the behaviour related to the business logic, that is to say, the whole ISSIGraph application features.
Axis class implements the movable coordinate system which inherits from
VertexBox abstract class. The
Memory class implements a tiny pattern design for the memory operations used by Copy/Paste/Cut and Undo/Redo procedures.
Fig. 8. World subsystem
This trivial set of classes is a help-system package of needed maths, library specifics and conversions routines. They are grouped as an external tool of static member functions useful for the correctness and the organization of the application.
Fig. 9. Tool subsystem
Fig. 10. Sequence diagram
- The user wants to move a whole
NURBS. He notifies it to the
IssiGLCanvasobject reports to the
Worldobject (according to the business logic) reports the NURBS to move.
NURBSobject up-calls its
Surfaceobject iterates through all the
CtrlPointobjects stored in the list in order to move them.
- Now, the user wants to change the toroid's dimensions so he notifies it to the
- Again, the
IssiGLCanvasobject reports the
Worldobject performs the action to the
- Because the toroid object has two dimensions (innerradius and outerradius) it is notified to the
- Now the user wants to move the
- Again, the
IssiGLCanvasreports to the
- The World object (according to the business logic) reports the
- Suddenly, an ONPAINT event happens.
- So the
ISSIGLCanvasnotifies the World object's render method.
Worldobject calls its
NURBSobject to process their control points.
- According to this, the
NURBSprocesses all its control points.
- Now, the World's render routine has to draw its
- So, the
NURBSiterates to draw all its control points.
- Again, the World's render routine has to draw its
- as well as drawing the selection rectangle (
- the selection
DrawSelectionhandler for the
- and the selection handler for the
- Finally, the World's render routine draws the
The complete application has been developed in C++ using the Visual C++ 2010 Express Edition compiler on Windows XP 32-bit version. Later on, the application has been ported to Linux using (with GNU-GCC 4.9 and finally, the Leopard Mac OS X version has been ported with X-Code GCC 4.0 and GNU Make.
In order to perform a suitable 3D graphics output and a state-of-the-art 3D application, I have used the OpenGL libraries for primitive drawing and GLUT for quadrics and text output. As in  I opted to use GLEW libraries for NURBS and Bezier drawing, instead of implementing an algorithm to tessellate them. However, in the Linux and Mac versions I had to use freeglut for GLUT primitives.
The common framework I used for all the application was the wxWidgets version 2.9.3, because it is a free and stable software for a cross-platform user interface implementation.
The distributed code has the following structure:
|main.h||User interface main header|
|main.cpp||User interface main implementation|
|box.h||Base subsystem header|
|box.cpp||Base subsystem implementation|
|surface.h||NURBS, Bezier and Control Points header classes|
|surface.cpp||NURBS, Bezier and Control Points implementation classes|
|quadric.h||Quadrics, volumes and text header classes|
|quadric.cpp||Quadrics, volumes and text implementation classes|
|textout.h||GLUT text routine class header|
|textout.cpp||GLUT text routine class implementation|
|world.h||World subsystem header classes|
|world.cpp||World subsystem implementation classes|
|tool.h||Tool subsystem header classes|
|tool.cpp||Tool subsystem implementation classes|
Tab. 1. Source file directory structure
According to , the dynamics techniques applied to ISSIGraph tests allow the quality assurance of the application.
This technique tries to examine the program logic based on its internal structure. That is to say, it allows seeing the application internals (which would be a symbolic box).
Since exhaustive and complete tests are impracticables in the 100% of the cases, I tried to do a Code coverage of all basic paths for the sentences, decisions and conditions, as well as revisions on paper as software metric.
With this technique I tried to examine the behaviour of the application based on the function specification to perform. It is called so because it does not matter the application internals but the execution response.
To perform black-box testing I used Limit values analysis, for example using a few number versus a high number of control points and objects.
In order to demonstrate a good application performance, I designed two black-box test cases (A and B) as useful stress test using the following system equipment:
- Mac Book Pro
- Intel CPU with Core i5 (four cores) M529 2.40 GHz @ 1.17 GHz
- 2.17 GB RAM
- Windows XP 32-bit operating system
- NVidia GeForce GT 330M
- 3 Cones
- 2 Toroids
- 1 Teapot
- 1 Icosahedron
- 1 Dodecahedron
- 1 Rhombic dodecahedron
- 1 Text
- 1 NURBS
- 1 Bezier
- 1 Coordinate system
Fig. 11. A case
The performance and overhead when rotating the whole scene was:
Fig. 12. System performance in A
Fig. 13. B case
In this case the objects were zoomed 4x, so the performance was:
Fig. 14. System performance in B
The ISSIGraph application has been released as GPLv3.0 license through the Web site SourceForge.NET where it can be accessed at the URL: http://issigraph.sourceforge.net . A download section of the executable and sources for Win32, Linux and Mac is available at the same URL. A complete tutorial on how to use the main features is hosted at http://issigraph.sourceforge.net/docs.html where you may seek all the instructions to play with the program and build surfaces.
If you are interested in contributing and making a real-world 3D application for ISSIGraph, just drop me a letter in either the Codeproject forum or the SourceForge.NET forum and I will check your proposal. A set of future goals are listed below:
- Adding new surfaces (cubes, lines, triangles, circles, interpolations...)
- Adding materials
- Adding textures
- Adding lights
- Adding shadows
- Improving positioning system
- Import/Export 3D models
- Other ideas
Therefore, if you would like to implement any of the above ideas or have any other great one, you are welcome!
- Energy optimization, less than 1% (only renders when the screen must be repainted)
- Improved internal copy/paste/cut
- Improved to one-step-cycled undo/redo
- Fixed blink bug in Windows 7 and 8 versions
- Fixed some annoying bugs
- Compiled at Warning Level 4 (maximum level in Visual C++ and g++)
 Juan M. Cordero Valle and José Cortés Parejo. "Modelado Geométrico". Ra-ma.
 Bjarne Stroustrup. "The C++ programming language (3rd edition)" . Addison-Wesley.
 Julian Smart and Kevin Hock. "Cross-platform GUI Programming with wxWidgets". Prentice Hall.
 Shaw Garlan. "An introduction to Software Architecture". World Scientific Publishing Company.
 Raphael Malveau and Thomas J. Mowbray PhD. "Software Architect Bootcamp". Prentice Hall.