Managed DirectX (Chapter 5)

xiaoxiao2021-03-06  15

Define Mesh

Although there are many times, you need to manually create vertices and index data, but more common situations are from external resources, such as from a file. Usually we use the .x file to save this information. In the previous chapter, most of the code is used to create geometries. For simple triangles and cubes, this seems to be completely feasible, but imagines that the time and effort spent in the same way, the time and efforts taken will be terrible.

Fortunately, there is an object that can be packaged and loaded with vertices and index data in Managed DirectX. This is

Mesh. Mesh can be used to store any type of graphical data, but mainly used to encapsulate complex models. The Mesh class also has some methods used to improve rendering object performance. All Mesh objects contain a vertex buffer and an index cache, in addition to this, he also contains one

Attribute Buffer - We will discuss it behind this chapter.

The real Mesh object is in the Direct3D extension (D3DX Direct3D Extensions Library). Add a reference to the Direct3dx.dll assembly, we will try to use Mesh to create a rotating cube. First, add Mesh members before declaring vertex buffer and index buffer:

PRIVATE MESH MESH = NULL;

The Mesh class has three constructor, but now it is not required to use any one of them. There are several static methods for the Mesh class to create or load different models. First, you need to pay attention to the "box" method, just like its name, it will create Mesh that contains a cube. Think about it, we can render this cube right, just perfect ^ _ ^ (Note: Oh, you can delete all the code related to the vertex buffer, index buffer). Add the following code after creating Device:

Mesh = Mesh.box (Device, 2.0F, 2.0F, 2.0F);

This method creates a mesh containing vertices and indexes, and can be rendered as a cube with a length, width, and high. It is the same as the cube size created by the vertex buffer manual. We have reduced the code of the created object to a line, and it can't be simple. Although Mesh has been created, can I render it with the original way, still need another way? Previously, when rendering, we need to call SetStreamSource to tell which of which top buffering data from Direct3D must also set an index and attributes in the vertex format. These are unwanted for rendering mesh.

(Tips: MESH has built-in all vertex buffers, index buffers, and valued information. Attributes of Stream Source, Index, and Vertex Formats are automatically set up when rendering

So how do you render mesh? Mesh will be divided into a series of subsets (allocated in accordance with the size of the property buffer), and use a method called "DrawSubset" to render. Modify the Drawbox method:

Private void Drawbox (Float Yaw, Float Pitch, Float Roll, Float X, Float Y, Float Z)

{

Angle = 0.01F;

Device.Transform.World = (Matrix.Rotationyawpitchroll (YAW, Pitch, Roll) *

Matrix.Translation (X, Y, Z));

Mesh.drawsubset (0);

}

Here, the DeawIndexedPrimitives method is changed to DrawSubset. Normal elements created using the Mesh class always only one subset of 0-based subsets. Ok, this is to let the program run again all the changes, unexpected simple. Run a look. Well, a box of nine (12 in the source code) again, but all changes to white pair? Observe the vertex format of the Mesh's top point (can be viewed through the VertexFormat property of Mesh), and you will find that only the position of the vertex and the normal data are stored in Mesh. There is no data on color in Mesh, and the light is also open, and everything is white.

I still remember that the first mentioned, as long as the vertex data contains the information of the normal, you can use the lights, since there is a normal data, maybe we should open the light. By default, the light is open, and now you can delete the code that turns off the light or set to True.

Oh, we successfully change the white box to black -.- #. I hope that you have already guessed this because there is no light source in the scene, so everything is black. For specifying a specific source, create a light that can illuminate the entire scene will be very good. Welcome to

Ambient Lighting.

The ambient light provides a web source for the scene. All objects in the scene are illuminated in the same manner because the ambient light does not depend on factors (such as position, direction, attenuation). There is no need to use the normal data to use ambient light. The ambient light is the most efficient light type, but it cannot create a true "world". But now, he can achieve our satisfaction. Add the following code to the place where RenDrState is set:

Device.renderstate.Ambient = color.red;

The ambient light is completely defined by the Ambient Render State, accepts a color parameter. Here, we hope that the global light is red, so you can see the obvious effect. Run the program, you want to see 9 red rotating boxes, unfortunately, they are still black. What are you still missing?

Use material and lighting (Using Materials and Lighting)

What is the difference between using the lights we used to use? The biggest difference (except for the use of Mesh), there is no information about the color in the vertex number beads. This caused the light failure.

In order to make Direct 3D correctly calculate the color of the specific point in the 3D object, in addition to the color of the light, it is necessary to know how the object reflects the color of the light. In the real world, if the red light is on the light blue surface, then it will present soft purple. You also need to describe how our "surface" is reflective.

In Direct 3D,

Materials describes this property. You can specify how objects reflect ambient light and scattering (SPECUSE) light (Specular Highlights) (will discuss it), as well as the object is completely reflected (EMIT) light. Add the following code to DrawBox (before the DrawSubset method):

Material boxmaterial = new material ();

BoxMaterial.Ambient = color.white;

Boxmare.diffuse = color.white;

Device.material = boxmaterial; create a new material here, it

Ambient Color (Note: The color of the ambient color and the ambient light is different, and the scatter color value is set to white. Use white to refer to it reflects all light. Next, we give the material to the Device's Material property, so Direct3D knows that material data is used when rendering.

Run the program, you can now see the correct result. Modifying the color of the ambient light can change the color of all boxes. Modify the environment color elements of the material can change the light how to illuminate objects (Note: I don't have good listening to optical classes, 555 ~~, MAYA full manual: Ambient color, when it is black, Indicates that (ambient light) does not affect the color of the material, when the color is shallow, it will illuminate the material, and mix the two colors, which affect the color of the material. How to have ambient light in the scene, then these lights The color and brightness control the degree of environmental effect on the final material color). Change the material with no red ingredients (such as green) will make the object again become black (Note: because the object does not reflect red, the red light is absorbed by the object, and the color containing some red ingredients (Such as gray gray) will make the object deep gray.

I said before, the object to rendering this way will not be too real. Even if you can't see the "chamfer" of each cube, it seems to be the same as some red cubic cubes. This is because the ambient light calculates all vertices in the same way. We need a real point light, add the following code after creating ambient light:

Device.lights [0] .type = lightttype.directional;

Device.lights [0] .diffuse = color.white;

Device.lights [0] .direction = new vector3 (0, -1, -1);

Device.lights [0] .Commit ();

Device.lights [0] .enabled = true;

Here, a white direction is created, which is the same as the camera. It can now be seen in different directions.

When you create mesh, a series of objects can be used. Use one of the following methods to create Mesh (these methods require Device as the first parameter):

(The following uses the left hand coordinate system)

Mesh = Mesh.box (Device, 2.0F, 2.0F, 2.0F);

Width, Height, Depth represents the size of the box on x, y, z-axis, respectively

Mesh = Mesh.Cylinder (Device, 2.0F, 2.0F, 2.0F, 36, 36);

RADIUS1, RADIUS2 represents the lower bottom surface of the cylinder and the upper bottom radius must be non-negative; the length represents the height of the cylinder in the Z direction; STACKS represents the number of "stacks) along the main shaft. (Note: Similar to the number of blocks in the horizontal and vertical directions divided by the weft

Mesh = Mesh.Polygon (Device, 2.0F, 8);

Length represents the length of each side of the polygon, SIDES said how many edges

Mesh = Mesh.Sphere (Device, 2.0F, 36, 36);

Radius represents the radius of the sphere, the meaning of SLICES and STACks is the same as Cylinder. Mesh = Mesh.torus (Device, 0.5F, 2.0F, 36, 18)

The innerradius rings, the outer diameter of the Outterradius ring, the number of faces on the SIDES cross section, the number of rings on the rings cross section, the first two values ​​must be non-negative numbers, and the latter two must be greater than equal to three.

Mesh = Mesh.Teapot (Device)

Create a teapot (for a teapot, you don't have a mistake ^ _ ^).

Each of the above methods has a heavy load that returns the Adjacency Information. Each face is used as a 阾 信息 信息, specifies the three faces of the phase (Adjacency Information IS Returned As Three Integers) Per Face That Specify The Three Neighbors of Each Face In The Mesh).

Use a Mesh rendering complex model

Although the teapot is rendered is very interesting, it is impossible to render the teapot in the game. A large number of Mesh is created by artists using professional modeling software. If your modeling software can export .x files so congratulations, you are fortunate (Direct SDK contains the export converter of common modeling software).

Mesh can be created by loading several data types stored in the x file. Of course, vertices and index data are the most basic requirements for rendering objects. Each subset of Mesh will be associated with a material. Each material group can also contain texture information. You can also create Mesh using the X file and the High Level Shader Language (HLSL) file. HLSL is a high-level technology, we will discuss in depth in the content behind.

Like the Static method of creating a "simple" Tura type, the Mesh class has two main static methods to load external models. These two methods are Mesh.Formfile and Mesh.Fromstream. The two methods are in nature, and the Stream method has more overloaded to accommodate different sizes. The most commonly used overloading method is as follows:

Public Static Mesh fromfile (String FileName, Meshflags Options, Device Device, Out GraphicsStream Adjacency, Out ExtendededMaRial Materials, Out EffectInstance Effects);

Public Static Mesh fromstream (Stream Street, Int ReadBytes, Meshflags Options, Device Device, Out Graphicsstream Adjacency, Out ExtendedMaterial Effects);

The first parameter is a data source that is loaded as Mesh. For the fromfile method, he is the file name to be loaded; for the fromstream method, it is the stream used and the number of data bytes to read. If you use the entire stream, you can use the overload without ReadBytes parameters. The Meshflags parameter controls where and how to load data. The value of this parameter can be combined by the following values:

Mesh flags enumeration value

Parameter Value

Meshflags.donotclip Use the usage.donotclip flag for vertex and index buffers.

Meshflags.dynamic equivalent to use both ibdynamic and vbdynamic.meshflags.Ibdynamicuse usage.dynamic for index buffers.

Meshflags.ibmanaged use the pool.managed memory store for index buffers.

Meshflags.ibsoftware processinguse the usage.softwareprocessing flag for index buffers.

Meshflags.ibsystemMem Use the pool.systemMemory Memory pool for index buffers.

Meshflags.ibwriteonly use the usage.writeonly flag for index buffers.

Meshflags.vbdynamic use usage.dynamic for vertex buffers.

Meshflags.vbmanaged use the pool.managed memory store for vertex buffers.

Meshflags.vbsoftwareProcessing Use the usage.softwareProcessing flag for vertex buffers.

Meshflags.vbsystemMem Use the pool.systemMemory Memory pool for vertex buffers.

Meshflags.vbwriteonly use the usage.writeonly flag for verpex buffers.

Meshflags.Managed Equivalent to use baoth ibManaged and vbmanaged.

..

Meshflags.Points Use the usage.points flag forboth index and vertex buffers.

Meshflags.rtpatches Use the usage.rtpatches flag for Both index and vertex buffers.

Meshflags.SoftwareProcessing Equivalent to use Both ibsoftwareProcessing and vbsoftwareProcessing.

Meshflags.SystemMemory Equivalent to use Both ibsystemmem and vbsystemmem.

................................

The next parameter is the device that renders Mesh. Because resources must be associated into a device, this is a must-select parameter. The Adjacency parameter is a "out" parameter, which means that Adjacency will be assigned and passed after this method, which will return information. The ExtendedMaterial class saves a normal Direct3D material and a string loaded as textured. This string is usually used for the texture or resource file name because the loading texture is made by the program, which can also be a string provided by any user. After the group, the EffectInstance parameter describes the HLSL material files and values ​​for Mesh. Method reloading with different parameters can be selected as needed.

Here, a lot of details about loading and rendering Mesh are discussed, but it is actually not so complicated. At the beginning, you may be a little worried, but after seeing the actual code, it is really simple. try it now. First, make sure there are variable members that can be used to store materials and textures for different subsets. Add the following code after declaring mesh:

Private Material [] Meshmaterials;

PRIVATE TEXTURE [] Meshtextures;

Because there may be many different subsets in Mesh, you need to create an array of materials and textures to meet the needs of each subset. Ok, now to add some methods that really load mesh, create a function called "loadmesh", the code is as follows:

Private void loadmesh (string file)

{

`` `` `` (More code here, see the source code)

}

Ok, although it seems that it is scary than our previous simple work, it is actually not the case. First, we declare an ExtendenMarerial array for saving the Mesh subset information. Then, call the fromfile method to load the Mesh. We don't care about Adjacency or HLSL parameters, so we use the overloading of these two parameters.

After loading Mesh, you need to store material and texture information for a large number of subsets. After determining if there is a different subset, we finally use the size of the subset to allocate the size of the material and texture. Next, use the loop to copy the data in ExteNedMaTerial to Meshmaterials. If the subset contains texture information, use the TextureLoader.FromFile method to create textures. This method accepts two parameters, Device, and file names as textures, this method can be fast than previously used system.drawing.bitmap

a lot of.

To draw Mesh, you need to add the following method:

Private Void Drawmesh (Float Yaw, Float Pitch, Float Roll, Float X, Float Y, Float Z)

{

Angle = 0.01F;

Device.Transform.World = Matrix.RotationYawpitchroll (YAW, Pitch, Roll) * Matrix.Translation (X, Y, Z);

For (int i = 0; i

{

Device.material = meshmaterials [i];

Device.Settexture (0, Meshtextures [i]); Mesh.drawsubset (i);

}

}

You may have noticed that this method retains the signature section of the Drawbox method. Next, in order to draw Mesh, iterate all materials, and perform steps:

1. Give the preserved material to Device;

2. Give the texture to Device. Here, if there is no texture, it will not be wrong even if the value is NULL.

3, call the DrawSubset method according to the idiographic ID

Perfect, now we have completed the load and rendering Mesh. I have made a model called Tiny.x. Add this code to load this model:

this.loadmesh (@ "../../ tiny.x");

It is also necessary to adjust the location of the camera, and should look like an except Tiny except Tiny. Since the model is very large, the camera needs to be returned, modify the following methods:

Device.Transform.Projection = Matrix.PerspectiveFovLH ((float) Math.pi / 4, this.width / this.height, 1.0F, 1000.0F);

Device.Transform.View = Matrix.lookatlh (New Vector3 (0, 580.0F), New Vector3 (), New Vector3 (0, 1, 0));

We rebuilt the distance of the plane after the removal, flat and flat, and the last task is called: in the rendering part call the DrawMesh method:

This.drawmesh (Angle / (Float) Math.pi, Angle / (Float) Math.pi * 2.0F, Angle / (Float) Math.Pi / 4.0F, 0.0F, 0.0F, 0.0F);

Finally, you can also adjust the color of the light.

We have moved forward, this is more interesting to rotate more than always look at the cube.

We have moved forward, this is more interesting to rotate more than always look at the cube.

The next chapter we will use Managed DirectX to write a real game, the most it may look very simple, but after all, it is our first three-dimensional game ^ _ ^, the sixth chapter content comparison, about 3, 4 times Can you translate ^ _ ^.

Can go to this place to download the source code http://bbs.gameres.com/showthread.asp?threadid=24918

转载请注明原文地址:https://www.9cbs.com/read-46603.html

New Post(0)