Ogre implements tianlong terrain

Source: Internet
Author: User
Tags case statement gety

Post from http://www.cnblogs.com/syqking/archive/2009/10/20/1586993.html

Let's get down to the point:

  • Read the. scene file
  • Read the. Terrain file according to <terrain>
  • <Tilesize> (<tilesize>) terrain size (xsize, ysize), scaling value (<scale>), and Map Center Coordinate (<center> ).
  • Read all the terrain maps to use (<textures> ).
  • Read the. gridinfo file, which contains the texture coordinates of each grid.
  • Based on step 3, 4, and step 5, create a terrain with the modified SMS. (Note: You can also use the self-built vertex cache and index cache to specify the texture method)
  • Read lightmap, which is a pre-processed scene shadow graph in PNG format.
  • Read various models in the scenario and insert them to the scenario root.

The following describes how to implement the scenario demo of tianlong Babu.

Read height chart

First, you must read the height chart. The height chart of tianlong Babu is saved in. in the heightmap file, the read method is to skip the first eight bytes (the first eight bytes are version information), read the width and height of the terrain, and then read the width * Height float data, as mentioned above. the terrain file contains the terrain size (xsize, ysize), scaling value (<scale>), and map center coordinates (<center> ), <scale> there are three XYZ values (generally 100,100,100), which are the amplification coefficients of X, Y, and Z axes, directly use the read float data as the height chart data, and then use the above values as parameters to define the terrain size, scaling value, and offset.

This is the code for reading the height chart. heightmapdata is a float array that stores the original height chart information.

void TileTerrainInfo::LoadHightMap( const char* fileName, const char* type ){    FILE* pf = fopen( fileName, "rb" );    fseek( pf, 8, SEEK_SET );    int height, width;    fread( &width, 4,1, pf );    fread( &height, 4,1, pf );    assert( height = this->height+1 );    assert( width == this->width+1 );    if( heightMapData )        delete []heightMapData;        heightMapData = new float[height*width];    for( int i = 0; i < height; ++i )    {        for( int j  = 0; j < width; ++j )        {            float data;            fread( &data, 4,1,pf );            heightMapData[i*width+j] = data;        }        }    fclose( pf );}
 

Material File Analysis

I want to talk about the terrain materials first, because we need to know how to use other people's resources first, in general, material information can clearly reflect how to use texture resources (it is not ruled out that it is possible to use code to dynamically generate materials ).

At the bottom of each. Terrain file, there is such content.

<Materials>
<Template material = "Terrain/onelayer" name = "onelayer"/>
<Template material = "Terrain/onelayerlightmap" name = "onelayerlightmap"/>
<Template material = "Terrain/twolayer" name = "twolayer"/>
<Template material = "Terrain/twolayerlightmap" name = "twolayerlightmap"/>
<Fog_replacement exp = "Terrain/onelayer_ps % fog_exp" exp2 = "Terrain/onelayer_ps % fog_exp2" Linear = "Terrain/train % fog_linear" None = "Terrain/train"/>
<Fog_replacement exp = "Terrain/twolayer_ps % fog_exp" exp2 = "Terrain/twolayer_ps % fog_exp2" Linear = "Terrain/train % fog_linear" None = "Terrain/train"/>
<Fog_replacement exp = "Terrain/onelayerlightmap_ps % fog_exp" exp2 = "Terrain/onelayerlightmap_ps % fog_exp2" Linear = "Terrain/logs % fog_linear" None = "Terrain/logs
<Fog_replacement exp = "Terrain/twolayerlightmap_ps % fog_exp" exp2 = "Terrain/twolayerlightmap_ps % fog_exp2" Linear = "Terrain/logs % fog_linear" None = "Terrain/logs
</Materials>

Some material templates are defined.

I did not go into other aspects. I only considered the twolayerlightmap material.

Do not remember which folder there is a file named fairyterrain. material, which is the texture of the terrain.

I modified some content and set <lightmap> tex_coord = 0. <layer0> tex_coord = 1, and <layer1> tex_coord = 2. This is because I want to make the original terrain of the text map coexist with the terrain of the arms, and the texture coordinates of the original terrain are exactly the same as those of the <lightmap> texture coordinates, so they are set to the same layer.

This is the material I changed.

Material Terrain/twolayerlightmap
{

Technique
{
Pass
{
Fragment_program_ref Terrain/twolayerlightmap_ps
{
}

Texture_unit
{
Texture_alias <layer0>
Texture <layer0>
Tex_address_mode clamp
Tex_coord_set 1
}

Texture_unit
{
Texture_alias <layer1>
Texture <layer1>
Tex_address_mode clamp
Tex_coord_set 2
}

Texture_unit
{
Texture_alias <lightmap>
Texture <lightmap>
Tex_address_mode clamp
Tex_coord_set 0

}
}
}

}

<Layer0>, <layer1>, <lightmap> is the three texture_unit in a pass, that is, the layer-3 texture. As the name suggests, <layer0> is the first layer of texture, <layer1> is the second layer of texture, and <lightmap> is the light image texture (Shadow). How to use it, how to map the terrain map resources of tianlong Babu to layer0 and layer1 will be discussed below.

We can find the corresponding shader from fairyterrain. CG.
Void twolayerlightmap_ps (
In float2 uv0: texcoord0,
In float2 uv1: texcoord1,
In float2 uvlightmap: texcoord2,
In Uniform sampler2d layer0,
In Uniform sampler2d layer1,
In Uniform sampler2d lightmap,
In float4 diffuse: color0,
In float4 specular: color1,
Out float4 ocolour: color)
{
Float4 C0 = tex2d (layer0, uv0 );
Float4 C1 = tex2d (layer1, uv1 );
Float3 texturedcolour = lerp (c0.rgb, c1.rgb, c1.a );
Float4 lightmapcolour = tex2d (lightmap, uvlightmap );
Float4 basecolour = diffuse * lightmapcolour;
Float3 finalcolour = basecolour. RGB * texturedcolour + specular. RGB * (1-c0.a) * (1-c1.a) * lightmapcolour.;
Float3 resultcolour = fogging (finalcolour );
Ocolour = float4 (finalcolour, basecolour. );
}

It is easy to see that the general idea is to mix the Alpha Value Control <layer0> and <layer1> of <layer1>.

It can be seen that the terrain of tianlong Babu is part of the grid-like terrain like Warcraft, part of the weight map terrain, that is, the original texture mode of the text map, with many layers of texture, then, the texture data manually generated by 1-2 layers controls the Alpha value of each layer texture to achieve the mixed effect, except that there is only one alpha channel to control texture mixing.

The effect of two layers of texture is much better than that of a single layer of texture. I tried it with onelayerlightmap. The effect is quite remarkable...

Implementation of terrain texture

<Lightmap> The texture is obvious. It is a whole texture attached to the entire terrain, and there is nothing to say.

But how should I mount the <layer0> <layer1> texture of the two layers?

There are two possibilities for the two textures in the material.

1. <layer0>, <layer1> is only the name of the texture in the material template. It has no practical significance. In the actual program, a template is inherited from the material template for each terrain, then, modify the name of the texture in the material.

2. manually create <layer0> and <layer1> in the program.

There are two methods that cannot be implemented:

1. manually create <layer0> and <layer1> In the program. For a very large texture (as big as the real terrain), the texture is based on. terrain and. similar to lightmap, the information in gridinfo is pasted on the terrain.

In a small game, only one terrain that may be as big as a screen can be used, and the effect may be good, but it is impossible in a game with relatively large terrain. First of all, A huge waste of resources. The texture of a floor tile may be used dozens of times or hundreds of times. In this large texture, there will be several hundred copies of the floor tile texture. Secondly, it is impossible to create such a large texture (not supported by hardware? I tried not to create it ..)

2. like the image watermark, all the textures used (assuming n images exist) are placed as texture_unit one by one in the material, then, use N/4 manually generated textures to control the Alpha values of these textures. This method is not very realistic for the terrain of tianlong Babu. Generally, the terrain of tianlong Babu has about a dozen different textures. If this method is used, each pass generally supports 8 texture_unit, more than a dozen textures, plus N/4 Texture Control requires 3-4 pass, the efficiency seems to be... in addition, we can see from the tianlong Material file that the game should not be implemented using this method.

3. each lattice has its own material. Modify <layer0> and <layer1> in each lattice material to the desired material file, for example, "05 Wudang/brown land bottom layer .jpg" is equivalent to using each grid as a separate mesh. This can be achieved. I tried to set the tilesize of the image watermark to 1, and then modify the material when generating each tile. The terrain is displayed successfully, which is completely correct, but the frame rate ..... in debug mode, FPS is greater than 0 and less than 1... it may take more than a dozen times to get to release. I didn't try it. Obviously, it cannot be done like this...

I used texture Atlas to create a texture. I used texture Atlas to combine all the terrain textures I needed into a large texture, and then set each vertex Based on the UV coordinates of the large texture, the reason why texture Atlas is better than each lattice is obvious. For details, refer to the article in the attachment, "batch, batch, batch:" What does it really mean?" Page 30th: Batch breaker: texture change.

That is

<Textures>

<Textures>

<Texture filename = "03 Nanhai/ 01.jpg" type = "image"/>

<Texture filename = "03 Nanhai/ 03.jpg" type = "image"/>

<Texture filename = "05 Wudang/brown land bottom layer .jpg" type = "image"/>

<Texture filename = "05 Wudang/brown land upper layer. TGA" type = "image"/>

<Texture filename = "05 Wudang/Blue Brick ground bottom layer. TGA" type = "image"/>

<Texture filename = "13 Jinghu/Jinghu peach petals. TGA" type = "image"/>

......

</Textures>

A large texture that combines all the defined textures.

It can be found that the terrain textures in tianlong Babu are different in size, but the maximum is 256x256 (as far as I know), So I simply divide each grid into 256x256, A total of row_sizexcol_size small textures can be accommodated, so the size of the large texture should be 256 * col_size x 256 * row_size.

The maximum texture size supported by my machine seems to be 4096x4096, So theoretically it is more than enough to accommodate 16*16 small textures. In this way, although a little space is wasted, you can easily index the texture coordinates by ID.

For example, <pixmap Bottom = "0.2480469" Left = "0.00390625" Right = "0.4960938" textureid = "2" Top = "0.001953125"/> using this pixmap definition, we can find the location of textureid = 2.

Its behavior is textureid/col_size, and its column is textureid % col_size. For example, the cole_size of the above large texture is 8 (a row contains 8 small textures)

So the row where this small texture of textureid = 2 is located is ROW = 0, and the row is sitting in column Col = 2.

We know that the texture coordinate range is 0.0f-1.0f, so the UV coordinate in the upper left corner of the textureid = 2 is u = (float) COL/col_size = 0.25f, V = (float) row/row_size = 0.0f.

Then, based on the left, right, top, and bottom information in pixmap, the coordinates of the four points of the small map can be calculated. Attach the texture coordinates when creating the vertex.

The specific process should be

1. manually create texture named <layer0>

The Code is as follows:

Textureptr layer0 = texturemanager: getsingletonptr ()-> createmanual (
"<Layer0>", "General", tex_type_2d,
Layertexturewidth, layertextureheight, 1, 3, pf_byte_rgba, tu_write_only );

2. change texture_name in texture_unit <layer1> from <layer1> to <layer0>. Because the two layers use the same texture, there is no need to copy it again, you just need to change the name to point to the same texture.

The Code is as follows:

Materialptr material (materialmanager: getsingleton (). getbyname ("Terrain/twolayerlightmap "));
Material-> gettechnique (0)-> getpass (0)-> gettextureunitstate (1)-> settexturename ("<layer0> ");

3. Read the. Texture file and splice the texture to be used into a large texture, as shown in the figure above.

Terrain vertices and Indexes

If the map is 192x192, it should have 192*192 grids. In general, it should have 193*193 vertices and be woven into a mesh, but because of the atlas,

We can know that each non-edge vertex will have four texture coordinates (top left, top right, bottom left, bottom right)

For example

The vertex in the middle is responsible for both the lower right of block A, the lower left of Block B, the upper right of Block C, and the upper left of block D.

To say that a vertex does have multiple texture coordinates at the same time, you only need to set different tex_coord. However, tianlong Babu Terrain Maps generally have three layers: <layer0>, <layer1>, and <lightmap>, which are two layers of terrain and one layer of preprocessing shadow.

A layer of <lightmap> is a large texture. The coordinates of each vertex are u = COL/terraincolsize, V = row/terrainrowsize.

We need to consider the other two layers, because there are two layers, so that each vertex is responsible for more than four at the same time, but also for eight at the same time, so that the eight texture_units of this pass are full, A pass must be used for the <lightmap> layer, which is inefficient.

So we have to use another method, that is, to combine the four vertices at every position without edges. The texture coordinates of these four vertices are different, but the positions are the same, that is, each grid has four independent vertices, and the adjacent two grids have two vertices overlapped.

That is to say, a map of 192x192 requires four vertices: 192*192. The indexing method is similar. Each grid requires six indexes, so a total of 192*192*6 indexes are required.

In this way, you need to modify the code for generating vertices and indexes in the text map. The code for generating vertices is in void tile: createvertexdata (size_t startx, size_t startz, the code for generating the index is in void tile: createindexdata.

Tianlong Babu. the terrain file usually has such a line <scale x = "100" Y = "100" z = "100"/>, which means that the terrain is magnified 100 times in three directions, X, Z is the unit of 1x1 in a grid. After amplification, It is 100x100,

The actual size of a 192x192 terrain in the game should be 19200*19200, and the coordinate system of tianlong is the median coordinate. the value of <center> in the terrain file. If it does not exist, the center is (), the positive direction is positive, and the negative direction is negative. Therefore, when the value of <center> is ), the actual coordinate range of the 192x192 terrain should be (-9600,-9600) to (9600,9600 ).

It should be noted that all vertices are regarded as a mesh, but should be based on. the <tilesize> in the terrain file specifies the size of each terraintile. Each terraintile contains tilesize x tilesize terrain mesh, and a terraintile is inserted as an entity to a scene node.

After considering the vertex position and index, we need to consider the texture coordinates of each vertex.

The. gridinfo file must be used to set UV for each vertex. This file defines the texture information corresponding to each grid.

For details about the file format, I will not go into details here.

Http://www.cppblog.com/mybios/archive/2009/07/26/91267.html

This is a positive solution. It seems that there are more or less errors in other places. Especially when op is set to 8, note that the two points on the two sides of the diagonal line (not on the diagonal line) are copied from the top to the bottom.

1. Copy the vertices texture coordinates in the upper left corner to the lower right corner.

Figure 2 copies the texture coordinates in the upper-right corner to the lower-left corner.

Figure 1 Figure 2

But there is another difference. When op = 4, I think it should be a clockwise turn of 90 degrees. It seems that there is no problem after testing.

This is my code for operating UV coordinates based on Op. When op = 4, it seems that I am actually turning clockwise ......

Void changegridinfouv (autotexcoord & lefttop, autotexcoord & righttop, autotexcoord & leftbottom, autotexcoord & rightbottom, uchar state, bool bindex) {// 0 unchanged // 1 picture horizontal flip // 2 picture vertical flip // 4 clockwise rotation // The texture coordinate of the top vertex of the 8 diagonal line is copied to the vertex below the diagonal line. (Two vertices perpendicular to the diagonal line) uchar RES1 = State & 1; uchar RES2 = State & 2; uchar RES3 = State & 4; uchar res4 = State & 8; If (RES1! = 0) {lefttop. Exchange (righttop); leftbottom. Exchange (rightbottom);} If (RES2! = 0) {lefttop. Exchange (leftbottom); righttop. Exchange (rightbottom);} If (RES3! = 0) {lefttop. Exchange (righttop); leftbottom. Exchange (righttop); rightbottom. Exchange (righttop);} If (res4! = 0) {// abnormal index if (bindex) {(leftbottom. setx (righttop. getx); leftbottom. sety (righttop. gety ();} // else {rightbottom. setx (lefttop. getx (); rightbottom. sety (lefttop. gety ());}}}
Read scenario environment and Model

In the first phase, I read some scenarios, including the environment, models, particles, and so on, but this scenario is incomplete, but the rough outlines have all come out.

The reading scenario is actually to use tinyxml to read various XML items in. scene, and then create corresponding scenario Nodes Based on the read data, or set the corresponding scenario environment, such as fog and skydome.
Download the attachment for specific code. It's boring. It's a switch-case statement.
Note that you must call a function before reading the resource.
setlocale( LC_CTYPE, "" );
Otherwise, the. Mesh file of the Chinese path or file name cannot be read.
The terrain and scenario are all done. Now let's take a look at the results! However, the tragedy has emerged!
Obviously, the terrain is like cracks ......

Close, close, there will be no cracks in the terrain ......

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.