WPF 3D旋转球体GUI [英] WPF 3D rotating sphere GUI

查看:354
本文介绍了WPF 3D旋转球体GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图在WPF中为我的课堂作业创建一个3D用户界面,并且遇到了一个我现在无法修复的问题。我试图谷歌的答案,我看了一些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 =SphereGeneratorCenter =0 0 0Radius =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 =#00FFFFFFSpecularPower =50/>
< / MaterialGroup>
< /Viewport2DVisual3D.Material>

< Viewport2DVisual3D.Transform>
< RotateTransform3D>
< RotateTransform3D.Rotation>
< AxisAngleRotation3D x:Name =HaxAxis =0 1 0/>
< / RotateTransform3D>
< /Viewport2DVisual3D.Transform>

< Viewport2DVisual3D.Visual>
<画布背景=透明宽度=500高度=500>
< StackPanel Canvas.Top =150>
< Button Content =RotatePadding =10>
< Button.Triggers>
< EventTrigger RoutedEvent =Button.Click>
< BeginStoryboard>
< Storyboard TargetName =RotateInterfaceTargetProperty =Angle>
< DoubleAnimation From =0To =360RepeatBehavior =1xDuration =0:0:5/>
< / Storyboard>
< / BeginStoryboard>
< / EventTrigger>
< / Button>
< Button Padding =10Content =Click meClick =Button_Click_1>
< Button.Triggers>
< EventTrigger RoutedEvent =Button.Click>
< BeginStoryboard>
< Storyboard TargetName =SphereMaterialTargetProperty =Color>
< ColorAnimation To =TransparentRepeatBehavior =1xDuration =0:0:5/>
< / Storyboard>
< / BeginStoryboard>
< / EventTrigger>
< / Button>
< / StackPanel>
< / Canvas>
< /Viewport2DVisual3D.Visual>
< / Viewport2DVisual3D>

< ModelVisual3D.Content>

< Model3DGroup x:Name =SphereModel3DGroup>

< GeometryModel3D x:Name =SphereGeometryModelGeometry ={Binding Source = {StaticResource SphereGenerator},Path = Geometry}>

< GeometryModel3D.BackMaterial>
< DiffuseMaterial x:Name =SphereBackMaterialBrush =透明/>
< /GeometryModel3D.BackMaterial>

< GeometryModel3D.Material>
< DiffuseMaterial x:Name =SphereMaterial>
< DiffuseMaterial.Brush>
< RadialGradientBrush>
< GradientStop Color =#FF000000Offset =1/>
< GradientStop Color =#FF555555Offset =0/>
< / RadialGradientBrush>
< / DiffuseMaterial>

< GeometryModel3D.Transform>
< TranslateTransform3D />
< /GeometryModel3D.Transform>
< / GeometryModel3D>

< AmbientLight Color =White/>

< / Model3DGroup>
< /ModelVisual3D.Content>

< ModelVisual3D.Transform>
< RotateTransform3D>
< RotateTransform3D.Rotation>
< AxisAngleRotation3D x:Name =RotateInterfaceAxis =0 1 0/>
< / RotateTransform3D>
< /ModelVisual3D.Transform>

< / ModelVisual3D>

< /Viewport3D.Children>

< Viewport3D.Camera>
< PerspectiveCamera Position =0 0 -3LookDirection =0 0 1UpDirection =0 1 0FieldOfView =45/>
< /Viewport3D.Camera>

< / Viewport3D>



来自Charles Petzold:

  using System; 
使用System.Windows;
使用System.Windows.Media;
使用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();



$ b 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čida je scale = -_radius * Math.Cos(phi)
double z = scale * Math.Cos(theta); // Odredi poziciju Z koordinate。 Uočida je scale = -_radius * Math.Cos(phi)

Vector3D normal = new Vector3D(x,y,z); // Normala je vektor koji je okomit napovršinu。 U ovomslučajunormala je vektor okomit na trokut plohu trokuta。
mesh.Normals.Add(normal);
mesh.Positions.Add(普通+中心); //位置dobiva vrhove trokuta。
mesh.TextureCoordinates.Add(new Point((double)slice / Slices,(double)stack / Stacks));
// TextureCoordinateskažegdjećese nekatočkaiz 2D-a preslikati u 3D svijet。 (int stack = 0; stack< = Stacks; stack ++)
{
}

int top =(stack + 0) *(片+ 1);
int bot =(stack + 1)*(Slices + 1);

(int slice = 0; slice< Slices; slice ++)
{
if(stack!= 0)
{
mesh.TriangleIndices .Add(顶部+切片);
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;




解决方案

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



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

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;
      }
  }
}

解决方案

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.

Thanks to anyone who took the time to read my question.

这篇关于WPF 3D旋转球体GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆