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.
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...
Any help would be very much appreciated.
Here is my 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:
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;
}
}
}