# 3D image transform question

hi there! im recreating this effect : Login • Instagram
but my looks not very good.
this is my looks like:

I think that in the original video, where the gray value is high, It’s not that the height of boxes change, but more boxes are generated, how can i made that? Then I used sin() to control the switch of two pictures, but it’s not good, is there any other good choice?

My code:
<

``````PImage source1, source2;
PImage destination;
float t = 1;

void setup() {
size(1000, 1000, P3D);
destination = createImage(width, height, RGB);
}

void draw() {
background(0);
float tiles = 500;
float tileSize = width/tiles;

directionalLight(126, 126, 126, 1, -1, 0);
directionalLight(126, 126, 126, 1, -1, 0);
ambientLight(100, 100, 100);

t += 0.2;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int loc = x + y * width;
color c1 = source1.pixels[loc];
color c2 = source2.pixels[loc];

float d1 = brightness(c1);
float d2 = brightness(c2);
float d = map(cos(t), 0, 1, d1, d2);

destination.pixels[loc] = color(d);
}
}
//destination.updatePixels();

push();
translate(width/2, height/2);
rotateY(map(mouseX, 0, width, -PI, PI));
rotateX(map(mouseY, 0, height, PI, -PI));

for (int x = 0; x < tiles; x++) {
for (int y = 0; y < tiles; y++) {
color c = destination.get(int(x * tileSize), int(y * tileSize));
float b = map(brightness(c), 0, 255, 1, 0);
float z = map(b, 0, 1, 100, -100);
float wave = map(cos(radians(frameCount + z + z )), -1, 1, -2, 2);
push();
fill(255);
translate(x * tileSize - width/2, y * tileSize - height/2, z * wave - 300);
noStroke();
box(tileSize * b, tileSize * b, tileSize * b * 10 );
pop();
}
}
pop();
}
``````

hi! welcome to the forum!

please format your code with </> button so it’s easier to see and copy/paste. also if you can provide example images, that would be better.

what I see in Tim’s video is that when greyscale value is high (or low, I don’t know), the z position of the boxes change - plus, the sizes change at certain threshold. regarding your question with `sin()` as well, I think they are using easing functions to make smooth change. There are libraries like Ani but I found they are confusing so I adapted easing functions from processing-penner-easing/src at master · jesusgollonet/processing-penner-easing · GitHub

``````// adapted from https://github.com/jesusgollonet/processing-penner-easing/tree/master/src
float easeInOutLinear (float t) {
float b = 0, c = 1, d = 1;
return c*t/d + b;
}

float b = 0, c = 1, d = 1;
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
}

float easeInOutCubic (float t) {
float b = 0, c = 1, d = 1;
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
}

float easeInOutQuart(float t) {
float b = 0, c = 1, d = 1;
if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
return -c/2 * ((t-=2)*t*t*t - 2) + b;
}

float easeInOutQuint (float t) {
float b = 0, c = 1, d = 1;
if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
return c/2*((t-=2)*t*t*t*t + 2) + b;
}

void setup() {
size(800, 800);
}

void draw() {
background(0);
float T = millis() * 0.001;
float t = (T / 2) % 2;
if (t > 1) t = 2 - t; // back and forth
float ystep = height / 10;
float r = 100;
push();
{
translate(0, ystep);
float x = easeInOutLinear(t);
ellipse(x * width, 0, r, r);
translate(0, ystep);
}
{
translate(0, ystep);
ellipse(x * width, 0, r, r);
translate(0, ystep);
}
{
translate(0, ystep);
float x = easeInOutCubic(t);
ellipse(x * width, 0, r, r);
translate(0, ystep);
}
{
translate(0, ystep);
float x = easeInOutQuart(t);
ellipse(x * width, 0, r, r);
translate(0, ystep);
}
{
translate(0, ystep);
float x = easeInOutQuint(t);
ellipse(x * width, 0, r, r);
translate(0, ystep);
}
pop();

push();
translate(width / 2, 0);
rectMode(CENTER);
{
translate(0, ystep);
push();
float x = easeInOutLinear(t);
rotate(x * PI * 2);
rect(0, 0, r, r);
pop();
translate(0, ystep);
}
{
translate(0, ystep);
push();
rotate(x * PI * 2);
rect(0, 0, r, r);
pop();
translate(0, ystep);
}
{
translate(0, ystep);
push();
float x = easeInOutCubic(t);
rotate(x * PI * 2);
rect(0, 0, r, r);
pop();
translate(0, ystep);
}
{
translate(0, ystep);
push();
float x = easeInOutQuart(t);
rotate(x * PI * 2);
rect(0, 0, r, r);
pop();
translate(0, ystep);
}
{
translate(0, ystep);
push();
float x = easeInOutQuint(t);
rotate(x * PI * 2);
rect(0, 0, r, r);
pop();
translate(0, ystep);
}
pop();
}
``````

you can see that the lower ones’ movements are more crisp and human like… note that you have to clamp the input values of `easeInOut*` always between 0 to 1.