conf template and bugfixs

This commit is contained in:
sam 2020-09-29 22:40:10 +02:00
parent 93a5bf7fe5
commit 71bcd8ba68
17 changed files with 1433 additions and 74 deletions

47
LJ.conf
View File

@ -1,5 +1,5 @@
[General]
lasernumber = 1
lasernumber = 4
debug = 0
ljayserverip = 0.0.0.0
wwwip = 192.168.2.43
@ -13,13 +13,13 @@ type = DS1000
ip = 192.168.2.4
kpps = 25000
centerx = 0
centery = 0
centery = 765
zoomx = 45.0
zoomy = 45.0
sizex = 32000
sizey = 32000
finangle = 0.0
swapx = 1
swapx = -1
swapy = -1
lsteps = [ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
@ -32,20 +32,20 @@ color = -1
type = LOCAL
ip = 192.168.2.43
kpps = 25000
centerx = 0
centery = 0
zoomx = 45.0
zoomy = 45.0
centerx = -11970
centery = -6510
zoomx = 30.0
zoomy = 30.0
sizex = 32000
sizey = 32000
finangle = -30.0
finangle = 0.0
swapx = -1
swapy = -1
lsteps = [ (1.0, 2),(0.25, 1), (0.75, 1), (1.0, 5)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[laser2]
color = -1
@ -63,14 +63,14 @@ swapx = -1
swapy = -1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[laser3]
color = -1
type = LUKE400
ip = 192.168.1.5
ip = 192.168.2.3
kpps = 25000
centerx = 0
centery = 0
@ -83,19 +83,13 @@ swapx = -1
swapy = -1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[plugins]
plugins = {
"trckr": {"OSC": 8017, "command": "python3 plugins/VJing/trckr.py", "display": True},
"aurora": {"OSC": 8090, "command": "python3 plugins/aurora/aurora.py", "display": True},
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
"nozoid": {"OSC": 8003, "command": "python3 plugins/audio/nozoids3.py", "display": True},
"glyph": {"OSC": 8004, "command": "python3 plugins/laserglyph.py", "display": True},
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py", "display": True},
@ -103,6 +97,11 @@ plugins = {
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py", "display": True},
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py", "display": False},
"artnet": {"OSC": 8009, "command": "python3 libs3/artnet.py", "display": False},
"trckr": {"OSC": 8017, "command": "python3 plugins/trckr.py", "display": False},
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py", "display": True},
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py", "display": True},

View File

@ -34,11 +34,11 @@ ip = 192.168.2.43
kpps = 25000
centerx = 0
centery = 0
zoomx = 45.0
zoomy = 45.0
zoomx = 30.0
zoomy = 30.0
sizex = 32000
sizey = 32000
finangle = -30.0
finangle = 0
swapx = -1
swapy = -1
lsteps = [ (1.0, 2),(0.25, 1), (0.75, 1), (1.0, 5)]
@ -89,13 +89,7 @@ warpdest = [[-1500., 1500.],
[plugins]
plugins = {
"trckr": {"OSC": 8017, "command": "python3 plugins/VJing/trckr.py", "display": True},
"aurora": {"OSC": 8090, "command": "python3 plugins/aurora/aurora.py", "display": True},
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
"nozoid": {"OSC": 8003, "command": "python3 plugins/audio/nozoids3.py", "display": True},
"glyph": {"OSC": 8004, "command": "python3 plugins/laserglyph.py", "display": True},
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py", "display": True},
@ -103,6 +97,11 @@ plugins = {
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py", "display": True},
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py", "display": False},
"artnet": {"OSC": 8009, "command": "python3 libs3/artnet.py", "display": False},
"trckr": {"OSC": 8017, "command": "python3 plugins/trckr.py", "display": False},
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py", "display": True},
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py", "display": True},

View File

@ -28,7 +28,7 @@ Important : for best performance LJ is meant to run in a dedicated computer espe
- Some Lasermapping ('alignment') like in videomapping.
- OSC and websocket commands. Very cool : LJ can script or be scripted.
- Python3
- Web User Interface in your browser : open www/index.html. Javascript is needed. By default it connect to localhost. If you want to control remotely, you need to change the uri line in LJ.js.
- Web User Interface in your browser : open www/index.html. Javascript is needed. By default it connect to localhost. If you want to control remotely, you need edit webui choice : python3 configure.py
- Live WebUI extras : change debug level, restart plugin, rescan DACs,...
- Status update every 0.5 seconds : every etherdream DAC state, number of buffer points sent,...
- "Optimisation" points automatically added, can be changed live for glitch art. Search "resampler" commands.
@ -260,10 +260,14 @@ DrawDests() will take care of all your declared drawn elements/"objects" and Des
# Nannou etherdeam simulator aka visualiser
#
2 compiled nannou visualisers are included, one for Linux, one for macOS. It's pretty old version but much more compatible with "old" processors/computer.
Nannou visualiser kind of emulate an etherdream and display in a window what a real laser draws.
2 compiled nannou visualisers are included, one for Linux, one for macOS. It's pretty old versions but much more compatible with "old" processors/computer, as you may want to repurpose an old computer to run LJ.
To use this visualiser as one of LJ's lasers, in LJ.conf edit one of line ip = someipaddress with the IP of the computer running the visualiser. Relaunch LJ. One visualiser per computer.
Nannou visualiser emulation is better and better but one can find a few known non-working situations. See it's github repository (https://github.com/nannou-org/ether-dream/tree/master/dac-emulator) for more recent versions.
#
# Todo
#
@ -349,9 +353,9 @@ About hardware setup, especially if you have several lasers : ILDA cables are in
# Ethertools directory
#
2 useful and always working tools from j4cdac github repository : sitter and talk
- Sitter will display all real etherdreams available on the network and their state (playing, idle,...). python sitter.py or use the compiled version (for macOS).
- Talk : will draw a 4 colors square. python3 talk3.py
2 useful and *always working tools* from j4cdac github repository : sitter and talk.
- Sitter will display all etherdreams available on the network and their state (playing, idle,...). python sitter.py or use the compiled version (for macOS). May need tkinter : pip3 install tk
- Talk : will draw a 4 colors square. Try : python3 talk3.py -h
#
# Links
@ -367,6 +371,8 @@ Generic :
![Laser Faq](https://www.repairfaq.org/sam/lasersam.htm)
![Etherdream protocol](https://ether-dream.com/protocol.html)
There is a nice websocket debug tool : websocat.
#

View File

@ -9,7 +9,7 @@ BOOM | WIIIIIZ :: PHHHHHRACKRACKRACK ~~ WOOP ~~###~~ WIIT
## The basic loop
```
python3 generators/dummy.py -f 2 | filters/kaleidoscope.py | exports/toRedis.py -v
python3 generators/dummy.py -f 2 | python3 filters/kaleidoscope.py | python3 exports/toRedis.py -v
------------------------------ --------------------- -------------------
\/ \/ \/
Generator Filter Export

View File

@ -165,7 +165,7 @@ class DAC(object):
return self.readresp("d")
def prepare(self):
self.conn.sendall('p')
self.conn.sendall(b'p')
return self.readresp('p')
def stop(self):

View File

@ -1,4 +1,17 @@
#!/usr/bin/env python
'''
Improved dac.py and talk.py (by Jacob Potter). Pimped by Sam Neurohack.
- python3
- works with nannou visualisers
- can talk to a given etherdream knowing it's IP.
v0.1.0
'''
#
# j4cDAC test code
#
@ -17,6 +30,19 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import dac3 as dac
import argparse
import sys
argsparser = argparse.ArgumentParser(description="Draw a square on a laser via Etherdream DAC")
argsparser.add_argument("-i","--ip",help="Etherdream IP (default : first etherdream broadcast received",default="True",type=str)
args = argsparser.parse_args()
etherIP = args.ip
class SquarePointStream(object):
'''
@ -88,8 +114,14 @@ class NullPointStream(object):
return [(0, 0, 0, 0, 0)] * n
#dac.find_dac()
if etherIP == "True":
print("Waiting for the first DAC broadcast...")
d = dac.DAC(dac.find_first_dac())
d = dac.DAC(dac.find_first_dac())
#d = dac.DAC("192.168.1.43")
else:
print("Using Etherdream :", etherIP)
d = dac.DAC(etherIP)
print("Sending points...")
d.play_stream(SquarePointStream())

View File

@ -25,15 +25,15 @@ ljpath = r'%s' % os.getcwd().replace('\\','/')
# import from shell
sys.path.append(ljpath +'/../libs/')
sys.path.append(ljpath +'/../libs3/')
#import from LJ
sys.path.append(ljpath +'/libs/')
print(ljpath+'/../libs/')
sys.path.append(ljpath +'/libs3/')
print(ljpath+'/../libs3/')
import lj23layers as lj
sys.path.append('../libs')
sys.path.append('../libs3')
from OSC3 import OSCServer, OSCClient, OSCMessage
import redis
import math

View File

@ -25,15 +25,15 @@ ljpath = r'%s' % os.getcwd().replace('\\','/')
# import from shell
sys.path.append(ljpath +'/../libs/')
sys.path.append(ljpath +'/../libs3/')
#import from LJ
sys.path.append(ljpath +'/libs/')
print(ljpath+'/../libs/')
sys.path.append(ljpath +'/libs3/')
print(ljpath+'/../libs3/')
import lj23layers as lj
sys.path.append('../libs')
sys.path.append('../libs3')
from OSC3 import OSCServer, OSCClient, OSCMessage
import redis
import math

647
plugins/trckr.py Normal file
View File

@ -0,0 +1,647 @@
#!/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);
}
}
'''

View File

@ -25,6 +25,7 @@ sudo apt install libjack-dev
pip3 install python-rtmidi
pip3 install mido
git clone https://github.com/ptone/pyosc --depth 1 /tmp/pyosc && cd /tmp/pyosc && sudo ./setup.py install
pip3 install tk
cd ../
python3 configure.py
# todo : ask for computer ip and run updateUI.py

View File

@ -21,7 +21,7 @@ brew install libasound2-dev
brew install libjack-dev
pip3 install python-rtmidi
pip3 install mido
#pip3 install tk
cd ../
python3 configure.py
#sudo cp syncthing.conf to /etc/supervisor/conf.d/

View File

@ -60,6 +60,7 @@ def www(wwwip):
print("Updating www files to use", wwwIP)
Updatepage(ljpath+"/www/LJ.js")
Updatepage(ljpath+"/www/trckr/trckrcam1.html")
Updatepage(ljpath+"/www/trckr/trckr.html")
Updatepage(ljpath+"/www/simu.html")
Updatepage(ljpath+"/www/align.html")
Updatepage(ljpath+"/www/auralls.html")

View File

@ -1,5 +1,21 @@
clmtrackr
======
= Web Interface
You can load index.html file from your browser or have a webserver of your choice pointing to this directory.
Webserver is mandatory if you want :
- to remotely control LJ : imagine LJ can be installed in a dedicated computer/container with no easy access.
- to use the face tracking, say from a smartphone. That's Lasercam (a clmtrackr plugin).
== Simu
A laser simulator. Choose lasernumber and it will display redis points for current scene/lasernumber
== clmtrackr
[![npm version](https://img.shields.io/npm/v/clmtrackr.svg)](https://www.npmjs.com/package/clmtrackr)

View File

@ -300,16 +300,6 @@
console.log("/laser "+res[1])
newlaser(res[1])
break;
case "/lack/":
console.log("/lack "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
case "/lstt/":
console.log("/lstt "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
default:

View File

@ -287,17 +287,6 @@
case "/plpoi":
//console.log("plpoint");
break;
case "/lack/":
console.log("/lack "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
case "/lstt/":
console.log("/lstt "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
default:
//console.log("test "+res[0].slice(1)+" "+res[1]);
document.getElementById(res[0].slice(1)).value = res[1];

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

679
www/trckr/trckr.html Normal file
View File

<
@ -0,0 +1,679 @@
<!doctype html>
<html lang="en">
<head>
<title>LASERCam 1</title>
<meta charset="utf-8">
<link href="./styles/bootstrap.min.css" rel="stylesheet" type="text/css">
<meta name="apple-mobile-web-app-title" content="Tracker">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-startup-image" href="../launch.png">
<link rel="apple-touch-icon" href="../touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="152x152" href="../touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="180x180" href="../touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="167x167" href="../touch-icon-ipad-retina.png">
<style>
</style>
<script>
// getUserMedia only works over https in Chrome 47+, so we redirect to https. Also notify user if running from file.
if (window.location.protocol == "file:") {
alert("You seem to be running this example directly from a file. Note that these examples only work when served from a server or localhost due to canvas cross-domain restrictions.");
} else if (window.location.hostname !== "localhost" && window.location.protocol !== "https:"){
window.location.protocol = "http";
//window.location.protocol = "https";
}
</script>
<!--
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-32642923-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
-->
<!-- Web audio buttons defaults -->
<script type="application/javascript" src="../webcomponents-lite.js"></script>
<script>
WebAudioControlsOptions={
useMidi:1,
knobSrc:"knobs/simplegray.png",
knobSprites:100,
switchSrc:"knobs/switch_toggle.png",
sliderSrc:"knobs/vsliderbody.png",
sliderKnobsrc:"knobs/vsliderknob.png",
}
</script>
<script src="../webaudio-controls.js"></script>
<!-- link rel="stylesheet" href="LJgrid.css" / -->
<link rel="stylesheet" type="text/css" href="../selector.min.css">
<script type="application/javascript" src="../selector.min.js"></script>
<link rel="stylesheet" href="../css/common.css" />
</head>
<body style="background-color:#222;">
<script src="./js/libs/utils.js"></script>
<script src="../build/clmtrackr.js"></script>
<script src="./js/libs/Stats.js"></script>
<!--
Top Rack
<div align="center">
<a href="index.html"><img height="25" width="21" src="../knobs/indexs.png"></a>
</div>
-->
<div class="Rackcontent">
<!--
Navigation Rack
-->
<div class="content">
<div class="buttons-7container">
<a href="../index.html">
<div class="webaudiobut">
<div align="center" class="navled">
Index
</div>
</div>
</a>
<a href="../align.html">
<div class="webaudiobut">
<div align="center" class="navled">
Align
</div>
</div>
</a>
<a href="../auralls.html">
<div class="webaudiobut">
<div align="center" class="navled">
Aurora
</div>
</div>
</a>
<a href="trckrcam1.html">
<div class="webaudiobut">
<div align="center" class="navled">
Lasercam
</div>
</div>
</a>
<a href="../simu.html">
<div class="webaudiobut">
<div align="center" class="navled">
Simu
</div>
</div>
</a>
<div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
rstrt LJ
</button>
</div>
<div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart aurora" >
rstrt AU
</button>
</div>
</div>
</div>
<!--
Lasers & colors Rack
-->
<div class="content">
<div class="TopRackGrid">
<div>
<h2>
/TL RGY 1
<span class="shade">&nbsp;</span>
</h2>
<webaudio-switch id="on" value="1" tooltip="Switch-B" height="35" width="85" src="../knobs/switch1.png">
</webaudio-switch>
</div>
<div style="border : #242424 1px solid;background: #000;">
<div align="center" id="line1" class="busled">
LASERcam 1 : Allow to use your webcam + start
</div>
<div align="center" id="status" class="busled">
/team/laser
</div>
</div>
<div></div>
<div>
<div style="margin-top : 30px;">
</div>
<div>
</div>
</div>
</div>
</div>
<!--
Colors Rack
-->
<div class="content">
<div class="Rackgrid">
<div>
<h2>
Colors
</h2>
</div>
<div class="webaudiobut"><webaudio-switch id="noteon 24" value="1" tooltip="Switch-B" height="64" width="64" src="../knobs/big0.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="noteon 25" value="0" tooltip="Switch-B" height="64" width="64" src=" ../knobs/big1.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="noteon 26" value="0" tooltip="Switch-B" height="64" width="64" src="../knobs/big2.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="noteon 27" value="0" tooltip="Switch-B" height="64" width="64" src="../knobs/big3.png"></webaudio-switch></div>
<div></div>
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 red" value="1" tooltip="Switch-B" height="64" width="64" src="knobs/red.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 yellow" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/yellow.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 green" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/green.png"></webaudio-switch></div>
<div></div>
</div>
</div>
<!--
Webcam Rack
-->
<div class="content" style="background-image: linear-gradient(174deg, #111,#030303);">
<video id="videoel" class="webaudiobut" width="400" height="300" preload="auto" loop playsinline autoplay>
</video>
<canvas id="overlay" width="400" height="300"></canvas>
<input class="btn" type="button" value="wait" style="margin-left: 150px;" disabled="disabled" onclick="startVideo()" id="startbutton"></input>
</div>
<!--
Big Display Rack
-->
<div class="content">
<div id="text" class="busled" style="font-size:1.5em;border : #242424 1px solid;background: #000;-webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);-moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);">
<div id="gum" class="gum">
<p>To try it out:
<ol>
<li>Allow the page to use your webcamera</li>
<li>Make sure that your face is clearly visible in the video, and click start</li>
<li>See the model fitted to your face</li>
<ol>
</p>
</div>
<div id="nogum" class="nogum">
</div>
</div>
</div>
</div>
<!--
JS
-->
<script>
var vid = document.getElementById('videoel');
var vid_width = vid.width;
var vid_height = vid.height;
var overlay = document.getElementById('overlay');
var overlayCC = overlay.getContext('2d');
/*********** Setup of video/webcam and checking for webGL support *********/
function enablestart() {
var startbutton = document.getElementById('startbutton');
startbutton.value = "start";
startbutton.disabled = null;
}
var insertAltVideo = function(video) {
// insert alternate video if getUserMedia not available
if (supports_video()) {
if (supports_webm_video()) {
video.src = "./media/cap12_edit.webm";
} else if (supports_h264_baseline_video()) {
video.src = "./media/cap12_edit.mp4";
} else {
return false;
}
return true;
} else return false;
}
function adjustVideoProportions() {
// resize overlay and video if proportions of video are not 4:3
// keep same height, just change width
var proportion = vid.videoWidth/vid.videoHeight;
vid_width = Math.round(vid_height * proportion);
vid.width = vid_width;
overlay.width = vid_width;
}
function gumSuccess( stream ) {
// add camera stream if getUserMedia succeeded
if ("srcObject" in vid) {
vid.srcObject = stream;
} else {
vid.src = (window.URL && window.URL.createObjectURL(stream));
}
vid.onloadedmetadata = function() {
adjustVideoProportions();
vid.play();
}
vid.onresize = function() {
adjustVideoProportions();
if (trackingStarted) {
ctrack.stop();
ctrack.reset();
ctrack.start(vid);
}
}
}
function gumFail() {
// fall back to video if getUserMedia failed
insertAltVideo(vid);
document.getElementById('gum').className = "hide";
document.getElementById('nogum').className = "nohide";
}
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL;
// set up video
if (navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia({video : true}).then(gumSuccess).catch(gumFail);
} else if (navigator.getUserMedia) {
navigator.getUserMedia({video : true}, gumSuccess, gumFail);
} else {
insertAltVideo(vid);
document.getElementById('gum').className = "hide";
document.getElementById('nogum').className = "nohide";
alert("Your browser does not seem to support getUserMedia, using a fallback video instead.");
}
vid.addEventListener('canplay', enablestart, false);
/*********** Code for face tracking *********/
var ctrack = new clm.tracker();
ctrack.init();
var trackingStarted = false;
var counter = 0;
var layer = 0;
function startVideo() {
// start video
vid.play();
// start tracking
ctrack.start(vid);
trackingStarted = true;
// start loop to draw face
drawLoop();
}
function drawLoop() {
requestAnimFrame(drawLoop);
overlayCC.clearRect(0, 0, vid_width, vid_height);
//psrElement.innerHTML = "score :" + ctrack.getScore().toFixed(4);
var positions = ctrack.getCurrentPosition();
// do something with the positions ...
// print the positions
var positionString = "";
var positionFace = 'trckr/frame '+layer+" "+counter+" ";
if (positions) {
ctrack.draw(overlay);
for (var p = 0;p < 71;p++) {
positionString += "featurepoint "+p+" : ["+positions[p][0].toFixed(2)+","+positions[p][1].toFixed(2)+"]<br/>";
positionFace += positions[p][0].toFixed(2)+" "+positions[p][1].toFixed(2)+" ";
}
//document.getElementById('positions').innerHTML = positionString;
_WS.s.send(positionFace);
counter +=1;
}
}
/*********** Code for stats **********/
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.getElementById('container').appendChild( stats.domElement );
// update stats on every iteration
document.addEventListener('clmtrackrIteration', function(event) {
stats.update();
}, false);
</script>
<!-- LJ style WS : A nettoyer ! -->