Introduction:
Geographical Information System (GIS) is a system for Map Display through a computer system. Allows users to access, display, and analyze geographical data. Because most people do not know GIS, several large companies in the IT market often monopolize the industry, such as Intergraph, Bentley, Mapinfo, Autodesk, and ESRI. Today, Microsoft, a global IT monopoly, google and Oracle are competing to build a virtual Earth system project, Google Earth and Oracle spatial. NASA has also released a new version. The Open Source GIS browsing software is called World Wind.
Here, I will explain how to create an independent 3D terrain display tool, which will be developed using C # and managed DirectX 9.0c. This program allows users to rotate the viewing angle and switch to three refresh modes: Point, grid, and smooth surface.
Background:
I recently completed a city-level GIS system. In this project, I developed a set of software ideas. To demonstrate this technology, I used some photos taken in the air as the texture of the terrain. The purpose is to share experiences with all developers who develop GIS Using. net.
Running Conditions:
Before the program starts, I first understand the Running Conditions of the program:
Visual Studio. net ide (I am using 2005 beta 2)
Managed DirectX 9.0c SDK (I used August 2005 update)
. NET Framework (I use V2.0 but it will run better in V1.1)
3D refresh method:
First, let's talk about the design ideas of general 3D programs. Sorry, I cannot give a complete explanation or add comments to each line of code, but I can explain some ideas.
In order to display any 3D terrain model, some grid data of the terrain is required. These data contain coordinate points marked by X, Y, and Z. What is very important is the storage of Z values, in the left-hand coordinate system used by DirectX (if you want to learn more coordinate systems, you can search for them online ). I set a grid range of 79x88, which is the storage method of my terrain data. You can also change it as needed. Similarly, my data uses a 20 m solution, which means that the actual distance between two adjacent points is 20 m.
Once you import coordinates of all the terrain, you will generate a terrain model. This model is composed of a series of triangles. Therefore, the rendering of a few graphics cards is completed by the program. There are very effective calculation methods, such as roam or plod (later encapsulated in DirectX 9). These and other familiar algorithms are used to solve the problem of triangular surface rendering number determined by distance. The other method is to reduce the number of triangular surfaces with low detail density. We reserve the number of triangular surfaces for the parts with high detail density. I will not use these algorithms here, but you need to understand and understand their usage.
Finally, textures are used to provide more realistic effects. Texture uses its own coordinate system, which is at the top to the left and at the bottom to the right. Any texture point in this range ).
As an exercise, you can further deepen the details, such as adding sky boxes, lights, shadows, and physical effects, such as collision detection. Managed DirectX also includes directplay and directsound support and advanced network functions and sound APIs. Expand your imagination and the sky is infinite.
Using system;
Using system. drawing;
Using system. collections;
Using system. componentmodel;
Using system. Windows. forms;
Using system. Data;
Using system. IO;
Using Microsoft. DirectX;
Using Microsoft. DirectX. direct3d;
Using Microsoft. DirectX. directinput;
Then we declare the length and width of the mesh, display and keyboard devices, vertex buffering and index buffering, textures, vertex and triangle structures, and some other variables.
Private int grid_width = 79; // grid width
Private int grid_height = 88; // grid height
Private Microsoft. DirectX. direct3d. device = NULL; // device object
Private Microsoft. DirectX. directinput. device keyb = NULL; // keyboard
Private float anglez = 0f; // POV Z
Private float anglex = 0f; // POV x
Private float [,] heightdata; // array storing our height data
Private int [] indices; // indices Array
Private indexbuffer IB = NULL;
Private vertexbuffer VB = NULL;
Private texture Tex = NULL;
// Points (vertices)
Public struct dvertex
{
Public float X;
Public float y;
Public float Z;
}
// Created triangles, VV # Are the vertex pointers
Public struct dtriangle
{
Public long vv0;
Public long vv1;
Public long vv2;
}
Private system. componentmodel. Container components = NULL;
Now you are ready to load the direct3d device object:
// Define parameters for our device object
Presentparameters presentparams = new presentparameters ();
Presentparams. incluwed = true;
Presentparams. swapeffect = swapeffect. Discard;
Presentparams. enableautodepthstencel = true;
Presentparams. autodepthstencilformat = depthformat. D16;
// Declare the device object
Device = new Microsoft. DirectX. direct3d. Device (0,
Microsoft. DirectX. direct3d. devicetype. Hardware, this,
Createflags. softwarevertexprocessing, presentparams );
Device. renderstate. fillmode = fillmode. Solid;
Device. renderstate. cullmode = cull. None;
// Hook the device reset event
Device. devicereset + = new eventhandler (this. ondevicereset );
This. ondevicereset (device, null );
This. Resize + = new eventhandler (this. onresize );
You can see that I call ondevicereset, which is called every hour when the user rechanges the window. Our vertex data is stored in the vertex buffer.
// Create vertexbuffer to store the points
VB = new vertexbuffer (typeof (customvertex. positiontextured ),
Grid_width * grid_height, device, usage. Dynamic | usage. writeonly,
Customvertex. positiontextured. format, pool. Default );
VB. Created + = new eventhandler (this. onvertexbuffercreate );
Onvertexbuffercreate (VB, null );
Then we need to create an index buffer to store all the triangle data in it. The index buffer accesses the vertex data through the index:
IB = new indexbuffer (typeof (INT), (grid_width-1 )*
(Grid_height-1) * 6, device, usage. writeonly, pool. Default );
Ib. Created + = new eventhandler (this. onindexbuffercreate );
Onindexbuffercreate (IB, null );
Also pay attention to initialiseindices () and loadheightdata () functions in the source code attached, where we load and "triangulate" our data. Next, we initialise the keyboard device:
Note that the initialiseindices () and loadheightdata () functions are loaded to Triangle talk data, and the keyboard device is finally loaded:
Public void initialisekeyboard ()
{
Keyb = new Microsoft. DirectX. directinput. Device (systemguid. keyboard );
Keyb. setcooperativelevel (this, cooperativelevelflags. Background |
Cooperativelevelflags. nonexclusive );
Keyb. Acquire ();
}
Then place the camera:
Private void camerapositioning ()
{
Device. Transform. Projection =
Matrix. perspectivefovlh (float) math. PI/4,
This. width/This. Height, 1f, 350f );
Device. Transform. view =
Matrix. lookatlh (New vector3 (0,-70,-35), new vector3 (0,-5, 0 ),
New vector3 (0, 1, 0 ));
Device. renderstate. Lighting = false;
Device. renderstate. cullmode = cull. None;
}
It takes a small step to add the refresh code to onpaint:
Protected override void onpaint (system. Windows. Forms. painteventargs E)
{
Device. Clear (clearflags. Target | clearflags. zbuffer, color. lightblue, 1.0f, 0 );
// Set the camera position
Camerapositioning ();
// Draw the scene
Device. beginscene ();
Device. settexture (0, Tex );
Device. vertexformat = customvertex. positiontextured. format;
Device. setstreamsource (0, VB, 0 );
Device. Indices = Ib;
Device. Transform. World =
Matrix. Translation (-grid_width/2,-grid_height/2, 0 )*
Matrix. rotationz (anglez) * matrix. rotationx (anglex );
Device. drawindexedprimitives (primitivetype. trianglelist, 0, 0, grid_width *
Grid_height, 0, indices. Length/3 );
Device. endscene ();
Device. Present ();
This. invalidate ();
Readkeyboard ();
}
Finally, write the main process:
Static void main ()
{
Using (winform directx_form = new winform ())
{
Directx_form.loadheightdata ();
Directx_form.initialiseindices ();
Directx_form.initialisedevice ();
Directx_form.initialisekeyboard ();
Directx_form.camerapositioning ();
Directx_form.show ();
Application. Run (directx_form );
}
}
Compile and run now. You will see a rendered terrain. Use arrows to control the direction and P, W, and s to switch the rendering mode: Point, network cable, and smooth.
Notes:
You need to pay attention to the resource consumption problem of 3D rendering, so that a small detail and special effects can cause performance degradation and bring about a few days of pain. However, once you solve the problem, you will be gratified. I recommend that you search for solutions to these problems over the Internet. Some people have already solved what you want to do, and have created documents better. If you are lucky, you will also get a step-by-step tutorial and the original code, which will help you solve the problem.