public bool Connect(IMoCapClient_ConnectionInfo connectionInfo)
		{
			connected = VRDevice.isPresent;

			if (connected)
			{
				system = OpenVR.System;
				if (system == null)
				{
					connected = false;
					Debug.LogWarning("Could not find OpenVR System instance.");
				}
				compositor = OpenVR.Compositor;
				if (compositor == null)
				{
					connected = false;
					Debug.LogWarning("Could not find OpenVR Compositor instance.");
				}
			}

			if (connected)
			{
				poses     = new TrackedDevicePose_t[OpenVR.k_unMaxTrackedDeviceCount];
				gamePoses = new TrackedDevicePose_t[0];

				FindControllerIndices();
				scene.actors  = new Actor[controllerIndices.Length];
				scene.devices = new Device[controllerIndices.Length];
				states        = new VRControllerState_t[controllerIndices.Length];

				for (int idx = 0; idx < controllerIndices.Length; idx++)
				{
					string name = "Controller" + (idx + 1);

					Actor actor        = new Actor(scene, name, idx);
					actor.bones        = new Bone[1];
					actor.bones[0]     = new Bone(actor, "root", 0);
					scene.actors[idx]  = actor;

					Device device      = new Device(scene, name, idx);
					device.channels    = new Channel[7];
					device.channels[0] = new Channel(device, "button1");  // fire
					device.channels[1] = new Channel(device, "button2");  // menu
					device.channels[2] = new Channel(device, "button3");  // grip
					device.channels[3] = new Channel(device, "axis1");    // touchpad + press
					device.channels[4] = new Channel(device, "axis2");
					device.channels[5] = new Channel(device, "axis1raw"); // touchpad touch
					device.channels[6] = new Channel(device, "axis2raw");

					scene.devices[idx] = device;
				}
			}
			return connected;
		}
		public List<Bone> chain;      // chain from root bone to this bone


		/// <summary>
		/// Creates a new bone with a name and ID.
		/// </summary>
		/// <param name="actor">actor this bonebelongs to</param>
		/// <param name="name">name of the bone</param>
		/// <param name="in">ID of the bone</param>
		/// 
		public Bone(Actor actor, string name, int id)
		{
			this.actor = actor;
			this.name  = name;
			this.id    = id;

			ox = oy = oz = 0;  // no offset
			parent = null;     // no parent

			px = py = pz = 0;         // origin position
			qx = qy = qz = 0; qw = 1; // no rotation
			length = 0;               // no length

			children = new List<Bone>();
			chain    = new List<Bone>();
			chain.Add(this); // this bone is part of the chain
		}
		public          bool   tracked;    // tracking state

		/// <summary>
		/// Creates a new marker with a name.
		/// </summary>
		/// <param name="actor">actor this marker is associated with</param>
		/// <param name="name">name of the marker</param>
		/// 
		public Marker(Actor actor, string name)
		{
			this.actor = actor;
			this.name  = name;
			px = py = pz = 0;
			tracked = false;
		}
		private void ReadSkeletonDescription(ref List<Actor> actors)
		{
			int    skeletonId   = dataStream.GetInt();    // ID
			string skeletonName = dataStream.GetString(); // name

			// rigid body name should be equal to actor name: search
			Actor actor = null;
			foreach (Actor a in actors)
			{
				if (a.name.CompareTo(skeletonName) == 0)
				{
					actor = a;
					actor.id = skeletonId; // associate actor and skeleton 
				}
			}
			if (actor == null)
			{
				// names don't match > try IDs
				if ((skeletonId >= 0) && (skeletonId < actors.Count))
				{
					actor = actors[skeletonId];
				}
			}
			if (actor == null)
			{
				Debug.LogWarning("Skeleton " + skeletonName + " could not be matched to an actor.");
				actor = new Actor(scene, skeletonName, skeletonId);
				actors.Add(actor);
			}

			int nBones  = dataStream.GetInt(); // Skeleton bone count
			actor.bones = new Bone[nBones];
			for (int boneIdx = 0; boneIdx < nBones; boneIdx++)
			{
				int    id   = dataStream.GetInt();    // bone ID
				String name = dataStream.GetString(); // bone name 
				Bone   bone = new Bone(actor, name, id);

				int parentId = dataStream.GetInt(); // Skeleton parent ID
				bone.parent = actor.FindBone(parentId); 
				if (bone.parent != null)
				{
					// if bone has a parent, update child list of parent
					bone.parent.children.Add(bone);
				}
				bone.BuildChain(); // build chain from root to this bone

				bone.ox = dataStream.GetFloat(); // X offset
				bone.oy = dataStream.GetFloat(); // Y offset
				bone.oz = dataStream.GetFloat(); // Z offset

				actor.bones[boneIdx] = bone;
			}
		}
		private void ReadRigidBodyDescription(ref List<Actor> actors)
		{
			int    id   = dataStream.GetInt();    // ID
			string name = dataStream.GetString(); // name

			// rigid body name should be equal to actor name: search
			Actor actor = null;
			foreach (Actor a in actors)
			{
				if (a.name.Equals(name))
				{
					actor = a;
				}
			}
			if (actor == null)
			{
				Debug.LogWarning("Rigid Body " + name + " could not be matched to an actor.");
				actor = new Actor(scene, name, id);
				actors.Add(actor);
			}

			Bone bone = new Bone(actor, name, id);

			dataStream.GetInt();             // Parent ID (ignore for rigid body)
			bone.parent = null;              // rigid bodies should not have a parent
			bone.ox = dataStream.GetFloat(); // X offset
			bone.oy = dataStream.GetFloat(); // Y offset
			bone.oz = dataStream.GetFloat(); // Z offset

			actor.bones = new Bone[1];
			actor.bones[0] = bone;
		}
		private void ReadMarkersetDescription(ref List<Actor> actors)
		{
			int    id   = 0;                      // no ID for markersets
			string name = dataStream.GetString(); // markerset name
			Actor actor = new Actor(scene, name, id);

			int nMarkers  = dataStream.GetInt(); // marker count
			actor.markers = new Marker[nMarkers];
			for (int markerIdx = 0; markerIdx < nMarkers; markerIdx++)
			{
				name = dataStream.GetString();
				Marker marker = new Marker(actor, name);
				actor.markers[markerIdx] = marker;
			}
			actors.Add(actor);
		}
		private void ParseSkeleton(NatNetPacket_In packet, List<Actor> actors)
		{
			bool includesBoneNames = // starting at v2.0
					(serverInfo.versionNatNet[0] >= 2);

			String skeletonName = packet.GetString(); // name
			int    skeletonId   = packet.GetInt32();  // ID

			// rigid body name should be equal to actor name: search
			Actor actor = null;
			foreach (Actor a in actors)
			{
				if (a.name.CompareTo(skeletonName) == 0)
				{
					actor = a;
					actor.id = skeletonId; // associate actor and skeleton 
				}
			}
			if (actor == null)
			{
				// names don't match > try IDs
				if ((skeletonId >= 0) && (skeletonId < actors.Count))
				{
					actor = actors[skeletonId];
				}
			}
			if (actor == null)
			{
				Debug.LogWarning("Skeleton " + skeletonName + " could not be matched to an actor.");
				actor = new Actor(scene, skeletonName, skeletonId);
				actors.Add(actor);
			}

			int nBones = packet.GetInt32(); // Skeleton bone count
			// TODO: Sanity check on the number before allocating that much space
			actor.bones = new Bone[nBones];
			for ( int boneIdx = 0 ; boneIdx < nBones ; boneIdx++ )
			{
				String name = "";
				if (includesBoneNames)
				{
					name = packet.GetString(); // bone name 
				}
				int id = packet.GetInt32(); // bone ID
				Bone bone = new Bone(actor, name, id);

				bone.parent = actor.FindBone(packet.GetInt32()); // Skeleton parent ID
				if (bone.parent != null)
				{
					// if bone has a parent, update child list of parent
					bone.parent.children.Add(bone);
				}
				bone.BuildChain(); // build chain from root to this bone

				bone.ox =  packet.GetFloat(); // X offset
				bone.oy =  packet.GetFloat(); // Y offset
				bone.oz = -packet.GetFloat(); // Z offset

				actor.bones[boneIdx] = bone;
			}
		}
		private void ParseRigidBody(NatNetPacket_In packet, List<Actor> actors)
		{
			string name = packet.GetString(); // name, TODO: No name in major version < 2
			int    id   = packet.GetInt32();  // ID

			// rigid body name should be equal to actor name: search
			Actor actor = null;
			foreach (Actor a in actors)
			{
				if (a.name.Equals(name))
				{
					actor = a;
				}
			}
			if (actor == null)
			{
				Debug.LogWarning("Rigid Body " + name + " could not be matched to an actor.");
				actor = new Actor(scene, name, id);
				actors.Add(actor);
			}

			Bone bone = new Bone(actor, name, id);

			packet.GetInt32();    // Parent ID (ignore for rigid body)
			bone.parent  =  null;                 // rigid bodies should not have a parent
			bone.ox      =  packet.GetFloat();    // X offset
			bone.oy      =  packet.GetFloat();    // Y offset
			bone.oz      = -packet.GetFloat();    // Z offset
			
			actor.bones    = new Bone[1];
			actor.bones[0] = bone;
		}
		private void ParseMarkerset(NatNetPacket_In packet, List<Actor> actors)
		{
			int    id   = 0;                  // no ID for markersets
			string name = packet.GetString(); // markerset name
			Actor actor = new Actor(scene, name, id);

			int nMarkers = packet.GetInt32();  // marker count
			// TODO: Sanity check on the number before allocating that much space
			actor.markers = new Marker[nMarkers];
			for ( int markerIdx = 0 ; markerIdx < nMarkers ; markerIdx++ )
			{
				name = packet.GetString();
				Marker marker = new Marker(actor, name);
				actor.markers[markerIdx] = marker;
			}
			actors.Add(actor);
		}