示例#1
0
        /**
         * @brief Creates a new state and adds it to this clip.
         * @param[in] timestamp    The timestamp for this new state.
         * @return The newly created state.
         */
        public RigState new_state(double timestamp)
        {
            RigState state = new RigState(m_rig);

            state.set_timestamp(timestamp);
            m_states.Add(state);
            return(state);
        }
示例#2
0
        /**
         * @brief Creates a new state and adds it to this clip.
         * @param[in] timestamp    The timestamp for this new state.
         * @return The newly created state.
         */
        public RigState NewState(double timestamp)
        {
            RigState state = new RigState(m_rig);

            state.SetTimestamp(timestamp);
            m_states.Add(state);
            return(state);
        }
示例#3
0
		//! duplicate this state (deep copy)
		public RigState Duplicate() {
		
			RigState rig_state = new RigState();
			rig_state.m_tracking_successful = m_tracking_successful;
			rig_state.m_timestamp = m_timestamp;
			rig_state.m_blendshape_coefficients = (double[]) m_blendshape_coefficients.Clone();
			rig_state.m_bone_rotations = (Quaternion[])m_bone_rotations.Clone();
			rig_state.m_bone_translations = (Vector3[])m_bone_translations.Clone();
			return rig_state;
		}
示例#4
0
        void Update()
        {
            bool new_data = false;

            m_mutex.WaitOne();
            // check if there are new blendshape names, and if so update
            if (NewBlendShapeNamesArrived())
            {
                m_rig = Rig.GetRigFromBlendShapeNames(GetBlendShapeNames());
            }

            // get most recent tracking data
            while (m_data_parser.CountAvailableTracks() > 0)
            {
                m_current_track = m_data_parser.Dequeue();
                new_data        = true;
            }

            // check that we have a rig (set up from blendshape names) with the same number of blendshapes as what we receive
            if (m_rig != null && m_current_track != null)
            {
                int n_track_coefficients = m_current_track.n_coefficients();
                int n_rig_coefficients   = m_rig.NumShapes();
                if (n_track_coefficients != n_rig_coefficients)
                {
                    Debug.LogWarning("number of coefficients of rig and tracking state have changed: " + n_track_coefficients + " vs " + n_rig_coefficients);
                    // clear the current rig as it is not usable with the data coming from faceshift
                    m_rig           = null;
                    m_current_track = null;
                    // get again the blendshapes from fs studio
                    AskForBlendshapeNames();
                }
            }
            m_mutex.ReleaseMutex();

            if (m_rig != null && m_current_track != null && m_Retargeting != null)
            {
                if (new_data && m_current_track.TrackSuccess)
                {
                    // create a rig state
                    RigState state = new RigState(m_rig);
                    state.SetTimestamp(m_current_track.TimeStamp);
                    state.SetBoneTranslation(0, m_current_track.HeadTranslation());
                    state.SetBoneRotation(0, m_current_track.HeadRotation());
                    state.SetBoneRotation(1, m_current_track.LeftEyeRotation());
                    state.SetBoneRotation(2, m_current_track.RightEyeRotation());
                    for (int i = 0; i < m_rig.NumShapes(); i++)
                    {
                        state.SetBlendshapeCoefficient(i, m_current_track.Coefficient[i]);
                    }

                    base.UpdateAnimation(m_rig, state);
                }
            }
        }
示例#5
0
        //! duplicate this state (deep copy)
        public RigState Duplicate()
        {
            RigState rig_state = new RigState();

            rig_state.m_tracking_successful     = m_tracking_successful;
            rig_state.m_timestamp               = m_timestamp;
            rig_state.m_blendshape_coefficients = (double[])m_blendshape_coefficients.Clone();
            rig_state.m_bone_rotations          = (Quaternion[])m_bone_rotations.Clone();
            rig_state.m_bone_translations       = (Vector3[])m_bone_translations.Clone();
            return(rig_state);
        }
		void Update () {
		
			bool new_data = false;
			m_mutex.WaitOne();
			// check if there are new blendshape names, and if so update
			if (NewBlendShapeNamesArrived()) {
				m_rig = Rig.GetRigFromBlendShapeNames(GetBlendShapeNames());
			}
	
			// get most recent tracking data
			while (m_data_parser.CountAvailableTracks() > 0) {
				m_current_track = m_data_parser.Dequeue();
				new_data = true;
			}
	
			// check that we have a rig (set up from blendshape names) with the same number of blendshapes as what we receive
			if (m_rig != null && m_current_track != null) {
				int n_track_coefficients = m_current_track.n_coefficients();
				int n_rig_coefficients = m_rig.NumShapes();
				if (n_track_coefficients != n_rig_coefficients) {
					Debug.LogWarning("number of coefficients of rig and tracking state have changed: " + n_track_coefficients + " vs " + n_rig_coefficients);
					// clear the current rig as it is not usable with the data coming from faceshift
					m_rig = null;
					m_current_track = null;
					// get again the blendshapes from fs studio
					AskForBlendshapeNames();
				}
			}
			m_mutex.ReleaseMutex();
	
			if (m_rig != null && m_current_track != null && m_Retargeting != null) {
				if (new_data && m_current_track.TrackSuccess) {
					// create a rig state
					RigState state = new RigState(m_rig);
					state.SetTimestamp(m_current_track.TimeStamp);
					state.SetBoneTranslation(0, m_current_track.HeadTranslation());
					state.SetBoneRotation(0, m_current_track.HeadRotation());
					state.SetBoneRotation(1, m_current_track.LeftEyeRotation());
					state.SetBoneRotation(2, m_current_track.RightEyeRotation());
					for (int i = 0; i < m_rig.NumShapes(); i++) {
						state.SetBlendshapeCoefficient(i, m_current_track.Coefficient[i]);
					}
					
					base.UpdateAnimation(m_rig, state);
				}
			}
		}
示例#7
0
        /**
         *	Evaluates the target blendshape values based on the state of a rig and a retargeting configuration.
         *  If a blendshape is not affected by the retargeting then the value of this blendshape is null.
         */
        public static BlendshapeValue [] evaluate_target_blendshapes(ClipRetargeting retargeting,
                                                                     Rig rig,
                                                                     RigState state,
                                                                     ArrayList target_blendshapes)
        {
            int n_target_blendshapes = target_blendshapes.Count;

            BlendshapeValue [] values = new BlendshapeValue[n_target_blendshapes];
            // We iterate over the targets and accumulate all sources to them
            for (int index = 0; index < n_target_blendshapes; index++)
            {
                double value       = 0.0;
                int    value_count = 0;
                for (int mapping_nr = 0; mapping_nr < retargeting.get_number_of_blendshape_mappings(); mapping_nr++)
                {
                    string mapping_target = retargeting.get_blendshape_mapping_destination(mapping_nr);
                    if (!mapping_target.Equals(((BlendshapeInfo)target_blendshapes[index]).m_name))
                    {
                        continue;
                    }
                    string mapping_src = retargeting.get_blendshape_mapping_source(mapping_nr);
                    int    src_index   = rig.shape_index(mapping_src);
                    if (src_index >= 0)
                    {
                        double mapping_weight = retargeting.get_blendshape_mapping_weight(mapping_nr);
                        value += state.blendshape_coefficient(src_index) * mapping_weight;
                        value_count++;
                    }
                    else
                    {
                        Debug.Log("Could not find source blend shape '" + mapping_src);
                    }
                }
                // Apply the value for this target
                if (value_count > 0)
                {
                    values[index] = new BlendshapeValue(value);
                }
            }
            return(values);
        }
        /// <summary>
        /// Performs faceshift live tracking animation given a rig and a state.
        /// </summary>
        public void UpdateAnimation(Rig rig, RigState state)
        {
            if (rig == null || state == null)
            {
                return;
            }

            // evaluate joint transformations
            TransformationValue [] transformationsTracking = null;
            if (m_TPose != null && m_TPose.m_joints.Count == m_GameObjectTransformations.Count)
            {
                // evaluate using tpose
                transformationsTracking = Utils.EvaluateTargetTransformations(m_Retargeting, rig, state, m_TPose.m_joints);
            }
            else
            {
                // evaluate using state from start of application
                transformationsTracking = Utils.EvaluateTargetTransformations(m_Retargeting, rig, state, m_GameObjectTransformations);
            }

            if (transformationsTracking != null)
            {
                if (!ApplyTransformations(transformationsTracking, 1.0f))
                {
                    Debug.LogError("Cannot apply tracking transformations as evaluated shape size is incorrect");
                }
            }

            if (state != null)
            {
                BlendshapeValue [] blendshapesTracking = Utils.EvaluateTargetBlendshapes(m_Retargeting, rig, state, m_GameObjectBlendshapes);
                if (!ApplyBlendshapes(blendshapesTracking, 1.0f))
                {
                    Debug.LogError("Cannot apply tracking blendshapes as the number of blendshapes is not the same");
                }
            }
        }
示例#9
0
        /**
         * @brief Reads an fsb file and returns a clip constructed from the the content of the fsb file.
         * @param[in] filename  The filename of the fsb file.
         * @return A clip with the track data imported from the fsb file, null if there was some error during loading.
         */
        public static Clip read(string filename)
        {
            if (!File.Exists(filename))
            {
                return(null);
            }

            FileStream fileReader = File.OpenRead(filename);
            int        size       = (int)fileReader.Length;

            byte [] data      = new byte[size];
            int     size_read = fileReader.Read(data, 0, size);

            if (size != size_read)
            {
                Debug.LogError("Reading file unsuccessful: read " + size_read + " bytes instead of " + size + " bytes");
                return(null);
            }

            DataParser parser = new DataParser();

            parser.ExtractData(data);

            if (parser.Valid())
            {
                Rig rig = new Rig();

                // add hardcoded bone names of fsb file
                rig.add_bone("Neck");
                rig.add_bone("EyeLeft");
                rig.add_bone("EyeRight");

                for (int i = 0; i < parser.fsBlendShapeNames.Length; i++)
                {
                    rig.add_shape(parser.fsBlendShapeNames[i]);
                }

                Clip clip = new Clip(rig);

                while (parser.CountAvailableTracks() > 0)
                {
                    TrackData track_data = parser.Dequeue();

                    if (!track_data.TrackSuccess)
                    {
                        // do not save the state if the tracking data is not valid
                        Debug.LogWarning("this frame doesn't contain valid tracking data");
                        continue;
                    }

                    RigState state = clip.new_state(track_data.TimeStamp);

                    if (rig.num_shapes() != track_data.n_coefficients())
                    {
                        Debug.LogError("num blendshapes do not agree in file with " + rig.num_shapes() +
                                       " in rig and " + track_data.n_coefficients() + " in state");
                        return(null);
                    }

                    // Assume the head translation to be joint 0 (Neck)
                    state.set_bone_translation(0, track_data.HeadTranslation());

                    // bone indices same as the order when added to the rig
                    state.set_bone_rotation(0, track_data.HeadRotation());
                    state.set_bone_rotation(1, track_data.LeftEyeRotation());
                    state.set_bone_rotation(2, track_data.RightEyeRotation());

                    for (int i = 0; i < track_data.n_coefficients(); i++)
                    {
                        state.set_blendshape_coefficient(i, track_data.Coefficient[i]);
                    }
                }

                return(clip);
            }
            else
            {
                Debug.LogError("cannot parse fsb file");
            }

            return(null);
        }
示例#10
0
        /**
         * @brief Reads an fsb file and returns a clip constructed from the the content of the fsb file.
         * @param[in] data  The binary data from the fsb file.
         * @return A clip with the track data imported from the fsb file, null if there was some error during loading.
         */
        public static Clip Read(byte[] data)
        {
            DataParser parser = new DataParser();

            parser.ExtractData(data, false, 0.0);

            if (parser.Valid())
            {
                Rig rig = new Rig();

                // add hardcoded bone names of fsb file
                rig.AddBone("Neck");
                rig.AddBone("EyeLeft");
                rig.AddBone("EyeRight");

                for (int i = 0; i < parser.fsBlendShapeNames.Length; i++)
                {
                    rig.AddShape(parser.fsBlendShapeNames[i]);
                }

                Clip clip = new Clip(rig);

                while (parser.CountAvailableTracks() > 0)
                {
                    TrackData track_data = parser.Dequeue();

                    if (!track_data.TrackSuccess)
                    {
                        // do not save the state if the tracking data is not valid
                        Debug.LogWarning("this frame doesn't contain valid tracking data");
                        continue;
                    }

                    RigState state = clip.NewState(track_data.TimeStamp);

                    state.SetTrackingSuccessful(track_data.TrackSuccess);

                    if (rig.NumShapes() != track_data.n_coefficients())
                    {
                        Debug.LogError("num blendshapes do not agree in file with " + rig.NumShapes() +
                                       " in rig and " + track_data.n_coefficients() + " in state");
                        return(null);
                    }

                    // Assume the head translation to be joint 0 (Neck)
                    state.SetBoneTranslation(0, track_data.HeadTranslation());

                    // bone indices same as the order when added to the rig
                    state.SetBoneRotation(0, track_data.HeadRotation());
                    state.SetBoneRotation(1, track_data.LeftEyeRotation());
                    state.SetBoneRotation(2, track_data.RightEyeRotation());

                    for (int i = 0; i < track_data.n_coefficients(); i++)
                    {
                        state.SetBlendshapeCoefficient(i, track_data.Coefficient[i]);
                    }
                }

                return(clip);
            }
            else
            {
                Debug.LogError("cannot parse fsb file");
            }

            return(null);
        }
示例#11
0
        /**
         *	Evaluates the target transformation based on the state of a rig and a retargeting configuration.
         *  If a transform is not affected by the retargeting then the value of the transform is null.
         */
        public static TransformationValue [] evaluate_target_transformations(ClipRetargeting retargeting,
                                                                             Rig rig,
                                                                             RigState state,
                                                                             ArrayList target_transformations)
        {
            if (retargeting == null || rig == null || state == null || target_transformations == null)
            {
                Debug.LogError("cannot evaluat target transformations as one or more object is null");
                return(null);
            }

            int n_target_transformations = target_transformations.Count;

            TransformationValue [] values = new TransformationValue[n_target_transformations];
            // We iterate over the target transformations and accumulate all sources to them
            for (int target_nr = 0; target_nr < target_transformations.Count; target_nr++)
            {
                // get original rotation and translation from tpose
                TransformationInformation tpose_joint = target_transformations[target_nr] as TransformationInformation;
                if (tpose_joint == null)
                {
                    Debug.LogError("joint " + target_nr + " is null");
                    continue;
                }
                Vector3    tpose_translation            = tpose_joint.localPosition;
                Quaternion tpose_local_rotation         = tpose_joint.localRotation;
                Quaternion tpose_parent_global_rotation = tpose_joint.parentRotation;

                Quaternion fs_joint_rotation_local_from_t_pose    = Quaternion.identity;
                Vector3    fs_joint_translation_local_from_t_pose = new Vector3(0, 0, 0);

                // Sum the translation to apply
                int value_count_trans = 0;
                for (int mapping_nr = 0; mapping_nr < retargeting.get_number_of_translation_mappings(); mapping_nr++)
                {
                    string mapping_target = retargeting.get_translation_mapping_destination(mapping_nr);
                    if (!mapping_target.Equals(tpose_joint.transformName))
                    {
                        continue;
                    }
                    string mapping_src = retargeting.get_translation_mapping_source(mapping_nr);
                    int    src_index   = rig.bone_index(mapping_src);
                    if (src_index >= 0)
                    {
                        double mapping_weight = retargeting.get_translation_mapping_weight(mapping_nr);
                        fs_joint_translation_local_from_t_pose += state.bone_translation(src_index) * (float)mapping_weight;
                        value_count_trans++;
                    }
                    else
                    {
                        Debug.Log("Could not find source index for '" + mapping_src + "'");
                    }
                }

                // Convert translation to global translation
                //Vector3 unity_joint_translation_local = fs_joint_translation_local_from_t_pose + tpose_translation;
                Vector3 unity_joint_translation_local =
                    Quaternion.Inverse(tpose_parent_global_rotation) * fs_joint_translation_local_from_t_pose
                    + tpose_translation;

                // Sum the rotations to apply
                int value_count_rot = 0;
                for (int mapping_nr = 0; mapping_nr < retargeting.get_number_of_rotation_mappings(); mapping_nr++)
                {
                    string mapping_target = retargeting.get_rotation_mapping_destination(mapping_nr);
                    if (!mapping_target.Equals(tpose_joint.transformName))
                    {
                        continue;
                    }
                    string mapping_src = retargeting.get_rotation_mapping_source(mapping_nr);
                    int    src_index   = rig.bone_index(mapping_src);
                    if (src_index >= 0)
                    {
                        double mapping_weight = retargeting.get_rotation_mapping_weight(mapping_nr);

                        // use slerp for weighting
                        fs_joint_rotation_local_from_t_pose = Quaternion.Slerp(Quaternion.identity, state.bone_rotation(src_index), (float)mapping_weight);
                        // TODO: here we should accumulate if there are more than one sources (like with blendshapes)
                        value_count_rot++;
                    }
                    else
                    {
                        Debug.Log("Could not find source rotation for '" + mapping_src);
                    }
                }

                // Convert to local unity rotation
                Quaternion unity_joint_rotation_local =
                    Quaternion.Inverse(tpose_parent_global_rotation)
                    * fs_joint_rotation_local_from_t_pose
                    * tpose_parent_global_rotation
                    * tpose_local_rotation;                                     // The initial local rotation;

                if (value_count_trans > 0 || value_count_rot > 0)
                {
                    values[target_nr] = new TransformationValue(unity_joint_rotation_local, unity_joint_translation_local);
                }
            }

            return(values);
        }
示例#12
0
	    /**
	     * @brief Creates a new state and adds it to this clip.
	     * @param[in] timestamp    The timestamp for this new state.
	     * @return The newly created state.
	     */
	    public RigState NewState(double timestamp) {
	        RigState state = new RigState(m_rig);
	        state.SetTimestamp(timestamp);
	        m_states.Add(state);
	        return state;
	    }
示例#13
0
        void Update()
        {
            // ten kod kalkuluje bazowa pozycje glowy
            // trzeba jeszcze dorobic zeby przechwytywal trigerra
            // i wtedy zmieniał isBaseCalculated na false
            // i resetował timer i kalkulował jeszcze raz
            // pozniej trzeba jeszcze dodac zeby kazda metoda zwracała
            // to co zwraca minus base
            if (!isBaseCalculated)
            {
                timer += Time.deltaTime;
                if (timer < baseCalculationTime)
                {
                    if (getXHeadRotation() != -1)
                    {
                        baseX += getXHeadRotation();
                        ticksX++;
                    }

                    if (getYHeadRotation() != -1)
                    {
                        baseY += getYHeadRotation();
                        ticksY++;
                    }
                }
                else
                {
                    baseX           /= ticksX;
                    baseY           /= ticksY;
                    isBaseCalculated = true;
                }
            }


            new_data = false;
            m_mutex.WaitOne();
            // check if there are new blendshape names, and if so update
            if (newBlendShapeNamesArrived())
            {
                m_rig = getRigFromBlendShapeNames(getBlendShapeNames());
            }

            // get most recent tracking data
            while (m_data_parser.CountAvailableTracks() > 0)
            {
                m_current_track = m_data_parser.Dequeue();
                new_data        = true;
            }

            // check that we have a rig (set up from blendshape names) with the same number of blendshapes as what we receive
            if (m_rig != null && m_current_track != null)
            {
                int n_track_coefficients = m_current_track.n_coefficients();
                int n_rig_coefficients   = m_rig.num_shapes();
                if (n_track_coefficients != n_rig_coefficients)
                {
                    Debug.LogWarning("number of coefficients of rig and tracking state have changed: " + n_track_coefficients + " vs " + n_rig_coefficients);
                    // clear the current rig as it is not usable with the data coming from faceshift
                    m_rig           = null;
                    m_current_track = null;
                    // get again the blendshapes from fs studio
                    askForBlendshapeNames();
                }
            }
            m_mutex.ReleaseMutex();

            if (m_rig != null && m_current_track != null && m_retargeting != null)
            {
                if (new_data && m_current_track.TrackSuccess)
                {
                    // create a rig state
                    RigState state = new RigState(m_rig);
                    state.set_timestamp(m_current_track.TimeStamp);
                    state.set_bone_translation(0, m_current_track.HeadTranslation());
                    state.set_bone_rotation(0, m_current_track.HeadRotation());
                    state.set_bone_rotation(1, m_current_track.LeftEyeRotation());
                    state.set_bone_rotation(2, m_current_track.RightEyeRotation());

                    for (int i = 0; i < m_rig.num_shapes(); i++)
                    {
                        state.set_blendshape_coefficient(i, m_current_track.Coefficient [i]);
                    }

                    // evaluate joint transformations
                    TransformationValue [] transformation_values = null;
                    if (m_tpose != null && m_tpose.m_joints.Count == m_game_object_transformations.Count)
                    {
                        // evaluate using tpose
                        transformation_values = Utils.evaluate_target_transformations(m_retargeting, m_rig, state, m_tpose.m_joints);
                    }
                    else
                    {
                        // evaluate using state from start of application
                        transformation_values = Utils.evaluate_target_transformations(m_retargeting, m_rig, state, m_game_object_transformations);
                    }

                    if (transformation_values.Length == m_game_object_transformations.Count)
                    {
                        for (int index = 0; index < transformation_values.Length; index++)
                        {
                            // Apply the value for this target
                            if (transformation_values [index] != null)
                            {
                                TransformationInformation joint = m_game_object_transformations [index] as TransformationInformation;
                                joint.transform.localRotation = transformation_values [index].m_rotation;
                                joint.transform.localPosition = transformation_values [index].m_translation;
                            }
                        }
                    }
                    else
                    {
                        Debug.LogError("Cannot create transformation as evaluated shape size is incorrect");
                    }

                    // evaluate blendshape valuesf
                    BlendshapeValue [] values = Utils.evaluate_target_blendshapes(m_retargeting, m_rig, state, m_game_object_blendshapes);

                    if (values.Length == m_game_object_blendshapes.Count)
                    {
                        for (int index = 0; index < m_game_object_blendshapes.Count; index++)
                        {
                            BlendshapeInfo bs_info = m_game_object_blendshapes [index] as BlendshapeInfo;
                            // Apply the value for this target
                            if (bs_info != null && values [index] != null)
                            {
                                bs_info.m_mesh_renderer.SetBlendShapeWeight(bs_info.m_index, (float)values [index].m_value);
                            }
                        }
                    }
                    else
                    {
                        Debug.LogError("Cannot create blendshapes as evaluated shape size is incorrect");
                    }
                }
            }
        }
示例#14
0
		/**
		 *	Evaluates the target transformation based on the state of a rig and a retargeting configuration.
		 *  If a transform is not affected by the retargeting then the value of the transform is null.
		 */
		public static TransformationValue [] EvaluateTargetTransformations(ClipRetargeting retargeting,
		                                                       Rig rig,
		                                                       RigState state,
		                                                       ArrayList target_transformations) {
		                                                       
			if (retargeting == null || rig == null || state == null || target_transformations == null) {
				Debug.LogError("cannot evaluat target transformations as one or more object is null");
				return null;
			}
			
			int n_target_transformations = target_transformations.Count;
			TransformationValue [] values = new TransformationValue[n_target_transformations];
			// We iterate over the target transformations and accumulate all sources to them
			for (int target_nr = 0; target_nr < target_transformations.Count; target_nr++) {
				
				// get original rotation and translation from tpose
				TransformationInformation tpose_joint = target_transformations[target_nr] as TransformationInformation;
				if (tpose_joint == null) {
					Debug.LogError("joint " + target_nr + " is null");
					continue;
				}
				Vector3 tpose_translation               = tpose_joint.localPosition;
				Quaternion tpose_local_rotation         = tpose_joint.localRotation;
				Quaternion tpose_parent_global_rotation = tpose_joint.parentRotation;
				
				Quaternion fs_joint_rotation_local_from_t_pose = Quaternion.identity;
				Vector3 fs_joint_translation_local_from_t_pose = new Vector3(0, 0, 0);
				
				// Sum the translation to apply
				int value_count_trans = 0;
				for (int mapping_nr = 0; mapping_nr < retargeting.GetNumberOfTranslationMappings(); mapping_nr++) {
					string mapping_target = retargeting.GetTranslationMappingDestination (mapping_nr);
					if (!mapping_target.Equals(tpose_joint.transformName)) {
						continue;
					}
					string mapping_src = retargeting.GetTranslationMappingSource (mapping_nr);
					int src_index = rig.BoneIndex (mapping_src);
					if (src_index >= 0) {
						double mapping_weight = retargeting.GetTranslationMappingWeight (mapping_nr);
						fs_joint_translation_local_from_t_pose += state.BoneTranslation (src_index) * (float)mapping_weight;
						value_count_trans++;
					} else {
						Debug.Log ("Could not find source index for '" + mapping_src + "'");
					}
				} 
				
				// Convert translation to global translation
				//Vector3 unity_joint_translation_local = fs_joint_translation_local_from_t_pose + tpose_translation;
				Vector3 unity_joint_translation_local = 
					Quaternion.Inverse(tpose_parent_global_rotation) * fs_joint_translation_local_from_t_pose
					+ tpose_translation;
						
				// Sum the rotations to apply
				int value_count_rot = 0;
				for (int mapping_nr = 0; mapping_nr < retargeting.GetNumberOfRotationMappings(); mapping_nr++) {
					string mapping_target = retargeting.GetRotationMappingDestination (mapping_nr);
					if (!mapping_target.Equals (tpose_joint.transformName)) {
						continue;
					}
					string mapping_src = retargeting.GetRotationMappingSource (mapping_nr);
					int src_index = rig.BoneIndex (mapping_src);
					if (src_index >= 0) {
						double mapping_weight = retargeting.GetRotationMappingWeight (mapping_nr);
						
						// use slerp for weighting
						fs_joint_rotation_local_from_t_pose = Quaternion.Slerp (Quaternion.identity, state.BoneRotation (src_index), (float)mapping_weight);
						// TODO: here we should accumulate if there are more than one sources (like with blendshapes)
						value_count_rot++;
					} else {
						Debug.Log ("Could not find source rotation for '" + mapping_src);
					}
				} 
				
				// Convert to local unity rotation
				Quaternion unity_joint_rotation_local = 
						Quaternion.Inverse(tpose_parent_global_rotation) 
					 		* fs_joint_rotation_local_from_t_pose 
							* tpose_parent_global_rotation
							* tpose_local_rotation; // The initial local rotation;

				if (value_count_trans > 0 || value_count_rot > 0) {
					values[target_nr] = new TransformationValue(unity_joint_rotation_local, unity_joint_translation_local);
				}
			}
			
			return values;
		}
示例#15
0
		/**
		 *	Evaluates the target blendshape values based on the state of a rig and a retargeting configuration.
		 *  If a blendshape is not affected by the retargeting then the value of this blendshape is null.
		 */
		public static BlendshapeValue [] EvaluateTargetBlendshapes(ClipRetargeting retargeting,
						                                             Rig rig,
						                                             RigState state,
						                                             ArrayList target_blendshapes) {
						                                             
			int n_target_blendshapes = target_blendshapes.Count;
			BlendshapeValue [] values = new BlendshapeValue[n_target_blendshapes];
			// We iterate over the targets and accumulate all sources to them
			for (int index = 0; index < n_target_blendshapes; index++) {
				double value = 0.0;
				int value_count = 0;
				for (int mapping_nr = 0; mapping_nr < retargeting.GetNumberOfBlendshapeMappings(); mapping_nr++) {
					string mapping_target = retargeting.GetBlendshapeMappingDestination(mapping_nr);
					if (!mapping_target.Equals(((BlendshapeInfo)target_blendshapes[index]).m_name)) {
						continue;
					}
					string mapping_src = retargeting.GetBlendshapeMappingSource(mapping_nr);
					int src_index = rig.ShapeIndex(mapping_src);
					if (src_index >= 0) {
						double mapping_weight = retargeting.GetBlendshapeMappingWeight(mapping_nr);
						value += state.BlendshapeCoefficient(src_index) * mapping_weight;
						value_count++;
					} else {
						Debug.Log("Could not find source blend shape '" + mapping_src);
					}
				} 
				// Apply the value for this target
				if (value_count > 0) {
					values[index] = new BlendshapeValue(value);
				}
			}
			return values;
		}
		/// <summary>
		/// Performs faceshift live tracking animation given a rig and a state.
		/// </summary>
		public void UpdateAnimation(Rig rig, RigState state) {
			
			if (rig == null || state == null) return;
			
			// evaluate joint transformations
			TransformationValue [] transformationsTracking = null;
			if (m_TPose != null && m_TPose.m_joints.Count == m_GameObjectTransformations.Count) {
				// evaluate using tpose
				transformationsTracking = Utils.EvaluateTargetTransformations(m_Retargeting, rig, state, m_TPose.m_joints);
			} else {
				// evaluate using state from start of application
				transformationsTracking = Utils.EvaluateTargetTransformations(m_Retargeting, rig, state, m_GameObjectTransformations);
			}
	
			if (transformationsTracking != null) {
				if (!ApplyTransformations(transformationsTracking, 1.0f)) {
					Debug.LogError("Cannot apply tracking transformations as evaluated shape size is incorrect");
				}
			}
	
			if (state != null) {
				BlendshapeValue [] blendshapesTracking = Utils.EvaluateTargetBlendshapes(m_Retargeting, rig, state, m_GameObjectBlendshapes);
				if (!ApplyBlendshapes(blendshapesTracking, 1.0f)) {
					Debug.LogError("Cannot apply tracking blendshapes as the number of blendshapes is not the same");
				}
			}
		}