SIGN UP MEMBER LOGIN:    
ARTICLE

Playing with 3-D Coordinate Space in C#, GDI+ and .NET

Posted by Mike Gold Articles | GDI+ & Graphics January 10, 2002
This article show to dealing with a 3-D Coordinate System.
Reader Level:
Download Files:
 

 

Figure 1 - 3-D Rotation of a Cube on a Windows Form

As I was trying to think of an article to write on GDI+, I started looking through some of my old programming books and came across Tricks of the Game Programming Guru.    There are  good explanations in this book of the Ray Tracing Algorithm,  the Painter's Algorithm, Z-Buffering, 3-D Sprite Manipulation, and (relevant to this article) dealing with a 3-D Coordinate System.  The 3-D Coordinate system is shown below:

Figure 2 - 3D Coordinate system

This coordinate system consists of an x, a y and a z axis.  The z axis is coming out from the screen towards you.  As with a 2D Coordinate system, translation, scaling and rotation can all be handled using Matrix mathematics.  The only difference is we are now translating, rotating, and scaling in 3 dimensions instead of 2. Translation, Scaling, and Rotation are all handled by 4x4 matrices.

To Translate a 3-D Object,  you would multiply each vertices of the object by the matrix below:

Figure 3 - Translation in 3-D Space

Scaling is done with a scale factor multiplied by the identity matrix:

Figure 4 - Scaling a Point in 3D Space

And Rotation is done with trigonometric functions in the matrix. Because Rotation can be done either along the x, y, or z axis, there is a different rotation matrix for each of the axises:

Figure 6a - Rotation around the X axis

Figure 6b - Rotation around the Y axis

Figure 6c - Rotation around the Z axis

After looking at all these 3D equations, a question may arise in your mind.  How the heck do I show a 3D object on a 2 Dimensional PC Monitor?  The way this is done is with a clever mapping that fools the eye into seeing depth called perspective projection.  Perspective projection relies on the fact that smaller things seem farther away.  To project our 3D object onto a 2D screen we need to "throw away" the z component and scale the x and y components based on the z component.  Therefore the points that have a larger z component, will appear farther away from the viewer.  Also we need to multiply by a viewing distance factor to scale the image into view. Below is the formula for calculating the coordinates:

x p = distance_value * x/z;
y p   = distance_value * y/z;

Hence we have a "3-D" coordinate in 2D Space so we can plot it on the computer.

Now that we have all the tools we need to play around in a 3-D coordinate system, let's lay out a simple design for drawing 3-D Objects.  This architecture is a simple composite design consisting of an Object which consists of polygons which consists of points.  There is also a matrix class used to do the transformations on the points. Methods for rotating, translating, and scaling the points are propogated through the shape to the polygon class and finally to the 3-D point class. The 3-D projection mentioned above is automatically calculated when drawing the shape.

Figure 7 - UML Design of Simple 3-D Library reverse engineered using WithClass 2000

We use the library to construct a simple cube by passing the coordinates of 6 square polygons.  Then we  translate and scale the cube so that we can see it large enough on the form:

private void CreateCube()
{
TheCube.AddPolygon(
new ThreeDPoint[]{
new ThreeDPoint(0, 0, 0),
new ThreeDPoint(0, 1, 0),
new ThreeDPoint(1, 1, 0),
new ThreeDPoint(1, 0, 0),
new ThreeDPoint(0, 0, 0)
});

TheCube.AddPolygon(
new ThreeDPoint[]{
new ThreeDPoint(0, 0, 0),
new ThreeDPoint(0, 0, 0.5f),
new ThreeDPoint(0, 1, 0.5f),
new ThreeDPoint(0, 1, 0),
new ThreeDPoint(0, 0, 0)});

TheCube.AddPolygon(
new ThreeDPoint[]{
new ThreeDPoint(0, 0, 0),
new ThreeDPoint(0, 0, 0.5f),
new ThreeDPoint(1, 0, 0.5f),
new ThreeDPoint(1, 0, 0),
new ThreeDPoint(0, 0, 0)});

TheCube.AddPolygon(new ThreeDPoint[]{
new ThreeDPoint(1, 1, 0),
new ThreeDPoint(1, 1, 0.5f),
new ThreeDPoint(0, 1, 0.5f),
new ThreeDPoint(0, 1, 0),
new ThreeDPoint(1, 1, 0)
});

TheCube.AddPolygon(new ThreeDPoint[]{
new ThreeDPoint(1, 0, 0),
new ThreeDPoint(1, 0, 0.5f),
new ThreeDPoint(1, 1, 0.5f),
new ThreeDPoint(1, 1, 0),
new ThreeDPoint(1, 0, 0)
});

TheCube.AddPolygon(new ThreeDPoint[]{
new ThreeDPoint(0, 0, 0.5f),
new ThreeDPoint(0, 1, 0.5f),
new ThreeDPoint(1, 1, 0.5f),
new ThreeDPoint(1, 0, 0.5f),
new ThreeDPoint(0, 0, 0.5f)
});

// scale the cube 50x
TheCube.Scale(50);
// translate the cube to position 100, 100, 100
TheCube.Translate(new float[]{100, 100, 100});
}

Listing 1 - Creating the 3D Object 

The translate, rotate, and scale functions use a Vector multiplication method found in the Matrix class which multiplies a 3-D Point by the transformation matrix:

public float[] VectorMultiply(float[] vector)
{
float[] result = new float[4];
// Multiply the vector by the matrix multiplying the transposed matrix elements and summing
// to form a new element
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
result[i] += vector[j] * Elements[j,i];
}
}
return result;
}

Listing 2 - Multiplying the 3-D Point by the transformation matrix

Painting the Object

Another aspect of drawing a 3-D Shape is painting it so it looks more realistic and not just some wire sculpture.  Texturing and painting is accomplished by filling in the polygons that make up the 3D Object.  The thing is, you can't just fill the polygons in using some random order because then the surfaces in the front could be overshadowed by the surfaces in the back simply because many of the polygons overlap.  Therefore we need to put the polygons in an order we can paint them so that the polygons that are hidden are supposed to be hidden and those that are exposed are supposed to be exposed to give a correct view of the object. There are a few suggested ways to approach this problem.  One is to use the painter's algorithm, which tests different cases of whether the polygons overlap or not and orders them appropriately.  The other is to use Z-Buffering which uses the plane equation to find a normal vector of the polygon, and use this vector to order the painting of the pixels. Z-Buffering is often, these days built into graphics boards that utilize fast polygon painting. 

In my example, I take the ultra simple approach which works to some extent. I compare each polygon based on the sum of the Z coordinates of each vertices. I use the IComparable interface to sort the polygons in an ArrayList based on whether this sum is greater or less than the previous polygon.  This algorithm of course falls apart if you are implementing it on an object that is not concave and has many different shaped polygons, but for a cube it seems to work for the most part.

Shading is accomplished by assigning a grayscale color (where in argb, r = g = b) to each of the facets based on the order of the polygons.  The lightest color is assigned to the polygon that is painted last (the polygon in the front).  This gives the illusion that the cube is illuminated from the front.  Below is the code in the ThreeDObject class that draws all the polygons

public void Draw(Graphics g)
{
// draw each polygon in the ArrayList's order and fill them
for (int i = 0; i < Polygons.Count; i++)
{
((ThreeDPolygon)Polygons[i]).Draw(g);
// Fill the polygon with lighter and lighter grayscale colors
((ThreeDPolygon)Polygons[i]).Fill(g, Color.FromArgb(i*30 + 50, i*30 + 50, i*30 + 50));
}
}

The form includes a button that rotates the 3-D Cube each time it is pressed.  This library currently has support for rotating around the X axis:

// Button Handling Event
private void button1_Click(object sender, System.EventArgs e)
{
// Sort the polygons for painting
TheCube.SortPolygonsInZOrder();
// Rotate the cube around its center 1 degrees around the X Axis
TheCube.RotateAt(TheCube.GetCenter(), 1);
Invalidate();
}

Improvements

The Painting algorithm can be improved to implement one of the painting algorithms mentioned in this article. Also, the next step in this library is to add texturing capability so you can draw some really cool object.  Anyway, have fun in the 3-D World!

Login to add your contents and source code to this article
share this article :
post comment
 

the source code has really helped my understand how to depth sort, my lectures pretty much teaching me this article!

Posted by gary Feb 15, 2011

So beautiful  it is! But how can i do as you do.yet,I want to draw a 3D project by myself but I don't know where to start ,could you tell me how should i do?Thank you very much,hehe,my English is so-so,don't laught at me^-^.I think you could read my words!^-^ Thank you

Posted by Ice Man May 30, 2010

Hi! Thanks a lot for creating this library and this article. I am using you library to paint some stuffs in 3D. However, I don't get the part of the algorithm where you rotate the shape, I mean, I know where you have the function and I got it thanks to the debugging, the point is that I don't understand it at all, and I would like to obtain the resulting image without deformation at all when it rotates. I know that when an image rotates it gets deformed, but not in that way like stretching and contracting. Thanks a lot for your attention and I hope you can help me!

Posted by S C Nov 04, 2008
Become a Sponsor
PREMIUM SPONSORS
  • Finally – a virtual platform that delivers next-generation Windows Server 2008 Hyper-V virtualization technology from a managed hosting partner you can truly depend on. Visit www.maximumasp.com/max for a FREE 30 day trial. Hurry offer ends soon. Climb aboard the MaxV platform and take advantage of High Availability, Intelligent Monitoring, Recurrent Backups, and Scalability – with no hassle or hidden fees. As a managed hosting partner focused solely on Microsoft technologies since 2000, MaximumASP is uniquely qualified to provide the superior support that our business is built on. Unparalleled expertise with Microsoft technologies lead to working directly with Microsoft as first to offer IIS 7 and SQL 2008 betas in a hosted environment; partnering in the Go Live Program for Hyper-V; and product co-launches built on WS 2008 with Hyper-V technology.
    ceTE software specializes in components for dynamic PDF generation and manipulation. The DynamicPDF™ product line allows you to dynamically generate PDF documents, merge PDF documents and new content to existing PDF documents from within your applications. Visit DynamicPDF here
Become a Sponsor