xxxxxxxxxx
// Based on original Processing sketch: 3D arcPlay engine by jWilliamDunn 2013
// ported to p5 jWilliamDunn 2019
// any key toggles fill/stroke mode
var easycam, angle=Math.PI/4, filler=true, t=0, ax=false, animate=true,
segmentAngle=3,
segmentDepth=10,
camState = {
distance: 1100,
center : [0, 0, 0],
rotation: [0.02, 0.28, -0.36, 0.889]
// 0.159, -0.17, -0.337, 0.912
},
arcs=[];
function setup() {
createCanvas(1112, 834, WEBGL);
perspective(PI/8, width/height, 1, 6000);
easycam = createEasyCam({distance:450});
// set initial camera state
easycam.setState(camState, 1000); // animate to camState on 1 second
easycam.state_reset = camState; // state to use on reset
// prevent context menus
document.oncontextmenu = function() { return false; }
// prevent other default mouse behaviors
// BUT, it causes keyPressed() to not work in Chrome v77
//document.onmousedown = function() { return false; }
noStroke();
specularMaterial(0,0,255);
for(var i=0; i<20; i++) {
arcs.push(new Arc3D(i));
}
}
function draw() {
if(!easycam) return;
background(0);
if(ax)drawAxes();
for(let i=0; i<20; i++) {
arcs[i].display();
}
}
function Arc3D(i) {
this.id = i;
this.innerRadius = 30 + random(i*5,i*10+50); // pick an inner radius based on the Arc id
this.outerRadius = this.innerRadius + 10 + random(i+10); // vary the outer radius also
this.radius = this.innerRadius + (this.outerRadius - this.innerRadius) / 2;
this.startAngle = random(360); // choose a random starting angle
this.lengthAngle = 40 + random(120);// and a length of angular Arc
this.segmentHeight=sin(radians(segmentAngle/2))*2*this.outerRadius; // compute the height based on angle and radius
this.level = random(-20,20); // vary the position of the Arc in Z space
this.lengthDelta = random(-1,1); // how fast the length will grow/shrink
this.startDelta = random(-2*(100-i)/100,2*(100-i)/100); // how fast the starting angle varies
this.display = function() {
t+=0.0001;
beginShape();
// render the Arc by creating a series of 3D boxes in increments around a circle
//rotateZ(TAU*noise(t*(20-this.id)));
for (let n = 0; n < this.lengthAngle/segmentAngle; n++) {
push();
translate(this.radius*cos(radians(this.startAngle+n*segmentAngle)), this.innerRadius*sin(radians(this.startAngle+n*segmentAngle)), this.level); // polar to cartesian
rotateZ(radians(this.startAngle+n*segmentAngle)); // orient the box toward the center point
normalMaterial();
box(this.outerRadius-this.innerRadius,this.segmentHeight,segmentDepth);
pop();
}
endShape();
if(animate){
this.startAngle += this.startDelta; // advance the Arc along the ring by the startDelta
this.lengthAngle += this.lengthDelta; // adjust the length of the Arc
if (this.lengthAngle>200)
this.lengthDelta = -this.lengthDelta;
if (this.lengthAngle<20)
this.lengthDelta = -this.lengthDelta;
}
}
}
function keyPressed(){
if(key=='c') console.log(easycam.getState()); // useful for setting initial state
if(key=='v') {
filler = !filler;
if(filler) {
noStroke();
fill(255);
specularMaterial(0,0,255);
} else {
stroke(0,246,255);
noFill();
strokeWeight(0.5);
}
}
if(key=='x') ax=!ax;
if(key==' ') animate=!animate;
}
function drawAxes(){
push();
noStroke();
fill(127,0,0); // X
translate(400,0,0);
box(800,1,1);
pop();
push();
noStroke();
fill(0,127,0); // Y
translate(0,400,0);
box(1,800,1);
pop();
push();
noStroke();
fill(0,0,127); // Z
translate(0,0,400);
box(1,1,800);
pop();
}
function mousePressed(){
save('pix.jpg');
}