public bool UpdateAndCheckIfRedrawRequired() { if (_showSceneControl.RenderSetup == null) { return(false); } // Stop all transitions when switching between camera-ops if (_showSceneControl.RenderSetup.CurrentCameraOp != _cameraOperator) { _cameraOperator = _showSceneControl.RenderSetup.CurrentCameraOp; _cameraPositionGoal = _showSceneControl.RenderSetup.CameraPosition; _cameraTargetGoal = _showSceneControl.RenderSetup.CameraTarget; MoveVelocity = Vector3.Zero; _isTransitionActive = false; } // This is an extremely unfortunate solution to check if the camera has been manipulated from the // outside (e.g. by another view, parameters or animation) if (!_isTransitionActive && (PositionDistance.Length() > STOP_DISTANCE_THRESHOLD || TargetDistance.Length() > STOP_DISTANCE_THRESHOLD)) { _cameraPositionGoal = _showSceneControl.RenderSetup.CameraPosition; _cameraTargetGoal = _showSceneControl.RenderSetup.CameraTarget; return(true); } var redrawRequired = false; UpdateRawMouseData(); if (_lockInteraction) { return(false); } _lockInteraction = true; // Manipulation... redrawRequired |= ManipulateGizmos(); if (_showSceneControl.RenderSetup.TransformGizmo.State != TransformGizmo.TransformGizmo.GizmoStates.Dragged) { ManipulateCameraByMouse(); } _manipulatedByKeyboard = ManipulateCameraByKeyboard(); _spaceMouse.ManipulateCamera(); // Transition... redrawRequired |= ComputeCameraMovement(); _lockInteraction = false; return(redrawRequired); }
/* * Returns false if camera didn't move */ private bool ComputeCameraMovement() { var frameDurationFactor = (float)(App.Current.TimeSinceLastFrame) / FRAME_DURATION_AT_60_FPS; if (PositionDistance.Length() > STOP_DISTANCE_THRESHOLD || TargetDistance.Length() > STOP_DISTANCE_THRESHOLD || MoveVelocity.Length() > STOP_DISTANCE_THRESHOLD || _lookingAroundDelta.Length() > STOP_DISTANCE_THRESHOLD || _manipulatedByMouseWheel || _orbitDelta.Length() > 0.001f || _manipulatedByKeyboard) { if (_orbitDelta.Length() > 0.001f) { OrbitByAngle(_orbitDelta); _orbitDelta *= new Vector2(ORBIT_HORIZONTAL_FRICTION, ORBIT_VERTICAL_FRICTION) / frameDurationFactor; } if (MoveVelocity.Length() > MaxMoveVelocity) { MoveVelocity *= MaxMoveVelocity / MoveVelocity.Length(); } else if (!_manipulatedByKeyboard) { MoveVelocity *= (1 - _frictionKeyboardManipulation) / frameDurationFactor; } _cameraPositionGoal += MoveVelocity; _cameraTargetGoal += MoveVelocity + _lookingAroundDelta; _lookingAroundDelta = Vector3.Zero; PositionDistance *= CAMERA_MOVE_FRICTION / frameDurationFactor; TargetDistance *= CAMERA_MOVE_FRICTION / frameDurationFactor; _isTransitionActive = true; _manipulatedByMouseWheel = false; return(true); } else { StopTransitionOfPositionTarget(); _isTransitionActive = false; return(false); } }
/** * WPF will discard some mouse-wheel events on slow framerates which leads to a laggy * interaction in complex scenes. For that reason, we include the framerate into the zoom-speed * and -- sadly -- avoid transitions for for zooming. */ public void HandleMouseWheel(float delta) { var transitionActive = PositionDistance.Length() > STOP_DISTANCE_THRESHOLD || TargetDistance.Length() > STOP_DISTANCE_THRESHOLD; var viewDirection = transitionActive ? _cameraPositionGoal - _cameraTargetGoal : _showSceneControl.RenderSetup.CameraPosition - _showSceneControl.RenderSetup.CameraTarget; var frameDurationFactor = (float)(App.Current.TimeSinceLastFrame) / FRAME_DURATION_AT_60_FPS; var zoomFactorForCurrentFramerate = 1 + (ZOOM_SPEED * frameDurationFactor); if (delta < 0) { viewDirection *= zoomFactorForCurrentFramerate; } else { viewDirection /= zoomFactorForCurrentFramerate; } _showSceneControl.RenderSetup.CameraPosition = _cameraPositionGoal = _cameraTargetGoal + viewDirection; _manipulatedByMouseWheel = true; }