Edit:Can someone help me figure out how to do the texture Coordinates please on a 16x16 pixel png
I got a test case working except for texturing
Does anyone know how to use a 16x16 image as a texture
I am following this link on making a custom mesh but cant figure out how to uv map a texture that is a single pixel.
https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:custom_meshes
It just seems to bleed to the next pixel instead of using it as a full color
it might also be a rounding issue by using float but I am not sure
From what I understand the texture is normalized to 1 so 1x1 instead of 16x16 . To convert I divide each pixel position by 16
here is the image notice how the colors are off.

Here is the output texture coordinates
[java]
-Front-
0.4375,0.4375 0.4375,0.4375 0.4375,0.4375 0.4375,0.4375
-Back-
0.4375,0.4375 0.4375,0.4375 0.4375,0.4375 0.4375,0.4375
-Front-
0.5,0.4375 0.5,0.4375 0.5,0.4375 0.5,0.4375
-Back-
0.5,0.4375 0.5,0.4375 0.5,0.4375 0.5,0.4375
-Front-
0.5625,0.4375 0.5625,0.4375 0.5625,0.4375 0.5625,0.4375
-Back-
0.5625,0.4375 0.5625,0.4375 0.5625,0.4375 0.5625,0.4375
-Front-
0.625,0.4375 0.625,0.4375 0.625,0.4375 0.625,0.4375
-Back-
0.625,0.4375 0.625,0.4375 0.625,0.4375 0.625,0.4375
[/java]
[java]
package imageprocess;
import com.jme3.app.SimpleApplication;
import com.jme3.asset.TextureKey;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.texture.Texture;
import com.jme3.util.BufferUtils;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
/**
*
*
*/
public class ImageProcessTestMain extends SimpleApplication {
// String IMAGE_NAME = “diamond_pickaxe.png”;
String IMAGE_NAME = “test.png”;
public static void main(String[] args) {
ImageProcessTestMain app = new ImageProcessTestMain();
app.start();
}
//Code From internet to get Pixels from image
private Sprite convertTo2DWithoutUsingGetRGB(BufferedImage image) {
final byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
final int width = image.getWidth();
final int height = image.getHeight();
final boolean hasAlphaChannel = image.getAlphaRaster() != null;
int[][] result = new int[height][width];
if (hasAlphaChannel) {
final int pixelLength = 4;
for (int pixel = 0, row = 0, col = 0; pixel < pixels.length; pixel += pixelLength) {
int argb = 0;
argb += (((int) pixels[pixel] & 0xff) << 24); // alpha
argb += ((int) pixels[pixel + 1] & 0xff); // blue
argb += (((int) pixels[pixel + 2] & 0xff) << 8); // green
argb += (((int) pixels[pixel + 3] & 0xff) << 16); // red
result[row][col] = argb;
col++;
if (col == width) {
col = 0;
row++;
}
}
} else {
final int pixelLength = 3;
//Added +3
for (int pixel = 0, row = 0, col = 0; pixel + 3 < pixels.length; pixel += pixelLength) {
int argb = 0;
argb += -16777216; // 255 alpha
argb += ((int) pixels[pixel] & 0xff); // blue
argb += (((int) pixels[pixel + 1] & 0xff) << 8); // green
argb += (((int) pixels[pixel + 2] & 0xff) << 16); // red
result[row][col] = argb;
col++;
if (col == width) {
col = 0;
row++;
}
}
}
Sprite sprite = new Sprite();
sprite.width = width;
sprite.height = height;
sprite.array = result;
sprite.hasAlpha = hasAlphaChannel;
return sprite;
}
@Override
public void simpleInitApp() {
cam.setLocation(new Vector3f(10, 10, 20));
try {
URL url = ImageProcessTestMain.class.getResource(IMAGE_NAME);
System.out.println("URL " + url);
BufferedImage voxelTestImage = ImageIO.read(url);
Sprite sprite = convertTo2DWithoutUsingGetRGB(voxelTestImage);
this.createMesh(sprite);
viewPort.setBackgroundColor(ColorRGBA.White);
System.out.println("Done");
flyCam.setMoveSpeed(20f);
} catch (IOException ex) {
Logger.getLogger(ImageProcessTestMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
private void createMesh(Sprite sprite) {
Mesh mesh = new Mesh();
int pixelCount = 0;
for (int row = 0; row < sprite.height; row++) {
for (int column = 0; column < sprite.width; column++) {
if (sprite.array[row][column] != 0) {
pixelCount++;
}
}
}
//Verticies - TODO Optimized to not have duplicate verticies
int vertexCountTwo = 0;
Vector3f[] vertices = new Vector3f[pixelCount * 8];
for (int row = 0; row < sprite.height; row++) {
for (int column = 0; column < sprite.width; column++) {
if (sprite.array[row][column] != 0) {
//Front Side
vertices[vertexCountTwo++] = new Vector3f(column, row, 0);
vertices[vertexCountTwo++] = new Vector3f(column + 1, row, 0);
vertices[vertexCountTwo++] = new Vector3f(column, row + 1, 0);
vertices[vertexCountTwo++] = new Vector3f(column + 1, row + 1, 0);
//Back Side
vertices[vertexCountTwo++] = new Vector3f(column, row, -1);
vertices[vertexCountTwo++] = new Vector3f(column + 1, row, -1);
vertices[vertexCountTwo++] = new Vector3f(column, row + 1, -1);
vertices[vertexCountTwo++] = new Vector3f(column + 1, row + 1, -1);
}
}
}
//Texture - 1 x 1 is the whole image
Vector2f[] texCoord = new Vector2f[pixelCount * 8];
int texCoordCount = 0;
int texX = 0;
int texY = 0;
for (int row = 0; row < sprite.height; row++) {
for (int column = 0; column < sprite.width; column++) {
if (sprite.array[row][column] != 0) {
texX = column+1;
texY = row+1;
System.out.println("\n-Front-");
//Front Side
texCoord[texCoordCount++] = convertTexCoor(texX, texY, sprite.height, sprite.width);
texCoord[texCoordCount++] = convertTexCoor(texX, texY, sprite.height, sprite.width);
texCoord[texCoordCount++] = convertTexCoor(texX, texY , sprite.height, sprite.width);
texCoord[texCoordCount++] = convertTexCoor(texX, texY, sprite.height, sprite.width);
System.out.println("\n-Back-");
//Back Side
texCoord[texCoordCount++] = convertTexCoor(texX, texY, sprite.height, sprite.width);
texCoord[texCoordCount++] = convertTexCoor(texX, texY, sprite.height, sprite.width);
texCoord[texCoordCount++] = convertTexCoor(texX, texY , sprite.height, sprite.width);
texCoord[texCoordCount++] = convertTexCoor(texX, texY, sprite.height, sprite.width);
}
}
}
//Index - Convert to Triangles
int[] indexes = new int[pixelCount * (6 + 6+ 6 +6 +6 +6)]; //Front + Back + Right + Left + Top + Bottom
int indexCount = 0;
int newPixelCount = 0;
for (int row = 0; row < sprite.height; row++) {
for (int column = 0; column < sprite.width; column++) {
if (sprite.array[row][column] != 0) {
int offset = newPixelCount * 8;
//Front Side
indexes[indexCount++] = 2 + offset;
indexes[indexCount++] = 0 + offset;
indexes[indexCount++] = 1 + offset;
indexes[indexCount++] = 1 + offset;
indexes[indexCount++] = 3 + offset;
indexes[indexCount++] = 2 + offset;
//Back Side - Reverse
indexes[indexCount++] = 5 + offset;
indexes[indexCount++] = 4 + offset;
indexes[indexCount++] = 6 + offset;
indexes[indexCount++] = 6 + offset;
indexes[indexCount++] = 7 + offset;
indexes[indexCount++] = 5 + offset;
//Right Side
indexes[indexCount++] = 3 + offset;
indexes[indexCount++] = 1 + offset;
indexes[indexCount++] = 5 + offset;
indexes[indexCount++] = 5 + offset;
indexes[indexCount++] = 7 + offset;
indexes[indexCount++] = 3 + offset;
//Left Side
indexes[indexCount++] = 6 + offset;
indexes[indexCount++] = 4 + offset;
indexes[indexCount++] = 0 + offset;
indexes[indexCount++] = 0 + offset;
indexes[indexCount++] = 2 + offset;
indexes[indexCount++] = 6 + offset;
//Top Side
indexes[indexCount++] = 6 + offset;
indexes[indexCount++] = 2 + offset;
indexes[indexCount++] = 3 + offset;
indexes[indexCount++] = 3 + offset;
indexes[indexCount++] = 7 + offset;
indexes[indexCount++] = 6 + offset;
//Bottom Side
indexes[indexCount++] = 0 + offset;
indexes[indexCount++] = 4 + offset;
indexes[indexCount++] = 5 + offset;
indexes[indexCount++] = 5 + offset;
indexes[indexCount++] = 1 + offset;
indexes[indexCount++] = 0 + offset;
newPixelCount++;
}
}
}
System.out.println("newPixelCount = " + newPixelCount);
System.out.println("indexCount = " + indexCount);
//Triangle Index - The indices 0,1,2,3 stand for the four vertices
//that you specified for the quad in vertices[].
//int [] indexes = { 2,0,1, 1,3,2 , 6,4,5, 5,7,6};
mesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(vertices));
mesh.setBuffer(Type.TexCoord, 2, BufferUtils.createFloatBuffer(texCoord));
mesh.setBuffer(Type.Index, 3, BufferUtils.createIntBuffer(indexes));
mesh.updateBound();
//Create Spacial
Geometry geo = new Geometry("OurMesh", mesh); // using our custom mesh object
Material mat = new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md");
// TextureKey tk = new TextureKey(“Textures/diamond_pickaxe.png”, false);
TextureKey tk = new TextureKey(“Textures/test.png”, false);
Texture cube1Tex = assetManager.loadTexture(tk);
mat.setTexture(“ColorMap”, cube1Tex);
geo.setMaterial(mat);
rootNode.attachChild(geo);
}
//Take the column and row and divide by the height and width
private Vector2f convertTexCoor(int column, int row, int height, int width) {
float x = (float) column / width; //cast to float otherwise it will always be zero
float y = (float) row / height;
System.out.print(x+","+y + " ");
return new Vector2f(x, y);
}
private class Sprite {
public int[][] array;
public boolean hasAlpha = false;
public int width;
public int height;
}
}
[/java]