BoxRemapper

A tiny class for remapping a box:



import com.jme.math.Vector2f;
import com.jme.scene.shape.Box;
import java.nio.FloatBuffer;

/**
 *
 * @author DGronau
 */
public class BoxRemapper {

    public static final int BACK = 1;
    public static final int RIGHT = 2;
    public static final int FRONT = 4;
    public static final int LEFT = 8;
    public static final int TOP = 16;
    public static final int BOTTOM = 32;
    public static final int ALL = 63;
   
    private float tex[] = new float[]{
        1,0, 0,0, 0,1, 1,1,
        1,0, 0,0, 0,1, 1,1,
        1,0, 0,0, 0,1, 1,1,
        1,0, 0,0, 0,1, 1,1,
        1,0, 0,0, 0,1, 1,1,
        1,0, 0,0, 0,1, 1,1
    };
   
    /**
     * Give the coordinates in the following order:
     * bottom right, bottom left, top left, top right.
     * For rotating or mirroring change the order.
     * The coordinates don't have to be rectangular,
     * so you can create distortions.
     * @param side int the side that should be set, sides can be added together
     * @param coords the coordinates of the texture
     */
    public void setSide(int side, Vector2f... coords) {
        if (coords.length != 4) {
            throw new IllegalArgumentException("Requires 4 Vector2f objects.");
        }
        setSide(side, coords[0].x, coords[0].y,
                      coords[1].x, coords[1].y,
                      coords[2].x, coords[2].y,
                      coords[3].x, coords[3].y);
    }
   
    /**
     * Give the coordinates in the following order:
     * bottom right, bottom left, top left, top right.
     * For rotating or mirroring change the order.
     * The coordinates don't have to be rectangular,
     * so you can create distortions.
     * @param side the side that should be set, sides can be added together
     * @param coords the coordinates of the texture
     */
    public void setSide(int side, float... coords) {
        if (coords.length != 8) {
            throw new IllegalArgumentException("Requires 8 floats.");
        }       
        for(int i = 0; i < 6; i++) {
            int n = 1 << i;
            if ((side & n) > 0) {
                System.out.println("writing side " + i);
                for (int t = 0; t < 8; t++) {
                    tex[t + 8*i] = coords[t];
                }
            }
        }
    }
   
    /**
     * The Box to be remapped
     * @param box the box
     */
    public void remap(Box box) {
                FloatBuffer fb = box.getTextureBuffer(0, 0);
      fb.rewind();
      fb.put(tex);
    }

}



Imagine you have a texture which has 4 quarters, and you want the top left quarter at front and back, the top right quarter at right, the bottom left quarter at left and the bottom right quarter at up and bottom of your box. Then you'd write (out of my head, beware of typos):


import static BoxRemapper.*; //too lazy to type the constants

BoxRemapper br = new BoxRemapper();
br.setSide(FRONT + BACK, 0.5f, 0.5f, 0, 0.5f, 0, 1, 0.5f, 1);
br.setSide(RIGHT, 1,  0.5f, 0.5f, 0.5f, 0.5f, 1, 1, 1);
br.setSide(LEFT, 0.5f, 0, 0, 0, 0, 0.5f, 0.5f, 0.5f);
br.setSide(UP+DOWN, 1, 0, 0.5f, 0, 0.5f, 0.5f, 1, 0.5f);
br.remap(box)



If you have any ideas to simplify the remapping further, let me know...

Hey guys !

I just did an update of the class that Landei did for JME3.

In that way people would be happy like me to find something that is doing a multi textured box with one texture and without using Blender.

[java]

import com.jme3.math.Vector2f;

import com.jme3.scene.VertexBuffer.Type;

import com.jme3.scene.shape.Box;

import com.jme3.util.BufferUtils;

/**

*

  • @author DGronau & thebreton

    */

    public class BoxRemapper {

    public static final int BACK = 1;

    public static final int RIGHT = 2;

    public static final int FRONT = 4;

    public static final int LEFT = 8;

    public static final int TOP = 16;

    public static final int BOTTOM = 32;

    public static final int ALL = 63;

    private float tex[] = new float[]{

    1,0, 0,0, 0,1, 1,1,

    1,0, 0,0, 0,1, 1,1,

    1,0, 0,0, 0,1, 1,1,

    1,0, 0,0, 0,1, 1,1,

    1,0, 0,0, 0,1, 1,1,

    1,0, 0,0, 0,1, 1,1

    };

    /**
  • Give the coordinates in the following order:
  • bottom right, bottom left, top left, top right.
  • For rotating or mirroring change the order.
  • The coordinates don’t have to be rectangular,
  • so you can create distortions.
  • @param side int the side that should be set, sides can be added together
  • @param coords the coordinates of the texture

    */

    public void setSide(int side, Vector2f… coords) {

    if (coords.length != 4) {

    throw new IllegalArgumentException("Requires 4 Vector2f objects.");

    }

    setSide(side, coords[0].x, coords[0].y,

    coords[1].x, coords[1].y,

    coords[2].x, coords[2].y,

    coords[3].x, coords[3].y);

    }

    /**
  • Give the coordinates in the following order:
  • bottom right, bottom left, top left, top right.
  • For rotating or mirroring change the order.
  • The coordinates don’t have to be rectangular,
  • so you can create distortions.
  • @param side the side that should be set, sides can be added together
  • @param coords the coordinates of the texture

    /

    public void setSide(int side, float… coords) {

    if (coords.length != 8 ) {

    throw new IllegalArgumentException("Requires 8 floats.");

    }

    for(int i = 0; i < 6; i++) {

    int n = 1 << i;

    if ((side & n) > 0) {

    System.out.println("writing side " + i);

    for (int t = 0; t < 8; t++) {

    tex[t + 8
    i] = coords[t];

    }

    }

    }

    }

    /**
  • The Box to be remapped
  • @param box the box

    */

    public void remap(Box box) {

    if (box.getBuffer(Type.TexCoord) != null){

    box.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(tex));

    }

    }

    }[/java]

    Enjoy!

Cool :slight_smile:

Line 53 is pretty awesome! :wink:

buuuhahaha :slight_smile:

I guess a bug in the forum editor when I copy / paste :wink:

I fix it ! (add just a space)

Thanks for the remark !

Looks good to me but the thing I would change is use an Logger/Info instead of System.out.println(…). That way it won’t spam the console if you have multiple boxes to skin that way. With an Info, it can be turned off.

I agree. In general, do not use any System.out.print command in your code … because it stays :wink:

Log4j is a good/pro alternative indeed.

I forget even if it is obvious :

[java]import static BoxRemapper.*; //too lazy to type the constants

BoxRemapper br = new BoxRemapper();

br.setSide(FRONT + BACK, 0.5f, 0.5f, 0, 0.5f, 0, 1, 0.5f, 1);

br.setSide(RIGHT, 1, 0.5f, 0.5f, 0.5f, 0.5f, 1, 1, 1);

br.setSide(LEFT, 0.5f, 0, 0, 0, 0, 0.5f, 0.5f, 0.5f);

br.setSide(TOP+BOTTOM, 1, 0, 0.5f, 0, 0.5f, 0.5f, 1, 0.5f);

br.remap(box)[/java]

it is TOP and BOTTOM to use, not up/down.



I edit the post to even give a concrete example and resource - as I know a lot of you are interesting by Minecraft :

[java]Box box = new Box(Vector3f.ZERO, 1, 1, 1);

cube = new Geometry(“minecraftBlockLike”, box);



Material mat_stl = new Material(assetManager, “Common/MatDefs/Misc/Unshaded.j3md”);

Texture tex_ml = assetManager.loadTexture(“Materials/multitexture.png”);

mat_stl.setTexture(“ColorMap”, tex_ml);

cube.setMaterial(mat_stl);





BoxRemapper br = new BoxRemapper();

br.setSide(BoxRemapper.FRONT + BoxRemapper.BACK + BoxRemapper.RIGHT + BoxRemapper.LEFT,

1f, 0.333f, 0, 0.333f, 0, 0.666f, 1,0.666f);

br.setSide(BoxRemapper.TOP, 1, 0.666f, 0, 0.666f, 0, 1, 1, 1);

br.setSide(BoxRemapper.BOTTOM, 1, 0, 0, 0, 0, 0.333f, 1, 0.333f);

br.remap(box);



rootNode.attachChild(cube);[/java]



and use the following textures that is composed of 3 textures : of 64 pixels (texture size : 64 * 192)



you will get the following result :





You can start to build a minecraft game like :wink:

You see it is efficient and simple.

I think it could be even a tutorial :wink: