1. Introduction
2. Background and Covered Topics
3. The IssiGraph Project
3.1 Requirements
3.1.1 Functional requirements
3.1.2 Non-functional requirements
3.1.3 Use Case
3.2 Architecture
3.3 High-Level Design
3.3.1 User Interface
3.3.2 Data Management
3.4 Detailed Design
3.4.1 Class diagram
3.4.1.1 Presentation Subsystem
3.4.1.2 Base-hierarchy Subsystem
3.4.1.3 Surface Subsystem
3.4.1.4 Quadrics Subsystem
3.4.1.5 World Subsystem
3.4.1.6 Tool Subsystem
3.5 Implementation
3.5.1 Compilers
3.5.2 Libraries
3.5.3 Frameworks
3.5.4 Code Distribution
3.6 Tests
3.6.1 White-Box Testing
3.6.2 Black-Box Testing
4. Release and Features
5. Contribute
6. New Features in 1.41 version
7. Further Reading and References
1. Introduction
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.
2. Background and Covered Topics
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.
3. The ISSIGraph Project
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.
3.1 Requirements
When I conceived the ISSIGraph application I tried to fulfil to the following functional and non-functional requirements.
3.1.1 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.
3.1.2 Non-functional requirements
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.
3.1.3 Use Case
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
3.2 Architecture
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
3.3 High-Level Design
3.3.1 User Interface
As in [1] 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
3.3.2 Data management
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.
3.4 Detailed Design
3.4.1 Class Diagram
3.4.1.1 Presentation Subsystem
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
3.4.1.2 Base-hierarchy 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 QuadricBox
and VertexBox
core base classes.
Fig. 5. Base classes
3.4.1.3 Surface Subsystem
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
3.4.1.4 Quadrics 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 Cylinder
, Cone
, Torus
, etc. implements the virtual behaviour defined at the top core classes like QuadricBox
and Quadric
. Note that the classes OneDimension
and TwoDimension
implements the facilities to change volume dimensions such as height and width.
Fig. 7. Quadrics subsystem
3.4.1.5 World Subsystem
Finally, the 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.
The 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
3.4.1.6 Tool 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 IssiGLCanvas
object. - The
IssiGLCanvas
object reports to the World
object. - The
World
object (according to the business logic) reports the NURBS to move. - The
NURBS
object up-calls its Surface
base. - The
Surface
object iterates through all the CtrlPoint
objects 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
IssiGLCanvas
object. - Again, the
IssiGLCanvas
object reports the World
object. - The
World
object performs the action to the Torus
object. - Because the toroid object has two dimensions (innerradius and outerradius) it is notified to the
TwoDimension
object. - Now the user wants to move the
Axis
object. - Again, the
IssiGLCanvas
reports to the World
object. - The World object (according to the business logic) reports the
Axis
. - Suddenly, an ONPAINT event happens.
- So the
ISSIGLCanvas
notifies the World object's render method. - The
World
object calls its NURBS
object to process their control points. - According to this, the
NURBS
processes all its control points. - Now, the World's render routine has to draw its
NURBS
. - So, the
NURBS
iterates to draw all its control points. - Again, the World's render routine has to draw its
Torus
object, - as well as drawing the selection rectangle (
DrawBox
), - the selection
DrawSelection
handler for the NURBS
, - and the selection handler for the
Torus
. - Finally, the World's render routine draws the
Axis
(coordinate system).
3.5 Implementation
3.5.1 Compilers
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.
3.5.2 Libraries
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 [2] 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.
3.5.3 Frameworks
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.
3.5.4 Code Distribution
The distributed code has the following structure:
Source file | Meaning |
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
3.6 Tests
According to [1], the dynamics techniques applied to ISSIGraph tests allow the quality assurance of the application.
3.6.1 White-Box Testing
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.
3.6.2 Black-Box Testing
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
Case A:
- 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
Case B:
Fig. 13. B case
In this case the objects were zoomed 4x, so the performance was:
Fig. 14. System performance in B
4. Release and Features
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.
5. Contribute
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!
6. New Features in 1.41 version
- 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++)
7. Further Reading and References
[1] Robert S. Pressman. "Software Engineering: A Practitioner's Approach (fifth edition)". McGraw-Hill.
[2] Donald Hearn and Pauline Baker. "Computer Graphics with OpenGL (3rd edition)". Pearson - Prentice Hall.
[3] Juan M. Cordero Valle and José Cortés Parejo. "Modelado Geométrico". Ra-ma.
[4] Bjarne Stroustrup. "The C++ programming language (3rd edition)" . Addison-Wesley.
[5] Julian Smart and Kevin Hock. "Cross-platform GUI Programming with wxWidgets". Prentice Hall.
[6] Shaw Garlan. "An introduction to Software Architecture". World Scientific Publishing Company.
[7] Raphael Malveau and Thomas J. Mowbray PhD. "Software Architect Bootcamp". Prentice Hall.