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,681 questions
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Now, with a some ScreenSpaceLines3D
in the drawing the Plane and Parabolic surface looks like this:
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;
}
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);