WPF:3D正四面体自动旋转

#一、坐标系

  • WPF 的 3D 坐标系原点通常位于对象中心,X 轴向右,Y 轴向上,Z 轴朝向观察者(右手定则)。
    正四面体旋转以原点为中心,绕Z 轴自动旋转。

#二、正四面体的坐标

  • 问题:是否存在所有四个顶点均为整数的正四面体?
    是的。实际上,存在"整数正四面体"(也称为Heronian四面体)。
    取四个顶点为:(0,0,0),(1,1,0),(1,0,1),(0,1,1) ,可以验证所有六条棱长均为 2\sqrt{2}2 ,所以这是一个棱长为 2\sqrt{2}2 的正四面体,且四个顶点全是整数。

#三、功能

  • 在右侧控制面板中,每个轴对应的 Slider 后面都增加了一个 TextBox,绑定到对应滑块的 Value 属性。

  • 在右侧面板的 StackPanel 底部增加两个按钮:一个用于切换自动旋转的启动/停止,另一个用于退出程序。

    自动旋转通过定时器使Z轴 每帧旋转角度增加0.5。

#四、MainWindow.xaml

复制代码
<Window x:Class="WpfA_Tetrahedron.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfA_Tetrahedron"
        mc:Ignorable="d"
        Title="正四面体" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="250"/>
        </Grid.ColumnDefinitions>

        <!-- 右侧控制面板 -->
        <StackPanel Grid.Column="1" Margin="10">
            <!-- 焦距控制 -->
            <TextBlock Text="调节相机焦距" Margin="0,0,0,5"/>
            <Slider x:Name="viewAngle" Width="200" Value="60" Minimum="10" Maximum="150" />
            <TextBox Text="{Binding ElementName=viewAngle, Path=Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                     Width="80" Margin="0,5,0,10" HorizontalAlignment="Left"/>

            <!-- X轴旋转 -->
            <TextBlock Text="X轴旋转" Margin="0,0,0,5"/>
            <Slider x:Name="rotateX" Width="200" Value="220" Minimum="0" Maximum="360" />
            <TextBox Text="{Binding ElementName=rotateX, Path=Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                     Width="80" Margin="0,5,0,10" HorizontalAlignment="Left"/>

            <!-- Y轴旋转 -->
            <TextBlock Text="Y轴旋转" Margin="0,0,0,5"/>
            <Slider x:Name="rotateY" Width="200" Value="40" Minimum="0" Maximum="360" />
            <TextBox Text="{Binding ElementName=rotateY, Path=Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                     Width="80" Margin="0,5,0,10" HorizontalAlignment="Left"/>

            <!-- Z轴旋转 -->
            <TextBlock Text="Z轴旋转" Margin="0,0,0,5"/>
            <Slider x:Name="rotateZ" Width="200" Value="0" Minimum="0" Maximum="360" />
            <TextBox Text="{Binding ElementName=rotateZ, Path=Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
                     Width="80" Margin="0,5,0,10" HorizontalAlignment="Left"/>

            <!-- 按钮 -->
            <Button x:Name="btnAutoRotate" Content="启动自动旋转" Width="120" Margin="0,20,0,5" Click="BtnAutoRotate_Click"/>
            <Button x:Name="btnExit" Content="退出程序" Width="120" Click="BtnExit_Click"/>
        </StackPanel>

        <!-- 3D 视口(保持不变) -->
        <Viewport3D Grid.Column="0">
            <Viewport3D.Camera>
                <PerspectiveCamera Position="0,0,50" LookDirection="0,0,-1" 
                                   FieldOfView="{Binding Value, ElementName=viewAngle}" 
                                   UpDirection="0,1,0"/>
            </Viewport3D.Camera>

            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <Model3DGroup>
                        <AmbientLight Color="Gray"/>
                        <DirectionalLight Color="Gray" Direction="-1,-1,-1"/>

                        <!-- 四个三角面 -->
                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <MeshGeometry3D Positions="0,0,0    10,10,0  10,0,10"
                                                 TriangleIndices="0,1,2"/>
                            </GeometryModel3D.Geometry>
                            <GeometryModel3D.Material>
                                <DiffuseMaterial Brush="Blue"/>
                            </GeometryModel3D.Material>
                        </GeometryModel3D>

                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <MeshGeometry3D Positions="0,0,0    10,10,0   0,10,10"
                                                 TriangleIndices="0,1,2"/>
                            </GeometryModel3D.Geometry>
                            <GeometryModel3D.Material>
                                <DiffuseMaterial Brush="Red"/>
                            </GeometryModel3D.Material>
                        </GeometryModel3D>

                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <MeshGeometry3D Positions="0,0,0   10,0,10  0,10,10"
                                                 TriangleIndices="0,1,2"/>
                            </GeometryModel3D.Geometry>
                            <GeometryModel3D.Material>
                                <DiffuseMaterial Brush="Green"/>
                            </GeometryModel3D.Material>
                        </GeometryModel3D>

                        <GeometryModel3D>
                            <GeometryModel3D.Geometry>
                                <MeshGeometry3D Positions="10,0,10  0,10,10  10,10,0"
                                                 TriangleIndices="0,1,2"/>
                            </GeometryModel3D.Geometry>
                            <GeometryModel3D.Material>
                                <DiffuseMaterial Brush="Yellow"/>
                            </GeometryModel3D.Material>
                        </GeometryModel3D>
                    </Model3DGroup>
                </ModelVisual3D.Content>

                <!-- 整体旋转变换 -->
                <ModelVisual3D.Transform>
                    <Transform3DGroup>
                        <RotateTransform3D>
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D Axis="1,0,0" Angle="{Binding Value, ElementName=rotateX}"/>
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                        <RotateTransform3D>
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D Axis="0,1,0" Angle="{Binding Value, ElementName=rotateY}"/>
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                        <RotateTransform3D>
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D Axis="0,0,1" Angle="{Binding Value, ElementName=rotateZ}"/>
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                    </Transform3DGroup>
                </ModelVisual3D.Transform>
            </ModelVisual3D>
        </Viewport3D>
    </Grid>
</Window>

#五、MainWindow.xaml.cs

复制代码
using System;
using System.Windows;
using System.Windows.Threading;

namespace WpfA_Tetrahedron
{
    public partial class MainWindow : Window
    {
        private DispatcherTimer _rotationTimer;
        private const double RotationStep = 0.5;   // 每帧旋转角度增量

        public MainWindow()
        {
            InitializeComponent();

            // 初始化定时器
            _rotationTimer = new DispatcherTimer
            {
                Interval = TimeSpan.FromMilliseconds(30) // 约 33 帧/秒
            };
            _rotationTimer.Tick += RotationTimer_Tick;
        }

        // 自动旋转按钮点击事件
        private void BtnAutoRotate_Click(object sender, RoutedEventArgs e)
        {
            if (_rotationTimer.IsEnabled)
            {
                // 停止旋转
                _rotationTimer.Stop();
                btnAutoRotate.Content = "启动自动旋转";
            }
            else
            {
                // 启动旋转
                _rotationTimer.Start();
                btnAutoRotate.Content = "停止自动旋转";
            }
        }

        // 定时器 Tick:累加 Z 轴角度
        private void RotationTimer_Tick(object sender, EventArgs e)
        {
            double newValue = rotateZ.Value + RotationStep;
            if (newValue >= 360)
                newValue -= 360;   // 保持在 [0,360)
            rotateZ.Value = newValue;
        }

        // 退出按钮点击事件
        private void BtnExit_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }
    }
}

#六、源码下载

复制代码
https://download.csdn.net/download/dalong10/93193444
相关推荐
AGI_Eval1 天前
AI 3D生成技术:从“可用”走向“可靠”还有多远?
人工智能·3d
光泽雨2 天前
WPF 音视频四大核心方案对比
wpf·音视频
翌日阳2 天前
二十分之一的压缩比:Spatial Vivid 1.0 把 3DGS 全链路参考实现按 MIT 开源了
3d·开源
浪扼飞舟2 天前
WPF(数据绑定)
wpf
Dream-Y.ocean3 天前
鸿蒙PC平台宅匠 3D 室内设计适配实战:基于 Electron 壳方案的 Three.js 双渲染引擎与参数化户型编辑器开发
javascript·3d·harmonyos
硕迪科技SOLIDWORKS3 天前
SOLIDWORKS Electrical 2027:从线束定义到2D–3D更改分析
3d·solidworks 202
DolitD3 天前
UE像素流与云渲染技术方案对比分析
3d·云原生·ue5·云计算·图形渲染
tealcwu3 天前
【Unity高级】Unity URP:构建同时支持 2D 与 3D 场景的项目完全指南
3d·unity·游戏引擎
samble3 天前
从零搭建半导体设备上位机(四):单实例、启动流程与配置文件,App 里那 526 行到底在干什么
wpf·配置文件·单实例
Jmyd01233 天前
文物3D数字化的技术选型指南:从WW/T 0115标准到落地工程,一次讲透采集、建档、管理与展示
3d·系统架构·博物馆·数字展厅·博物馆数字化