This video highlights the process of creating a Tactum wearable.
Tactum (2015), by Madeline Gannon, is a skin centric design tool that allows people to design 3D printed wearables on their bodies using depth sensing and projection mapping. This modeling tool allows people to design wearables naturally. Through touching, poking, rubbing, or pinching the skin, people can easily manipulate the design of the wearables and then 3D print them. I admire this project because it is interactive, efficient, and customizable. I admire how the designer found a way to use interactive technology for fashion and functional purposes. This project was led by Madeline Gannon, the head of Madlab.cc and a PhD candidate in Computational Design at Carnegie Mellon University. She runs Madlab.cc which is a research studio that specializes in creating interfaces for wearables on the body.
/*Eunice Choe
Section E
ejchoe@andrew.cmu.edu
Project-10*/
var cloud = [];
var trees = [];
var terrainSpeed = 0.0001;
var terrainDetail1 = 0.005;
var terrainDetail2 = 0.008;
function setup() {
createCanvas(480,300);
angleMode(DEGREES);
// initial collection of trees and clouds
for (var i = 0; i < 10; i++) {
var cloudX = random(width);
var rx = random(width);
cloud[i] = makeCloud(cloudX);
trees[i] = makeTree(rx);
}
}
function draw() {
background(255, 223, 197);
// dark mountains in background
push();
beginShape();
fill(104, 101, 181);
vertex(0,height);
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail2) + (millis() * terrainSpeed);
var y = map(noise(t), 0, 1, 0, height);
vertex(x, y - 50);
}
vertex(width, height);
endShape();
pop();
// light mountains in background
push();
beginShape();
fill(165, 168, 199);
vertex(0,height);
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail1) + (millis() * terrainSpeed);
var y = map(noise(t), 0, 1, 0, height);
vertex(x, y);
}
vertex(width, height);
endShape();
pop();
displayHorizon();
updateTrees();
removeTrees();
randomTrees();
fill(165, 168, 199);
// drawing and moving the transparent clouds
for(var i = 0; i < cloud.length; i++) {
cloud[i].draw();
cloud[i].move();
}
}
function cloudDraw() {
push();
translate(this.xPos, this.yOffset);
stroke(255, 255, 255, 60);
strokeWeight(this.cHeight);
line(0, 0, this.cSize, 0);
pop();
}
// when moving clouds reach edge
// send them to other edge with random position, size, height
function cloudMove() {
this.xPos += this.speed;
if(this.xPos < 0 - this.cSize - 30) {
this.cHeight = random(10, 50);
this.cSize = random(30, 150);
this.xPos = width + this.cSize + random(-25, 25);
}
}
function makeCloud() {
var cloud = {xPos: random(width), //, width*4
speed: random(-0.4, -0.3),
cSize: random(30, 150),
cHeight: random(20, 60),
yOffset: random(50, height),
draw: cloudDraw,
move: cloudMove};
return cloud;
}
function updateTrees(){
// Update the trees positions
for (var i = 0; i < trees.length; i++){
trees[i].move();
trees[i].display();
}
}
// if trees hit edge, then remove from array
function removeTrees(){
var keepTrees = [];
for (var i = 0; i < trees.length; i++){
if (trees[i].x + trees[i].breadth > 0) {
keepTrees.push(trees[i]);
}
}
trees = keepTrees;
}
// with probability, add tree to the end
function randomTrees() {
var newTreeLikelihood = 0.007;
if (random(0,1) < newTreeLikelihood) {
trees.push(makeTree(width));
}
}
// update position of tree every frame
function treeMove() {
this.x += this.speed;
}
// drawing the trees
function treeDisplay() {
var floorHeight = 10;
var bHeight = this.nFloors * floorHeight;
noStroke();
// tree trunk
push();
translate(this.x, height - 100);
fill(204, 187, 145);
rect(0, -bHeight, this.breadth, bHeight);
// tree trunk reflections
fill(204, 187, 145, 50);
rect(0, -bHeight + bHeight, this.breadth, bHeight);
// tree leaves
fill(255, 136, 112);
ellipse(2.5, -bHeight, 35, bHeight);
//tree leaves reflections
fill(255, 136, 112, 50);
ellipse(2.5, bHeight, 35, bHeight);
pop();
}
function makeTree(birthLocationX) {
var tr = {x: birthLocationX,
breadth: 5,
speed: -1.0,
nFloors: round(random(2,8)),
move: treeMove,
display: treeDisplay}
return tr;
}
function displayHorizon(){
noStroke();
// water
fill(192, 219, 212);
rect(0,height-100, width, height-50);
// grqss
fill(152, 194, 146);
rect(0,height-100, width, 20);
}
Overall, I found this project a little challenging. I had a solid plan with my sketch and I was able to execute it, but I found myself getting easily confused because there were so many lines of code. However, when I got the code figured out, I was able to capture the calmness and serenity of a mountain landscape. Along with the mountains in the background, I added trees, water, and tree reflections in the front. I also added moving transparent clouds that overlay the canvas. While this project was difficult for me, I am satisfied with the outcome and the skills I developed from it.
Swing Times is an interactive public installation of 20 illuminated ring-shaped swings located in Boston. At rest, the swings emit a soft, white light that lightens the area, but, once in motion, a custom micro-controller flips the LED lighting within the swing from a white to a more vibrant purple. This controller signals and measures the swing’s activity level, which then triggers the light at varying intensities. I admire this project a lot because of how it creates an engaging experience and transforms a static place into an active park for Boston residents and visitors, as I had the pleasure of personally interacting with this installation when I visited my brother in Boston.
J. Meejin Yoon is an architect, designer, educator, and co-founder of design-drive architecture studio Howeler + Yoon. She is a current professor and Head of the Department of Architecture at the Massachusetts Institute of Technology, and previously studied at Cornell University for her Bachelor of Architecture degree and Harvard University for her Master of Architecture degree in Urban Design. She also received a Fullbright Fellowship to Korea. Broadly speaking, her work revolves around innovative and interactive landscape, and subversive structural work in various communities and for various audiences. Although she is not listed as a direct member of the design team for the Swing Time project, she is in charge and principle of many other projects under her studio, such as an upcoming “Float Lab” architectural installation.
/*Vicky Zhou
Section E
vzhou@andrew.cmu.edu
Project-10-Landscape
*/
//window roll down variables
var mtnspeed1 = 0.00009;
var mtndetail1 = 0.0002;
//mountain variables
var mtnspeed2 = 0.0001;
var mtndetail2 = 0.002;
var mtnspeed3 = 0.0008;
var mtndetail3 = 0.005;
var trees = [];
var windowrolldown = [];
function setup() {
createCanvas(480, 480);
//places trees throughout landscape
for (var i = 0; i < 10; i++){
var rx = random(width);
trees[i] = maketrees(rx);
}
frameRate(50);
}
function draw() {
background(255, 220, 200);
makewindowrolldown();
makemtns();
push();
noStroke();
updateAndDisplaytrees();
removetrees();
addtrees();
pop();
displayCarWindow();
displayCarMirror();
}
//creating function to show and update trees
function updateAndDisplaytrees(){
for (var i = 0; i < trees.length; i++){
trees[i].move();
trees[i].display();
}
}
//removing old trees from landscape
function removetrees(){
var treesToKeep = [];
for (var i = 0; i < trees.length; i++){
if (trees[i].x + trees[i].peaks > 0) {
treesToKeep.push(trees[i]);
}
}
trees = treesToKeep;
}
//adding new random trees
function addtrees(){
var newtrees = 0.005;
if (random(0,1) < newtrees) {
trees.push(maketrees(width));
}
}
//moving trees across screen
function treeMove() {
this.x += this.speed;
}
//drawing trees
function treeDisplay() {
// var treeheight = 10;
var randomtreeheight = this.tbranches;
fill(65, 90, 85);
push();
translate(this.x, height - 30); // WHAT IS PURPOSE OF THIS TRANSLATE????
triangle(this.peaks + 10, -this.peaks - 20,
this.peaks + 90, -this.peaks - 20,
this.peaks + 45, -this.peaks - 210 * randomtreeheight);
pop();
}
//making trees
function maketrees(mx){
// noStroke();
var trees = {x: mx,
tbranches: random(0.4, 1.2),
peaks: 50,
speed: -5.0,
move: treeMove,
display: treeDisplay}
return trees;
}
//making window roll down
function makewindowrolldown() {
push();
beginShape();
strokeWeight(0.2);
stroke(60, 60, 170, 300);
for (var x = 0; x < width; x++) {
var t = (x * mtndetail1) + (millis() * mtnspeed1);
var y = map(noise(t), 0, 1, height, 100);
// vertex(x, y);
line(x, y - 100, x, height - 100);
}
endShape();
pop();
}
//making mountains
function makemtns() {
push();
//light purple mountains
beginShape();
stroke(150, 125, 130, 100);
for (var x = 0; x < width; x++) {
var t = (x * mtndetail2) + (millis() * mtnspeed2);
var y = map(noise(t), 0, 1, 0, height);
// vertex(x, y);
line(x, y, x, height);
}
endShape();
//dark green mountains
beginShape();
stroke(60, 80, 90, 120);
for (var x = 0; x < width; x++) {
var t = (x * mtndetail3) + (millis() * mtnspeed3);
var y = map(noise(t), 0, 1, 0, height * 2);
line(x, y, x, height);
}
endShape();
pop();
}
//draws car windows, frame, and handle detail
function displayCarWindow(){
//car window and frame display
push();
stroke(40, 40, 40);
strokeWeight(150);
line(-30, 100, 150, 0);
strokeWeight(100);
line(150, 15, 480, 0);
line(0, 430, 480, 430);
strokeWeight(70);
stroke(40, 50, 50);
line(0, 450, 480, 450);
noStroke();
fill(255, 220, 210);
triangle(0, 40, 0, 100, 50, 50);
//car handle and details
fill(70, 70, 70);
rect(30, 415, 120, 90);
triangle(150, 415, 150, 480, 210, 480);
fill(50, 50, 50);
rect(40, 425, 90, 60);
fill(80, 90, 80);
push();
fill(80, 90, 80);
strokeWeight(20);
stroke(80, 90, 80);
curve(40, 430, 60, 445, 120, 440, 150, 470);
pop();
pop();
}
//draws car mirror
function displayCarMirror(){
push();
noStroke();
fill(240, 240, 240, 190);
rect(0, 310, 100, 40);
rect(0, 340, 120, 10);
rect(0, 360, 40, 20);
pop();
push();
strokeWeight(25);
stroke(40, 40, 40);
fill(40, 40, 40);
curve(5, 316, 5, 316, 95, 314, 95, 400);
curve(30, 320, 103, 318, 103, 355, 35, 359);
curve(5, 410, 5, 380, 100, 365 - 10, 100, 290);
pop();
}
For this week’s project, I decided to the view from a car window in the passenger seat, because roadtripping and looking out the windows is one of my favorite views in the whole world (especially in woodsy, mountainous areas). Originally, I had envisioned making telephone poles and clouds to go along with the scenery, however, after playing around with the noise function, I discovered a very pleasing wave that forms when dialing down the speed and detail aspects. I thought this form was very similar to the feeling of sticking your hand out the car window on the highway and having it glide and ride the air, but I also thought it also waved in a manner similar to rolling up and down a car window, so I implemented it as the latter. I originally wanted to implement a reflective, smaller, moving generative landscape mirroring the current on in the small car side mirror, but I could not end up figuring it out; I would like to revisit that concept when I have more time in the future.
// assignment 10 sample code referenced for trees
// source: https://courses.ideate.cmu.edu/15-104/f2018/week-10-due-nov-4/#landscape
// p5.js.org example referenced for snowflakes
// source: https://p5js.org/examples/simulate-snowflakes.html
var trees = [];
var snowflakes = [];
function setup() {
createCanvas(480, 200);
for (var i = 0; i < 10; i++){
var rx = random(width);
trees[i] = makeTree(rx);
}
frameRate(15);
}
function draw() {
background(80, 100, 150);
displayGround();
// trees
updateCanvas();
eraseOld();
addNew();
// snowflakes
let t = frameCount / 60;
for (var i = 0; i < random(5); i++) {
snowflakes.push(new snowflake());
}
for (let flake of snowflakes) {
flake.update(t);
flake.display();
}
}
// tree functions
function updateCanvas(){
for (var i = 0; i < trees.length; i++){
trees[i].move();
trees[i].display();
}
}
function eraseOld(){
var treesToKeep = [];
for (var i = 0; i < trees.length; i++){
if (trees[i].x + trees[i].width > 0) {
treesToKeep.push(trees[i]);
}
}
trees = treesToKeep;
}
function addNew() {
var newTreeLikelihood = 0.02;
if (random(0,1) < newTreeLikelihood) {
trees.push(makeTree(width));
}
}
function treeMove() {
this.x += this.speed;
}
function treeDisplay() {
var treeH = this.height;
fill(10, 60, 20);
noStroke();
push();
translate(this.x, height - 40);
triangle(0, treeH - 17, this.width, treeH - 17, this.width / 2, -treeH - 17);
pop();
}
function makeTree(birthLocationX) {
var tr = {x: birthLocationX,
width: random(10, 20),
speed: -1.0,
height: random(10, 20),
move: treeMove,
display: treeDisplay}
return tr;
}
function displayGround(){
fill(255);
noStroke();
rect(0, height - 50, width, 50);
// frame
stroke(200);
noFill();
rect(0, 0, width - 1, height - 1);
}
// snowflakes
function snowflake() {
this.posX = 0;
this.posY = random(-50, 0);
this.initialangle = random(0, 2 * PI);
this.size = random(1, 3);
this.radius = sqrt(random(pow(width / 2, 2)));
this.update = function(time) {
let w = 0.6;
let angle = w * time + this.initialangle;
this.posX = width / 2 + this.radius * sin(angle);
this.posY += pow(this.size, 0.5);
if (this.posY > height) {
let index = snowflakes.indexOf(this);
snowflakes.splice(index, 1);
}
}
this.display = function() {
fill(255);
noStroke();
ellipse(this.posX, this.posY, this.size);
}
}
It snowed in my hometown this past week so I was inspired to do a snowy winter landscape.
I started with a blue sky and white ground. Then, I referenced the buildings sample code to generate trees of different height and width triangles. Finally, I looked on the p5.js website to find an example showing how to make falling snowflakes (source: https://p5js.org/examples/simulate-snowflakes.html). I studied the code and adapted it to my landscape which required smaller snowflake particles.
I am really happy with the end result and it reminds me a lot of what Ottawa looks like in the winter. Also, I had some trouble understanding the lectures on particles last week so studying and learning from the snowflake example really helped.
For this week’s Looking Outwards writing, I want to discuss Lauren McCarthy‘s work and project LAUREN.
Lauren McCarthy is an LA-based artist whose work centers on the tensions of automation, surveillance, and culture. She is also the creator of p5.js, the javascript library this whole class and all my work thus far rely on. What I love from her biography is the following quote: “I make art about what confuses me”. Work that speaks to me most strongly is work that carefully explores, processes, and asks the unexpected questions.
*video of project LAUREN
Her work LAUREN describes how Lauren watched and remotely interacted with people in their homes through a variety of cameras, sensors, etc and aimed to be an even better personal AI assistant than the commercial assistants available today. Her proposition is simple: A human can understand each person better, and anticipate their needs.
What I precisely love about this work is how it revises the ongoing distrust (and trust) of AI assistant products, and at large, the idea of sentience in artificial objects and materials. If we allow this sentience artificially, isn’t it much better to allow it naturally (an actual human being)? Our current paradigm of privacy is clearly placed in discourse in the LAUREN project.
//Jenny Hu
//Section E
//jjh1@andrew.cmu.edu
//Project 10
var moonx;
var moony;
var moonr;
var sunx;
var suny;
var sunr;
function setup() {
createCanvas(480, 300);
//frameRate(10);
hillSpeedB = random(0.000002, 0.00003);
hillSpeedFront = random(0.000005, 0.00009);
moonx = 350;
moony = random(20,80);
moonr = random(20,50);
sunx = 420;
suny = random(90,200);
sunr = random(80,150);
}
function draw() {
//background gradient
var c1 = color(0);
var c2 = color(200);
for (var i = 0; i < height/2; i++){
var gr = map (i, 0, height/2, 0, 1);
var newC = lerpColor( c1, c2, gr);
stroke(newC);
line(0, i, width, i);
}
//make my moon and sun
moonx = moonx - .01;
if (moonx < -100) {
moonx = 490;
moonx = moonx - .01;
};
myMoon();
sunx = sunx - .01;
if (sunx < -100) {
sunx = 490;
sunx = sunx - .01;
};
mySun();
//generate my hills
drawHill();
}
function drawHill() {
stroke(50);
beginShape();
for (var x = 0; x < width; x++) {
var t = x * 0.002 + (millis() * hillSpeedB);
var y = map(noise(t), 0,.9, 0, height/2);
line(x, y, x, height);
}
endShape();
stroke(200);
beginShape();
for (var x = 0; x < width; x++) {
var t = x * 0.003 + (millis() * hillSpeedFront);
var y = map(noise(t), 0, 0.7, 0, height);
line(x, y, x, height);
}
endShape();
}
function myMoon(){
noStroke();
fill(200);
ellipse(moonx, moony , moonr, moonr);
}
function mySun(){
noStroke();
fill(250);
ellipse(sunx, suny , sunr, sunr);
}
For this project, I wanted to lean especially simple and elegant. Arguably, this might have been one of the most off-kilter process thus far in the class— I started with the intention to do simple, but subtle shapes. I wanted to impose 3D spheres onto the generative landscape, and apply a small gaussian blur to create a greater sense of focus.. but alas, I failed to find how to apply both the blur and the 3D implementation. I had explored and programmed using Perlin noise methods, and considered multiple ways to apply blur (including generating from an array of images).
I think if I had more time, I would be able to find a method to implement these techniques on top of one another (the noise, with the landscape, with 3D on top), but in this case, I had to scale back.
In doing so, I think I learned a valuable lesson that I should have started small, and worked towards my bigger goal. Scaling back was mildly disappointing.
Neri Oxman is well known for a plethora of things around Mediated Matter and creating Material Ecology. As an associate professor at MIT Media Lab, she’s a well-recognized artist, designer, and architect that speaks, most famously, about the intersection of design, technology, and biology. I want to focus specifically on her collaboration with another prolific female designer, Iris Van Herpen. Anthozoa is a wearable feat of 3D printing technology where they created a custom program to enable printing in both rigid and soft materials.
This week, the project I have chosen to investigate is ‘Liminoid Garden’ by Filipa Valente. Filipa Valente is a Portuguese interactive artist who is based in Los Angles. She studied architecture and media art and architecture at the Bartlett School of Architecture, UCL (London), and SciArc (Los Angles). Valente primarily creates dynamic light architectures, through she also works in experience design, architecture, product design and animation.
‘Liminoid Garden’ features mechanical blooms that are fitted with electronic controllers. Such controllers receive real time data regarding temperature, light and pollution conditions from the outside, and translate the data into varying physical movements and light qualities in the interior installation space. What I admired about Valente’s project was how the installation managed to be so beautiful but reflective of real world conditions and contexts by almost personifying the blooms. I also admire how the piece encourages and fosters audience interaction in a way that allows viewers to develop a constantly changing relationship with the installation, since the data inputs breathe new life into the piece.
Different from traditional architecture, architect Jenny Sabin’s Sabin Design Lab in Ithaca, New York investigates the interaction between architecture and science. They apply theories from biology and mathematics to designs, fabrication, spatial inventions and materials. The firm is a combination of engineers, architects, designers, artists, and even scientists. The scales of their work varies, from installation to a building facade. I find the form of their projects very appealing because it is dynamic and organic. It seems random but also has order and system to it.
The newest project Lumen creates a space I really want to experience. It is very interesting because of the fabrication materials, the shapes of each element and how the structure come together.