I have the following code snippet that generates a 3D cube:
ModelBuilder modelBuilder = new ModelBuilder();
box = modelBuilder.createBox(2f, 2f, 2f,
new Material(TextureAttribute.createDiffuse(AssetLoader.tr[0])),
VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates
);
So far so good. The problem is that all faces of the cube uses the same texture, whereas what I want is Assetloader.tr[], which is an array with 6 individual textures to appear on each face respectively.
I have tried
box.nodes.get(0).parts.get(0).material.set(new Material(TextureAttribute.createDiffuse(AssetLoader.tr[0])));
box.nodes.get(0).parts.get(1).material.set(new Material(TextureAttribute.createDiffuse(AssetLoader.tr[1])));
...
but somehow the documentation doesn't give me any hints for how to do it properly. I'm a bit stuck here atm.
There are several considerations to keep in mind. First of all make sure to carefully read: https://github.com/libgdx/libgdx/wiki/ModelBuilder%2C-MeshBuilder-and-MeshPartBuilder.
Secondly, try to avoid the ModelBuilder#createXXX
methods. They are just a shortcut for debugging and testing purposes. If you look at the code behind it, you'll see that's very straightforward:
modelBuilder.begin();
modelBuilder.part("box", GL20.GL_TRIANGLES,
VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates,
new Material(TextureAttribute.createDiffuse(AssetLoader.tr[0])))
.box(2f, 2f, 2f);
box = modelBuilder.end();
As you can see this creates a single part for the entire box, so trying to access a second part (as you do in your example) will not work. But because you want to use a different material for each face, you'll need to create a part for each face.
int attr = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates;
modelBuilder.begin();
modelBuilder.part("front", GL20.GL_TRIANGLES, attr, new Material(TextureAttribute.createDiffuse(AssetLoader.tr[0])))
.rect(-2f,-2f,-2f, -2f,2f,-2f, 2f,2f,-2, 2f,-2f,-2f, 0,0,-1);
modelBuilder.part("back", GL20.GL_TRIANGLES, attr, new Material(TextureAttribute.createDiffuse(AssetLoader.tr[1])))
.rect(-2f,2f,2f, -2f,-2f,2f, 2f,-2f,2f, 2f,2f,2f, 0,0,1);
modelBuilder.part("bottom", GL20.GL_TRIANGLES, attr, new Material(TextureAttribute.createDiffuse(AssetLoader.tr[2])))
.rect(-2f,-2f,2f, -2f,-2f,-2f, 2f,-2f,-2f, 2f,-2f,2f, 0,-1,0);
modelBuilder.part("top", GL20.GL_TRIANGLES, attr, new Material(TextureAttribute.createDiffuse(AssetLoader.tr[3])))
.rect(-2f,2f,-2f, -2f,2f,2f, 2f,2f,2f, 2f,2f,-2f, 0,1,0);
modelBuilder.part("left", GL20.GL_TRIANGLES, attr, new Material(TextureAttribute.createDiffuse(AssetLoader.tr[4])))
.rect(-2f,-2f,2f, -2f,2f,2f, -2f,2f,-2f, -2f,-2f,-2f, -1,0,0);
modelBuilder.part("right", GL20.GL_TRIANGLES, attr, new Material(TextureAttribute.createDiffuse(AssetLoader.tr[5])))
.rect(2f,-2f,-2f, 2f,2f,-2f, 2f,2f,2f, 2f,-2f,2f, 1,0,0);
box = modelBuilder.end();
However, having a part for each face does imply a render call for each face. It is more performant to make sure that all TextureRegion
s share the same texture and use that instead:
int attr = VertexAttributes.Usage.Position | VertexAttributes.Usage.Normal | VertexAttributes.Usage.TextureCoordinates;
modelBuilder.begin();
MeshPartBuilder mpb = modelBuilder.part("box", GL20.GL_TRIANGLES, attr, new Material(TextureAttribute.createDiffuse(AssetLoader.tr[0].getTexture())));
mpb.setUVRange(AssetLoader.tr[0]);
mpb.rect(-2f,-2f,-2f, -2f,2f,-2f, 2f,2f,-2, 2f,-2f,-2f, 0,0,-1);
mpb.setUVRange(AssetLoader.tr[1]);
mpb.rect(-2f,2f,2f, -2f,-2f,2f, 2f,-2f,2f, 2f,2f,2f, 0,0,1);
mpb.setUVRange(AssetLoader.tr[2]);
mpb.rect(-2f,-2f,2f, -2f,-2f,-2f, 2f,-2f,-2f, 2f,-2f,2f, 0,-1,0);
mpb.setUVRange(AssetLoader.tr[3]);
mpb.rect(-2f,2f,-2f, -2f,2f,2f, 2f,2f,2f, 2f,2f,-2f, 0,1,0);
mpb.setUVRange(AssetLoader.tr[4]);
mpb.rect(-2f,-2f,2f, -2f,2f,2f, -2f,2f,-2f, -2f,-2f,-2f, -1,0,0);
mpb.setUVRange(AssetLoader.tr[5]);
mpb.rect(2f,-2f,-2f, 2f,2f,-2f, 2f,2f,2f, 2f,-2f,2f, 1,0,0);
box = modelBuilder.end();
While this might help you do you want, you should really reconsider your approach. As you can see, creating a model by code can get messy really fast. And, moreover, creating a single model for a box is in most cases far from optimal unless your goal is to only render a single box and nothing more than a box. Instead use a modeling application to create your models. Have a look at my blog at http://blog.xoppa.com/ for more info. If you really want to modify parts yourself, then make sure to read at least up to and including the "behind the scenes" tutorials.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With