2009-08-13 54 views
1

我在3D WPF具有點狀三維點(0,0,0)和三維點繪製兩個球(-1.0,1.0,2.0)與半徑爲0.103D變換WPF

現在我想畫連接這些球體的圓柱體,我唯一擁有的是半徑0.02。我想知道如何計算這個氣缸的三維點,高度,方向等。

我試圖找到中點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的

請讓我知道如果你需要更多的澄清,我必須弄清楚。 感謝您的所有時間。

+0

嘿安迪...有沒有我可以通過指定開始繪製一個圓柱體的方式和終點... – SituStarz 2009-08-20 20:34:13

回答

0

我已經集成了你的球體代碼和我的例子,它工作正常 - 圓柱體c與這兩個領域相連。

繼承人的代碼...

乾杯,安迪

視口中之前...

<Window x:Class="wpfspin.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<StackPanel> 

    <Viewport3D Name="mainViewport" ClipToBounds="True" HorizontalAlignment="Stretch" Height="300"> 
     <Viewport3D.Camera> 
      <PerspectiveCamera 
       LookDirection="0,0,-20" 
       UpDirection="0,1,0" 
       Position="0,0,100" 
       /> 
     </Viewport3D.Camera> 
     <ModelVisual3D> 
      <ModelVisual3D.Content> 
       <Model3DGroup x:Name="group3d"> 

        <SpotLight Position="30,30,30" x:Name="mySpotLight" Color="Yellow" InnerConeAngle="100" OuterConeAngle="1000" Range="100" /> 
       </Model3DGroup> 
      </ModelVisual3D.Content> 

     </ModelVisual3D> 
    </Viewport3D> 

</StackPanel> 

...和繼承人後面的代碼...

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 
{ 
/// <summary> 
/// Interaction logic for Window1.xaml 
/// </summary> 
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<ModelVisual3D> _models = new List<ModelVisual3D>(); 
    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<double>(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; 
    } 

} 

}

+0

對不起,我上週末出城了。這是一個很好的解決方案。請嘗試以下幾點,如果可能,我的採樣點爲: 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。用我的點它不是在右方向畫兩個圓點的圓柱體,也不是直到結束點(它只連接到第二點)另外一點,如果Z軸的中點是(midpoint.Z = 0),它甚至不畫圓柱體。 – SituStarz 2009-08-17 15:18:10

+0

ps - 圓的半徑爲0.10,圓柱體爲0.02 – SituStarz 2009-08-17 15:22:03

+0

在你的評論中,p2和p3是一樣的嗎?你能重新檢查一下分數嗎? – 2009-08-17 19:22:22

0

我不知道這是否對你有用,但你評論了我最近發佈的一些類似的代碼,尋求幫助 - 所以我想我會將該代碼轉換成兩個對象,通過一個圓柱體連接在3D空間中旋轉 - Init()方法需要兩個點,在點處創建10x10x10立方體,然後將它們與圓柱體連接。我認爲這大致上是你想要達到的目標,儘管我承認我的例子有點做作,(你只能在兩個點的每一個上改變Z軸)!!!但是,我會從中得到一些東西!

對不起,代碼有點亂,但我已經從我的一些類中編譯出來,將它編譯成易於剪切和粘貼的塊!

不管怎麼說,希望這有助於...

繼承人的XAML ...這只是設置的視口,光源...

<Window x:Class="WpfApplication1.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="300" Width="300"> 
<StackPanel> 

    <Viewport3D Name="mainViewport" ClipToBounds="True" HorizontalAlignment="Stretch" Height="300"> 
     <Viewport3D.Camera> 
      <PerspectiveCamera 
        LookDirection="0,0,-20" 
        UpDirection="0,1,0" 
        Position="0,0,100" 
        /> 
     </Viewport3D.Camera> 
     <ModelVisual3D> 
      <ModelVisual3D.Content> 
       <Model3DGroup x:Name="group3d"> 

        <SpotLight Position="30,30,30" x:Name="mySpotLight" Color="Yellow" InnerConeAngle="100" OuterConeAngle="1000" Range="100" /> 
       </Model3DGroup> 
      </ModelVisual3D.Content> 

     </ModelVisual3D> 
    </Viewport3D> 

</StackPanel> 

...和繼承人代碼背後...

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 
{ 
/// <summary> 
/// Interaction logic for Window1.xaml 
/// </summary> 
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<ModelVisual3D> _models = new List<ModelVisual3D>(); 
    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<double>(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; 
    } 



} 
} 
0

繼承人一些更多的代碼 - 我想我已經找到了您的解決方案......

再次,它是一個拼湊起來的例子,你就必須細化。

請注意,轉換代碼已經發生了巨大的變化,我只是開始自己去處理WPF 3D,並且我意識到我做了很多錯誤的事情。我每次都在重新創建Transform3DGroup,而不是僅僅改變已經應用的Transform的角度。

看看代碼並注意altTransform組 - 我正在做的是給這個alt組添加一個額外的轉換。然後,我在圓柱體和球體上使用了altTransform,否則它們會與其他圓柱體和球體的位置相同。我已經將這個圓筒標記爲綠色,以便您可以看到它是哪一個。

我對你的建議是你在同一個軸上創建所有的球體和柱體,然後將它們轉換到你想要的位置。

我也將球體和圓柱體的大小更改爲您在先前的評論中所要求的。

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

乾杯,

安迪

<Window x:Class="wpfspin.Window1" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="Window1" Height="600" Width="600"> 
<StackPanel> 

    <Viewport3D Name="mainViewport" ClipToBounds="True" HorizontalAlignment="Stretch" Height="600"> 
     <Viewport3D.Camera> 
      <PerspectiveCamera 
       LookDirection="0,0,-5" 
       UpDirection="0,1,0" 
       Position="0,0,10" 
       /> 
     </Viewport3D.Camera> 
     <ModelVisual3D> 
      <ModelVisual3D.Content> 
       <Model3DGroup x:Name="group3d"> 

        <SpotLight Position="30,30,30" x:Name="mySpotLight" Color="Yellow" InnerConeAngle="100" OuterConeAngle="1000" Range="100" /> 
       </Model3DGroup> 
      </ModelVisual3D.Content> 

     </ModelVisual3D> 
    </Viewport3D> 

</StackPanel> 
</Window> 

和繼承人後面的代碼...

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 
{ 
/// <summary> 
/// Interaction logic for Window1.xaml 
/// </summary> 
public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 
     Init(); 
    } 

    private Timer _timer; 
    private readonly List<ModelVisual3D> _models = new List<ModelVisual3D>(); 
    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<double>(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; 
    } 



} 
}