Exemple #1
0
 public void AddLine(Point3D p1, Point3D p2)
 {
     int i0 = positions.Count;
     this.positions.Add(p1);
     this.positions.Add(p2);
     this.lineListIndices.Add(i0);
     this.lineListIndices.Add(i0 + 1);
 }
Exemple #2
0
 public void AddBox(Point3D center, double xlength, double ylength, double zlength)
 {
     int i0 = positions.Count;
     var dx = new Vector3D((float)xlength/2f, 0, 0);
     var dy = new Vector3D(0, (float)ylength/2f, 0);
     var dz = new Vector3D(0, 0, (float)zlength/2f);
     this.Add(true, center - dx - dy - dz, center + dx - dy - dz, center + dx + dy - dz, center - dx + dy - dz);
     this.Add(true, center - dx - dy + dz, center + dx - dy + dz, center + dx + dy + dz, center - dx + dy + dz);
     lineListIndices.AddRange(new[] { i0 + 0, i0 + 4, i0 + 1, i0 + 5, i0 + 2, i0 + 6, i0 + 3, i0 + 7 });
 }
        /// <summary>
        /// Un-projects a point from the screen (2D) to a point on plane (3D)
        /// </summary>
        /// <param name="p">
        /// The 2D point.
        /// </param>
        /// <param name="position">
        /// plane position
        /// </param>
        /// <param name="normal">
        /// plane normal
        /// </param>
        /// <returns>
        /// A 3D point.
        /// </returns>
        public Vector3?UnProject(Point p, Vector3 position, Vector3 normal)
        {
            var ray = this.GetRay(p);

            if (ray == null)
            {
                return(null);
            }
            var plane = new Plane(position, normal);

            if (ray.Intersects(ref plane, out Vector3 point))
            {
                return(point);
            }
Exemple #4
0
        private void Timer_Tick(object sender, EventArgs e)
        {
            double angle     = (0.05f * frame) * Math.PI / 180;
            var    xAxis     = new Vector3(1, 0, 0);
            var    zAxis     = new Vector3(0, 0, 1);
            var    yAxis     = new Vector3(0, 1, 0);
            var    rotation  = Matrix.RotationAxis(xAxis, 0);
            double angleEach = 0;
            int    counter   = 0;

            for (int i = 0; i < NumSegments && i < numBonesInModel; ++i, counter += numSegmentPerBone)
            {
                if (i == 0)
                {
                    boneInternal[0] = rotation;
                }
                else
                {
                    var vp = Vector3.Transform(path[counter - numSegmentPerBone], Matrix.RotationAxis(xAxis, (float)angleEach)).ToVector3();
                    angleEach += angle;
                    var v   = Vector3.Transform(path[counter], Matrix.RotationAxis(xAxis, (float)angleEach)).ToVector3();
                    var rad = Math.Acos(Vector3.Dot(yAxis, (v - vp).Normalized()));
                    if (angleEach < 0)
                    {
                        rad = -rad;
                    }
                    var rot   = Matrix.RotationAxis(xAxis, (float)rad);
                    var trans = Matrix.Translation(v);
                    boneInternal[i] = rot * trans;
                }
            }
            Bones = new BoneMatricesStruct()
            {
                Bones = boneInternal.ToArray()
            };

            if (frame > 40 || frame < -40)
            {
                direction = !direction;
            }
            if (direction)
            {
                ++frame;
            }
            else
            {
                --frame;
            }
        }
Exemple #5
0
        /// <summary>
        /// Zooms the camera to the specified rectangle.
        /// </summary>
        /// <param name="camera">
        /// The camera.
        /// </param>
        /// <param name="viewport">
        /// The viewport.
        /// </param>
        /// <param name="zoomRectangle">
        /// The zoom rectangle.
        /// </param>
        public static void ZoomToRectangle(this Camera camera, Viewport3DX viewport, Rect zoomRectangle)
        {
            var topLeftRay  = viewport.UnProjectToRay(zoomRectangle.TopLeft);
            var topRightRay = viewport.UnProjectToRay(zoomRectangle.TopRight);
            var centerRay   =
                viewport.UnProjectToRay(
                    new Point(
                        (zoomRectangle.Left + zoomRectangle.Right) * 0.5,
                        (zoomRectangle.Top + zoomRectangle.Bottom) * 0.5));

            if (topLeftRay == null || topRightRay == null || centerRay == null)
            {
                // could not invert camera matrix
                return;
            }

            var u = Vector3.Normalize(topLeftRay.Direction);
            var v = Vector3.Normalize(topRightRay.Direction);
            var w = Vector3.Normalize(centerRay.Direction);

            if (camera is IPerspectiveCameraModel perspectiveCamera)
            {
                var distance = camera.LookDirection.Length;

                // option 1: change distance
                var newDistance      = distance * zoomRectangle.Width / viewport.ActualWidth;
                var newLookDirection = (float)newDistance * w;
                var newPosition      = camera.CameraInternal.Position + ((float)(distance - newDistance) * w);
                var newTarget        = newPosition + newLookDirection;
                LookAt(camera, newTarget.ToPoint3D(), newLookDirection.ToVector3D(), 200);

                // option 2: change fov
                // double newFieldOfView = Math.Acos(Vector3D.DotProduct(u, v));
                // var newTarget = camera.Position + distance * w;
                // pcamera.FieldOfView = newFieldOfView * 180 / Math.PI;
                // LookAt(camera, newTarget, distance * w, 0);
            }
            else if (camera is IOrthographicCameraModel orthographicCamera)
            {
                orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth;
                var oldTarget = camera.CameraInternal.Position + camera.CameraInternal.LookDirection;
                var distance  = camera.CameraInternal.LookDirection.Length();
                var newTarget = centerRay.PlaneIntersection(oldTarget, w);
                if (newTarget != null)
                {
                    LookAt(orthographicCamera, newTarget.Value.ToPoint3D(), 200);
                }
            }
        }
Exemple #6
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));
            }
        }
Exemple #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();
        }
Exemple #8
0
        /// <summary>
        /// Finds the bounding box of the viewport.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <returns>The bounding box.</returns>
        public static Rect3D FindBounds(this Viewport3DX viewport)
        {
            var maxVector  = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
            var firstModel = viewport.Renderables.PreorderDFT((r) =>
            {
                if (r.Visible && !(r is ScreenSpacedNode))
                {
                    return(true);
                }
                return(false);
            }).Where(x =>
            {
                if (x is IBoundable b)
                {
                    return(b.HasBound && b.BoundsWithTransform.Maximum != b.BoundsWithTransform.Minimum &&
                           b.BoundsWithTransform.Maximum != Vector3.Zero && b.BoundsWithTransform.Maximum != maxVector);
                }
                else
                {
                    return(false);
                }
            }).FirstOrDefault();

            if (firstModel == null)
            {
                return(new Rect3D());
            }
            var bounds = firstModel.BoundsWithTransform;

            foreach (var renderable in viewport.Renderables.PreorderDFT((r) =>
            {
                if (r.Visible && !(r is ScreenSpacedNode))
                {
                    return(true);
                }
                return(false);
            }))
            {
                if (renderable is IBoundable r)
                {
                    if (r.HasBound && r.BoundsWithTransform.Maximum != maxVector)
                    {
                        bounds = global::SharpDX.BoundingBox.Merge(bounds, r.BoundsWithTransform);
                    }
                }
            }
            return(new Rect3D(bounds.Minimum.ToPoint3D(), (bounds.Maximum - bounds.Minimum).ToSize3D()));
        }
        /// <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);
        }
        /// <summary>
        /// Zooms the view around the specified point.
        /// </summary>
        /// <param name="delta">
        /// The delta.
        /// </param>
        /// <param name="zoomAround">
        /// The zoom around.
        /// </param>
        /// <param name="isTouch"></param>
        /// <param name="stopOther">Stop other manipulation</param>
        public void Zoom(double delta, Vector3 zoomAround, bool isTouch = false, bool stopOther = true)
        {
            if (!this.Controller.IsZoomEnabled)
            {
                return;
            }
            if (stopOther)
            {
                this.Controller.StopSpin();
                this.Controller.StopPanning();
            }
            if (this.Camera is IPerspectiveCameraModel)
            {
                if (!isTouch)
                {
                    if (delta < -0.5)
                    {
                        delta = -0.5;
                    }
                    delta *= this.ZoomSensitivity;
                }

                if (this.CameraMode == CameraMode.FixedPosition || this.changeFieldOfView)
                {
                    this.Viewport.ZoomByChangingFieldOfView(delta);
                }
                else
                {
                    switch (this.CameraMode)
                    {
                    case CameraMode.Inspect:
                        this.ChangeCameraDistance(ref delta, zoomAround);
                        break;

                    case CameraMode.WalkAround:
                        this.Camera.Position -= this.Camera.LookDirection * delta;
                        break;
                    }
                }

                return;
            }
            else if (this.Camera is IOrthographicCameraModel)
            {
                this.ZoomByChangingCameraWidth(delta, zoomAround);
            }
        }
Exemple #11
0
        /// <summary>
        /// Tries to parse a vertex from a string.
        /// </summary>
        /// <param name="line">
        /// The input string.
        /// </param>
        /// <param name="point">
        /// The vertex point.
        /// </param>
        /// <returns>
        /// True if parsing was successful.
        /// </returns>
        private static bool TryParseVertex(string line, out Point3D point)
        {
            var match = VertexRegex.Match(line);

            if (!match.Success)
            {
                point = new Point3D();
                return(false);
            }

            float x = float.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
            float y = float.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture);
            float z = float.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);

            point = new Point3D(x, y, z);
            return(true);
        }
        /// <summary>
        /// Occurs when the manipulation is started.
        /// </summary>
        /// <param name="e">The <see cref="Point"/> instance containing the event data.</param>
        public override void Started(Point e)
        {
            base.Started(e);
            this.zoomPoint   = new Point(this.Viewport.ActualWidth / 2, this.Viewport.ActualHeight / 2);
            this.zoomPoint3D = this.Camera.CameraInternal.Target;

            if (this.Controller.ZoomAroundMouseDownPoint && this.MouseDownNearestPoint3D != null)
            {
                this.zoomPoint   = this.MouseDownPoint;
                this.zoomPoint3D = this.MouseDownNearestPoint3D.Value;
            }

            if (!this.changeFieldOfView)
            {
                this.Viewport.ShowTargetAdorner(this.zoomPoint);
            }
        }
Exemple #13
0
        /// <summary>
        /// Pans the camera by the specified 3D vector (world coordinates).
        /// </summary>
        /// <param name="delta">
        /// The panning vector.
        /// </param>
        /// <param name="stopOther">Stop other manipulation</param>
        public void Pan(Vector3 delta, bool stopOther = true)
        {
            if (!this.Controller.IsPanEnabled)
            {
                return;
            }
            if (stopOther)
            {
                this.Controller.StopSpin();
                this.Controller.StopZooming();
            }
            if (this.CameraMode == CameraMode.FixedPosition)
            {
                return;
            }

            this.Camera.Position += delta.ToVector3D();
        }
Exemple #14
0
        /// <summary>
        /// Finds the nearest connected segment to the specified point.
        /// </summary>
        /// <param name="segments">
        /// The segments.
        /// </param>
        /// <param name="point">
        /// The point.
        /// </param>
        /// <param name="eps">
        /// The tolerance.
        /// </param>
        /// <returns>
        /// The index of the nearest point.
        /// </returns>
        private static int FindConnectedSegment(IList <Point3D> segments, Point3D point, DoubleOrSingle eps)
        {
            var best   = eps;
            int result = -1;

            for (int i = 0; i < segments.Count; i++)
            {
                var v   = point - segments[i];
                var ls0 = SharedFunctions.LengthSquared(ref v);
                if (ls0 < best)
                {
                    result = i;
                    best   = ls0;
                }
            }

            return(result);
        }
        /// <summary>
        /// The add pan force.
        /// </summary>
        /// <param name="pan">
        /// The pan.
        /// </param>
        public void AddPanForce(Vector3 pan)
        {
            if (!this.IsPanEnabled)
            {
                return;
            }

            this.PushCameraSetting();
            if (this.IsInertiaEnabled)
            {
                this.panSpeed += pan * 40;
            }
            else
            {
                this.panHandler.Pan(pan);
            }
            Viewport.InvalidateRender();
        }
        private double CalculateError(int id_v1, int id_v2, out Vector3D p_result)
        {
            p_result = new Vector3D();
            // compute interpolated vertex
            var    q      = vertices[id_v1].q + vertices[id_v2].q;
            bool   border = vertices[id_v1].border & vertices[id_v2].border;
            double error  = 0;

            double det = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7);

            if (det != 0 && !border)
            {
                // q_delta is invertible
                p_result.X = (float)(-1 / det * (q.det(1, 2, 3, 4, 5, 6, 5, 7, 8))); // vx = A41/det(q_delta)
                p_result.Y = (float)(1 / det * (q.det(0, 2, 3, 1, 5, 6, 2, 7, 8)));  // vy = A42/det(q_delta)
                p_result.Z = (float)(-1 / det * (q.det(0, 1, 3, 1, 4, 6, 2, 5, 8))); // vz = A43/det(q_delta)

                error = VertexError(ref q, p_result.X, p_result.Y, p_result.Z);
            }
            else
            {
                // det = 0 -> try to find best result
                var    p1     = vertices[id_v1].p;
                var    p2     = vertices[id_v2].p;
                var    p3     = (p1 + p2) / 2;
                double error1 = VertexError(ref q, p1.X, p1.Y, p1.Z);
                double error2 = VertexError(ref q, p2.X, p2.Y, p2.Z);
                double error3 = VertexError(ref q, p3.X, p3.Y, p3.Z);
                error = Math.Min(error1, Math.Min(error2, error3));
                if (error1 == error)
                {
                    p_result = p1;
                }
                if (error2 == error)
                {
                    p_result = p2;
                }
                if (error3 == error)
                {
                    p_result = p3;
                }
            }
            return(error);
        }
        /// <summary>
        /// Adds the zoom force.
        /// </summary>
        /// <param name="delta">
        /// The delta.
        /// </param>
        /// <param name="zoomOrigin">
        /// The zoom origin.
        /// </param>
        public void AddZoomForce(float delta, Vector3 zoomOrigin)
        {
            if (!this.IsZoomEnabled)
            {
                return;
            }
            this.PushCameraSetting();

            if (this.IsInertiaEnabled)
            {
                this.zoomPoint3D = zoomOrigin;
                this.zoomSpeed  += delta * 8;
            }
            else
            {
                this.zoomHandler.Zoom(delta, zoomOrigin);
            }
            Viewport.InvalidateRender();
        }
        /// <summary>
        /// Rotates the specified p0.
        /// </summary>
        /// <param name="p0">The p0.</param>
        /// <param name="p1">The p1.</param>
        /// <param name="rotateAround">The rotate around.</param>
        /// <param name="stopOther">if set to <c>true</c> [stop other].</param>
        public void Rotate(Vector2 p0, Vector2 p1, Vector3 rotateAround, bool stopOther = true)
        {
            if (!this.Controller.IsRotationEnabled)
            {
                return;
            }
            if (stopOther)
            {
                Controller.StopZooming();
                Controller.StopPanning();
            }
            p0 = Vector2.Multiply(p0, Controller.AllowRotateXY);
            p1 = Vector2.Multiply(p1, Controller.AllowRotateXY);
            Vector3 newPos  = Camera.CameraInternal.Position;
            Vector3 newLook = Camera.CameraInternal.LookDirection;
            Vector3 newUp   = Vector3.Normalize(Camera.CameraInternal.UpDirection);

            switch (this.Controller.CameraRotationMode)
            {
            case CameraRotationMode.Trackball:
                CameraMath.RotateTrackball(CameraMode, ref p0, ref p1, ref rotateAround, (float)RotationSensitivity,
                                           Controller.Width, Controller.Height, Camera, Inv, out newPos, out newLook, out newUp);
                break;

            case CameraRotationMode.Turntable:
                var p = p1 - p0;
                CameraMath.RotateTurntable(CameraMode, ref p, ref rotateAround, (float)RotationSensitivity,
                                           Controller.Width, Controller.Height, Camera, Inv, ModelUpDirection, out newPos, out newLook, out newUp);
                break;

            case CameraRotationMode.Turnball:
                CameraMath.RotateTurnball(CameraMode, ref p0, ref p1, ref rotateAround, (float)RotationSensitivity,
                                          Controller.Width, Controller.Height, Camera, Inv, out newPos, out newLook, out newUp);
                break;

            default:
                break;
            }
            Camera.LookDirection = newLook.ToVector3D();
            Camera.Position      = newPos.ToPoint3D();
            Camera.UpDirection   = newUp.ToVector3D();
        }
        /// <summary>
        /// Un-projects a 2D screen point.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="pointIn">The input point.</param>
        /// <param name="pointNear">The point at the near clipping plane.</param>
        /// <param name="pointFar">The point at the far clipping plane.</param>
        /// <returns>The ray.</returns>
        public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar)
        {
            var camera = viewport.Camera as ProjectionCamera;

            if (camera != null)
            {
                var p = new Vector3((float)point2d.X, (float)point2d.Y, 1);


                //var wvp = GetViewProjectionMatrix(viewport);
                //Vector3 r = Vector3.Unproject(p, 0f, 0f, (float)viewport.ActualWidth, (float)viewport.ActualHeight, 0f, 1f, wvp);
                //r.Normalize();

                var vp  = GetScreenViewProjectionMatrix(viewport);
                var vpi = Matrix.Invert(vp);

                var test = 1f / ((p.X * vpi.M14) + (p.Y * vpi.M24) + (p.Z * vpi.M34) + vpi.M44);
                if (double.IsInfinity(test))
                {
                    vpi.M44 = vpi.M44 + 0.000001f;
                }

                Vector3 zn, zf;
                p.Z = 0;
                Vector3.TransformCoordinate(ref p, ref vpi, out zn);
                p.Z = 1;
                Vector3.TransformCoordinate(ref p, ref vpi, out zf);
                Vector3 r = zf - zn;

                r.Normalize();

                if (camera is PerspectiveCamera)
                {
                    return(new Ray(camera.Position.ToVector3(), r));
                }
                else if (camera is OrthographicCamera)
                {
                    return(new Ray(zn, r));
                }
            }
            throw new HelixToolkitException("Unproject camera error.");
        }
Exemple #20
0
        /// <summary>
        /// Generates a square grid with a step of 1.0
        /// </summary>
        /// <returns></returns>
        public static LineGeometry3D GenerateGrid(Vector3 plane, int min0 = 0, int max0 = 10, int min1 = 0, int max1 = 10)
        {
            var grid = new LineBuilder();

            //int width = max - min;
            if (plane == Vector3.UnitX)
            {
                for (int i = min0; i <= max0; i++)
                {
                    grid.AddLine(new Vector3(0, i, min1), new Vector3(0, i, max1));
                }
                for (int i = min1; i <= max1; i++)
                {
                    grid.AddLine(new Vector3(0, min0, i), new Vector3(0, max0, i));
                }
            }
            else if (plane == Vector3.UnitY)
            {
                for (int i = min0; i <= max0; i++)
                {
                    grid.AddLine(new Vector3(i, 0, min1), new Vector3(i, 0, max1));
                }
                for (int i = min1; i <= max1; i++)
                {
                    grid.AddLine(new Vector3(min0, 0, i), new Vector3(max0, 0, i));
                }
            }
            else
            {
                for (int i = min0; i <= max0; i++)
                {
                    grid.AddLine(new Vector3(i, min1, 0), new Vector3(i, max1, 0));
                }
                for (int i = min1; i <= max1; i++)
                {
                    grid.AddLine(new Vector3(min0, i, 0), new Vector3(max0, i, 0));
                }
            }

            return(grid.ToLineGeometry3D());
        }
Exemple #21
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);
        }
Exemple #22
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.");
        }
Exemple #23
0
        /// <summary>
        /// Un-projects a 2D screen point.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="point2d">The input point.</param>
        /// <returns>The ray.</returns>
        public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar)
        {
            var camera = viewport.CameraCore as ProjectionCameraCore;

            if (camera != null)
            {
                var px = (float)point2d.X;
                var py = (float)point2d.Y;

                var     viewMatrix = camera.GetViewMatrix();
                Vector3 v          = new Vector3();

                var   matrix      = MatrixExtensions.PsudoInvert(ref viewMatrix);
                float w           = (float)viewport.ActualWidth;
                float h           = (float)viewport.ActualHeight;
                var   aspectRatio = w / h;

                var     projMatrix = camera.GetProjectionMatrix(aspectRatio);
                Vector3 zn, zf;
                v.X = (2 * px / w - 1) / projMatrix.M11;
                v.Y = -(2 * py / h - 1) / projMatrix.M22;
                v.Z = 1 / projMatrix.M33;
                Vector3.TransformCoordinate(ref v, ref matrix, out zf);

                if (camera is PerspectiveCameraCore)
                {
                    zn = camera.Position;
                }
                else
                {
                    v.Z = 0;
                    Vector3.TransformCoordinate(ref v, ref matrix, out zn);
                }
                Vector3 r = zf - zn;
                r.Normalize();

                return(new Ray(zn + r * camera.NearPlaneDistance, r));
            }
            throw new HelixToolkitException("Unproject camera error.");
        }
Exemple #24
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();
        }
Exemple #25
0
        /// <summary>
        /// Zooms the camera to the specified rectangle.
        /// </summary>
        /// <param name="camera">
        /// The camera.
        /// </param>
        /// <param name="viewport">
        /// The viewport.
        /// </param>
        /// <param name="zoomRectangle">
        /// The zoom rectangle.
        /// </param>
        public static void ZoomToRectangle(this Camera camera, Viewport3DX viewport, Rect zoomRectangle)
        {
            if (viewport.UnProject(zoomRectangle.TopLeft.ToVector2(), out var topLeftRay) &&
                viewport.UnProject(zoomRectangle.TopRight.ToVector2(), out var topRightRay) &&
                viewport.UnProject(new global::SharpDX.Vector2(
                                       (float)(zoomRectangle.Left + zoomRectangle.Right) * 0.5f,
                                       (float)(zoomRectangle.Top + zoomRectangle.Bottom) * 0.5f), out var centerRay))
            {
                var u = Vector3.Normalize(topLeftRay.Direction);
                var v = Vector3.Normalize(topRightRay.Direction);
                var w = Vector3.Normalize(centerRay.Direction);
                if (camera is IPerspectiveCameraModel perspectiveCamera)
                {
                    var distance = camera.LookDirection.Length;

                    // option 1: change distance
                    var newDistance      = distance * zoomRectangle.Width / viewport.ActualWidth;
                    var newLookDirection = (float)newDistance * w;
                    var newPosition      = camera.CameraInternal.Position + ((float)(distance - newDistance) * w);
                    var newTarget        = newPosition + newLookDirection;
                    LookAt(camera, newTarget.ToPoint3D(), newLookDirection.ToVector3D(), 200);

                    // option 2: change fov
                    // double newFieldOfView = Math.Acos(Vector3D.DotProduct(u, v));
                    // var newTarget = camera.Position + distance * w;
                    // pcamera.FieldOfView = newFieldOfView * 180 / Math.PI;
                    // LookAt(camera, newTarget, distance * w, 0);
                }
                else if (camera is IOrthographicCameraModel orthographicCamera)
                {
                    orthographicCamera.Width *= zoomRectangle.Width / viewport.ActualWidth;
                    var oldTarget = camera.CameraInternal.Position + camera.CameraInternal.LookDirection;
                    var distance  = camera.CameraInternal.LookDirection.Length();
                    if (centerRay.PlaneIntersection(oldTarget, w, out var newTarget))
                    {
                        LookAt(orthographicCamera, newTarget.ToPoint3D(), 200);
                    }
                }
            }
        }
Exemple #26
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ContourHelper" /> class.
        /// </summary>
        /// <param name="planeOrigin">The plane origin.</param>
        /// <param name="planeNormal">The plane normal.</param>
        /// <param name="originalMesh">The original mesh.</param>
        public ContourHelper(Point3D planeOrigin, Vector3D planeNormal, MeshGeometry3D originalMesh)
        {
            var hasNormals            = originalMesh.Normals != null && originalMesh.Normals.Count > 0;
            var hasTextureCoordinates = originalMesh.TextureCoordinates != null && originalMesh.TextureCoordinates.Count > 0;

            this.normals       = hasNormals ? new Vector3D[3] : null;
            this.textures      = hasTextureCoordinates ? new Point[3] : null;
            this.positionCount = originalMesh.Positions.Count;

            this.meshPositions          = originalMesh.Positions.ToArray();
            this.meshNormals            = hasNormals ? originalMesh.Normals.ToArray() : null;
            this.meshTextureCoordinates = hasTextureCoordinates ? originalMesh.TextureCoordinates.ToArray() : null;

            // Determine the equation of the plane as
            // ax + by + cz + d = 0
            var l = (float)Math.Sqrt((planeNormal.X * planeNormal.X) + (planeNormal.Y * planeNormal.Y) + (planeNormal.Z * planeNormal.Z));

            this.a = planeNormal.X / l;
            this.b = planeNormal.Y / l;
            this.c = planeNormal.Z / l;
            this.d = -(float)((planeNormal.X * planeOrigin.X) + (planeNormal.Y * planeOrigin.Y) + (planeNormal.Z * planeOrigin.Z));
        }
        /// <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;
            }
        }
Exemple #28
0
        /// <summary>
        /// Occurs when the position is changed during a manipulation.
        /// </summary>
        /// <param name="e">The <see cref="Point"/> instance containing the event data.</param>
        public override void Delta(Point e)
        {
            base.Delta(e);
            var thisPoint3D = this.UnProject(e, this.panPoint3D, this.Camera.CameraInternal.LookDirection);

            if (Camera.CameraInternal.LookDirection.LengthSquared() < 1f && MouseDownNearestPoint3D.HasValue)
            {
                var look = Camera.CameraInternal.LookDirection.Normalized();
                var v    = MouseDownNearestPoint3D.Value - Camera.CameraInternal.Position;
                Camera.CameraInternal.LookDirection = look * Math.Max(1, Vector3.Dot(v, look));
            }
            if (this.LastPoint3D == null || thisPoint3D == null)
            {
                return;
            }

            var delta3D = this.LastPoint3D.Value - thisPoint3D.Value;

            this.Pan(delta3D);

            this.LastPoint   = e;
            this.LastPoint3D = this.UnProject(e, this.panPoint3D, this.Camera.CameraInternal.LookDirection);
        }
        /// <summary>
        /// The change camera width.
        /// </summary>
        /// <param name="delta">
        /// The delta.
        /// </param>
        /// <param name="zoomAround">
        /// The zoom around.
        /// </param>
        public void ZoomByChangingCameraWidth(double delta, Vector3 zoomAround)
        {
            if (delta < -0.5)
            {
                delta = -0.5;
            }

            switch (this.CameraMode)
            {
            case CameraMode.WalkAround:
            case CameraMode.Inspect:
            case CameraMode.FixedPosition:
                if (ChangeCameraDistance(ref delta, zoomAround))
                {
                    // Modify the camera width
                    if (Camera is IOrthographicCameraModel ocamera)
                    {
                        ocamera.Width *= Math.Pow(2.5, delta);
                    }
                }
                break;
            }
        }
        private bool Flipped(ref Vector3D p, int i0, int i1, ref Vertex v0, ref Vertex v1, IList <bool> deleted)
        {
            for (int i = 0; i < v0.tCount; ++i)
            {
                var t = triangles[refs[v0.tStart + i].tid];
                if (t.deleted)
                {
                    continue;
                }
                int s   = refs[v0.tStart + i].tvertex;
                int id1 = t.v[(s + 1) % 3];
                int id2 = t.v[(s + 2) % 3];
                if (id1 == i1 || id2 == i1)
                {
                    deleted[i] = true;
                    continue;
                }

                Vector3D d1 = vertices[id1].p - p;
                d1.Normalize();
                Vector3D d2 = vertices[id2].p - p;
                d2.Normalize();
                if (SharedFunctions.DotProduct(ref d1, ref d2) > 0.999)
                {
                    return(true);
                }
                var n = SharedFunctions.CrossProduct(ref d1, ref d2);
                n.Normalize();
                deleted[i] = false;
                if (SharedFunctions.DotProduct(ref n, ref t.normal) < 0.2)
                {
                    return(true);
                }
            }
            return(false);
        }
Exemple #31
0
        /// <summary>
        /// Adds a sphere.
        /// </summary>
        /// <param name="center">
        /// The center of the sphere.
        /// </param>
        /// <param name="radius">
        /// The radius of the sphere.
        /// </param>
        /// <param name="thetaDiv">
        /// The number of divisions around the sphere.
        /// </param>
        /// <param name="phiDiv">
        /// The number of divisions from top to bottom of the sphere.
        /// </param>
        public void AddSphere(Point3D center, double radius = 1, int thetaDiv = 32, int phiDiv = 32)
        {
            int index0 = this.positions.Count;
            float dt = (float)(2 * Math.PI / thetaDiv);
            float dp = (float)(Math.PI / phiDiv);

            for (int pi = 0; pi <= phiDiv; pi++)
            {
                float phi = pi * dp;

                for (int ti = 0; ti <= thetaDiv; ti++)
                {
                    // we want to start the mesh on the x axis
                    float theta = ti * dt;

                    // Spherical coordinates
                    // http://mathworld.wolfram.com/SphericalCoordinates.html
                    //float x = (float)(Math.Cos(theta) * Math.Sin(phi));
                    //float y = (float)(Math.Sin(theta) * Math.Sin(phi));
                    //float z = (float)(Math.Cos(phi));

                    float x = (float)(Math.Sin(theta) * Math.Sin(phi));
                    float y = (float)(Math.Cos(phi));
                    float z = (float)(Math.Cos(theta) * Math.Sin(phi));

                    var p = new Point3D(center.X + ((float)radius * x), center.Y + ((float)radius * y), center.Z + ((float)radius * z));
                    this.positions.Add(p);

                    if (this.normals != null)
                    {
                        var n = new Vector3D(x, y, z);
                        this.normals.Add(n);
                    }

                    if (this.textureCoordinates != null)
                    {
                        var uv = new Point((float)(theta / (2 * Math.PI)), (float)(phi / Math.PI));
                        this.textureCoordinates.Add(uv);
                    }
                }
            }

            this.AddRectangularMeshTriangleIndices(index0, phiDiv + 1, thetaDiv + 1, true);
            Console.WriteLine();
        }
Exemple #32
0
        /// <summary>
        /// Adds a triangle.
        /// </summary>
        /// <param name="p0">
        /// The first point.
        /// </param>
        /// <param name="p1">
        /// The second point.
        /// </param>
        /// <param name="p2">
        /// The third point.
        /// </param>
        /// <param name="uv0">
        /// The first texture coordinate.
        /// </param>
        /// <param name="uv1">
        /// The second texture coordinate.
        /// </param>
        /// <param name="uv2">
        /// The third texture coordinate.
        /// </param>
        public void AddTriangle(Point3D p0, Point3D p1, Point3D p2, Point uv0, Point uv1, Point uv2)
        {
            int i0 = this.positions.Count;

            this.positions.Add(p0);
            this.positions.Add(p1);
            this.positions.Add(p2);

            if (this.textureCoordinates != null)
            {
                this.textureCoordinates.Add(uv0);
                this.textureCoordinates.Add(uv1);
                this.textureCoordinates.Add(uv2);
            }

            if (this.normals != null)
            {
                var w = Vector3D.Cross(p1 - p0, p2 - p0);
                w.Normalize();
                this.normals.Add(w);
                this.normals.Add(w);
                this.normals.Add(w);
            }

            this.triangleIndices.Add(i0 + 0);
            this.triangleIndices.Add(i0 + 1);
            this.triangleIndices.Add(i0 + 2);
        }
Exemple #33
0
 /// <summary>
 /// Adds a triangle.
 /// </summary>
 /// <param name="p0">
 /// The first point.
 /// </param>
 /// <param name="p1">
 /// The second point.
 /// </param>
 /// <param name="p2">
 /// The third point.
 /// </param>
 public void AddTriangle(Point3D p0, Point3D p1, Point3D p2)
 {           
     var uv0 = new Point(0, 0);
     var uv1 = new Point(1, 0);
     var uv2 = new Point(0, 1);
     this.AddTriangle(p0, p1, p2, uv0, uv1, uv2);
 }
Exemple #34
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="viewport"></param>
        /// <param name="p"></param>
        /// <param name="position"></param>
        /// <param name="normal"></param>
        /// <returns></returns>
        public static Vector3?UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Vector3 position, Vector3 normal)
        {
            var plane = new Plane(position, normal);

            return(UnProjectOnPlane(viewport, p, plane));
        }
Exemple #35
0
        private static void ComputeNormals(List<Vector3D> positions, List<int> triangleIndices, out Vector3D[] normals)
        {
            //var normals = new List<Vector3D>(positions.Count);
            normals = new Point3D[positions.Count];
            for (int t = 0; t < triangleIndices.Count; t += 3)
            {
                var i1 = triangleIndices[t];
                var i2 = triangleIndices[t + 1];
                var i3 = triangleIndices[t + 2];

                var v1 = positions[i1];
                var v2 = positions[i2];
                var v3 = positions[i3];

                var p1 = v2 - v1;
                var p2 = v3 - v1;
                var n = Vector3D.Cross(p1, p2);
                // angle
                p1.Normalize();
                p2.Normalize();
                var a = (float)Math.Acos(Vector3D.Dot(p1, p2));
                n.Normalize();
                normals[i1] += (a * n);
                normals[i2] += (a * n);
                normals[i3] += (a * n);
            }
            for (int i = 0; i < normals.Length; i++)
            {
                normals[i].Normalize();
            }
        }
Exemple #36
0
        /// <summary>
        /// Adds a rectangular mesh defined by a two-dimensional arrary of points.
        /// </summary>
        /// <param name="points">
        /// The points.
        /// </param>
        /// <param name="texCoords">
        /// The texture coordinates (optional).
        /// </param>
        /// <param name="closed0">
        /// set to <c>true</c> if the mesh is closed in the 1st dimension.
        /// </param>
        /// <param name="closed1">
        /// set to <c>true</c> if the mesh is closed in the 2nd dimension.
        /// </param>
        public void AddRectangularMesh(Point3D[,] points, Point[,] texCoords = null, bool closed0 = false, bool closed1 = false)
        {
            if (points == null)
            {
                throw new ArgumentNullException("points");
            }

            int rows = points.GetUpperBound(0) + 1;
            int columns = points.GetUpperBound(1) + 1;
            int index0 = this.positions.Count;
            for (int i = 0; i < rows; i++)
            {
                for (int j = 0; j < columns; j++)
                {
                    this.positions.Add(points[i, j]);
                }
            }

            this.AddRectangularMeshTriangleIndices(index0, rows, columns, closed0, closed1);

            if (this.normals != null)
            {
                this.AddRectangularMeshNormals(index0, rows, columns);
            }

            if (this.textureCoordinates != null)
            {
                if (texCoords != null)
                {
                    for (int i = 0; i < rows; i++)
                    {
                        for (int j = 0; j < columns; j++)
                        {
                            this.textureCoordinates.Add(texCoords[i, j]);
                        }
                    }
                }
                else
                {
                    this.AddRectangularMeshTextureCoordinates(rows, columns);
                }
            }
        }
Exemple #37
0
        /// <summary>
        /// Adds a regular icosahedron.
        /// </summary>
        /// <param name="center">
        /// The center.
        /// </param>
        /// <param name="radius">
        /// The radius.
        /// </param>
        /// <param name="shareVertices">
        /// share vertices if set to <c>true</c> .
        /// </param>
        /// <remarks>
        /// See http://en.wikipedia.org/wiki/Icosahedron and http://www.gamedev.net/community/forums/topic.asp?topic_id=283350.
        /// </remarks>
        public void AddRegularIcosahedron(Point3D center, double radius, bool shareVertices)
        {
            float a = (float)Math.Sqrt(2.0 / (5.0 + Math.Sqrt(5.0)));

            float b = (float)Math.Sqrt(2.0 / (5.0 - Math.Sqrt(5.0)));

            var icosahedronIndices = new[]
                {
                    1, 4, 0, 4, 9, 0, 4, 5, 9, 8, 5, 4, 1, 8, 4, 1, 10, 8, 10, 3, 8, 8, 3, 5, 3, 2, 5, 3, 7, 2, 3, 10, 7,
                    10, 6, 7, 6, 11, 7, 6, 0, 11, 6, 1, 0, 10, 1, 6, 11, 0, 9, 2, 11, 9, 5, 2, 9, 11, 2, 7
                };

            var icosahedronVertices = new[]
                {
                    new Vector3D(-a, 0, b), new Vector3D(a, 0, b), new Vector3D(-a, 0, -b), new Vector3D(a, 0, -b),
                    new Vector3D(0, b, a), new Vector3D(0, b, -a), new Vector3D(0, -b, a), new Vector3D(0, -b, -a),
                    new Vector3D(b, a, 0), new Vector3D(-b, a, 0), new Vector3D(b, -a, 0), new Vector3D(-b, -a, 0)
                };

            if (shareVertices)
            {
                int index0 = this.positions.Count;
                foreach (var v in icosahedronVertices)
                {
                    this.positions.Add(center + (v * (float)radius));
                }

                foreach (int i in icosahedronIndices)
                {
                    this.triangleIndices.Add(index0 + i);
                }
            }
            else
            {
                for (int i = 0; i + 2 < icosahedronIndices.Length; i += 3)
                {
                    this.AddTriangle(
                        center + (icosahedronVertices[icosahedronIndices[i]] * (float)radius),
                        center + (icosahedronVertices[icosahedronIndices[i + 1]] * (float)radius),
                        center + (icosahedronVertices[icosahedronIndices[i + 2]] * (float)radius));
                }
            }
        }
Exemple #38
0
        private static void ComputeTangentsQuads(List<Point3D> positions, List<Point3D> normals, List<Point> textureCoordinates, List<int> indices,
            out List<Point3D> tangents, out List<Point3D> bitangents)
        {

            var tan1 = new Point3D[positions.Count];
            
            for (int t = 0; t < indices.Count; t += 4)
            {
                var i1 = indices[t];
                var i2 = indices[t + 1];
                var i3 = indices[t + 2];
                var i4 = indices[t + 3];

                var v1 = positions[i1];
                var v2 = positions[i2];
                var v3 = positions[i3];
                var v4 = positions[i4];

                var w1 = textureCoordinates[i1];
                var w2 = textureCoordinates[i2];
                var w3 = textureCoordinates[i3];
                var w4 = textureCoordinates[i4];

                float x1 = v2.X - v1.X;
                float x2 = v4.X - v1.X;
                float y1 = v2.Y - v1.Y;
                float y2 = v4.Y - v1.Y;
                float z1 = v2.Z - v1.Z;
                float z2 = v4.Z - v1.Z;

                float s1 = w2.X - w1.X;
                float s2 = w4.X - w1.X;
                float t1 = w2.Y - w1.Y;
                float t2 = w4.Y - w1.Y;

                float r = 1.0f / (s1 * t2 - s2 * t1);
                var udir = new Vector3D((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
                //var vdir = new Vector3D((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);

                tan1[i1] += udir;
                tan1[i2] += udir;
                tan1[i3] += udir;
                tan1[i4] += udir;

                //tan2[i1] += vdir;
                //tan2[i2] += vdir;
                //tan2[i3] += vdir;
            }

            tangents = new List<Point3D>(positions.Count);
            bitangents = new List<Point3D>(positions.Count);
            for (int i = 0; i < positions.Count; i++)
            {
                var n = normals[i];
                var t = tan1[i];
                t = (t - n * Vector3D.Dot(n, t));
                t.Normalize();
                var b = Vector3D.Cross(n, t);
                tangents.Add(t);
                bitangents.Add(b);
            }
        }
Exemple #39
0
 /// <summary>
 /// Adds a sphere (by subdiving a regular icosahedron).
 /// </summary>
 /// <param name="center">
 /// The center of the sphere.
 /// </param>
 /// <param name="radius">
 /// The radius of the sphere.
 /// </param>
 /// <param name="subdivisions">
 /// The number of triangular subdivisions of the original icosahedron.
 /// </param>
 /// <remarks>
 /// See http://www.fho-emden.de/~hoffmann/ikos27042002.pdf.
 /// </remarks>
 public void AddSubdivisionSphere(Point3D center, double radius, int subdivisions)
 {
     int p0 = this.positions.Count;
     this.Append(GetUnitSphere(subdivisions));
     int p1 = this.positions.Count;
     for (int i = p0; i < p1; i++)
     {
         this.positions[i] = center + ((float)radius * this.positions[i]);
     }
 }
Exemple #40
0
        private static void AppendSphere(Point3D center, double radius, int thetaSteps, int phiSteps,
            out List<Point3D> positions, out List<Point3D> normals, out List<Point> textureCoordinates, out List<int> triangleIndices)
        {
            positions = new List<Point3D>();
            normals = new List<Point3D>();
            textureCoordinates = new List<Point>();
            triangleIndices = new List<int>();

            double dt = DegToRad(360.0) / thetaSteps;
            double dp = DegToRad(180.0) / phiSteps;

            for (int pi = 0; pi <= phiSteps; pi++)
            {
                double phi = pi * dp;
                for (int ti = 0; ti <= thetaSteps; ti++)
                {
                    // we want to start the mesh on the x axis
                    double theta = ti * dt;

                    positions.Add(GetPosition(theta, phi, radius) + center);
                    normals.Add(GetNormal(theta, phi));
                    textureCoordinates.Add(GetTextureCoordinate(theta, phi));
                }
            }

            for (int pi = 0; pi < phiSteps; pi++)
            {
                for (int ti = 0; ti < thetaSteps; ti++)
                {
                    int x0 = ti;
                    int x1 = ti + 1;
                    int y0 = pi * (thetaSteps + 1);
                    int y1 = (pi + 1) * (thetaSteps + 1);

                    triangleIndices.Add(x0 + y0);
                    triangleIndices.Add(x0 + y1);
                    triangleIndices.Add(x1 + y0);

                    triangleIndices.Add(x1 + y0);
                    triangleIndices.Add(x0 + y1);
                    triangleIndices.Add(x1 + y1);
                }
            }
        }
Exemple #41
0
        /// <summary>
        /// Tesselates the element and returns a MeshGeometry3D representing the 
        /// tessellation based on the parameters given 
        /// </summary>        
        public void AppendSphere(Point3D center, double radius = 1, int thetaSteps = 64, int phiSteps = 64)
        {
            List<Point3D> pos, nor;
            List<Point> tcoord;
            List<int> tind;

            AppendSphere(center, radius, thetaSteps, phiSteps, out pos, out nor, out tcoord, out tind);

            int i0 = positions.Count;
            this.positions.AddRange(pos);
            this.normals.AddRange(nor);
            this.textureCoordinates.AddRange(tcoord);
            this.triangleIndices.AddRange(tind.Select(x => x + i0));
        }
Exemple #42
0
        /// <summary>
        /// Adds an arrow to the mesh.
        /// </summary>
        /// <param name="point1">
        /// The start point.
        /// </param>
        /// <param name="point2">
        /// The end point.
        /// </param>
        /// <param name="diameter">
        /// The diameter of the arrow cylinder.
        /// </param>
        /// <param name="headLength">
        /// Length of the head (relative to diameter).
        /// </param>
        /// <param name="thetaDiv">
        /// The number of divisions around the arrow.
        /// </param>
        public void AddArrow(Point3D point1, Point3D point2, double diameter, double headLength = 3, int thetaDiv = 18)
        {
            var dir = point2 - point1;
            var length = dir.Length();
            var r = (float)diameter / 2;

            var pc = new PointCollection
                {
                    new Point(0, 0),
                    new Point(0, r),
                    new Point(length - (float)(diameter * headLength), r),
                    new Point(length - (float)(diameter * headLength), r * 2),
                    new Point(length, 0)
                };

            this.AddRevolvedGeometry(pc, point1, dir, thetaDiv);
        }
Exemple #43
0
 /// <summary>
 /// Adds a pyramid.
 /// </summary>
 /// <param name="center">
 /// The center.
 /// </param>
 /// <param name="sideLength">
 /// Length of the sides of the pyramid.
 /// </param>
 /// <param name="height">
 /// The height of the pyramid.
 /// </param>
 /// <remarks>
 /// See http://en.wikipedia.org/wiki/Pyramid_(geometry).
 /// </remarks>
 public void AddPyramid(Point3D center, double sideLength, double height)
 {
     var p1 = new Point3D(center.X - (float)(sideLength * 0.5), center.Y - (float)(sideLength * 0.5), center.Z);
     var p2 = new Point3D(center.X + (float)(sideLength * 0.5), center.Y - (float)(sideLength * 0.5), center.Z);
     var p3 = new Point3D(center.X + (float)(sideLength * 0.5), center.Y + (float)(sideLength * 0.5), center.Z);
     var p4 = new Point3D(center.X - (float)(sideLength * 0.5), center.Y + (float)(sideLength * 0.5), center.Z);
     var p5 = new Point3D(center.X, center.Y, center.Z + (float)height);
     this.AddTriangle(p1, p2, p5);
     this.AddTriangle(p2, p3, p5);
     this.AddTriangle(p3, p4, p5);
     this.AddTriangle(p4, p1, p5);
 }
Exemple #44
0
 /// <summary>
 /// Adds a quadrilateral polygon.
 /// </summary>
 /// <param name="p0">
 /// The first point.
 /// </param>
 /// <param name="p1">
 /// The second point.
 /// </param>
 /// <param name="p2">
 /// The third point.
 /// </param>
 /// <param name="p3">
 /// The fourth point.
 /// </param>
 /// <remarks>
 /// See http://en.wikipedia.org/wiki/Quadrilateral.
 /// </remarks>
 public void AddQuad(Point3D p0, Point3D p1, Point3D p2, Point3D p3)
 {
     //// The nodes are arranged in counter-clockwise order
     //// p3               p2
     //// +---------------+
     //// |               |
     //// |               |
     //// +---------------+
     //// p0               p1
     var uv0 = new Point(0, 0);
     var uv1 = new Point(1, 0);
     var uv2 = new Point(0, 1);
     var uv3 = new Point(1, 1);
     this.AddQuad(p0, p1, p2, p3, uv0, uv1, uv2, uv3);
 }
        /// <summary>
        /// Un-projects a 2D screen point.
        /// </summary>
        /// <param name="viewport">The viewport.</param>
        /// <param name="pointIn">The input point.</param>
        /// <param name="pointNear">The point at the near clipping plane.</param>
        /// <param name="pointFar">The point at the far clipping plane.</param>
        /// <returns>The ray.</returns>
        public static Ray UnProject(this Viewport3DX viewport, Vector2 point2d)//, out Vector3 pointNear, out Vector3 pointFar)
        {
            var camera = viewport.Camera as ProjectionCamera;
            if (camera != null)
            {
                var p = new Vector3((float)point2d.X, (float)point2d.Y, 1);


                //var wvp = GetViewProjectionMatrix(viewport);
                //Vector3 r = Vector3.Unproject(p, 0f, 0f, (float)viewport.ActualWidth, (float)viewport.ActualHeight, 0f, 1f, wvp);
                //r.Normalize();

                var vp = GetScreenViewProjectionMatrix(viewport);
                var vpi = Matrix.Invert(vp);
                Vector3 zn, zf;
                p.Z = 0;
                Vector3.TransformCoordinate(ref p, ref vpi, out zn);
                p.Z = 1;
                Vector3.TransformCoordinate(ref p, ref vpi, out zf);
                Vector3 r = zf - zn;
                r.Normalize();

                if (camera is PerspectiveCamera)
                {
                    return new Ray(camera.Position.ToVector3(), r);
                }
                else if (camera is OrthographicCamera)
                {
                    return new Ray(zn, r);
                }
            }
            throw new HelixToolkitException("Unproject camera error.");
        }
Exemple #46
0
        /// <summary>
        /// Adds a cube face.
        /// </summary>
        /// <param name="center">
        /// The center of the cube.
        /// </param>
        /// <param name="normal">
        /// The normal vector for the face.
        /// </param>
        /// <param name="up">
        /// The up vector for the face.
        /// </param>
        /// <param name="dist">
        /// The dist from the center of the cube to the face.
        /// </param>
        /// <param name="width">
        /// The width of the face.
        /// </param>
        /// <param name="height">
        /// The height of the face.
        /// </param>
        private void AddCubeFace(Point3D center, Vector3D normal, Vector3D up, double dist, double width, double height)
        {
            var right = Vector3D.Cross(normal, up);
            var n = normal * (float)dist / 2;
            up *= (float)height / 2f;
            right *= (float)width / 2f;
            var p1 = center + n - up - right;
            var p2 = center + n - up + right;
            var p3 = center + n + up + right;
            var p4 = center + n + up - right;

            int i0 = this.positions.Count;
            this.positions.Add(p1);
            this.positions.Add(p2);
            this.positions.Add(p3);
            this.positions.Add(p4);

            if (this.normals != null)
            {
                this.normals.Add(normal);
                this.normals.Add(normal);
                this.normals.Add(normal);
                this.normals.Add(normal);
            }

            if (this.textureCoordinates != null)
            {
                this.textureCoordinates.Add(new Point(1, 1));
                this.textureCoordinates.Add(new Point(0, 1));
                this.textureCoordinates.Add(new Point(0, 0));
                this.textureCoordinates.Add(new Point(1, 0));
            }

            this.triangleIndices.Add(i0 + 2);
            this.triangleIndices.Add(i0 + 1);
            this.triangleIndices.Add(i0 + 0);

            this.triangleIndices.Add(i0 + 0);
            this.triangleIndices.Add(i0 + 3);
            this.triangleIndices.Add(i0 + 2);
        }
 public static Vector3? UnProjectOnPlane(this Viewport3DX viewport, Vector2 p, Vector3 position, Vector3 normal)
 {            
     var plane = new Plane(position, normal);
     return UnProjectOnPlane(viewport, p, plane);
 }
Exemple #48
0
        /// <summary>
        /// Adds the edges of a bounding box as cylinders.
        /// </summary>
        /// <param name="boundingBox">
        /// The bounding box.
        /// </param>
        /// <param name="diameter">
        /// The diameter of the cylinders.
        /// </param>
        public void AddBoundingBox(System.Windows.Media.Media3D.Rect3D boundingBox, double diameter)
        {
            var p0 = new Point3D((float)boundingBox.X, (float)boundingBox.Y, (float)boundingBox.Z);
            var p1 = new Point3D((float)boundingBox.X, (float)boundingBox.Y + (float)boundingBox.SizeY, (float)boundingBox.Z);
            var p2 = new Point3D((float)boundingBox.X + (float)boundingBox.SizeX, (float)boundingBox.Y + (float)boundingBox.SizeY, (float)boundingBox.Z);
            var p3 = new Point3D((float)boundingBox.X + (float)boundingBox.SizeX, (float)boundingBox.Y, (float)boundingBox.Z);
            var p4 = new Point3D((float)boundingBox.X, (float)boundingBox.Y, (float)boundingBox.Z + (float)boundingBox.SizeZ);
            var p5 = new Point3D((float)boundingBox.X, (float)boundingBox.Y + (float)boundingBox.SizeY, (float)boundingBox.Z + (float)boundingBox.SizeZ);
            var p6 = new Point3D((float)boundingBox.X + (float)boundingBox.SizeX, (float)boundingBox.Y + (float)boundingBox.SizeY, (float)boundingBox.Z + (float)boundingBox.SizeZ);
            var p7 = new Point3D((float)boundingBox.X + (float)boundingBox.SizeX, (float)boundingBox.Y, (float)boundingBox.Z + (float)boundingBox.SizeZ);

            Action<Point3D, Point3D> addEdge = (c1, c2) => this.AddCylinder(c1, c2, diameter, 10);

            addEdge(p0, p1);
            addEdge(p1, p2);
            addEdge(p2, p3);
            addEdge(p3, p0);

            addEdge(p4, p5);
            addEdge(p5, p6);
            addEdge(p6, p7);
            addEdge(p7, p4);

            addEdge(p0, p4);
            addEdge(p1, p5);
            addEdge(p2, p6);
            addEdge(p3, p7);
        }
Exemple #49
0
        /// <summary>
        /// Adds a surface of revolution.
        /// </summary>
        /// <param name="points">
        /// The points (y coordinates are radius, x coordinates are distance from the origin along the axis of revolution)
        /// </param>
        /// <param name="origin">
        /// The origin of the revolution axis.
        /// </param>
        /// <param name="direction">
        /// The direction of the revolution axis.
        /// </param>
        /// <param name="thetaDiv">
        /// The number of divisions around the mesh.
        /// </param>
        /// <remarks>
        /// See http://en.wikipedia.org/wiki/Surface_of_revolution.
        /// </remarks>
        public void AddRevolvedGeometry(IList<Point> points, Point3D origin, Vector3D direction, int thetaDiv)
        {
            direction.Normalize();

            // Find two unit vectors orthogonal to the specified direction
            var u = direction.FindAnyPerpendicular();
            var v = Vector3D.Cross(direction, u);

            u.Normalize();
            v.Normalize();

            var circle = GetCircle(thetaDiv);

            int index0 = this.positions.Count;
            int n = points.Count;

            int totalNodes = (points.Count - 1) * 2 * thetaDiv;
            int rowNodes = (points.Count - 1) * 2;

            for (int i = 0; i < thetaDiv; i++)
            {
                var w = (v * circle[i].X) + (u * circle[i].Y);

                for (int j = 0; j + 1 < n; j++)
                {
                    // Add segment
                    var q1 = origin + (direction * points[j].X) + (w * points[j].Y);
                    var q2 = origin + (direction * points[j + 1].X) + (w * points[j + 1].Y);

                    // todo:should not add segment if q1==q2 (corner point)
                    // const double eps = 1e-6;
                    // if (Point3D.Subtract(q1, q2).LengthSquared < eps)
                    // continue;
                    float tx = points[j + 1].X - points[j].X;
                    float ty = points[j + 1].Y - points[j].Y;

                    var normal = (-direction * ty) + (w * tx);
                    normal.Normalize();

                    this.positions.Add(q1);
                    this.positions.Add(q2);

                    if (this.normals != null)
                    {
                        this.normals.Add(normal);
                        this.normals.Add(normal);
                    }

                    if (this.textureCoordinates != null)
                    {
                        this.textureCoordinates.Add(new Point((float)i / (thetaDiv - 1), (float)j / (n - 1)));
                        this.textureCoordinates.Add(new Point((float)i / (thetaDiv - 1), (float)(j + 1) / (n - 1)));
                    }

                    int i0 = index0 + (i * rowNodes) + (j * 2);
                    int i1 = i0 + 1;
                    int i2 = index0 + ((((i + 1) * rowNodes) + (j * 2)) % totalNodes);
                    int i3 = i2 + 1;

                    this.triangleIndices.Add(i1);
                    this.triangleIndices.Add(i0);
                    this.triangleIndices.Add(i2);

                    this.triangleIndices.Add(i1);
                    this.triangleIndices.Add(i2);
                    this.triangleIndices.Add(i3);
                }
            }
        }
Exemple #50
0
        public void AddFaceNY()
        {
            var positions = new Vector3D[]
            {                                                                                                  
                new Vector3D(0,0,0), //p0
                new Vector3D(0,0,1), //p1
                new Vector3D(1,0,1), //p2
                new Vector3D(1,0,0), //p3
            };
            var normals = new Vector3D[]
            {
                -Vector3D.UnitY,
                -Vector3D.UnitY,
                -Vector3D.UnitY,
                -Vector3D.UnitY,
            };


            int i0 = this.positions.Count;
            var indices = new int[]
            {
                i0+0,i0+3,i0+2,
                i0+0,i0+2,i0+1,
            };
            var texcoords = new Point[]
            {
                new Point(0,1),
                new Point(1,1),
                new Point(1,0),
                new Point(0,0),
            };

            this.positions.AddRange(positions);
            this.normals.AddRange(normals);
            this.triangleIndices.AddRange(indices);
            this.textureCoordinates.AddRange(texcoords);
        }
Exemple #51
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;
        }
Exemple #52
0
        /// <summary>
        /// Chamfers the specified corner (experimental code).
        /// </summary>
        /// <param name="p">
        /// The corner point.
        /// </param>
        /// <param name="d">
        /// The chamfer distance.
        /// </param>
        /// <param name="eps">
        /// The corner search limit distance.
        /// </param>
        /// <param name="chamferPoints">
        /// If this parameter is provided, the collection will be filled with the generated chamfer points.
        /// </param>
        public void ChamferCorner(Point3D p, double d, double eps = 1e-6, IList<Point3D> chamferPoints = null)
        {
            this.NoSharedVertices();

            this.normals = null;
            this.textureCoordinates = null;

            var cornerNormal = this.FindCornerNormal(p, eps);

            var newCornerPoint = p - (cornerNormal * (float)d);
            int index0 = this.positions.Count;
            this.positions.Add(newCornerPoint);

            var plane = new Plane3D(newCornerPoint, cornerNormal);

            int ntri = this.triangleIndices.Count;

            for (int i = 0; i < ntri; i += 3)
            {
                int i0 = i;
                int i1 = i + 1;
                int i2 = i + 2;
                var p0 = this.positions[this.triangleIndices[i0]];
                var p1 = this.positions[this.triangleIndices[i1]];
                var p2 = this.positions[this.triangleIndices[i2]];
                var d0 = (p - p0).LengthSquared();
                var d1 = (p - p1).LengthSquared();
                var d2 = (p - p2).LengthSquared();
                var mind = Math.Min(d0, Math.Min(d1, d2));
                if (mind > eps)
                {
                    continue;
                }

                if (d1 < eps)
                {
                    i0 = i + 1;
                    i1 = i + 2;
                    i2 = i;
                }

                if (d2 < eps)
                {
                    i0 = i + 2;
                    i1 = i;
                    i2 = i + 1;
                }

                p0 = this.positions[this.triangleIndices[i0]];
                p1 = this.positions[this.triangleIndices[i1]];
                p2 = this.positions[this.triangleIndices[i2]];

                // p0 is the corner vertex (at index i0)
                // find the intersections between the chamfer plane and the two edges connected to the corner
                var line1 = new Ray(p0, p1 - p0);
                var line2 = new Ray(p0, p2 - p0);
                Point3D p01, p02;

                if (!plane.Intersects(ref line1, out p01))
                {
                    continue;
                }

                if (!plane.Intersects(ref line2, out p02))
                {
                    continue;
                }

                if (chamferPoints != null)
                {
                    // add the chamfered points
                    if (!chamferPoints.Contains(p01))
                    {
                        chamferPoints.Add(p01);
                    }

                    if (!chamferPoints.Contains(p02))
                    {
                        chamferPoints.Add(p02);
                    }
                }

                int i01 = i0;

                // change the original triangle to use the first chamfer point
                this.positions[this.triangleIndices[i01]] = p01;

                int i02 = this.positions.Count;
                this.positions.Add(p02);

                // add a new triangle for the other chamfer point
                this.triangleIndices.Add(i01);
                this.triangleIndices.Add(i2);
                this.triangleIndices.Add(i02);

                // add a triangle connecting the chamfer points and the new corner point
                this.triangleIndices.Add(index0);
                this.triangleIndices.Add(i01);
                this.triangleIndices.Add(i02);
            }

            this.NoSharedVertices();
        }
Exemple #53
0
        /// <summary>
        /// Subdivides each triangle into six triangles. Adds a vertex at the midpoint of each triangle.
        /// </summary>
        /// <remarks>
        /// See http://en.wikipedia.org/wiki/Barycentric_subdivision
        /// </remarks>
        private void SubdivideBarycentric()
        {
            // The BCS of a triangle S divides it into six triangles; each part has one vertex v2 at the
            // barycenter of S, another one v1 at the midpoint of some side, and the last one v0 at one
            // of the original vertices.
            int im = this.positions.Count;
            int ntri = this.triangleIndices.Count;
            for (int i = 0; i < ntri; i += 3)
            {
                int i0 = this.triangleIndices[i];
                int i1 = this.triangleIndices[i + 1];
                int i2 = this.triangleIndices[i + 2];
                var p0 = this.positions[i0];
                var p1 = this.positions[i1];
                var p2 = this.positions[i2];
                var v01 = p1 - p0;
                var v12 = p2 - p1;
                var v20 = p0 - p2;
                var p01 = p0 + (v01 * 0.5f);
                var p12 = p1 + (v12 * 0.5f);
                var p20 = p2 + (v20 * 0.5f);
                var m = new Point3D((p0.X + p1.X + p2.X) / 3, (p0.Y + p1.Y + p2.Y) / 3, (p0.Z + p1.Z + p2.Z) / 3);

                int i01 = im + 1;
                int i12 = im + 2;
                int i20 = im + 3;

                this.positions.Add(m);
                this.positions.Add(p01);
                this.positions.Add(p12);
                this.positions.Add(p20);

                if (this.normals != null)
                {
                    var n = this.normals[i0];
                    this.normals.Add(n);
                    this.normals.Add(n);
                    this.normals.Add(n);
                    this.normals.Add(n);
                }

                if (this.textureCoordinates != null)
                {
                    var uv0 = this.textureCoordinates[i0];
                    var uv1 = this.textureCoordinates[i0 + 1];
                    var uv2 = this.textureCoordinates[i0 + 2];
                    var t01 = uv1 - uv0;
                    var t12 = uv2 - uv1;
                    var t20 = uv0 - uv2;
                    var u01 = uv0 + (t01 * 0.5f);
                    var u12 = uv1 + (t12 * 0.5f);
                    var u20 = uv2 + (t20 * 0.5f);
                    var uvm = new Point((uv0.X + uv1.X) * 0.5f, (uv0.Y + uv1.Y) * 0.5f);
                    this.textureCoordinates.Add(uvm);
                    this.textureCoordinates.Add(u01);
                    this.textureCoordinates.Add(u12);
                    this.textureCoordinates.Add(u20);
                }

                // TriangleIndices[i ] = i0;
                this.triangleIndices[i + 1] = i01;
                this.triangleIndices[i + 2] = im;

                this.triangleIndices.Add(i01);
                this.triangleIndices.Add(i1);
                this.triangleIndices.Add(im);

                this.triangleIndices.Add(i1);
                this.triangleIndices.Add(i12);
                this.triangleIndices.Add(im);

                this.triangleIndices.Add(i12);
                this.triangleIndices.Add(i2);
                this.triangleIndices.Add(im);

                this.triangleIndices.Add(i2);
                this.triangleIndices.Add(i20);
                this.triangleIndices.Add(im);

                this.triangleIndices.Add(i20);
                this.triangleIndices.Add(i0);
                this.triangleIndices.Add(im);

                im += 4;
            }
        }
Exemple #54
0
        /// <summary>
        /// Adds a box with the specifed faces, aligned with the X, Y and Z axes.
        /// </summary>
        /// <param name="center">
        /// The center point of the box.
        /// </param>
        /// <param name="xlength">
        /// The length of the box along the X axis.
        /// </param>
        /// <param name="ylength">
        /// The length of the box along the Y axis.
        /// </param>
        /// <param name="zlength">
        /// The length of the box along the Z axis.
        /// </param>
        /// <param name="faces">
        /// The faces to include.
        /// </param>
        public void AddBox(Point3D center, double xlength, double ylength, double zlength, BoxFaces faces = BoxFaces.All)
        {
            if ((faces & BoxFaces.PositiveX) == BoxFaces.PositiveX)
            {
                this.AddCubeFace(center, new Vector3D(1, 0, 0), new Vector3D(0, 0, 1), xlength, ylength, zlength);
            }

            if ((faces & BoxFaces.NegativeX) == BoxFaces.NegativeX)
            {
                this.AddCubeFace(center, new Vector3D(-1, 0, 0), new Vector3D(0, 0, 1), xlength, ylength, zlength);
            }

            if ((faces & BoxFaces.NegativeY) == BoxFaces.NegativeY)
            {
                this.AddCubeFace(center, new Vector3D(0, -1, 0), new Vector3D(0, 0, 1), ylength, xlength, zlength);
            }

            if ((faces & BoxFaces.PositiveY) == BoxFaces.PositiveY)
            {
                this.AddCubeFace(center, new Vector3D(0, 1, 0), new Vector3D(0, 0, 1), ylength, xlength, zlength);
            }

            if ((faces & BoxFaces.PositiveZ) == BoxFaces.PositiveZ)
            {
                this.AddCubeFace(center, new Vector3D(0, 0, 1), new Vector3D(0, 1, 0), zlength, xlength, ylength);
            }

            if ((faces & BoxFaces.NegativeZ) == BoxFaces.NegativeZ)
            {
                this.AddCubeFace(center, new Vector3D(0, 0, -1), new Vector3D(0, 1, 0), zlength, xlength, ylength);
            }
        }
Exemple #55
0
        /// <summary>
        /// Finds the average normal to the specified corner (experimental code).
        /// </summary>
        /// <param name="p">
        /// The corner point.
        /// </param>
        /// <param name="eps">
        /// The corner search limit distance.
        /// </param>
        /// <returns>
        /// The normal.
        /// </returns>
        private Vector3D FindCornerNormal(Point3D p, double eps)
        {
            var sum = new Vector3D();
            int count = 0;
            var addedNormals = new HashSet<Vector3D>();
            for (int i = 0; i < this.triangleIndices.Count; i += 3)
            {
                int i0 = i;
                int i1 = i + 1;
                int i2 = i + 2;
                var p0 = this.positions[this.triangleIndices[i0]];
                var p1 = this.positions[this.triangleIndices[i1]];
                var p2 = this.positions[this.triangleIndices[i2]];

                // check if any of the vertices are on the corner
                double d0 = (p - p0).LengthSquared();
                double d1 = (p - p1).LengthSquared();
                double d2 = (p - p2).LengthSquared();
                double mind = Math.Min(d0, Math.Min(d1, d2));
                if (mind > eps)
                {
                    continue;
                }

                // calculate the triangle normal and check if this face is already added
                var normal = Vector3D.Cross(p1 - p0, p2 - p0);
                normal.Normalize();

                // todo: need to use the epsilon value to compare the normals?
                if (addedNormals.Contains(normal))
                {
                    continue;
                }

                // todo: this does not work yet
                // double dp = 1;
                // foreach (var n in addedNormals)
                // {
                // dp = Math.Abs(Vector3D.DotProduct(n, normal) - 1);
                // if (dp < eps)
                // continue;
                // }
                // if (dp < eps)
                // {
                // continue;
                // }
                count++;
                sum += normal;
                addedNormals.Add(normal);
            }

            if (count == 0)
            {
                return new Vector3D();
            }

            return sum * (1.0f / count);
        }
Exemple #56
0
 /// <summary>
 /// Adds a box aligned with the X, Y and Z axes.
 /// </summary>
 /// <param name="center">
 /// The center point of the box.
 /// </param>
 /// <param name="xlength">
 /// The length of the box along the X axis.
 /// </param>
 /// <param name="ylength">
 /// The length of the box along the Y axis.
 /// </param>
 /// <param name="zlength">
 /// The length of the box along the Z axis.
 /// </param>
 public void AddBox(Point3D center, double xlength, double ylength, double zlength)
 {
     this.AddBox(center, (float)xlength, (float)ylength, (float)zlength, BoxFaces.All);
 }
Exemple #57
0
 /// <summary>
 /// Returns a line geometry of the axis-aligned bounding-box of the given mesh.
 /// </summary>
 /// <param name="mesh">Input mesh for the computation of the b-box</param>
 /// <returns></returns>
 public static LineGeometry3D GenerateBoundingBox(Vector3[] points)
 {
     var bb = global::SharpDX.BoundingBox.FromPoints(points);
     return GenerateBoundingBox(bb);
 }
Exemple #58
0
        /// <summary>
        /// Adds a quadrilateral polygon.
        /// </summary>
        /// <param name="p0">
        /// The first point.
        /// </param>
        /// <param name="p1">
        /// The second point.
        /// </param>
        /// <param name="p2">
        /// The third point.
        /// </param>
        /// <param name="p3">
        /// The fourth point.
        /// </param>
        /// <param name="uv0">
        /// The first texture coordinate.
        /// </param>
        /// <param name="uv1">
        /// The second texture coordinate.
        /// </param>
        /// <param name="uv2">
        /// The third texture coordinate.
        /// </param>
        /// <param name="uv3">
        /// The fourth texture coordinate.
        /// </param>
        /// <remarks>
        /// See http://en.wikipedia.org/wiki/Quadrilateral.
        /// </remarks>
        public void AddQuad(Point3D p0, Point3D p1, Point3D p2, Point3D p3, Point uv0, Point uv1, Point uv2, Point uv3)
        {
            //// The nodes are arranged in counter-clockwise order
            //// p3               p2
            //// +---------------+
            //// |               |
            //// |               |
            //// +---------------+
            //// p0               p1
            int i0 = this.positions.Count;

            this.positions.Add(p0);
            this.positions.Add(p1);
            this.positions.Add(p2);
            this.positions.Add(p3);

            if (this.textureCoordinates != null)
            {
                this.textureCoordinates.Add(uv0);
                this.textureCoordinates.Add(uv1);
                this.textureCoordinates.Add(uv2);
                this.textureCoordinates.Add(uv3);
            }

            if (this.normals != null)
            {
                var w = Vector3D.Cross(p3 - p0, p1 - p0);
                w.Normalize();
                this.normals.Add(w);
                this.normals.Add(w);
                this.normals.Add(w);
                this.normals.Add(w);
            }

            this.triangleIndices.Add(i0 + 0);
            this.triangleIndices.Add(i0 + 1);
            this.triangleIndices.Add(i0 + 2);

            this.triangleIndices.Add(i0 + 2);
            this.triangleIndices.Add(i0 + 3);
            this.triangleIndices.Add(i0 + 0);
        }
Exemple #59
0
 /// <summary>
 /// Rotate the camera around the specified point.
 /// </summary>
 /// <param name="p0">
 /// The p 0.
 /// </param>
 /// <param name="p1">
 /// The p 1.
 /// </param>
 /// <param name="rotateAround">
 /// The rotate around.
 /// </param>
 public void Rotate(Point p0, Point p1, Vector3 rotateAround)
 {
     Rotate(p0.ToVector2(), p1.ToVector2(), rotateAround);
 }
Exemple #60
0
        /// <summary>
        /// Generates a square grid with a step of 1.0 
        /// </summary>
        /// <returns></returns>
        public static LineGeometry3D GenerateGrid(Vector3 plane, int min = 0, int max = 10)
        {
            var grid = new LineBuilder();
            //int width = max - min;
            if (plane == Vector3.UnitX)
            {
                for (int i = min; i <= max; i++)
                {
                    grid.AddLine(new Vector3(0, i, min), new Vector3(0, i, max));
                    grid.AddLine(new Vector3(0, min, i), new Vector3(0, max, i));
                }
            }
            else if (plane == Vector3.UnitY)
            {
                for (int i = min; i <= max; i++)
                {
                    grid.AddLine(new Vector3(i, 0, min), new Vector3(i, 0, max));
                    grid.AddLine(new Vector3(min, 0, i), new Vector3(max, 0, i));
                }
            }
            else
            {
                for (int i = min; i <= max; i++)
                {
                    grid.AddLine(new Vector3(i, min, 0), new Vector3(i, max, 0));
                    grid.AddLine(new Vector3(min, i, 0), new Vector3(max, i, 0));
                }
            }

            return grid.ToLineGeometry3D();
        }