WPF 3D 旋转球体 GUI
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14292873/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF 3D rotating sphere GUI
提问by Marin
I've been trying to make a 3D user interface in WPF for my class assignment and I ran into a problem which I can't fix for 2-3 days now. I've tried to google the answer, I've taken a look into some stackoverflow posts, but none have yet helped me to fix the issue.
我一直在尝试在 WPF 中为我的课堂作业制作一个 3D 用户界面,但我遇到了一个我现在 2-3 天都无法解决的问题。我试图用谷歌搜索答案,我查看了一些 stackoverflow 帖子,但没有人帮助我解决这个问题。
So this is the situation: I have a 3D sphere on which I put 2 buttons. One button causes the material of the sphere to become transparent, and the other rotates the entire interface (Sphere + buttons)... The problem is the fact that the texture of the sphere is still there when it's transparent, so I can't see the buttons when they are at the other side of the sphere... I expected to see the buttons background at least...
所以情况就是这样:我有一个 3D 球体,我在上面放了 2 个按钮。一个按钮使球体的材质变透明,另一个使整个界面旋转(球体+按钮)...问题是球体的纹理在透明时仍然存在,所以我不能当它们在球体的另一侧时看到按钮......我希望至少看到按钮背景......
Any help would be very much appreciated.
任何帮助将不胜感激。
Here is my XAML:
这是我的 XAML:
<Window x:Class="RacunalnaGrafika_seminar.SphereWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:RacunalnaGrafika_seminar"
AllowsTransparency="True"
WindowStyle="None"
Title="SphereWindow">
<Window.Resources>
<src:SphereMeshGenerator x:Key="SphereGenerator" Center="0 0 0" Radius="0.5" />
</Window.Resources>
<Viewport3D x:Name="myViewport3D">
<Viewport3D.Children>
<ModelVisual3D>
<Viewport2DVisual3D Geometry="{Binding Source={StaticResource SphereGenerator}, Path=Geometry}">
<Viewport2DVisual3D.Material>
<MaterialGroup>
<DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True"/>
<SpecularMaterial Brush="#00FFFFFF" SpecularPower="50"/>
</MaterialGroup>
</Viewport2DVisual3D.Material>
<Viewport2DVisual3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="Hax" Axis="0 1 0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</Viewport2DVisual3D.Transform>
<Viewport2DVisual3D.Visual>
<Canvas Background="Transparent" Width="500" Height="500">
<StackPanel Canvas.Top="150">
<Button Content="Rotate" Padding="10" >
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard TargetName="RotateInterface" TargetProperty="Angle">
<DoubleAnimation From="0" To="360" RepeatBehavior="1x" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
<Button Padding="10" Content="Click me" Click="Button_Click_1">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard TargetName="SphereMaterial" TargetProperty="Color">
<ColorAnimation To="Transparent" RepeatBehavior="1x" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
</StackPanel>
</Canvas>
</Viewport2DVisual3D.Visual>
</Viewport2DVisual3D>
<ModelVisual3D.Content>
<Model3DGroup x:Name="SphereModel3DGroup">
<GeometryModel3D x:Name="SphereGeometryModel" Geometry="{Binding Source={StaticResource SphereGenerator}, Path=Geometry}">
<GeometryModel3D.BackMaterial>
<DiffuseMaterial x:Name="SphereBackMaterial" Brush="Transparent" />
</GeometryModel3D.BackMaterial>
<GeometryModel3D.Material>
<DiffuseMaterial x:Name="SphereMaterial" >
<DiffuseMaterial.Brush>
<RadialGradientBrush>
<GradientStop Color="#FF000000" Offset="1" />
<GradientStop Color="#FF555555" Offset="0" />
</RadialGradientBrush>
</DiffuseMaterial.Brush>
</DiffuseMaterial>
</GeometryModel3D.Material>
<GeometryModel3D.Transform>
<TranslateTransform3D />
</GeometryModel3D.Transform>
</GeometryModel3D>
<AmbientLight Color="White" />
</Model3DGroup>
</ModelVisual3D.Content>
<ModelVisual3D.Transform>
<RotateTransform3D>
<RotateTransform3D.Rotation>
<AxisAngleRotation3D x:Name="RotateInterface" Axis="0 1 0" />
</RotateTransform3D.Rotation>
</RotateTransform3D>
</ModelVisual3D.Transform>
</ModelVisual3D>
</Viewport3D.Children>
<Viewport3D.Camera>
<PerspectiveCamera Position="0 0 -3" LookDirection="0 0 1" UpDirection="0 1 0" FieldOfView="45" />
</Viewport3D.Camera>
</Viewport3D>
Here is the sphere generator taken from Charles Petzold:
这是来自 Charles Petzold 的球体生成器:
using System;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Media3D;
namespace RacunalnaGrafika_seminar
{
public class SphereMeshGenerator
{
private int _slices = 32;
private int _stacks = 16;
private Point3D _center = new Point3D();
private double _radius = 1;
public int Slices
{
get { return _slices; }
set { _slices = value; }
}
public int Stacks
{
get { return _stacks; }
set { _stacks = value; }
}
public Point3D Center
{
get { return _center; }
set { _center = value; }
}
public double Radius
{
get { return _radius; }
set { _radius = value; }
}
public MeshGeometry3D Geometry
{
get
{
return CalculateMesh();
}
}
private MeshGeometry3D CalculateMesh()
{
MeshGeometry3D mesh = new MeshGeometry3D();
for (int stack = 0; stack <= Stacks; stack++)
{
double phi = Math.PI / 2 - stack * Math.PI / Stacks; // kut koji zamisljeni pravac povucen iz sredista koordinatnog sustava zatvara sa XZ ravninom.
double y = _radius * Math.Sin(phi); // Odredi poziciju Y koordinate.
double scale = -_radius * Math.Cos(phi);
for (int slice = 0; slice <= Slices; slice++)
{
double theta = slice * 2 * Math.PI / Slices; // Kada gledamo 2D koordinatni sustav osi X i Z... ovo je kut koji zatvara zamisljeni pravac povucen iz sredista koordinatnog sustava sa Z osi ( Z = Y ).
double x = scale * Math.Sin(theta); // Odredi poziciju X koordinate. Uo?i da je scale = -_radius * Math.Cos(phi)
double z = scale * Math.Cos(theta); // Odredi poziciju Z koordinate. Uo?i da je scale = -_radius * Math.Cos(phi)
Vector3D normal = new Vector3D(x, y, z); // Normala je vektor koji je okomit na povr?inu. U ovom slu?aju normala je vektor okomit na trokut plohu trokuta.
mesh.Normals.Add(normal);
mesh.Positions.Add(normal + Center); // Positions dobiva vrhove trokuta.
mesh.TextureCoordinates.Add(new Point((double)slice / Slices, (double)stack / Stacks));
// TextureCoordinates ka?e gdje ?e se neka to?ka iz 2D-a preslikati u 3D svijet.
}
}
for (int stack = 0; stack <= Stacks; stack++)
{
int top = (stack + 0) * (Slices + 1);
int bot = (stack + 1) * (Slices + 1);
for (int slice = 0; slice < Slices; slice++)
{
if (stack != 0)
{
mesh.TriangleIndices.Add(top + slice);
mesh.TriangleIndices.Add(bot + slice);
mesh.TriangleIndices.Add(top + slice + 1);
}
if (stack != Stacks - 1)
{
mesh.TriangleIndices.Add(top + slice + 1);
mesh.TriangleIndices.Add(bot + slice);
mesh.TriangleIndices.Add(bot + slice + 1);
}
}
}
return mesh;
}
}
}
回答by Marin
Ok, I've just realised that I can't do this because the button has no back defined... after removing the GeometryModel3D that defined the sphere and clicking the rotate button, I've noticed that the same thing happend which means there is no back of a button... I can't believe I didn't think of this sooner.
好的,我刚刚意识到我不能这样做,因为按钮没有定义背面......在删除定义球体的 GeometryModel3D 并单击旋转按钮后,我注意到同样的事情发生了,这意味着那里没有按钮的背面......我不敢相信我没有早点想到这一点。
Thanks to anyone who took the time to read my question.
感谢任何花时间阅读我的问题的人。

