WPF 3D旋转球体GUI

时间:2013-01-12 11:23:44

标签: wpf 3d geometry

我一直在尝试在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;
      }
  }
}

1 个答案:

答案 0 :(得分:1)

好吧,我刚刚意识到我不能这样做,因为按钮没有后向定义...在删除定义球体的GeometryModel3D并单击旋转按钮后,我注意到同样的事情发生了这意味着没有按钮的背面......我简直不敢相信我没想到这一点。

感谢任何花时间阅读我的问题的人。

相关问题