/// <summary>
		/// Finds the rigging in the model and matches it to the MoCap bone system.
		/// </summary>
		/// <param name="bones">bone data from the MoCap system</param>
		/// 
		private void MatchBones(Bone[] bones)
		{
			dataBuffers = new Dictionary<Bone, MoCapDataBuffer>();
			string unmatchedBones = "";

			// create copies of the marker template
			foreach (Bone bone in bones)
			{
				BoneNameTranslationEntry entry = null;
				string boneName = boneNamePrefix + TranslateBoneName(bone.name, ref entry);
				// find the child in the model with the given bone name
				Transform boneNode = Utilities.FindInHierarchy(boneName, transform);
				if (boneNode != null)
				{
					dataBuffers[bone] = new MoCapDataBuffer(bone.name, this.gameObject, boneNode.gameObject, entry);
				}
				else
				{
					if (unmatchedBones.Length > 0)
					{
						unmatchedBones += ", ";
					}
					unmatchedBones += bone.name;
				}
			}

			if (unmatchedBones.Length > 0)
			{
				Debug.LogWarning("Could not find the following bones in Model '" + this.name + "': " + unmatchedBones);
			}
		}
		/// <summary>
		/// Stores bone data.
		/// </summary>
		/// <param name="bone">the bone to store data of</param>
		/// 
		public void Store(Bone bone)
		{
			pos.Set(bone.px, bone.py, bone.pz);
			rot.Set(bone.qx, bone.qy, bone.qz, bone.qw);
			tracked = bone.tracked;
			length  = bone.length;
		}
		/// <summary>
		/// Creates copies of the bone template for all bones.
		/// </summary>
		/// <param name="bones">bone data from the MoCap system</param>
		/// 
		private void CreateBones(Bone[] bones)
		{
			// create node for containing all the marker objects
			skeletonNode = new GameObject();
			skeletonNode.name = "Bones";
			skeletonNode.transform.parent        = this.transform;
			skeletonNode.transform.localPosition = Vector3.zero;
			skeletonNode.transform.localRotation = Quaternion.identity;
			skeletonNode.transform.localScale    = Vector3.one;

			// create copies of the marker template
			foreach (Bone bone in bones)
			{
				// add empty for position/orientation
				GameObject boneNode = new GameObject();
				boneNode.name = bone.name;

				GameObject boneRepresentation = null;

				if (boneTemplate != null)
				{
					float scale = bone.length;
					if (scale <= 0) { scale = 1; }

					// add subnode for visual that can be scaled
					boneRepresentation = GameObject.Instantiate(boneTemplate);
					boneRepresentation.transform.parent = boneNode.transform;
					boneRepresentation.transform.localScale = scale * Vector3.one;
					boneRepresentation.transform.localRotation = new Quaternion();
					boneRepresentation.name = bone.name + "_visual";
					boneRepresentation.SetActive(true);
				}

				if (bone.parent != null)
				{
					// attach to parent node
					GameObject parentObject = dataBuffers[bone.parent].GameObject;
					boneNode.transform.parent = parentObject.transform;
				}
				else
				{
					// no parent > attach to base skeleton node
					boneNode.transform.parent = skeletonNode.transform;
				}

				dataBuffers[bone] = new MoCapDataBuffer(bone.name, this.gameObject, boneNode, boneRepresentation);
				boneTemplate.SetActive(false);
			}
		}
		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
		}
		/// <summary>
		/// Converts a bone from a right handed rotation to a left handed (Unity).
		/// </summary>
		/// <param name="bone">the bone to convert</param>
		/// 
		private void TransformToUnity(ref Bone bone)
		{
			bone.pz *= -1; // flip Z pos

			/*
			Quaternion q = new Quaternion(bone.qx, bone.qy, bone.qz, bone.qw);
			Vector3 e = q.eulerAngles;
			Quaternion x = Quaternion.AngleAxis( e.x, Vector3.right);
			Quaternion y = Quaternion.AngleAxis(-e.y + 180, Vector3.up);
			Quaternion z = Quaternion.AngleAxis( e.z, Vector3.forward);
			q = (z * y * x);

			bone.qx = q.x;
			bone.qy = q.y;
			bone.qz = q.z;
			bone.qw = q.w;
			*/
			
			bone.qx *= -1;
			bone.qy *= -1;
			
			/*
			Quaternion q = new Quaternion(bone.qx, bone.qy, bone.qz, bone.qw);
			float   angle = 0.0f;
			Vector3 axis = Vector3.zero;
			q.ToAngleAxis(out angle, out axis);
			axis.z = -axis.z;
			q = Quaternion.AngleAxis(-angle, axis);

			Debug.Log(
				"from X=" + bone.qx + ",Y=" + bone.qy + ",Z=" + bone.qz + ",W=" + bone.qw +
				"  to  X=" + q.x + ",Y=" + q.y + ",Z=" + q.z + ",W=" + q.w);				

			bone.qx = q.x;
			bone.qy = q.y;
			bone.qz = q.z;
			bone.qw = q.w;
			*/
		}
		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;
		}
		/// <summary>
		/// Put a bone dataset into the pipeline
		/// and extract the delayed dataset.
		/// </summary>
		/// <param name="bone">the bone data to add into the queue</param>
		/// <returns>the delayed dataset</returns>
		/// 
		public MoCapData Process(Bone bone)
		{
			if (firstPush)
			{
				// first piece of data > fill the whole pipeline with it
				for (int i = 0; i < pipeline.Length; i++)
				{
					pipeline[i].Store(bone);
				}
				firstPush = false;
			}
			else
			{
				pipeline[index].Store(bone);
			}
			index = (index + 1) % pipeline.Length;

			// manipulate data before returning
			MoCapData retValue = pipeline[index];
			foreach (IModifier m in modifiers)
			{
				m.Process(ref retValue);
			}

			return retValue;
		}
		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;
		}