问题
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.
回答1:
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.
来源:https://stackoverflow.com/questions/27452192/libgdx-mapping-individual-textures-to-each-face-of-a-box-using-modelbuilder-cr