Exemplo n.º 1
0
        /// <summary>
        /// The rotate trackball.
        /// </summary>
        /// <param name="p1">
        /// The previous mouse position.
        /// </param>
        /// <param name="p2">
        /// The current mouse position.
        /// </param>
        /// <param name="rotateAround">
        /// The point to rotate around.
        /// </param>
        private void RotateTrackball(Point p1, Point p2, Point3D rotateAround)
        {
            // http://viewport3d.com/trackball.htm
            // http://www.codeplex.com/3DTools/Thread/View.aspx?ThreadId=22310
            var v1 = ProjectToTrackball(p1, this.Viewport.ActualWidth, this.Viewport.ActualHeight);
            var v2 = ProjectToTrackball(p2, this.Viewport.ActualWidth, this.Viewport.ActualHeight);

            // transform the trackball coordinates to view space
            var viewZ = this.Camera.LookDirection;
            var viewX = Vector3D.Cross(this.Camera.UpDirection, viewZ);
            var viewY = Vector3D.Cross(viewX, viewZ);

            viewX.Normalize();
            viewY.Normalize();
            viewZ.Normalize();
            var u1 = (viewZ * v1.Z) + (viewX * v1.X) + (viewY * v1.Y);
            var u2 = (viewZ * v2.Z) + (viewX * v2.X) + (viewY * v2.Y);

            // Could also use the Camera ViewMatrix
            // var vm = Viewport3DHelper.GetViewMatrix(this.ActualCamera);
            // vm.Invert();
            // var ct = new MatrixTransform3D(vm);
            // var u1 = ct.Transform(v1);
            // var u2 = ct.Transform(v2);

            // Find the rotation axis and angle
            var axis = Vector3D.Cross(u1, u2);

            if (axis.LengthSquared() < 1e-8)
            {
                return;
            }

            var angle = u1.AngleBetween(u2);

            // Create the transform
            var delta  = Quaternion.RotationAxis(axis, -(float)(angle * this.RotationSensitivity * 5));
            var rotate = Matrix.RotationQuaternion(delta);

            // Find vectors relative to the rotate-around point
            var relativeTarget   = rotateAround - this.Camera.Target;
            var relativePosition = rotateAround - this.Camera.Position;

            // Rotate the relative vectors
            var newRelativeTarget   = Vector3D.Transform(relativeTarget, rotate).ToVector3();
            var newRelativePosition = Vector3D.Transform(relativePosition, rotate).ToVector3();
            var newUpDirection      = Vector3D.Transform(this.Camera.UpDirection, rotate).ToVector3();

            // Find new camera position
            var newTarget   = rotateAround - newRelativeTarget;
            var newPosition = rotateAround - newRelativePosition;

            this.Camera.LookDirection = newTarget - newPosition;
            if (this.CameraMode == CameraMode.Inspect)
            {
                this.Camera.Position = newPosition;
            }

            this.Camera.UpDirection = newUpDirection;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Rotate around three axes.
        /// </summary>
        /// <param name="p1">
        /// The previous mouse position.
        /// </param>
        /// <param name="p2">
        /// The current mouse position.
        /// </param>
        /// <param name="rotateAround">
        /// The point to rotate around.
        /// </param>
        public void RotateTurnball(Point p1, Point p2, Point3D rotateAround)
        {
            this.InitTurnballRotationAxes(p1);

            Vector2 delta = p2.ToVector2() - p1.ToVector2();

            var relativeTarget   = rotateAround - this.Camera.Target;
            var relativePosition = rotateAround - this.Camera.Position;

            float d = -1f;

            if (this.CameraMode != CameraMode.Inspect)
            {
                d = 0.2f;
            }

            d *= (float)this.RotationSensitivity;

            var        q1 = Quaternion.RotationAxis(this.rotationAxisX, (float)(d * delta.X / 180 * Math.PI));
            var        q2 = Quaternion.RotationAxis(this.rotationAxisY, (float)(d * delta.Y / 180 * Math.PI));
            Quaternion q  = q1 * q2;

            var m = Matrix.RotationQuaternion(q);

            var newLookDir     = Vector3D.Transform(this.Camera.LookDirection, m).ToVector3();
            var newUpDirection = Vector3D.Transform(this.Camera.UpDirection, m).ToVector3();

            var newRelativeTarget   = Vector3D.Transform(relativeTarget, m).ToVector3();
            var newRelativePosition = Vector3D.Transform(relativePosition, m).ToVector3();

            var newRightVector = Vector3D.Cross(newLookDir, newUpDirection);

            newRightVector.Normalize();
            var modUpDir = Vector3D.Cross(newRightVector, newLookDir);

            modUpDir.Normalize();
            if ((newUpDirection - modUpDir).Length() > 1e-8)
            {
                newUpDirection = modUpDir;
            }

            var newTarget        = rotateAround - newRelativeTarget;
            var newPosition      = rotateAround - newRelativePosition;
            var newLookDirection = newTarget - newPosition;

            this.Camera.LookDirection = newLookDirection;
            if (this.CameraMode == CameraMode.Inspect)
            {
                this.Camera.Position = newPosition;
            }

            this.Camera.UpDirection = newUpDirection;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Rotate camera using 'Turntable' rotation.
        /// </summary>
        /// <param name="delta">
        /// The relative change in position.
        /// </param>
        /// <param name="rotateAround">
        /// The point to rotate around.
        /// </param>
        public void RotateTurntable(Vector2 delta, Point3D rotateAround)
        {
            var relativeTarget   = rotateAround - this.Camera.Target;
            var relativePosition = rotateAround - this.Camera.Position;

            var up  = this.ModelUpDirection;
            var dir = this.Camera.LookDirection;

            dir.Normalize();

            var right = Vector3D.Cross(dir, this.Camera.UpDirection);

            right.Normalize();

            var d = -0.5f;

            if (this.CameraMode != CameraMode.Inspect)
            {
                d *= -0.2f;
            }

            d *= (float)this.RotationSensitivity;

            var        q1 = Quaternion.RotationAxis(up, (float)(d * delta.X / 180 * Math.PI));
            var        q2 = Quaternion.RotationAxis(right, (float)(d * delta.Y / 180 * Math.PI));
            Quaternion q  = q1 * q2;

            var m = Matrix.RotationQuaternion(q);

            var newUpDirection      = Vector3D.Transform(this.Camera.UpDirection, m).ToVector3();
            var newRelativeTarget   = Vector3D.Transform(relativeTarget, m).ToVector3();
            var newRelativePosition = Vector3D.Transform(relativePosition, m).ToVector3();
            var newTarget           = rotateAround - newRelativeTarget;
            var newPosition         = rotateAround - newRelativePosition;

            this.Camera.LookDirection = newTarget - newPosition;
            if (this.CameraMode == CameraMode.Inspect)
            {
                this.Camera.Position = newPosition;
            }

            this.Camera.UpDirection = newUpDirection;
        }
Exemplo n.º 4
0
        private void ProcessLeftMouse(EButtonEvent buttonEvent)
        {
            if (buttonEvent == EButtonEvent.Pressed && m_controlledTransform != null)
            {
                if (IsHovered)
                {
                    Plane axisPlane;
                    if (m_activeAxisList.Count > 1)
                    {
                        Vector3 planeNormal = Vector3.Cross(m_activeAxisList[0], m_activeAxisList[1]);
                        axisPlane = new Plane(m_gizmoLocation, planeNormal);
                    }
                    else
                    {
                        Vector3 planeNormal;
                        if (Mode == EGizmoMode.Rotation)
                        {
                            // Rotation
                            planeNormal = m_activeAxisList[0];
                        }
                        else
                        {
                            //Translation / Scale
                            Vector3 toCamera     = m_frameViewInfo.ViewLocation - m_gizmoLocation;
                            Vector3 planeTangent = Vector3.Cross(m_activeAxisList[0], toCamera);
                            planeNormal = Vector3.Cross(m_activeAxisList[0], planeTangent);
                        }

                        axisPlane = new Plane(m_gizmoLocation, planeNormal);
                    }

                    World.ViewManager.GetViewInfo(out SSceneViewInfo viewInfo);
                    Ray ray = CreateMouseRay(viewInfo);

                    if (ray.Intersects(ref axisPlane, out Vector3 intersectionPoint))
                    {
                        m_startLocation = intersectionPoint;

                        switch (Mode)
                        {
                        case EGizmoMode.Translation:
                            m_clickOffset      = intersectionPoint - m_gizmoLocation;
                            m_originalPosition = m_controlledTransform.WorldPosition;
                            break;

                        case EGizmoMode.Rotation:
                            Vector3 toStart = m_startLocation - m_gizmoLocation;
                            m_rotationDragAxis = Vector3.Cross(toStart, m_activeAxisList[0]);
                            m_rotationDragAxis.Normalize();
                            m_originalRotation = m_controlledTransform.WorldRotation;
                            break;

                        case EGizmoMode.Scale:
                            m_originalScale = m_controlledTransform.WorldScale;
                            m_scaleAxis     = Vector3.Zero;
                            foreach (Vector3 axis in m_activeAxisList)
                            {
                                m_scaleAxis += Vector3.Transform(axis, Quaternion.Invert(m_controlledTransform.WorldRotation));
                            }

                            m_scaleAxis.Normalize();
                            m_scaleSizeFactor = m_originalScale.Length();
                            break;

                        default:
                            throw new ArgumentOutOfRangeException();
                        }

                        IsClicked = true;
                    }
                }
            }
            else if (m_controlledTransform != null)
            {
                if (IsClicked)
                {
                    switch (Mode)
                    {
                    case EGizmoMode.Translation:
                        Vector3 newPosition = m_controlledTransform.WorldPosition;
                        if (newPosition != m_originalPosition)
                        {
                            OnTranslationChanged?.Invoke(m_controlledTransform, m_originalPosition, newPosition);
                        }
                        break;

                    case EGizmoMode.Rotation:
                        Quaternion newRotation = m_controlledTransform.WorldRotation;
                        if (newRotation != m_originalRotation)
                        {
                            OnRotationChanged?.Invoke(m_controlledTransform, m_originalRotation, newRotation);
                        }
                        break;

                    case EGizmoMode.Scale:
                        Vector3 newScale = m_controlledTransform.WorldScale;
                        if (newScale != m_originalScale)
                        {
                            OnScaleChanged?.Invoke(m_controlledTransform, m_originalScale, newScale);
                        }
                        break;
                    }
                }

                IsClicked         = false;
                m_totalAngleDelta = 0.0f;
                m_totalScaleDelta = 0.0f;
            }
        }