WPF实现3D立方体波浪墙效果
程序员文章站
2022-03-02 14:45:43
本文实例为大家分享了wpf实现3d立方体波浪墙效果的具体代码,供大家参考,具体内容如下实现效果如下:思路:仿照3d粒子系统,将粒子颗粒的geometry改造为立方体,鼠标移动时将鼠标位置转为3d场景中...
本文实例为大家分享了wpf实现3d立方体波浪墙效果的具体代码,供大家参考,具体内容如下
实现效果如下:
思路:仿照3d粒子系统,将粒子颗粒的geometry改造为立方体,鼠标移动时将鼠标位置转为3d场景中的坐标。
步骤:
1、粒子类particle.cs
public point3d position;//位置 public double width;//长方体底面宽 public double height;//长方体侧面高
2、粒子系统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) { //求点到圆心的距离 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:
<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> /// 获取鼠标在场景中的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); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 形形色色的Fragment生命周期
下一篇: WPF实现文字粒子闪烁动画效果