airsun-arsculpture

A Starbucks-specific menu sculpture for improving the decision-making process on what to eat in Starbucks in an efficient and interactive way.

Background Story:

In the AR menu, not only the default items in the bakery counter of the store will be shown, the holiday special food will also be displayed with their name and price. Moreover, if users want to get a more detailed look of the specific item, they can enlarge them using their fingers. This project is currently a prototype demonstrating this idea. More specific research of the items sold in different stores is needed to be done and connected to the final display. In doing this project, I used found model of the bakery items and made the model of the text and price in blender. Moreover, I incorporated two scripts, one for animating the items to let them rotate and travel in circles, the other one is for the interaction with fingers.  All color and font are consistent with the current color theme and font type Starbucks is using. And the specific item and their prices are also consistent with Starbucks' current market price.

airsun-book

Link of the zip file:https://drive.google.com/file/d/1vK9PlB3Dhnp6-Pvgipe16i5Mij0k40fH/view?usp=sharing

Link of the sample chapter: https://drive.google.com/file/d/1wINmM0CPXhITyv4fDxDD3slvJv1umwXm/view?usp=sharing

Title: Value of Advertisements

Short Description: In today's industry, advertising is actually much less effective than people have historically thought. This work, by using the AFINN ranking of words, challenges the traditional value of advertisement and its effect in building product's quality image.

Long Description: In today's industry, advertising is actually much less effective than people have historically thought. The research paper "The effect of advertising on brand awareness and perceived quality: An empirical investigation using panel data" done by C.R. Clark, Ulrich Doraszelski (University of Pennsylvania), and Michaela Draganska, establishes the finding that advertising has "no significant effect on perceived quality" of a brand. The use of advertisement does build a significant positive effect on brand awareness, but details in the advertisement do not change people's quality perception. Therefore, looking at the most recent products by Apple, an experiment of changing the advertisements from its official website with different descriptive words (all positive, but differs in the levels of positivity) is conducted. Through the process, I am wondering about the differences between the randomly generated results and the original transcript. From the generated advertisement, will people really pay attention to new descriptive words? If so, to what extent? If not, then I am curious about whether computing generated word will be able to replace the traditional advertisement.

To discover this effect, I first copied down and cleaned the set of advertisements from the Apple official websites. Then, I categorized the list of AFINN ranking of words by the level of positivity and part of speech (noun/verb/adj/adv). After that, I replaced descriptive words from the original ads with the AFINN ranking word with the proper capitalization and punctuation to make things "make sense". An example of advertisements for iPhone Xs:

Here is an example of the advertisement for the AirPods:

Moreover, to make the advertisement resembles more of the actual advertisement of Apple, I studied typography, choice of images, layout and color scheme of their official website. From one of their advertisement videos, I got photos that represent the product and randomly assigned them to each advertisement.

Here are some inspirational layout and photos used for designing the final pages: 

Embedded Code:

var rhymes, word, data;
 
var afinn;
 
function preload() {
  afinn = loadJSON('afinn111.json');
  script = loadJSON('description.json');
}
 
 
var detect_words = [];
var detect_values = [];
var currentlevel;
//for general category
var pos_verbs = [];
var neg_verbs = [];
var pos_adj = [];
var neg_adj = [];
var pos_adv = [];
var neg_adv = [];
//for high category
var pos_adj_high = [];
var pos_adv_high = [];
var pos_verbs_high = [];
//for low category 
var pos_adj_low = [];
var pos_adv_low = [];
var pos_verbs_low = [];
 
var original_ary1 = [];
var original_ary2 = [];
var original_ad;
var original_ad_ary;
var output = [];
var output1 = [];
var output2 = [];
var currentT1 = [];
var currentT2 = [];
var currentT3 = [];
var currentT4 = [];
var currentT5 = [];
var currentT6 = [];
var currentT7 = [];
var currentT8 = [];
var currentT9 = [];
var phonecontent;
var imagecontent;
// var page = {phone: phonecontent, image: imagecontent}
// var page2 = {phone: phonecontent, image: imagecontent}
// var page3 = {phone: phonecontent, image: imagecontent}
var final_array = [];
 
 
//creating the larger 2d array
var pagearray1 = [];
var pagearray2 = [];
 
 
 
function setup(){
  createCanvas(800, 1000);
  fill(255);
  textFont("Georgia");
 
  var txt = afinn;
  var currentWord;
 
  detect_words = Object.getOwnPropertyNames(txt);
 	detect_values = Object.values(txt);
//AirPods
//IphoneXs
  original_ary1 = script.IphoneXs;
  //print(original_ary1)
  produceP(original_ary1, pagearray1);
  //original_ary2 = script.AirPods;
  //produceP(original_ary2, pagearray2);
  print("array1", pagearray1)
  //print("array2", pagearray2)
 
}
 
function produceP(original_ary, pagearray){
  //print(original_ary)
  //this for loop is used to get the positive and negative verbs for the advertisement
  for (var i = 0; i < detect_values.length; i ++){ currentWord = detect_words [i].replace(/\s+/g, ''); if (detect_values[i] > 0){
      if (RiTa.isVerb(currentWord)) {
      	pos_verbs.push(currentWord)
    	} 
      if (RiTa.isAdjective(currentWord)){
        pos_adj.push(currentWord)
      }
      if (RiTa.isAdverb(currentWord)){
        pos_adv.push(currentWord)
      }
    } if  (detect_values[i] <= 5 && detect_values[i] >= 3){
      if (RiTa.isVerb(currentWord)) {
      	pos_verbs_high.push(currentWord)
    	} 
      if (RiTa.isAdjective(currentWord)){
        pos_adj_high.push(currentWord)
      }
      if (RiTa.isAdverb(currentWord)){
        pos_adv_high.push(currentWord)
      }
    } if  (detect_values[i] < 3 && detect_values[i] >= 0){
      if (RiTa.isVerb(currentWord)) {
      	pos_verbs_low.push(currentWord)
    	} 
      if (RiTa.isAdjective(currentWord)){
        pos_adj_low.push(currentWord)
      }
      if (RiTa.isAdverb(currentWord)){
        pos_adv_low.push(currentWord)
      }
    }
  }
 
  // print("verbs", pos_verbs_5)
  // print("adj", pos_adj_5)
  // print("adv",pos_adv_5)
 
////////////////generating positivity words in general////////////
	for (var t = 0; t < original_ary.length; t++){
    var newstring =new RiString (original_ary[t])
    var posset = newstring.pos()
    var wordset = newstring.words()
    var original_ad_ary = original_ary[t].match(/\w+|\s+|[^\s\w]+/g)
    var current_content = "";
    for (var j = 0; j < posset.length; j++){ // if the word is a verb if (/vb.*/.test(posset[j])){ // if the word is not is/are/be if (wordset[j] != "is" && wordset[j] != "are" && wordset[j] != "be"){ //running for all positive word var newverb = round(random(0, pos_verbs.length-1)); var track; if (j>=2){
            if (wordset[j-1] == "." ){
              track = pos_verbs[str(newverb)][0].toUpperCase()+pos_verbs[str(newverb)].slice(1);
            }else{
              track = pos_verbs[str(newverb)];
            }
          }else{
            if (j==0){
            	track = pos_verbs[str(newverb)][0].toUpperCase()+pos_verbs[str(newverb)].slice(1);
            }else{
            	track = pos_verbs[str(newverb)];
            }
          }
          current_content += track;
        }else if (wordset[j] == "is"){
          current_content += "is";
        }else if (wordset[j] == "are"){
          current_content += "are";
        }else{
          current_content += "be";
        }
      }else{
        if (/jj.*/.test(posset[j])){
          var newadj = round(random(0, pos_adj.length-1));
          var track2;
          if (j>=2){
            if (wordset[j-1] == "." ){
              track2 = pos_adj[str(newadj)][0].toUpperCase()+pos_adj[str(newadj)].slice(1);
            }else{
              track2 = pos_adj[str(newadj)];
            }
          }else{
            if (j==0){
            	track2 = pos_adj[str(newadj)][0].toUpperCase()+pos_adj[str(newadj)].slice(1);
            }else{
            	track2 = pos_adj[str(newadj)];
            }
          }
          current_content += track2;
        } else if (/rb.*/.test(posset[j])){
          var newadv = round(random(0, pos_adv.length-1));
          var track3;
          if (j>=2){
            if (wordset[j-1] == "." ){
              track3 = pos_adv[str(newadv)][0].toUpperCase()+pos_adv[str(newadv)].slice(1);
            }else{
              track3 = pos_adv[str(newadv)];
            }
          }else{
            if (j==0){
            	track3 = pos_adv[str(newadv)][0].toUpperCase()+pos_adv[str(newadv)].slice(1);
            }else{
            	track3 = pos_adv[str(newadv)];
            }
          }
          current_content += track3;
        }else{
          current_content += wordset[j];
        }
      }
      if (wordset[j+1] != "." && wordset[j+1] != "!" && wordset[j+1] != "," && wordset[j+1] != "?"){
      	current_content += " ";
      }
    }
    output.push(current_content);
    if (t<2) { currentT1.push(current_content) }else if (t>=2 && t<4){
      currentT2.push(current_content)
    }else{
      currentT3.push(current_content)
    }
  }
  append(pagearray, output);
 
////////////////generating high positivity words////////////
for (var t1 = 0; t1 < original_ary.length; t1++){
    lexicon = new RiLexicon();
    var newstring1 =new RiString (original_ary[t1])
    var posset1 = newstring1.pos()
    var wordset1 = newstring1.words()
    var current_content1 = "";
    for (var j1 = 0; j1 < posset1.length; j1++){ // getting the positive adj,adv,verbs //print("1", wordset1[j1]) // if the word is a verb if (/vb.*/.test(posset1[j1])){ //print("4",wordset1[j1]) // if the word is not is/are/be if (wordset1[j1] != "is" && wordset1[j1] != "are" && wordset1[j1] != "be"){ //print("**", wordset1[j1]) //running for all positive word var newverb1 = round(random(0, pos_verbs_high.length-1)); var trackb1; if (j1>=2){
            //print("***", wordset1[j1], wordset1[j1-1])
            if (wordset1[j1-1] == "." ){
              //print("****", wordset1[j1])
              trackb1 = pos_verbs_high[str(newverb1)][0].toUpperCase()+pos_verbs_high[str(newverb1)].slice(1);
            }else{
              //print("*!", wordset1[j1])
              trackb1 = pos_verbs_high[str(newverb1)];
            }
          }else{
            if (j1==0){
            	trackb1 = pos_verbs_high[str(newverb1)][0].toUpperCase()+pos_verbs_high[str(newverb1)].slice(1);
            }else{
            	trackb1 = pos_verbs_high[str(newverb1)];
            }
          }
          current_content1 += trackb1;
        }else if (wordset1[j1] == "is"){
          current_content1 += "is";
        }else if (wordset1[j1] == "are"){
          current_content1 += "are";
        }else{
          current_content1 += "be";
        }
      }else{
        if (/jj.*/.test(posset1[j1])){
          //print("2",wordset1[j1])
          var newadj1 = round(random(0, pos_adj_high.length-1));
          var trackb2;
          if (j1>=2){
            //print("2*", wordset1[j1], wordset1[j1-1])
            if (wordset1[j1-1] == "." ){
              //print("2**", wordset1[j1])
              trackb2 = pos_adj_high[str(newadj1)][0].toUpperCase()+pos_adj_high[str(newadj1)].slice(1);
            }else{
              //print("2!", wordset1[j1])
              trackb2 = pos_adj_high[str(newadj1)];
            }
          }else{
            if (j1==0){
              trackb2 = pos_adj_high[str(newadj1)][0].toUpperCase()+pos_adj_high[str(newadj1)].slice(1);
            }else{
             trackb2 = pos_adj_high[str(newadj1)];
            }
          }
          current_content1 += trackb2;
        } else if(/rb.*/.test(posset1[j1])){
          //print("3",wordset1[j1])
          var newadv1 = round(random(0, pos_adv_high.length-1));
          var trackb3;
          if (j1>=2){
            //print("3*", wordset1[j1], wordset1[j1-1])
            if (wordset1[j1-1] == "." ){
              //print("3**", wordset1[j1])
              trackb3 = pos_adv_high[str(newadv1)][0].toUpperCase()+pos_adv_high[str(newadv1)].slice(1);
            }else{
              //print("3!", wordset1[j1])
              trackb3 = pos_adv_high[str(newadv1)];
            }
          }else{
            if (j1==0){
              trackb3 = pos_adv_high[str(newadv1)][0].toUpperCase()+pos_adv[str(newadv1)].slice(1);
            }else{
             trackb3 = pos_adv_high[str(newadv1)];
            }
          }
          current_content1 += trackb3;
        }else{
          //print("5",wordset1[j1])
          current_content1 += wordset1[j1];
        } 
      }
      if (wordset1[j1+1] != "." && wordset1[j1+1] != "!" && wordset1[j1+1] != "," && wordset1[j1+1] != "?"){
        current_content1 += " ";
        //print("6",wordset1[j1]);
      }
    }
 
    output1.push(current_content1);
  	if (t1<2) { currentT4.push(current_content1) }else if (t1>=2 && t1<4){
      currentT5.push(current_content1)
    }else{
      currentT6.push(current_content1)
    }
}
 
	append(pagearray, output1);
  //print("arraybig",pagearray);
 
////////////////generating low positivity words////////////
for (var t2 = 0; t2 < original_ary.length; t2++){
    lexicon = new RiLexicon();
    var newstring2 =new RiString (original_ary[t2])
    var posset2 = newstring2.pos()
    var wordset2 = newstring2.words()
    var current_content2 = "";
    for (var j2 = 0; j2 < posset2.length; j2++){ // getting the positive adj,adv,verbs //print("1", wordset2[j2]) // if the word is a verb if (/vb.*/.test(posset2[j2])){ //print("4",wordset2[j2]) // if the word is not is/are/be if (wordset2[j2] != "is" && wordset2[j2] != "are" && wordset2[j2] != "be"){ //print("**", wordset2[j2]) //running for all positive word var newverb2 = round(random(0, pos_verbs_low.length-1)); var trackc1; if (j2>=2){
            //print("***", wordset2[j2], wordset2[j2-1])
            if (wordset2[j2-1] == "." ){
              //print("****", wordset2[j2])
              trackc1 = pos_verbs_low[str(newverb2)][0].toUpperCase()+pos_verbs_low[str(newverb2)].slice(1);
            }else{
              //print("*!", wordset2[j2])
              trackc1 = pos_verbs_low[str(newverb2)];
            }
          }else{
            if (j2==0){
            	trackc1 = pos_verbs_low[str(newverb2)][0].toUpperCase()+pos_verbs_low[str(newverb2)].slice(1);
            }else{
            	trackc1 = pos_verbs_low[str(newverb2)];
            }
          }
          current_content2 += trackc1;
        }else if (wordset2[j2] == "is"){
          current_content2 += "is";
        }else if (wordset2[j2] == "are"){
          current_content2 += "are";
        }else{
          current_content2 += "be";
        }
      }else{
        if (/jj.*/.test(posset2[j2])){
          //print("2",wordset2[j2])
          var newadj2 = round(random(0, pos_adj_low.length-1));
          var trackc2;
          if (j2>=2){
            //print("2*", wordset2[j2], wordset2[j2-1])
            if (wordset2[j2-1] == "." ){
              //print("2**", wordset2[j2])
              trackc2 = pos_adj_low[str(newadj2)][0].toUpperCase()+pos_adj_low[str(newadj2)].slice(1);
            }else{
              //print("2!", wordset2[j2])
              trackc2 = pos_adj_low[str(newadj2)];
            }
          }else{
            if (j2==0){
              trackc2 = pos_adj_low[str(newadj2)][0].toUpperCase()+pos_adj_low[str(newadj2)].slice(1);
            }else{
             trackc2 = pos_adj_low[str(newadj2)];
            }
          }
          current_content2 += trackc2;
        } else if(/rb.*/.test(posset2[j2])){
          //print("3",wordset2[j2])
          var newadv2 = round(random(0, pos_adv_low.length-1));
          var trackc3;
          if (j2>=2){
            //print("3*", wordset2[j2], wordset2[j2-1])
            if (wordset2[j2-1] == "." ){
              //print("3**", wordset2[j2])
              trackc3 = pos_adv_low[str(newadv2)][0].toUpperCase()+pos_adv_low[str(newadv2)].slice(1);
            }else{
              //print("3!", wordset2[j2])
              trackc3 = pos_adv_low[str(newadv2)];
            }
          }else{
            if (j2==0){
              trackc3 = pos_adv_low[str(newadv2)][0].toUpperCase()+pos_adv_low[str(newadv2)].slice(1);
            }else{
             trackc3 = pos_adv_low[str(newadv2)];
            }
          }
          current_content2 += trackc3;
        }else{
          //print("5",wordset2[j2])
          current_content2 += wordset2[j2];
        } 
      }
      if (wordset2[j2+1] != "." && wordset2[j2+1] != "!" && wordset2[j2+1] != "," && wordset2[j2+1] != "?"){
        current_content2 += " ";
        //print("6",wordset2[j2]);
      }
    }
 
    output2.push(current_content2);
  	if (t2<2) { currentT7.push(current_content2) }else if (t2>=2 && t2<4){
      currentT8.push(current_content2)
    }else{
      currentT9.push(current_content2)
    }
}
  //append(pagearray, output2);
  for (var h = 1; h < 10; h++){
    if (h<4){ currentlevel = "Generally Positive" }else if (h>=4 && h < 7){
      currentlevel = "Highly Positive"
    }else {
      currentlevel = "Barely Positive"
    }
    var page = {level: currentlevel, phone: window["currentT"+str(h)], image: str("random"+round(random(1,20))+".jpg")}
    //print(page)
    final_array.push(page);
  }
 
  // print("hi")
  // page1.phone = currentT1;
  // page+str(h).image = str("random"+round(random(1,20))+".jpg")
  // // page2.phone = currentT2;
  // // page2.image = str("random"+round(random(1,20))+".jpg")
  // // page3.phone = currentT3;
  // // page3.image = str("random"+round(random(1,20))+".jpg")
  // final_array.push(page+str(h))
  // // final_array.push(page2)
  // // final_array.push(page3)
  // }
 
 
}
 
function draw()
{
  background(100,0,100);
  textAlign(RIGHT);
  textSize(36);
  //text(output, 280, 40);
 
  textAlign(LEFT);
  textSize(10);
  textLeading(14);
  text(output, 30, 20, 500, 1000);
  text(output1, 30, 220, 500, 1000);
  text(output2, 30, 420, 500, 1000);
 
  createButton('SAVE POEMS BUTTON')
    .position(10, 10)
    .mousePressed(function() {
      saveJSON(final_array, 'test.json');
  });
 
}

 

airsun-shuann-justaline

This AR experience adds playful and creative elements on top of the classic statue.

We were imagining people experiences this in a more serious museum setting. By adding creative components to the statues, the audiences are able to apply their own imagination on top of a well-recognized piece, potentially changing the original aura and meaning of it. This could easily be turned into a shared experience where people exchange their re-imagination.

airsun-shuann-Automaton

 

 

Top shot to display the gums

For this project, we created an automatic display that presents distinct gum and description pairs on a rotating base. Once the viewer approaches the machine, the belt located on the top of the white box will turn to display the next gum within the gum family. Simultaneously, the museum label facing the viewer will also turn to display the next story in association with the gum.

We really put a lot of thoughts into the development of the background stories for each gum, including their appearances, personalities, and background of how they ended up here in this gum collection. We also attempted to create an impactful contrast between the conventionally neat and clean museum display with gums, which people often associate with the opposite connotation.

Front Look
Process shot for inside structure
Process shot
Process shot

Here is the list of gums' stories. For each gum, we will personalize a story for them based on their shape, color, and brand. The first card gives a brief introduction of the gum family, which serves as a museum label introducing the artwork.

airsun-parrish

Watching Allison Parrish's talk before actually doing the project has given me a very informative and helpful introduction to the significance of text in my daily life. Coming from a decision science background, I did research on word recognition and verbal perception. During the research and learning process, what I have been focused on is the human beings' impacts on words. For example, how our opinions/personalities influence the way we talk, write, and communicate. However, when Allison talks about the "lexical space", what is being reflected is how words show our behaviors. It focuses on words and its pattern to discover human beings instead of focusing on humans and see their impacts on words. This change in perspective is really interesting. While I am listening to Allison's talk, my mind has jumped to places where I reflected on how our language reflects our political standing, our emotions, etc. Then, some ideas came to my mind, it will be interesting to create an algorithm where the drawings are created based on the keywords in the text. And the text is captured through social media/email/messenger or any of the medium of communication. Then, without seeing the subject of this sentence, what are some interpretation that can be created upon the keywords, the word choice, the tenses, and other verbal patterns?

airsun-LookingOutwards04

MULTITOUCH ( 2010 )
Filmed at the Claremont Colleges in Claremont, CA

Multitouch (2010), designed and made by Amanda Ghassei, is a very elegant, clean designed, and interesting multitouch system. It interacts with fingers. When someone touches the glass surface, the lights will be scattered down on the corresponding plane. Moreover, it will generate different sound effects or music tone when different squared surfaces were selected. The engineer behind this is briefly introduced on Ghassei's website. It was built based on the open source monome project. In order to generate a thin plane of light on the surface, she uses a technique called Laser Light Plane. The work also uses an Arduino Uno scanner for determining the coordinates of the point(s) of contact. What attracts me the most about the project is the later versions of development. After making the MULTITOUCH interacting with the hand, Ghassei places the work into new context and environment, e.g. before a museum or in nature. By placing them there, she let the context interact with Multitouch. It is really interesting to see the change in natural light and the corresponding subtle music. It challenges how we usually associate music with a specific setting and a mood. Compared with our conventional concept towards this association, seeing how technology/algorithm interprets different environment and to find a music tone for them is very fresh and thoughtful.

 

airsun-body

Anxiety is the inspiration for the project. More specifically, reflecting on me often get nervous when people interacting with me. When people that I am not familiar with talk with me, sometimes, I just blushed and could not control it. Moreover, when talking to other introverts, I found we share a similar experience. Therefore, I want to portray this nervous tension going on between individuals, and exaggerate it. And this is when Ovia was born. And to help my audience understand more about her, here is a paragraph of the introduction: "Ovia is quiet and simple being. She is very shy and nervous when interacting with people. When you try to interact with her, she will always be shaking, blushing, and getting smaller. When you push her limits, she will hide all her features and become a ball."

// Clair Sijing Sun
// Copyright (c) 2018 ml5
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
 
 
let video;
let poseNet;
let poses = [];
var r=20;
var posy;
var posx;
var timer = 0;
var dim;
// var colorR = 252;
// var colorG = 238;
// var colorB = 213;
var colorR = 250;
var colorG = 210;
var moving = 1;
var hairp1x = 301;
var hairp1y = 136-40;
var hairp2x = 297;
var hairp2y = 129-40;
var hairp3x = 303;
var hairp3y = 118-40;
var hairp4x = 299;
var hairp4y = 115-40;
var right = 1;
var left  = 1;
var radius;
var blushl = 59;
var frames = [];
 
 
function setup() {
  createCanvas(640, 480);
  ellipseMode(RADIUS);
  dim = width/2;
  posx = width/2;
  radius = width/6;
  //colorMode(HSB, 360, 100, 100);
  posy = height/2-40;
  video = createCapture(VIDEO);
  video.size(width, height);
 
  // Create a new poseNet method with a single detection
  poseNet = ml5.poseNet(video, modelReady);
  // This sets up an event that fills the global variable "poses"
  // with an array every time new poses are detected
  poseNet.on('pose', function(results) {
    poses = results;
  });
  // Hide the video element, and just show the canvas
  video.hide();
}
 
function preload(){
  frames.push(loadImage("https://i.imgur.com/qVyg9s1.png"));
}
 
function modelReady() {
  select('#status').html('!!!');
}
 
function draw() {
  background(255);
 
  timer +=1;
 
  //background face
  if (poses.length > 0){
    posx = random(width/2-moving,width/2+moving);
    moving = randomGaussian (-poses.length,poses.length);
 
  }
  if (poses.length < 5){
    drawGradient(posx, posy);
  }
 
  //the eyewhite
  push();
  fill(252,238, 213);
  if (poses.length < 5){ ellipse(posx,posy,20,20); } fill(0); drawKeypoints(); stroke(4); pop(); //blushing push(); noStroke(); if (poses.length == 1){ if (blushl > 55.6){
     blushl -= 0.2;
    } if (blushl < 55.6){ blushl += 0.2; } }if (poses.length == 2){ if (blushl > 50){
     blushl -= 0.2;
    } if (blushl < 50){ blushl += 0.2; } }if (poses.length == 3){ if (blushl > 38){
     blushl -= 0.2;
    }if (blushl < 38){ blushl += 0.2; } }if (poses.length == 4){ if (blushl > 16){
     blushl -= 0.2;
    }if (blushl < 16){
     blushl += 0.2;
    }
  }
 
  fill(255,126,0);
  if (poses.length < 5){ ellipse(posx+blushl, 240, 10, 6); ellipse(posx-blushl, 240, 10, 6); } pop(); //hair drawHair(); image(frames[0], width/2-190, height/2+50, 400, 200); } function drawHair() { stroke(1); noFill(); beginShape(); if (timer%10 == 0){ right *= -1; } if (timer%15 == 0){ left *= -1; } hairp1x = posx - 19; hairp2x +=right; hairp3x -=left*0.5; hairp4x +=right; if (poses.length == 0){ if (hairp1y > 95){
      hairp1y = hairp1y - 0.2;
      hairp2y = hairp2y - 0.2;
      hairp3y = hairp3y - 0.2;
      hairp4y = hairp4y - 0.2;
    }
  }
  if (poses.length == 1){
    if (hairp1y < 101){ hairp1y = hairp1y + 0.2; hairp2y = hairp2y + 0.2; hairp3y = hairp3y + 0.2; hairp4y = hairp4y + 0.2; }if (hairp1y > 101){
      hairp1y = hairp1y - 0.2;
      hairp2y = hairp2y - 0.2;
      hairp3y = hairp3y - 0.2;
      hairp4y = hairp4y - 0.2;
    }
  }if (poses.length == 2){
    if (hairp1y < 111){ hairp1y = hairp1y + 0.2; hairp2y = hairp2y + 0.2; hairp3y = hairp3y + 0.2; hairp4y = hairp4y + 0.2; }if (hairp1y > 111){
      hairp1y = hairp1y - 0.2;
      hairp2y = hairp2y - 0.2;
      hairp3y = hairp3y - 0.2;
      hairp4y = hairp4y - 0.2;
    }
  }if (poses.length == 3){
    if (hairp1y < 131){ hairp1y = hairp1y + 0.2; hairp2y = hairp2y + 0.2; hairp3y = hairp3y + 0.2; hairp4y = hairp4y + 0.2; }if (hairp1y > 131){
      hairp1y = hairp1y - 0.2;
      hairp2y = hairp2y - 0.2;
      hairp3y = hairp3y - 0.2;
      hairp4y = hairp4y - 0.2;
    }
  }if (poses.length == 4){
    if (hairp1y < 171){ hairp1y = hairp1y + 0.2; hairp2y = hairp2y + 0.2; hairp3y = hairp3y + 0.2; hairp4y = hairp4y + 0.2; }if (hairp1y > 171){
      hairp1y = hairp1y - 0.2;
      hairp2y = hairp2y - 0.2;
      hairp3y = hairp3y - 0.2;
      hairp4y = hairp4y - 0.2;
    }
  }
 
  if (poses.length < 5){
  curveVertex(hairp1x, hairp1y);
  curveVertex(hairp1x, hairp1y);
  curveVertex(hairp2x, hairp2y);
  curveVertex(hairp3x, hairp3y);
  curveVertex(hairp4x, hairp4y);
  curveVertex(hairp4x, hairp4y);
  endShape();
 
  beginShape();
  curveVertex(hairp1x+20, hairp1y);
  curveVertex(hairp1x+20, hairp1y);
  curveVertex(hairp2x+20, hairp2y);
  curveVertex(hairp3x+20, hairp3y);
  curveVertex(hairp4x+20, hairp4y);
  curveVertex(hairp4x+20, hairp4y);
  endShape();
 
  beginShape();
  curveVertex(hairp1x+40, hairp1y);
  curveVertex(hairp1x+40, hairp1y);
  curveVertex(hairp2x+40, hairp2y);
  curveVertex(hairp3x+40, hairp3y);
  curveVertex(hairp4x+40, hairp4y);
  curveVertex(hairp4x+40, hairp4y);
  endShape();
  }
 
 
}
 
 
 
// A function to draw ellipses over the detected keypoints
function drawKeypoints()  {
  // Loop through all the poses detected
 
  if (poses.length == 1){
    for (let i = 0; i < poses.length; i++) {
      // For each pose detected, loop through all the keypoints
      let pose = poses[i].pose;
      for (let j = 0; j < pose.keypoints.length; j++) {
        // A keypoint is an object describing a body part (like rightArm or leftShoulder)
        let keypoint = pose.keypoints[j];
 
        let noseP = pose.keypoints[0]
        // Only draw an ellipse is the pose probability is bigger than 0.2
        //print(keypoint.position.x);
        push();
        var fx = map(noseP.position.x, 0, width, -1, 1);
        var fy = map(noseP.position.y, 0, height, -1, 1);
        var mx = map(posx, 0, width, -1, 1);
        var my = map(posy, 0, height, -1, 1);
        var dir = atan2((fy - my), (fx - mx));
 
        var amp = 10;
        if (dist(posx, posy, noseP.position.x, noseP.position.y) <= 12){
           amp = dist(posx, posy, noseP.position.x, noseP.position.y);
        }
        translate(posx + amp * cos(dir), posy + amp * sin(dir));
        rotate(dir);
 
        var c = constrain(dist(posx, posy, noseP.position.x, noseP.position.y), 0, 12);
        var distshape = map(c, 0, 30, 1, 0.9);
 
 
        ellipse(0, 0, 5 * distshape, 5);
        pop();
 
      }
    }
  }else{
    ellipse(posx, posy, 5, 5); 
  }
}
 
 
function drawGradient(x, y) {
  var h = 255;
  noStroke();
  if (poses.length == 0){
    if (radius < 106.6){ radius = radius + 0.2; } } if (poses.length == 1){ if (radius > 100){
      radius = radius - 0.2;
    }
    if (radius <= 100){ radius = radius + 0.2; } }if (poses.length ==2){ if (radius > 90){
      radius = radius - 0.2;
    }
    if (radius <= 90){ radius = radius + 0.2; } }if (poses.length ==3){ if (radius > 70){
      radius = radius - 0.2;
    }
    if (radius <= 70){ radius = radius + 0.2; } }if (poses.length ==4){ if (radius > 30){
      radius = radius - 0.2;
    }
    if (radius <= 30){ radius = radius + 0.2; } }if (poses.length ==5){ if (radius > 10){
      radius = radius - 0.2;
    }
    if (radius <= 10){ radius = radius + 0.2; } } for (var r = radius; r > 0; --r) {
    if (poses.length == 0){
      colorR = 250;
      colorG = 210;
    } if (poses.length == 1){
 
      if (colorG > 188){
        colorG -= 0.01;
      }if (colorG < 188){ colorG += 0.01; } } if (poses.length == 2){ if (colorG > 148){
        colorG -= 0.01;
      }
    }
    fill(colorR, colorG-r/3.5, 0);
    ellipse(x, y, r, r);
  }
}
 
 
 
 
/*
 
function setup() {
  createCanvas(710, 400);
  background(255);
  ellipseMode(RADIUS);
}
 
function draw() {
  background(255);
  drawGradient(width/2, height/2);
  push();
  fill(252,238,213)
  ellipse(width/2,height/2,20,20);
  fill(0);
  ellipse(width/2,height/2+10,4,4);
  stroke(4);
  line(width/2,height/2-width/6,width/2,height/2-width/6-20);
  line(width/2-20,height/2-width/6+2,width/2-22,height/2-width/6-18);
  line(width/2+20,height/2-width/6+2,width/2+22,height/2-width/6-18);
  pull();
}
 
function drawGradient(x, y) {
  var h = 255;
  var radius = width/6;
  noStroke();
  for (var r = radius; r > 0; --r) {
    fill(250, 166-r/3.5, 0);
    ellipse(x, y, r, r);
  }
}
*/

 

airsun-telematic

Recorded Version of two people talking and exploring some visual feedbacks

Click To enter full-screen mode

This is a dynamic chat room. The idea is that user can see the visual response of the content and words they are putting into the conversation. The font, color, position of the text, and typography all change corresponding to the content of the conversation. For example, when typing "right", the text will go towards the right edge of the chatroom. Similarly, when typing "left", the text will go toward the left edge of the chatroom. When typing "larger", the text size will increase, and when typing "smaller", the text size will decrease. Moreover, the similar idea applies to the color function in which when users type keywords of different shades of color, the color of the text will change. Other more reactions can be found when typing "bold", "child", "design", "Halloween", "scare", "scary", "fear", "essay", "report", "homework", "study", "important", "highlight", "tension", "note","technology", "computer", "coding", "computing", "round","circle", "hand", "poe", "literature", "letter", "dot", "tight", "squee", "italic", "Italic".
I always feel like text in conversation can be more fun and interesting than what it looks like now in messaging apps (all in default gray color and same size). Except for using emoji, how can text itself express anything interesting? If the text can do more, maybe we can get rid off emoji. The original idea of this project was to incorporate the basic emotions ("joy", "angry", "fear", "surprise", "disgust", and "sad") to execute the changes of type. However, this idea generalizes people's current state of feeling and have many issues with the user experience, therefore, I changed and developed the current version of the project, hoping the idea will come across with more interesting user interactions.