服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - WPF实现3D立方体波浪墙效果

WPF实现3D立方体波浪墙效果

2022-10-08 15:44RunnerDNA C#

这篇文章主要为大家详细介绍了WPF实现3D立方体波浪墙效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了WPF实现3D立方体波浪墙效果的具体代码,供大家参考,具体内容如下

实现效果如下:

WPF实现3D立方体波浪墙效果

思路:仿照3D粒子系统,将粒子颗粒的Geometry改造为立方体,鼠标移动时将鼠标位置转为3D场景中的坐标。

步骤:

1、粒子类Particle.cs

?
1
2
3
public Point3D Position;//位置
public double Width;//长方体底面宽
public double Height;//长方体侧面高

2、粒子系统ParticleSystem.cs

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
private readonly List<Particle> _particleList;
private readonly GeometryModel3D _particleModel;
private readonly int CUBOIDHEIGHT = 20;
private readonly int MOUSERADIUS = 1000;
private int XParticleCount;
private int YParticleCount;
public Model3D ParticleModel => _particleModel;
 
public ParticleSystem(int amountX, int amountY, Color color)
    {
      XParticleCount = amountX;
      YParticleCount = amountY;
 
      _particleList = new List<Particle>();
      _particleModel = new GeometryModel3D { Geometry = new MeshGeometry3D() };
      var material = new DiffuseMaterial(new SolidColorBrush(color));
      _particleModel.Material = material;
    }
 
public void SpawnParticle(double size)
    {
      // 初始化粒子位置和大小
      for (int ix = 0; ix < XParticleCount; ix++)
      {
        for (int iy = 0; iy < YParticleCount; iy++)
        {
          var p = new Particle
          {
            Position = new Point3D(ix * size, iy * size, 0),
            Width = size,
            Height = CUBOIDHEIGHT,
          };
          _particleList.Add(p);
        }
      }
    }
 
public void Update(Point mp)
    {
      foreach (var p in _particleList)
      {
        //求点到圆心的距离
        double c = Math.Pow(Math.Pow(mp.X - p.Position.X, 2) + Math.Pow(mp.Y - p.Position.Y, 2), 0.5);
        p.Height = (MOUSERADIUS / (c + CUBOIDHEIGHT)) * CUBOIDHEIGHT;
      }
      UpdateGeometry();
    }
 
private void UpdateGeometry()
    {
      var positions = new Point3DCollection();
      var indices = new Int32Collection();
 
      for (var i = 0; i < _particleList.Count; ++i)
      {
        var positionIndex = i * 8;
        var p = _particleList[i];
 
        var p1 = new Point3D(p.Position.X, p.Position.Y, p.Position.Z);
        var p2 = new Point3D(p.Position.X + p.Width, p.Position.Y, p.Position.Z);
        var p3 = new Point3D(p.Position.X + p.Width, p.Position.Y + p.Width, p.Position.Z);
        var p4 = new Point3D(p.Position.X, p.Position.Y + p.Width, p.Position.Z);
        var p5 = new Point3D(p.Position.X, p.Position.Y, p.Position.Z + p.Height);
        var p6 = new Point3D(p.Position.X + p.Width, p.Position.Y, p.Position.Z + p.Height);
        var p7 = new Point3D(p.Position.X + p.Width, p.Position.Y + p.Width, p.Position.Z + p.Height);
        var p8 = new Point3D(p.Position.X, p.Position.Y + p.Width, p.Position.Z + p.Height);
 
        positions.Add(p1);
        positions.Add(p2);
        positions.Add(p3);
        positions.Add(p4);
        positions.Add(p5);
        positions.Add(p6);
        positions.Add(p7);
        positions.Add(p8);
 
        indices.Add(positionIndex);
        indices.Add(positionIndex + 1);
        indices.Add(positionIndex + 3);
        indices.Add(positionIndex + 1);
        indices.Add(positionIndex + 2);
        indices.Add(positionIndex + 3);
        indices.Add(positionIndex);
        indices.Add(positionIndex + 4);
        indices.Add(positionIndex + 3);
        indices.Add(positionIndex + 4);
        indices.Add(positionIndex + 7);
        indices.Add(positionIndex + 3);
        indices.Add(positionIndex + 4);
        indices.Add(positionIndex + 6);
        indices.Add(positionIndex + 7);
        indices.Add(positionIndex + 4);
        indices.Add(positionIndex + 5);
        indices.Add(positionIndex + 6);
        indices.Add(positionIndex);
        indices.Add(positionIndex + 4);
        indices.Add(positionIndex + 1);
        indices.Add(positionIndex + 1);
        indices.Add(positionIndex + 4);
        indices.Add(positionIndex + 5);
        indices.Add(positionIndex + 1);
        indices.Add(positionIndex + 2);
        indices.Add(positionIndex + 6);
        indices.Add(positionIndex + 6);
        indices.Add(positionIndex + 5);
        indices.Add(positionIndex + 1);
        indices.Add(positionIndex + 2);
        indices.Add(positionIndex + 3);
        indices.Add(positionIndex + 7);
        indices.Add(positionIndex + 7);
        indices.Add(positionIndex + 6);
        indices.Add(positionIndex + 2);
      }
 
      ((MeshGeometry3D)_particleModel.Geometry).Positions = positions;
      ((MeshGeometry3D)_particleModel.Geometry).TriangleIndices = indices;
 }

3、主窗体调用

xaml:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Grid x:Name="mainGrid" Background="#0D6589" >
    <Viewport3D Name="myViewport" MouseLeave="Grid_MouseLeave" MouseMove="Grid_MouseMove">
      <Viewport3D.Camera>
        <PerspectiveCamera Position="-1500,3000,2200" LookDirection="1,-1,-1" UpDirection="0,0,1"/>
      </Viewport3D.Camera>
      <Viewport3D.Children>
        <ModelVisual3D>
          <ModelVisual3D.Content>
            <Model3DGroup x:Name="WorldModels">
              <DirectionalLight Color="White" Direction="-1,-1,-3" />
            </Model3DGroup>
          </ModelVisual3D.Content>
        </ModelVisual3D>
      </Viewport3D.Children>
    </Viewport3D>
</Grid>

交互逻辑:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
private readonly ParticleSystem _ps;
private DispatcherTimer _frameTimer;
private Point pMouse = new Point(9999, 9999);
 
public MainWindow()
    {
      InitializeComponent();
 
      _frameTimer = new DispatcherTimer();
      _frameTimer.Tick += OnFrame;
      _frameTimer.Interval = TimeSpan.FromMilliseconds(100);
      _frameTimer.Start();
 
      _ps = new ParticleSystem(30, 30, Colors.White);
      WorldModels.Children.Add(_ps.ParticleModel);
      _ps.SpawnParticle(50);
 
      KeyDown += Window_KeyDown;
    }
 
    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
      if (e.Key == Key.Escape)
        Close();
    }
 
    private void OnFrame(object sender, EventArgs e)
    {
      _ps.Update(pMouse);
    }
 
    private void Grid_MouseMove(object sender, MouseEventArgs e)
    {
      Point mouseposition = e.GetPosition(myViewport);
      PointHitTestParameters pointparams = new PointHitTestParameters(mouseposition);
      VisualTreeHelper.HitTest(myViewport, null, HTResult, pointparams);
    }
 
    /// <summary>
    /// 获取鼠标在场景中的3D坐标
    /// </summary>
    public HitTestResultBehavior HTResult(System.Windows.Media.HitTestResult rawresult)
    {
      RayHitTestResult rayResult = rawresult as RayHitTestResult;
      if (rayResult != null)
      {
        RayMeshGeometry3DHitTestResult rayMeshResult = rayResult as RayMeshGeometry3DHitTestResult;
        if (rayMeshResult != null)
        {
          GeometryModel3D hitgeo = rayMeshResult.ModelHit as GeometryModel3D;
          MeshGeometry3D hitmesh = hitgeo.Geometry as MeshGeometry3D;
          Point3D p1 = hitmesh.Positions.ElementAt(rayMeshResult.VertexIndex1);
          double weight1 = rayMeshResult.VertexWeight1;
          Point3D p2 = hitmesh.Positions.ElementAt(rayMeshResult.VertexIndex2);
          double weight2 = rayMeshResult.VertexWeight2;
          Point3D p3 = hitmesh.Positions.ElementAt(rayMeshResult.VertexIndex3);
          double weight3 = rayMeshResult.VertexWeight3;
          Point3D prePoint = new Point3D(p1.X * weight1 + p2.X * weight2 + p3.X * weight3, p1.Y * weight1 + p2.Y * weight2 + p3.Y * weight3, p1.Z * weight1 + p2.Z * weight2 + p3.Z * weight3);
          pMouse = new Point(prePoint.X, prePoint.Y);
        }
      }
      return HitTestResultBehavior.Continue;
    }
 
    private void Grid_MouseLeave(object sender, MouseEventArgs e)
    {
      pMouse = new Point(9999, 9999);
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/dnazhd/article/details/108243041

延伸 · 阅读

精彩推荐
  • C#c# 以类名为参创建父类相同的类的实例代码

    c# 以类名为参创建父类相同的类的实例代码

    下面小编就为大家带来一篇c# 以类名为参创建父类相同的类的实例代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看...

    C#教程网9762021-12-22
  • C#C# WebApi 接口传参详解

    C# WebApi 接口传参详解

    这篇文章主要介绍了C# WebApi 接口传参详解,本篇打算通过get、post、put、delete四种请求方式分别谈谈基础类型(包括int/string/datetime等)、实体、数组等类型...

    懒得安分9892022-02-25
  • C#C# winform实现右下角弹出窗口结果的方法

    C# winform实现右下角弹出窗口结果的方法

    这篇文章主要介绍了C# winform实现右下角弹出窗口结果的方法,结合实例形式分析了C#窗口操作的相关技巧,需要的朋友可以参考下...

    廖先生6442022-01-10
  • C#C#中#define后面只加一个参数的解释

    C#中#define后面只加一个参数的解释

    今天小编就为大家分享一篇关于C#中#define后面只加一个参数的解释,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随...

    passtome7922022-07-20
  • C#C#生成验证码图片的方法

    C#生成验证码图片的方法

    这篇文章主要为大家详细介绍了C#生成验证码图片的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    薛定谔家的猫11462022-03-01
  • C#winform简单缓存类实例

    winform简单缓存类实例

    这篇文章主要介绍了winform简单缓存类,涉及C#缓存使用技巧,非常简单实用,需要的朋友可以参考下...

    我心依旧10892021-10-25
  • C#基于C#的电视台节目表接口调用代码

    基于C#的电视台节目表接口调用代码

    这篇文章主要介绍了基于C#的电视台节目表接口调用代码的相关资料,需要的朋友可以参考下...

    C#教程网7052021-11-26
  • C#C#完成word文档打印的方法

    C#完成word文档打印的方法

    在日常工作中,我们可能常常需要打印各种文件资料,比如word文档。对于编程员,应用程序中文档的打印是一项非常重要的功能,也一直是一个非常复杂的...

    Yesi11092021-12-09