WPF實(shí)現(xiàn)3D立方體波浪墻效果
本文實(shí)例為大家分享了WPF實(shí)現(xiàn)3D立方體波浪墻效果的具體代碼,供大家參考,具體內(nèi)容如下
實(shí)現(xiàn)效果如下:

思路:仿照3D粒子系統(tǒng),將粒子顆粒的Geometry改造為立方體,鼠標(biāo)移動(dòng)時(shí)將鼠標(biāo)位置轉(zhuǎn)為3D場(chǎng)景中的坐標(biāo)。
步驟:
1、粒子類Particle.cs
public Point3D Position;//位置 public double Width;//長(zhǎng)方體底面寬 public double Height;//長(zhǎng)方體側(cè)面高
2、粒子系統(tǒng)ParticleSystem.cs
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)
{
//求點(diǎn)到圓心的距離
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、主窗體調(diào)用
xaml:
<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>
交互邏輯:
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>
/// 獲取鼠標(biāo)在場(chǎng)景中的3D坐標(biāo)
/// </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);
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- WPF實(shí)現(xiàn)3D翻牌式倒計(jì)時(shí)特效
- WPF實(shí)現(xiàn)時(shí)鐘特效
- WPF實(shí)現(xiàn)文本描邊+外發(fā)光效果的示例代碼
- WPF實(shí)現(xiàn)動(dòng)畫效果
- WPF實(shí)現(xiàn)3D粒子波浪效果
- WPF實(shí)現(xiàn)平面三角形3D運(yùn)動(dòng)效果
- WPF實(shí)現(xiàn)文字粒子閃爍動(dòng)畫效果
- WPF實(shí)現(xiàn)進(jìn)度條實(shí)時(shí)更新效果
- WPF實(shí)現(xiàn)轉(zhuǎn)圈進(jìn)度條效果
- WPF實(shí)現(xiàn)流光動(dòng)畫特效
相關(guān)文章
C#程序員應(yīng)該養(yǎng)成的程序性能優(yōu)化寫法
工作和生活中經(jīng)??梢钥吹揭恍┏绦蛟?寫代碼的時(shí)候只關(guān)注代碼的邏輯性,而不考慮運(yùn)行效率,其實(shí)這對(duì)大多數(shù)程序猿來說都是沒有問題的,不過作為一只有理想的CodeMonkey,我還是希望給大家分享一些性能優(yōu)化心得2017-08-08
Unity3D實(shí)現(xiàn)相機(jī)跟隨控制
這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)相機(jī)跟隨控制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07
C#中DataTable 轉(zhuǎn)換為 Json的方法匯總(三種方法)
JavaScript Object Notation (Json)是一種輕量級(jí)的數(shù)據(jù)交換格式,下面小編給大家介紹三種方法實(shí)現(xiàn)DataTable轉(zhuǎn)換成 Json 對(duì)象,感興趣的朋友一起看看吧2016-11-11
基于StreamRead和StreamWriter的使用(實(shí)例講解)
下面小編就為大家分享一篇基于StreamRead和StreamWriter的使用實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-11-11
C#實(shí)現(xiàn)IP代理池調(diào)度的示例代碼
這篇文章主要為大家介紹了C#實(shí)現(xiàn)IP代理池調(diào)度的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),具有一定的參考與學(xué)習(xí)價(jià)值,感興趣的小伙伴可以了解一下2023-07-07
c#之獲取本機(jī)主機(jī)名的四種方式總結(jié)
這篇文章主要介紹了c#之獲取本機(jī)主機(jī)名的四種方式總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
C#設(shè)計(jì)模式實(shí)現(xiàn)之迭代器模式
迭代器模式把對(duì)象的職責(zé)分離,職責(zé)分離可以最大限度減少彼此之間的耦合程度,從而建立一個(gè)松耦合的對(duì)象,這篇文章主要給大家介紹了關(guān)于C#設(shè)計(jì)模式實(shí)現(xiàn)之迭代器模式的相關(guān)資料,需要的朋友可以參考下2021-08-08

