Background & Introduction

All of the Mathematical Sciences library/environment, like the GNU plot, matlab, R, scipy, have their own 3D engine for the scientific data 3D plots. My recent work required of the 3D scatter plot for visualizing my experiment data, and my sciBASIC# library didn't have its own 3D graphic engine yet so I decided to create my own 3D graphic engine for my experiment data plots. For search on the Google and wiki, I found all the necessary algorithms for the 3D graphic and implemented this 3D engine based on the GDI+ graphic techniques successfully.

Although this GDI+ based 3D graphic engine has the performance problem when the model is too complicated and has a lot of 3D surface to draw, but it is good enough for the 3D plots for the scientific computing. For example, using this 3D graphic engine works perfectly for generating this 3D function plot:

In this article, I want to introduce how to build my own 3D graphic engine from ZERO step by step, and I want to mainly introduce the 3D graphic algorithm and the 3mf 3D model format that can help you to implement your own 3D graphic engine in the future.

The 3D Graphics Algorithm

The 3D Graphic Object Models

First of all, I want to introduce the 2 important objects that I use in my own 3D graphic engine.

And based on these two important data structures, we are able to apply the 3D algorithm in this 3D graphic engine. And here is the 3D graphic algorithm that I implemented in this article:

3D rotation

3D to 2D projection

The painter algorithm

The light source algorithm

The 3D Rotation

3D Rotation is more complicated than 2D rotation since we must specify an axis of rotation. In 2D, the axis of rotation is always perpendicular to the x,y plane, i.e., the Z axis, but in 3D, the axis of rotation can have any spatial orientation. We will first look at rotation around the three principle axes (X, Y, Z) and then about an arbitrary axis. Note that for Inverse Rotation: replace q with -q and then R(R-1) = 1.

The Painter Algorithm

The painter's algorithm, also known as a priority fill, is one of the simplest solutions to the visibility problem in 3D computer graphics. When projecting a 3D scene onto a 2D plane, it is necessary at some point to decide which polygons are visible, and which are hidden.

The name "painter's algorithm" refers to the technique employed by many painters of painting distant parts of a scene before parts which are nearer thereby covering some areas of distant parts. The painter's algorithm sorts all the polygons in a scene by their depth and then paints them in this order, farthest to closest. It will paint over the parts that are normally not visible — thus solving the visibility problem — at the cost of having painted invisible areas of distant objects. The ordering used by the algorithm is called a 'depth order', and does not have to respect the numerical distances to the parts of the scene: the essential property of this ordering is, rather, that if one object obscures part of another, then the first object is painted after the object that it obscures. Thus, a valid ordering can be described as a topological ordering of a directed acyclic graph representing occlusions between objects.

One simple method to implement this painter algorithm is using the z-order method:

The Display Device

I have created a Winform control for displaying the 3D model which is avaliable in namespace Microsoft.VisualBasic.Imaging.Drawing3D.Device.GDIDevice. Here is a simple code example of using this 3D model display control in winform:

This 3D model display control is based on the GDI+ graphic engine, so that if the model is too complicated and has a lot of surface to draw, then this control rendering will be very slow. For improvements on the graphics rendering performance, I using 2 worker threads for the 3D graphic display:

This model buffer worker thread applies the 3D projection for all surfaces in the model and runs the Z-order based painters' algorithm, and then creates the 2D polygon buffer for the rendering thread. Here is the definition of this 2D polygon buffer unit:

When the method of the winform control Me.Invalidate() has been invoked, then this method call will force the control to refresh itself and raise the Control.Paint event, then we are able to do the rendering job:

3mf Format

Finally, we have all of the elements that can be used for displaying the 3D graphic. For displaying a 3D graphic, we must put the model data into the display device control. And I use the 3mf model file as my 3D engine input model data. Here is how I do it for loading the 3mf model data:

Open the 3mf model file and load the 3D model into the canvas control using just two simple functions:

3MF is a new 3D printing format that will allow design applications to send full-fidelity 3D models to a mix of other applications, platforms, services and printers. The 3MF specification allows companies to focus on innovation, rather than on basic interoperability issues, and it is engineered to avoid the problems associated with other 3D file formats.

Since 3MF is an XML-based data format designed for using additive manufacturing, we can easily load the model in the *.3mf file using XML de-serialization in Visual Basic, and the XML model for this serialization operation is avaliable in namespace: Microsoft.VisualBasic.Imaging.Drawing3D.Landscape.Vendor_3mf.XML

I think this is simply amazing! When you started with 'I decided to build my own 3D graphics engine from scratch", I thought "yeah, right..." but then you proceeded to do exactly that using an astoundingly small amount of code... and in Visual Basic, no less! Brilliant stuff - well done!