Link :

There are surprisingly many emojis out there (or more accurately stored in your OS). I wanted to make use of this rich source of images somehow. This Emoji Editor grabs the emojis from the hidden file of your computer, enlarges them, and lets you conveniently reconstruct images. You can create virtually infinite number of combinations with various transformations. The resulting images look familiar, but still feel somewhat different from ones we're used to seeing.

There were maybe too many trials and errors. At the end, I got rid of libraries and used plain Javascript. So it took me longer, but the experience was somewhat rewarding. The app is still a bit buggy and is missing a few functions. But I finished much of what I planned for. My goal was to make the whole image-making process simple and addictive. The interface turned out a bit complicated. But I'm still hooked on this idea, and I'm planning to refine the app in the following couple weeks.



I thought of a digital clock with each digit restlessly trying to stand still, while continuously having to offset external forces to stay balanced. I think such state is called dynamic stability. I was inspired by Jacob Tonski's Balance From Within. I used processing with geomerative and fisica libraries.

1. Every time a digit needs to update, it disappears and falls again from a fixed position. Same rule when a digit goes out of bounds. This can cause some unexpected chain reactions in the following few seconds.
2. Each digit has an inherent "tremble" generated by noise. The digit would try to offset the torque by shifting its body left or right. But once it falls to its side, it will be hard to get back up again. Sadly, it will stay there until it needs update and a new number takes its place.

when the clock first turns on

some tension from 8

I like how 0 falls on the 5.

I think my current code cannot perfectly offset the forces. It could be more interesting if the numbers stayed on their feet longer. Also, I first imagined the numbers kind of bouncing left and right micro-scale (like a person does on one foot) and bumping into one another, but couldn't implement that in time. But I can still somewhat see how the numbers are reluctant to fall on its side, and I like that.

import fisica.*;
import geomerative.*;
FWorld world;
RFont font;
FBody[] bodies;
int FONT_SIZE = 200;
int lastShiftTime; 
int newShiftInterval;
float randomShift;
boolean bRecording = false;
int lastMinute;
boolean[] needToCheckUpdate = {true, true, true, true};
FCharController[] controllers;
FChar[] colon;
void setup() {
  world = new FWorld();
  randomShift = random(-50, 50);
  world.setGravity( 0, 400 );
  newShiftInterval= int(random(2000,8000));
  world.setEdges(0, 0, width, height+5, color(255, 0, 0)); 
  font = RG.loadFont("cheltenham-cond-normal-300.ttf");
  colon = new FChar[2];
  colon[0] = new FChar('.', width/2-15, 142);
  colon[1] = new FChar('.', width/2-15, 75);
  controllers = new FCharController[4];
  for (int i=0; i<controllers.length; i++) {
    FCharController controller = new FCharController(i);
    controllers[i] = controller;
  lastMinute = minute();
void draw() {
  for (int i=0; i<controllers.length; i++) controllers[i].update();
void checkMinutePassed() {
  if (minute() == lastMinute) return;
  for (int i=0; i<needToCheckUpdate.length; i++) needToCheckUpdate[i] = true; lastMinute = minute(); } class FCharController { FChar charObj; int index; int lastNumber; boolean disappeared; int dropX; float shiver; float xoff; FCharController(int index) { //charObj = new FChar('9', 100, 150); this.index = index; disappeared = false; lastNumber = 0; // doesn't matter what I assign here dropX = index*150+50; if (index==1) dropX -= 20; else if (index==2) dropX += 20; } void dropNewCharObj() { needToCheckUpdate[index] = false; int newNumber = parseTime(index); println((char)(newNumber+48)); charObj = new FChar((char)(newNumber+48), dropX, -50); world.add(charObj); lastNumber = newNumber; } void dropNewCharObj(int test) { needToCheckUpdate[index] = false; int newNumber = test; println((char)(newNumber+48)); charObj = new FChar((char)(newNumber+48), dropX, -50); //charObj.setRotation(0.115*PI); world.add(charObj); } void update() { if(charObj.isTouchingBody(world.bottom)) { shiver = noise(xoff+=0.025); shiver*=10; shiver-=5; charObj.addTorque(shiver*10000); charObj.addForce(shiver*-10000, 0, 40, 0); } if (charObj.getY()>230) {
      xoff = random(100);
    if (needToCheckUpdate[index] == true) {
      if (lastNumber == parseTime(index)) return;
      int newNumber = parseTime(index);
      lastNumber = newNumber;
      xoff = random(100);
  int parseTime(int index) {
    switch (index){
      case 0: return hour()/10;
      case 1: return hour()%10;
      case 2: return minute()/10;
      case 3: return minute()%10;
    return 9;
class FChar extends FPoly {
  RShape m_shape;
  RShape m_poly;
  boolean m_bodyCreated;
  float initialAngle=0;
  FChar(char chr, float dropX, float dropY){
    this.setFill(0, 0, 0);
    if (chr=='.') {
      this.setPosition(dropX, dropY);
    else {
      this.setPosition(dropX, dropY);
    m_bodyCreated = true;
  void polygonize(char chr) {
    String txt = "";
    txt += chr;
    RG.textFont(font, FONT_SIZE);
    m_shape = RG.getText(txt);
    m_poly = RG.polygonize(m_shape);
    if (m_poly.countChildren() < 1) return;
    m_poly = m_poly.children[0];    
    // Find the longest contour of our letter    `  
    float maxLength = 0.0;
    int maxIndex = -1;
    for (int i = 0; i < m_poly.countPaths(); i++) { float currentLength = m_poly.paths[i].getCurveLength(); if (currentLength > maxLength) {
        maxLength = currentLength;
        maxIndex = i;
    if (maxIndex == -1) return;
    RPoint[] points = m_poly.paths[maxIndex].getPoints();
    for (int i=0; i<points.length; i++) {
      this.vertex(points[i].x, points[i].y);
  void setInitialAngle(char chr) {
    float randomFloat = random(1);
    switch(chr) {
      case '0':
        initialAngle = -0.01*PI;
      case '1':
        if (randomFloat<0.5) initialAngle = 0.115*PI;
        else initialAngle = -0.1*PI;
      case '2':
        if (randomFloat<0.5) initialAngle = 0.14*PI;
        else initialAngle = -0.17*PI;
      case '3':
        initialAngle = -0.15*PI;
      case '4':
        initialAngle = 0.135*PI;
      case '5':
        initialAngle = -0.1*PI;
      case '6':
        //initialAngle = 0.14*PI;
        initialAngle = 0.04*PI;
      case '7':
        initialAngle = -0.04*PI;
      case '8':
        initialAngle = -0.03*PI;
      case '9':
        initialAngle = -0.095*PI;
  boolean bodyCreated(){
    return m_bodyCreated;
  void draw(PGraphics applet){


Digital Grotesque II - Michael Hansmeyer

"What is needed is a new type of design instrument. We need tools for search and exploration, rather than simply control and execution. We require tools that go beyond the fulfillment or optimization of simple functional requirements, and that allow us to investigate and advance more ambiguous factors of the design: soft criteria."

The above excerpt from the project description effectively summarizes the core value of the artwork. Digital Grotesque II is 3.5 meter high 3D printed structure that explores both form and design/manufacture process. I am not familiar with grasshopper or any other parametric modeling tools, so I'm not sure as to how this form came about, or how much of it would be generative. But even if the form weren't completely generated by computer, I believe the result is a proof of the architect's statement that the computer "expands the imagination of the designer." Computer much exceeds the human capacity for speed and complexity in thought.

I also love how the work falls right within the range of "effective complexity"--with both identifiable architectural details and incomprehensible chaotic distortions.


This is a similar kind of question to that I've been asking myself for a long time. I believe there is often a dichotomy between hi-tech and low-tech that divides form of practice, people's tastes, and even school curriculums. I wasn't sure which of two I should side on, (I felt that both groups of people were often disapproving of each other) until recently when I started programming, and found out this was something I wanted to do.

And I very much agree with how the author closed his essay. I believe newer tools should be harnessed by more finesse. An unconditional endorsement of established tastes and rules bares some risk of falling into mannerism. And a careless collection of "novel" expressions often has a low signal-to-noise ratio, or seems to have wasted good resource. I think, by staying self-critical at the same time as being inventive and progressive, one could achieve both first and last word art.


I wanted to make a series of simple animations with circles as a main theme. But ended up only making two. I wanted to try the blur effect too, but spent too much time figuring out how to export frames from p5 without randomly skipping any frames. But I just gave up. I think slowing down the frame rate might be a solution, although I haven't tried it. Apart from that, I had fun.




void renderMyDesign (float percent) {
  float x1 = cos(percent*6*PI);
  float x2 = -cos(percent*6*PI);
  float z1 = sin(percent*6*PI);
  float z2 = -sin(percent*6*PI);
  background(0, 0, 200);
  translate(width/2, height/2);
  if (percent%(1/3f) < 1/6f) {
      map(x1, -1, 1, -160, 160), 
      200+ map(z1, -1, 1, -80, 80), 
      200+ map(z1, -1, 1, -80, 80));
      map(x2, -1, 1, -160, 160), 
      200+ map(z2, -1, 1, -80, 80), 
      200+ map(z2, -1, 1, -80, 80));
  } else {
      map(x2, -1, 1, -160, 160), 
      200+ map(z2, -1, 1, -80, 80), 
      200+ map(z2, -1, 1, -80, 80));
      map(x1, -1, 1, -160, 160), 
      200+ map(z1, -1, 1, -80, 80), 
      200+ map(z1, -1, 1, -80, 80));
var frame = 0;
var phase1 = 30;
var phase2 = 50;
var phase3 = 150; // start falling
var phase4 = 160;
var phase5 = 190;
var SIZE = 120;
var r = 255;
var g = 255;
var b = 255;
var cnv;
function setup() {
  cnv = createCanvas(640/2, 640/2);
function draw() {
  background(225, 0, 100);
  if (frame <= phase2) { translate(0, map(pennerEaseOutCubic(frame/phase2), 0, 1, -60/2, 520/2)); } // horizontal oscillation if (frame > phase1 && frame < phase4) { var osc = map(sin((frame-phase2)/PI*2), -1, 1, -50/2, 50/2); var oscScale = reverseSineEase(map(frame, phase1, phase4, 0, 2*PI)); translate(osc*oscScale, 0); // ellipse(width/2, 0, reverseSineEase(map(frame, phase1, phase4, SIZE, 400))); } if (frame > phase2 && frame <= phase3) { translate(0, map(pennerEaseInOutQuad((frame-phase2)/(phase3-phase2)), 0, 1, 520/2, 200/2)); SIZE += 1.5/2; } if (frame > phase3) {
    translate(0, map(pennerEaseInCubic((frame-phase3)/(phase5-phase3)), 0, 1, 200/2, 840/2)); 
  if (frame > phase2 + 20 && frame < phase4) { r -= 3.5; g -= 3.5; b -= 3.5; } fill(r, g, b); ellipse(width/2, 0, SIZE); frame++; if (frame>phase5) {
    SIZE = 120;
function pennerEaseOutCubic(t) {
  t = t-1.0;
  return (t*t*t + 1);
function pennerEaseInCubic(t) {
  return t*t*t;
function reverseSineEase(t) {
  return ((1-cos(t))/2)*((1-cos(t))/2);
function pennerEaseInOutQuad (t) {
  if ((t/=1/2) < 1) return 1/2*t*t;
  return -1/2 * ((--t)*(t-2) - 1);



I thought it would be fun to animate a random looking scribble like the one in the sketch below. In the setup() function, I created an array of random vertices to be connected by bezier curves, then added periodical offsets created by noise() function to each vertex just before drawing the shape. While it took me longer than I expected to implement the code, the outcome didn't seem as interesting as I thought, mainly due to the periodicity of the movement.




float[][] line = new float[120][6];
float[] num = new float[120];
int count = 0;
void setup() {
  size(792, 612); // 11x8.5" at 72DPI
  int i = 0;
  for (int y = 60; y> -60; y-=5) {
    line[i][0] = random(-60+y/3, 60-y/3);
    line[i][1] = random(-20, 20)+y;
    line[i][2] = random(-60+y/3, 60-y/3);
    line[i][3] = random(-20, 20)+y;
    line[i][4] = 0;
    line[i][5] = random(-5, 5)+y;
    num[i] = random(50);
void drawArtFrame (int whichFrame) { 
  vertex(0, 60);
  int count = 0;
  for (int i =0; i<23; i++) {
    line[i][0]+80*(getNoise(whichFrame, 0.05, num[count], num[count])-0.5),
    line[i][1]+40*(getNoiseSlow(whichFrame, 0.1, num[count], num[count])-0.5),
    line[i][2]+80*(getNoiseSlow(whichFrame, 0.1, num[count], num[count])-0.5),
    line[i][3]+40*(getNoise(whichFrame, 0.05, num[count], num[count])-0.5),
    line[i][4]+80*(getNoiseSlow(whichFrame, 0.1, num[count], num[count])-0.5),
    line[i][5]+40*(getNoiseSlow(whichFrame, 0.1, num[count], num[count])-0.5));


Question 1A
I like effective complexity in graphic layouts. Since all decisions are made by a person, it is disputable whether it can be called a complexity formed by a system (probably not). Still, the most intriguing graphic layouts to me are the ones that seem based on strict, well-informed rules, but that also arbitrarily escape them for a more graphically pleasant outcome.

Question 1B
On The Problem of Authenticity:
I like early 20th century oil paintings. I enjoy staring at them and sort of tracing the painter's intentions. An aesthetic composition in paint mediums can provide that unique, warm firsthand experience as if you're talking to the artist. Most generative art, as with the postmodern approach explained in the article, tend to lack this quality.


Slow Hot Computer - Sam Lavigne

"Slow Hot Computer is a website that makes your computer run slow and hot. Use it at work to decrease your productivity."

I love introducing this work to my friends in design school. You can surprisingly see a lot of art-phobic people in design departments, and it can be hard at times to successfully introduce a work that you like. But Slow Hot Computer has been a constant success. A friend of mine recently got into Samsung and bragged to me about how he's been spreading the site around to his coworkers.

I very much admire the transcendent experience you get from some types of artworks. And this one doesn't give you that. But it speaks to you immediately. When I show this work to people, most of them initially have a good laugh, and agree that Sam Lavigne is a genius. The main factors in play here are:

1. Humor
2. Succinctness
3. Narrative

The first two are quite obvious. This simple artifact also speaks much more about itself than it initially appears to. And that process of revelation happens pretty quick and easily, giving you a pleasant emotional burst, or that "aha" moment. I identify this quality as having a narrative.


2. The Critical Engineer raises awareness that with each technological advance our techno-political literacy is challenged.

Sometimes, when I'm on the subway, I would wonder if the net knowledge of all passengers on the train could amount to making a smart phone. When you think about it for a couple seconds, you will soon realize that there is nearly no way to make a smart phone with that many people on the same train. But at the same time, we're all constantly staring at our phones (especially on the trains). Often, we're so physically close to pieces of technology, yet have no clue of what goes into them and how they've been engineered or manufactured. I haven't had any political view on this, so I'm not perfectly sure what "techno-political" literacy would mean. But I think it would have some things to do with the privacy- and duopoly-related disputes surrounding the web.

But I do feel uneasy with the current pace that technology is evolving. I enjoy coding and learning more about computers, because it gives me composure, a sense that I'm incrementally gaining more control over my life. 


1. Two colors are used: black and white.
2. The artwork is square.
3. There's a bit of margin on all sides
4. All lines are equal length.
5. The lines are rotated at random angles.
6. The center point of the lines are precisely positioned on a grid.
7. There are a total of 57x57 spots
8. There are empty spots. Some are small with just one or two lines missing. Some have grown bigger.
9. There is either a horizontal or vertical grain.
10. The length of each line is the twice that of the spacing between center points of adjacent lines (or maybe a bit shorter).



var NOISE_SCALE = 0.13;
var grains = ['H', 'V'];
var defaultRotation;
var justClicked = true;
var initialSeed;
function setup() {
  createCanvas(720, 720);
  UNIT_SPACE = width/61;
  initialSeed = random(1000);
  noiseDetail(8, 0.5);
function draw() {
  if (justClicked) {
    // set grain between "horizontal" and "vertical"
    if (random(grains) === 'H') defaultRotation = 0;
    else defaultRotation = PI/2;
    // set a new noise seed value
    // draw pattern
    for (var y = 3; y < 59; y++ ) {
       for (var x = 3; x < 59; x++) { // generate noise var noiseValue = noise(NOISE_SCALE*x, NOISE_SCALE*y); // low-pass filter if (noiseValue > NOISE_THRESHOLD) { 
           // draw individual line
           translate( x*UNIT_SPACE, y*UNIT_SPACE );
           // apply noise to rotation
           rotate(map(noise(NOISE_SCALE_ROT*x, NOISE_SCALE_ROT*y), 0, 1, -PI/1.8, PI/1.8)); // rotate based on noise
           line( -0.95*UNIT_SPACE, 0, 0.95*UNIT_SPACE, 0 );
    justClicked = false;
function mouseClicked() {
  justClicked = true;

Writing down the observations really helped me realize certain details that might have gone unnoticed such as the horizontal or vertical grain. The images also grew on me as I looked more at them. I set off to learn more about the Perlin noise. Soon I figured that the pattern of the empty spots and line rotations could be achieved with Perlin noise. I started coding right away, only to find out that I didn't understand Perlin noise correctly. So I took my time reading the p5 documentations and some texts on the mathematical foundation of Perlin noise. I was really surprised when I found out that Vera Molnar made Interruptions before Perlin noise was invented. If there was any particular difficulty with this sketch, it was trying to get both outcomes right--the empty patterns and line rotation--with the same parameters for the noiseDetail() function.