/// <summary> /// Applies the joint transformations given an influence factor /// </summary> /// <returns><c>true</c>, if transformations could be applied, <c>false</c> otherwise.</returns> /// <param name="transformationsToSet">The set of transformations to apply</param> /// <param name="influence">The factor to apply the transformations. 0.0 means that they are not used at all and the current /// animations are not changed. 1.0 means that they are fully used.</param> protected bool ApplyTransformations(TransformationValue [] transformationsToSet, float influence) { if (transformationsToSet.Length != m_GameObjectTransformations.Count) { return(false); } for (int index = 0; index < m_GameObjectTransformations.Count; index++) { // Apply the value for this target if (transformationsToSet[index] != null) { TransformationInformation joint = m_GameObjectTransformations[index] as TransformationInformation; joint.transform.localRotation = Quaternion.Slerp(joint.transform.localRotation, transformationsToSet[index].m_rotation, influence); joint.transform.localPosition = (1.0f - influence) * joint.transform.localPosition + influence * transformationsToSet[index].m_translation; } } return(true); }
/** * Adds all possible transformation targets of the game object * curGameObject and its sub-objects (recursively) to the * list of target transformations. */ public static void getGameObjectTransformations(GameObject curGameObject, ArrayList transformations) { if (transformations != null) { transformations.Clear(); } // Iterate over game object itself and over children and add blendshapes Transform [] children = curGameObject.GetComponentsInChildren <Transform>(); foreach (Transform child in children) { string transformPath = calculateTransformPath(child, curGameObject.transform); if (transformations != null) { TransformationInformation transform_copy = new TransformationInformation(); transform_copy.rotation = new Quaternion(child.rotation.x, child.rotation.y, child.rotation.z, child.rotation.w); transform_copy.localRotation = new Quaternion(child.localRotation.x, child.localRotation.y, child.localRotation.z, child.localRotation.w); transform_copy.position = new Vector3(child.position.x, child.position.y, child.position.z); transform_copy.localPosition = new Vector3(child.localPosition.x, child.localPosition.y, child.localPosition.z); if (child.parent != null) { transform_copy.parentRotation = new Quaternion(child.parent.rotation.x, child.parent.rotation.y, child.parent.rotation.z, child.parent.rotation.w); //Debug.Log("parent of child " + child.name + " is " + child.parent.name); } else { transform_copy.parentRotation = Quaternion.identity; //Debug.Log("child " + child.name + " has no parent"); } transform_copy.transform = child; transform_copy.transformPath = transformPath; transform_copy.transformName = child.name; transformations.Add(transform_copy); } } }
//! @brief Loads the tpose from a byte array. //! @returns True if load was successful, false otherwise. public bool LoadFromBytes(byte [] data) { if (data == null) { return(false); } // create 2D grid of the file string text = System.Text.Encoding.UTF8.GetString(data); string[,] grid = SplitTPoseFile(text); //Debug.Log("size = " + grid.GetLength(0) + " , " + grid.GetLength (1)); // first row contains version, number of joints int row = 0; int col = 0; Int32 version = 0; try { Convert.ToInt32(grid[row, col + 0]); } catch (Exception) { return(false); } if (version != TPOSE_FILE_VERSION) { return(false); } Int32 number_of_joints = Convert.ToInt32(grid[row, col + 1]); ArrayList new_joints = new ArrayList(); for (int i = 0; i < number_of_joints; i++) { TransformationInformation joint = new TransformationInformation(); int start_row = 1 + 2 * i; joint.rotation.x = (float)Convert.ToDouble(grid[start_row, 0]); joint.rotation.y = (float)Convert.ToDouble(grid[start_row, 1]); joint.rotation.z = (float)Convert.ToDouble(grid[start_row, 2]); joint.rotation.w = (float)Convert.ToDouble(grid[start_row, 3]); joint.localRotation.x = (float)Convert.ToDouble(grid[start_row, 4]); joint.localRotation.y = (float)Convert.ToDouble(grid[start_row, 5]); joint.localRotation.z = (float)Convert.ToDouble(grid[start_row, 6]); joint.localRotation.w = (float)Convert.ToDouble(grid[start_row, 7]); joint.position.x = (float)Convert.ToDouble(grid[start_row, 8]); joint.position.y = (float)Convert.ToDouble(grid[start_row, 9]); joint.position.z = (float)Convert.ToDouble(grid[start_row, 10]); joint.localPosition.x = (float)Convert.ToDouble(grid[start_row, 11]); joint.localPosition.y = (float)Convert.ToDouble(grid[start_row, 12]); joint.localPosition.z = (float)Convert.ToDouble(grid[start_row, 13]); joint.parentRotation.x = (float)Convert.ToDouble(grid[start_row, 14]); joint.parentRotation.y = (float)Convert.ToDouble(grid[start_row, 15]); joint.parentRotation.z = (float)Convert.ToDouble(grid[start_row, 16]); joint.parentRotation.w = (float)Convert.ToDouble(grid[start_row, 17]); joint.transformPath = grid[start_row + 1, 0]; if (grid[start_row + 1, 1] != null) { joint.transformName = grid[start_row + row + 1, 1]; } new_joints.Add(joint); } // Apply m_joints = new_joints; return(true); }
/** * 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); }
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"); } } } }
//! @brief Loads the tpose from a byte array. //! @returns True if load was successful, false otherwise. public bool LoadFromBytes(byte [] data) { if (data == null) return false; // create 2D grid of the file string text = System.Text.Encoding.UTF8.GetString(data); string[,] grid = SplitTPoseFile(text); //Debug.Log("size = " + grid.GetLength(0) + " , " + grid.GetLength (1)); // first row contains version, number of joints int row = 0; int col = 0; Int32 version = 0; try { Convert.ToInt32(grid[row,col+0]); } catch (Exception) { return false; } if (version != TPOSE_FILE_VERSION) { return false; } Int32 number_of_joints = Convert.ToInt32(grid[row,col+1]); ArrayList new_joints = new ArrayList(); for (int i = 0; i < number_of_joints; i++) { TransformationInformation joint = new TransformationInformation(); int start_row = 1 + 2 * i; joint.rotation.x = (float)Convert.ToDouble(grid[start_row, 0]); joint.rotation.y = (float)Convert.ToDouble(grid[start_row, 1]); joint.rotation.z = (float)Convert.ToDouble(grid[start_row, 2]); joint.rotation.w = (float)Convert.ToDouble(grid[start_row, 3]); joint.localRotation.x = (float)Convert.ToDouble(grid[start_row, 4]); joint.localRotation.y = (float)Convert.ToDouble(grid[start_row, 5]); joint.localRotation.z = (float)Convert.ToDouble(grid[start_row, 6]); joint.localRotation.w = (float)Convert.ToDouble(grid[start_row, 7]); joint.position.x = (float)Convert.ToDouble(grid[start_row, 8]); joint.position.y = (float)Convert.ToDouble(grid[start_row, 9]); joint.position.z = (float)Convert.ToDouble(grid[start_row, 10]); joint.localPosition.x = (float)Convert.ToDouble(grid[start_row, 11]); joint.localPosition.y = (float)Convert.ToDouble(grid[start_row, 12]); joint.localPosition.z = (float)Convert.ToDouble(grid[start_row, 13]); joint.parentRotation.x = (float)Convert.ToDouble(grid[start_row, 14]); joint.parentRotation.y = (float)Convert.ToDouble(grid[start_row, 15]); joint.parentRotation.z = (float)Convert.ToDouble(grid[start_row, 16]); joint.parentRotation.w = (float)Convert.ToDouble(grid[start_row, 17]); joint.transformPath = grid[start_row + 1, 0]; if (grid[start_row+1,1] != null) joint.transformName = grid[start_row+row+1, 1]; new_joints.Add(joint); } // Apply m_joints = new_joints; return true; }
/** * Adds all possible transformation targets of the game object * curGameObject and its sub-objects (recursively) to the * list of target transformations. */ public static void GetGameObjectTransformations(GameObject curGameObject, ArrayList transformations) { if (transformations != null) transformations.Clear(); // Iterate over game object itself and over children and add blendshapes Transform [] children = curGameObject.GetComponentsInChildren<Transform>(); foreach (Transform child in children) { string transformPath = CalculateTransformPath(child, curGameObject.transform); if (transformations != null) { TransformationInformation transform_copy = new TransformationInformation(); transform_copy.rotation = new Quaternion(child.rotation.x, child.rotation.y, child.rotation.z, child.rotation.w); transform_copy.localRotation = new Quaternion(child.localRotation.x, child.localRotation.y, child.localRotation.z, child.localRotation.w); transform_copy.position = new Vector3(child.position.x, child.position.y, child.position.z); transform_copy.localPosition = new Vector3(child.localPosition.x, child.localPosition.y, child.localPosition.z); if (child.parent != null) { transform_copy.parentRotation = new Quaternion(child.parent.rotation.x, child.parent.rotation.y, child.parent.rotation.z, child.parent.rotation.w); //Debug.Log("parent of child " + child.name + " is " + child.parent.name); } else { transform_copy.parentRotation = Quaternion.identity; //Debug.Log("child " + child.name + " has no parent"); } transform_copy.transform = child; transform_copy.transformPath = transformPath; transform_copy.transformName = child.name; transformations.Add(transform_copy); } } }