forked from protonphoton/LJ
648 lines
16 KiB
Python
648 lines
16 KiB
Python
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
# -*- mode: Python -*-
|
|
|
|
|
|
'''
|
|
|
|
trckr
|
|
Work with clmtrackr-dev and www/trckr/trckr.html
|
|
v0.1.0
|
|
|
|
|
|
LICENCE : CC
|
|
by Sam Neurohack
|
|
|
|
To test the examples locally, you need to run a local server.
|
|
One easy way to do this is to install http-server, a small node.js utility:
|
|
npm install -g http-server.
|
|
|
|
Then run http-server in the root of clmtrackr and go to
|
|
|
|
- read a video :
|
|
http://localhost:8080/examples/trckr.html
|
|
- webcam
|
|
|
|
|
|
clmtrackr :
|
|
https://github.com/auduno/clmtrackr/tree/dev/examples
|
|
|
|
|
|
'''
|
|
import sys
|
|
import os
|
|
print()
|
|
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
|
|
|
# import from shell
|
|
sys.path.append(ljpath +'/../libs3/')
|
|
#import from LJ
|
|
import log
|
|
|
|
print ("")
|
|
|
|
log.infog("Trckr Plugin v0.1")
|
|
|
|
|
|
sys.path.append('../libs3')
|
|
sys.path.append(ljpath +'/../../libs3')
|
|
|
|
from OSC3 import OSCServer, OSCClient, OSCMessage
|
|
import lj23layers as lj
|
|
import redis
|
|
import math
|
|
import time
|
|
import argparse
|
|
|
|
OSCinPort = 8017
|
|
|
|
print ("")
|
|
print ("Arguments parsing if needed...")
|
|
argsparser = argparse.ArgumentParser(description="trckr example for LJ")
|
|
argsparser.add_argument("-r","--redisIP",help="IP of the Redis server used by LJ (127.0.0.1 by default) ",type=str)
|
|
argsparser.add_argument("-s","--scene",help="LJ scene number (0 by default)",type=int)
|
|
#argsparser.add_argument("-l","--laser",help="Laser number to be displayed (0 by default)",type=int)
|
|
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",type=int)
|
|
argsparser.add_argument("-m","--myIP",help="Local IP (127.0.0.1 by default) ",type=str)
|
|
|
|
args = argsparser.parse_args()
|
|
|
|
if args.scene:
|
|
ljscene = args.scene
|
|
else:
|
|
ljscene = 0
|
|
'''
|
|
if args.laser:
|
|
plnumber = args.laser
|
|
else:
|
|
plnumber = 0
|
|
'''
|
|
|
|
# Redis Computer IP
|
|
if args.redisIP != None:
|
|
redisIP = args.redisIP
|
|
else:
|
|
redisIP = '127.0.0.1'
|
|
|
|
print("redisIP",redisIP)
|
|
|
|
# myIP
|
|
if args.myIP != None:
|
|
myIP = args.myIP
|
|
else:
|
|
myIP = '127.0.0.1'
|
|
|
|
print("myIP",myIP)
|
|
|
|
if args.verbose:
|
|
debug = args.verbose
|
|
else:
|
|
debug = 0
|
|
|
|
# Useful variables init.
|
|
white = lj.rgb2int(255,255,255)
|
|
red = lj.rgb2int(255,0,0)
|
|
blue = lj.rgb2int(0,0,255)
|
|
green = lj.rgb2int(0,255,0)
|
|
|
|
# 3D to 2D projection parameters
|
|
fov = 256
|
|
viewer_distance = 2.2
|
|
|
|
width = 800
|
|
height = 600
|
|
centerX = width / 2
|
|
centerY = height / 2
|
|
|
|
TrckrPts = [[0,0]] * 70
|
|
|
|
|
|
|
|
#
|
|
# LJ inits
|
|
#
|
|
|
|
layer = 0
|
|
|
|
# Setup LJ library mandatory properties for this layerugin
|
|
lj.Config(redisIP, ljscene, "trckr")
|
|
|
|
# Define properties for each drawn "element" : name, intensity, active, xy, color, red, green, blue, layer , closed
|
|
FaceForm = lj.FixedObject('Face', True, 255, [], red, 255, 0, 0, layer , False)
|
|
|
|
# 'Destination' for given layer : name, number, active, layer , scene, laser
|
|
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0
|
|
|
|
|
|
|
|
#
|
|
# OSC
|
|
#
|
|
|
|
oscserver = OSCServer( (myIP, OSCinPort) )
|
|
oscserver.timeout = 0
|
|
|
|
|
|
# this method of reporting timeouts only works by convention
|
|
# that before calling handle_request() field .timed_out is
|
|
# set to False
|
|
def handle_timeout(self):
|
|
self.timed_out = True
|
|
|
|
# funny python's way to add a method to an instance of a class
|
|
import types
|
|
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
|
|
|
|
|
# OSC callbacks
|
|
|
|
# /trckr/ljscene
|
|
def OSCljscene(path, tags, args, source):
|
|
|
|
print("Got /trckr/ljscene with value", args[0])
|
|
lj.WebStatus("trckr to virtual "+ str(args[0]))
|
|
ljscene = args[0]
|
|
lj.Ljscene(ljscene)
|
|
|
|
# /trckr/layer
|
|
def OSClayer(path, tags, args, source):
|
|
|
|
print()
|
|
print()
|
|
print("Got /trckr/layer with value", args[0])
|
|
lj.WebStatus("trckr to layer "+ str(args[0]))
|
|
FaceForm.layer = int(args[0])
|
|
Dest0.layer = int(args[0])
|
|
Dest0.laser = int(args[0])
|
|
|
|
# /trckr/frame
|
|
def OSCtrckr(path, tags, args, source):
|
|
global TrckrPts
|
|
|
|
#print("trckr got frame", args[0])
|
|
if debug != 0:
|
|
print("trckr plugin got frame", args[0])
|
|
print(len(args),"args", args)
|
|
counter =0
|
|
TrckrPts = []
|
|
|
|
for dot in range(1,len(args)-1,2):
|
|
|
|
TrckrPts.append([float(args[dot]), float(args[dot+1])])
|
|
print(TrckrPts)
|
|
|
|
# /trckr/frame layernumber framenumber points
|
|
def OSCTrckrframe(path, tags, args, source):
|
|
global TrckrPts
|
|
|
|
if debug != 0:
|
|
print("trckr plugin got frame", args[1], "for layer", args[0], "with path", path)
|
|
print(len(args),"args", args)
|
|
|
|
TrckrPts[args[0]] = []
|
|
|
|
for dot in range(2,len(args)-1,2):
|
|
TrckrPts[args[0]].append([float(args[dot]), float(args[dot+1])])
|
|
|
|
|
|
|
|
|
|
#/trckr/color/0 red ?
|
|
def OSColor():
|
|
global FaceForm
|
|
|
|
if debug != 0:
|
|
print("trckr color got ", args[1], "for layer", args[0], "with path", path)
|
|
print(len(args),"args", args)
|
|
FaceForm.color = args[1]
|
|
|
|
|
|
# default handler
|
|
def OSChandler(path, tags, args, source):
|
|
|
|
oscaddress = ''.join(path.split("/"))
|
|
print()
|
|
print("trckr default OSC Handler :", path, "from Client :" + str(source[0]))
|
|
|
|
|
|
#
|
|
# Face Tracking
|
|
#
|
|
|
|
# get absolute face position points
|
|
def getPART(pose_points):
|
|
|
|
dots = []
|
|
for dot in pose_points:
|
|
|
|
dots.append((TrckrPts[dot][0], TrckrPts[dot][1],0))
|
|
|
|
return dots
|
|
|
|
|
|
# Face keypoints
|
|
def face():
|
|
pose_points = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14]
|
|
return getPART(pose_points)
|
|
|
|
def browL():
|
|
pose_points = [15,16,17,18]
|
|
return getPART(pose_points)
|
|
|
|
def browR():
|
|
pose_points = [22,21,20,19]
|
|
return getPART(pose_points)
|
|
|
|
def eyeR():
|
|
pose_points = [25,64,24,63,23,66,26,65,25]
|
|
return getPART(pose_points)
|
|
|
|
def eyeL():
|
|
pose_points = [28,67,29,68,30,69,31,28]
|
|
return getPART(pose_points)
|
|
|
|
def pupR():
|
|
pose_points = [27]
|
|
return getPART(pose_points)
|
|
|
|
def pupL():
|
|
pose_points = [32]
|
|
return getPART(pose_points)
|
|
|
|
|
|
def nose1():
|
|
pose_points = [62,41,33]
|
|
return getPART(pose_points)
|
|
|
|
def nose2():
|
|
pose_points = [40,39,38,43,37,42,36,35,34]
|
|
return getPART(pose_points)
|
|
|
|
def mouth():
|
|
pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50]
|
|
return getPART(pose_points)
|
|
|
|
def mouthfull():
|
|
pose_points = [50,49,48,47,46,45,44,55,54,53,52,51,50,59,60,61,44,56,57,58,50]
|
|
return getPART(pose_points)
|
|
|
|
|
|
|
|
|
|
def Proj(x,y,z,angleX,angleY,angleZ):
|
|
|
|
rad = angleX * math.pi / 180
|
|
cosa = math.cos(rad)
|
|
sina = math.sin(rad)
|
|
y2 = y
|
|
y = y2 * cosa - z * sina
|
|
z = y2 * sina + z * cosa
|
|
|
|
rad = angleY * math.pi / 180
|
|
cosa = math.cos(rad)
|
|
sina = math.sin(rad)
|
|
z2 = z
|
|
z = z2 * cosa - x * sina
|
|
x = z2 * sina + x * cosa
|
|
|
|
rad = angleZ * math.pi / 180
|
|
cosa = math.cos(rad)
|
|
sina = math.sin(rad)
|
|
x2 = x
|
|
x = x2 * cosa - y * sina
|
|
y = x2 * sina + y * cosa
|
|
|
|
|
|
""" Transforms this 3D point to 2D using a perspective projection. """
|
|
factor = fov / (viewer_distance + z)
|
|
x = x * factor + centerX
|
|
y = - y * factor + centerY
|
|
return (x,y)
|
|
|
|
|
|
#
|
|
# Main
|
|
#
|
|
|
|
def Run():
|
|
|
|
|
|
Facepts = []
|
|
counter =0
|
|
lj.WebStatus("trckr")
|
|
lj.SendLJ("/trckr/start 1")
|
|
|
|
# OSC Server callbacks
|
|
print("Starting OSC server at",myIP," port",OSCinPort,"...")
|
|
oscserver.addMsgHandler( "/trckr/ljscene", OSCljscene)
|
|
oscserver.addMsgHandler( "/trckr/layer", OSClayer)
|
|
oscserver.addMsgHandler( "/trckr/frame", OSCtrckr)
|
|
oscserver.addMsgHandler( "/trckr/color", OSColor)
|
|
|
|
|
|
# Add OSC generic layerugins commands : 'default", /ping, /quit, /pluginame/obj, /pluginame/var, /pluginame/adddest, /pluginame/deldest
|
|
lj.addOSCdefaults(oscserver)
|
|
oscserver.addMsgHandler( "default", OSChandler )
|
|
try:
|
|
|
|
while lj.oscrun:
|
|
|
|
lj.OSCframe()
|
|
|
|
#print("browL", browL(), "browR", browR(), "nose1", nose1(), "mouth", mouth())
|
|
lj.rPolyLineOneColor(browL(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(eyeL(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(browR(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(eyeR(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(pupL(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(pupR(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(nose1(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(nose2(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
lj.rPolyLineOneColor(mouthfull(), c = FaceForm.color, layer = FaceForm.layer, closed = FaceForm.closed, xpos = -300, ypos = -300, resize = 3.6, rotx = 0, roty = 0, rotz = 0)
|
|
|
|
lj.DrawDests()
|
|
|
|
time.sleep(0.005)
|
|
|
|
counter += 1
|
|
if counter > 360:
|
|
counter = 0
|
|
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|
|
# Gently stop on CTRL C
|
|
|
|
finally:
|
|
|
|
lj.ClosePlugin()
|
|
|
|
|
|
Run()
|
|
'''
|
|
//
|
|
// a template for receiving face tracking osc messages from
|
|
// Kyle McDonald's trckr https://github.com/kylemcdonald/ofxFaceTracker
|
|
//
|
|
// 2012 Dan Wilcox danomatika.com
|
|
// for the IACD Spring 2012 class at the CMU School of Art
|
|
//
|
|
// adapted from from Greg Borenstein's 2011 example
|
|
// http://www.gregborenstein.com/
|
|
// https://gist.github.com/1603230
|
|
//
|
|
|
|
//Xavier Apostol
|
|
//Generative Faces: Plotter Project Concept
|
|
|
|
import oscP5.*;
|
|
OscP5 oscP5;
|
|
|
|
// num faces found
|
|
int found;
|
|
|
|
// pose
|
|
float poseScale;
|
|
PVector posePosition = new PVector();
|
|
PVector poseOrientation = new PVector();
|
|
|
|
// gesture
|
|
float mouthHeight;
|
|
float mouthWidth;
|
|
float eyeLeft;
|
|
float eyeRight;
|
|
float eyebrowLeft;
|
|
float eyebrowRight;
|
|
float jaw;
|
|
float nostrils;
|
|
|
|
float sz = 1;
|
|
float spacing = 100;
|
|
float genSz = spacing/4;
|
|
float fcOff = genSz/2;
|
|
|
|
//Initialization of Colors
|
|
float R = random(255);
|
|
float G = random(255);
|
|
float B = random(255);
|
|
|
|
//Initialization of Head
|
|
float rotInt = 15;
|
|
float hdX = cos(sz) + random(genSz, 3*genSz);
|
|
float hdY = sin(sz) + random(genSz, 3*genSz);
|
|
float rotAngle = random(-rotInt,rotInt);
|
|
|
|
//Initialization of Eyes
|
|
float lEyeX1 = sin(sz*0) + random(genSz);
|
|
float lEyeY1 = cos(sz*0) + random(genSz);
|
|
float rEyeX1 = sin(sz*0) + random(genSz);
|
|
float rEyeY1 = cos(sz*0) + random(genSz);
|
|
float lEyeX2 = sin(sz*1) + random(genSz);
|
|
float lEyeY2 = cos(sz*1) + random(genSz);
|
|
float rEyeX2 = sin(sz*1) + random(genSz);
|
|
float rEyeY2 = cos(sz*1) + random(genSz);
|
|
float ranREye = random(7, 9);
|
|
float ranLEye = random(7, 9);
|
|
|
|
//Initialization of Mouth
|
|
float mthX = cos(sz) + random(genSz);
|
|
float mthY = sin(sz) + random(genSz);
|
|
float ranM = random(-0.1, 1.5);
|
|
|
|
//Initialization of Spine
|
|
float hdOffset = hdY/1.5;
|
|
float spineSz = random(genSz/2);
|
|
float spXOff1 = random(-8, 8);
|
|
float spYOff1 = hdOffset + random(genSz/3);
|
|
float spXOff2 = random(-8, 8)+spXOff1;
|
|
float spYOff2 = random(genSz/3)+spYOff1;
|
|
float spXOff3 = random(-8, 8)+spXOff2;
|
|
float spYOff3 = random(genSz/3)+spYOff2;
|
|
float spXOff4 = random(-8, 8)+spXOff3;
|
|
float spYOff4 = random(genSz/3)+spYOff3;
|
|
float spXOff5 = random(-8, 8)+spXOff4;
|
|
float spYOff5 = random(genSz/3)+spYOff4;
|
|
|
|
void setup() {
|
|
size(800, 600, OPENGL);
|
|
frameRate(30);
|
|
|
|
oscP5 = new OscP5(this, 8338);
|
|
oscP5.plug(this, "found", "/found");
|
|
oscP5.plug(this, "poseScale", "/pose/scale");
|
|
oscP5.plug(this, "posePosition", "/pose/position");
|
|
oscP5.plug(this, "poseOrientation", "/pose/orientation");
|
|
oscP5.plug(this, "mouthWidthReceived", "/gesture/mouth/width");
|
|
oscP5.plug(this, "mouthHeightReceived", "/gesture/mouth/height");
|
|
oscP5.plug(this, "eyeLeftReceived", "/gesture/eye/left");
|
|
oscP5.plug(this, "eyeRightReceived", "/gesture/eye/right");
|
|
oscP5.plug(this, "eyebrowLeftReceived", "/gesture/eyebrow/left");
|
|
oscP5.plug(this, "eyebrowRightReceived", "/gesture/eyebrow/right");
|
|
oscP5.plug(this, "jawReceived", "/gesture/jaw");
|
|
oscP5.plug(this, "nostrilsReceived", "/gesture/nostrils");
|
|
}
|
|
|
|
void keyPressed() {
|
|
if (key == CODED) {
|
|
if (keyCode == UP) {
|
|
//Create an entirely new character.
|
|
|
|
//For Eyes
|
|
lEyeX1 = sin(sz*0) + random(genSz);
|
|
lEyeY1 = cos(sz*0) + random(genSz);
|
|
rEyeX1 = sin(sz*0) + random(genSz);
|
|
rEyeY1 = cos(sz*0) + random(genSz);
|
|
lEyeX2 = sin(sz*1) + random(genSz);
|
|
lEyeY2 = cos(sz*1) + random(genSz);
|
|
rEyeX2 = sin(sz*1) + random(genSz);
|
|
rEyeY2 = cos(sz*1) + random(genSz);
|
|
ranREye = random(7, 9);
|
|
ranLEye = random(7, 9);
|
|
|
|
//For Mouth
|
|
mthX = cos(sz) + random(genSz);
|
|
mthY = sin(sz) + random(genSz);
|
|
ranM = random(-0.1, 1.5);
|
|
|
|
//For Spine
|
|
spineSz = random(genSz/2);
|
|
spXOff1 = random(-8, 8);
|
|
spYOff1 = hdOffset + random(genSz/3);
|
|
spXOff2 = random(-8, 8) + spXOff1;
|
|
spYOff2 = random(genSz/3) + spYOff1;
|
|
spXOff3 = random(-8, 8) + spXOff2;
|
|
spYOff3 = random(genSz/3) + spYOff2;
|
|
spXOff4 = random(-8, 8) + spXOff3;
|
|
spYOff4 = random(genSz/3) + spYOff3;
|
|
spXOff5 = random(-8, 8) + spXOff4;
|
|
spYOff5 = random(genSz/3) + spYOff4;
|
|
|
|
//For Head
|
|
hdX = cos(sz) + random(genSz, 3*genSz);
|
|
hdY = sin(sz) + random(genSz, 3*genSz);
|
|
rotAngle = random(-rotInt,rotInt);
|
|
|
|
//For Colors
|
|
R = random(255);
|
|
G = random(255);
|
|
B = random(255);
|
|
draw();
|
|
}
|
|
}
|
|
}
|
|
|
|
void draw() {
|
|
background(0);
|
|
strokeWeight(1);
|
|
noFill();
|
|
|
|
if(found != 0) {
|
|
pushMatrix();
|
|
translate(posePosition.x, posePosition.y);
|
|
//Scales head and allows for rotations
|
|
scale(poseScale*2);
|
|
rotateY(0 - poseOrientation.y);
|
|
rotateX(0 - poseOrientation.x);
|
|
rotateZ(poseOrientation.z);
|
|
rotate(radians(rotAngle));
|
|
ellipse(0,0, hdX,hdY);
|
|
popMatrix();
|
|
|
|
//FACE
|
|
translate(posePosition.x, posePosition.y);
|
|
scale(poseScale);
|
|
noFill();
|
|
|
|
//Eyes
|
|
float eyeFac = 1;
|
|
float eyeBL = eyebrowLeft * 2;
|
|
float eyeBR = eyebrowRight * 2;
|
|
ellipse(-20,eyeLeft * -ranLEye, lEyeX1*eyeFac + eyeBL,lEyeY1*eyeFac + eyeBL);
|
|
ellipse(20,eyeRight * -ranREye, rEyeX1*eyeFac + eyeBR,rEyeY1*eyeFac + eyeBR);
|
|
ellipse(-20,eyeLeft * -ranLEye, lEyeX2*eyeFac + eyeBL,lEyeY2*eyeFac + eyeBL);
|
|
ellipse(20,eyeRight * -ranREye, rEyeX2*eyeFac + eyeBR,rEyeY2*eyeFac + eyeBR);
|
|
|
|
//Mouth
|
|
ellipse(0, 20*ranM, mouthWidth* mthX/3, mouthHeight * mthY);
|
|
|
|
//BODY/BUBBLES
|
|
stroke(R,G,B);
|
|
ellipse(spXOff1,spYOff1, spineSz,spineSz);
|
|
ellipse(spXOff2,spYOff2, spineSz,spineSz);
|
|
ellipse(spXOff3,spYOff3, spineSz,spineSz);
|
|
ellipse(spXOff4,spYOff4, spineSz,spineSz);
|
|
ellipse(spXOff5,spYOff5, spineSz,spineSz);
|
|
|
|
}
|
|
}
|
|
|
|
// OSC CALLBACK FUNCTIONS
|
|
|
|
public void found(int i) {
|
|
println("found: " + i);
|
|
found = i;
|
|
}
|
|
|
|
public void poseScale(float s) {
|
|
println("scale: " + s);
|
|
poseScale = s;
|
|
}
|
|
|
|
public void posePosition(float x, float y) {
|
|
println("pose position\tX: " + x + " Y: " + y );
|
|
posePosition.set(x, y, 0);
|
|
}
|
|
|
|
public void poseOrientation(float x, float y, float z) {
|
|
println("pose orientation\tX: " + x + " Y: " + y + " Z: " + z);
|
|
poseOrientation.set(x, y, z);
|
|
}
|
|
|
|
public void mouthWidthReceived(float w) {
|
|
println("mouth Width: " + w);
|
|
mouthWidth = w;
|
|
}
|
|
|
|
public void mouthHeightReceived(float h) {
|
|
println("mouth height: " + h);
|
|
mouthHeight = h;
|
|
}
|
|
|
|
public void eyeLeftReceived(float f) {
|
|
println("eye left: " + f);
|
|
eyeLeft = f;
|
|
}
|
|
|
|
public void eyeRightReceived(float f) {
|
|
println("eye right: " + f);
|
|
eyeRight = f;
|
|
}
|
|
|
|
public void eyebrowLeftReceived(float f) {
|
|
println("eyebrow left: " + f);
|
|
eyebrowLeft = f;
|
|
}
|
|
|
|
public void eyebrowRightReceived(float f) {
|
|
println("eyebrow right: " + f);
|
|
eyebrowRight = f;
|
|
}
|
|
|
|
public void jawReceived(float f) {
|
|
println("jaw: " + f);
|
|
jaw = f;
|
|
}
|
|
|
|
public void nostrilsReceived(float f) {
|
|
println("nostrils: " + f);
|
|
nostrils = f;
|
|
}
|
|
|
|
// all other OSC messages end up here
|
|
void oscEvent(OscMessage m) {
|
|
if(m.isPlugged() == false) {
|
|
println("UNPLUGGED: " + m);
|
|
}
|
|
}
|
|
'''
|