forked from protonphoton/LJ
325 lines
7.2 KiB
Python
325 lines
7.2 KiB
Python
#!/usr/bin/python3
|
|
# -*- coding: utf-8 -*-
|
|
# -*- mode: Python -*-
|
|
|
|
|
|
'''
|
|
|
|
Laserglyph
|
|
v0.1.0
|
|
|
|
Anaglyphed rotating cube (for red and green glasses)
|
|
|
|
This client uses the drawing functions (polyline) provided by LJ in lj.py
|
|
|
|
LICENCE : CC
|
|
|
|
by Sam Neurohack
|
|
|
|
|
|
'''
|
|
import sys
|
|
import os
|
|
print()
|
|
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
|
|
|
# import from shell
|
|
|
|
sys.path.append(ljpath +'/../libs/')
|
|
|
|
#import from LJ
|
|
sys.path.append(ljpath +'/libs/')
|
|
print (ljpath+'/../libs/')
|
|
|
|
import lj23 as lj
|
|
|
|
from OSC3 import OSCServer, OSCClient, OSCMessage
|
|
import redis
|
|
import math
|
|
import time
|
|
import argparse
|
|
|
|
'''
|
|
from osc4py3.as_eventloop import *
|
|
from osc4py3 import oscbuildparse
|
|
#from osc4py3 import oscmethod as osm
|
|
from osc4py3.oscmethod import *
|
|
'''
|
|
|
|
OSCinPort = 8004
|
|
oscrun = True
|
|
# myIP = "127.0.0.1"
|
|
PL = 0
|
|
|
|
print ("")
|
|
print ("Arguments parsing if needed...")
|
|
argsparser = argparse.ArgumentParser(description="Text Cycling 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("-c","--client",help="LJ client 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.client:
|
|
ljclient = args.client
|
|
else:
|
|
ljclient = 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
|
|
|
|
|
|
lj.Config(redisIP,ljclient,"glyph")
|
|
|
|
white = lj.rgb2int(255,255,255)
|
|
red = lj.rgb2int(255,0,0)
|
|
blue = lj.rgb2int(0,0,255)
|
|
green = lj.rgb2int(0,255,0)
|
|
|
|
width = 800
|
|
height = 600
|
|
centerX = width / 2
|
|
centerY = height / 2
|
|
|
|
# 3D to 2D projection parameters
|
|
fov = 256
|
|
viewer_distance = 2.2
|
|
|
|
|
|
# Anaglyph computation parameters for right and left eyes.
|
|
eye_spacing = 100
|
|
nadir = 0.5
|
|
observer_altitude = 30000
|
|
#observer_altitude = 10000
|
|
# elevation = z coordinate
|
|
# 0.0, -2000 pop out
|
|
map_plane_altitude = 0.0
|
|
|
|
# Cube coordinates
|
|
# Define the vertices that compose each of the 6 faces.
|
|
vertices = [
|
|
(- 1.0, 1.0,- 1.0),
|
|
( 1.0, 1.0,- 1.0),
|
|
( 1.0,- 1.0,- 1.0),
|
|
(- 1.0,- 1.0,- 1.0),
|
|
(- 1.0, 1.0, 1.0),
|
|
( 1.0, 1.0, 1.0),
|
|
( 1.0,- 1.0, 1.0),
|
|
(- 1.0,- 1.0, 1.0)
|
|
]
|
|
#faces = [(0,1,2,3),(0,4,5,1),(1,5,6,2),(2,3,7,6),(6,5,4,7),(7,3,0,4)]
|
|
faces = [(0,1,2,3),(0,4,5,1),(1,5,6,2),(2,3,7,6),(7,3,0,4),(7,3,0,4)]
|
|
# name, intensity, active, xy, color, red, green, blue, PL , closed):
|
|
Leftcube = lj.FixedObject('Leftcube', True, 255, [], red, 255, 0, 0, PL , True)
|
|
Rightcube = lj.FixedObject('Rightcube', True, 255, [], green, 0, 255, 0, PL , True)
|
|
|
|
# 'Destination' for each PL
|
|
# name, number, active, PL , scene, laser
|
|
# PL 0
|
|
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0)
|
|
Dest1 = lj.DestObject('1', 1, True, 0 , 1, 1)
|
|
|
|
'''
|
|
viewgen3Lasers = [True,False,False,False]
|
|
# Add here, one by one, as much destination as you want for each PL.
|
|
# LJ and OSC can remotely add/delete destinations here.
|
|
|
|
lj.Dests = {
|
|
"0": {"PL": 0, "scene": 0, "laser": 0},
|
|
"1": {"PL": 0, "scene": 1, "laser": 1}
|
|
}
|
|
|
|
'''
|
|
|
|
def LeftShift(elevation):
|
|
|
|
diff = elevation - map_plane_altitude
|
|
return nadir * eye_spacing * diff / (observer_altitude - elevation)
|
|
|
|
def RightShift(elevation):
|
|
|
|
diff = map_plane_altitude - elevation
|
|
return (1 - nadir) * eye_spacing * diff / (observer_altitude - elevation)
|
|
|
|
|
|
# OSC
|
|
#
|
|
|
|
oscserver = OSCServer( (myIP, OSCinPort) )
|
|
oscserver.timeout = 0
|
|
#oscrun = True
|
|
|
|
# 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
|
|
|
|
# /viewgen/ljclient
|
|
def OSCljclient(path, tags, args, source):
|
|
|
|
print("Got /viewgen/ljclient with value", args[0])
|
|
lj.WebStatus("viewgen to virtual "+ str(args[0]))
|
|
ljclient = args[0]
|
|
lj.LjClient(ljclient)
|
|
|
|
|
|
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)
|
|
|
|
def Run():
|
|
|
|
|
|
Left = []
|
|
Right = []
|
|
counter =0
|
|
lj.WebStatus("LaserGlyph")
|
|
lj.SendLJ("/glyph/start 1")
|
|
|
|
# OSC Server callbacks
|
|
print("Starting OSC server at",myIP," port",OSCinPort,"...")
|
|
'''
|
|
osc_startup()
|
|
osc_udp_server(myIP, OSCinPort, "InPort")
|
|
osc_method("/ping", lj.OSCping)
|
|
osc_method("/quit*", quit)
|
|
osc_method("/glyph/ljclient", OSCljclient)
|
|
'''
|
|
oscserver.addMsgHandler( "/glyph/ljclient", OSCljclient )
|
|
|
|
# Add OSC generic plugins commands : 'default", /ping, /quit, /pluginame/obj, /pluginame/var, /pluginame/adddest, /pluginame/deldest
|
|
lj.addOSCdefaults(oscserver)
|
|
|
|
try:
|
|
|
|
while lj.oscrun:
|
|
|
|
lj.OSCframe()
|
|
Left = []
|
|
Right = []
|
|
|
|
x = vertices[0][0]
|
|
y = vertices[0][1]
|
|
z = vertices[0][2]
|
|
|
|
# The cube start always with vertice 0
|
|
# LJ tracers will "move" the laser to this first point in black, then move to the next with second point color.
|
|
# For more accuracy in dac emulator, repeat this first point.
|
|
|
|
# Cube Y axis rotation of 'counter' angle and 3d-2d Proj function.
|
|
#Left.append( Proj(x+LeftShift(z*5),y,z,0,counter,0))
|
|
#Right.append(Proj(x+RightShift(z*5),y,z,0,counter,0))
|
|
|
|
|
|
# Add all the cube points face by face.
|
|
for fa in faces:
|
|
for point in fa:
|
|
x = vertices[point][0]
|
|
y = vertices[point][1]
|
|
z = vertices[point][2]
|
|
|
|
Left.append(Proj(x+LeftShift(z*25),y,z,0,counter,0))
|
|
Right.append(Proj(x+RightShift(z*25),y,z,0,counter,0))
|
|
|
|
|
|
# Drawing step, 2 possibilities
|
|
|
|
# Red and Green drawn by laser 0
|
|
#lj.PolyLineOneColor(Left, c = red, PL = PL, closed = True)
|
|
#lj.PolyLineOneColor(Right, c = green, PL = PL, closed = True)
|
|
|
|
lj.PolyLineOneColor(Left, c = Leftcube.color , PL = Leftcube.PL, closed = Leftcube.closed)
|
|
lj.PolyLineOneColor(Right, c = Rightcube.color , PL = Rightcube.PL, closed = Rightcube.closed)
|
|
#print(len(Left))
|
|
|
|
#lj.DrawPL(PL)
|
|
#print(Dest0.name, Dest1.name)
|
|
lj.DrawDests()
|
|
|
|
'''
|
|
# Red on laser 1 and green on laser 2
|
|
lj.PolyLineOneColor(Left, c = red, PL = 1, closed = True)
|
|
lj.PolyLineOneColor(Right, c = green, PL = 2, closed = True)
|
|
lj.DrawPL(1)
|
|
lj.DrawPL(2)
|
|
|
|
'''
|
|
|
|
time.sleep(0.1)
|
|
|
|
counter += 1
|
|
if counter > 360:
|
|
counter = 0
|
|
|
|
except KeyboardInterrupt:
|
|
pass
|
|
|
|
# Gently stop on CTRL C
|
|
|
|
finally:
|
|
|
|
lj.ClosePlugin()
|
|
|
|
|
|
Run()
|