예제 #1
0
        /// <summary>
        /// Initializes the 'turn-ball' rotation axes from the specified point.
        /// </summary>
        /// <param name="p1">
        /// The point.
        /// </param>
        private void InitTurnballRotationAxes(Point p1)
        {
            double fx = p1.X / this.Viewport.ActualWidth;
            double fy = p1.Y / this.Viewport.ActualHeight;

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

            dir.Normalize();

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

            right.Normalize();

            this.rotationAxisX = up;
            this.rotationAxisY = right;
            if (fy > 0.8 || fy < 0.2)
            {
                // delta.Y = 0;
            }

            if (fx > 0.8)
            {
                // delta.X = 0;
                this.rotationAxisY = dir;
            }

            if (fx < 0.2)
            {
                // delta.X = 0;
                this.rotationAxisY = -dir;
            }
        }
예제 #2
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;
        }
예제 #3
0
        /// <summary>
        /// Changes the camera position by the specified vector.
        /// </summary>
        /// <param name="delta">The translation vector in camera space (z in look direction, y in up direction, and x perpendicular to the two others)</param>
        /// <param name="stopOther">Stop other manipulation</param>
        public void MoveCameraPosition(Vector3D delta, bool stopOther = true)
        {
            if (stopOther)
            {
                this.Controller.StopSpin();
                this.Controller.StopPanning();
            }
            var z = this.Camera.CameraInternal.LookDirection;

            z.Normalize();
            var x = Vector3D.Cross(this.Camera.CameraInternal.LookDirection, this.Camera.CameraInternal.UpDirection);
            var y = Vector3D.Cross(x, z);

            y.Normalize();
            x = Vector3D.Cross(z, y);

            // delta *= this.ZoomSensitivity;
            switch (this.CameraMode)
            {
            case CameraMode.Inspect:
            case CameraMode.WalkAround:
                this.Camera.Position += (x * delta.X) + (y * delta.Y) + (z * delta.Z);
                break;
            }
        }
        //https://stackoverflow.com/questions/18558910/direction-vector-to-rotation-matrix

        //Vector3 column1;
        //Vector3 column2;
        //Vector3 column3;


        public static Matrix3x3 makeRotationDir(Vector3 direction, Vector3 up) //  Vector3 up = 0,1,0
        {
            Matrix3x3 mat = Matrix3x3.Identity;

            Vector3 xaxis = Vector3.Cross(up, direction);

            xaxis.Normalize();

            Vector3 yaxis = Vector3.Cross(direction, xaxis);

            yaxis.Normalize();

            mat.M11 = xaxis.X;
            mat.M12 = yaxis.X;
            mat.M13 = direction.X;

            mat.M21 = xaxis.Y;
            mat.M21 = yaxis.Y;
            mat.M21 = direction.Y;

            mat.M31 = xaxis.Z;
            mat.M31 = yaxis.Z;
            mat.M31 = direction.Z;
            return(mat);
        }
예제 #5
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;
        }
예제 #6
0
        /// <summary>
        /// Finds the pan vector.
        /// </summary>
        /// <param name="dx">
        /// The delta x.
        /// </param>
        /// <param name="dy">
        /// The delta y.
        /// </param>
        /// <returns>
        /// The <see cref="Vector3D"/> .
        /// </returns>
        private Vector3D FindPanVector(double dx, double dy)
        {
            var axis1 = Vector3D.Cross(this.CameraLookDirection, this.CameraUpDirection);
            var axis2 = Vector3D.Cross(axis1, this.CameraLookDirection);

            axis1.Normalize();
            axis2.Normalize();
            var l    = this.CameraLookDirection.Length();
            var f    = l * 0.001f;
            var move = (-axis1 * f * (float)dx) + (axis2 * f * (float)dy);

            // this should be dependent on distance to target?
            return(move);
        }
예제 #7
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;
        }
예제 #8
0
        private void ProcessTranslationDrag()
        {
            if (m_activeAxis == EGizmoAxis.None)
            {
                return;
            }

            if (m_activeAxisList.Count <= 0)
            {
                return;
            }

            Ray pickRay = CreateMouseRay(in m_frameViewInfo);

            if (m_activeAxisList.Count > 1)
            {
                Vector3 planeNormal       = Vector3.Cross(m_activeAxisList[0], m_activeAxisList[1]);
                Plane   intersectionPlane = new Plane(m_startLocation, planeNormal);

                if (intersectionPlane.Intersects(ref pickRay, out Vector3 intersection))
                {
                    m_controlledTransform.SetWorldPosition(intersection - m_clickOffset);
                }
            }
            else
            {
                Vector3 planeTangent      = Vector3.Cross(m_activeAxisList[0], m_frameViewInfo.ViewLocation - m_gizmoLocation);
                Vector3 planeNormal       = Vector3.Cross(m_activeAxisList[0], planeTangent);
                Plane   intersectionPlane = new Plane(m_startLocation, planeNormal);

                if (intersectionPlane.Intersects(ref pickRay, out Vector3 intersection))
                {
                    intersection -= m_originalPosition + m_clickOffset;
                    m_controlledTransform.SetWorldPosition(m_originalPosition + m_activeAxisList[0] * Vector3.Dot(intersection, m_activeAxisList[0]));
                }
            }
        }
예제 #9
0
        public void UpdateMesh()
        {
            Vector3 point = new Vector3();

            //Updates Terrainmesh

            for (int x = 0; x < TerrainSize; x++)
            {
                for (int z = 0; z < TerrainSize; z++)
                {
                    point   = terrainMesh.Positions[z + (x * TerrainSize)];
                    point.Y = (TerrainHeights[z + x * TerrainSize] * HeightMultiplicator);
                    terrainMesh.Positions[z + x * TerrainSize] = point;
                }
            }
            TerrainMeshMainGeometry3D = terrainMesh.ToMeshGeometry3D();

            for (int x = 1; x < TerrainSize - 1; x++)
            {
                for (int z = 1; z < TerrainSize - 1; z++)
                {
                    Vector3 neighbour0 = terrainMesh.Positions[z + (x * TerrainSize) - 1];
                    Vector3 neighbour1 = terrainMesh.Positions[z + (x * TerrainSize) + 1];
                    Vector3 neighbour2 = terrainMesh.Positions[z + (x * TerrainSize) - TerrainSize];
                    Vector3 neighbour3 = terrainMesh.Positions[z + (x * TerrainSize) + TerrainSize];
                    Vector3 vec0       = neighbour0 - neighbour1;
                    Vector3 vec1       = neighbour2 - neighbour3;
                    terrainMesh.Normals[z + x * TerrainSize] = Vector3.Cross(vec0, vec1);
                }
            }

            //Updates Bordermesh
            for (int z = 0; z < TerrainSize; z++)
            {
                point   = borderMesh.Positions[(z * 2) + 1];
                point.Y = (TerrainHeights[z] * HeightMultiplicator);
                borderMesh.Positions[(z * 2) + 1] = point;
            }

            for (int x = 0; x < TerrainSize; x++)
            {
                point   = borderMesh.Positions[(x * 2) + 1 + (2 * TerrainSize)];
                point.Y = (TerrainHeights[x * TerrainSize + TerrainSize - 1] * HeightMultiplicator);
                borderMesh.Positions[(x * 2) + 1 + (2 * TerrainSize)] = point;
            }

            for (int z = TerrainSize; z > 0; z--)
            {
                point   = borderMesh.Positions[(z * 2) - 1 + (4 * TerrainSize)];
                point.Y = (TerrainHeights[(TerrainSize * TerrainSize) - z] * HeightMultiplicator);
                borderMesh.Positions[(z * 2) - 1 + (4 * TerrainSize)] = point;
            }

            for (int x = TerrainSize; x > 0; x--)
            {
                point   = borderMesh.Positions[(x * 2) - 1 + (6 * TerrainSize)];
                point.Y = (TerrainHeights[(TerrainSize - x) * TerrainSize] * HeightMultiplicator);
                borderMesh.Positions[(x * 2) - 1 + (6 * TerrainSize)] = point;
            }
            TerrainMeshBorderGeometry3D = borderMesh.ToMeshGeometry3D();
        }
예제 #10
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;
            }
        }