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