// This is a template for creating a looping animation in p5.js (JavaScript).
// When you press the 'F' key, this program will export a series of images into
// your default Downloads folder. These can then be made into an animated gif.
// This code is known to work with p5.js version 0.6.0
// Prof. Golan Levin, 28 January 2018
// INSTRUCTIONS FOR EXPORTING FRAMES (from which to make a GIF):
// 1. Run a local server, using instructions from here:
// https://github.com/processing/p5.js/wiki/Local-server
// 2. Set the bEnableExport variable to true.
// 3. Set the myNickname variable to your name.
// 4. Run the program from Chrome, press 'f'.
// Look in your 'Downloads' folder for the generated frames.
// 5. Note: Retina screens may export frames at twice the resolution.
//===================================================
// User-modifiable global variables.
var myNickname = "rigatoni";
var nFramesInLoop = 60;
var bEnableExport = true;
// Other global variables you don't need to touch.
var nElapsedFrames;
var bRecording;
var theCanvas;
//===================================================
function setup() {
theCanvas = createCanvas(720, 720, WEBGL);
bRecording = false;
nElapsedFrames = 0;
}
//===================================================
function keyTyped() {
if (bEnableExport) {
if ((key === 'f') || (key === 'F')) {
bRecording = true;
nElapsedFrames = 0;
}
}
}
//===================================================
function draw() {
// Compute a percentage (0...1) representing where we are in the loop.
var percentCompleteFraction = 0;
if (bRecording) {
percentCompleteFraction = float(nElapsedFrames) / float(nFramesInLoop);
} else {
percentCompleteFraction = float(frameCount % nFramesInLoop) / float(nFramesInLoop);
}
// Render the design, based on that percentage.
// This function renderMyDesign() is the one for you to change.
renderMyDesign (percentCompleteFraction);
// If we're recording the output, save the frame to a file.
// Note that the output images may be 2x large if you have a Retina mac.
// You can compile these frames into an animated GIF using a tool like:
if (bRecording && bEnableExport) {
var frameOutputFilename = myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png";
print("Saving output image: " + frameOutputFilename);
saveCanvas(theCanvas, frameOutputFilename, 'png');
nElapsedFrames++;
if (nElapsedFrames >= nFramesInLoop) {
bRecording = false;
}
}
}
//===================================================
function renderMyDesign (percent) {
background(180);
var cube = new Hypercube(500, percent)
rotateY(percent*PI)
cube.Draw()
}
function Hypercube(size, margin) {
this.points = []
margin -= 1
margin = doubleExponentialSigmoid(margin)
for(var i=0; i<16; i++) {
var j = i
var w = floor(j/8)*margin
j=j%8
var stereo = 1/(2-w)
var z = floor(j/4)*stereo-(0.5*stereo)
j=j%4
var y = floor(j/2)*stereo-(0.5*stereo)
j=j%2
var x = floor(j/1)*stereo-(0.5*stereo)
this.points[i] = new P4(x*size, y*size, z*size, 0)
}
this.Draw = function() {
fill(225,15)
var front = new Face(this.points[4], this.points[5],
this.points[6], this.points[7])
var back = new Face(this.points[0], this.points[1],
this.points[2], this.points[3])
var left = new Face(this.points[0], this.points[2],
this.points[4], this.points[6])
var right = new Face(this.points[1], this.points[3],
this.points[5], this.points[7])
var top = new Face(this.points[2], this.points[3],
this.points[6], this.points[7])
var bottom = new Face(this.points[0], this.points[1],
this.points[4], this.points[5])
var sFront = new Face(this.points[12], this.points[13],
this.points[14], this.points[15])
var sBack = new Face(this.points[8], this.points[9],
this.points[10], this.points[11])
var sLeft = new Face(this.points[8], this.points[10],
this.points[12], this.points[14])
var sRight = new Face(this.points[9], this.points[11],
this.points[13], this.points[15])
var sTop = new Face(this.points[10], this.points[11],
this.points[14], this.points[15])
var sBottom = new Face(this.points[8], this.points[9],
this.points[12], this.points[13])
var pfront = new Face(this.points[4], this.points[5],
this.points[12], this.points[13])
var pback = new Face(this.points[0], this.points[1],
this.points[8], this.points[9])
var pleft = new Face(this.points[0], this.points[2],
this.points[8], this.points[10])
var pright = new Face(this.points[1], this.points[3],
this.points[9], this.points[11])
var ptop = new Face(this.points[2], this.points[3],
this.points[10], this.points[11])
var pbottom = new Face(this.points[0], this.points[4],
this.points[8], this.points[12])
var psFront = new Face(this.points[1], this.points[5],
this.points[9], this.points[13])
var psBack = new Face(this.points[5], this.points[7],
this.points[13], this.points[15])
var psLeft = new Face(this.points[3], this.points[7],
this.points[11], this.points[15])
var psRight = new Face(this.points[2], this.points[6],
this.points[10], this.points[14])
var psTop = new Face(this.points[6], this.points[7],
this.points[14], this.points[15])
var psBottom = new Face(this.points[4], this.points[6],
this.points[12], this.points[14])
front.Draw()
back.Draw()
left.Draw()
right.Draw()
sFront.Draw()
sBack.Draw()
sLeft.Draw()
sRight.Draw()
pfront.Draw()
pback.Draw()
pleft.Draw()
pright.Draw()
psFront.Draw()
psBack.Draw()
psLeft.Draw()
psRight.Draw()
}
}
function Face(p1, p2, p3, p4) {
var distance = 200
this.p1 = p1
this.p2 = p2
this.p3 = p3
this.p4 = p4
this.Draw = function() {
beginShape()
vertex(this.p1.x,this.p1.y,this.p1.z)
vertex(this.p2.x,this.p2.y,this.p2.z)
vertex(this.p4.x,this.p4.y,this.p4.z)
vertex(this.p3.x,this.p3.y,this.p3.z)
endShape(CLOSE)
}
this.Print = function() {
this.p1.Print()
this.p2.Print()
this.p3.Print()
this.p4.Print()
}
}
function P4(x,y,z,w) {
this.x = x
this.y = y
this.z = z
this.w = w
this.Print = function() {
print(this.x, this.y, this.z, this.w)
}
this.ScalarMult = function(multiplier) {
this.x*=multiplier
this.y*=multiplier
this.z*=multiplier
this.w*=multiplier
}
}
// Symmetric double-element sigmoid function ('_a' is the slope)
// See https://github.com/IDMNYU/p5.js-func/blob/master/lib/p5.func.js
// From: https://idmnyu.github.io/p5.js-func/
//===================================================
function doubleExponentialSigmoid (_x, _a){
if(!_a) _a = 0.75; // default
var min_param_a = 0.0 + Number.EPSILON;
var max_param_a = 1.0 - Number.EPSILON;
_a = constrain(_a, min_param_a, max_param_a);
_a = 1-_a;
var _y = 0;
if (_x<=0.5){
_y = (pow(2.0*_x, 1.0/_a))/2.0;
}
else {
_y = 1.0 - (pow(2.0*(1.0-_x), 1.0/_a))/2.0;
}
return(_y);
} |