Robert P
Robert P

Reputation: 9783

Repeating Textures on a Model

I am creating a little game, where you are in a maze. The maze is organized in a 2D Array, describing the x and z position and the block type. So it is Tile-based. Lets say every block is 1 m³. Now my character is 2m tall and the maze should be 4m tall. Therefore i add 4 blocks over eachother if there is a wall on that tile. Of course this is a huge performance impact in a 100 * 100 meter/tile maze, even with Viewfrustum- and backface culling. As this is my first 3D game i want to keep it simple and i don't want to use advanced culling techniques (octree or whatever :P). So i tried to create 1*4*1 blocks instead of 1*1*1 and add them as Walls to my world. It works great, performance is perfect again (60 FPS), but the Texture (64*64px) is stretched up and it really looks ugly.

So my questions are:

  1. Is it possible to repeat the texture every meter, instead of stretching it?
  2. Or do i need to modify the texture to have it 4 times as high?
  3. Or is there a even better solution?

EDIT: I found out, that Textures have the TextureWrap modes. I set that to TextureWrap.Repeat, but i can't set the UVs on a Texture. If you are creating a Sprite out of a Texture you can easily set them to 4 to repeat the Texture 4 times. But i can't add a Sprite to my Model, only Textures are possible. Is there a way to repeat those Textures?

Upvotes: 2

Views: 1348

Answers (3)

Krzysztof Cieśliński
Krzysztof Cieśliński

Reputation: 339

If someone will have problems with changing UVs while using ModelBuilder.createRect method then this might help:

...
Model rect = modelBuilder.createRect ...

Matrix3 mat = new Matrix3();
mat.scl(2);
rect.meshes.get(0).transformUV(mat);

instance = new ModelInstance(rect); 
...

That way you will get 2x2 texture repeat. (I wasted some time searching for this solution. I used it to repeat grass texture on big ground surface)

Upvotes: 4

Robert P
Robert P

Reputation: 9783

As @kolenda s answer were right, but i did not find any way to apply them i had to find another way. I am now using ModelBuilder.createRect() and i create 4 rects over each other, for every wall. By using rects, i can simply draw only visible rects, by just ignoring rects, which are occupied by another wall. So if a wall is on the left of another wall i don't draw its left face and the other walls right face. The problem is, that there are many rects then and even with frustum culling enabled the FPS fall down to 20 if i look in a direction with many rects inside my fiewfrustum. @xoppa told me, that ModelBuilder is used for debug only and i should use other techniques, but i am not sure which one. So if somebody knows that, please post it as an answere here, as it answers this question (instead of repeating a texture on the model do this...), and it also solves some other problems. But for the moment this is my solution, it works good enough for me and maybe it can help someone else to. But as i said i like to see other, better solutions, as i am still learning some basics of 3D programming.

Upvotes: 0

kolenda
kolenda

Reputation: 2801

The way your texture is applied to your model depends on UV values of each vertex in the model.

If you consider one plane of your cube - it is a rectangle made of 4 vertices. If you vertices have UV values like: (0,0), (1,0), (1,1), (0,1) then your entire texture will be rendered once on your entire plane (as you have right now).

What you need is to change some of your UVs value to 4 instead of 1 - you should use something like (0,0), (1,0), (1,4), (0,4) - this way your texture will be repeated 4 times.

Unfortunately I don't know how to change UVs in Libgdx, maybe somebody else will help here.


EDIT for questions in comment:

You know that each vertex you render has its own 3D position vector, made of x,y,z components. This represents the position in a 3D space.

If you want to add texture, you need to tell to your vertex at which point of texture it is. You define some 2D vector that represents a point in your texture (you can also use 3D textures but let's stick to 2D example for now).

Your texture vector components could be named x,y also, but to avoid possible confusions with position data somebody decided to call them u,v (it's quite often in mathematics to do such things, even if you store the same type of data it makes some equations easier to read and understand). Those vectors are called texture coordinates or UVs in short.

Now imagine you have your texture in front of you, one of its corners is at (0,0) and the opposite is at (1,1). You take 3 vertices of some triangle and for each vertex you take its UVs and you mark this point on your texture. Then, when you connect all 3 points you'll get the same triangle as you would get from the rendering.

But what if one of your UVs component is bigger than 1 or smaller than 0? For simplicity we could say that GPU will take the same texture and copy it just after the original one (it doesn't work exactly this way but the result is the same). This answers your question about the 4 number - if we used a texture coordinate like (1,4) it means we're moving 4* textureHeight from origin, so you'll have your texture repeated 4 times.

I think that for now you should find a way to add UVs to your vertices and experiment with this a bit. Try to set 0, 0.1, 1, 10, etc... as your texture coordinates and look what it gives you. This way you should get some basic understanding how does UVs work.

Upvotes: 3

Related Questions