WPF实现3D粒子波浪效果

 更新时间:2020年11月3日 15:19  点击:2006

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

实现效果如下:

步骤:

1、3D粒子类Particle.cs

public class Particle
 {
  public Point3D Position;//位置
  public double Size;//尺寸
  public int XIndex;//X位置标识
  public int YIndex;//Y位置标识
 }

2、粒子系统ParticleSystem类

public class ParticleSystem
 {
  private readonly List<Particle> _particleList;
  private readonly GeometryModel3D _particleModel;
  private readonly int SEPARATION = 100;
 
  public ParticleSystem(int amountX, int amountY, Color color, int Size)
  {
   XParticleCount = amountX;
   YParticleCount = amountY;
 
   _particleList = new List<Particle>();
 
   _particleModel = new GeometryModel3D { Geometry = new MeshGeometry3D() };
 
   var e = new Ellipse
   {
    Width = Size,
    Height = Size
   };
   var b = new RadialGradientBrush();
   b.GradientStops.Add(new GradientStop(Color.FromArgb(0xFF, color.R, color.G, color.B), 0.25));
   b.GradientStops.Add(new GradientStop(Color.FromArgb(0x00, color.R, color.G, color.B), 1.0));
   e.Fill = b;
   e.Measure(new Size(Size, Size));
   e.Arrange(new Rect(0, 0, Size, Size));
 
   Brush brush = null;
   var renderTarget = new RenderTargetBitmap(Size, Size, 96, 96, PixelFormats.Pbgra32);
   renderTarget.Render(e);
   renderTarget.Freeze();
   brush = new ImageBrush(renderTarget);
 
   var material = new DiffuseMaterial(brush);
   _particleModel.Material = material;
  }
 
  public int XParticleCount { get; set; }
  public int YParticleCount { get; set; }
  public Model3D ParticleModel => _particleModel;
  private double _count = 0;
 
  public void Update()
  {
   // 计算粒子位置及大小
   for (int ix = 0; ix < XParticleCount; ix++)
   {
    for (int iy = 0; iy < YParticleCount; iy++)
    {
     foreach (var p in _particleList)
     {
      if(p.XIndex == ix && p.YIndex == iy)
      {
       p.Position.Z = (Math.Sin((ix + _count) * 0.3) * 100) + (Math.Sin((iy + _count) * 0.5) * 100);
       p.Size = (Math.Sin((ix + _count) * 0.3) + 1) * 8 + (Math.Sin((iy + _count) * 0.5) + 1) * 8;
      }
     }
    }
   }
   _count += 0.1;
 
   UpdateGeometry();
  }
 
  private void UpdateGeometry()
  {
   var positions = new Point3DCollection();
   var indices = new Int32Collection();
   var texcoords = new PointCollection();
 
   for (var i = 0; i < _particleList.Count; ++i)
   {
    var positionIndex = i * 4;
    var indexIndex = i * 6;
    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.Position.Y + p.Size, p.Position.Z);
    var p3 = new Point3D(p.Position.X + p.Size, p.Position.Y + p.Size, p.Position.Z);
    var p4 = new Point3D(p.Position.X + p.Size, p.Position.Y, p.Position.Z);
 
    positions.Add(p1);
    positions.Add(p2);
    positions.Add(p3);
    positions.Add(p4);
 
    var t1 = new Point(0.0, 0.0);
    var t2 = new Point(0.0, 1.0);
    var t3 = new Point(1.0, 1.0);
    var t4 = new Point(1.0, 0.0);
 
    texcoords.Add(t1);
    texcoords.Add(t2);
    texcoords.Add(t3);
    texcoords.Add(t4);
 
    indices.Add(positionIndex);
    indices.Add(positionIndex + 2);
    indices.Add(positionIndex + 1);
    indices.Add(positionIndex);
    indices.Add(positionIndex + 3);
    indices.Add(positionIndex + 2);
   }
 
   ((MeshGeometry3D)_particleModel.Geometry).Positions = positions;
   ((MeshGeometry3D)_particleModel.Geometry).TriangleIndices = indices;
   ((MeshGeometry3D)_particleModel.Geometry).TextureCoordinates = texcoords;
  }
 
  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 * SEPARATION - ((XParticleCount * SEPARATION) / 2), iy * SEPARATION - ((YParticleCount * SEPARATION) / 2), 0),
      Size = size,
      XIndex = ix,
      YIndex = iy,
     };
     _particleList.Add(p);
    }
   }
  }
 }

3、Viewport布局

<Viewport3D Name="World">
   <Viewport3D.Camera>
    <PerspectiveCamera Position="0,50,1000" LookDirection="0,2,-1" UpDirection="0,-1,-1" FieldOfView="10000" NearPlaneDistance="10" FarPlaneDistance="8000"/>
   </Viewport3D.Camera>
   <Viewport3D.Children>
    <ModelVisual3D>
     <ModelVisual3D.Content>
      <Model3DGroup x:Name="WorldModels">
       <AmbientLight Color="#FFFFFFFF" />
      </Model3DGroup>
     </ModelVisual3D.Content>
    </ModelVisual3D>
   </Viewport3D.Children>
</Viewport3D>

4、交互逻辑

private readonly ParticleSystem _ps;
private DispatcherTimer _frameTimer;
 
  public MainWindow()
  {
   InitializeComponent();
 
   _frameTimer = new DispatcherTimer();
   _frameTimer.Tick += OnFrame;
   _frameTimer.Interval = TimeSpan.FromSeconds(1.0 / 60.0);
   _frameTimer.Start();
 
   _ps = new ParticleSystem(50, 50, Colors.White, 30);
 
   WorldModels.Children.Add(_ps.ParticleModel);
 
   _ps.SpawnParticle(30);
 
   KeyDown += Window_KeyDown;
   Cursor = Cursors.None;
  }
 
  private void Window_KeyDown(object sender, KeyEventArgs e)
  {
   if (e.Key == Key.Escape)
    Close();
  }
 
  private void OnFrame(object sender, EventArgs e)
  {
   _ps.Update();
 }

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

[!--infotagslink--]

相关文章

  • c# WPF中通过双击编辑DataGrid中Cell的示例(附源码)

    这篇文章主要介绍了c# WPF中通过双击编辑DataGrid中Cell的示例(附源码),帮助大家更好的理解和学习使用c#,感兴趣的朋友可以了解下...2021-03-03
  • WPF实现类似360安全卫士界面的程序源码分享

    最近在网上看到了新版的360安全卫士,感觉界面还不错,于是用WPF制作了一个,时间有限,一些具体的控件没有制作,用图片代替了。感兴趣的朋友一起跟着小编学习WPF实现类似360安全卫士界面的程序源码分享...2020-06-25
  • WPF仿三星手机充电界面实现代码

    这篇文章主要为大家详细介绍了WPF仿三星手机充电界面实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • C# WPF 通过委托实现多窗口间的传值的方法

    这篇文章主要介绍了C# WPF 通过委托实现多窗口间的传值的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • WPF TextBox实现按字节长度限制输入功能

    这篇文章主要为大家详细介绍了WPF TextBox实现按字节长度限制输入功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • JS实现躲避粒子小游戏

    这篇文章主要为大家详细介绍了JS实现躲避粒子小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-19
  • C#中WPF使用多线程调用窗体组件的方法

    这篇文章主要介绍了C#中WPF使用多线程调用窗体组件的方法,涉及C#中多线程的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • WPF InkCanvas绘制矩形和椭圆

    这篇文章主要为大家详细介绍了WPF InkCanvas绘制矩形和椭圆,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Vue登录页面的动态粒子背景插件实现

    本文主要介绍了Vue登录页面的动态粒子背景插件实现,将登录组件背景设置为 "粒子背景",具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-07-12
  • WPF基础教程之形状画刷与变换详解

    这篇文章主要给大家介绍了关于WPF基础教程之形状画刷与变换的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • WPF如何自定义TabControl控件样式示例详解

    这篇文章主要给大家介绍了关于WPF如何自定义TabControl控件样式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。...2020-06-25
  • WPF水珠效果按钮组的实现教程

    下面小编就为大家分享一篇WPF水珠效果按钮组的实现教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-09-22
  • 解析WPF实现音频文件循环顺序播放的解决方法

    本篇文章是对WPF实现音频文件循环顺序播放的方法进行了详细的分析介绍,需要的朋友参考下...2021-09-22
  • WPF实现转圈进度条效果

    这篇文章主要为大家详细介绍了WPF实现转圈进度条效果,如何设计自定义的绕圈进度条,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • 在Winform和WPF中注册全局快捷键实现思路及代码

    如果注册快捷键,RegisterHotKey中的fsModifiers参数为0,即None选项,一些安全软件会警报,可能因为这样就可以全局监听键盘而造成安全问题,感兴趣的你可以参考下本文...2020-06-25
  • WPF中自定义GridLengthAnimation

    这篇文章主要为大家详细介绍了WPF中自定义GridLengthAnimation的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-22
  • WPF/Silverlight实现图片局部放大的方法分析

    这篇文章主要介绍了WPF/Silverlight实现图片局部放大的方法,结合实例形式分析了WPF/Silverlight针对图片属性操作相关实现技巧,需要的朋友可以参考下...2020-06-25
  • WPF MVVM制作发送短信小按钮

    这篇文章主要为大家详细介绍了WPF MVVM发送短信小按钮的制作方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • WPF中窗体最大化问题的解决方法

    这篇文章主要给大家介绍了关于WPF中窗体最大化问题的解决方法,文中通过示例代码介绍的非常详细,对大家学习或者使用wpf具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-06-25
  • C# WPF 父控件通过使用可视化树找到子控件的示例代码

    这篇文章主要介绍了C# WPF 父控件通过使用可视化树找到子控件的示例代码,需要的朋友可以参考下...2020-06-25