question

EmonHaque-1485 avatar image
0 Votes"
EmonHaque-1485 asked EmonHaque-1485 commented

How to add RadialGradientBrush as surface material.

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-wpf
test1.gif (2.8 MiB)
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

DaisyTian-1203 avatar image
1 Vote"
DaisyTian-1203 answered EmonHaque-1485 commented

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);
· 1
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

@DaisyTian-MSFT, that doesn't work.

0 Votes 0 ·