Skip to content

Instantly share code, notes, and snippets.

@edeetee
Forked from dribnet/.block
Created September 20, 2017 06:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edeetee/5bef732021648f8262fa297febbcf8f5 to your computer and use it in GitHub Desktop.
Save edeetee/5bef732021648f8262fa297febbcf8f5 to your computer and use it in GitHub Desktop.
17.2.MDDN342 PS3
license: mit
function resetFocusedRandom() {
return Math.seedrandom(arguments);
}
function focusedRandom(min, max, focus, mean) {
// console.log("hello")
if(max === undefined) {
max = min;
min = 0;
}
if(focus === undefined) {
focus = 1.0;
}
if(mean === undefined) {
mean = (min + max) / 2.0;
}
if(focus == 0) {
return d3.randomUniform(min, max)();
}
else if(focus < 0) {
focus = -1 / focus;
}
sigma = (max - mean) / focus;
val = d3.randomNormal(mean, sigma)();
if (val > min && val < max) {
return val;
}
return d3.randomUniform(min, max)();
}
// note: this file is poorly named - it can generally be ignored.
// helper functions below for supporting blocks/purview
function saveBlocksImages(doZoom) {
if(doZoom == null) {
doZoom = false;
}
// generate 960x500 preview.jpg of entire canvas
// TODO: should this be recycled?
var offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 960;
offscreenCanvas.height = 500;
var context = offscreenCanvas.getContext('2d');
// background is flat white
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 960, 500);
context.drawImage(this.canvas, 0, 0, 960, 500);
// save to browser
var downloadMime = 'image/octet-stream';
var imageData = offscreenCanvas.toDataURL('image/jpeg');
imageData = imageData.replace('image/jpeg', downloadMime);
p5.prototype.downloadFile(imageData, 'preview.jpg', 'jpg');
// generate 230x120 thumbnail.png centered on mouse
offscreenCanvas.width = 230;
offscreenCanvas.height = 120;
// background is flat white
context = offscreenCanvas.getContext('2d');
context.fillStyle="#FFFFFF";
context.fillRect(0, 0, 230, 120);
if(doZoom) {
// pixelDensity does the right thing on retina displays
var pd = this._pixelDensity;
var sx = pd * mouseX - pd * 230/2;
var sy = pd * mouseY - pd * 120/2;
var sw = pd * 230;
var sh = pd * 120;
// bounds checking - just displace if necessary
if (sx < 0) {
sx = 0;
}
if (sx > this.canvas.width - sw) {
sx = this.canvas.width - sw;
}
if (sy < 0) {
sy = 0;
}
if (sy > this.canvas.height - sh) {
sy = this.canvas.height - sh;
}
// save to browser
context.drawImage(this.canvas, sx, sy, sw, sh, 0, 0, 230, 120);
}
else {
// now scaledown
var full_width = this.canvas.width;
var full_height = this.canvas.height;
context.drawImage(this.canvas, 0, 0, full_width, full_height, 0, 0, 230, 120);
}
imageData = offscreenCanvas.toDataURL('image/png');
imageData = imageData.replace('image/png', downloadMime);
p5.prototype.downloadFile(imageData, 'thumbnail.png', 'png');
}

17.2.MDDN342 PS3

Overall

In my two works, I wanted to show how inorganic functions can create organic and lifelike movement in the time domain. They change over time with different values and can always suprise the viewer through behaviour at a higher scale view in time. It was important of course for it to also be interesting to view at a low level, so the interactions between different objects are made to compliment each other, such as with the large shapes in the wallpaper becoming transparent.

Wallpaper

I am quite interested in how sin/cos waves work through interference etc, and different ways that we can use it to show more organic and reactive movement over time in designs.

The wallpaper generates a grid of moving shapes, all driven by the same base interval so that they line up in the time domain. I started with rendering it with lines and tracers, which looked much like a mandela when the shapes were big enough, but ended up changing it to be a checkerboard fill pattern so that the edges of different objects overlap and create interesting complexity. I also made the largest sizes of shape loose some opacity so that the viewer gets to look into the innards every now and then.

This piece required a lot of iteration, but I am happy with the result and how it looks very simple at first glance but exhibits an interesting and organic movement when time is spent being mesmerized by it.

Landscape

In my landscape design I wanted to show off the next level of complexity of random noise. I spent a lot of time changing around the area and variety of perlin noise it generated. I started this one by just generating lines of noise, and ended up filling them with an increacing darkness. Then I wanted to show the viewer to scale of the perlin noise, so i added a bit of animation in showing multiple scales of the noise. I also modulate the noise over time, by mapping the third noise dimension to millis. I ended up also mirroring it in the middle so that the viewer can more easily follow the scale increace.

<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/p5.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.14/addons/p5.dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.0/seedrandom.min.js"></script>
<script src="https://d3js.org/d3-random.v1.min.js"></script>
<script language="javascript" type="text/javascript" src=".focused_random.js"></script>
<script language="javascript" type="text/javascript" src=".purview_helper.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<style>
body {padding: 0; margin: 0; background-color: white}
#controls {
font: 300 18px Arial, Helvetica, sans-serif;
position: absolute;
padding: 5;
margin: 5;
background: #f0f0f0;
opacity: 0.0;
-webkit-transition: opacity 0.2s ease;
-moz-transition: opacity 0.2s ease;
-o-transition: opacity 0.2s ease;
-ms-transition: opacity 0.2s ease;
}
#controls:hover { opacity: 0.9; }
#controls input{
position: inherit !important;
}
#canvas{
position: absolute;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="canvas"></div>
<div id="controls">
View:
<div id="view"></div>
<div id="mirror"></div>
</div>
</body>
{
"commits": [
{
"sha": "bc3eda41d13f5b3cedeca8f1ecb2ad1e386c5053",
"name": "final_version"
},
{
"sha": "25dad37a9d9bfc079efcbea9e37f20edd9155116",
"name": "almost finished landscape"
},
{
"sha": "3c622b18d5c2ab600d1a846dfdc85e80736fef8b",
"name": "background"
},
{
"sha": "59b06ec19e50de55d2bc5827fc70ad8107dd3556",
"name": "first wave test"
}
]
}
function setup () {
let container = document.getElementById('canvas')
let canvas = createCanvas(container.offsetWidth, container.offsetHeight);
canvas.parent('canvas')
angleMode(RADIANS)
colorMode(HSB)
view = createSelect()
view.parent('view')
view.option('wallpaper')
view.option('landscape')
view.value('landscape')
mirror = createCheckbox('Mirrored', false)
mirror.parent('mirror')
bgColor = color(0, 0, 0, 1)
}
let view;
let mirror;
function draw(){
if(view.value() == 'wallpaper')
drawWallpaper()
else
drawLandscape()
}
function keyTyped() {
if (key == '!') {
saveBlocksImages();
}
if(key == ' '){
if(view.value() == 'wallpaper')
view.value('landscape')
else
view.value('wallpaper')
}
}
function mousePressed(){
extraTime = -500000+random()*1000000
}
let extraTime = 0;
let layers = 10;
let points = 100;
function drawLandscape(){
let time = millis()+extraTime;
background('white')
let singleH = height/layers
noStroke()
let y = 0;
while(y < (height)){
let yP = y/height;
let singleH = map(y, height, 0, height*0.2, height*0.001)*2
fill(0, 0, 100-yP*100)
beginShape()
for(let x = -2; x < points+2; x++){
let xP = x/points;
let xScale = (7-6.99*cos(time/100000*TWO_PI))
curveVertex(map(x, 0, points, 0, width),
y + singleH/2 - singleH*noise((mirror.checked() ? 0 : 100000)+xScale/2-xP*xScale, yP*4, time/10000))
}
curveVertex(width, height)
curveVertex(0, height)
curveVertex(-100, height)
curveVertex(-200, height)
endShape()
y += map(y, height, 0, height*0.2, height*0.001)
}
}
let size = 1;
function drawWallpaper () {
fill(0,0,0,0)
stroke(0,0,0)
strokeWeight(0.4)
noStroke();
let gridSize = 40*width/500;
// let gridSize = 25+5*st(10007+st(2023)+st(4061))
let modX = gridSize*2*t(2000)
let modY = gridSize*2*t(5000)
let fX = makeMap(-gridSize*4, width+gridSize*4);
let fY = makeMap(-gridSize*4, height+gridSize*4);
let time = millis()+extraTime;
background(bgColor)
let i = Math.floor(time/5000)//+Math.floor(time/2000)
for(let x = modX-gridSize*4; x < width+gridSize*4+modX; x+= gridSize*2){
for(let y = modY-gridSize*4; y < height+gridSize*4+modY; y += gridSize*2){
i++;
let fx = fX(x)
let fy = fY(y)
translate(x, y)
let heightI = 8000+fx*3000
// let heightI = 5000
let radius = gridSize*(1.4 -0.5*ct(heightI/2) -0.8*ct(heightI*6));
if(gridSize*2 < radius){
let alpha = Math.min((radius-gridSize*2)/(gridSize*2), 1);
fill(0, 0, i%2 == 0 ? 0 : 100, 1-alpha*0.8)
} else{
fill(0, 0, i%2 == 0 ? 0 : 100)
}
drawCircle(radius,
genWaveMap(1+Math.floor(t(heightI*2)*4), 0.25*st(heightI)),
t(heightI*4)*TWO_PI)
translate(-x, -y)
}
}
}
function makeMap(low, high){
return val => (val-low)/(high-low)
}
/**
*
* @param {Number} radius
* @param {ForEachCallback} waveMap
* @param {Number} offset
*/
function drawCircle(radius, waveMap, offset){
radius = radius || 100
waveMap = waveMap || (x => x)
offset = offset || 0
let points = 24
let circle = fillArray(points, radius)
//wavy offset
.map(waveMap)
//circle coordinates
.map((radius, i, arr) => {
let ang = i/points*TWO_PI+offset
return createVector(radius*sin(ang), -radius*cos(ang))
})
drawCurve(circle)
}
function t(period){
return (millis()+extraTime).mod(period)/period
}
function st(period){
return sin(t(period)*TWO_PI)
}
function ct(period){
return cos(t(period)*TWO_PI)
}
/**
* generates the wave over the radius of a circle
* @param {number} waves
* @param {Number} height
* @returns {ForEachCallback}
*/
function genWaveMap(waves, height){
height = height || 0.2
return (radius, i, arr) => radius+radius*height*cos(i/arr.length*TWO_PI*waves)
}
function drawCurve(points){
beginShape()
for(let i = -1; i < points.length+2; i++){
let point = points[i.mod(points.length)]
curveVertex(point.x, point.y)
}
endShape()
}
function fillArray(n, val){
let array = []
for(let i = 0; i<n; i++){
array.push(val || i)
}
return array;
}
//mod helper
Number.prototype.mod = function(y){
return this - y * floor(this / y)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment