/// <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;
    }
Ejemplo n.º 3
0
    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;
    }
Ejemplo n.º 4
0
    /// <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);
    }
Ejemplo n.º 6
0
    /// <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);
        }
    }