Tiling a terrain in 3D

Started by
10 comments, last by Bullmax 21 years, 11 months ago
Hello there. I had a problem recently. It is about drawing a terrain with DirectX 8. I am wondering how I could draw a tiled terrain with reused vertices. The problem is the texture coordinates. Let''s say the upper left tile would have these coordinates : (0.0,0.0) (1.0,0.0) *---------* |#########| |#########| |#########| |#########| *---------* (0.0,1.0) (1.0,1.0) The tile at his right would have these coordinates, but from another texture : (0.0,0.0) (1.0,0.0) *---------* |#########| |#########| |#########| |#########| *---------* (0.0,1.0) (1.0,1.0) So, if the tile don''t use the same vertices, it would look like this : (0.0,0.0) (1.0,0.0) (0.0,0.0) (1.0,0.0) *---------* *---------* |#########| |#########| |#########| |#########| |#########| |#########| |#########| |#########| *---------* *---------* (0.0,1.0) (1.0,1.0) (0.0,0.0) (1.0,0.0) But it would be impossible to use the same vertex, no ? If it is ...how ? /* Bullmax */ ------------- Reality has many forms : good and evil, black and white, ying and yang.
/* Bullmax */-------------Reality has many forms : good and evil, black and white, yin and yang.
Advertisement
This may help :

-------------------------------

void DrawIsoTile(LPDIRECT3DDEVICE8 Device, float x, float y, float z, LPDIRECT3DTEXTURE8 tex)
{
ISOVERTEX Tile[4] =
{
{ x, y, z+1.0f, 0,1,0, 0xffffffff, 1.0f, 0.0f},
{ x, y, z+0.0f, 0,1,0, 0xffffffff, 1.0f, 1.0f},
{ x+1.0f, y, z+1.0f, 0,1,0, 0xffffffff, 0.0f, 0.0f},
{ x+1.0f, y, z+0.0f, 0,1,0, 0xffffffff, 0.0f, 1.0f},
} ;

Device->SetVertexShader(D3DFVF_ISOVERTEX);
Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
Device->SetTexture( 0, tex );
Device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, Tile, sizeof(ISOVERTEX));
}

-------------------------------

There are better ways of doing this, but this works fine for me.

Stuart.
I'm not sure if I understand what you want to do exaclty... do you want to write all the data into a single vertex buffer to write to the screen in a single call? If you do you're sol anyways, as you'ld need to change your texture before every batched primitive drawing call.

If you want to draw each "tile" as a single batched primitive then there's no issue to begin with. You just change your world matrix.. change your texture.. and redraw...

I guess I need a better idea of what you're trying to do and how you plan to do it (and why sharing those two vertices is even an issue).

Though I guess your question would make more sense if it was a static terrain and you just want to build the vertex list up once... with different sets of indices for the tiles with different textures on it...

In which case the answer is,I think, well actully yes. You can share the vertices if you set your texture co-ordinate system up so that it well.. tiles your textures automatically.

i.e if you have your left vertex with a u co-ordinate of 0, and your right vertex with a u co-ordinate of 1, then it will render the full width of the texture between the two. If your next vertex over is 2 it will AGAIN render the full width.

i.e. your vertices would be like this :

    (0,0)          (1,0)           (2,0)*---------------*--------------*|---------------|--------------||---------------|--------------||---------------|--------------|*---------------*--------------*(0,1)          (1,1)           (2,1)    


you'll end up with the textures properly filling out there individual tiles when you render.

There may be some limits as to just how high the texture co-ordinate can go though, so you should look that up before using this technique. This is a method you might normally use for drawing a brick wall or something but it also applies to your case (if my static terrain guess is correct...)


I think it's just a matter of setting a render state... look up texture tiling in the sdk documentation


Edited by - Sorrow on February 23, 2002 1:07:56 AM
Stooby, your example shows a little what I do, but yours does not batch...

Sorrow, what you've said i true, I admit, but this would work if you used the same texture repeatedly. The same texture would repeat its pattern, but if each tile required different texture coordinates, they could not be reused. I'm not sure, but I think that what I'm talking of is multi-texturing.

But here is an example with a cube instead of a tile.
If your cube have 8 logical points, you would certainly technicaly create 8 vertices in a vertex buffer and 36 indices in a index buffer. Doing so, the 8 vertices would be reused to draw the 12 triangles that compose the cube.

Let's say you apply one brick texture on your cube. You could use texture coordinates higher than 1.0 to tile it over all the cube surfaces. BUT if you decide that each surface (or one specific surface, it doesn't matter) of the cube would have a different texture than the brick texture, it would be impossible (that's my question...) to reuse the vertices, in this case with the help of the index buffer, because the texture coordinates would different and the texture would appear messed up.

And if the vertices aren't reused, there would be more than 8 vertices needed to compose the cube and that's what I want to avoid.

So I'm wondering if this is not a multitexturing or mulipassing or impossible to do subject, but I'll try to find out again. If you think you have other solutions, please help. Thanks again sorrow, but I think I need a little more and sorry for my blurry question, but it's very hard to explain. I think I'll prepare pictures to explain next time, because for readers it must be a pain...



/* Bullmax */
-------------
Reality has many forms : good and evil, black and white, ying and yang.

Edited by - Bullmax on February 23, 2002 9:43:48 AM
/* Bullmax */-------------Reality has many forms : good and evil, black and white, yin and yang.
I think this may explain what he wants a bit better.. coz i have the same problem..

Here's the problem.

http://www.websrusmalls.com/~spikeles/help.jpg
In the picture above i have some quads.. i want to paint a different texture on each quad.. obviously each quad uses
different texture co-ordinates.

For example.. for the red vertex it has 4 co-ords.

Green texture - 1,0
Yellow Texture - 0,0
Blue Texture - 1,1
Magenta Texture - 0,1

And here's the question..
How do i render these using a single command of DrawPrimitive?

I know i can do it using 4 vertex co-ordinates in the FVF structure. Then using a DrawPrimitve command to render
each triangle of the quad and using SetTextureStageState (0, D3DTSS_TEXCOORDINDEX ,index) before each DrawPrimitve
command to reference the right co-ords..OR i could use DrawPrimitiUP as Stooby showed...

But.. i'd rather avoid this.. Surely there is a better way?



[edited by - Spikeles on April 27, 2002 11:16:07 AM]
Hi!
Like you, I''am trying to make a 3d tiled engined and I successful made it.
If you want, we can discuss and help us together.
quote:Original post by viddak
Hi!
Like you, I''am trying to make a 3d tiled engined and I successful made it.
If you want, we can discuss and help us together.


Dosn''t matter.. I figured it out..
I think that the trick to acheive this technique is by using multitexturing method. I''ve read a book about this recently. It is kinda impossible because the terrain is in fact tiled.

To have the same effect, a cheaper technique would be to have less textures, but larger ones with repetition (uv coords higher than 1.0f). Theses textures would be overlayed. Places where a texture does not need to be drawn has an alpha of 0.0f.

But this is, I think, more cpu aggressive than tiling with quads. Again, here is a dead-end...


/* Bullmax */
-------------
Reality has many forms : good and evil, black and white, ying and yang.
/* Bullmax */-------------Reality has many forms : good and evil, black and white, yin and yang.
It''s NOT impossible.. you generate a vertex buffer using 4 vertices per tile..

vertex - x=0,y=0, u=0, v=0
vertex - x=0,y=1, u=0, v=1
vertex - x=1,y=1, u=1, v=1
vertex - x=1,y=0, u=1, v=0

then just use indices to make a triangle strip or list out of these 4 verts.. and make each texture have it''s own Index Buffer.. so that you use SetTexture once.. then call the Index Buffer associated with that texture to draw all the triangle for that texture.. simple!

:D


That technique would work if your map was made up of 4 textures. Otherwise, it is just a waste, it would be less vertices but more DrawPimitive calls.

This topic is closed to new replies.

Advertisement