Better redis doc
This commit is contained in:
		
							parent
							
								
									56e95c4c4b
								
							
						
					
					
						commit
						c5c7051ddc
					
				
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @ -172,18 +172,18 @@ A "plugin" is a software that send any number of pointlist(s). LJ comes with dif | |||||||
| # Client Side : Program your own "plugin"  | # Client Side : Program your own "plugin"  | ||||||
| # | # | ||||||
| 
 | 
 | ||||||
| The server approach is based on redis, so you can write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients). An external program that just send pointlists is a "client". If you want some interactions from the webUI, like text status area support, crash detection, launch,... it's a "plugin" and some default code is needed. See custom1.py, a basic plugin you can modiffy. LJ and plugins signaling is mainly over OSC. | The server approach is based on redis, so you can write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients). An external program that just send pointlists to redis is a "client". If you want some interactions from the webUI, like text status area support, crash detection, autostart,... it's a "plugin" and some default code is needed. LJ and plugins signaling is over OSC. | ||||||
| 
 | 
 | ||||||
| - Read all this readme ;-) | - Read all this readme ;-) | ||||||
| - Generate at least one pointlist array (say a square) with *enough points*, one point is likely to fail for buffering reason. See command reference below for more. | - Generate at least one pointlist array (say a square) with *enough points*, one point is likely to fail for buffering reason.  | ||||||
| - Feed your point list array in string format to redis server. i.e use "/pl/0/1" redis key to feed scene 0, laser 1. | - Feed your point list array in string format to redis server. i.e use "/pl/0/1" redis key to feed scene 0, laser 1. See /pl/ command in command reference below how to send your pointlist to i.e /pl/0/1 redis key. | ||||||
| - Tell LJ.conf your plugin configuration : OSC port and command line to start it. | - Tell LJ.conf your plugin configuration : OSC port and command line to start it. | ||||||
| - At least a plugin must reply /pong to OSC request /ping. | - At least a plugin must reply /pong to OSC request /ping. | ||||||
| 
 | 
 | ||||||
| Currently the WebUI (www/index.html) is static.  | Currently the WebUI (www/index.html) is static.  | ||||||
| 
 | 
 | ||||||
| # | # | ||||||
| # Client side dope mode : How to use lj23 (python3) | # Client side dope mode for python 3 generators : How to use lj23  | ||||||
| #  | #  | ||||||
| 
 | 
 | ||||||
| lj23 have many very useful functions to not reinvent the wheel for advanced points generation "client" side : layers, sprites, built in rotations,.. | lj23 have many very useful functions to not reinvent the wheel for advanced points generation "client" side : layers, sprites, built in rotations,.. | ||||||
| @ -191,7 +191,7 @@ lj23 have many very useful functions to not reinvent the wheel for advanced poin | |||||||
| 
 | 
 | ||||||
| 4 Great TRICKS with lj23 : | 4 Great TRICKS with lj23 : | ||||||
| 
 | 
 | ||||||
| First open square.py and learn how to declare different objects. square.py is a 2D shape example in 3D rotation (red/green anaglyph rendering) that use 2 layers : one for left eye and one for right eye. | First open custom1.py and learn how to declare different objects. custom1.py is a 2D shape example in 3D rotation (red/green anaglyph rendering) that use 2 layers : one for left eye and one for right eye. custom1 is a copy of square.py | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 1/ How to have another laser drawing the same thing ? | 1/ How to have another laser drawing the same thing ? | ||||||
| @ -370,12 +370,16 @@ Generic : | |||||||
| # LJ commands reference | # LJ commands reference | ||||||
| # | # | ||||||
| 
 | 
 | ||||||
| All commands are available via OSC (port 8002) or websocket (port 9001) | All these commands are available via OSC (port 8002) or websocket (port 9001)  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| /pl/scenenumber/lasernumber value : value is the pointlist to draw as string. Example :  | /pl/scenenumber/lasernumber value : value is the pointlist to draw as string. Example :  | ||||||
| /pl/0/0 "[(150.0, 230.0, 65280), (170.0, 170.0, 65280), (230.0, 170.0, 65280), (210.0, 230.0, 65280), (150.0, 230.0, 65280)]" | /pl/0/0 "[(150.0, 230.0, 65280), (170.0, 170.0, 65280), (230.0, 170.0, 65280), (210.0, 230.0, 65280), (150.0, 230.0, 65280)]" | ||||||
| 
 | 
 | ||||||
|  | Use the same syntax if you send your pointlist directly in redis : "/pl/0/0" is the key and value is "[(150.0,..."  | ||||||
|  | 
 | ||||||
|  | Every point must be : (x,y,color). Color is the hex color #FFFFFF in decimal. | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| /scale/X/lasernumber value    | /scale/X/lasernumber value    | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										277
									
								
								plugins/custom1.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										277
									
								
								plugins/custom1.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,277 @@ | |||||||
|  | #!/usr/bin/python3 | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # -*- mode: Python -*- | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ''' | ||||||
|  | 
 | ||||||
|  | custom1 | ||||||
|  | v0.1.0 | ||||||
|  | 
 | ||||||
|  | A copy of square.py you can modify to code your plugin. | ||||||
|  | custom1 has necessary hooks in LJ.conf, webui and so on. | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 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 lj23layers as lj | ||||||
|  | 
 | ||||||
|  | sys.path.append('../libs') | ||||||
|  | from OSC3 import OSCServer, OSCClient, OSCMessage | ||||||
|  | import redis | ||||||
|  | import math | ||||||
|  | import time | ||||||
|  | import argparse | ||||||
|  | 
 | ||||||
|  | OSCinPort = 8014 | ||||||
|  | 
 | ||||||
|  | print ("") | ||||||
|  | print ("Arguments parsing if needed...") | ||||||
|  | argsparser = argparse.ArgumentParser(description="Custom1 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) | ||||||
|  | 
 | ||||||
|  | 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. | ||||||
|  | # algorythm come from anaglyph geo maps  | ||||||
|  | eye_spacing = 100 | ||||||
|  | nadir = 0.5 | ||||||
|  | observer_altitude = 30000 | ||||||
|  | map_layerane_altitude = 0.0 | ||||||
|  | 
 | ||||||
|  | # square coordinates : vertices that compose each of the square. | ||||||
|  | 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) | ||||||
|  | 	] | ||||||
|  | 
 | ||||||
|  | face = [0,1,2,3] | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # LJ inits | ||||||
|  | #  | ||||||
|  | 
 | ||||||
|  | layer = 0 | ||||||
|  | 
 | ||||||
|  | # Setup LJ library mandatory properties for this plugin | ||||||
|  | lj.Config(redisIP, ljscene, "custom1") | ||||||
|  | 
 | ||||||
|  | # Define properties for each drawn "element" : name, intensity, active, xy, color, red, green, blue, layer , closed | ||||||
|  | Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, layer , True) | ||||||
|  | Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], green, 0, 255, 0, layer , True) | ||||||
|  | 
 | ||||||
|  | # '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  | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # Anaglyph computation : different X coordinate for each eye | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | def LeftShift(elevation): | ||||||
|  | 
 | ||||||
|  | 			diff = elevation - map_layerane_altitude | ||||||
|  | 			return nadir * eye_spacing *  diff / (observer_altitude - elevation) | ||||||
|  | 
 | ||||||
|  | def RightShift(elevation): | ||||||
|  | 
 | ||||||
|  | 			diff = map_layerane_altitude - elevation | ||||||
|  | 			return (1 - nadir) * eye_spacing * diff / (observer_altitude - elevation) | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # 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 | ||||||
|  | 
 | ||||||
|  | # /custom1/ljscene | ||||||
|  | def OSCljscene(path, tags, args, source): | ||||||
|  | 
 | ||||||
|  |     print("Got /custom1/ljscene with value", args[0]) | ||||||
|  |     lj.WebStatus("custom1 to virtual "+ str(args[0])) | ||||||
|  |     ljscene = args[0] | ||||||
|  |     lj.Ljscene(ljscene) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 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(): | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	Left = [] | ||||||
|  | 	Right = [] | ||||||
|  | 	counter =0 | ||||||
|  | 	#lj.SendLJ("/custom1/start 1") | ||||||
|  | 
 | ||||||
|  | 	# OSC Server callbacks | ||||||
|  | 	print("Starting OSC server at",myIP," port",OSCinPort,"...") | ||||||
|  | 	oscserver.addMsgHandler( "/custom1/ljscene", OSCljscene ) | ||||||
|  | 
 | ||||||
|  | 	# 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] | ||||||
|  | 	 | ||||||
|  | 			# 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. | ||||||
|  | 
 | ||||||
|  | 			# Generate all points in square. | ||||||
|  | 			for point in face: | ||||||
|  | 				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))	 | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 			lj.PolyLineOneColor(Left, c = Leftsquare.color , layer = Leftsquare.layer, closed = Leftsquare.closed) | ||||||
|  | 			lj.PolyLineOneColor(Right, c = Rightsquare.color , layer = Rightsquare.layer, closed = Rightsquare.closed) | ||||||
|  | 
 | ||||||
|  | 			lj.DrawDests() | ||||||
|  | 	 | ||||||
|  | 			 | ||||||
|  | 			time.sleep(0.1) | ||||||
|  | 	 | ||||||
|  | 			counter += 1 | ||||||
|  | 			if counter > 360: | ||||||
|  | 				counter = 0 | ||||||
|  | 
 | ||||||
|  | 	except KeyboardInterrupt: | ||||||
|  | 		pass | ||||||
|  | 
 | ||||||
|  | 	# Gently stop on CTRL C | ||||||
|  | 
 | ||||||
|  | 	finally: | ||||||
|  | 
 | ||||||
|  | 		lj.ClosePlugin() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Run() | ||||||
							
								
								
									
										279
									
								
								plugins/square.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										279
									
								
								plugins/square.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,279 @@ | |||||||
|  | #!/usr/bin/python3 | ||||||
|  | # -*- coding: utf-8 -*- | ||||||
|  | # -*- mode: Python -*- | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ''' | ||||||
|  | 
 | ||||||
|  | Square | ||||||
|  | v0.1.0 | ||||||
|  | 
 | ||||||
|  | Anaglyphed rotating square (for red and green glasses) | ||||||
|  | 
 | ||||||
|  | This scene uses the drawing functions provided by LJ in lj23.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 lj23layers as lj | ||||||
|  | 
 | ||||||
|  | sys.path.append('../libs') | ||||||
|  | from OSC3 import OSCServer, OSCClient, OSCMessage | ||||||
|  | import redis | ||||||
|  | import math | ||||||
|  | import time | ||||||
|  | import argparse | ||||||
|  | 
 | ||||||
|  | OSCinPort = 8013 | ||||||
|  | 
 | ||||||
|  | print ("") | ||||||
|  | print ("Arguments parsing if needed...") | ||||||
|  | argsparser = argparse.ArgumentParser(description="Square 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) | ||||||
|  | 
 | ||||||
|  | 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. | ||||||
|  | # algorythm come from anaglyph geo maps  | ||||||
|  | eye_spacing = 100 | ||||||
|  | nadir = 0.5 | ||||||
|  | observer_altitude = 30000 | ||||||
|  | map_layerane_altitude = 0.0 | ||||||
|  | 
 | ||||||
|  | # square coordinates : vertices that compose each of the square. | ||||||
|  | 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) | ||||||
|  | 	] | ||||||
|  | 
 | ||||||
|  | face = [0,1,2,3] | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # LJ inits | ||||||
|  | #  | ||||||
|  | 
 | ||||||
|  | layer = 0 | ||||||
|  | 
 | ||||||
|  | # Setup LJ library mandatory properties. | ||||||
|  | lj.Config(redisIP, ljscene, "square") | ||||||
|  | 
 | ||||||
|  | # You can define properties for each drawn "element" : name, intensity, active, xy, color, red, green, blue, layer , closed | ||||||
|  | Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, layer , True) | ||||||
|  | Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], blue, 0, 255, 0, layer , True) | ||||||
|  | 
 | ||||||
|  | # '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  | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # Anaglyph computation : different X coordinate for each eye | ||||||
|  | # | ||||||
|  | 
 | ||||||
|  | def LeftShift(elevation): | ||||||
|  | 
 | ||||||
|  | 			diff = elevation - map_layerane_altitude | ||||||
|  | 			return nadir * eye_spacing *  diff / (observer_altitude - elevation) | ||||||
|  | 
 | ||||||
|  | def RightShift(elevation): | ||||||
|  | 
 | ||||||
|  | 			diff = map_layerane_altitude - elevation | ||||||
|  | 			return (1 - nadir) * eye_spacing * diff / (observer_altitude - elevation) | ||||||
|  | 
 | ||||||
|  | # | ||||||
|  | # 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 | ||||||
|  | 
 | ||||||
|  | # /square/ljscene | ||||||
|  | def OSCljscene(path, tags, args, source): | ||||||
|  | 
 | ||||||
|  |     print("Got /square/ljscene with value", args[0]) | ||||||
|  |     lj.WebStatus("square to virtual "+ str(args[0])) | ||||||
|  |     ljscene = args[0] | ||||||
|  |     lj.Ljscene(ljscene) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 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(): | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	Left = [] | ||||||
|  | 	Right = [] | ||||||
|  | 	counter =0 | ||||||
|  | 	lj.WebStatus("Square") | ||||||
|  | 	lj.SendLJ("/square/start 1") | ||||||
|  | 
 | ||||||
|  | 	# OSC Server callbacks | ||||||
|  | 	print("Starting OSC server at",myIP," port",OSCinPort,"...") | ||||||
|  | 	oscserver.addMsgHandler( "/square/ljscene", OSCljscene ) | ||||||
|  | 
 | ||||||
|  | 	# 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] | ||||||
|  | 	 | ||||||
|  | 			# 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. | ||||||
|  | 
 | ||||||
|  | 			# Generate all points in square. | ||||||
|  | 			for point in face: | ||||||
|  | 				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))	 | ||||||
|  | 	 | ||||||
|  | 
 | ||||||
|  | 			lj.PolyLineOneColor(Left, c = Leftsquare.color , layer = Leftsquare.layer, closed = Leftsquare.closed) | ||||||
|  | 			lj.PolyLineOneColor(Right, c = Rightsquare.color , layer = Rightsquare.layer, closed = Rightsquare.closed) | ||||||
|  | 
 | ||||||
|  | 			lj.DrawDests() | ||||||
|  | 	 | ||||||
|  | 			 | ||||||
|  | 			time.sleep(0.1) | ||||||
|  | 	 | ||||||
|  | 			counter += 1 | ||||||
|  | 			if counter > 360: | ||||||
|  | 				counter = 0 | ||||||
|  | 
 | ||||||
|  | 	except KeyboardInterrupt: | ||||||
|  | 		pass | ||||||
|  | 
 | ||||||
|  | 	# Gently stop on CTRL C | ||||||
|  | 
 | ||||||
|  | 	finally: | ||||||
|  | 
 | ||||||
|  | 		lj.ClosePlugin() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | Run() | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user