Created
August 15, 2022 02:57
-
-
Save Ooseykins/542926c5386f1971b73d937a55280b3b to your computer and use it in GitHub Desktop.
Simpler Unity receiver for IFacialMocap. Statically access IFacialMocapReciever.currentFrame to get the most recent weights and transforms.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Net; | |
using System.Net.Sockets; | |
using System.Text; | |
using System.Threading; | |
using UnityEngine; | |
public class IFacialMocapReciever : MonoBehaviour | |
{ | |
const string KEY_IFACIALMOCAP = "iFacialMocap_sahuasouryya9218sauhuiayeta91555dy3719"; | |
const string KEY_FACEMOTION3D = "FACEMOTION3D_OtherStreaming"; | |
const string KEY_DISCONNECT = "StopStreaming_FACEMOTION3D"; | |
const string KEY_LOOKFORWARD = "iFacialMocap_lookForward"; | |
static MocapFrame _currentFrame = new(); | |
public static MocapFrame currentFrame => _currentFrame; | |
public class MocapFrame | |
{ | |
public Dictionary<string, float> shapeWeights = new(); | |
public Dictionary<string, Vector3> transformAngles = new(); | |
public Dictionary<string, Vector3> transformPositions = new(); | |
public override string ToString() | |
{ | |
StringBuilder b = new StringBuilder(); | |
foreach(var k in shapeWeights.Keys) | |
{ | |
b.Append($"{k}, {shapeWeights[k]}\n"); | |
} | |
foreach (var k in transformAngles.Keys) | |
{ | |
b.Append($"Transform {k}, Position {transformPositions[k]}, Angles {transformAngles[k]}\n"); | |
} | |
return b.ToString(); | |
} | |
} | |
Queue<MocapFrame> mocapFrames = new(); | |
bool terminateThread; | |
Thread thread; | |
UdpClient udpClient; | |
public string address; | |
public int port = 49993; | |
public int localPort = 49983; | |
private void Update() | |
{ | |
if ( thread == null && !terminateThread) | |
{ | |
Debug.Log("Starting IFacialMocapRecieverThread"); | |
terminateThread = false; | |
SendMessage(KEY_FACEMOTION3D, port, 6); | |
SendMessage(KEY_IFACIALMOCAP, port, 6); | |
udpClient = new UdpClient(localPort); | |
udpClient.Client.ReceiveTimeout = 10000; | |
thread = new Thread(new ThreadStart(ThreadMethod)); | |
thread.Start(); | |
} | |
if(mocapFrames.Count > 0) | |
{ | |
_currentFrame = mocapFrames.Dequeue(); | |
} | |
} | |
private void OnEnable() | |
{ | |
terminateThread = false; | |
} | |
private void OnDisable() | |
{ | |
terminateThread = true; | |
udpClient.Dispose(); | |
} | |
void ThreadMethod() | |
{ | |
SendMessage(KEY_IFACIALMOCAP, port, 6); | |
SendMessage(KEY_FACEMOTION3D, port, 6); | |
while (true) | |
{ | |
try | |
{ | |
IPEndPoint RemoteIpEndPoint = null; | |
byte[] data = udpClient.Receive(ref RemoteIpEndPoint); | |
MocapFrame frame = new MocapFrame(); | |
string dataString = Encoding.ASCII.GetString(data); | |
char delimiter = dataString.Contains('&') ? '&' : '-'; | |
foreach (string kv1 in dataString.Split('|')) | |
{ | |
if (kv1.Contains("#")) | |
{ | |
string[] kv2 = kv1.Split('#'); | |
if (kv2.Length == 2) | |
{ | |
string[] pa = kv2[1].Split(','); | |
if (pa.Length == 6) | |
{ | |
Vector3 a = new Vector3(ParseFloat(pa[0]), ParseFloat(pa[1]), ParseFloat(pa[2])); | |
Vector3 p = new Vector3(ParseFloat(pa[3]), ParseFloat(pa[4]), ParseFloat(pa[5])); | |
frame.transformAngles[kv2[0]] = a; | |
frame.transformPositions[kv2[0]] = p; | |
} | |
else if(pa.Length == 3) | |
{ | |
Vector3 a = new Vector3(ParseFloat(pa[0]), ParseFloat(pa[1]), ParseFloat(pa[2])); | |
frame.transformAngles[kv2[0]] = a; | |
frame.transformPositions[kv2[0]] = Vector3.zero; | |
} | |
} | |
} | |
else | |
{ | |
string[] kv2 = kv1.Split(delimiter); | |
if (kv2.Length == 2) | |
{ | |
frame.shapeWeights[kv2[0]] = ParseFloat(kv2[1]); | |
} | |
} | |
} | |
lock (mocapFrames) | |
{ | |
mocapFrames.Enqueue(frame); | |
} | |
} | |
catch (SocketException e) { | |
if( e.SocketErrorCode == SocketError.TimedOut) | |
{ | |
Debug.Log("IFacialMocapReceiver disconnected due to timeout"); | |
} | |
else if (e.SocketErrorCode == SocketError.Interrupted) | |
{ | |
Debug.Log("IFacialMocapReceiver socket was forcibly closed"); | |
} | |
else | |
{ | |
Debug.LogError($"IFacialMocapReceiver some socket error has occured: {e.SocketErrorCode}"); | |
Debug.LogError(e); | |
} | |
break; | |
} | |
catch(Exception e) | |
{ | |
Debug.LogError($"IFacialMocapReceiver some other error occured:"); | |
Debug.LogError(e); | |
break; | |
} | |
if (terminateThread) | |
{ | |
Debug.Log("IFacialMocapReciever thread terminating"); | |
break; | |
} | |
} | |
SendMessage(KEY_DISCONNECT, port, 6); | |
udpClient.Dispose(); | |
Debug.Log("IFacialMocapReciever is shut down"); | |
static float ParseFloat(string k) | |
{ | |
if (float.TryParse(k, out var f)) | |
{ | |
return f; | |
} | |
return 0f; | |
} | |
} | |
void SendMessage(string sendMessage, int send_port, int repeats = 1) | |
{ | |
try | |
{ | |
UdpClient c = new UdpClient(); | |
c.Connect(address, send_port); | |
byte[] dgram = Encoding.UTF8.GetBytes(sendMessage); | |
for (int i = 0; i < repeats; i++) | |
{ | |
c.Send(dgram, dgram.Length); | |
} | |
} | |
catch (Exception e) | |
{ | |
Debug.LogError(e); | |
} | |
} | |
public void LookForward() | |
{ | |
SendMessage(KEY_LOOKFORWARD, port, 1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment