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          float  value;  // value of the channel

		/// <summary>
		/// Creates a new device channel with a name.
		/// </summary>
		/// <param name="device">device this channel belongs to</param>
		/// <param name="name">name of the channel</param>
		/// 
		public Channel(Device device, string name)
		{
			this.device = device;
			this.name   = name;
		}
		private void ReadForcePlateDescription(ref List<Device> devices)
		{
			int    id   = dataStream.GetInt();    // ID
			string name = dataStream.GetString(); // name
			Device device = new Device(scene, name, id); // create device

			int nChannels   = dataStream.GetInt(); // channel count
			device.channels = new Channel[nChannels];
			for (int channelIdx = 0; channelIdx < nChannels; channelIdx++)
			{
				name = dataStream.GetString();
				Channel channel = new Channel(device, name);
				device.channels[channelIdx] = channel;
			}
			devices.Add(device);
		}
		private void ParseForcePlate(NatNetPacket_In packet, List<Device> devices)
		{
			int    id     = packet.GetInt32();           // force plate ID
			String name   = packet.GetString();          // force plate serial #
			Device device = new Device(scene, name, id); // create device

			// skip next 652 bytes 
			// (SDK 2.9 sample code does not explain what this is about)
			packet.Skip(652);

			int nChannels = packet.GetInt32(); // channel count
			device.channels = new Channel[nChannels];
			for (int channelIdx = 0; channelIdx < nChannels; channelIdx++)
			{
				name = packet.GetString();
				Channel channel = new Channel(device, name);
				device.channels[channelIdx] = channel;
			}
			devices.Add(device);
		}