How to draw lines in Viewport3D?

Emon Haque 3,176 Reputation points
2021-04-14T20:41:58.077+00:00

Was looking at some examples of 3D drawing and used the approach shown here to draw y = x^2 + z^2 and a plane at y=0 in Viewport3D. Here's how it looks like:

87897-test1.gif

and here's the code:

class Plot3D : FrameworkElement  
{  
    Viewport3D viewPort;  
    PerspectiveCamera camera;  
    Model3DGroup group;  
    Point3DAnimationUsingKeyFrames positionAnim;  
    Vector3DAnimationUsingKeyFrames lookAnim;  

    public Plot3D() {  
        camera = new PerspectiveCamera() {  
            FieldOfView = 120,  
            LookDirection = new Vector3D(0, -12, 9),  
            Position = new Point3D(0, 12, -9),  
            UpDirection = new Vector3D(0, 1, 0)  
        };  

        group = new Model3DGroup() { Children = { new AmbientLight(Colors.White) } };  
        viewPort = new Viewport3D() {  
            Camera = camera,  
            Children = { new ModelVisual3D() { Content = group } }  
        };  
        AddVisualChild(viewPort);  
        addModel();  

        positionAnim = new Point3DAnimationUsingKeyFrames() {  
            KeyFrames = {  
                new LinearPoint3DKeyFrame(new Point3D( 0, 12,-9), TimeSpan.FromSeconds(0)),  
                new LinearPoint3DKeyFrame(new Point3D(-9, 12, 0), TimeSpan.FromSeconds(5)),  
                new LinearPoint3DKeyFrame(new Point3D( 0, 12, 9), TimeSpan.FromSeconds(10)),  
                new LinearPoint3DKeyFrame(new Point3D( 9, 12, 0), TimeSpan.FromSeconds(15)),  
                new LinearPoint3DKeyFrame(new Point3D( 0, 12,-9), TimeSpan.FromSeconds(20))  
            },  
            RepeatBehavior = RepeatBehavior.Forever  
        };  
        lookAnim = new Vector3DAnimationUsingKeyFrames() {  
            KeyFrames = {  
                new LinearVector3DKeyFrame(new Vector3D( 0, -12, 9), TimeSpan.FromSeconds(0)),  
                new LinearVector3DKeyFrame(new Vector3D( 9, -12, 0), TimeSpan.FromSeconds(5)),  
                new LinearVector3DKeyFrame(new Vector3D( 0, -12,-9), TimeSpan.FromSeconds(10)),  
                new LinearVector3DKeyFrame(new Vector3D(-9, -12, 0), TimeSpan.FromSeconds(15)),  
                new LinearVector3DKeyFrame(new Vector3D( 0, -12, 9), TimeSpan.FromSeconds(20))  
            },  
            RepeatBehavior = RepeatBehavior.Forever  
        };  
        Loaded += animate;  
    }  

    void animate(object sender, RoutedEventArgs e) {  
        camera.BeginAnimation(PerspectiveCamera.PositionProperty, positionAnim);  
        camera.BeginAnimation(PerspectiveCamera.LookDirectionProperty, lookAnim);  
    }  

    void addModel() {  
        var mesh = new MeshGeometry3D();  
        double dx, dz; dx = dz = 0.25;  
        for (double x = -2; x < 2; x += dx) {  
            for (double z = -2; z < 2; z += dz) {  
                var p1 = new Point3D(x, f(x, z), z);  
                var p2 = new Point3D(x + dx, f(x + dx, z), z);  
                var p3 = new Point3D(x + dx, f(x + dx, z + dz), z + dz);  
                var p4 = new Point3D(x, f(x, z + dz), z + dz);  
                addTriangle(mesh, p1, p2, p3);  
                addTriangle(mesh, p3, p4, p1);  
            }  
        }  
        var surface = new GeometryModel3D() {  
            Geometry = mesh,  
            Material = new DiffuseMaterial(Brushes.LightBlue),  
            BackMaterial = new DiffuseMaterial(Brushes.SkyBlue),  
        };  
        group.Children.Add(surface);  

        var plane = new GeometryModel3D() {  
            Geometry = new MeshGeometry3D() {  
                Positions = {  
                    new Point3D(-3, 0, 3),  
                    new Point3D( 3, 0, 3),  
                    new Point3D(-3, 0,-3),  
                    new Point3D( 3, 0,-3)  
                },  
                TriangleIndices = { 0, 1, 2, 2, 1, 3 }  
            },  
            Material = new DiffuseMaterial(Brushes.LightGray)  
        };  
        group.Children.Add(plane);  
          
        //var line = new Line() { X1 = 0, X2 = 0, Y1 = 0, Y2 = 8, Stroke = Brushes.Blue, StrokeThickness = 4 };  
        //var line2d = new Viewport2DVisual3D() {  
        //    Geometry = plane.Geometry,  
        //    Visual = line,  
        //    Material = new DiffuseMaterial(Brushes.Blue)  
        //};  
        //line2d.Material.SetValue(Viewport2DVisual3D.IsVisualHostMaterialProperty, true);  
        //viewPort.Children.Add(line2d);  
    }  

    double f(double x, double z) => x * x + z * z;  
    void addTriangle(MeshGeometry3D mesh, Point3D p1, Point3D p2, Point3D p3) {  
        int index1 = addPoint(mesh.Positions, p1);  
        int index2 = addPoint(mesh.Positions, p2);  
        int index3 = addPoint(mesh.Positions, p3);  
        mesh.TriangleIndices.Add(index1);  
        mesh.TriangleIndices.Add(index2);  
        mesh.TriangleIndices.Add(index3);  
    }  

    int addPoint(Point3DCollection positions, Point3D point) {  
        for (int i = 0; i < positions.Count; i++) {  
            if ((point.X == positions[i].X) &&  
                (point.Y == positions[i].Y) &&  
                (point.Z == positions[i].Z))  
                return i;  
        }  
        positions.Add(point);  
        return positions.Count - 1;  
    }  
    protected override Size ArrangeOverride(Size finalSize) {  
        viewPort.Width = finalSize.Width;  
        viewPort.Height = finalSize.Height;  
        viewPort.Measure(finalSize);  
        viewPort.Arrange(new Rect(viewPort.DesiredSize));  
        return finalSize;  
    }  
    protected override Visual GetVisualChild(int index) => viewPort;  
    protected override int VisualChildrenCount => 1;  
}  

in MainWindow.xaml, I've used it like:

<Grid Margin="20">  
    <cc:Plot3D/>  
</Grid>  

Wanted to draw some gridlines on the plane and the y-axis, perpendicular to the plane, BUT looks like there's is no Line3D, Ellipse3D, Path3D, etc. to draw lines, parametric curve or point in space!

How do you draw these in Viewport3D?

Developer technologies | Windows Presentation Foundation
{count} votes

Accepted answer
  1. DaisyTian-1203 11,646 Reputation points
    2021-04-15T08:23:40.94+00:00

    I add below code to your Plot3D, the code refers to three class MathUtils, Matrix3DStack and ScreenSpaceLines3D, they come from Microsoft's free, open source project, you can download it from 3DTools.

    public Plot3D()  
            {  
                //........Your code  
                Point3DCollection point3Ds_X = new Point3DCollection();  
                point3Ds_X.Add(new Point3D(0, 0, -20));  
                point3Ds_X.Add(new Point3D(0, 0, 20));  
                ScreenSpaceLines3D X_axis = new ScreenSpaceLines3D() { Points = point3Ds_X, Thickness = 2, Color = Colors.Red };  
      
      
                Point3DCollection point3Ds_Y = new Point3DCollection();  
                point3Ds_Y.Add(new Point3D(0, -20, 0));  
                point3Ds_Y.Add(new Point3D(0, 20, 0));  
                ScreenSpaceLines3D Y_axis = new ScreenSpaceLines3D() { Points = point3Ds_Y, Thickness = 2, Color = Colors.Green };  
      
      
                Point3DCollection point3Ds_Z = new Point3DCollection();  
                point3Ds_Z.Add(new Point3D(-20, 0, 0));  
                point3Ds_Z.Add(new Point3D(20, 0, 0));  
                ScreenSpaceLines3D Z_axis = new ScreenSpaceLines3D() { Points = point3Ds_Z, Thickness = 2, Color = Colors.Yellow };  
      
                viewPort.Children.Add(X_axis);  
                viewPort.Children.Add(Y_axis);  
                viewPort.Children.Add(Z_axis);  
                Loaded += animate;  
            }  
    

    And the result picture is:
    88136-2.gif


    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.