Map 3D coordinates to 2D texture pixels

I stuck at implementing proper mapping XYZ coordinates of 3D grid to UV coordinates of pixels on texture.
I have big cube made of many smaller cubes and I need to change RGBA color of each smaller cube individually.
I tryed to make implementation of such 3D to 2D and back maping, but seems i just miss something little.
On this image all cubes must make black and white slices, but they did not.
%D0%91%D0%B5%D0%B7%D1%8B%D0%BC%D1%8F%D0%BD%D0%BD%D1%8B%D0%B9
My sketch

int ar_size = 15;// number of cubes is ar_size^3
float cube_scale = 500; //hardcoded scaling
int texture_size = int(sqrt(ar_size*ar_size*ar_size) + 1);

PShape bigCube;
PGraphics texture;
int q[][] = new int[ar_size* ar_size*ar_size][4];

int fcount, lastm;
float frate;
int fint = 3;

void setup()  {
  size(640, 640, P3D);  
 // frameRate(60);
 // hint(ENABLE_DEPTH_SORT);
  //hint(DISABLE_DEPTH_TEST);;

// init cubes order maping
for(int i=0;i<ar_size;i++){
  for(int j=0;j<ar_size;j++){
    for(int k=0;k<ar_size;k++){   
     q[i+j*ar_size+k*ar_size*ar_size][0] = i;
     q[i+j*ar_size+k*ar_size*ar_size][1] = j;   
     q[i+j*ar_size+k*ar_size*ar_size][2] = k;
     q[i+j*ar_size+k*ar_size*ar_size][3] = i+j*ar_size+k*ar_size*ar_size;
    }
  }
}

//bubble sort of cubes for drawing order
for(int i=0; i<ar_size*ar_size*ar_size-1; i++){
  for(int j=i+1; j<ar_size*ar_size*ar_size; j++){
    int s1 = q[i][0]+q[i][1]+q[i][2];
    int s2 = q[j][0]+q[j][1]+q[j][2];
    if(s1<s2){
      int t1 = q[i][0];
      int t2 = q[i][1];
      int t3 = q[i][2];
      int t4 = q[i][3];
      q[i][0]=q[j][0];
      q[i][1]=q[j][1];
      q[i][2]=q[j][2];
      q[i][3]=q[j][3];
      q[j][0]=t1;
      q[j][1]=t2;
      q[j][2]=t3;
      q[j][3]=t4;
    }
  }
}
  texture = createGraphics(texture_size, texture_size, P3D);
  texture.beginDraw();
  texture.background(0,255,0);
  texture.endDraw();
  
  float size = cube_scale/(2*ar_size);
  bigCube = createShape(PShape.GROUP);
  for(int i=0; i<ar_size*ar_size*ar_size; i++){ 
    PVector uv = map3dto2d(q[i][0],q[i][1],q[i][2]); 

    PShape cube = createShape();            
    cube.beginShape(QUAD);
    cube.texture(texture);
    cube.noStroke();    
    setCube(cube,    
       q[i][0]*size-size*ar_size/2,
       q[i][1]*size-size*ar_size/2,
       q[i][2]*size-size*ar_size/2,
       int(uv.x),
       int(uv.y),
       size/2);
    cube.endShape();
    bigCube.addChild(cube);     
  }
}

PVector map3dto2d(int x, int y,int z){
 int u,v;
 int r = x + y*ar_size+z*ar_size*ar_size;
 u = r % texture_size;
 v = r / texture_size;
 return new PVector(u,v);
}

PVector map2dto3d(int u,int v){
  int x,y,z;
  int r = u + v*texture_size;
  x = r % ar_size;
  r /= ar_size;
  y = r % ar_size;
  r /= ar_size;
  z = r;
  return new PVector(x,y,z);  
}


// place only 3 "front" faces of cube to the world and map all faces to same pixel on texture
void setCube(PShape cube,float x,float y,float z,int pixelIdX,int pixelIdY,float size){
  cube.vertex(x-size,y-size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y+size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y+size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y-size,z-size,pixelIdX,pixelIdY); 
   
  cube.vertex(x-size,y-size,z+size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y-size,z+size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y-size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y-size,z-size,pixelIdX,pixelIdY);
    
  cube.vertex(x-size,y-size,z+size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y-size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y+size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y+size,z+size,pixelIdX,pixelIdY);
}

void draw()  {
  colorMode(HSB,100,100,100,100);
  background(50,100,100);

  translate(width/2, height/2, 0);
  rotateX(0.05*210*PI/8 + (mouseY-height/2)*0.004);  
  rotateY(0.05*285*PI/8 + (mouseX-width/2)*0.004);
  
  //update texture
  texture.loadPixels();
  for(int i=0;i<ar_size*ar_size*ar_size;i++){    
    int u = i % texture_size;
    int v = i / texture_size;
    PVector vec = map2dto3d(u,v);
    int x = int(vec.x);
    int y = int(vec.y);
    int z = int(vec.z);
    //int cl = 100*(x % 2);
    //int cl = 100*(y % 2);
    int cl = 100*(z % 2);
    texture.pixels[u + v*texture_size] = color(0,0,cl,20);
  }  
  texture.updatePixels();
  
  //draw cubes
  shape(bigCube);
  
  //calc FPS  
  fcount += 1;
  int m = millis();      
  if (m - lastm > 1000 * fint) {
    frate = float(fcount) / fint;
    fcount = 0;
    lastm = m;
    println("fps: " + frate); 
  } 
}
1 Like

I think problem can be about texture neightbor pixels values is mixed.
LIke on this picture instead of 1 black opaque cube i have 2 places with 2 transparent cubes.


sketch

int ar_size = 8;// number of cubes is ar_size^3
float cube_scale = 500; //hardcoded scaling
int texture_size = int(sqrt(ar_size*ar_size*ar_size)+1);


PShape bigCube;
PGraphics texture;
int q[][] = new int[ar_size* ar_size*ar_size][4];

int fcount, lastm;
float frate;
int fint = 3;

void setup()  {
  size(640, 640, P3D);  
 // frameRate(60);
 // hint(ENABLE_DEPTH_SORT);
  //hint(DISABLE_DEPTH_TEST);;

// init cubes order maping
for(int i=0;i<ar_size;i++){
  for(int j=0;j<ar_size;j++){
    for(int k=0;k<ar_size;k++){   
     q[i+j*ar_size+k*ar_size*ar_size][0] = i;
     q[i+j*ar_size+k*ar_size*ar_size][1] = j;   
     q[i+j*ar_size+k*ar_size*ar_size][2] = k;
     q[i+j*ar_size+k*ar_size*ar_size][3] = i+j*ar_size+k*ar_size*ar_size;
    }
  }
}

//bubble sort of cubes for drawing order
for(int i=0; i<ar_size*ar_size*ar_size-1; i++){
  for(int j=i+1; j<ar_size*ar_size*ar_size; j++){
    int s1 = q[i][0]+q[i][1]+q[i][2];
    int s2 = q[j][0]+q[j][1]+q[j][2];
    if(s1<s2){
      int t1 = q[i][0];
      int t2 = q[i][1];
      int t3 = q[i][2];
      int t4 = q[i][3];
      q[i][0]=q[j][0];
      q[i][1]=q[j][1];
      q[i][2]=q[j][2];
      q[i][3]=q[j][3];
      q[j][0]=t1;
      q[j][1]=t2;
      q[j][2]=t3;
      q[j][3]=t4;
    }
  }
}
  texture = createGraphics(texture_size, texture_size, P3D);
  texture.beginDraw();
  texture.background(0,255,0);
  texture.endDraw();
  
  float size = cube_scale/(2*ar_size);
  bigCube = createShape(PShape.GROUP);
  for(int i=0; i<ar_size*ar_size*ar_size; i++){ 
    PVector uv = map3dto2d(q[i][0],q[i][1],q[i][2]); 

    PShape cube = createShape();            
    cube.beginShape(QUAD);
    cube.texture(texture);
    cube.noStroke();    
    setCube(cube,    
       q[i][0]*size-size*ar_size/2,
       q[i][1]*size-size*ar_size/2,
       q[i][2]*size-size*ar_size/2,
       int(uv.x),
       int(uv.y),
       size/2);
    cube.endShape();
    bigCube.addChild(cube);     
  }
}

PVector map3dto2d(int x, int y,int z){
 int u,v;
 int r = x + y*ar_size+z*ar_size*ar_size;
 u = r % texture_size;
 v = r / texture_size;
 return new PVector(u,v);
}

PVector map2dto3d(int u,int v){
  int x,y,z;
  int r = u + v*texture_size;
  x = r % ar_size;
  r /= ar_size;
  y = r % ar_size;
  r /= ar_size;
  z = r;
  return new PVector(x,y,z);  
}


// place only 3 "front" faces of cube to the world and map all faces to same pixel on texture
void setCube(PShape cube,float x,float y,float z,int pixelIdX,int pixelIdY,float size){
  cube.vertex(x-size,y-size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y+size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y+size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y-size,z-size,pixelIdX,pixelIdY); 
   
  cube.vertex(x-size,y-size,z+size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y-size,z+size,pixelIdX,pixelIdY);
  cube.vertex(x+size,y-size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y-size,z-size,pixelIdX,pixelIdY);
    
  cube.vertex(x-size,y-size,z+size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y-size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y+size,z-size,pixelIdX,pixelIdY);
  cube.vertex(x-size,y+size,z+size,pixelIdX,pixelIdY);
}
int p = 0;
void draw()  {
  colorMode(HSB,100,100,100,100);
  background(50,100,100);

  translate(width/2, height/2, 0);
  rotateX(0.05*210*PI/8 + (mouseY-height/2)*0.004);  
  rotateY(0.05*285*PI/8 + (mouseX-width/2)*0.004);
  
  //update texture
  texture.loadPixels();
  p += 1;
  for(int i=0;i<ar_size*ar_size*ar_size;i++){    
    int u = i % texture_size;
    int v = i / texture_size;
    PVector vec = map2dto3d(u,v);
    int x = int(vec.x);
    int y = int(vec.y);
    int z = int(vec.z);
    //int cl = 100*(x % 2);
    //int cl = 100*(y % 2);
    int cl = 100*(z % 2);
    
    int k = 10;
    if (p / k > ar_size*ar_size*ar_size){ p = 0;}
    if (u + v*texture_size == (p/k)) {
        texture.pixels[u + v*texture_size] = color(0,0,000,100);
        println(p/k);
    }
    else{
      texture.pixels[u + v*texture_size] = color(0,0,cl,1);}
  }  
  
  texture.updatePixels();
  
  //draw cubes
  shape(bigCube);
  //image(texture,-200,-200,400,400);
  //calc FPS  
  fcount += 1;
  int m = millis();      
  if (m - lastm > 1000 * fint) {
    frate = float(fcount) / fint;
    fcount = 0;
    lastm = m;
    println("fps: " + frate); 
  } 
}

okay, I see problem is really in texture with nearest pixels are blurred.
I do not know how to make it work in right way, but right now I made workaround using bigger texture and drawing 4x4 rect instead ot pixel.
%D0%91%D0%B5%D0%B7%D1%8B%D0%BC%D1%8F%D0%BD%D0%BD%D1%8B%D0%B9