3D转换WPF

我在3D WPF中绘制两个球体,其中包含Point3D(0,0,0)和Point3D(-1.0,1.0,2.0)等点,半径为0.10

现在我想绘制一个连接这些球体的圆柱体,我唯一拥有的是半径0.02。 我想知道如何计算这个圆柱体的3d点,高度,方向等。

我尝试通过找到中点btw球体点,它将圆柱体放置在这两个球体的中间但不是正确的方向。 我想以正确的角度旋转圆柱体。 我使用Vector3D.angleBetween(v1,v2)找到它给我“NaN”的角度。 我把我正在使用的代码放在下面。

Vector3D v1 = new Vector3D(0, 0, 0); Vector3D v2 = new Vector3D(1.0, -1.0, 2.0); Vector3D center = v1+ v2/2; Vector3D axis = Vector3D.CrossProduct(v1, v2); double angle = Vector3D.AngleBetween(v1, v2); AxisAngleRotation3D axisAngle = new AxisAngleRotation3D(axis, angle); RotateTransform3D myRotateTransform = new RotateTransform3D(axisAngle, center); center.X = myRotateTransform.CenterX; center.Y = myRotateTransform.CenterY; center.Z = myRotateTransform.CenterZ; 

[编辑]

首先非常感谢你的回应。 我在使用这个代码时遇到了一些问题。 但是我的观点不是在正确的方向上向两个圆点绘制圆柱体,也不是直到终点(它只连接到第二点)还有一点,如果Z轴的中点是(中点)。 Z = 0),甚至没有绘制圆柱体。

我只是想知道,是因为我画圈子的方式。 请看一下

 public ModelVisual3D CreateSphere(Point3D center, double radius, int u, int v, Color color) { Model3DGroup spear = new Model3DGroup(); if (u < 2 || v < 2) return null; Point3D[,] pts = new Point3D[u, v]; for (int i = 0; i < u; i++) { for (int j = 0; j < v; j++) { pts[i, j] = GetPosition(radius, i * 180 / (u - 1), j * 360 / (v - 1)); pts[i, j] += (Vector3D)center; } } Point3D[] p = new Point3D[4]; for (int i = 0; i < u - 1; i++) { for (int j = 0; j < v - 1; j++) { p[0] = pts[i, j]; p[1] = pts[i + 1, j]; p[2] = pts[i + 1, j + 1]; p[3] = pts[i, j + 1]; spear.Children.Add(CreateTriangleModel(p[0], p[1], p[2], color)); spear.Children.Add(CreateTriangleModel(p[2], p[3], p[0], color)); } } ModelVisual3D model = new ModelVisual3D(); model.Content = spear; return model; } private Point3D GetPosition(double radius, double theta, double phi) { Point3D pt = new Point3D(); double snt = Math.Sin(theta * Math.PI / 180); double cnt = Math.Cos(theta * Math.PI / 180); double snp = Math.Sin(phi * Math.PI / 180); double cnp = Math.Cos(phi * Math.PI / 180); pt.X = radius * snt * cnp; pt.Y = radius * cnt; pt.Z = -radius * snt * snp; return pt; } public Model3DGroup CreateTriangleFace(Point3D p0, Point3D p1, Point3D p2, Color color) { MeshGeometry3D mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); Vector3D normal = VectorHelper.CalcNormal(p0, p1, p2); mesh.Normals.Add(normal); mesh.Normals.Add(normal); mesh.Normals.Add(normal); Material material = new DiffuseMaterial(new SolidColorBrush(color)); GeometryModel3D model = new GeometryModel3D(mesh, material); Model3DGroup group = new Model3DGroup(); group.Children.Add(model); return group; } private class VectorHelper { public static Vector3D CalcNormal(Point3D p0, Point3D p1, Point3D p2) { Vector3D v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); Vector3D v1 = new Vector3D( p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); return Vector3D.CrossProduct(v0, v1); } } 

几乎和你的代码相同>

  my sample point are : p1 = Point3D(0,0,0) p2= Point3D(-1.0, 1.0, 2.0) p3= Point3D(-1.0, 1.0, 2.0) p4 =Point3D(1.0, -1.0, 2.0) 

我想绘制气缸btw p1到p2,p1到p3,p1到p4 p2到p3,p2到p4

如果您需要进一步澄清,请告诉我,我必须解决这个问题。 谢谢你所有的时间。

我已经将你的球体代码与我的例子集成在一起并且工作正常 – 圆柱连接两个球体。

inheritance人代码……

干杯,安迪

ViewPort和以前一样……

                

…而且背后的代码……

 using System; using System.Collections.Generic; using System.Timers; using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Threading; namespace wpfspin { ///  /// Interaction logic for Window1.xaml ///  public partial class Window1 : Window { public Window1() { InitializeComponent(); Init(new Point3D(0, 0, 30), new Point3D(0, 0, -30)); } private Timer _timer; private readonly List _models = new List(); private double _angle; public void Init(Point3D firstPoint, Point3D secondPoint) { var midPoint = firstPoint - secondPoint; _models.Add(CreateSphere(firstPoint, 10, 10, 10, Colors.AliceBlue )); _models.Add(CreateSphere(secondPoint, 10, 10, 10, Colors.AliceBlue)); _models.Add(GetCylinder(GetSurfaceMaterial(Colors.Red), secondPoint, 2, midPoint.Z)); _models.ForEach(x => mainViewport.Children.Add(x)); _timer = new Timer(10); _timer.Elapsed += TimerElapsed; _timer.Enabled = true; } void TimerElapsed(object sender, ElapsedEventArgs e) { Dispatcher.Invoke(DispatcherPriority.Normal, new Action(Transform), 0.5d); } public MaterialGroup GetSurfaceMaterial(Color colour) { var materialGroup = new MaterialGroup(); var emmMat = new EmissiveMaterial(new SolidColorBrush(colour)); materialGroup.Children.Add(emmMat); materialGroup.Children.Add(new DiffuseMaterial(new SolidColorBrush(colour))); var specMat = new SpecularMaterial(new SolidColorBrush(Colors.White), 30); materialGroup.Children.Add(specMat); return materialGroup; } public ModelVisual3D GetCube(MaterialGroup materialGroup, Point3D point, Size3D size) { var farPoint = new Point3D(point.X - (size.X / 2), point.Y - (size.Y / 2), point.Z - (size.Z / 2)); var nearPoint = new Point3D(point.X + (size.X / 2), point.Y + (size.Y / 2), point.Z + (size.Z / 2)); var cube = new Model3DGroup(); var p0 = new Point3D(farPoint.X, farPoint.Y, farPoint.Z); var p1 = new Point3D(nearPoint.X, farPoint.Y, farPoint.Z); var p2 = new Point3D(nearPoint.X, farPoint.Y, nearPoint.Z); var p3 = new Point3D(farPoint.X, farPoint.Y, nearPoint.Z); var p4 = new Point3D(farPoint.X, nearPoint.Y, farPoint.Z); var p5 = new Point3D(nearPoint.X, nearPoint.Y, farPoint.Z); var p6 = new Point3D(nearPoint.X, nearPoint.Y, nearPoint.Z); var p7 = new Point3D(farPoint.X, nearPoint.Y, nearPoint.Z); //front side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p3, p2, p6)); cube.Children.Add(CreateTriangleModel(materialGroup, p3, p6, p7)); //right side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p2, p1, p5)); cube.Children.Add(CreateTriangleModel(materialGroup, p2, p5, p6)); //back side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p1, p0, p4)); cube.Children.Add(CreateTriangleModel(materialGroup, p1, p4, p5)); //left side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p0, p3, p7)); cube.Children.Add(CreateTriangleModel(materialGroup, p0, p7, p4)); //top side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p7, p6, p5)); cube.Children.Add(CreateTriangleModel(materialGroup, p7, p5, p4)); //bottom side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p2, p3, p0)); cube.Children.Add(CreateTriangleModel(materialGroup, p2, p0, p1)); var model = new ModelVisual3D(); model.Content = cube; return model; } private Model3DGroup CreateTriangleModel(MaterialGroup materialGroup, Triangle triangle) { return CreateTriangleModel(materialGroup, triangle.P0, triangle.P1, triangle.P2); } private Model3DGroup CreateTriangleModel(Material material, Point3D p0, Point3D p1, Point3D p2) { var mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); var normal = CalculateNormal(p0, p1, p2); mesh.Normals.Add(normal); mesh.Normals.Add(normal); mesh.Normals.Add(normal); var model = new GeometryModel3D(mesh, material); var group = new Model3DGroup(); group.Children.Add(model); return group; } private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2) { var v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); var v1 = new Vector3D(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); return Vector3D.CrossProduct(v0, v1); } void Transform(double adjustBy) { _angle += adjustBy; var rotateTransform3D = new RotateTransform3D { CenterX = 0, CenterZ = 0 }; var axisAngleRotation3D = new AxisAngleRotation3D { Axis = new Vector3D(1, 1, 1), Angle = _angle }; rotateTransform3D.Rotation = axisAngleRotation3D; var myTransform3DGroup = new Transform3DGroup(); myTransform3DGroup.Children.Add(rotateTransform3D); _models.ForEach(x => x.Transform = myTransform3DGroup); } public ModelVisual3D GetCylinder(MaterialGroup materialGroup, Point3D midPoint, double radius, double depth) { var cylinder = new Model3DGroup(); var nearCircle = new CircleAssitor(); var farCircle = new CircleAssitor(); var twoPi = Math.PI * 2; var firstPass = true; double x; double y; var increment = 0.1d; for (double i = 0; i < twoPi + increment; i = i + increment) { x = (radius * Math.Cos(i)); y = (-radius * Math.Sin(i)); farCircle.CurrentTriangle.P0 = midPoint; farCircle.CurrentTriangle.P1 = farCircle.LastPoint; farCircle.CurrentTriangle.P2 = new Point3D(x + midPoint.X, y + midPoint.Y, midPoint.Z); nearCircle.CurrentTriangle = farCircle.CurrentTriangle.Clone(depth, true); if (!firstPass) { cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle)); cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle)); cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle.P2, farCircle.CurrentTriangle.P1, nearCircle.CurrentTriangle.P2)); cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle.P2, nearCircle.CurrentTriangle.P1, farCircle.CurrentTriangle.P2)); } else { farCircle.FirstPoint = farCircle.CurrentTriangle.P1; nearCircle.FirstPoint = nearCircle.CurrentTriangle.P1; firstPass = false; } farCircle.LastPoint = farCircle.CurrentTriangle.P2; nearCircle.LastPoint = nearCircle.CurrentTriangle.P2; } var model = new ModelVisual3D { Content = cylinder }; return model; } public ModelVisual3D CreateSphere(Point3D center, double radius, int u, int v, Color color) { Model3DGroup spear = new Model3DGroup(); if (u < 2 || v < 2) return null; Point3D[,] pts = new Point3D[u, v]; for (int i = 0; i < u; i++) { for (int j = 0; j < v; j++) { pts[i, j] = GetPosition(radius, i * 180 / (u - 1), j * 360 / (v - 1)); pts[i, j] += (Vector3D)center; } } Point3D[] p = new Point3D[4]; for (int i = 0; i < u - 1; i++) { for (int j = 0; j < v - 1; j++) { p[0] = pts[i, j]; p[1] = pts[i + 1, j]; p[2] = pts[i + 1, j + 1]; p[3] = pts[i, j + 1]; spear.Children.Add(CreateTriangleFace(p[0], p[1], p[2], color)); spear.Children.Add(CreateTriangleFace(p[2], p[3], p[0], color)); } } ModelVisual3D model = new ModelVisual3D(); model.Content = spear; return model; } private Point3D GetPosition(double radius, double theta, double phi) { Point3D pt = new Point3D(); double snt = Math.Sin(theta * Math.PI / 180); double cnt = Math.Cos(theta * Math.PI / 180); double snp = Math.Sin(phi * Math.PI / 180); double cnp = Math.Cos(phi * Math.PI / 180); pt.X = radius * snt * cnp; pt.Y = radius * cnt; pt.Z = -radius * snt * snp; return pt; } public Model3DGroup CreateTriangleFace(Point3D p0, Point3D p1, Point3D p2, Color color) { MeshGeometry3D mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); Vector3D normal = VectorHelper.CalcNormal(p0, p1, p2); mesh.Normals.Add(normal); mesh.Normals.Add(normal); mesh.Normals.Add(normal); Material material = new DiffuseMaterial( new SolidColorBrush(color)); GeometryModel3D model = new GeometryModel3D( mesh, material); Model3DGroup group = new Model3DGroup(); group.Children.Add(model); return group; } private class VectorHelper { public static Vector3D CalcNormal(Point3D p0, Point3D p1, Point3D p2) { Vector3D v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); Vector3D v1 = new Vector3D(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); return Vector3D.CrossProduct(v0, v1); } } } public class CircleAssitor { public CircleAssitor() { CurrentTriangle = new Triangle(); } public Point3D FirstPoint { get; set; } public Point3D LastPoint { get; set; } public Triangle CurrentTriangle { get; set; } } public class Triangle { public Point3D P0 { get; set; } public Point3D P1 { get; set; } public Point3D P2 { get; set; } public Triangle Clone(double z, bool switchP1andP2) { var newTriangle = new Triangle(); newTriangle.P0 = GetPointAdjustedBy(this.P0, new Point3D(0, 0, z)); var point1 = GetPointAdjustedBy(this.P1, new Point3D(0, 0, z)); var point2 = GetPointAdjustedBy(this.P2, new Point3D(0, 0, z)); if (!switchP1andP2) { newTriangle.P1 = point1; newTriangle.P2 = point2; } else { newTriangle.P1 = point2; newTriangle.P2 = point1; } return newTriangle; } private Point3D GetPointAdjustedBy(Point3D point, Point3D adjustBy) { var newPoint = new Point3D { X = point.X, Y = point.Y, Z = point.Z }; newPoint.Offset(adjustBy.X, adjustBy.Y, adjustBy.Z); return newPoint; } } 

}

我不知道这对你是否有用,但是你对我最近发布的一些类似的代码发表了评论,请求帮助 – 所以我想我会将这些代码转换为两个对象,通过3D旋转连接space – Init()方法需要两个点,在点处创建10x10x10立方体,然后用圆柱体连接它们。

我认为这大致是你想要实现的,虽然我承认我的例子有点做作,(你只能在!!!中的两个点上改变Z轴),但希望你能得到一些东西它!

对不起代码有点乱,但是我已经从我的一些课程中编译了它,把它变成一个简单的剪切和粘贴的块!

无论如何,希望这有助于……

inheritance人XAML ……这只是设置ViewPort和光源……

                

…而且背后的代码……

  using System; using System.Collections.Generic; using System.Timers; using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Threading; namespace WpfApplication1 { ///  /// Interaction logic for Window1.xaml ///  public partial class Window1 : Window { public Window1() { InitializeComponent(); Init(new Point3D(0, 0, 30), new Point3D(0,0,-30)); } private Timer _timer; private readonly List _models = new List(); private double _angle; public void Init(Point3D firstPoint, Point3D secondPoint) { var midPoint = firstPoint - secondPoint; var size = new Size3D(10,10,10); _models.Add(GetCube(GetSurfaceMaterial(Colors.Green), firstPoint, size)); _models.Add(GetCube(GetSurfaceMaterial(Colors.Green), secondPoint, size)); _models.Add(GetCylinder(GetSurfaceMaterial(Colors.Red), secondPoint, 2, midPoint.Z)); _models.ForEach(x => mainViewport.Children.Add(x)); _timer = new Timer(10); _timer.Elapsed += TimerElapsed; _timer.Enabled = true; } void TimerElapsed(object sender, ElapsedEventArgs e) { Dispatcher.Invoke(DispatcherPriority.Normal, new Action(Transform), 0.5d); } public MaterialGroup GetSurfaceMaterial(Color colour) { var materialGroup = new MaterialGroup(); var emmMat = new EmissiveMaterial(new SolidColorBrush(colour)); materialGroup.Children.Add(emmMat); materialGroup.Children.Add(new DiffuseMaterial(new SolidColorBrush(colour))); var specMat = new SpecularMaterial(new SolidColorBrush(Colors.White), 30); materialGroup.Children.Add(specMat); return materialGroup; } public ModelVisual3D GetCube(MaterialGroup materialGroup, Point3D point, Size3D size) { var farPoint = new Point3D(point.X - (size.X / 2), point.Y - (size.Y / 2), point.Z - (size.Z / 2)); var nearPoint = new Point3D(point.X + (size.X / 2), point.Y + (size.Y / 2), point.Z + (size.Z / 2)); var cube = new Model3DGroup(); var p0 = new Point3D(farPoint.X, farPoint.Y, farPoint.Z); var p1 = new Point3D(nearPoint.X, farPoint.Y, farPoint.Z); var p2 = new Point3D(nearPoint.X, farPoint.Y, nearPoint.Z); var p3 = new Point3D(farPoint.X, farPoint.Y, nearPoint.Z); var p4 = new Point3D(farPoint.X, nearPoint.Y, farPoint.Z); var p5 = new Point3D(nearPoint.X, nearPoint.Y, farPoint.Z); var p6 = new Point3D(nearPoint.X, nearPoint.Y, nearPoint.Z); var p7 = new Point3D(farPoint.X, nearPoint.Y, nearPoint.Z); //front side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p3, p2, p6)); cube.Children.Add(CreateTriangleModel(materialGroup, p3, p6, p7)); //right side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p2, p1, p5)); cube.Children.Add(CreateTriangleModel(materialGroup, p2, p5, p6)); //back side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p1, p0, p4)); cube.Children.Add(CreateTriangleModel(materialGroup, p1, p4, p5)); //left side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p0, p3, p7)); cube.Children.Add(CreateTriangleModel(materialGroup, p0, p7, p4)); //top side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p7, p6, p5)); cube.Children.Add(CreateTriangleModel(materialGroup, p7, p5, p4)); //bottom side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p2, p3, p0)); cube.Children.Add(CreateTriangleModel(materialGroup, p2, p0, p1)); var model = new ModelVisual3D(); model.Content = cube; return model; } private Model3DGroup CreateTriangleModel(MaterialGroup materialGroup, Triangle triangle) { return CreateTriangleModel(materialGroup, triangle.P0, triangle.P1, triangle.P2); } private Model3DGroup CreateTriangleModel(Material material, Point3D p0, Point3D p1, Point3D p2) { var mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); var normal = CalculateNormal(p0, p1, p2); mesh.Normals.Add(normal); mesh.Normals.Add(normal); mesh.Normals.Add(normal); var model = new GeometryModel3D(mesh, material); var group = new Model3DGroup(); group.Children.Add(model); return group; } private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2) { var v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); var v1 = new Vector3D(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); return Vector3D.CrossProduct(v0, v1); } void Transform(double adjustBy) { _angle += adjustBy; var rotateTransform3D = new RotateTransform3D {CenterX = 0, CenterZ = 0}; var axisAngleRotation3D = new AxisAngleRotation3D {Axis = new Vector3D(1, 1, 1), Angle = _angle}; rotateTransform3D.Rotation = axisAngleRotation3D; var myTransform3DGroup = new Transform3DGroup(); myTransform3DGroup.Children.Add(rotateTransform3D); _models.ForEach(x => x.Transform = myTransform3DGroup); } public ModelVisual3D GetCylinder(MaterialGroup materialGroup, Point3D midPoint, double radius, double depth) { var cylinder = new Model3DGroup(); var nearCircle = new CircleAssitor(); var farCircle = new CircleAssitor(); var twoPi = Math.PI * 2; var firstPass = true; double x; double y; var increment = 0.1d; for (double i = 0; i < twoPi + increment; i = i + increment) { x = (radius * Math.Cos(i)); y = (-radius * Math.Sin(i)); farCircle.CurrentTriangle.P0 = midPoint; farCircle.CurrentTriangle.P1 = farCircle.LastPoint; farCircle.CurrentTriangle.P2 = new Point3D(x + midPoint.X, y + midPoint.Y, midPoint.Z); nearCircle.CurrentTriangle = farCircle.CurrentTriangle.Clone(depth, true); if (!firstPass) { cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle)); cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle)); cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle.P2, farCircle.CurrentTriangle.P1, nearCircle.CurrentTriangle.P2)); cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle.P2, nearCircle.CurrentTriangle.P1, farCircle.CurrentTriangle.P2)); } else { farCircle.FirstPoint = farCircle.CurrentTriangle.P1; nearCircle.FirstPoint = nearCircle.CurrentTriangle.P1; firstPass = false; } farCircle.LastPoint = farCircle.CurrentTriangle.P2; nearCircle.LastPoint = nearCircle.CurrentTriangle.P2; } var model = new ModelVisual3D {Content = cylinder}; return model; } } public class CircleAssitor { public CircleAssitor() { CurrentTriangle = new Triangle(); } public Point3D FirstPoint { get; set; } public Point3D LastPoint { get; set; } public Triangle CurrentTriangle { get; set; } } public class Triangle { public Point3D P0 { get; set; } public Point3D P1 { get; set; } public Point3D P2 { get; set; } public Triangle Clone(double z, bool switchP1andP2) { var newTriangle = new Triangle(); newTriangle.P0 = GetPointAdjustedBy(this.P0, new Point3D(0, 0, z)); var point1 = GetPointAdjustedBy(this.P1, new Point3D(0, 0, z)); var point2 = GetPointAdjustedBy(this.P2, new Point3D(0, 0, z)); if (!switchP1andP2) { newTriangle.P1 = point1; newTriangle.P2 = point2; } else { newTriangle.P1 = point2; newTriangle.P2 = point1; } return newTriangle; } private Point3D GetPointAdjustedBy(Point3D point, Point3D adjustBy) { var newPoint = new Point3D { X = point.X, Y = point.Y, Z = point.Z }; newPoint.Offset(adjustBy.X, adjustBy.Y, adjustBy.Z); return newPoint; } } } 

inheritance了更多代码 – 我想我找到了一个解决方案……

再次,它是一个拼凑的例子,你必须改进。

请注意,转换代码发生了巨大变化,我只是自己掌握了WPF 3D,并且我意识到我做了很多错事。 我每次都在重新创建Transform3DGroup,而不仅仅是改变已经应用的Transform的角度。

看看代码并注意altTransform组 – 我正在做的是为这个alt组添加额外的转换。 然后我在圆柱体和球体上使用altTransform,否则它将与其他圆柱体和球体之一处于相同的位置。 我把这个圆筒标记为绿色,这样你就可以看到它是哪一个。

我的建议是,您在同一轴上创建所有球体和圆柱体,然后将它们转换为您想要的位置。

我还将球体和圆柱体尺寸更改为您在之前的评论中所要求的尺寸。

看看代码,看看你的想法?

干杯,

安迪

                  

而后面的代码……

 using System; using System.Collections.Generic; using System.Timers; using System.Windows; using System.Windows.Media; using System.Windows.Media.Media3D; using System.Windows.Threading; namespace wpfspin { ///  /// Interaction logic for Window1.xaml ///  public partial class Window1 : Window { public Window1() { InitializeComponent(); Init(); } private Timer _timer; private readonly List _models = new List(); private double _angle; private Transform3DGroup _transform3DGroup; private AxisAngleRotation3D _axisAngleRotation3D; private Transform3DGroup _altTransform; public void Init() { _models.Add(CreateSphere(new Point3D(0,0,0), 0.1, 10, 10, Colors.AliceBlue)); _models.Add(CreateSphere(new Point3D(0,0,2), 0.1, 10, 10, Colors.AliceBlue)); //notice that the following two spheres are created in the same place _models.Add(CreateSphere(new Point3D(0, 0, -2), 0.1, 10, 10, Colors.AliceBlue)); _models.Add(CreateSphere(new Point3D(0, 0, -2), 0.1, 10, 10, Colors.AliceBlue)); _models.Add(GetCylinder(GetSurfaceMaterial(Colors.Red), new Point3D(0,0,0), 0.02, 2)); //notice that the following to cylinders are also created in the same place _models.Add(GetCylinder(GetSurfaceMaterial(Colors.Red), new Point3D(0, 0, 0), 0.02, -2)); _models.Add(GetCylinder(GetSurfaceMaterial(Colors.Green), new Point3D(0, 0, 0), 0.02, -2)); _transform3DGroup = new Transform3DGroup(); _models.ForEach(x => x.Transform = _transform3DGroup); //heres my alt transform that i'm just using for the duplicate sphere and cylinder _altTransform = new Transform3DGroup(); _models[3].Transform = _altTransform; _models[6].Transform = _altTransform; var rotateTransform3D = new RotateTransform3D { CenterX = 0, CenterZ = 0 }; _axisAngleRotation3D = new AxisAngleRotation3D { Axis = new Vector3D(1, 1, 1), Angle = _angle }; rotateTransform3D.Rotation = _axisAngleRotation3D; //i'm adding the animation rotation to both groups so that all my models spin _transform3DGroup.Children.Add(rotateTransform3D); _altTransform.Children.Add(rotateTransform3D); //but my alt transform gets an extra transformation var altRotate = new RotateTransform3D { CenterX = 0, CenterZ = 0 }; var altAxis = new AxisAngleRotation3D { Axis = new Vector3D(0, 1, 1), Angle = 90 }; altRotate.Rotation = altAxis; _altTransform.Children.Add(altRotate); _models.ForEach(x => mainViewport.Children.Add(x)); _timer = new Timer(10); _timer.Elapsed += TimerElapsed; _timer.Enabled = true; } void TimerElapsed(object sender, ElapsedEventArgs e) { Dispatcher.Invoke(DispatcherPriority.Normal, new Action(Transform), 0.5d); } public MaterialGroup GetSurfaceMaterial(Color colour) { var materialGroup = new MaterialGroup(); var emmMat = new EmissiveMaterial(new SolidColorBrush(colour)); materialGroup.Children.Add(emmMat); materialGroup.Children.Add(new DiffuseMaterial(new SolidColorBrush(colour))); var specMat = new SpecularMaterial(new SolidColorBrush(Colors.White), 30); materialGroup.Children.Add(specMat); return materialGroup; } public ModelVisual3D GetCube(MaterialGroup materialGroup, Point3D point, Size3D size) { var farPoint = new Point3D(point.X - (size.X / 2), point.Y - (size.Y / 2), point.Z - (size.Z / 2)); var nearPoint = new Point3D(point.X + (size.X / 2), point.Y + (size.Y / 2), point.Z + (size.Z / 2)); var cube = new Model3DGroup(); var p0 = new Point3D(farPoint.X, farPoint.Y, farPoint.Z); var p1 = new Point3D(nearPoint.X, farPoint.Y, farPoint.Z); var p2 = new Point3D(nearPoint.X, farPoint.Y, nearPoint.Z); var p3 = new Point3D(farPoint.X, farPoint.Y, nearPoint.Z); var p4 = new Point3D(farPoint.X, nearPoint.Y, farPoint.Z); var p5 = new Point3D(nearPoint.X, nearPoint.Y, farPoint.Z); var p6 = new Point3D(nearPoint.X, nearPoint.Y, nearPoint.Z); var p7 = new Point3D(farPoint.X, nearPoint.Y, nearPoint.Z); //front side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p3, p2, p6)); cube.Children.Add(CreateTriangleModel(materialGroup, p3, p6, p7)); //right side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p2, p1, p5)); cube.Children.Add(CreateTriangleModel(materialGroup, p2, p5, p6)); //back side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p1, p0, p4)); cube.Children.Add(CreateTriangleModel(materialGroup, p1, p4, p5)); //left side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p0, p3, p7)); cube.Children.Add(CreateTriangleModel(materialGroup, p0, p7, p4)); //top side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p7, p6, p5)); cube.Children.Add(CreateTriangleModel(materialGroup, p7, p5, p4)); //bottom side triangles cube.Children.Add(CreateTriangleModel(materialGroup, p2, p3, p0)); cube.Children.Add(CreateTriangleModel(materialGroup, p2, p0, p1)); var model = new ModelVisual3D(); model.Content = cube; return model; } private Model3DGroup CreateTriangleModel(MaterialGroup materialGroup, Triangle triangle) { return CreateTriangleModel(materialGroup, triangle.P0, triangle.P1, triangle.P2); } private Model3DGroup CreateTriangleModel(Material material, Point3D p0, Point3D p1, Point3D p2) { var mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); var normal = CalculateNormal(p0, p1, p2); mesh.Normals.Add(normal); mesh.Normals.Add(normal); mesh.Normals.Add(normal); var model = new GeometryModel3D(mesh, material); var group = new Model3DGroup(); group.Children.Add(model); return group; } private Vector3D CalculateNormal(Point3D p0, Point3D p1, Point3D p2) { var v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); var v1 = new Vector3D(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); return Vector3D.CrossProduct(v0, v1); } void Transform(double adjustBy) { _angle += adjustBy; _axisAngleRotation3D.Angle = _angle; } public ModelVisual3D GetCylinder(MaterialGroup materialGroup, Point3D midPoint, double radius, double depth) { var cylinder = new Model3DGroup(); var nearCircle = new CircleAssitor(); var farCircle = new CircleAssitor(); var twoPi = Math.PI * 2; var firstPass = true; double x; double y; var increment = 0.1d; for (double i = 0; i < twoPi + increment; i = i + increment) { x = (radius * Math.Cos(i)); y = (-radius * Math.Sin(i)); farCircle.CurrentTriangle.P0 = midPoint; farCircle.CurrentTriangle.P1 = farCircle.LastPoint; farCircle.CurrentTriangle.P2 = new Point3D(x + midPoint.X, y + midPoint.Y, midPoint.Z); nearCircle.CurrentTriangle = farCircle.CurrentTriangle.Clone(depth, true); if (!firstPass) { cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle)); cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle)); cylinder.Children.Add(CreateTriangleModel(materialGroup, farCircle.CurrentTriangle.P2, farCircle.CurrentTriangle.P1, nearCircle.CurrentTriangle.P2)); cylinder.Children.Add(CreateTriangleModel(materialGroup, nearCircle.CurrentTriangle.P2, nearCircle.CurrentTriangle.P1, farCircle.CurrentTriangle.P2)); } else { farCircle.FirstPoint = farCircle.CurrentTriangle.P1; nearCircle.FirstPoint = nearCircle.CurrentTriangle.P1; firstPass = false; } farCircle.LastPoint = farCircle.CurrentTriangle.P2; nearCircle.LastPoint = nearCircle.CurrentTriangle.P2; } var model = new ModelVisual3D { Content = cylinder }; return model; } public ModelVisual3D CreateSphere(Point3D center, double radius, int u, int v, Color color) { Model3DGroup spear = new Model3DGroup(); if (u < 2 || v < 2) return null; Point3D[,] pts = new Point3D[u, v]; for (int i = 0; i < u; i++) { for (int j = 0; j < v; j++) { pts[i, j] = GetPosition(radius, i * 180 / (u - 1), j * 360 / (v - 1)); pts[i, j] += (Vector3D)center; } } Point3D[] p = new Point3D[4]; for (int i = 0; i < u - 1; i++) { for (int j = 0; j < v - 1; j++) { p[0] = pts[i, j]; p[1] = pts[i + 1, j]; p[2] = pts[i + 1, j + 1]; p[3] = pts[i, j + 1]; spear.Children.Add(CreateTriangleFace(p[0], p[1], p[2], color)); spear.Children.Add(CreateTriangleFace(p[2], p[3], p[0], color)); } } ModelVisual3D model = new ModelVisual3D(); model.Content = spear; return model; } private Point3D GetPosition(double radius, double theta, double phi) { Point3D pt = new Point3D(); double snt = Math.Sin(theta * Math.PI / 180); double cnt = Math.Cos(theta * Math.PI / 180); double snp = Math.Sin(phi * Math.PI / 180); double cnp = Math.Cos(phi * Math.PI / 180); pt.X = radius * snt * cnp; pt.Y = radius * cnt; pt.Z = -radius * snt * snp; return pt; } public Model3DGroup CreateTriangleFace(Point3D p0, Point3D p1, Point3D p2, Color color) { MeshGeometry3D mesh = new MeshGeometry3D(); mesh.Positions.Add(p0); mesh.Positions.Add(p1); mesh.Positions.Add(p2); mesh.TriangleIndices.Add(0); mesh.TriangleIndices.Add(1); mesh.TriangleIndices.Add(2); Vector3D normal = VectorHelper.CalcNormal(p0, p1, p2); mesh.Normals.Add(normal); mesh.Normals.Add(normal); mesh.Normals.Add(normal); Material material = new DiffuseMaterial( new SolidColorBrush(color)); GeometryModel3D model = new GeometryModel3D( mesh, material); Model3DGroup group = new Model3DGroup(); group.Children.Add(model); return group; } private class VectorHelper { public static Vector3D CalcNormal(Point3D p0, Point3D p1, Point3D p2) { Vector3D v0 = new Vector3D(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); Vector3D v1 = new Vector3D(p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); return Vector3D.CrossProduct(v0, v1); } } } public class CircleAssitor { public CircleAssitor() { CurrentTriangle = new Triangle(); } public Point3D FirstPoint { get; set; } public Point3D LastPoint { get; set; } public Triangle CurrentTriangle { get; set; } } public class Triangle { public Point3D P0 { get; set; } public Point3D P1 { get; set; } public Point3D P2 { get; set; } public Triangle Clone(double z, bool switchP1andP2) { var newTriangle = new Triangle(); newTriangle.P0 = GetPointAdjustedBy(this.P0, new Point3D(0, 0, z)); var point1 = GetPointAdjustedBy(this.P1, new Point3D(0, 0, z)); var point2 = GetPointAdjustedBy(this.P2, new Point3D(0, 0, z)); if (!switchP1andP2) { newTriangle.P1 = point1; newTriangle.P2 = point2; } else { newTriangle.P1 = point2; newTriangle.P2 = point1; } return newTriangle; } private Point3D GetPointAdjustedBy(Point3D point, Point3D adjustBy) { var newPoint = new Point3D { X = point.X, Y = point.Y, Z = point.Z }; newPoint.Offset(adjustBy.X, adjustBy.Y, adjustBy.Z); return newPoint; } } }