Hello,
I am fairly new to Processing and coding in general. I have been trying to replicate a creation I found on the homepage of a studio called Yes. See www.yes.studio
I have got quite close, managing to create a number of sketches which, separately, kind of produce the required functionality. I am however struggling to put it all together.
My main stumbling block at the moment is arranging PVectors out in the required pattern - I’m also not sure exactly what the required layout is. I don’t think its concentric rings of points/ellipses. Almost looks like a spiral galaxy formation.
I have got a sketch working that does achieves the 3D rotation and shrinks the ellipses when the mouse is close (although this isn’t 100% correct).
Anyway, here is my code, I would really appreciate any suggestions towards how I might get closer to my goal.
The main sketch:
float angleX = 0;
float angleY = 0;
float angleZ = 0;
PVector[] points = new PVector[8];
void setup() {
size(600, 600);
points[0] = new PVector(-0.5, -0.5, 0);
points[1] = new PVector(0.5, -0.5, 0);
points[2] = new PVector(0.5, 0.5, 0);
points[3] = new PVector(-0.5, 0.5, 0);
points[4] = new PVector(-1, -1, 0);
points[5] = new PVector(1, -1, 0);
points[6] = new PVector(1, 1, 0);
points[7] = new PVector(-1, 1, 0);
}
void draw() {
background(0);
translate(width/2, height/2);
noStroke();
fill(0, 255, 0);
// Rotation matricies
float[][] rotationZ = {
{ cos(angleZ), -sin(angleZ), 0},
{ sin(angleZ), cos(angleZ), 0},
{ 0, 0, 1}
};
float[][] rotationX = {
{ 1, 0, 0},
{ 0, cos(angleX), -sin(angleX)},
{ 0, sin(angleX), cos(angleX)}
};
float[][] rotationY = {
{ cos(angleY), 0, sin(angleY)},
{ 0, 1, 0},
{ -sin(angleY), 0, cos(angleY)}
};
for (PVector v : points) {
//Compound rotation about the X and Y axis
PVector rotated = matmul(rotationY, (matmul(rotationX, v)));
float distance = 2; //Projection distance
float z = 1 / (distance - rotated.z);
float[][] projection = {
{z, 0, 0},
{0, z, 0}
};
PVector projected2d = matmul(projection, rotated);
projected2d.mult(100); //Scale up
//As mouse gets closer to ellipse shrink it diameter
float d = dist(projected2d.x, projected2d.y, mouseX, mouseY);
float maxDist = dist(0, 0, width/2, height/2);
float diameter = map(d, 0, maxDist, 30, 0);
ellipse(projected2d.x, projected2d.y, diameter, diameter);
}
//Calculate the angle to rotate about the Y axis
float dY = dist(mouseX, 0, width/2, 0);
float maxDistY = dist(0, 0, width/2, 0);
float rotateItY;
if (mouseX < width/2) {
rotateItY = map(dY, 0, maxDistY, 0, -45);
} else {
rotateItY = map(dY, 0, maxDistY, 0, 45);
}
//Calculate the angle to rotate about the X axis
float dX = dist(0, mouseY, 0, height/2);
float maxDistX = dist(0, 0, 0, height/2);
float rotateItX;
if (mouseY < height/2) {
rotateItX = map(dX, 0, maxDistX, 0, 45);
} else {
rotateItX = map(dX, 0, maxDistX, 0, -45);
}
angleY = radians(rotateItY);
angleX = radians(rotateItX);
}
Shiffman’s 3D rotation matrix functions etc:
// Daniel Shiffman
// http://youtube.com/thecodingtrain
// http://codingtra.in
// Coding Challenge #112: 3D Rendering with Rotation and Projection
// https://youtu.be/p4Iz0XJY-Qk
// Matrix Multiplication
// https://youtu.be/tzsgS19RRc8
float[][] vecToMatrix(PVector v) {
float[][] m = new float[3][1];
m[0][0] = v.x;
m[1][0] = v.y;
m[2][0] = v.z;
return m;
}
PVector matrixToVec(float[][] m) {
PVector v = new PVector();
v.x = m[0][0];
v.y = m[1][0];
if (m.length > 2) {
v.z = m[2][0];
}
return v;
}
void logMatrix(float[][] m) {
int cols = m[0].length;
int rows = m.length;
println(rows + "x" + cols);
println("----------------");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
print(m[i][j] + " ");
}
println();
}
println();
}
PVector matmul(float[][] a, PVector b) {
float[][] m = vecToMatrix(b);
return matrixToVec(matmul(a,m));
}
float[][] matmul(float[][] a, float[][] b) {
int colsA = a[0].length;
int rowsA = a.length;
int colsB = b[0].length;
int rowsB = b.length;
if (colsA != rowsB) {
println("Columns of A must match rows of B");
return null;
}
float result[][] = new float[rowsA][colsB];
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
float sum = 0;
for (int k = 0; k < colsA; k++) {
sum += a[i][k] * b[k][j];
}
result[i][j] = sum;
}
}
return result;
}
Thanks