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