WPF 3D 旋转球体 GUI

2024-04-18

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF 3D 旋转球体 GUI 的相关文章

  • 合并空间上接近的路径/线段的算法

    我正在寻找一种用于街道地图制图概括的几何算法 名称 在我的地图数据中 我有许多路径 点的有序列表 由线段连接 这些路径彼此靠近且几乎平行 我如何 1 识别这些 相邻路径 即如何找到比某个阈值更接近的路径 以及 2 将它们合并成一条路径 即如
  • 执行按钮单击时使 wpf UI 响应

    在我的 wpf c 应用程序中 当用户按下按钮时会执行一个很长的过程 当按下按钮直到执行完整的代码时 窗口将冻结 用户无法在窗口中执行任何其他任务 如何使按钮单击代码作为后台进程 以便窗口响应用户 我尝试过以下方法 但没有成功 privat
  • 在显示另一个对话框之前隐藏所有可见的 Metro 对话框

    我在用着MahApps Metro http mahapps com在我的 WPF 项目中 我正在构建一个类来帮助我展示Dialogs http mahapps com controls dialogs html 我想知道是否有一种方法可以
  • Trace.Assert 没有中断,也不显示消息框

    我有一个 WPF 应用程序 我在其中在画布上移动数据 当我像怪物一样尝试用鼠标移动数据时 问题就开始了 以下是操作的顺序 画布上的 MouseMove 被触发 在 MouseMove 中 我更改了一些数据 Trace Assert 失败 调
  • 在 WPF 中设置控件内容比将类绑定到选择器控件更好的方法是什么?

    我有一个分为 4 个面板的应用程序 有一个主绘图区域 一个顶部面板 一个左侧菜单面板和一个右侧子菜单面板 如下图所示 子菜单的内容由选择哪个顶部菜单按钮决定 子菜单的内容由选择哪个右侧菜单决定 例如 这是单击 网络设计和测试 扩展器上的第一
  • 如何使TabTip.exe窗口弹出时最大化

    我想使用以下代码弹出虚拟键盘 var info new ProcessStartInfo C Program Files Common Files Microsoft Shared ink TabTip exe info WindowSty
  • 当 ToString() 具有协作对象时,为什么 WPF 数据绑定不显示文本?

    在一个简单的形式中 我绑定到许多不同的对象 有些放在列表框中 有些放在列表框中 有些放在列表框中 一些在文本块中 其中一些对象具有协作对象 在这些对象上ToString 方法在执行其工作时调用 通常是某种格式化程序 当我单步执行代码时 我发
  • DataGrid、TextBox - 绑定和即时更新

    我的应用程序 包含图中的窗口 DataGrid 的 ItemsSource 设置为 editList 声明为 IList editList 数据网格设置为只读 供应商名称文本框的绑定设置为 Text Binding ElementName
  • C#/WPF:将 Datagrid 中的 Combobox ItemSource 绑定到 DataContext 外部的元素

    我想做以下事情 public List
  • 慢速 WPF 文本框

    我正在开发一个简单的串行数据查看器 它将用于观察传输到计算机串行端口之一的数据 我使用 C 和 WPF 编写了一个测试应用程序 它只是将最近读取的行放入文本块中 但是 它会跳过所有其他行 我的理论是 在 WPF 渲染窗口之前 新数据会被放入
  • iOS 绘制圆圈

    我正在尝试在我的 iOS 应用程序中创建下面的圆圈 我知道如何制作圆圈 但不完全确定如何沿着弧线获取点 它必须是代码而不是图像 下面也是我目前拥有的代码 void drawRect CGRect rect CGPoint point poi
  • 使用画布矩形裁剪图像

    裁剪图像无法正常工作 我哪里错了 我的Xaml
  • 带有添加新选项卡按钮 (+) 的 TabControl

    在 WPF 中选项卡控件的选项卡条中的所有选项卡项的末尾添加 按钮选项卡的正确方法是什么 它应该可以正确地处理多个选项卡标题行 它应该位于所有选项卡项目的末尾 Tab cycling should work correctly Alt Ta
  • 按度数在圆上找到一个点?

    假设我们有一个 100x100 坐标系 如下所示 0 0 是它的左上角 50 50 是它的中心点 100 100 是它的右下角 等等 现在我们需要从中心向外画一条线 我们知道线的角度 但需要计算其终点的坐标 您认为最好的方法是什么 例如 如
  • iTextSharp 从 WPF 固定文档生成 PDF

    我有一个简单的 WPF 应用程序 可以显示和打印一些内容 使用固定文档进行报告 如何使用免费且开放的解决方案从中生成 PDF 比如iTextSharp WPF 固定文档 也称为 XPS 文档 是对 PDF 的明显改进 它具有 PDF 所缺乏
  • Three.js :face4 生成三角形而不是正方形

    我正在尝试使用 tree js 自定义几何图形生成一个正方形 但是这段代码 var cubeGeo new THREE Geometry cubeGeo vertices push new THREE Vector3 25 25 25 cu
  • 如何确保 ViewModel 属性在再次更改其值之前已绑定在视图上?

    有以下情况 ViewModel有一个变化非常快的对象 通过不同的线程 View通过以下方式获悉NotifyPropertyChanged界面 但似乎它的工作速度很慢 并且在视图绑定新值并绘制它之前 它会更改更多次 因此它会丢失一些值 我也尝
  • WPF 网格布局

    是否可以在 WPF 中使用 Grid 来设计类似的东西 设计列很容易 但是行呢 或者有没有更好的解决方案 比如另一个容器 将每个矩形想象为模块 GroupBox 创建一个包含两列的外部网格 在此网格中 放置另外两个网格 每列一个 这将导致所
  • 在 WPF 中打开 ContextMenu 时保留 DataGrid IsSelectionActive?

    我有一个DataGrid其风格为IsSelectionActive 然而 一旦ContextMenu打开 网格丢失IsSelectionActive在用户看来 上下文菜单似乎以某种方式进行了选择 可能会让用户感到困惑 有没有办法保留IsSe
  • 如何从注册表获取安装的软件路径?

    我需要替换安装在任何驱动器 如 C D E 中的文件 我想从注册表中找到安装的文件路径并将该文件替换为其他文件 软件将安装在任何驱动器中 我想替换文件 我正在使用这段代码 如何使用注册表查找安装的文件路径并替换为 C 中的其他文件 stri

随机推荐