// Update is called once per frame void Update() { var time = Time.time - startTime; int keyFrame = -1; if (playback) { keyFrame = GetCurrentKeyFrame(); if (pauseKeyFrame) { keyFrame = lastKeyFrame; } lastKeyFrame = keyFrame; //This one allows to get an array of vectors positions of the trackers wanted from PhaseSpace for (int i = 0; i < markerIds.Length; i++) { string id = markerIds[i]; int j = markerUI.marker_alias_to_ids[id]; if (!float.IsNaN(mocapCaptureData[keyFrame].position[i].x)) { markerPositions[id] = mocapCaptureData[keyFrame].position[i]; markerUI.marker_positions[j, 0] = -markerPositions[markerIds[i]].x; markerUI.marker_positions[j, 1] = markerPositions[markerIds[i]].y; markerUI.marker_positions[j, 2] = markerPositions[markerIds[i]].z; } else { markerPositions[id] = mocapCaptureData[keyFrame].position[i]; markerUI.marker_positions[j, 0] = float.NaN; markerUI.marker_positions[j, 1] = float.NaN; markerUI.marker_positions[j, 2] = float.NaN; } } } else { mocapCaptureData.Clear(); keyFrame = mocapCaptureData.Count; for (int i = 0; i < markerIds.Length; i++) { Vector3 pos; markerUI.GetMarkerPosition(markerIds[i], out pos); markerPositions[markerIds[i]] = pos; } MocapSample sM = new MocapSample(time, markerPositions.Count); for (int i = 0; i < handTemplate.MarkerList.Count; i++) { sM.position[i] = markerPositions[handTemplate.MarkerList[i]]; sM.isValid[i] = !float.IsNaN(markerPositions[handTemplate.MarkerList[i]].x); } mocapCaptureData.Add(sM); } for (int i = 0; i < markerIds.Length; i++) { // Keyboard buttons [0-9] simulate sensor occlusion bool overrideMarker = Input.GetKey((KeyCode)((int)KeyCode.Alpha1 + i)); if (overrideMarker) { string id = markerIds[i]; int j = markerUI.marker_alias_to_ids[id]; markerPositions[id] = new Vector3(float.NaN, float.NaN, float.NaN); markerUI.marker_positions[j, 0] = float.NaN; markerUI.marker_positions[j, 1] = float.NaN; markerUI.marker_positions[j, 2] = float.NaN; } } // Reset initial orientations foreach (var m in Constants.NodesToExport) { var transform = GameObject.Find(m).transform; transform.localRotation = Quaternion.identity; } if (!playback) { // No input data available return; } occlusionManager.Update(markerPositions, Time.deltaTime); if (!jointPredictions) { FusedSample s = fusedCaptureData[keyFrame]; for (int i = 0; i < s.position.Length; i++) { var obj = GameObject.Find(Constants.NodesToExport[i]); Vector3 rot = s.orientation[i]; obj.transform.localRotation = Quaternion.Euler(rot); } } else { var output = jointPredictor.Predict(markerPositions); foreach (var joint in output) { GameObject.Find(joint.Key).transform.localRotation = joint.Value; } } List <int> nanIndices = new List <int>(); foreach (var marker in markerPositions) { int j = markerUI.marker_alias_to_ids[marker.Key]; if (double.IsNaN(markerUI.marker_positions[j, 0])) { nanIndices.Add(j); } markerUI.marker_positions[j, 0] = -marker.Value.x; markerUI.marker_positions[j, 1] = marker.Value.y; markerUI.marker_positions[j, 2] = marker.Value.z; } if (drawMarkers) { markerUI.RenderMarkers(); } foreach (int i in nanIndices) { markerUI.marker_spheres[i].GetComponent <Renderer>().material.color = Color.red; } // Pose estimation: move the hand template towards the markers var X = new List <Vector3>(); var Y = new List <Vector3>(); foreach (var markerId in handTemplate.AlignmentMarkerList) { Transform tBone = GameObject.Find(handTemplate.GetJointName(markerId)).transform; var pos = tBone.TransformPoint(handTemplate.GetMarkerOffset(markerId)); // Add offset X.Add(pos); var posTarget = markerPositions[markerId]; Y.Add(posTarget); } double[,] R; double[] offset; HandTracking.Utils.ComputeRigidMotion(X, Y, out R, out offset); HandTracking.Utils.RotateAndShift(GameObject.Find(Constants.ElbowBone).transform, R, offset); // Post-processing: align finger directions if (postProcessing && jointPredictions) { for (int i = 0; i < Constants.FingerTips.Length; i++) { var tipJoint = GameObject.Find(Constants.FingerTips[i]).transform; var baseJoint = tipJoint.parent.parent.parent; Vector3 targetPosition = markerPositions[handTemplate.GetMarkerId(Constants.FingerTips[i])]; if (!float.IsNaN(targetPosition.x)) { HandTracking.Utils.AlignDirections(baseJoint, tipJoint.position, targetPosition); } } } // Focus on the hand Camera.main.transform.LookAt(GameObject.Find(Constants.WristBone).transform.position); float scroll = Input.GetAxis("Mouse ScrollWheel"); Camera.main.fieldOfView -= scroll * 10; }
void OnGUI() { if (!playback) { if (GUILayout.Button("Play recording")) { string path = UnityEditor.EditorUtility.OpenFilePanel("Select dump", Constants.OutputDirectory, "csv"); if (path != null && path.Length > 0) { path = path.Replace("mocap", "***").Replace("neuron", "***").Replace("fused", "***"); Debug.Log("Loading recording from disk..."); mocapCaptureData = MocapSample.Import(path.Replace("***", "mocap")); fusedCaptureData = FusedSample.Import(path.Replace("***", "fused")); Debug.Log("Playing..."); playback = true; startTime = Time.time; } } } else if (playback) { if (GUILayout.Button("Stop playback")) { Debug.Log("Stopped."); playback = false; } pauseKeyFrame = GUILayout.Toggle(pauseKeyFrame, "Pause current key frame"); } if (playback) { float time; int keyFrame; keyFrame = GetCurrentKeyFrame(); time = mocapCaptureData[keyFrame].time - mocapCaptureData[0].time; GUILayout.Label("Time: " + Math.Round(time, 2) + " s"); GUILayout.Label("Key frame: " + keyFrame); } drawMarkers = GUILayout.Toggle(drawMarkers, "Draw markers"); if (!drawMarkers) { for (int i = 0; i < markerUI.marker_positions.GetLength(0); i++) { for (int j = 0; j < markerUI.marker_positions.GetLength(1); j++) { markerUI.marker_positions[i, j] = -1000; } } markerUI.RenderMarkers(); } jointPredictions = GUILayout.Toggle(jointPredictions, "Prediction mode"); if (!jointPredictions) { GUILayout.Label("Displaying raw dataset"); } else { GUILayout.Label("Displaying NN predictions"); } if (jointPredictions) { GUILayout.Label("Occlusion prediction:"); bool opt0 = predictionMode == 0; bool opt1 = predictionMode == 1; bool opt2 = predictionMode == 2; bool opt3 = predictionMode == 3; opt0 = GUILayout.Toggle(opt0, "None (last position)"); opt1 = GUILayout.Toggle(opt1, "Moving average"); opt2 = GUILayout.Toggle(opt2, "Affine combination"); opt3 = GUILayout.Toggle(opt3, "Neural network"); int newPredictionMode = 0; if (opt0 && predictionMode != 0) { newPredictionMode = 0; } else if (opt1 && predictionMode != 1) { newPredictionMode = 1; } else if (opt2 && predictionMode != 2) { newPredictionMode = 2; } else if (opt3 && predictionMode != 3) { newPredictionMode = 3; } else { newPredictionMode = predictionMode; } if (newPredictionMode != predictionMode) { occlusionManager.RemoveAllImplementations(); switch (newPredictionMode) { case 0: occlusionManager.AddImplementation(new NaiveOcclusionPredictor()); break; case 1: occlusionManager.AddImplementation(new MovingAverageOcclusionPredictor(20, handTemplate)); break; case 2: occlusionManager.AddImplementation(new LinearOcclusionPredictor()); break; case 3: occlusionManager.AddImplementation(new NeuralOcclusionPredictor("models/marker_model.bin", handTemplate, true, true)); break; } } predictionMode = newPredictionMode; if (predictionMode > 0) { GUILayout.Label(""); postProcessing = GUILayout.Toggle(postProcessing, "Post-processing"); } GUILayout.Label("Use keyboard [1-9]\nto simulate occlusions."); } }