Skip to content

Instantly share code, notes, and snippets.

@Jennaltj
Last active October 23, 2023 21:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jennaltj/d5addd6a73d6e85a81c5 to your computer and use it in GitHub Desktop.
Save Jennaltj/d5addd6a73d6e85a81c5 to your computer and use it in GitHub Desktop.
Arduino, openCV, EEG, Processing to Unity
public void attentionEvent(int attentionLevel)
{
attention = attentionLevel;
println("Attention:"+attentionLevel);
}
void poorSignalEvent(int sig){}
void meditationEvent(int meditationLevel)
{
meditation = meditationLevel;
//meditation =51;
println("Meditation:"+meditationLevel);
}
void blinkEvent(int blinkStrength)
{
blink = blinkStrength;
}
public void eegEvent(int delta, int theta,int low_alpha,int high_alpha, int low_beta, int high_beta, int low_gamma, int mid_gamma)
{}
void rawEvent(int[]raw){}
void stop() {
neuroSocket.stop();
super.stop();
}
import gab.opencv.*;
import processing.video.*;
import java.awt.*;
import oscP5.*;
import netP5.*;
OscP5 oscP5;
NetAddress myRemoteLocation;
Capture video;
OpenCV opencv;
float rectX,rectY;
float sendX,sendY;
float sendRY,sendRX;
//----------eeg----------//
import neurosky.*;
import org.json.*;
ThinkGearSocket neuroSocket;
boolean enableRawOutput = true;
int attention = 10;
int meditation = 10;
int blink=0;
float raw;
float angle =0.0;
float angleSpeed=0.5;
float sendSpeed;/////
float sendSpeed2;
float sendMe;
float sendBlink;
//----------ping--------//
import processing.serial.*;
float waterLevel;
float waterLevel_NUM;
float WL;
int i=1;
float sendWL;
Serial myPort;
//-----------sound--------//
import ddf.minim.*;
Minim minim;
AudioPlayer player;
//boolean playon= false;
//=========================//
void setup() {
size(640, 480);
frameRate(60);////////
//--------choose camera-----------------
String[] cameras = Capture.list();
if (cameras.length == 0)
{
println("no cameras!");
exit();
}
else
{
println("Available cameras:");
for (int i = 0; i< cameras.length; i++)
{
println(cameras[i]);
}
}
// video = new Capture(this,640/2,480/2,"Logitech Camera");//use other camera
video = new Capture(this,640/2,480/2);
//-------------end choose camera-----------
opencv = new OpenCV(this, 640/2, 480/2);
opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
video.start();
oscP5 = new OscP5(this, 57131);
myRemoteLocation = new NetAddress("127.0.0.1", 57130);
//-----------eeg----------//
ThinkGearSocket neuroSocket = new ThinkGearSocket(this);
try
{
neuroSocket.start();
}
catch (Exception e)
{
}
//=========================//
//----------Ping-----------//
println(Serial.list());
myPort = new Serial(this,Serial.list()[9],9600);
//=========================//
//recordWL.add(waterLevel_NUM);
//----------sound-----------//
minim = new Minim(this);
player = minim.loadFile("034.mp3");
}
void draw() {
scale(2);
opencv.loadImage(video);
image(video, 0, 0 );
noFill();
stroke(0, 255, 0);
strokeWeight(3);
Rectangle[] faces = opencv.detect();
println(faces.length);
for (int i = 0; i < faces.length; i++) {
rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
rectX= (faces[i].x+faces[i].width/2);
rectY= (faces[i].y+faces[i].height/2);
ellipse(rectX,rectY, 10,10);
sendX=(640-rectX)/5;
sendY=-rectY/5;
sendRY = map(sendX,70,118,14,-14);
sendRX = map(sendY,-11,-38,10,-10);
sendValue(sendX,sendY);
sendValueRo(sendRY,sendRX);
}
//---------------ping---------------//
String waterLevel = myPort.readStringUntil('\n');
if (waterLevel!= null)
{
waterLevel_NUM = int(trim(waterLevel));
sendWL = map(waterLevel_NUM,1570,0,-75,30);
sendValueWL(sendWL);
}
else
{
waterLevel_NUM=2000;
}
//---------------eeg-----------------//
//------ATTENTION
text("Attention:"+attention,10,20);
text("Meditation:"+meditation,10,40);
fill(blink,0,0);
if (waterLevel_NUM <800)
{
sendMe = (sin(angle))*0.05;
angle += angleSpeed;
if (attention>=10)
{
sendSpeed = -attention*0.010;
sendSpeed2 = 0;
}
else
{
sendSpeed = 0;
sendSpeed2 = 0;
}
}
else
{
sendSpeed = 0;
sendSpeed2 = 0;
}
println("Attention:"+attention);
println("sendSpeed:"+sendSpeed);
sendValueSp(sendSpeed);
sendValueSp2(sendSpeed2);
sendValueMe(sendMe);
println("sendMe:"+sendMe);
//-------BLINK
if (blink>100)
{
sendBlink = map(blink,0,255,0,30000);
}
else
{
sendBlink=0;
}
sendValueBlink(sendBlink);
println("blink:"+blink);
println("sendBlink:"+sendBlink);
//=======================//
//----------sound---------//
if (meditation>=50 && !player.isPlaying())
{
player.play();
player.rewind();
}
}
void captureEvent(Capture c) {
c.read();
}
//Thanks the orginal author of this function!
void sendValue(float x, float y) //camera position
{
OscMessage oscMess1 = new OscMessage("/sensorX");
oscMess1.add(x);
OscMessage oscMess2 = new OscMessage("/sensorY");
oscMess2.add(y);
oscP5.send(oscMess1, myRemoteLocation);
oscP5.send(oscMess2, myRemoteLocation);
}
void sendValueRo(float m, float n) //camera rotate
{
OscMessage oscMess3 = new OscMessage("/sensorRY");
oscMess3.add(m);
OscMessage oscMess4 = new OscMessage("/sensorRX");
oscMess4.add(n);
oscP5.send(oscMess3, myRemoteLocation);
oscP5.send(oscMess4, myRemoteLocation);
}
void sendValueSp(float s) //eeg move speed
{
OscMessage oscMess5 = new OscMessage("/sensorSp");
oscMess5.add(s);
oscP5.send(oscMess5, myRemoteLocation);
}
void sendValueWL(float w)//water level
{
OscMessage oscMess6 = new OscMessage("/sensorWL");
oscMess6.add(w);
oscP5.send(oscMess6, myRemoteLocation);
}
void sendValueBlink(float b)//blink
{
OscMessage oscMess7 = new OscMessage("/sensorBlink");
oscMess7.add(b);
oscP5.send(oscMess7, myRemoteLocation);
}
void sendValueMe(float me)//blink
{
OscMessage oscMess8 = new OscMessage("/sensorMe");
oscMess8.add(me);
oscP5.send(oscMess8, myRemoteLocation);
}
void sendValueSp2(float s2) //eeg move speed
{
OscMessage oscMess9 = new OscMessage("/sensorSp2");
oscMess9.add(s2);
oscP5.send(oscMess9, myRemoteLocation);
}
#pragma strict
var i :int =0;
var angle :float =0;
var speed : float = 0.05;
var dis: float;
function Start () {
}
function Update () {
var cam = GameObject.Find("Main Camera");
var con = GameObject.Find("Controller");
var cube = GameObject.Find("CubeMoveTest");
dis = Vector3.Distance(cam.transform.position,transform.position);
if (dis<180)
{
Application.LoadLevel("22");
}
}
#pragma strict
var xChannel : float;
var yChannel : float;
var RYChannel : float;
var RXChannel : float;
function Update () {
var x = OscReceiver.messages[xChannel];
var y = OscReceiver.messages[yChannel];
var m = OscReceiver.messages[RYChannel];
var n = OscReceiver.messages[RXChannel];
transform.position = Vector3(x,y,0);
transform.eulerAngles = new Vector3(n,m,0);
}
#pragma strict
var dis: float;
var BlinkChannel : float;
var i :int =0;
var num:int = 0;
var num2:int =0;
var pass: boolean = true;
function start()
{
}
function Update () {
if (pass == true);//why here is a ";" and works well?
{ var aa = GameObject.Find("test");
var bb = GameObject.Find("Main Camera");
var cc = GameObject.Find("Block"+num);
dis = Vector3.Distance(cc.transform.position,bb.transform.position);
if (dis<150 && dis >=0)
{
var b = OscReceiver.messages[BlinkChannel];
Debug.Log("b:"+b);
aa.transform.position = Vector3(aa.transform.position.x,b,aa.transform.position.z);
if (aa.transform.position.y>10000)
{
for(i =0;i<1;i+=1)
{cc.transform.localPosition.y += 20000;
}
}
}
if(dis > 10000)
{
pass = false;
if (num<2)
{
num ++;
num2 =num-1;
}
else
{
num=0;
num2 =2;
}
}
pass = true;
}
}
#pragma strict
var SpChannel : float;
var Sp2Channel : float;
var num: int;
var num2: int;
var pass: boolean = true;
var angle :float;
var speed : float = 0.05;
var turnround1 : boolean = false;
var turnround2 : boolean = false;
var turnback :boolean = false;
var s2: float;
function Start()
{
num = 0;
num2 = 2;
}
function Update () {
if( pass == true)
{
var s = OscReceiver.messages[SpChannel];
var s2 = OscReceiver.messages[Sp2Channel];
var aa = GameObject.Find("Main Camera");
var bb = GameObject.Find("Block"+num);
var cc = GameObject.Find("Block"+num2);
var ww = GameObject.Find("CubeMoveTest");
var ball = GameObject.Find("turntest");
var tt0 = GameObject.Find("turn0");
var tt1 = GameObject.Find("turn1");
var dis2: float = Vector3.Distance(aa.transform.position,bb.transform.position);
var dist0: float = Vector3.Distance(aa.transform.position,tt0.transform.position);
var dist1: float = Vector3.Distance(aa.transform.position,tt1.transform.position);
angle = ww.transform.eulerAngles.y;
}
if(dis2 > 10000)
{
pass = false;
if (num<2)
{
num ++;
num2 =num-1;
}
else
{
num=0;
num2 =2;
}
cc.transform.localPosition.y =0;
}
pass = true;
Debug.Log("num:"+num);
Debug.Log("num2:"+num2);
}
//////////////This is not written by me.....Thanks the author of this code/////////////////
using System.Collections;
using System.IO;
using System;
/// \mainpage
/// \section Overview
/// The .NET Visual C# library for the Make Controller Kit is designed
/// to make it as simple as possible for developers to integrate the
/// Make Controller Kit into their desktop applications, offering the
/// transparency that makes open source software so rewarding to work with.
/// You can communicate with the Make Controller Kit from your applications
/// over either an Ethernet or USB connection, or both. This library is
/// supplied both in source form and built, as MakeControllerOsc.dll
/// This document is a reference for MakeControllerOsc.
///
/// \section Communication
/// Messages to and from the board conform to the OSC (Open Sound Control) protocol.
/// OSC is an open, transport-independent standard supported by an increasing
/// number of environments and devices.
///
/// \subsection OSCmessages OSC Messages
/// OSC messages are represented by the class OscMessage, and consist of two elements:
/// - An address string for the device on the board youíre dealing with.
/// - A list of value(s) being sent to or from that device. The list of values is optional.
///
/// From the perspective of OSC addresses, the Make Controller Kit is organized into a hierarchy of two or three layers:
/// - subsystems ñ classes of device, such as analog inputs, servo controllers, and digital outputs.
/// - devices ñ the index of a specific device within a subsystem.
/// If there is only one device in a subsystem, the device is not included in the OSC address.
/// - properties ñ different devices have different properties, such as the value of an analog input,
/// the position of a servo motor, or the state of an LED.
///
/// OSC messages always begin with a slash, and use a slash to delimit each element in the address,
/// so an example OSC address string would look like:
/// \code /subsystem/device/property \endcode
///
/// The second part of an OscMessage is a list of values to be sent to the specified address.
/// The OSC types that are used by the Make Controller Kit for these values are integers,
/// floats, and strings. The values in this list are simply separated by spaces, and the
/// list can be arbitrarily long. Most devices on the Make Controller Kit expect only one value.
/// For example, to set the position of servo 1, you might send a message which
/// in string form might look like:
/// \code /servo/1/position 512 \endcode
///
/// This addressing scheme allows interactions with the board's various subsystems
/// and properties, and most importantly, accommodates the possibility of future or
/// custom devices on the board that have not yet been implemented or imagined.
/// If somebody creates, for example, a GPS extension to the board, communicating
/// with that device from this library is the same as for any other. More details
/// about OSC can be found at http://www.opensoundcontrol.org.
///
/// \section sendingdata Sending Data
/// As previously mentioned, the Make Controller Kit can communicate over both
/// Ethernet and USB. Messages are sent as packets, both over USB and UDP, and
/// corresponding structures are used ñ UsbPacket and UdpPacket. Once youíve created
/// a packet, you can simply call its Send() method, with the OscMessage youíd like to send.
/// There are helper methods to create an OscMessage from a string, or you can pass in the OscMessage itself.
///
/// For example, you might set up your UsbSend() routine to look something like:
/// \code public void usbSend(string text)
/// {
/// OscMessage oscM = Osc.StringToOscMessage(text);
/// oscUsb is an Osc object, connected to a UsbPacket object
/// oscUsb.Send(oscM);
/// } \endcode
/// If your data is already in the form of an OscMessage, you can call oscUsb.Send() directly.
///
/// \section readingdata Reading Data
/// The Make Controller Kit must be polled in order to read data from it. To do this,
/// send an OscMessage with the address of the device youíd like to read, but omit
/// the list of values. When the board receives an OscMessage with no value,
/// it interprets that as a read request, and sends back an OscMessage with the
/// current value at the appropriate address.
///
/// The .NET Make Controller Kit library conveniently provides handlers that will
/// call back a given function when an OscMessage with a given address string is received.
/// Your implementation could look something like:
/// \code// Set the handler in the constructor for a particular address
/// MyConstructor()
/// {
/// udpPacket = new UdpPacket();
/// oscUdp = new Osc(udpPacket);
/// // A thread is started when the Osc object is created to read
/// // incoming messages.
/// oscUdp.SetAddressHandler("/analogin/0/value", Ain0Message);
/// }
///
/// // The method you specified as the handler will be called back when a
/// // message with a matching address string comes back from the board.
/// public void AIn0Message(OscMessage oscMessage)
/// {
/// // write the message to a console, for example
/// mct.WriteLine("AIn0 > " + Osc.OscMessageToString(oscMessage));
/// } \endcode
/// You could alternatively set a handler for all incoming messages by calling
/// the SetAllMessageHandler() method in your setup, instead of SetAddressHandler().
///
///
//namespace MakingThings
//{
/// <summary>
/// The OscMessage class is a data structure that represents
/// an OSC address and an arbitrary number of values to be sent to that address.
/// </summary>
public class OscMessage
{
/// <summary>
/// The OSC address of the message as a string.
/// </summary>
public string Address;
/// <summary>
/// The list of values to be delivered to the Address.
/// </summary>
public ArrayList Values;
public OscMessage()
{
Values = new ArrayList();
}
}
public delegate void OscMessageHandler( OscMessage oscM );
/// <summary>
/// The Osc class provides the methods required to send, receive, and manipulate OSC messages.
/// Several of the helper methods are static since a running Osc instance is not required for
/// their use.
///
/// When instanciated, the Osc class opens the PacketIO instance that's handed to it and
/// begins to run a reader thread. The instance is then ready to service Send OscMessage requests
/// and to start supplying OscMessages as received back.
///
/// The Osc class can be called to Send either individual messages or collections of messages
/// in an Osc Bundle. Receiving is done by delegate. There are two ways: either submit a method
/// to receive all incoming messages or submit a method to handle only one particular address.
///
/// Messages can be encoded and decoded from Strings via the static methods on this class, or
/// can be hand assembled / disassembled since they're just a string (the address) and a list
/// of other parameters in Object form.
///
/// </summary>
public class Osc : MonoBehaviour
{
private UDPPacketIO OscPacketIO;
Thread ReadThread;
private bool ReaderRunning;
private OscMessageHandler AllMessageHandler;
Hashtable AddressTable;
void Start() {
//do nothing, init must be called
}
public void init(UDPPacketIO oscPacketIO){
OscPacketIO = oscPacketIO;
// Create the hashtable for the address lookup mechanism
AddressTable = new Hashtable();
ReadThread = new Thread(Read);
ReaderRunning = true;
ReadThread.IsBackground = true;
ReadThread.Start();
}
/// <summary>
/// Make sure the PacketExchange is closed.
/// </summary>
~Osc()
{
if (ReaderRunning) Cancel();
//Debug.LogError("~Osc");
}
public void Cancel()
{
//Debug.Log("Osc Cancel start");
if (ReaderRunning)
{
ReaderRunning = false;
ReadThread.Abort();
}
if (OscPacketIO != null && OscPacketIO.IsOpen())
{
OscPacketIO.Close();
OscPacketIO = null;
}
//Debug.Log("Osc Cancel finished");
}
/// <summary>
/// Read Thread. Loops waiting for packets. When a packet is received, it is
/// dispatched to any waiting All Message Handler. Also, the address is looked up and
/// any matching handler is called.
/// </summary>
private void Read()
{
try
{
while (ReaderRunning)
{
byte[] buffer = new byte[1000];
int length = OscPacketIO.ReceivePacket(buffer);
//Debug.Log("received packed of len=" + length);
if (length > 0)
{
ArrayList messages = Osc.PacketToOscMessages(buffer, length);
foreach (OscMessage om in messages)
{
if (AllMessageHandler != null)
AllMessageHandler(om);
OscMessageHandler h = (OscMessageHandler)Hashtable.Synchronized(AddressTable)[om.Address];
if (h != null)
h(om);
}
}
else
Thread.Sleep(20);
}
}
catch (Exception e)
{
//Debug.Log("ThreadAbortException"+e);
}
finally
{
//Debug.Log("terminating thread - clearing handlers");
//Cancel();
//Hashtable.Synchronized(AddressTable).Clear();
}
}
/// <summary>
/// Send an individual OSC message. Internally takes the OscMessage object and
/// serializes it into a byte[] suitable for sending to the PacketIO.
/// </summary>
/// <param name="oscMessage">The OSC Message to send.</param>
public void Send( OscMessage oscMessage )
{
byte[] packet = new byte[1000];
int length = Osc.OscMessageToPacket( oscMessage, packet, 1000 );
OscPacketIO.SendPacket( packet, length);
}
/// <summary>
/// Sends a list of OSC Messages. Internally takes the OscMessage objects and
/// serializes them into a byte[] suitable for sending to the PacketExchange.
/// </summary>
/// <param name="oms">The OSC Message to send.</param>
public void Send(ArrayList oms)
{
byte[] packet = new byte[1000];
int length = Osc.OscMessagesToPacket(oms, packet, 1000);
OscPacketIO.SendPacket(packet, length);
}
/// <summary>
/// Set the method to call back on when any message is received.
/// The method needs to have the OscMessageHandler signature - i.e. void amh( OscMessage oscM )
/// </summary>
/// <param name="amh">The method to call back on.</param>
public void SetAllMessageHandler(OscMessageHandler amh)
{
AllMessageHandler = amh;
}
/// <summary>
/// Set the method to call back on when a message with the specified
/// address is received. The method needs to have the OscMessageHandler signature - i.e.
/// void amh( OscMessage oscM )
/// </summary>
/// <param name="key">Address string to be matched</param>
/// <param name="ah">The method to call back on.</param>
public void SetAddressHandler(string key, OscMessageHandler ah)
{
Hashtable.Synchronized(AddressTable).Add(key, ah);
}
/// <summary>
/// General static helper that returns a string suitable for printing representing the supplied
/// OscMessage.
/// </summary>
/// <param name="message">The OscMessage to be stringified.</param>
/// <returns>The OscMessage as a string.</returns>
public static string OscMessageToString(OscMessage message)
{
StringBuilder s = new StringBuilder();
s.Append(message.Address);
foreach( object o in message.Values )
{
s.Append(" ");
s.Append(o.ToString());
}
return s.ToString();
}
/// <summary>
/// Creates an OscMessage from a string - extracts the address and determines each of the values.
/// </summary>
/// <param name="message">The string to be turned into an OscMessage</param>
/// <returns>The OscMessage.</returns>
public static OscMessage StringToOscMessage(string message)
{
OscMessage oM = new OscMessage();
Console.WriteLine("Splitting " + message);
string[] ss = message.Split(new char[] { ' ' });
IEnumerator sE = ss.GetEnumerator();
if (sE.MoveNext())
oM.Address = (string)sE.Current;
while ( sE.MoveNext() )
{
string s = (string)sE.Current;
// Console.WriteLine(" <" + s + ">");
if (s.StartsWith("\""))
{
StringBuilder quoted = new StringBuilder();
bool looped = false;
if (s.Length > 1)
quoted.Append(s.Substring(1));
else
looped = true;
while (sE.MoveNext())
{
string a = (string)sE.Current;
// Console.WriteLine(" q:<" + a + ">");
if (looped)
quoted.Append(" ");
if (a.EndsWith("\""))
{
quoted.Append(a.Substring(0, a.Length - 1));
break;
}
else
{
if (a.Length == 0)
quoted.Append(" ");
else
quoted.Append(a);
}
looped = true;
}
oM.Values.Add(quoted.ToString());
}
else
{
if (s.Length > 0)
{
try
{
int i = int.Parse(s);
// Console.WriteLine(" i:" + i);
oM.Values.Add(i);
}
catch
{
try
{
float f = float.Parse(s);
// Console.WriteLine(" f:" + f);
oM.Values.Add(f);
}
catch
{
// Console.WriteLine(" s:" + s);
oM.Values.Add(s);
}
}
}
}
}
return oM;
}
/// <summary>
/// Takes a packet (byte[]) and turns it into a list of OscMessages.
/// </summary>
/// <param name="packet">The packet to be parsed.</param>
/// <param name="length">The length of the packet.</param>
/// <returns>An ArrayList of OscMessages.</returns>
public static ArrayList PacketToOscMessages(byte[] packet, int length)
{
ArrayList messages = new ArrayList();
ExtractMessages(messages, packet, 0, length);
return messages;
}
/// <summary>
/// Puts an array of OscMessages into a packet (byte[]).
/// </summary>
/// <param name="messages">An ArrayList of OscMessages.</param>
/// <param name="packet">An array of bytes to be populated with the OscMessages.</param>
/// <param name="length">The size of the array of bytes.</param>
/// <returns>The length of the packet</returns>
public static int OscMessagesToPacket(ArrayList messages, byte[] packet, int length)
{
int index = 0;
if (messages.Count == 1)
index = OscMessageToPacket((OscMessage)messages[0], packet, 0, length);
else
{
// Write the first bundle bit
index = InsertString("#bundle", packet, index, length);
// Write a null timestamp (another 8bytes)
int c = 8;
while (( c-- )>0)
packet[index++]++;
// Now, put each message preceded by it's length
foreach (OscMessage oscM in messages)
{
int lengthIndex = index;
index += 4;
int packetStart = index;
index = OscMessageToPacket(oscM, packet, index, length);
int packetSize = index - packetStart;
packet[lengthIndex++] = (byte)((packetSize >> 24) & 0xFF);
packet[lengthIndex++] = (byte)((packetSize >> 16) & 0xFF);
packet[lengthIndex++] = (byte)((packetSize >> 8) & 0xFF);
packet[lengthIndex++] = (byte)((packetSize) & 0xFF);
}
}
return index;
}
/// <summary>
/// Creates a packet (an array of bytes) from a single OscMessage.
/// </summary>
/// <remarks>A convenience method, not requiring a start index.</remarks>
/// <param name="oscM">The OscMessage to be returned as a packet.</param>
/// <param name="packet">The packet to be populated with the OscMessage.</param>
/// <param name="length">The usable size of the array of bytes.</param>
/// <returns>The length of the packet</returns>
public static int OscMessageToPacket(OscMessage oscM, byte[] packet, int length)
{
return OscMessageToPacket(oscM, packet, 0, length);
}
/// <summary>
/// Creates an array of bytes from a single OscMessage. Used internally.
/// </summary>
/// <remarks>Can specify where in the array of bytes the OscMessage should be put.</remarks>
/// <param name="oscM">The OscMessage to be turned into an array of bytes.</param>
/// <param name="packet">The array of bytes to be populated with the OscMessage.</param>
/// <param name="start">The start index in the packet where the OscMessage should be put.</param>
/// <param name="length">The length of the array of bytes.</param>
/// <returns>The index into the packet after the last OscMessage.</returns>
private static int OscMessageToPacket(OscMessage oscM, byte[] packet, int start, int length)
{
int index = start;
index = InsertString(oscM.Address, packet, index, length);
//if (oscM.Values.Count > 0)
{
StringBuilder tag = new StringBuilder();
tag.Append(",");
int tagIndex = index;
index += PadSize(2 + oscM.Values.Count);
foreach (object o in oscM.Values)
{
if (o is int)
{
int i = (int)o;
tag.Append("i");
packet[index++] = (byte)((i >> 24) & 0xFF);
packet[index++] = (byte)((i >> 16) & 0xFF);
packet[index++] = (byte)((i >> 8) & 0xFF);
packet[index++] = (byte)((i) & 0xFF);
}
else
{
if (o is float)
{
float f = (float)o;
tag.Append("f");
byte[] buffer = new byte[4];
MemoryStream ms = new MemoryStream(buffer);
BinaryWriter bw = new BinaryWriter(ms);
bw.Write(f);
packet[index++] = buffer[3];
packet[index++] = buffer[2];
packet[index++] = buffer[1];
packet[index++] = buffer[0];
}
else
{
if (o is string)
{
tag.Append("s");
index = InsertString(o.ToString(), packet, index, length);
}
else
{
tag.Append("?");
}
}
}
}
InsertString(tag.ToString(), packet, tagIndex, length);
}
return index;
}
/// <summary>
/// Receive a raw packet of bytes and extract OscMessages from it. Used internally.
/// </summary>
/// <remarks>The packet may contain a OSC message or a bundle of messages.</remarks>
/// <param name="messages">An ArrayList to be populated with the OscMessages.</param>
/// <param name="packet">The packet of bytes to be parsed.</param>
/// <param name="start">The index of where to start looking in the packet.</param>
/// <param name="length">The length of the packet.</param>
/// <returns>The index after the last OscMessage read.</returns>
private static int ExtractMessages(ArrayList messages, byte[] packet, int start, int length)
{
int index = start;
switch ( (char)packet[ start ] )
{
case '/':
index = ExtractMessage( messages, packet, index, length );
break;
case '#':
string bundleString = ExtractString(packet, start, length);
if ( bundleString == "#bundle" )
{
// skip the "bundle" and the timestamp
index+=16;
while ( index < length )
{
int messageSize = ( packet[index++] << 24 ) + ( packet[index++] << 16 ) + ( packet[index++] << 8 ) + packet[index++];
/*int newIndex = */ExtractMessages( messages, packet, index, length );
index += messageSize;
}
}
break;
}
return index;
}
/// <summary>
/// Extracts a messages from a packet.
/// </summary>
/// <param name="messages">An ArrayList to be populated with the OscMessage.</param>
/// <param name="packet">The packet of bytes to be parsed.</param>
/// <param name="start">The index of where to start looking in the packet.</param>
/// <param name="length">The length of the packet.</param>
/// <returns>The index after the OscMessage is read.</returns>
private static int ExtractMessage(ArrayList messages, byte[] packet, int start, int length)
{
OscMessage oscM = new OscMessage();
oscM.Address = ExtractString(packet, start, length);
int index = start + PadSize(oscM.Address.Length+1);
string typeTag = ExtractString(packet, index, length);
index += PadSize(typeTag.Length + 1);
//oscM.Values.Add(typeTag);
foreach (char c in typeTag)
{
switch (c)
{
case ',':
break;
case 's':
{
string s = ExtractString(packet, index, length);
index += PadSize(s.Length + 1);
oscM.Values.Add(s);
break;
}
case 'i':
{
int i = ( packet[index++] << 24 ) + ( packet[index++] << 16 ) + ( packet[index++] << 8 ) + packet[index++];
oscM.Values.Add(i);
break;
}
case 'f':
{
byte[] buffer = new byte[4];
buffer[3] = packet[index++];
buffer[2] = packet[index++];
buffer[1] = packet[index++];
buffer[0] = packet[index++];
MemoryStream ms = new MemoryStream(buffer);
BinaryReader br = new BinaryReader(ms);
float f = br.ReadSingle();
oscM.Values.Add(f);
break;
}
}
}
messages.Add( oscM );
return index;
}
/// <summary>
/// Removes a string from a packet. Used internally.
/// </summary>
/// <param name="packet">The packet of bytes to be parsed.</param>
/// <param name="start">The index of where to start looking in the packet.</param>
/// <param name="length">The length of the packet.</param>
/// <returns>The string</returns>
private static string ExtractString(byte[] packet, int start, int length)
{
StringBuilder sb = new StringBuilder();
int index = start;
while (packet[index] != 0 && index < length)
sb.Append((char)packet[index++]);
return sb.ToString();
}
private static string Dump(byte[] packet, int start, int length)
{
StringBuilder sb = new StringBuilder();
int index = start;
while (index < length)
sb.Append(packet[index++]+"|");
return sb.ToString();
}
/// <summary>
/// Inserts a string, correctly padded into a packet. Used internally.
/// </summary>
/// <param name="string">The string to be inserted</param>
/// <param name="packet">The packet of bytes to be parsed.</param>
/// <param name="start">The index of where to start looking in the packet.</param>
/// <param name="length">The length of the packet.</param>
/// <returns>An index to the next byte in the packet after the padded string.</returns>
private static int InsertString(string s, byte[] packet, int start, int length)
{
int index = start;
foreach (char c in s)
{
packet[index++] = (byte)c;
if (index == length)
return index;
}
packet[index++] = 0;
int pad = (s.Length+1) % 4;
if (pad != 0)
{
pad = 4 - pad;
while (pad-- > 0)
packet[index++] = 0;
}
return index;
}
/// <summary>
/// Takes a length and returns what it would be if padded to the nearest 4 bytes.
/// </summary>
/// <param name="rawSize">Original size</param>
/// <returns>padded size</returns>
private static int PadSize(int rawSize)
{
int pad = rawSize % 4;
if (pad == 0)
return rawSize;
else
return rawSize + (4 - pad);
}
}
//}
// Make sure you have UDPPacketIO.cs and Osc.cs in the standard assets folder
var RemoteIP : String = "127.0.0.1";
var SendToPort : int = 57131;
var ListenerPort : int = 57130;
var controller : Transform;
var handler : Osc;
// Messages are accessible from this instance in other scripts
static var messages : Array = [0];
public function Start ()
{
// Set up OSC connection
var udp : UDPPacketIO = GetComponent("UDPPacketIO");
udp.init(RemoteIP, SendToPort, ListenerPort);
handler = GetComponent("Osc");
handler.init(udp);
// Listen to the channels set in the Processing sketch
handler.SetAddressHandler("/sensorX", ListenEvent);//-----camera positionX
handler.SetAddressHandler("/sensorY", ListenEvent);//-----camera positionY
handler.SetAddressHandler("/sensorRY", ListenEvent);//-----camera rotateY
handler.SetAddressHandler("/sensorRX", ListenEvent);//-----camera rotateX
handler.SetAddressHandler("/sensorSp", ListenEvent);//-----movespeed
handler.SetAddressHandler("/sensorWL", ListenEvent);//-----waterlevel
handler.SetAddressHandler("/sensorBlink", ListenEvent);//-----blink
handler.SetAddressHandler("/sensorMe", ListenEvent);//-----float
handler.SetAddressHandler("/sensorSp2", ListenEvent);//-----movespeed
}
public function ListenEvent(oscMessage : OscMessage) : void
{
switch(oscMessage.Address){
case "/sensorX": i = 0; break;
case "/sensorY": i = 1; break;
case "/sensorRY": i = 2; break;
case "/sensorRX": i = 3; break;
case "/sensorSp": i = 4; break;
case "/sensorWL": i = 5; break;
case "/sensorBlink":i = 6; break;
case "/sensorMe": i = 7; break;
case "/sensorSp2": i = 8; break;
}
// Make the data available
messages[i] = oscMessage.Values[0];
}
#pragma strict
var WLChannel : float;
function Update () {
var w = OscReceiver.messages[WLChannel];
transform.position = Vector3(transform.position.x,w,transform.position.z);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment