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.
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);
}
}