public static void MoveUserBy(Vector3 amount) { TrTransform pose = App.Scene.Pose; pose.translation -= amount; float BoundsRadius = SceneSettings.m_Instance.HardBoundsRadiusMeters_SS; pose = SketchControlsScript.MakeValidScenePose(pose, BoundsRadius); App.Scene.Pose = pose; }
void ApplyVelocity(Vector3 velocity) { TrTransform newScene = App.Scene.Pose; newScene.translation -= velocity; // newScene might have gotten just a little bit invalid. // Enforce the invariant that fly always sends you // to a scene which is MakeValidPose(scene) newScene = SketchControlsScript.MakeValidScenePose(newScene, BoundsRadius); App.Scene.Pose = newScene; }
override public void UpdateTool() { base.UpdateTool(); Transform rAttachPoint = InputManager.m_Instance.GetBrushControllerAttachPoint(); if (m_LockToController) { m_LastParabolaRay.origin = rAttachPoint.position; m_LastParabolaRay.direction = rAttachPoint.forward; m_BadTeleportIcon.transform.position = rAttachPoint.position; m_BadTeleportIcon.transform.rotation = rAttachPoint.rotation; } else { m_LastParabolaRay = ViewpointScript.Gaze; } bool bAimValid = m_LastParabolaRay.direction.y < m_TeleportParabolaMaxY; if (m_TeleportFadeState != TeleportFadeState.FadingToBlack) { bool visible = bAimValid; if (bAimValid) { bool canPlaceParabola = UpdateTool_PlaceParabola(); visible = canPlaceParabola; } else { visible = false; } SetBoundsVisibility(visible); } // Update hide parabola counter. if (!m_HideValidTeleportParabola) { m_TeleportParabolaFadeAmount += m_BoundsEnterSpeed * Time.deltaTime; m_TeleportParabolaFadeAmount = Mathf.Min(m_TeleportParabolaFadeAmount, 1.0f); } else { m_TeleportParabolaFadeAmount -= m_BoundsEnterSpeed * Time.deltaTime; m_TeleportParabolaFadeAmount = Mathf.Max(m_TeleportParabolaFadeAmount, 0.0f); } // Update bad teleport icon scale and visibility. bool bShowBadTeleport = !bAimValid; if (bShowBadTeleport) { if (m_BadTeleportIconEnterAmount < 1.0f) { m_BadTeleportIconEnterAmount += m_BoundsEnterSpeed * Time.deltaTime; m_BadTeleportIconEnterAmount = Mathf.Min(m_BadTeleportIconEnterAmount, 1.0f); m_BadTeleportIcon.transform.localScale = new Vector3(m_BadTeleportIconEnterAmount, m_BadTeleportIconEnterAmount, m_BadTeleportIconEnterAmount); } } else { if (m_BadTeleportIconEnterAmount > 0.0f) { m_BadTeleportIconEnterAmount -= m_BoundsEnterSpeed * Time.deltaTime; m_BadTeleportIconEnterAmount = Mathf.Max(m_BadTeleportIconEnterAmount, 0.0f); m_BadTeleportIcon.transform.localScale = new Vector3(m_BadTeleportIconEnterAmount, m_BadTeleportIconEnterAmount, m_BadTeleportIconEnterAmount); } } m_BadTeleportIcon.gameObject.SetActive(m_BadTeleportIconEnterAmount > 0.0f); // Update teleport fade. if (m_TeleportFadeState != TeleportFadeState.Default) { if (m_TeleportFadeState == TeleportFadeState.FadingToBlack) { m_TeleportFadeAmount += m_TeleportFadeSpeed * Time.deltaTime; if (m_TeleportFadeAmount >= 1.0f) { // Teleport the user Vector3 vMovement = m_TeleportBoundsCurrent.transform.position - m_TeleportBoundsDesired.transform.position; TrTransform newScene = App.Scene.Pose; newScene.translation += vMovement; // newScene might have gotten just a little bit invalid. // Enforce the invariant that teleport always sends you // to a scene which is MakeValidPose(scene) newScene = SketchControlsScript.MakeValidScenePose(newScene, BoundsRadius); App.Scene.Pose = newScene; m_TeleportFadeAmount = 1.0f; m_TeleportFadeState = TeleportFadeState.FadeToScene; ViewpointScript.m_Instance.FadeToScene(m_TeleportFadeSpeed); m_TeleportForceBoundsPosition = true; } } else if (m_TeleportFadeState == TeleportFadeState.FadeToScene) { m_TeleportFadeAmount -= m_TeleportFadeSpeed * Time.deltaTime; if (m_TeleportFadeAmount <= 0.0f) { // Done fading. m_TeleportFadeAmount = 0.0f; m_TeleportFadeState = TeleportFadeState.Default; } } } // Check for teleporting. if (!m_EatInput && !m_ToolHidden && CanTeleport() && InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Teleport)) { m_TeleportFadeState = TeleportFadeState.FadingToBlack; ViewpointScript.m_Instance.FadeToColor(Color.black, m_TeleportFadeSpeed); AudioManager.m_Instance.PlayTeleportSound( ViewpointScript.Head.position + ViewpointScript.Head.forward); } PointerManager.m_Instance.SetMainPointerPosition(rAttachPoint.position); }
void Update() { // Update bounds transitions. switch (m_BoundsState) { case BoundsState.FadingInDelay: m_BoundsEnterDelayCountdown -= Time.deltaTime; if (m_BoundsEnterDelayCountdown <= 0.0f) { m_BoundsState = BoundsState.FadingIn; m_TeleportPlaceIcon.gameObject.SetActive(true); m_TeleportParabola.enabled = true; } m_BoundsShowAmount = 0.0f; UpdateBoundsScale(m_BoundsShowAmount); UpdateIconScale(); SetTeleportParabola(); break; case BoundsState.FadingIn: m_BoundsShowAmount += m_BoundsEnterSpeed * Time.deltaTime; if (m_BoundsShowAmount >= 1.0f) { m_BoundsShowAmount = 1.0f; m_BoundsState = BoundsState.Showing; } UpdateBoundsScale(m_BoundsShowAmount); UpdateIconScale(); SetTeleportParabola(); break; case BoundsState.FadingOut: m_BoundsShowAmount -= m_BoundsEnterSpeed * Time.deltaTime; if (m_BoundsShowAmount <= 0.0f) { m_BoundsShowAmount = 0.0f; m_BoundsState = BoundsState.Off; m_TeleportPlaceIcon.gameObject.SetActive(false); m_TeleportParabola.enabled = false; m_BoundsEnterDelayCountdown = m_BoundsEnterDelay; } UpdateBoundsScale(m_BoundsShowAmount); UpdateIconScale(); SetTeleportParabola(); break; } // Update tool transitions. switch (m_CurrentState) { case ToolState.Enter: m_EnterAmount += (m_EnterSpeed * Time.deltaTime); if (m_EnterAmount >= 1.0f) { m_EnterAmount = 1.0f; m_CurrentState = ToolState.Active; } UpdateToolScale(); break; case ToolState.Active: break; default: case ToolState.Off: break; } if (!m_LockToController) { // If we're not locking to a controller, update our transforms now, instead of in LateUpdate. UpdateTransformsFromControllers(); } #if JOGGING_ENABLED && (UNITY_EDITOR || EXPERIMENTAL_ENABLED) if (Config.IsExperimental) { // Add jogging motion. Vector3 currentHeadPosition = ViewpointScript.Head.position; if (m_JogLastHeadPosition != Vector3.zero) { Vector3 headMotion = currentHeadPosition - m_JogLastHeadPosition; TrTransform newScene = Coords.ScenePose; float motionFactor = Vector3.Dot(headMotion, m_TeleportTargetVector); motionFactor = (motionFactor - m_MotionMinThreshhold) / (m_MotionMaxThreshhold - m_MotionMinThreshhold); motionFactor = Mathf.SmoothStep(0, 1, motionFactor) * (m_MotionMaxThreshhold - m_MotionMinThreshhold); newScene.translation -= m_MotionSpeedup * motionFactor * m_TeleportTargetVector.normalized; if (headMotion.y > m_JogMinThreshold) { m_JogStage = JogState.JoggingUp; } if (m_JogStage != JogState.NotJogging) { newScene.translation -= m_JogSpeed * m_TeleportTargetVector; if (m_JogStage == JogState.JoggingUp && headMotion.y < 0) { m_JogStage = JogState.JoggingDown; } else if (m_JogStage == JogState.JoggingDown && headMotion.y >= 0) { m_JogStage = JogState.NotJogging; } } // newScene might have gotten just a little bit invalid. // Enforce the invariant that teleport always sends you // to a scene which is MakeValidPose(scene) newScene = SketchControlsScript.MakeValidScenePose(newScene, BoundsRadius); Coords.ScenePose = newScene; } m_JogLastHeadPosition = currentHeadPosition; } #endif }
/// Returns true on success /// Also updates m_TeleportForceBoundsPosition, m_LastParabolaVelocity, /// m_HideValidTeleportParabola, m_TeleportPlaceIcon, m_TeleportBoundsDesired /// Calls SetTeleportParabola() /// Calls UpdateIconScale() bool UpdateTool_PlaceParabola() { // Given pointing Y and our scalar, determine where our parabola intersects with y == 0. Vector3 vel = m_LastParabolaRay.direction * m_TeleportParabolaSpeed; float yPos = m_LastParabolaRay.origin.y; float fRadicand = vel.y * vel.y - 2.0f * m_TeleportParabolaGravity * yPos; if (fRadicand < 0f) { return(false); } Vector3 vFeet = ViewpointScript.Head.position; vFeet.y = 0.0f; Vector3 vNewFeet = m_LastParabolaRay.origin; vNewFeet.y = m_TeleportBounds.position.y; m_LastParabolaTime = (vel.y + Mathf.Sqrt(fRadicand)) / -m_TeleportParabolaGravity; m_TeleportTargetVector = new Vector3(vel.x * m_LastParabolaTime, 0, vel.z * m_LastParabolaTime); vNewFeet += m_TeleportTargetVector; // Ensure vNewFeet remains valid { // We don't have any functions for validating foot poses. In fact, the // room doesn't "move" since it's the root of our hierarchy. So: // 1. Turn foot move into room move TrTransform xfRoomMove = TrTransform.T(vNewFeet - vFeet); // 2. Turn room move into new scene pose and validate // Note: assumes old room transform is identity (which it is, because // the room is the root of our transform hierarchy). TrTransform newScene = xfRoomMove.inverse * App.Scene.Pose; newScene = SketchControlsScript.MakeValidSceneMove(App.Scene.Pose, newScene, BoundsRadius); // 3. Reverse of #2 xfRoomMove = App.Scene.Pose * newScene.inverse; // 4. Reverse of #1 vNewFeet = vFeet + xfRoomMove.translation; } // Dampen motion of vNewFeet // Invariant: new room center == (vNewFeet - vFeet) if (!m_TeleportForceBoundsPosition) { vNewFeet = Vector3.Lerp( m_TeleportBoundsDesired.transform.position + vFeet, vNewFeet, m_TeleportParabolaDampen); } else { m_TeleportForceBoundsPosition = false; } // Curve parabola to hit final position. m_LastParabolaVelocity = (vNewFeet - m_LastParabolaRay.origin) / m_LastParabolaTime; m_LastParabolaVelocity.y = ( (vNewFeet.y - m_LastParabolaRay.origin.y) - (m_TeleportParabolaGravity * m_LastParabolaTime * m_LastParabolaTime * 0.5f)) / m_LastParabolaTime; Vector3 vVelNoY = vel; vVelNoY.y = 0.0f; Vector3 vLastVelNoY = m_LastParabolaVelocity; vLastVelNoY.y = 0.0f; bool bReasonableAngle = Vector3.Angle(vVelNoY, vLastVelNoY) < 60.0f; m_HideValidTeleportParabola = !bReasonableAngle || (m_LastParabolaVelocity.normalized.y > m_TeleportParabolaMaxY); SetTeleportParabola(); // Place icon at the user's head position inside the new bounds, facing the user. m_TeleportPlaceIcon.position = vNewFeet; Vector3 vGazeDirNoY = ViewpointScript.Head.forward; vGazeDirNoY.y = 0.0f; m_TeleportPlaceIcon.forward = vGazeDirNoY.normalized; // Shrink the icon if it's too close to us. UpdateIconScale(); // Finally, set the desired bounds. m_TeleportBoundsDesired.transform.position = vNewFeet - vFeet; return(true); }