Draggable [] anchor = new Draggable[2]; Draggable [] control = new Draggable[2]; float t = 0.0; void setup(){ size(400,400,P3D); anchor[0] = new Draggable (100,100,100,10,color(100,100,200),color(100,200,200),"rect"); anchor[1] = new Draggable (300,300,0,10,color(100,100,200),color(100,200,200),"rect"); control[0] = new Draggable (100,300,-100,10,color(100,100,200),color(100,200,200),"ellipse"); control[1] = new Draggable (300,100,0,10,color(100,100,200),color(100,200,200),"ellipse"); ellipseMode(CENTER); rectMode(CENTER); } void draw(){ background(144,130,140); directionalLight(100,100,100,0,0,-1); stroke(0); t = (t+0.01)%1.0; noStroke(); fill(255); pushMatrix(); translate( bezierPoint(anchor[0].x,control[0].x,control[1].x,anchor[1].x,t), bezierPoint(anchor[0].y,control[0].y,control[1].y,anchor[1].y,t), bezierPoint(anchor[0].z,control[0].z,control[1].z,anchor[1].z,t)); sphere(10); popMatrix(); pointLight(255,255,255, bezierPoint(anchor[0].x,control[0].x,control[1].x,anchor[1].x,t), bezierPoint(anchor[0].y,control[0].y,control[1].y,anchor[1].y,t), bezierPoint(anchor[0].z,control[0].z,control[1].z,anchor[1].z,t)); stroke(0); bezier( anchor[0].x,anchor[0].y,anchor[0].z,control[0].x,control[0].y,control[0].z, control[1].x,control[1].y,control[1].z,anchor[1].x,anchor[1].y,anchor[1].z); for (int i = 0; i < 2; i++){ anchor[i].draw(); control[i].draw(); anchor[i].update(); control[i].update(); } } class Draggable { int x,y,z,size,c1,c2; String mode; boolean locked = false; ; Draggable (int x, int y, int z, int size, color c1, color c2, String mode) { this.x = x; this.y = y; this.size = size; this.c1 = c1; this.c2 = c2; this.mode = mode; } void draw(){ noStroke(); if (locked || over()){ fill(c1); } else{ fill(c2); } if (mode == "rect"){ pushMatrix(); translate(x,y,z); box(size*2,size*2,size*2); popMatrix(); noFill(); stroke(c1); rect(x,y,size*2,size*2); } if (mode == "ellipse"){ pushMatrix(); translate(x,y,z); sphere(size); popMatrix(); noFill(); stroke(c1); ellipse(x,y,size*2,size*2); } } void update(){ if (over() && mousePressed){ locked = true; } if (locked){ x = mouseX; y = mouseY; } if (!mousePressed){ locked = false; } if (over() && keyPressed){ switch(key){ case '-': case '_': z -= 2; break; case '=': case '+': z += 2; break; } } } boolean over(){ if (mouseX <= x+size && mouseX >= x-size && mouseY <= y+size && mouseY >= y-size){ return true; } else{ return false; } } } float BezierPoint (float anchor0, float control0, float control1, float anchor1, float t) { float a = anchor1 - 3 * control1 + 3 * control0 - anchor0; float b = 3 * control1 - 6 * control0 + 3 * anchor0; float c = 3 * control0 - 3 * anchor0; float d = anchor0; return pow(t,3) * a + pow(t,2) * b + t * c + d; }