/// <summary> /// Generate the points for SLAM initialization that the user has to look at. /// TODO: If we go with the current version, only one point will be needed. If we go with the arrow version, all points are needed. /// </summary> private void Start() { // build all slam init points for the specified angle and step settings // "halfCircleCount * 2" pieces for "fromAngle" to "toAngle" // save them in an array // then do calibration fromIndex toIndex and use these points (activate/deactivate/show correct graphics/animation/light) _slamLocalizer = FindObjectOfType <SlamLocalizer>(); if (eyeCamera == null) { eyeCamera = GameObject.Find("StereoCameras").transform; } if (eyeCamera == null) { Debug.LogError("Couldn't find stereo cameras!"); } particles.gameObject.SetActive(false); leftArrows.gameObject.SetActive(useDirectionArrows); rightArrows.gameObject.SetActive(useDirectionArrows); var pointCount = useArrowAnimation ? stepCountHalfCircle * 2 : 1; pointCount = Mathf.RoundToInt(useArrowAnimation ? (stepCountHalfCircle * 2) : 1); _points = new SLAMInitializationGazePoint[pointCount]; for (int i = 0; i < pointCount; i++) { var angle = Mathf.Lerp(-180, 180, (float)i / (pointCount + 1)); SLAMInitializationGazePoint gazePoint = Instantiate(slamInitPrefab); gazePoint.EyeCamera = eyeCamera; gazePoint.transform.parent = transform; gazePoint.transform.localPosition = Vector3.zero; gazePoint.transform.localRotation = Quaternion.Euler(0, angle, 0); gazePoint.requiredLookAtTime = lookAtTime; // initialize and hide these points // in non-arrow mode, they are invisible anyways gazePoint.direction = 1; gazePoint.Activate(false); gazePoint.number = i; gazePoint.slamUI = this; _points[i] = gazePoint; } }
/// <summary> /// Shows multiple points at the same time and animates their blinking. /// </summary> private IEnumerator CalibrateDirectional_Arrows(int fromIndex, int toIndex) { timeSinceLastPoint = 0; direction = fromIndex > toIndex ? -1 : 1; if (useDirectionArrows && leftArrows && rightArrows) { leftArrows.SetBool("IsOn", direction > 0); rightArrows.SetBool("IsOn", direction < 0); } int i = fromIndex; while (i != toIndex) { Debug.Log("waiting for point " + i); SLAMInitializationGazePoint pCurrent = _points[i]; pCurrent.direction = -direction; pCurrent.allowGazing = true; pCurrent.Init(); pCurrent.Activate(true); currentTarget = pCurrent.r.transform; // wait until this point is detected (looked at for a minimum time set in the point prefab) while (pCurrent.isActive) { Debug.DrawLine(Vector3.zero, pCurrent.r.transform.position, Color.green); // check for early-out if slam calibration is fully done already if (CheckForSLAMInitComplete()) { timeSinceLastPoint = 0; yield break; } timeSinceLastPoint += Time.unscaledDeltaTime; yield return(null); } timeSinceLastPoint = 0; i += direction; } // wait for points to fade out }
/// <summary> /// Activates a single (invisible) point at a time and moves that around to have the user look at it. /// </summary> IEnumerator CalibrateDirectional_SinglePoint(int fromIndex, int toIndex) { timeSinceLastPoint = 0; direction = fromIndex > toIndex ? -1 : 1; leftArrows.SetBool("IsOn", direction > 0); rightArrows.SetBool("IsOn", direction < 0); int i = fromIndex; while (i != toIndex) { SLAMInitializationGazePoint pCurrent = _points[0]; // set point rotation var angle = Mathf.Lerp(fromAngle, toAngle, (float)i / (stepCountHalfCircle * 2 + 1)); pCurrent.transform.localRotation = Quaternion.Euler(0, angle, 0); // set up point for gazing pCurrent.direction = -direction; pCurrent.allowGazing = true; pCurrent.Init(); pCurrent.Activate(true); currentTarget = pCurrent.r.transform; // wait until point has been gazed at for long enough while (pCurrent.isActive) { // check for early-out if slam calibration is fully done already if (CheckForSLAMInitComplete()) { timeSinceLastPoint = 0; yield break; } timeSinceLastPoint += Time.unscaledDeltaTime; yield return(null); } timeSinceLastPoint = 0; i += direction; } }