SamGruber::Upkit::TextRain

Author: Sam Summary: Textual precipitation, courtesy processing. Abstract: The words of a poem fall from the top of the screen, coming to rest on the user's silouette. This project is a reimplmentation of Text Rain (1999) by Camille Utterback and Romy Achituv. Repository: https://github.com/scgruber/TextRain

TextRain transplants the viewer into a digital rainstorm, wherein the words of a poem descend from above and catch upon dark regions of the viewer’s silouette. As the viewer moves around, the resting letters follow his movements as though they were actual, tangible objects.

To develop this project further, I would like to detect edges in the image more effectively than the current brightness-based method, which is imprecise (for example, the letters falling through my hands in the video). Also, the behavior for raising letters when the supporting object moves stands to become more lifelike. The buildup of letters also seems that it could be handled by some sort of gradual decay.

This project is a reimplmentation of Text Rain (1999) by Camille Utterback and Romy Achituv. It has been developed in Processing 2.0b7. You can check out the source on Github.

/* Text Rain -- Reimplementation
 * Sam Gruber
 * S2013 IACD */

import processing.video.*;

Capture webcam;
ArrayList letters;
int pI = 0;
int ticks = 0;
PFont sans;

String[] poem = {
  "I like talking with you,",
  "simply that: conversing,",
  "a turning-with or -around,",
  "as in your turning around",
  "to face me suddenly . . .",
  "At your turning, each part",
  "of my body turns to verb.",
  "We are the opposite",
  "of tongue-tied, if there",
  "were such an antonym;",
  "We are synonyms",
  "for limbs' loosening",
  "of syntax.",
  "and yet turn to nothing:",
  "It's just talk." };
  
void setup() {
  size(640,480);
  letters = new ArrayList();

  String[] cameras = Capture.list();

  if (cameras.length == 0) {
    println("Wuh-oh! No camera!");
    exit();
  } else {
    webcam = new Capture(this, cameras[0]);
    webcam.start();
  }
  
  sans = loadFont("Cantarell-Bold-14.vlw");
  textFont(sans);
}

class Letter {
  PVector pos;
  PVector vel;
  char ltr;
  color col;
  
  Letter (char inLtr, int inPos, color inCol) {
    pos = new PVector(inPos + random(-2,2), random(-1,0));
    vel = new PVector(0,0.5 + random(-0.25,0.25));
    ltr = inLtr;
    col = inCol;
  }
  
  boolean detectCollision(PImage cam) {
    color slice = cam.get((int)(pos.x), (int)(pos.y));
    return (brightness(slice) < = 128);
  }
  
  void fall() {
    if (detectCollision(webcam)) {
      pos.sub(vel);
      if (detectCollision(webcam)) {
        pos.sub(vel);
      }
    }
    pos.add(vel);
  }
  
  void draw() {
    fill(col);
    text(Character.toString(ltr),pos.x+10,pos.y);
  }
}

void addLetters() {
  if (ticks % 240 == 0) {
    color tone = color(0);
    switch (pI / 5) {
      case 0:
        tone = color(178,18,18);
        break;
      case 1:
        tone = color(41,69,178);
        break;
      default:
        tone = color(255,238,123);
        break;
    }
    for(int i=0; i

This entry was posted in project-1, text-rain on by .

About Sam

Sam Gruber is a junior studying Computer Science and Architecture and the President of the CMU Computer Club. His interests include machine intelligence, realtime graphics demos, and interface design, and he has been sighted both playing in and running tabletop roleplaying games. Sam has experience working with PHP, HTML/CSS, Javascript/Node.js, SML, C/C++ and Linux. He also dabbles in Ruby, Processing, Cinder, Python, and pretty much anything that seems interesting.

Leave a Reply