Varying textures across instances in a GeometryBatch

Hi there,



I'm just getting started with JME, it's a great engine and feels very capable.



For a starter project, I'm trying to do a tile-based game in the tradition of old 16-bit role playing games. To create my floor, I'm using geometry instancing to handle a bunch of quads.



But I'm having trouble applying different textures to instances in the GeometryBatch. There was another thread here about "tile based games" and someone mentioned that they were able to do exactly this. I was wondering if anyone who knows how to do so would be kind enough to post a code snippet?



Thanks!


I recommend just creating one Quad element per tile. Then put the appropriate texture on each Quad. A 2D background with a few hundred quads on the screen just isn't complicated enough to need anything more complex, and that's the easiest way to do it.

I have the Quads approach working already. I was curious about how to do this with a GeometryBatch. Does anyone know how? :slight_smile:

You use a texture atlas, you put all your textures into a single texture and then adjust the UV coordinates to map into the texture's parts.

Moko is right on.  I have a working example of this using GeometryInstancing classes if you need to see it.

Beware of MIP map filtering when you are using a texture atlas for your tiles. It's actually impossible to do "correct" seamless tiling out of a texture atlas for all MIP map levels; you'll have to decide on an amount of MIP levels (say, 3) and add a border of size 1<<N (so, in this case, 8) pixels copied from the other side, around EACH tile in the atlas. Then generate the UV coordinates accordingly.

Thanks for the replies. I was trying to use a texture buffer to set UV coordinates on each instance:

[pre]

  private TriMesh createBatchMesh(float startX, float startY) {

    // A box that will be instantiated

    Quad box = new Quad("tile", 1.0f, 1.0f);

   

    // The batch geometry creator

    batchCreator = new GeometryBatchCreator();



    // Loop that creates NxN instances

    for (int y = 0; y < instances; y++) {

      for (int x = 0; x < instances; x++) {

        // Box instance attributes

        GeometryBatchInstanceAttributes attributes = new GeometryBatchInstanceAttributes(

            // Translation

            new Vector3f(startX + scale * x, startY + scale * y, 0.0f),

            // Scale

            //new Vector3f(scale * 0.04f + y * scale * 0.015f, scale * 0.02f, scale * 0.02f),

            Vector3f.UNIT_XYZ,

            // Rotation

            //new Vector3f(0.0f, (x + y) * -0.1f, 0.0f),

            Vector3f.ZERO,

            // Color

            ColorRGBA.white);



        // Box instance (batch and attributes)

        GeometryBatchInstance instance = new GeometryBatchInstance(box.getBatch(0), attributes);



        // Add the instance

        batchCreator.addInstance(instance);

      }

    }



    // Create a TriMesh

    mesh = new TriMesh();

    TriangleBatch batch = mesh.getBatch(0);

    mesh.setRenderState(texture); // Texture loaded elsewhere

    batch.setModelBound(new BoundingBox());



    // Create the batch's buffers – This doesn't work, and the changes don't seem to persist

    // in the instance after calling bacthCreator.commit()

    FloatBuffer textureBuffer = BufferUtils.createVector2Buffer(batchCreator.getNumVertices());

    textureBuffer.put(0f).put(1f);

    textureBuffer.put(0f).put(0.5f);

    textureBuffer.put(1f).put(1f);

    textureBuffer.put(1f).put(0.5f);

    textureBuffer.rewind();

   

    batch.setIndexBuffer(BufferUtils.createIntBuffer(batchCreator.getNumIndices()));

    batch.setVertexBuffer(BufferUtils.createVector3Buffer(batchCreator.getNumVertices()));

    batch.setNormalBuffer(BufferUtils.createVector3Buffer(batchCreator.getNumVertices()));

    batch.setTextureBuffer(textureBuffer, 0);

    batch.setColorBuffer(BufferUtils.createFloatBuffer(batchCreator.getNumVertices() * 4));

       

    GeometryBatchInstance instance = (GeometryBatchInstance)batchCreator.getInstances().get(0);

    FloatBuffer fb = instance.instanceBatch.getTextureBuffer(0);



    // Commit the instances to the mesh batch

    batchCreator.commit(batch);

   

    mesh.updateModelBound();



    // This also doesn't work, but the values seem to stick in the buffer.

    fb.rewind();

    fb.put(0f).put(1f);

    fb.put(0f).put(0.5f);

    fb.put(1f).put(1f);

    fb.put(1f).put(0.5f);

    fb.rewind();



    mesh.updateRenderState();



    // Return the mesh

    return mesh;

  }

[/pre]

Maybe there is something really obvious that a JME veteran can point out?


I believe batchCreator.commit() will copy all of the data you have configured, into the TriMesh you've created. That means it will overwrite the texture coordinates you have written. I suggest adjusting the texture coordinates in the mesh after the call to commit().