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

            var up  = Vector3.Normalize(Camera.CameraInternal.UpDirection);
            var dir = Vector3.Normalize(Camera.CameraInternal.LookDirection);

            var right = Vector3.Normalize(Vector3.Cross(dir, up));

            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;
            }
        }
Ejemplo n.º 2
0
        // http://en.wikipedia.org/wiki/Polygon_triangulation
        // http://en.wikipedia.org/wiki/Monotone_polygon
        // http://www.codeproject.com/KB/recipes/hgrd.aspx LGPL
        // http://www.springerlink.com/content/g805787811vr1v9v/
        /// <summary>
        /// Flattens this polygon.
        /// </summary>
        /// <returns>
        /// The 2D polygon.
        /// </returns>
        public Polygon Flatten()
        {
            // http://forums.xna.com/forums/p/16529/86802.aspx
            // http://stackoverflow.com/questions/1023948/rotate-normal-vector-onto-axis-plane
            var up = this.GetNormal();

            up.Normalize();
            var right = Vector3D.Cross(
                up, Math.Abs(up.X) > Math.Abs(up.Z) ? new Vector3D(0, 0, 1) : new Vector3D(1, 0, 0));
            var backward = Vector3D.Cross(right, up);
            var m        = new Matrix3D(
                backward.X, right.X, up.X, 0, backward.Y, right.Y, up.Y, 0, backward.Z, right.Z, up.Z, 0, 0, 0, 0, 1);

            // make first point origin
            var offs = Vector3D.TransformCoordinate(Points[0], m);

            m.M41 = -offs.X;
            m.M42 = -offs.Y;

            var polygon = new Polygon {
                Points = new PointCollection(this.Points.Count)
            };

            foreach (var p in this.Points)
            {
                var pp = Vector3D.TransformCoordinate(p, m);
                polygon.Points.Add(new Point(pp.X, pp.Y));
            }

            return(polygon);
        }
Ejemplo n.º 3
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(Vector2 p1, Vector2 p2, Vector3 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);
            var cUP = Camera.CameraInternal.UpDirection;
            // transform the trackball coordinates to view space
            var viewZ = Vector3.Normalize(Camera.CameraInternal.LookDirection * Inv);
            var viewX = Vector3.Normalize(Vector3.Cross(cUP, viewZ) * Inv);
            var viewY = Vector3.Normalize(Vector3.Cross(viewX, viewZ));
            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 = Vector3.Cross(u1, u2);

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

            var angle = VectorExtensions.AngleBetween(u1, u2);

            // Create the transform
            var rotate = Matrix.RotationAxis(Vector3.Normalize(axis), -angle * (float)RotationSensitivity * 5);

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

            // Rotate the relative vectors
            var newRelativeTarget   = Vector3.TransformCoordinate(relativeTarget, rotate);
            var newRelativePosition = Vector3.TransformCoordinate(relativePosition, rotate);
            var newUpDirection      = Vector3.TransformCoordinate(cUP, rotate);

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

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

            this.Camera.UpDirection = newUpDirection.ToVector3D();
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Moves the camera position.
        /// </summary>
        /// <param name="camera">The camera.</param>
        /// <param name="delta">The delta.</param>
        public static void MoveCameraPosition(this Camera camera, Vector3D delta)
        {
            var z = Vector3.Normalize(camera.CameraInternal.LookDirection);
            var x = Vector3.Cross(z, camera.CameraInternal.UpDirection);
            var y = Vector3.Normalize(Vector3.Cross(x, z));

            x = Vector3.Cross(z, y);

            // delta *= this.ZoomSensitivity;
            camera.Position += ((x * (float)delta.X) + (y * (float)delta.Y) + (z * (float)delta.Z)).ToVector3D();
        }
Ejemplo n.º 5
0
        public static void ExtrudeText(this MeshBuilder builder, string text, string font, FontStyle fontStyle, FontWeight fontWeight, double fontSize, Vector3D textDirection, Point3D p0, Point3D p1)
        {
            var outlineList = GetTextOutlines(text, font, fontStyle, fontWeight, fontSize);

            // Build the polygon to mesh (using Triangle.NET to triangulate)
            var polygon = new TriangleNet.Geometry.Polygon();
            int marker  = 0;

            foreach (var outlines in outlineList)
            {
                var outerOutline = outlines.OrderBy(x => x.AreaOfSegment()).Last();

                for (int i = 0; i < outlines.Count; i++)
                {
                    var outline = outlines[i];
                    var isHole  = i != outlines.Count - 1 && IsPointInPolygon(outerOutline, outline[0]);
                    polygon.AddContour(outline.Select(p => new Vertex(p.X, p.Y)), marker++, isHole);
                    builder.AddExtrudedSegments(outline.ToSegments().Select(x => new SharpDX.Vector2((float)x.X, (float)x.Y)).ToList(),
                                                textDirection, p0, p1);
                }
            }

            var mesher  = new GenericMesher();
            var options = new ConstraintOptions();
            var mesh    = mesher.Triangulate(polygon, options);

            var u = textDirection;

            u.Normalize();
            var z = p1 - p0;

            z.Normalize();
            var v = Vector3D.Cross(z, u);

            // Convert the triangles
            foreach (var t in mesh.Triangles)
            {
                var v0 = t.GetVertex(2);
                var v1 = t.GetVertex(1);
                var v2 = t.GetVertex(0);

                // Add the top triangle.
                // Project the X/Y vertices onto a plane defined by textdirection, p0 and p1.
                builder.AddTriangle(v0.Project(p0, u, v, z, 1), v1.Project(p0, u, v, z, 1), v2.Project(p0, u, v, z, 1));

                // Add the bottom triangle.
                builder.AddTriangle(v2.Project(p0, u, v, z, 0), v1.Project(p0, u, v, z, 0), v0.Project(p0, u, v, z, 0));
            }
            if (builder.CreateNormals)
            {
                builder.Normals = null;
                builder.ComputeNormalsAndTangents(MeshFaces.Default, builder.HasTangents);
            }
        }
Ejemplo n.º 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="Vector3"/> .
        /// </returns>
        private Vector3 FindPanVector(float dx, float dy)
        {
            var axis1 = Vector3.Normalize(Vector3.Cross(this.CameraLookDirection, this.CameraUpDirection));
            var axis2 = Vector3.Normalize(Vector3.Cross(axis1, this.CameraLookDirection));

            axis1 *= (ActualCamera.CreateLeftHandSystem ? -1 : 1);
            var l    = this.CameraLookDirection.Length();
            var f    = l * 0.001f;
            var move = (-axis1 * f * dx) + (axis2 * f * dy);

            // this should be dependent on distance to target?
            return(move);
        }
Ejemplo n.º 7
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(Vector2 p1, Vector2 p2, Vector3 rotateAround)
        {
            this.InitTurnballRotationAxes(p1);

            Vector2 delta = p2 - p1;

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

            float d = -1;

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

            d *= (float)RotationSensitivity;

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

            var     m              = Matrix.RotationQuaternion(q);
            Vector3 newLookDir     = Vector3.TransformNormal(this.Camera.CameraInternal.LookDirection, m);
            Vector3 newUpDirection = Vector3.TransformNormal(this.Camera.CameraInternal.UpDirection, m);

            Vector3 newRelativeTarget   = Vector3.TransformCoordinate(relativeTarget, m);
            Vector3 newRelativePosition = Vector3.TransformCoordinate(relativePosition, m);

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

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

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

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

            this.Camera.UpDirection = newUpDirection.ToVector3D();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// changes in lookdirection set the rotation point to wrong position
        /// Ref: https://github.com/helix-toolkit/helix-toolkit/issues/1068
        /// </summary>
        /// <param name="newRelativeTarget"></param>
        /// <param name="relativeTarget"></param>
        /// <returns></returns>
        private Vector3 CalcNewRelativeTargetOrthogonalToLookDirection(Vector3 newRelativeTarget, Vector3 relativeTarget)
        {
            var relativeTargetDiff = newRelativeTarget - relativeTarget;
            var lookDir            = Camera.CameraInternal.LookDirection;

            var crossProduct = Vector3.Cross(lookDir, relativeTargetDiff);
            var orthogonalRelativeTargetDiff = Vector3.Cross(crossProduct, lookDir).Normalized();

            // correct length
            var angle = orthogonalRelativeTargetDiff.AngleBetween(relativeTargetDiff);

            orthogonalRelativeTargetDiff *= (float)(Math.Cos(angle) * relativeTargetDiff.Length());
            newRelativeTarget             = relativeTarget + orthogonalRelativeTargetDiff;

            return(newRelativeTarget);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Determines whether this polygon is planar.
        /// </summary>
        /// <returns>
        /// The is planar.
        /// </returns>
        public bool IsPlanar()
        {
            Vector3D v1     = this.Points[1] - this.Points[0];
            var      normal = new Vector3D();

            for (int i = 2; i < this.Points.Count; i++)
            {
                var n = Vector3D.Cross(v1, this.Points[i] - this.Points[0]);
                n.Normalize();
                if (i == 2)
                {
                    normal = n;
                }
                else if (Math.Abs(Vector3D.Dot(n, normal) - 1) > 1e-8)
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Gets the normal of the polygon.
        /// </summary>
        /// <returns>
        /// The normal.
        /// </returns>
        public Vector3D GetNormal()
        {
            if (this.Points.Count < 3)
            {
                throw new InvalidOperationException("At least three points required in the polygon to find a normal.");
            }

            Vector3D v1 = this.Points[1] - this.Points[0];

            for (int i = 2; i < this.Points.Count; i++)
            {
                var n = Vector3D.Cross(v1, this.Points[i] - this.Points[0]);
                if (n.LengthSquared() > 1e-8)
                {
                    n.Normalize();
                    return(n);
                }
            }

            throw new InvalidOperationException("Invalid polygon.");
        }
Ejemplo n.º 11
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, Vector3 rotateAround)
        {
            var relativeTarget   = rotateAround - this.Camera.CameraInternal.Target;
            var relativePosition = rotateAround - this.Camera.CameraInternal.Position;
            var cUp   = Camera.CameraInternal.UpDirection;
            var up    = this.ModelUpDirection;
            var dir   = Vector3.Normalize(Camera.CameraInternal.LookDirection);
            var right = Vector3.Normalize(Vector3.Cross(dir, cUp));

            float d = -0.5f;

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

            d *= (float)this.RotationSensitivity;

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

            var m = Matrix.RotationQuaternion(q);

            var newUpDirection = Vector3.TransformNormal(cUp, m);

            var newRelativeTarget   = Vector3.TransformCoordinate(relativeTarget, m);
            var newRelativePosition = Vector3.TransformCoordinate(relativePosition, m);

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

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

            this.Camera.UpDirection = newUpDirection.ToVector3D();
        }
Ejemplo n.º 12
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(Vector3 delta, bool stopOther = true)
        {
            if (stopOther)
            {
                Controller.StopPanning();
                Controller.StopSpin();
            }
            var z = Vector3.Normalize(this.Camera.CameraInternal.LookDirection);
            var x = Vector3.Cross(this.Camera.CameraInternal.LookDirection, this.Camera.CameraInternal.UpDirection);
            var y = Vector3.Normalize(Vector3.Cross(x, z));

            x = Vector3.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)).ToVector3D();
                break;
            }
        }