WPF 3D开发教程(四)

四、实战:展示一个圆柱体

4.1 圆柱体分解

我们知道,3D模型是用三角形表示的,那一个圆该如何表示呢?其实用的就是割圆法,也就是用一个近似的多边形就表示一个圆。下图展示了10、20、50个顶点的正多边形,可以看出,正50边形看上去跟圆已经很接近了。我们的例子就是用正50边形。

WPF 3D开发教程(四)_第1张图片

切分之后,圆柱体变成了如下所示的三棱体的组合:

WPF 3D开发教程(四)_第2张图片

我们需要描述这个三棱体的三个面,共4个三角形(侧面是一个矩形,需要两个三角形)。

4.2 三角网格构建

这是最重要的一部分。示例代码打算让三个面渲染出不同颜色,所以需要构造三个三角网格。

代码如下:

//底面三角网格
MeshGeometry3D bottom_mesh = new MeshGeometry3D() { Positions = new Point3DCollection(), TriangleIndices = new Int32Collection() };
//顶面三角网格
MeshGeometry3D top_mesh = new MeshGeometry3D() { Positions = new Point3DCollection(), TriangleIndices = new Int32Collection() };            
//侧面三角网格
MeshGeometry3D side_mesh = new MeshGeometry3D() { Positions = new Point3DCollection(), TriangleIndices = new Int32Collection() };

Point3D bottom_center = new Point3D(0, 0, 0);//底面中心
Point3D top_center = new Point3D(0, 2, 0);//顶面中心
top_mesh.Positions.Add(top_center);
bottom_mesh.Positions.Add(bottom_center);

int parts = 50;//把圆切成50份
double angle = Math.PI * 2 / parts;
for (int i = 0; i < parts; i++)
{
    double x1 = 1 * Math.Cos(angle * i);
    double z1 = 1 * Math.Sin(angle * i);
    double x2 = 1 * Math.Cos(angle * (i + 1));
    double z2 = 1 * Math.Sin(angle * (i + 1));

    Point3D bottom1 = new Point3D(x1, 0, z1);//底面
    Point3D bottom2 = new Point3D(x2, 0, z2);
    Point3D top1 = new Point3D(x1, 2, z1);
    Point3D top2 = new Point3D(x2, 2, z2);

    //底面
    bottom_mesh.Positions.Add(bottom1);
    bottom_mesh.Positions.Add(bottom2);

    bottom_mesh.TriangleIndices.Add(i * 2 + 1);
    bottom_mesh.TriangleIndices.Add(i * 2 + 2);
    bottom_mesh.TriangleIndices.Add(0);

    //顶面
    top_mesh.Positions.Add(top1);
    top_mesh.Positions.Add(top2);

    top_mesh.TriangleIndices.Add(i * 2 + 2);
    top_mesh.TriangleIndices.Add(i * 2 + 1);
    top_mesh.TriangleIndices.Add(0);

    //侧面
    if (i == 0)
    {
        side_mesh.Positions.Add(bottom1);
        side_mesh.Positions.Add(top1);
    }
    side_mesh.Positions.Add(bottom2);
    side_mesh.Positions.Add(top2);

    side_mesh.TriangleIndices.Add(i * 2 + 1);
    side_mesh.TriangleIndices.Add(i * 2 + 3);
    side_mesh.TriangleIndices.Add(i * 2 + 2);

    side_mesh.TriangleIndices.Add(i * 2 + 1);
    side_mesh.TriangleIndices.Add(i * 2 + 2);
    side_mesh.TriangleIndices.Add(i * 2 + 0);
}

DiffuseMaterial bottom_material = new DiffuseMaterial(Brushes.Green);//底面绿色
DiffuseMaterial top_material = new DiffuseMaterial(Brushes.Blue);//顶面蓝色
DiffuseMaterial side_material = new DiffuseMaterial(Brushes.Red);//侧面红色

GeometryModel3D top = new GeometryModel3D(top_mesh, top_material);
GeometryModel3D bottom = new GeometryModel3D(bottom_mesh, bottom_material);
GeometryModel3D side = new GeometryModel3D(side_mesh, side_material);

4.3 相机、光源和其他代码

首先看我们在XAML文件里定义的画布:


代码是非常简单的。然后我们把定义好的圆柱体三角网格、相机、光源都放进画布中:

//相机
Camera camera = new PerspectiveCamera(new Point3D(3, 6, 10), new Vector3D(-3, -6, -10), new Vector3D(0, 1, 0), 45);
//光源
Light light = new AmbientLight(Colors.White);

Model3DGroup group = new Model3DGroup();
group.Children.Add(light);
group.Children.Add(top);
group.Children.Add(bottom);
group.Children.Add(side);

ModelVisual3D model = new ModelVisual3D();
model.Content = group;

view.Children.Add(model);
view.Camera = camera;

如此一来,圆柱体就能正常显示了,如下图所示:

WPF 3D开发教程(四)_第3张图片

我们把相机的Position和LookDirection改成如下,从下面瞄一眼:

Camera camera = new PerspectiveCamera(new Point3D(3, -6, 10), new Vector3D(-3, 6, -10), new Vector3D(0, 1, 0), 45);

图像是:

WPF 3D开发教程(四)_第4张图片

你可能感兴趣的:(WPF)