using System.Collections; using System.IO; using System.IO.Pipes; using System.Linq; using System.Text; using System.Threading; using UnityEngine; /* Currently very messy because both the server code and hand-drawn code is all in the same file here. * But it is still fairly straightforward to use as a reference/base. */ public class PipeServer : MonoBehaviour { public Transform rParent; public Transform lParent; public GameObject landmarkPrefab; public GameObject linePrefab; public GameObject headPrefab; public bool enableHead = true; public float multiplier = 10f; public float landmarkScale = 1f; public float maxSpeed = 50f; public float debug_samplespersecond; NamedPipeServerStream server; const int LANDMARK_COUNT = 33; const int LINES_COUNT = 11; public struct AccumulatedBuffer { public Vector3 value; public int accumulatedValuesCount; public AccumulatedBuffer(Vector3 v,int ac) { value = v; accumulatedValuesCount = ac; } } public class Body { public Transform parent; public AccumulatedBuffer[] positionsBuffer = new AccumulatedBuffer[LANDMARK_COUNT]; public Vector3[] localPositionTargets = new Vector3[LANDMARK_COUNT]; public GameObject[] instances = new GameObject[LANDMARK_COUNT]; public LineRenderer[] lines = new LineRenderer[LINES_COUNT]; public bool active; public Body(Transform parent, GameObject landmarkPrefab, GameObject linePrefab,float s, GameObject headPrefab) { this.parent = parent; for (int i = 0; i < instances.Length; ++i) { instances[i] = Instantiate(landmarkPrefab);// GameObject.CreatePrimitive(PrimitiveType.Sphere); instances[i].transform.localScale = Vector3.one * s; instances[i].transform.parent = parent; instances[i].name = ((Landmark)i).ToString(); } for (int i = 0; i < lines.Length; ++i) { lines[i] = Instantiate(linePrefab).GetComponent(); } if (headPrefab) { GameObject head = Instantiate(headPrefab); head.transform.parent = instances[(int)Landmark.NOSE].transform; head.transform.localPosition = headPrefab.transform.position; head.transform.localRotation = headPrefab.transform.localRotation; head.transform.localScale = headPrefab.transform.localScale; } } public void UpdateLines() { lines[0].positionCount = 4; lines[0].SetPosition(0, Position((Landmark)32)); lines[0].SetPosition(1, Position((Landmark)30)); lines[0].SetPosition(2, Position((Landmark)28)); lines[0].SetPosition(3, Position((Landmark)32)); lines[1].positionCount = 4; lines[1].SetPosition(0, Position((Landmark)31)); lines[1].SetPosition(1, Position((Landmark)29)); lines[1].SetPosition(2, Position((Landmark)27)); lines[1].SetPosition(3, Position((Landmark)31)); lines[2].positionCount = 3; lines[2].SetPosition(0, Position((Landmark)28)); lines[2].SetPosition(1, Position((Landmark)26)); lines[2].SetPosition(2, Position((Landmark)24)); lines[3].positionCount = 3; lines[3].SetPosition(0, Position((Landmark)27)); lines[3].SetPosition(1, Position((Landmark)25)); lines[3].SetPosition(2, Position((Landmark)23)); lines[4].positionCount = 5; lines[4].SetPosition(0, Position((Landmark)24)); lines[4].SetPosition(1, Position((Landmark)23)); lines[4].SetPosition(2, Position((Landmark)11)); lines[4].SetPosition(3, Position((Landmark)12)); lines[4].SetPosition(4, Position((Landmark)24)); lines[5].positionCount = 4; lines[5].SetPosition(0, Position((Landmark)12)); lines[5].SetPosition(1, Position((Landmark)14)); lines[5].SetPosition(2, Position((Landmark)16)); lines[5].SetPosition(3, Position((Landmark)22)); lines[6].positionCount = 4; lines[6].SetPosition(0, Position((Landmark)11)); lines[6].SetPosition(1, Position((Landmark)13)); lines[6].SetPosition(2, Position((Landmark)15)); lines[6].SetPosition(3, Position((Landmark)21)); lines[7].positionCount = 4; lines[7].SetPosition(0, Position((Landmark)16)); lines[7].SetPosition(1, Position((Landmark)18)); lines[7].SetPosition(2, Position((Landmark)20)); lines[7].SetPosition(3, Position((Landmark)16)); lines[8].positionCount = 4; lines[8].SetPosition(0, Position((Landmark)15)); lines[8].SetPosition(1, Position((Landmark)17)); lines[8].SetPosition(2, Position((Landmark)19)); lines[8].SetPosition(3, Position((Landmark)15)); lines[9].positionCount = 2; lines[9].SetPosition(0, Position((Landmark)10)); lines[9].SetPosition(1, Position((Landmark)9)); lines[10].positionCount = 5; lines[10].SetPosition(0, Position((Landmark)8)); lines[10].SetPosition(1, Position((Landmark)5)); lines[10].SetPosition(2, Position((Landmark)0)); lines[10].SetPosition(3, Position((Landmark)2)); lines[10].SetPosition(4, Position((Landmark)7)); } public float GetAngle(Landmark referenceFrom, Landmark referenceTo, Landmark from, Landmark to) { Vector3 reference = (instances[(int)referenceTo].transform.position - instances[(int)referenceFrom].transform.position).normalized; Vector3 direction = (instances[(int)to].transform.position - instances[(int)from].transform.position).normalized; return Vector3.SignedAngle(reference, direction, Vector3.Cross(reference, direction)); } public float Distance(Landmark from,Landmark to) { return (instances[(int)from].transform.position - instances[(int)to].transform.position).magnitude; } public Vector3 LocalPosition(Landmark Mark) { return instances[(int)Mark].transform.localPosition; } public Vector3 Position(Landmark Mark) { return instances[(int)Mark].transform.position; } } private Body body; public int samplesForPose = 1; public bool active; private void Start() { System.Globalization.CultureInfo.DefaultThreadCurrentCulture = System.Globalization.CultureInfo.InvariantCulture; body = new Body(lParent,landmarkPrefab,linePrefab,landmarkScale,enableHead?headPrefab:null); Thread t = new Thread(new ThreadStart(Run)); t.Start(); } private void Update() { UpdateBody(body); } private void UpdateBody(Body b) { for (int i = 0; i < LANDMARK_COUNT; ++i) { if (b.positionsBuffer[i].accumulatedValuesCount < samplesForPose) continue; // b.instances[i].transform.localPosition = b.positionsBuffer[i] / (float)b.samplesCounter * multiplier; b.localPositionTargets[i] = b.positionsBuffer[i].value / (float)b.positionsBuffer[i].accumulatedValuesCount * multiplier; b.positionsBuffer[i] = new AccumulatedBuffer(Vector3.zero,0); } for (int i = 0; i < LANDMARK_COUNT; ++i) { b.instances[i].transform.localPosition=Vector3.MoveTowards(b.instances[i].transform.localPosition, b.localPositionTargets[i], Time.deltaTime * maxSpeed); } b.UpdateLines(); } void Run() { System.Globalization.CultureInfo.CurrentCulture = System.Globalization.CultureInfo.InvariantCulture; // Open the named pipe. server = new NamedPipeServerStream("UnityMediaPipeBody",PipeDirection.InOut, 99, PipeTransmissionMode.Message); print("Waiting for connection..."); server.WaitForConnection(); print("Connected."); var br = new BinaryReader(server, Encoding.UTF8); while (true) { try { Body h = body; var len = (int)br.ReadUInt32(); var str = new string(br.ReadChars(len)); string[] lines = str.Split('\n'); foreach (string l in lines) { if (string.IsNullOrWhiteSpace(l)) continue; string[] s = l.Split('|'); if (s.Length < 4) continue; int i; if (!int.TryParse(s[0], out i)) continue; h.positionsBuffer[i].value += new Vector3(float.Parse(s[1]), float.Parse(s[2]), float.Parse(s[3])); h.positionsBuffer[i].accumulatedValuesCount += 1; h.active = true; } } catch (EndOfStreamException) { break; // When client disconnects } } } private void OnDisable() { print("Client disconnected."); server.Close(); server.Dispose(); } }