使用WPF做一个3D正方体并进行交互

使用WPF做一个3D正方体

1. 准备工作

安装Visual Studio

  • 下载Visual Studio安装包
  • 打开安装包,选择"使用C++的桌面开发"进行安装
  • 安装完成后打开Visual Studio,选择"新建项目",选择WPF应用程序
  • 在项目中添加3D空间,具体操作可以参考Microsoft官方文档

创建WPF项目

  • 在Visual Studio中创建一个WPF应用程序项目。
  • 在MainWindow.xaml中添加Viewport3D控件。
  • 在MainWindow.xaml.cs中添加代码以创建一个3D正方体,并将其添加到Viewport3D中。
// 创建一个3D正方体
MeshGeometry3D mesh = new MeshGeometry3D();
mesh.Positions = new Point3DCollection()
{
    
    
    new Point3D(-1, 1, 1),
    new Point3D(1, 1, 1),
    new Point3D(-1, -1, 1),
    new Point3D(1, -1, 1),
    new Point3D(-1, 1, -1),
    new Point3D(1, 1, -1),
    new Point3D(-1, -1, -1),
    new Point3D(1, -1, -1),
};
mesh.TriangleIndices = new Int32Collection()
{
    
    
    0, 1, 2,
    1, 3, 2,
    1, 5, 3,
    5, 7, 3,
    5, 4, 7,
    4, 6, 7,
    4, 0, 6,
    0, 2, 6,
    2, 3, 6,
    3, 7, 6,
    4, 5, 0,
    5, 1, 0,
};

// 创建一个材质
DiffuseMaterial material = new DiffuseMaterial(new SolidColorBrush(Colors.Blue));

// 创建一个模型
GeometryModel3D model = new GeometryModel3D(mesh, material);

// 创建一个模型组
Model3DGroup group = new Model3DGroup();
group.Children.Add(model);

// 将模型组添加到Viewport3D中
viewport3D.Children.Add(new ModelVisual3D() {
    
     Content = group });

引入Helix Toolkit NuGet包- 在Visual Studio中打开项目解决方案。

  • 右键点击项目名称,选择“管理NuGet程序包”。
  • 在搜索框中输入“Helix Toolkit”。
  • 选择最新版本的“Helix Toolkit WPF”并安装。
  • 在MainWindow.xaml文件中添加以下代码:
<Window x:Class="Wpf3DCube.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:h="http://helix-toolkit.org/wpf"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <h:HelixViewport3D>
            <!-- 3D模型将在此处添加 -->
        </h:HelixViewport3D>
    </Grid>
</Window>

2. 实现3D正方体

  1. 创建3D场景

创建Viewport3D对象

  • 使用XAML创建Viewport3D对象
<Viewport3D>
    <!-- 3D场景内容 -->
</Viewport3D>
  • 使用C#代码创建Viewport3D对象

    Viewport3D viewport = new Viewport3D();
    // 添加3D场景内容
    // ...
    
  • 在窗口中添加Viewport3D对象

    <Grid>
        <Viewport3D>
            <!-- 3D场景内容 -->
        </Viewport3D>
    </Grid>
    

设置相机位置
2. 创建正方体模型

  • 设置相机位置:
PerspectiveCamera camera = new PerspectiveCamera();
camera.Position = new Point3D(0, 0, 5);
camera.LookDirection = new Vector3D(0, 0, -1);
camera.FieldOfView = 60;
viewport.Camera = camera;
  • 创建正方体模型:

    MeshGeometry3D mesh = new MeshGeometry3D();
    mesh.Positions.Add(new Point3D(-1, -1, 1));
    mesh.Positions.Add(new Point3D(1, -1, 1));
    mesh.Positions.Add(new Point3D(1, 1, 1));
    mesh.Positions.Add(new Point3D(-1, 1, 1));
    mesh.Positions.Add(new Point3D(-1, -1, -1));
    mesh.Positions.Add(new Point3D(1, -1, -1));
    mesh.Positions.Add(new Point3D(1, 1, -1));
    mesh.Positions.Add(new Point3D(-1, 1, -1));
    
    mesh.TriangleIndices.Add(0);
    mesh.TriangleIndices.Add(1);
    mesh.TriangleIndices.Add(2);
    mesh.TriangleIndices.Add(2);
    mesh.TriangleIndices.Add(3);
    mesh.TriangleIndices.Add(0);
    
    mesh.TriangleIndices.Add(1);
    mesh.TriangleIndices.Add(5);
    mesh.TriangleIndices.Add(6);
    mesh.TriangleIndices.Add(6);
    mesh.TriangleIndices.Add(2);
    mesh.TriangleIndices.Add(1);
    
    mesh.TriangleIndices.Add(7);
    mesh.TriangleIndices.Add(6);
    mesh.TriangleIndices.Add(5);
    mesh.TriangleIndices.Add(5);
    mesh.TriangleIndices.Add(4);
    mesh.TriangleIndices.Add(7);
    
    mesh.TriangleIndices.Add(4);
    mesh.TriangleIndices.Add(0);
    mesh.TriangleIndices.Add(3);
    mesh.TriangleIndices.Add(3);
    mesh.TriangleIndices.Add(7);
    mesh.TriangleIndices.Add(4);
    
    mesh.TriangleIndices.Add(3);
    mesh.TriangleIndices.Add(2);
    mesh.TriangleIndices.Add(6);
    mesh.TriangleIndices.Add(6);
    mesh.TriangleIndices.Add(7);
    mesh.TriangleIndices.Add(3);
    
    mesh.TriangleIndices.Add(4);
    mesh.TriangleIndices.Add(5);
    mesh.TriangleIndices.Add(1);
    mesh.TriangleIndices.Add(1);
    mesh.TriangleIndices.Add(0);
    mesh.TriangleIndices.Add(4);
    
    GeometryModel3D model = new GeometryModel3D();
    model.Geometry = mesh;
    model.Material = new DiffuseMaterial(new SolidColorBrush(Colors.Blue));
    model.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Green));
    ModelVisual3D visual = new ModelVisual3D();
    visual.Content = model;
    viewport.Children.Add(visual);
    

创建MeshBuilder对象

  • 使用以下代码创建MeshBuilder对象:
MeshBuilder meshBuilder = new MeshBuilder();

添加顶点

  • 在代码中定义顶点坐标数组,例如:
Point3D[] vertices = new Point3D[]
{
    new Point3D(-1, 1, 1),
    new Point3D(1, 1, 1),
    new Point3D(1, -1, 1),
    new Point3D(-1, -1, 1),
    new Point3D(-1, 1, -1),
    new Point3D(1, 1, -1),
    new Point3D(1, -1, -1),
    new Point3D(-1, -1, -1)
};
  • 创建MeshGeometry3D对象,并将定义的顶点坐标数组赋值给它的Positions属性,例如:

    MeshGeometry3D mesh = new MeshGeometry3D();
    mesh.Positions = new Point3DCollection(vertices);
    
  • 将MeshGeometry3D对象赋值给Geometry属性,例如:

    Geometry = mesh;
    

添加三角形

  • 在场景中添加一个MeshGeometry3D对象,用于存储三角形的顶点信息:
MeshGeometry3D mesh = new MeshGeometry3D();
  • 添加三个顶点,构成一个三角形:

    mesh.Positions.Add(new Point3D(0, 0, 0));
    mesh.Positions.Add(new Point3D(1, 0, 0));
    mesh.Positions.Add(new Point3D(0, 1, 0));
    
  • 定义三角形的法线向量:

    Vector3D normal = new Vector3D(0, 0, 1);
    
  • 添加三角形的法线向量:

    mesh.Normals.Add(normal);
    mesh.Normals.Add(normal);
    mesh.Normals.Add(normal);
    
  • 添加三角形的索引:

    mesh.TriangleIndices.Add(0);
    mesh.TriangleIndices.Add(1);
    mesh.TriangleIndices.Add(2);
    
  • 创建一个GeometryModel3D对象,设置其Geometry属性为刚才创建的MeshGeometry3D对象:

    GeometryModel3D model = new GeometryModel3D();
    model.Geometry = mesh;
    
  • 创建一个MaterialGroup对象,用于设置三角形的颜色:

    MaterialGroup materials = new MaterialGroup();
    materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(Colors.Red)));
    
  • 将MaterialGroup对象设置为GeometryModel3D对象的Material属性:

    model.Material = materials;
    
  • 将GeometryModel3D对象添加到场景中:

    scene.Children.Add(model);
    

创建GeometryModel3D对象

  • 使用MeshGeometry3D类创建立方体的顶点坐标和索引数据:
MeshGeometry3D mesh = new MeshGeometry3D();
mesh.Positions = new Point3DCollection()
{
    
    
    new Point3D(-0.5, -0.5, -0.5),
    new Point3D(0.5, -0.5, -0.5),
    new Point3D(0.5, 0.5, -0.5),
    new Point3D(-0.5, 0.5, -0.5),
    new Point3D(-0.5, -0.5, 0.5),
    new Point3D(0.5, -0.5, 0.5),
    new Point3D(0.5, 0.5, 0.5),
    new Point3D(-0.5, 0.5, 0.5)
};
mesh.TriangleIndices = new Int32Collection()
{
    
    
    0, 1, 2, 2, 3, 0, // front face
    1, 5, 6, 6, 2, 1, // right face
    5, 4, 7, 7, 6, 5, // back face
    4, 0, 3, 3, 7, 4, // left face
    3, 2, 6, 6, 7, 3, // top face
    0, 4, 5, 5, 1, 0  // bottom face
};
  • 创建GeometryModel3D对象并设置其Geometry属性为上一步创建的MeshGeometry3D对象:

    GeometryModel3D model = new GeometryModel3D();
    model.Geometry = mesh;
    
  • 创建Material对象并设置其DiffuseColor属性为立方体的颜色:

    SolidColorBrush brush = new SolidColorBrush(Colors.Blue);
    Material material = new DiffuseMaterial(brush);
    
  • 创建ModelVisual3D对象并设置其Content属性为上一步创建的GeometryModel3D对象:

    ModelVisual3D visual = new ModelVisual3D();
    visual.Content = model;
    
  • 将ModelVisual3D对象添加到Viewport3D的Children集合中:

    viewport.Children.Add(visual);
    

设置材质

  • 在XAML中添加材质:
<GeometryModel3D.Material>
    <DiffuseMaterial Brush="Red"/>
</GeometryModel3D.Material>
  • 在代码中设置材质:
    DiffuseMaterial material = new DiffuseMaterial(Brushes.Red);
    GeometryModel3D cubeModel = new GeometryModel3D(cubeMesh, material);
    

设置模型
3. 添加灯光

  • 设置模型:
// 创建正方体模型
MeshGeometry3D cubeMesh = new MeshGeometry3D();
cubeMesh.Positions = new Point3DCollection()
{
    
    
    new Point3D(-0.5, -0.5, -0.5),
    new Point3D(0.5, -0.5, -0.5),
    new Point3D(0.5, 0.5, -0.5),
    new Point3D(-0.5, 0.5, -0.5),
    new Point3D(-0.5, -0.5, 0.5),
    new Point3D(0.5, -0.5, 0.5),
    new Point3D(0.5, 0.5, 0.5),
    new Point3D(-0.5, 0.5, 0.5)
};
cubeMesh.TriangleIndices = new Int32Collection()
{
    
    
    0, 1, 2, 2, 3, 0,
    1, 5, 6, 6, 2, 1,
    5, 4, 7, 7, 6, 5,
    4, 0, 3, 3, 7, 4,
    3, 2, 6, 6, 7, 3,
    0, 4, 5, 5, 1, 0
};

// 创建材质
DiffuseMaterial material = new DiffuseMaterial(new SolidColorBrush(Colors.Blue));

// 创建模型
GeometryModel3D model = new GeometryModel3D(cubeMesh, material);

// 创建模型容器
Model3DGroup modelGroup = new Model3DGroup();
modelGroup.Children.Add(model);

// 将模型容器添加到场景中
viewport.Children.Add(new ModelVisual3D() {
    
     Content = modelGroup });
  • 添加灯光:

    // 创建点光源
    PointLight light = new PointLight(Colors.White, new Point3D(0, 0, 0));
    
    // 将光源添加到场景中
    viewport.Children.Add(new ModelVisual3D() {
          
           Content = light });
    

创建AmbientLight对象

  • 创建AmbientLight对象的代码如下:
AmbientLight myAmbientLight = new AmbientLight();
myAmbientLight.Color = Colors.White;

这段代码创建了一个白色的环境光,用于照亮整个场景。

创建DirectionalLight对象

  • 创建DirectionalLight对象的代码示例:
DirectionalLight myDirectionalLight = new DirectionalLight();
myDirectionalLight.Color = Colors.White;
myDirectionalLight.Direction = new Vector3D(-0.61, -0.5, -0.61);
myViewport3D.Children.Add(myDirectionalLight);

这段代码创建了一个DirectionalLight对象,并设置了它的颜色和方向,最后将它添加到了Viewport3D中。

设置光照效果
4. 显示3D场景

  • 设置光照效果:
// 创建一个平行光源
DirectionalLight light = new DirectionalLight(Colors.White, new Vector3D(-1, -1, -1));

// 将光源添加到场景中
myViewport3D.Children.Add(light);
  • 显示3D场景:

    // 创建一个Viewport3DVisualizer对象
    Viewport3DVisualizer visualizer = new Viewport3DVisualizer();
    
    // 设置Viewport3DVisualizer的Viewport3D属性
    visualizer.Viewport3D = myViewport3D;
    
    // 将Viewport3DVisualizer添加到VisualTree中
    this.Content = visualizer;
    

将Viewport3D对象添加到Grid中- 将Viewport3D对象添加到Grid中的代码实例:

<Grid>
    <Viewport3D>
        <!-- 添加3D场景内容 -->
    </Viewport3D>
</Grid>

3. 实现旋转动画

  1. 创建动画

创建DoubleAnimation对象

  • 创建DoubleAnimation对象的实例代码:
DoubleAnimation rotateAnimation = new DoubleAnimation();
rotateAnimation.From = 0;
rotateAnimation.To = 360;
rotateAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
rotateAnimation.RepeatBehavior = RepeatBehavior.Forever;

这段代码创建了一个DoubleAnimation对象rotateAnimation,将其起始值设为0,终止值设为360,动画时长为5秒,并且重复播放。

设置From和To属性

  • 设置From和To属性的代码示例:
// 创建旋转动画
RotateTransform3D rotateTransform = new RotateTransform3D();
AxisAngleRotation3D axisAngleRotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0);
rotateTransform.Rotation = axisAngleRotation;

DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = 0;
doubleAnimation.To = 360;
doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;

// 将动画应用到旋转变换
axisAngleRotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, doubleAnimation);

设置Duration属性

  • 在XAML中设置Duration属性:
<Storyboard x:Key="RotateAnimation">
    <DoubleAnimation Storyboard.TargetName="myTransform" Storyboard.TargetProperty="Angle" From="0" To="360" Duration="0:0:1" RepeatBehavior="Forever" />
</Storyboard>
  • 在代码中设置Duration属性:

    DoubleAnimation animation = new DoubleAnimation();
    animation.From = 0;
    animation.To = 360;
    animation.Duration = new Duration(TimeSpan.FromSeconds(1));
    animation.RepeatBehavior = RepeatBehavior.Forever;
    Storyboard.SetTargetName(animation, "myTransform");
    Storyboard.SetTargetProperty(animation, new PropertyPath(RotateTransform.AngleProperty));
    Storyboard storyboard = new Storyboard();
    storyboard.Children.Add(animation);
    storyboard.Begin(this);
    

设置RepeatBehavior属性

  • 在XAML中设置RepeatBehavior属性:
<Storyboard x:Key="RotateAnimation">
    <DoubleAnimation Storyboard.TargetName="myTransform" 
                     Storyboard.TargetProperty="Angle"
                     From="0" To="360" Duration="0:0:3"
                     RepeatBehavior="Forever" />
</Storyboard>
  • 在代码中设置RepeatBehavior属性:

    DoubleAnimation animation = new DoubleAnimation();
    animation.From = 0;
    animation.To = 360;
    animation.Duration = new Duration(TimeSpan.FromSeconds(3));
    animation.RepeatBehavior = RepeatBehavior.Forever;
    
    Storyboard.SetTargetName(animation, "myTransform");
    Storyboard.SetTargetProperty(animation, new PropertyPath(RotateTransform.AngleProperty));
    
    Storyboard storyboard = new Storyboard();
    storyboard.Children.Add(animation);
    storyboard.Begin(this);
    

创建Storyboard对象

  • 创建Storyboard对象的实例代码:
Storyboard storyboard = new Storyboard();
  • 添加旋转动画的实例代码:
    DoubleAnimation animation = new DoubleAnimation();
    animation.From = 0;
    animation.To = 360;
    animation.Duration = new Duration(TimeSpan.FromSeconds(5));
    animation.RepeatBehavior = RepeatBehavior.Forever;
    Storyboard.SetTarget(animation, cube);
    Storyboard.SetTargetProperty(animation, new PropertyPath("(UIElement.RenderTransform).(Transform3DGroup.Children)[0].(RotateTransform3D.Rotation.Angle)"));
    storyboard.Children.Add(animation);
    

其中,cube是表示正方体的UIElement对象,可以根据实际情况进行替换。

将DoubleAnimation添加到Storyboard中
2. 应用动画

  • 将DoubleAnimation添加到Storyboard中:
DoubleAnimation rotateAnimation = new DoubleAnimation();
rotateAnimation.From = 0;
rotateAnimation.To = 360;
rotateAnimation.Duration = TimeSpan.FromSeconds(1);
rotateAnimation.RepeatBehavior = RepeatBehavior.Forever;

Storyboard.SetTarget(rotateAnimation, myModel);
Storyboard.SetTargetProperty(rotateAnimation, new PropertyPath(Model3D.TransformProperty));

Storyboard storyboard = new Storyboard();
storyboard.Children.Add(rotateAnimation);
storyboard.Begin();
  • 应用动画:
    在窗口的Loaded事件中,将上面创建的Storyboard开始播放即可。

将Storyboard对象添加到Viewport3D对象的Resources中

  • 将Storyboard对象添加到Viewport3D对象的Resources中:
<Viewport3D>
    <Viewport3D.Resources>
        <Storyboard x:Key="RotationStoryboard">
            <DoubleAnimation From="0" To="360" Duration="0:0:5" RepeatBehavior="Forever"
                             Storyboard.TargetName="TransformRotation" Storyboard.TargetProperty="Angle" />
        </Storyboard>
    </Viewport3D.Resources>
    ...
</Viewport3D>

给旋转对象绑定动画- 给旋转对象绑定动画:

// 创建旋转动画
DoubleAnimation rotationAnimation = new DoubleAnimation();
rotationAnimation.From = 0;
rotationAnimation.To = 360;
rotationAnimation.Duration = new Duration(TimeSpan.FromSeconds(5));
rotationAnimation.RepeatBehavior = RepeatBehavior.Forever;

// 绑定旋转动画
RotateTransform3D rotateTransform = new RotateTransform3D();
rotateTransform.Rotation = new AxisAngleRotation3D(new Vector3D(0, 1, 0), 0);
cubeModel.Transform = rotateTransform;
rotateTransform.Rotation.BeginAnimation(AxisAngleRotation3D.AngleProperty, rotationAnimation);

这段代码实现了一个旋转动画,将一个正方体对象绕着Y轴旋转。我们首先创建一个DoubleAnimation对象,设置其From属性为0,To属性为360,表示从0度到360度,Duration属性为5秒,表示动画的持续时间为5秒,RepeatBehavior属性为Forever,表示动画循环播放。接着,我们创建一个RotateTransform3D对象,将其赋值给正方体对象的Transform属性,表示该对象需要应用旋转变换。最后,我们将旋转对象的Rotation属性绑定到旋转动画,使得该对象能够按照动画的要求旋转。

4. 总结

通过本文,我们学习了如何使用WPF创建一个3D正方体,并实现旋转动画。同时,我们也了解了一些基本的WPF 3D图形编程知识。

猜你喜欢

转载自blog.csdn.net/Ataraki/article/details/130182640
今日推荐