欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

WPF实现3D立方体波浪墙效果

程序员文章站 2022-03-02 14:45:43
本文实例为大家分享了wpf实现3d立方体波浪墙效果的具体代码,供大家参考,具体内容如下实现效果如下:思路:仿照3d粒子系统,将粒子颗粒的geometry改造为立方体,鼠标移动时将鼠标位置转为3d场景中...

本文实例为大家分享了wpf实现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);
}

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