[LibGDX] creating a mesh with different textures

Hi,

What would be the best way to create a mesh (here a cube) with different textures each side?

I have tried this by creating a textured mesh in Blender. In Blender I have mapped the texture and then exported it to LibGDX. This works, no problem. But I would like to dynamically assign the texture (maybe different ones) to each side. Importing the model is to my understanding static.

As an alternative I have also created a quad (one face) to which I can put a texture. This works too but obviously I am missing 5 sides of the mesh (cube).

  1. I probably can create the missing 5 sides (as quads) and have them textured, but is this really the only option?
  2. Can I set texture for a mesh parts or faces created by modelBuilder.createBox somehow?
  3. Any other or better alternatives for doing this?

Thanks you in advance! I really have tried first to look the net and forum for an answer.

Cheers, Jaxes

WordSlinger- The best word game if developer opinion counts.
https://play.google.com/store/apps/details?id=com.method.wordslinger

You can use something call atlas, texturesheet or spritesheet.
Basically, lets say you have 4 textures of size 256x256. You can put them into single texture the size of 1024x1024 and render certain part of that altas.

You can also use a megatexture. Not really sure how that would work, just saw something about it on youtube yesterday :smiley:

Thanks for the answer.

I tried TextureAtlas and I got everything correctly packed with the tool but my problem is that I don’t know how to assign the textures to certain parts of the mesh (here cube face). I am not sure if you can assign texture from TextureAtlas because what you get returned is TextureRegion, but I might be wrong.

You might be answering the correct question but I don’t understand how using TextureAtlas helps me in setting different Textures for different parts of the Mesh?

I have also looked the attributes of the Model class and there’s an materials but but… How does one compose a Model with 6 meshes with 6 different textures?

Now I have actually done it in MeshBuilder but it sure feels clumsy.

Cheers, Jaxes

You use one texture with the mesh then you use texture coordinates to say what part of the texture you want to be drawn.

Thank you for the answer. Can you elaborate your answer? Or give me guidance where to find documents / tutorial / material regarding how to do this specific task in LibGDX?

I have done this like you say with MeshBuilder but it seems just a little bit tedious and clumsy. It works though which is the best part. :slight_smile:
I might be asking too simple thing but is there easier way for doing this?

Cheers, Jaxes

Uhmm… Start with LWJGL instead of LibGDX. You obviously have no idea what we are talking about.

This is how rendering works:

  • Bind certain texture to opengl
  • Point opengl to vertex data: each vertex has position, color, texture coordinate, normal. You can also add custom vertex attributes.
  • Tell opengl to rendering everything

If you want to use different textures for 1 mesh, you will need to render mesh in separate parts: render 1st part with texture 1, render 2nd part of the mesh with texture 2, render 3rd part of the mesh with texture 3. That is the only way. If you want to have different textures for 1 mesh, you have to split the mesh into manageable pieces…

Thank you for the answer.

Maybe you are right, but I got it working already. I did it by using MeshBuilder by adding 6 meshes with 6 textures and created a model. Now I can rotate the modelInstance created from the Model. This works all very well.

This applies in general level how this is achieved. I know how to do this. But my question was specifically LibGDX specific and moreover I was wondering if there’s any easier way than using MeshBuilder which to me felt a little bit “clumsy”.

Yeah, this is what I have done.

I might be asking too simple question but this is really LibGDX specific and I would like to know if there’s a better way to do this in LibGDX than building the mesh with MeshBuilder. Sorry if I am repeating myself or being just a noob but to me it still looks the actual question remains unanswered.

Cheers, Jaxes

@TrollWarrior1
Dont suggest lwjgl if the op is having trouble with the libgdx implementation. Also, dont tell him that he “oubviously has no idea what he his talking about.” You were once there too.

@Jaxes74
You dont need a separate texture for each image. Use one texture with all the images on it. You bind that one texture at the start of rendering. Then, each vertex has position, texture coordinates, color, and normal. The texture coordinates tell what part of the the image to render. Basically, theyre texture regions. Use a texture region to get the texture coordinates for the part of the texture youre trying to render.

Thanks. I am gonna try it now. I am not sure about the binding thing though. I am currently not binding the textures explicitly (at the render), but if OpenGL requires that then it might be done my the framework.

Cheers, Jaxes

Ok, I don’t understand. I admit it.

Relevant parts of my code:
create:

		textureAtlas = new TextureAtlas(Gdx.files.internal("data/pack.atlas"));
		Texture myTexture = new Texture(Gdx.files.internal("data/treasure.jpg"));
		
		ModelBuilder builder = new ModelBuilder();
		builder.begin();
		builder.part("1", createQuad(),	GL10.GL_TRIANGLES,new Material("1", TextureAttribute.createDiffuse(myTexture)));
		//builder.part("1", createQuad(),	GL10.GL_TRIANGLES,new Material("1", TextureAttribute.createDiffuse(textureAtlas
		//				.findRegion("myRegionName"))));
		quadInstance = new ModelInstance(builder.end(), 0, 0, 0);
		instances.add(quadInstance);


	private Mesh createQuad() {
		Mesh quad = new Mesh(true, 4, 6, new VertexAttribute(Usage.Position, 3,	"a_position"), 
				new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"));

		quad.setVertices(new float[] { -1f, -1f, 0, 0, 1, // bottom left
				1f, -1f, 0, 1, 1, // bottom right
				1f, 1f, 0, 1, 0, // top right
				-1f, 1f, 0, 0, 0 }); // top left
		quad.setIndices(new short[] { 0, 1, 2, 2, 3, 0 });
		return quad;
	}

render:


	public void render() {
		Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(),
				Gdx.graphics.getHeight());
		Gdx.gl.glClearColor(1, 1, 1, 1);
		Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

		camera.update();

		modelBatch.begin(camera);
		modelBatch.render(instances, environment);
		modelBatch.end();
	}

Now, how do I assign the texture from TextureAtlas to the mesh (the out commented part) ? The direct assign from Texture works.

Cheers, Jaxes


	private Mesh createQuad() {
		Mesh quad = new Mesh(true, 4, 6, new VertexAttribute(Usage.Position, 3,	"a_position"), 
				new VertexAttribute(Usage.TextureCoordinates, 2, "a_texCoords"));

      TextureRegion region = new TextureRegion("you spritesheet texture", 0, 0, 128, 128); // Basically this just gets the texture region that you want the side to be ("texture path", xLocation, yLocation, width, height)

		quad.setVertices(new float[] { -1f, -1f, 0, region.getU(), region.getV2(), // bottom left
				1f, -1f, 0, region.getU2(), region.getV2(), // bottom right
				1f, 1f, 0, region.getU2(), region.getV(), // top right
				-1f, 1f, 0, region.getU(), region.getV() }); // top left
		quad.setIndices(new short[] { 0, 1, 2, 2, 3, 0 });
		return quad;
	}

Getting the u/v/u2/v2 will give you the texture coordinates of that part of the whole texture. You’ll just have to repeat this for every face with different vertex locations & region locations. Basically, you use a spritesheet like this. This way, you don’t have to bind different textures, you just use different texture coordinates to locate the image you want.

Sorry for delay in reply, I was in CeBIT and what not, had a birthday etc. Thanks for the answer Longarmx!

Why are you instantiating the TextureRegion inside the createQuad? Couldn’t you just pass the same coordinates (here 0, 0, 128, 128) as u/v/u2/v2 ?

I ended up doing this like this:


	      TextureRegion region = textureAtlas.findRegion("regionName");

	      quad.setVertices(new float[] { -1f, -1f, 0, region.getU(), region.getV2(), // bottom left
	            1f, -1f, 0, region.getU2(), region.getV2(), // bottom right
	            1f, 1f, 0, region.getU2(), region.getV(), // top right
	            -1f, 1f, 0, region.getU(), region.getV() }); // top left
	      quad.setIndices(new short[] { 0, 1, 2, 2, 3, 0 });

And I have created the TextureAtlas like in my previous example. This works all very well.

Now, If I need to create all 6 quads, the next question is do I have to pass the Material to ModelBulder each time I create a MeshPart like this:


builder.part("1", createQuad(),	GL10.GL_TRIANGLES, new Material("1", TextureAttribute.createDiffuse(myTexture)));
builder.part("2", createQuad(),	GL10.GL_TRIANGLES, new Material("2", TextureAttribute.createDiffuse(myTexture)));

Here I am passing the same texture possibly 6 times which I find a bit strange.

Cheers, Jaxes