Transformación 3D WPF

Dibujé dos esferas en 3d WPF que tiene puntos como Point3D (0,0,0) y Point3D (-1.0,1.0,2.0) con el radio es 0.10

Ahora quiero dibujar un cilindro que une estas esferas, lo único que tengo para esto es el radio 0.02. Quiero saber cómo calcular el punto 3D, la altura, la dirección, etc. para este cilindro.

Intenté encontrar el punto medio entre dos puntos de esfera, es colocar el cilindro en medio de esas dos esferas pero no en la dirección correcta. Quiero girar el cilindro en el ángulo correcto. Usé Vector3D.angleBetween (v1, v2) para encontrar el ángulo que me está dando “NaN”. Pongo el código que estoy usando a continuación.

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; 

[EDITAR]

En primer lugar muchas gracias por la respuesta. Tengo algunos problemas con este código. Está funcionando bien con tu ejemplo. pero con mis puntos No dibuja el cilindro entre los dos puntos circulares en una dirección correcta y tampoco hasta el punto final (solo se conecta al segundo punto) Una cosa más, si el punto medio del eje Z es (punto medio. Z = 0), ni siquiera dibuja el cilindro.

Me pregunto, ¿es por la forma en que estoy dibujando mi círculo? Por favor echa un vistazo

 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); } } 

casi igual que tu código>

  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) 

Quiero dibujar los cilindros por cierto p1 a p2, p1 a p3, p1 a p4 p2 a p3, p2 a p4

Por favor, avíseme si necesita más aclaraciones, tengo que sacar esto. Gracias por todo tu tiempo.

He integrado su código de esfera con mi ejemplo y funciona bien: el cilindro conecta ambas esferas.

Aquí está el código …

Saludos Andy

ViewPort como antes …

                

… y aquí está el código detrás …

 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; } } 

}

No sé si esto será de utilidad para usted, pero comentó sobre un código similar que publiqué recientemente, solicitando asistencia, así que pensé que convertiría ese código en dos objetos, conectados por un cilindro que gira en 3D. espacio: el método Init () toma dos puntos, crea cubos de 10x10x10 en los puntos y luego los conecta con un cilindro.

Creo que esto es más o menos lo que intentas lograr, aunque admito que mi ejemplo es un poco artificial (¡¡¡solo puedes cambiar el eje Z en cada uno de los dos puntos !!!), pero espero que obtengas algo de ¡eso!

Lo siento, el código es un poco desordenado, pero lo he comstackdo de varias de mis clases para integrarlo en un solo trozo fácil de cortar y pegar.

De todos modos, espero que esto ayude …

Aquí está el XAML … esto solo configura el ViewPort y la fuente de luz …

                

… y aquí está el código detrás …

  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; } } } 

Heres un poco más de código – creo que he encontrado una solución para ti …

Una vez más, es un ejemplo adoquinado que tendrá que refinar.

Tenga en cuenta que el código de transformación ha cambiado drásticamente, solo me estoy familiarizando con WPF 3D y me di cuenta de que estaba haciendo algunas cosas mal. Estaba recreando el Transform3DGroup cada vez en lugar de simplemente cambiar el ángulo de la Transformación que ya estaba aplicada.

Eche un vistazo al código y observe el grupo altTransform; lo que estoy haciendo es agregar una transfomación adicional a este grupo alt. Luego utilicé el altTransform en un cilindro y una esfera que de otra manera estarían en la misma posición que uno de los otros cilindros y esferas. He marcado este cilindro en verde para que puedas ver cuál es.

Mi sugerencia para usted es que cree todas sus esferas y cilindros en el mismo eje y luego los transforme a la ubicación deseada.

También cambié los tamaños de esfera y cilindro a lo que solicitó en un comentario anterior.

¿Echar un vistazo al código y ver lo que piensas?

Aclamaciones,

Andy

                  

y aquí está el código detrás …

 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; } } }