我一直在尝试在 WPF 中为我的课堂作业制作一个 3D 用户界面,但我遇到了一个我现在 2-3 天都无法解决的问题。我试图用谷歌搜索答案,我查看了一些 stackoverflow 帖子,但还没有一个帮助我解决这个问题。
所以情况就是这样:我有一个 3D 球体,上面放了 2 个按钮。一个按钮使球体的材质变得透明,另一个旋转整个界面(球体+按钮)...问题是球体透明时的纹理仍然存在,所以我不能当它们位于球体的另一侧时看到按钮......我希望至少能看到按钮背景......
任何帮助将不胜感激。
这是我的 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>
这是取自 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;
}
}
}