Bootstrap

C# WPF 绘制 3D 甜甜圈

using System;
using System.Windows.Media;
using System.Windows.Media.Media3D;

namespace CS3DSpring;

public static class Spring
{
    public const double _2PI = 2.0 * Math.PI;

    public static ModelVisual3D BuildDonutModelVisual3D(
        Point3D Center, double R = 50, int Segments = 360, double r = 10, Color? light = null, Brush? brush = null)
    {
        brush ??= Brushes.Green;
        var model = new ModelVisual3D() { Content = new Model3DGroup() };
        var group = model.Content as Model3DGroup;
        var collection = new Model3DCollection
            {
                new AmbientLight
                {
                    Color = light ?? Colors.White,
                }
            };


        var Positions = new Point3DCollection();
        var Indices = new Int32Collection();
        var Textures = new PointCollection();
        var geometry = new MeshGeometry3D();
        var material = new DiffuseMaterial(brush);

        double delta_angle = _2PI / Segments;
        double theta = 0.0;
        for (int i = 0; i < Segments; i++)
        {
            var phi = 0.0;
            for (int j = 0; j < Segments; j++)
            {
                Positions.Add(new 
                    ((R + r * Math.Cos(phi)) * Math.Cos(theta),
                     (R + r * Math.Cos(phi)) * Math.Sin(theta),
                     r * Math.Sin(phi)
                    ));
                phi += delta_angle;
            }
            theta += delta_angle;
        }

        for (int current_layer = 0; current_layer < Segments; current_layer++)
        {
            int next_layer = (current_layer + 1) % Segments;

            for(int current_point = 0; current_point < Segments; current_point++)
            {
                int next_point = (current_point + 1) % Segments;
                int p0 = current_layer * Segments + current_point;
                int p1 = current_layer * Segments + next_point;
                int p2 = next_layer * Segments + current_point;
                int p3 = next_layer * Segments + next_point;

                Indices.Add(p1);
                Indices.Add(p0);
                Indices.Add(p2);

                Indices.Add(p2);
                Indices.Add(p3);
                Indices.Add(p1);

            }
        }

        geometry.Positions = Positions;
        geometry.TriangleIndices = Indices;
        geometry.TextureCoordinates = Textures;
        collection.Add(new GeometryModel3D(geometry, material));
        group.Children = collection;
        return model;
    }
}

这个任务有两个关键点,一个是计算顶点坐标,按照甜甜圈的公式生成离散的顶点;第二个关键点是把三个点的下标作为一组,构成三角形。注意这里的三角形顶点顺序必须按照逆时针顺序,不然会看不见。

GitHub - yyl-20020115/CS3DSpring: Build 3D Donut and Spring model by code

;