MainWindow.xaml
<Window x:Class="_3dwaveEffect.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:_3dwaveEffect"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<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="#000" />
</Model3DGroup>
</ModelVisual3D.Content>
</ModelVisual3D>
</Viewport3D.Children>
</Viewport3D>
</Grid>
</Window>
WindowMain.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace _3dwaveEffect
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
///
public partial class MainWindow : Window
{
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();
}
}
}
using System.Windows.Media.Media3D;
public class Particle
{
public Point3D Position;//Position
public double Size;//size
public int XIndex;//X position identification
public int YIndex;//Y position identification
}
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
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 System.Windows.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()
{
// Calculate particle position and size
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)
{
// Initialize particle position and 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);
}
}
}
}
No comments:
Post a Comment