本文实例为大家分享了WPF实现3D立方体波浪墙效果的具体代码,供大家参考,具体内容如下
实现效果如下:
思路:仿照3D粒子系统,将粒子颗粒的Geometry改造为立方体,鼠标移动时将鼠标位置转为3D场景中的坐标。
步骤:
1、粒子类Particle.cs
public Point3D Position;//位置 public double Width;//长方体底面宽 public double Height;//长方体侧面高
2、粒子系统ParticleSystem.cs
private readonly List_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 (); _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:
交互逻辑:
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);
}
///
/// 获取鼠标在场景中的3D坐标
///
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);
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。



