Wednesday, April 2, 2008

2) A 3D application in 5 minutes !


In this blog post we will make a very simple 3D application in 5 very simple steps.

Here is a screen-shot from our 3D "Hello World" example


Click here to download the code for our 3D "Hello World".
Please note the readme.txt file included in the zip file.

Before we continue, take a look at the code.
The entire program is just about 10 lines of code !

   Click on the code to enlarge

In this example I use the 3DSTATE 3D Engine. It is a general purpose engine that can be used to write fast games/simulator as well as business applications.
You can choose whatever 3D Engine you like, but it is important that you choose one or otherwise you will be spending months to do something that usually can be done in 5 minutes.
A good general purpose 3D Engine gives you the freedom to do any type of 3D graphics while at the same time avoiding:
Mastering complex 3D Math, advance 3D algorithms and techniques, making sure your application runs the same way on all computers/3D graphics cards etc.


How 3D applications work

In almost every 3D application we have the following 3 elements:

1) A file describing the geometry of the 3D world. The geometry is usually given by polygons and meshes, each with the bitmap images and shaders with which they are associated.

2) A camera. This is a point of view inside the world. This is our eye. The camera has location and direction. The image seen from the camera is what we see on the computer screen.

3) 3D Objects inside the world such as people, cars, planes, etc.

The most important task of every 3D Engine is to quickly calculate the image seen from the camera/eye. This process is called Rendering.
The 3D world is projected on a projection plane resulting in a 2D image that can be displayed on the screen.

Whenever the camera/eye moves or whenever a 3D object inside the world moves we need to redo the Rendering so that the image on the screen reflects the changes.

By repeating the rendering process many times per second, we generate the illusion of smooth movements/3D animation.



Getting started

In this blog post we will create a simple 3D demo from scratch.
We will go over the steps needed from opening Visual Studio and creating a new C# project till we complete our demo.

These steps are very simple and it will probably take you not more than 5 minutes to do.

In the future, while making your own 3D application, you can skip these steps and simply download the code from the link above and start from there.

So here we go.

Step 1 - Create a new empty project

Open visual studio and then from the file menu choose:
File->New->Project-> C# -> Windows Forms Application

Step 2 - Add 3DSTATE 3D Engine Library

2.1)  Add the _3D.cs file to your project.
This file is included in the zip file (see link above)
The file is located inside the 3D_Engine folder.
The _3D.cs file includes the _3D class which contains all the 3D Engine functions.
These functions are usually very simple and straight forward. There are many of them though usually you will need only about 20-30 functions for even a complex 3D game.
Note that the implementation of the _3D class functions is inside the 3dstate8.dll

2.2) Add:     using   _3dstate;
Adding the _3dstate namespace allows us to call the _3D class function without needing to write _3dstate each time we want to access a function.

2.3) Put the 3dstate8.dll and the D3DX9_41.dll in the folder of the program exe file 
When we will run our program it will automatically look for the 3dstate8.dll (3DSTATE 3D Engine) and the D3DX9_41.dll (DirectX implementation)  therefore we need to put the DLLs somewhere where our program can find them.
We can put them in the same forlder where we have the program exe file or we can put them inside the Windows folder (usually "C:\Windows" ...)

2.4) Allow unsafe code
The 3dstate 3D engine is a win32 DLL therefore we need to allow unsafe code

It doesn't mean that it is not safe ... only that win32 dlls are not .NET managed code

To allow unsafe code right click on your project->properties->Build Tab


Step 3 - Add the FormClosing and Load events

Open the Form (double click on Form1.cs) , open the properties window -> Events
Double click on the Load event and on the FormClosing events
Now you should have two empty functions.

Let's add the following code to the Form1_Load function

   Click on the code to enlarge

The code above does two things.
I) It loads the 3D world file and its bitmaps/jpg files

We can edit this world in 3D graphics editors such as 3D Editor (www.3d1.org)
or WorldBuilder (www.3dstate.com) or we can use 3D Studio MAX or other applications and export any 3D world to 3dstate file format ( Max=>3DS=>3dstate)

Note that we dont have to load the world on the Form1_Load event

We can load the world whenever we want to.

II) It creates a timer that will call the function timer_Tick() constantly
In step 5 we will explain the purpose of the timer_Tick() function.


Let's add the code for the FormClosing() function
Click on the code to enlarge







Step 4 - Add a pictureBox control to the form.

4.1) Add a pictureBox control to the form.
We will render (put the 3D image) on this control.

Note that we can also use other controls such as buttons, the form itself, etc.

4.2) Anchor the pictureBox control to the Form.
On the properties of the control select the Anchor property and mark all 4 sides i.e Top, Bottom, Left, Right.
Anchoring all 4 sides ensures that when the window is resized the pictureBox control will also be resized.
Of course if you want the rendering image to be a "fixed size" then you can skip this step and stick with the default anchoring (Top, Left)

Step 5 - Add the timer function

The timer is used for redoing the rendering process over and over so that changes that occur in the world (such as 3D objects that move or the camera/eye changes its location/direction) will be reflected on the screen (our pictureBox)

We can also use the timer function to move objects inside the world or to move the point of view (camera) as done in our simple example.
Click on the code to enlarge










In our example the image taken by the camera is rendered on the pictureBox control, then the camera is turned a bit (by 0.4 degrees)
When the camera is turned, the image seen by the camera is slightly different.
The next time that the timer function will be called it will render this slightly changed image into our pictureBox control.

Since the timer function is called around 100 times a second (depending on your computer speed) it will create the elusion of smooth movement (though we actually have discreet movement with 0.4 degrees gaps)


Advanced: Some more words about the timer
Note that the .NET has 3 different timers.
We use System.Windows.Forms.Timer
(the others are System.Timers.Timer and System.Threading.Timer)

The Windows.Forms.Timer is pefect for our needs. Note the following:
1) The timer works from the UI thread (User-Interface thread)
the same as the rest of the application.

2) The timer is called the same way any other event is called.
The timer tick events are inserted into the Window message queue together with all the rest of the events (button click, window resized etc).

3) If your program is busy doing something while it is time for a new timer call, the timer call will wait till your program reaches idle time. Then the UI thread will process all the messages in the application's Windows message queue including the timer tick events.

4) Note that we set the timer to tick every one milli second. This is a lot faster then what is actually possible since one rendering usually takes around 0.01 of a second.
This causes no problems. The timer function will be called as many times as the program is able to do (around 100 times per second)  and not as set by timer.Interval.


-- End --

1 comment:

  1. Click here to download the code doesn't exist on the site mentioned.
    Can you Sir please post the code
    Thank you

    ReplyDelete