class Cube {
float w=0, h=0, d=0;
float tw=0, th=0, td=0;
float x=0, y=0, z=0;
PVector p1=new PVector(), p2=new PVector(), p3=new PVector(), p4=new PVector(), p5=new PVector(), p6=new PVector(), p7=new PVector(), p8=new PVector();
PVector points[] = {p1,p2,p3,p4,p5,p6,p7,p8};
Cube(float x, float y,float z, float w, float h, float d) {
//println("Cube > .");
this.tw = w;
this.th = h;
this.td = d;
this.x = x;
this.y = y;
this.z = z;
computeVertex();
}
void computeVertex() {
//upper
p1.x = x;
p1.y = y;
p1.z = z;
p2.x = x+w;
p2.y = y;
p2.z = z;
p3.x = x+w;
p3.y = y;
p3.z = z+d;
p4.x = x;
p4.y = y;
p4.z = z+d;
// lower
p5.x = x;
p5.y = y+h;
p5.z = z;
p6.x = x+w;
p6.y = y+h;
p6.z = z;
p7.x = x+w;
p7.y = y+h;
p7.z = z+d;
p8.x = x;
p8.y = y+h;
p8.z = z+d;
}
void draw() {
beginShape(QUADS);
vertex(p1.x, p1.y, p1.z);
vertex(p2.x, p2.y, p2.z);
vertex(p3.x, p3.y, p3.z);
vertex(p4.x, p4.y, p4.z);
endShape();
beginShape(QUADS);
vertex(p5.x, p5.y, p5.z);
vertex(p6.x, p6.y, p6.z);
vertex(p7.x, p7.y, p7.z);
vertex(p8.x, p8.y, p8.z);
endShape();
beginShape(QUADS);
vertex(p1.x, p1.y, p1.z);
vertex(p4.x, p4.y, p4.z);
vertex(p8.x, p8.y, p8.z);
vertex(p5.x, p5.y, p5.z);
endShape();
beginShape(QUADS);
vertex(p1.x, p1.y, p1.z);
vertex(p5.x, p5.y, p5.z);
vertex(p6.x, p6.y, p6.z);
vertex(p2.x, p2.y, p2.z);
endShape();
beginShape(QUADS);
vertex(p2.x, p2.y, p2.z);
vertex(p3.x, p3.y, p3.z);
vertex(p7.x, p7.y, p7.z);
vertex(p6.x, p6.y, p6.z);
endShape();
beginShape(QUADS);
vertex(p4.x, p4.y, p4.z);
vertex(p3.x, p3.y, p3.z);
vertex(p7.x, p7.y, p7.z);
vertex(p8.x, p8.y, p8.z);
endShape();
}
boolean update(float x, float y, float z) {
boolean flag = true;
float delta;
this.x = x;
this.y = y;
this.z = z;
//println(this.y);
// easing!
delta = tw - w;
if (abs(delta)>0.1) {
w += delta*easing;
flag = flag&&false;
}
delta = th-h;
if (abs(delta)>0.1) {
h += delta*easing;
flag = flag&&false;
}
delta = td-d;
if (abs(delta)>0.01) {
d += delta*easing;
flag = flag&&false;
}
computeVertex();
return flag;
}
}
import processing.opengl.*;
int k = 100;
float easing = 0.5;
int n= 1;
int max_n = 100 + 1;
Cube cubes[] = new Cube[max_n];
//////////////////////////////////////////////////////////// SETUP
void setup() {
// processing setup
size(640, 360, OPENGL);
//smooth();
noStroke();
// init datas
for (int i=0; i<max_n; i++) {
cubes[i] = new Cube(0, 0, 0, 0, 0, 0);
}
addCube();
addCube();
addCube();
}
//////////////////////////////////////////////////////////// DRAW
void draw() {
background(105, 105, 170);
updateCubes();
computeBoundingBox();
centerCamera();
lights();
drawGrid();
rotateY(2);
if (mousePressed) {
rotateY(map(mouseX, 0, width, 0, TWO_PI));
rotateZ(map(mouseY, 0, height, 0, -TWO_PI));
}
for (int i=0; i<max_n;i++) {
noStroke();
fill(255, 255, 255);
cubes[i].draw();
}
noFill();
stroke(255, 0, 0, 60);
drawBoundingBox();
}
void drawGrid() {
for (int i=1; i<100; i++) {
for (int j=1; j<100; j++) {
pushMatrix();
translate(-200, i*100 - 900, j*100 -1000);
stroke(255, map(j, 1, 100, 0, 55));
noFill();
box(0, 100, 100);
popMatrix();
}
}
}
float fov = PI/3.0;
void centerCamera() {
float h = maxy - miny;
float distance = h / tan((fov)/2);
//if(keyPressed) distance = 500;
camera(AABBcenter.x, AABBcenter.y, distance,
AABBcenter.x, AABBcenter.y, 0,
0, 1, 0);
}
void mousePressed() {
randomAllCubes();
}
void keyPressed() {
if (key == CODED) {
if (keyCode == UP) {
addCube();
}
else if (keyCode == DOWN) {
removeCube();
}
}
}
void computeBoundingBox() {
computeAABB();
}
PVector AABBcenter = new PVector();
float minx, miny, minz, maxx, maxy, maxz;
float w=0,h=0,d=0;
void resetAABB() {
minx=0;
miny=0;
minz=0;
maxx=0;
maxy=0;
maxz=0;
}
void computeAABB() {
resetAABB();
PVector pts[];
PVector p;
Cube c;
for (int i=0; i<max_n;i++) {
cubes[i].computeVertex();
pts = cubes[i].points;
//c = cubes[i];
//pts = {c.p1, c.p2, c.p3, c.p4, c.p5, c.p6, c.p7, c.p8};
for (int j=0; j<pts.length; j++) {
p = pts[j];
minx = min(minx, p.x);
miny = min(miny, p.y);
minz = min(minz, p.z);
maxx = max(maxx, p.x);
maxy = max(maxy, p.y);
maxz = max(maxz, p.z);
}
}
w = maxx - minx;
h = maxy - miny;
d = maxz - minz;
AABBcenter.x = w/2+minx;
AABBcenter.y = h/2+miny;
AABBcenter.z = d/2+minz;
}
void drawBoundingBox() {
translate(AABBcenter.x,AABBcenter.y,AABBcenter.z);
box(w, h, d);
}
void addCube() {
cubes[n] = new Cube(0, 0, 0, random(k) + 5, random(k) + 5, random(k) + 5);
n++;
n = constrain(n, 1, max_n-1);
}
void removeCube() {
n--;
n = constrain(n, 1, max_n-1);
cubes[n].tw = 0;
cubes[n].th = 0;
cubes[n].td = 0;
println(n);
resetAABB();
}
void updateCubes() {
float x=0, y=0, z=0;
for (int i=0; i<max_n;i++) {
if (i!=0) {
// update cubes position for let cubes be attached also with easings with this 2 steps:
// 1: center of lower face
x = (cubes[i-1].p6.x - cubes[i-1].p5.x )/2 + cubes[i-1].x ;
y = cubes[i-1].p5.y;
z = (cubes[i-1].p8.z - cubes[i-1].p5.z )/2 + cubes[i-1].z ;
// // debug:
// pushMatrix();
// translate(x, y, z);
// fill(200, 0, 0);
// sphere(5);
// popMatrix();
// 2: fit for next cube dimension
x -= cubes[i].w/2;
z -= cubes[i].d/2;
}
// update!
cubes[i].update(x, y, z);
}
}
void randomAllCubes() { //TODO update and only generate new one
background(255, 0, 0);
float x=0, y=0, z=0;
for (int i=0; i<n; i++) {
cubes[i] = new Cube(x, y, z, random(k) + 5, random(k) + 5, random(k) + 5);
//cubes[i] = new Cube(0,0,0,100,100,100);
}
for (int i=n; i<max_n; i++) {
cubes[i] = new Cube(0, 0, 0, 0, 0, 0);
}
resetAABB();
}
Push UP and DOWN for add a box.
This sketch is for testing the formula for keep the camera at the exact distance, moving it near and far to obsessivly center the brick-tower in the viewport