//========================================= // connect a given transform to a skeleton //========================================= private void ConnectSkeleton(int actorId, Transform transform) { if (transform == null || !actors.ContainsKey(actorId)) { return; } communicationMutex.WaitOne(); CapturyActor actor = actors[actorId]; CapturySkeleton skel = skeletons[actorId]; skel.reference = transform; for (uint i = 0; i < actor.numJoints; i++) { // check if the joint name matches a reference transform and assign it ArrayList children = skel.reference.transform.GetAllChildren(); foreach (Transform tra in children) { if (tra.name.EndsWith(skel.joints[i].name)) { skel.joints[i].transform = tra; continue; } } } communicationMutex.ReleaseMutex(); }
//=============================================== // helper function to map an actor to a skeleton //=============================================== private void ConvertActor(CapturyActor actor, ref CapturySkeleton skel) { if (skel == null) { Debug.Log("Null skeleton reference"); return; } // copy data over skel.name = System.Text.Encoding.UTF8.GetString(actor.name); skel.id = actor.id; // create joints int szStruct = Marshal.SizeOf(typeof(CapturyJoint)); skel.joints = new CapturySkeletonJoint[actor.numJoints]; for (uint i = 0; i < actor.numJoints; i++) { // marshall the joints into a new joint struct CapturyJoint joint = new CapturyJoint(); joint = (CapturyJoint)Marshal.PtrToStructure(new IntPtr(actor.joints.ToInt64() + (szStruct * i)), typeof(CapturyJoint)); skel.joints[i] = new CapturySkeletonJoint(); skel.joints[i].name = System.Text.Encoding.ASCII.GetString(joint.name); int jpos = skel.joints[i].name.IndexOf("\0"); skel.joints[i].name = skel.joints[i].name.Substring(0, jpos); skel.joints[i].offset.Set(joint.ox, joint.oy, joint.oz); skel.joints[i].orientation.Set(joint.rx, joint.ry, joint.rz); //Debug.Log ("Got joint " + skel.joints[i].name + " at " + joint.ox + joint.oy + joint.oz); } }
//================================================ // This function continously looks for new actors // It runs in a separate thread //================================================ void lookForActors() { Debug.Log("looking for actors"); while (!communicationFinished) { // wait for actorCheckTimeout ms before continuing // Debug.Log ("Going to sleep..."); Thread.Sleep(actorCheckTimeout); // Debug.Log ("Waking up..."); // now look for new data // try to connect to captury live if (!isSetup) { Debug.Log("trying to connect to " + host + ":" + port); if (Captury_connect(host, port) == 1 && Captury_synchronizeTime() != 0) { isSetup = true; Debug.Log("Successfully opened port to Captury Live"); Debug.Log("The time difference is " + Captury_getTimeOffset()); } else { Debug.Log(String.Format("Unable to connect to Captury Live at {0}:{1} ", host, port)); } } if (isSetup) { // grab actors IntPtr actorData = IntPtr.Zero; int numActors = Captury_getActors(out actorData); if (numActors > 0 && actorData != IntPtr.Zero) { Debug.Log(String.Format("Successfully received {0} actors", numActors)); // create actor struct int szStruct = Marshal.SizeOf(typeof(CapturyActor)); for (uint i = 0; i < numActors; i++) { // get an actor CapturyActor actor = new CapturyActor(); actor = (CapturyActor)Marshal.PtrToStructure(new IntPtr(actorData.ToInt64() + (szStruct * i)), typeof(CapturyActor)); Debug.Log(String.Format("actor id {0} {1} ", actor.id, Encoding.UTF8.GetString(actor.name))); IntPtr ptr = new IntPtr(actorData.ToInt64() + (szStruct * i)); /* for (int x = 0; x < 64; ++x) { * Debug.Log(String.Format("byte {0} {1}", x, Marshal.ReadByte(ptr, x))); * }*/ // check if we already have it in our dictionary if (actors.ContainsKey(actor.id)) { actorFound[actor.id] = 5; Debug.Log("Found known actor " + actor.id); continue; } Debug.Log("Found new actor " + actor.id + " with " + actor.numJoints + " joints"); // no? we need to convert it IntPtr actorPointer = new IntPtr(actorData.ToInt64() + (szStruct * i)); CapturySkeleton skeleton = new CapturySkeleton(); ConvertActor(actor, ref skeleton); // and add it to the list of actors we are processing, making sure this is secured by the mutex communicationMutex.WaitOne(); actors.Add(actor.id, actor); actorPointers.Add(actor.id, actorPointer); skeletons.Add(actor.id, skeleton); actorFound.Add(actor.id, 5); communicationMutex.ReleaseMutex(); } if (!isConnected && Captury_startStreaming(1) == 1) { Debug.Log("Successfully started streaming data"); isConnected = true; } } // reduce the actor countdown by one for each actor int[] keys = new int[actorFound.Keys.Count]; actorFound.Keys.CopyTo(keys, 0); foreach (int key in keys) { actorFound[key]--; } } // remove all actors that were not found in the past few actor checks // Debug.Log ("Updating actor structure"); communicationMutex.WaitOne(); List <int> unusedKeys = new List <int>(); foreach (KeyValuePair <int, int> kvp in actorFound) { if (kvp.Value <= 0) { // check if this is the current actor if (kvp.Key == playerActor) { playerActor = -1; } // remove actor Debug.Log("Removing actor " + kvp.Key); actors.Remove(kvp.Key); actorPointers.Remove(kvp.Key); skeletons.Remove(kvp.Key); unusedKeys.Add(kvp.Key); } } communicationMutex.ReleaseMutex(); // Debug.Log ("Updating actor structure done"); // clear out actorfound structure foreach (int key in unusedKeys) { actorFound.Remove(key); } // look for current transformation of bones with ar tags - the head foreach (KeyValuePair <int, IntPtr> kvp in actorPointers) { int id = kvp.Key; // find the index of the head joint int headJointIndex = -1; for (int i = 0; i < skeletons[id].joints.Length; ++i) { if (skeletons[id].joints[i].name.EndsWith(headJointName)) { headJointIndex = i; break; } } if (headJointIndex == -1) { Debug.Log("no head joint for skeleton " + id); continue; } // get the transform and store it in headTransforms IntPtr trafo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(CapturyTransform))); UInt64 timestamp = Captury_getMarkerTransform(kvp.Value, headJointIndex, trafo); // is there a constraint for this joint that is not older than 500ms? if (timestamp != 0) { CapturyTransform t = (CapturyTransform)Marshal.PtrToStructure(trafo, typeof(CapturyTransform)); communicationMutex.WaitOne(); if (headTransforms.ContainsKey(id)) { // this is a new transform. the other thread should have a look at it. if (headTransforms[id].timestamp < timestamp) { headTransforms[id].consumed = false; } } else { headTransforms[id] = new CapturyMarkerTransform(); headTransforms[id].bestAccuracy = 0.95f; // if the new transform is actually already old mark it as old directly if (timestamp > Captury_getTime() - 500000) { headTransforms[id].consumed = false; } else { headTransforms[id].consumed = true; } } headTransforms[id].rotation = ConvertRotation(new Vector3(t.rx * 180 / (float)Math.PI, t.ry * 180 / (float)Math.PI, t.rz * 180 / (float)Math.PI)); headTransforms[id].translation = ConvertPosition(new Vector3(t.tx, t.ty, t.tz)); headTransforms[id].timestamp = timestamp; communicationMutex.ReleaseMutex(); // Debug.Log(string.Format("transform for actor.joint {0}.{1} is good, really t {2}, delta now {3}", id, headJointIndex, timestamp, Captury_getTime() - timestamp)); } else { communicationMutex.WaitOne(); headTransforms.Remove(id); communicationMutex.ReleaseMutex(); } Marshal.FreeHGlobal(trafo); } } Debug.Log("Disconnecting"); // make sure we disconnect Captury_disconnect(); isSetup = false; isConnected = false; }
public void sendActorSkeleton(CapturyActor actor, CapturySkeleton skeleton) { Debug.Log("received actor " + actor.name + " and skeleton " + skeleton.name); }