Files
Ganesh Saraswat 96bc4d9865 project
2023-06-03 20:23:10 -06:00

282 lines
9.9 KiB
C#

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;
public enum Landmark {
NOSE = 0,
LEFT_EYE_INNER = 1,
LEFT_EYE = 2,
LEFT_EYE_OUTER = 3,
RIGHT_EYE_INNER = 4,
RIGHT_EYE = 5,
RIGHT_EYE_OUTER = 6,
LEFT_EAR = 7,
RIGHT_EAR = 8,
MOUTH_LEFT = 9,
MOUTH_RIGHT = 10,
LEFT_SHOULDER = 11,
RIGHT_SHOULDER = 12,
LEFT_ELBOW = 13,
RIGHT_ELBOW = 14,
LEFT_WRIST = 15,
RIGHT_WRIST = 16,
LEFT_PINKY = 17,
RIGHT_PINKY = 18,
LEFT_INDEX = 19,
RIGHT_INDEX = 20,
LEFT_THUMB = 21,
RIGHT_THUMB = 22,
LEFT_HIP = 23,
RIGHT_HIP = 24,
LEFT_KNEE = 25,
RIGHT_KNEE = 26,
LEFT_ANKLE = 27,
RIGHT_ANKLE = 28,
LEFT_HEEL = 29,
RIGHT_HEEL = 30,
LEFT_FOOT_INDEX = 31,
RIGHT_FOOT_INDEX = 32
}
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<LineRenderer>();
}
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()
{
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()
{
// 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);
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();
}
}