/// <summary>
 /// Creates a new MoCap data object.
 /// </summary>
 ///
 public MoCapData(MoCapDataBuffer buffer)
 {
     this.buffer = buffer;
     pos         = new Vector3();
     rot         = new Quaternion();
     tracked     = false;
     length      = 0;
 }
		public float length;   // length of bone

		/// <summary>
		/// Creates a new MoCap data object.
		/// </summary>
		/// 
		public MoCapData(MoCapDataBuffer buffer)
		{
			this.buffer = buffer;
			pos = new Vector3();
			rot = new Quaternion();
			tracked = false;
			length  = 0;
		}
        public readonly MoCapDataBuffer buffer;    // buffer for data


        /// <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;
            buffer     = new MoCapDataBuffer(this);
        }
        public float length;                    // length of bone


        /// <summary>
        /// Creates a cloned MoCap data object.
        /// </summary>
        ///
        public MoCapData(MoCapData clone)
        {
            buffer  = clone.buffer;
            pos     = clone.pos;
            rot     = clone.rot;
            tracked = clone.tracked;
            length  = clone.length;
        }
        public readonly MoCapDataBuffer buffer; // buffer for data


        /// <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

            buffer = new MoCapDataBuffer(this);
        }
		/// <summary>
		/// Creates copies of the marker template for all markers.
		/// </summary>
		/// <param name="markers">marker data from the MoCap system</param>
		/// 
		private void CreateMarkers(Marker[] markers)
		{
			// create node for containing all the marker objects
			markerNode = new GameObject();
			markerNode.name = "Markers";
			markerNode.transform.parent = this.transform;
			markerNode.transform.localPosition = Vector3.zero;
			markerNode.transform.localRotation = Quaternion.identity;
			markerNode.transform.localScale = Vector3.one;

			if (markerTemplate != null)
			{
				// create copies of the marker template
				foreach (Marker marker in markers)
				{
					GameObject markerRepresentation = GameObject.Instantiate(markerTemplate);
					markerRepresentation.name = marker.name;
					markerRepresentation.transform.parent = markerNode.transform;
					dataBuffers[marker] = new MoCapDataBuffer(marker.name, this.gameObject, markerRepresentation);
				}
			}
		}
		/// <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>
		/// 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);
			}
		}
		/// <summary>
		/// Creates a hierarchy of a selected bone of an actor.
		/// </summary>
		/// 
		private void CreateHierarchy()
		{
			// create node for containing all the hierarchy objects
			rootNode = new GameObject();
			rootNode.name = this.name + "_Root";
			rootNode.transform.parent = this.transform.parent;
			rootNode.transform.localPosition = Vector3.zero;
			rootNode.transform.localRotation = Quaternion.identity;
			rootNode.transform.localScale = Vector3.one;

			// create hierarchy
			GameObject boneNode = rootNode;
			foreach (Bone bone in controllingBone.chain)
			{
				// add empty for position/orientation
				boneNode = new GameObject();
				boneNode.name = bone.name;

				if (bone.parent != null)
				{
					// attach to parent node
					GameObject parentObject = dataBuffers[bone.parent].GameObject;
					boneNode.transform.parent = parentObject.transform;
				}
				else
				{
					// no parent = root bone > attach to root node
					boneNode.transform.parent = rootNode.transform;
				}
				boneNode.transform.localScale = Vector3.one;

				dataBuffers[bone] = new MoCapDataBuffer(bone.name, this.gameObject, boneNode);
			}

			// move this transform to the end of the hierarchy
			this.transform.parent        = boneNode.transform;
			this.transform.localPosition = Vector3.zero;
			this.transform.localRotation = Quaternion.identity;
		}