/// <summary>Request data descriptions from the host, then update our definitions.</summary> /// <exception cref="NatNetException"> /// Thrown by <see cref="NatNetClient.GetDataDescriptions"/> if the request to the server fails. /// </exception> public void UpdateDefinitions() { // This may throw an exception if the server request times out or otherwise fails. m_dataDescs = m_client.GetDataDescriptions(); m_skeletonDefinitions.Clear(); for (int nativeDescIdx = 0; nativeDescIdx < m_dataDescs.SkeletonDescriptions.Count; ++nativeDescIdx) { sSkeletonDescription nativeSkel = m_dataDescs.SkeletonDescriptions[nativeDescIdx]; OptitrackSkeletonDefinition skelDef = new OptitrackSkeletonDefinition { Id = nativeSkel.Id, Name = nativeSkel.Name, Bones = new List <OptitrackSkeletonDefinition.BoneDefinition>(nativeSkel.RigidBodyCount), }; // Populate nested bone definitions. for (int nativeBoneIdx = 0; nativeBoneIdx < nativeSkel.RigidBodyCount; ++nativeBoneIdx) { sRigidBodyDescription nativeBone = nativeSkel.RigidBodies[nativeBoneIdx]; OptitrackSkeletonDefinition.BoneDefinition boneDef = new OptitrackSkeletonDefinition.BoneDefinition { Id = nativeBone.Id, ParentId = nativeBone.ParentId, Name = nativeBone.Name, Offset = new Vector3(nativeBone.OffsetX, nativeBone.OffsetY, nativeBone.OffsetZ), }; skelDef.Bones.Add(boneDef); } m_skeletonDefinitions.Add(skelDef); } }
void Start() { // If the user didn't explicitly associate a client, find a suitable default. if (this.StreamingClient == null) { this.StreamingClient = OptitrackStreamingClient.FindDefaultClient(); // If we still couldn't find one, disable this component. if (this.StreamingClient == null) { Debug.LogError(GetType().FullName + ": Streaming client not set, and no " + typeof(OptitrackStreamingClient).FullName + " components found in scene; disabling this component.", this); this.enabled = false; return; } } this.StreamingClient.RegisterSkeleton(this, this.SkeletonAssetName); // Create a lookup from Mecanim anatomy bone names to OptiTrack streaming bone names. CacheBoneNameMap(this.StreamingClient.BoneNamingConvention, this.SkeletonAssetName); // Retrieve the OptiTrack skeleton definition. m_skeletonDef = this.StreamingClient.GetSkeletonDefinitionByName(this.SkeletonAssetName); if (m_skeletonDef == null) { Debug.LogError(GetType().FullName + ": Could not find skeleton definition with the name \"" + this.SkeletonAssetName + "\"", this); this.enabled = false; return; } // Create a hierarchy of GameObjects that will receive the skeletal pose data. string rootObjectName = "OptiTrack Skeleton - " + this.SkeletonAssetName; m_rootObject = new GameObject(rootObjectName); m_boneObjectMap = new Dictionary <Int32, GameObject>(m_skeletonDef.Bones.Count); for (int boneDefIdx = 0; boneDefIdx < m_skeletonDef.Bones.Count; ++boneDefIdx) { OptitrackSkeletonDefinition.BoneDefinition boneDef = m_skeletonDef.Bones[boneDefIdx]; GameObject boneObject = new GameObject(boneDef.Name); boneObject.transform.parent = boneDef.ParentId == 0 ? m_rootObject.transform : m_boneObjectMap[boneDef.ParentId].transform; boneObject.transform.localPosition = boneDef.Offset; m_boneObjectMap[boneDef.Id] = boneObject; } // Hook up retargeting between those GameObjects and the destination Avatar. MecanimSetup(rootObjectName); // Can't re-parent this until after Mecanim setup, or else Mecanim gets confused. m_rootObject.transform.parent = this.StreamingClient.transform; m_rootObject.transform.localPosition = Vector3.zero; m_rootObject.transform.localRotation = Quaternion.identity; }
void redirectSkeleton() { if (this.StreamingClient == null) { return; } // Create a lookup from Mecanim anatomy bone names to OptiTrack streaming bone names. CacheBoneNameMap(this.StreamingClient.BoneNamingConvention, this.SkeletonAssetName); // Retrieve the OptiTrack skeleton definition. m_skeletonDef = this.StreamingClient.GetSkeletonDefinitionByName(this.SkeletonAssetName); if (m_skeletonDef == null) { StreamingClient.TriggerUpdateDefinitions(); Debug.LogError( GetType().FullName + ": Could not find skeleton definition with the name \"" + this.SkeletonAssetName + "\"", this); this.enabled = false; return; } else { Debug.Log("find a skeleton"); } // Create a hierarchy of GameObjects that will receive the skeletal pose data. string rootObjectName = "OptiTrack Skeleton - " + this.SkeletonAssetName; m_rootObject = new GameObject(rootObjectName); m_boneObjectMap = new Dictionary <Int32, GameObject>(m_skeletonDef.Bones.Count); for (int boneDefIdx = 0; boneDefIdx < m_skeletonDef.Bones.Count; ++boneDefIdx) { OptitrackSkeletonDefinition.BoneDefinition boneDef = m_skeletonDef.Bones[boneDefIdx]; GameObject boneObject = new GameObject(boneDef.Name); boneObject.transform.parent = boneDef.ParentId == 0 ? m_rootObject.transform : m_boneObjectMap[boneDef.ParentId].transform; boneObject.transform.localPosition = boneDef.Offset.V3; m_boneObjectMap[boneDef.Id] = boneObject; } // Hook up retargeting between those GameObjects and the destination Avatar. MecanimSetup(rootObjectName); // Can't reparent this until after Mecanim setup, or else Mecanim gets confused. m_rootObject.transform.parent = this.StreamingClient.transform; m_rootObject.transform.localPosition = Vector3.zero; m_rootObject.transform.localRotation = Quaternion.identity; }
/// <summary>Request data descriptions from the host, then update our definitions.</summary> /// <exception cref="NatNetException"> /// Thrown by <see cref="NatNetClient.GetDataDescriptions"/> if the request to the server fails. /// </exception> public void UpdateDefinitions() { if (m_client == null) { return; } // This may throw an exception if the server request times out or otherwise fails. m_dataDescs = m_client.GetDataDescriptions(); m_skeletonDefinitions.Clear(); for (int nativeDescIdx = 0; nativeDescIdx < m_dataDescs.SkeletonDescriptions.Count; ++nativeDescIdx) { sSkeletonDescription nativeSkel = m_dataDescs.SkeletonDescriptions[nativeDescIdx]; OptitrackSkeletonDefinition skelDef = new OptitrackSkeletonDefinition { Id = nativeSkel.Id, Name = nativeSkel.Name, Bones = new List <OptitrackSkeletonDefinition.BoneDefinition>(nativeSkel.RigidBodyCount), }; // Populate nested bone definitions. for (int nativeBoneIdx = 0; nativeBoneIdx < nativeSkel.RigidBodyCount; ++nativeBoneIdx) { sRigidBodyDescription nativeBone = nativeSkel.RigidBodies[nativeBoneIdx]; OptitrackSkeletonDefinition.BoneDefinition boneDef = new OptitrackSkeletonDefinition.BoneDefinition { Id = nativeBone.Id, ParentId = nativeBone.ParentId, Name = nativeBone.Name, Offset = new Vector3Serializer(nativeBone.OffsetX, nativeBone.OffsetY, nativeBone.OffsetZ), }; skelDef.Bones.Add(boneDef); } m_skeletonDefinitions.Add(skelDef); } BinaryFormatter binFormatter = new BinaryFormatter(); MemoryStream mStream = new MemoryStream(); binFormatter.Serialize(mStream, m_skeletonDefinitions); photonView.RPC("RPC_UpdateDefinitions", PhotonTargets.AllBuffered, new object[] { mStream.ToArray() }); }
/// <summary> /// Constructs the source Avatar and pose handlers for Mecanim retargeting. /// </summary> /// <param name="rootObjectName"></param> private void MecanimSetup(string rootObjectName) { string[] humanTraitBoneNames = HumanTrait.BoneName; // Set up the mapping between Mecanim human anatomy and OptiTrack skeleton representations. List <HumanBone> humanBones = new List <HumanBone>(m_skeletonDef.Bones.Count); for (int humanBoneNameIdx = 0; humanBoneNameIdx < humanTraitBoneNames.Length; ++humanBoneNameIdx) { string humanBoneName = humanTraitBoneNames[humanBoneNameIdx]; if (m_cachedMecanimBoneNameMap.ContainsKey(humanBoneName)) { HumanBone humanBone = new HumanBone(); humanBone.humanName = humanBoneName; humanBone.boneName = m_cachedMecanimBoneNameMap[humanBoneName]; humanBone.limit.useDefaultValues = true; humanBones.Add(humanBone); } } // Set up the T-pose and game object name mappings. List <SkeletonBone> skeletonBones = new List <SkeletonBone>(m_skeletonDef.Bones.Count + 1); // Special case: Create the root bone. { SkeletonBone rootBone = new SkeletonBone(); rootBone.name = rootObjectName; rootBone.position = Vector3.zero; rootBone.rotation = Quaternion.identity; rootBone.scale = Vector3.one; skeletonBones.Add(rootBone); } // Create remaining retargeted bone definitions. for (int boneDefIdx = 0; boneDefIdx < m_skeletonDef.Bones.Count; ++boneDefIdx) { OptitrackSkeletonDefinition.BoneDefinition boneDef = m_skeletonDef.Bones[boneDefIdx]; SkeletonBone skelBone = new SkeletonBone(); skelBone.name = boneDef.Name; skelBone.position = boneDef.Offset; skelBone.rotation = Quaternion.identity; skelBone.scale = Vector3.one; skeletonBones.Add(skelBone); } // Now set up the HumanDescription for the retargeting source Avatar. HumanDescription humanDesc = new HumanDescription(); humanDesc.human = humanBones.ToArray(); humanDesc.skeleton = skeletonBones.ToArray(); // These all correspond to default values. humanDesc.upperArmTwist = 0.5f; humanDesc.lowerArmTwist = 0.5f; humanDesc.upperLegTwist = 0.5f; humanDesc.lowerLegTwist = 0.5f; humanDesc.armStretch = 0.05f; humanDesc.legStretch = 0.05f; humanDesc.feetSpacing = 0.0f; humanDesc.hasTranslationDoF = false; // Finally, take the description and build the Avatar and pose handlers. m_srcAvatar = AvatarBuilder.BuildHumanAvatar(m_rootObject, humanDesc); if (m_srcAvatar.isValid == false || m_srcAvatar.isHuman == false) { Debug.LogError(GetType().FullName + ": Unable to create source Avatar for retargeting. Check that your Skeleton Asset Name and Bone Naming Convention are configured correctly.", this); this.enabled = false; return; } m_srcPoseHandler = new HumanPoseHandler(m_srcAvatar, m_rootObject.transform); m_destPoseHandler = new HumanPoseHandler(DestinationAvatar, this.transform); }
/// <summary>Request data descriptions from the host, then update our definitions.</summary> /// <exception cref="NatNetException"> /// Thrown by <see cref="NatNetClient.GetDataDescriptions"/> if the request to the server fails. /// </exception> public void UpdateDefinitions() { // This may throw an exception if the server request times out or otherwise fails. m_dataDescs = m_client.GetDataDescriptions(); m_rigidBodyDefinitions.Clear(); m_skeletonDefinitions.Clear(); // Translate rigid body definitions. for (int nativeRbDescIdx = 0; nativeRbDescIdx < m_dataDescs.RigidBodyDescriptions.Count; ++nativeRbDescIdx) { sRigidBodyDescription nativeRb = m_dataDescs.RigidBodyDescriptions[nativeRbDescIdx]; OptitrackRigidBodyDefinition rbDef = new OptitrackRigidBodyDefinition { Id = nativeRb.Id, Name = nativeRb.Name, Markers = new List <OptitrackRigidBodyDefinition.MarkerDefinition>(nativeRb.MarkerCount), }; // Populate nested marker definitions. for (int nativeMarkerIdx = 0; nativeMarkerIdx < nativeRb.MarkerCount; ++nativeMarkerIdx) { int positionOffset = nativeMarkerIdx * Marshal.SizeOf(typeof(MarkerDataVector)); IntPtr positionPtr = new IntPtr(nativeRb.MarkerPositions.ToInt64() + positionOffset); int labelOffset = nativeMarkerIdx * Marshal.SizeOf(typeof(Int32)); IntPtr labelPtr = new IntPtr(nativeRb.MarkerRequiredLabels.ToInt64() + labelOffset); MarkerDataVector nativePos = (MarkerDataVector)Marshal.PtrToStructure(positionPtr, typeof(MarkerDataVector)); Int32 nativeLabel = Marshal.ReadInt32(labelPtr); OptitrackRigidBodyDefinition.MarkerDefinition markerDef = new OptitrackRigidBodyDefinition.MarkerDefinition { Position = new Vector3(nativePos.Values[0], nativePos.Values[1], nativePos.Values[2]), RequiredLabel = nativeLabel, }; rbDef.Markers.Add(markerDef); } m_rigidBodyDefinitions.Add(rbDef); } // Translate skeleton definitions. for (int nativeSkelDescIdx = 0; nativeSkelDescIdx < m_dataDescs.SkeletonDescriptions.Count; ++nativeSkelDescIdx) { sSkeletonDescription nativeSkel = m_dataDescs.SkeletonDescriptions[nativeSkelDescIdx]; OptitrackSkeletonDefinition skelDef = new OptitrackSkeletonDefinition { Id = nativeSkel.Id, Name = nativeSkel.Name, Bones = new List <OptitrackSkeletonDefinition.BoneDefinition>(nativeSkel.RigidBodyCount), }; // Populate nested bone definitions. for (int nativeBoneIdx = 0; nativeBoneIdx < nativeSkel.RigidBodyCount; ++nativeBoneIdx) { sRigidBodyDescription nativeBone = nativeSkel.RigidBodies[nativeBoneIdx]; OptitrackSkeletonDefinition.BoneDefinition boneDef = new OptitrackSkeletonDefinition.BoneDefinition { Id = nativeBone.Id, ParentId = nativeBone.ParentId, Name = nativeBone.Name, Offset = new Vector3(-nativeBone.OffsetX, nativeBone.OffsetY, nativeBone.OffsetZ), }; skelDef.Bones.Add(boneDef); } m_skeletonDefinitions.Add(skelDef); } }