How to add RadialGradientBrush as surface material.

asked 2021-04-15T21:01:39.333+00:00
Emon Haque 3,176 Reputation points

Now, with a some ScreenSpaceLines3D in the drawing the Plane and Parabolic surface looks like this:

88338-test1.gif

So the Back and Front materials are messed up because I couldn't figure out how TextureCoordinates work on the MeshGeometry3D! I wanted Red to start from the origin (x = y = z = 0), Blue at end and transition in between.

Here's the code and the Radial material part is in void addParabolicSurface() method:

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

    public Plot3D() {  
        camera = new PerspectiveCamera() {  
            FieldOfView = 80,  
            LookDirection = new Vector3D(0, -12, 9),  
            Position = new Point3D(0, 12, -9),  
            UpDirection = new Vector3D(0, 1, 0)  
        };  
        camera.LookDirection.Normalize();  
        models = new Model3DGroup() { Children = { new AmbientLight(Colors.White) } };  
        viewPort = new Viewport3D() {  
            Camera = camera,  
            Children = { new ModelVisual3D() { Content = models } }  
        };  
        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 addAxis() {  
        var xAxis = new ScreenSpaceLines3D() { Thickness = 1, Color = Colors.Green };  
        var zAxis = new ScreenSpaceLines3D() { Thickness = 1, Color = Colors.Red };  
        for (int i = -3; i < 4; i++) {  
            xAxis.Points.Add(new Point3D(i, 0, -3));  
            xAxis.Points.Add(new Point3D(i, 0, 3));  

            zAxis.Points.Add(new Point3D(-3, 0, i));  
            zAxis.Points.Add(new Point3D(3, 0, i));  
        }  
          
        var yAxis = new ScreenSpaceLines3D() {  
            Points = new Point3DCollection() {  
                new Point3D(0, 0, 0),  
                new Point3D(0, 8, 0)  
            },  
            Thickness = 1,  
            Color = Colors.Green  
        };  
        viewPort.Children.Add(xAxis);  
        viewPort.Children.Add(yAxis);  
        viewPort.Children.Add(zAxis);  
    }  

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

    void addModel() {  
        addParabolicSurface();  
        addPlane();  
        addAxis();  
    }  

    void addPlane() {  
        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)  
        };  
        models.Children.Add(plane);  
    }  

    void addParabolicSurface() {  
        var mesh = new MeshGeometry3D();  
        //mesh.TextureCoordinates.Add(new Point(0,1));  
        //mesh.TextureCoordinates.Add(new Point(1,1));  
        //mesh.TextureCoordinates.Add(new Point(1,0));  
        //mesh.TextureCoordinates.Add(new Point(0,0));  

        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);  

                mesh.TextureCoordinates.Add(new Point(p1.X, p1.Z));  
                mesh.TextureCoordinates.Add(new Point(p2.X, p2.Z));  
                mesh.TextureCoordinates.Add(new Point(p3.X, p3.Z));  
                mesh.TextureCoordinates.Add(new Point(p4.X, p4.Z));  

                addWires(p1, p2, p3, p4);  
            }  
        }  
        var radialBrush = new RadialGradientBrush() {  
            Center = new Point(0.5, 0.5),  
            GradientOrigin = new Point(0.5, 0.5),  
            GradientStops = {  
                    new GradientStop(Colors.Red, 0),  
                    new GradientStop(Colors.Blue, 1),  
                }  
        };  
        var surface = new GeometryModel3D() {  
            Geometry = mesh,  
            Material = new DiffuseMaterial(radialBrush),  
            BackMaterial = new DiffuseMaterial(radialBrush),  
        };  
        models.Children.Add(surface);  
    }  

    void addWires(Point3D p1, Point3D p2, Point3D p3, Point3D p4) {  
        var line = new ScreenSpaceLines3D() { Color = Colors.Gray, Thickness = 1 };  
        line.Points.Add(p1);  
        line.Points.Add(p2);  
        line.Points.Add(p2);  
        line.Points.Add(p3);  
        line.Points.Add(p3);  
        line.Points.Add(p4);  
        line.Points.Add(p4);  
        line.Points.Add(p1);  
        viewPort.Children.Add(line);  
    }  

    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;  
}  
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,172 questions
No comments
{count} votes

1 answer

Sort by: Most helpful
  1. answered 2021-04-16T08:26:23.017+00:00
    DaisyTian-1203 11,506 Reputation points

    How about adding a back meshBack for the models like below?

    var meshBack = new MeshGeometry3D();
                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(meshBack, p1, p2, p3);
                        addTriangle(meshBack, p3, p4, p1);
                        meshBack.TextureCoordinates.Add(new Point(p1.X, p1.Z));
                        meshBack.TextureCoordinates.Add(new Point(p2.X, p2.Z));
                        meshBack.TextureCoordinates.Add(new Point(p3.X, p3.Z));
                        meshBack.TextureCoordinates.Add(new Point(p4.X, p4.Z));
                        addWires(p1, p2, p3, p4);
                    }
                }
    
                var radialBrushBack = new RadialGradientBrush()
                {
                    Center = new Point(0.5, 0.5),
                    GradientOrigin = new Point(0.5, 0.5),
                    GradientStops = {
                         new GradientStop(Colors.White, 0),
                         new GradientStop(Colors.White, 1),
                     }
                };
                var surfaceBack = new GeometryModel3D()
                {
                    Geometry = meshBack,
                    Material = new DiffuseMaterial(radialBrushBack),
                    BackMaterial = new DiffuseMaterial(radialBrushBack),
                };
                models.Children.Add(surfaceBack);