【WPF 实例】实现3D粒子波浪效果[转载]

本文主要介绍WPF实现3D粒子波浪效果:

步骤:

1、3D粒子类Particle.cs

1

2

3

4

5

6

7

public class Particle

 {

  public Point3D Position;//位置

  public double Size;//尺寸

  public int XIndex;//X位置标识

  public int YIndex;//Y位置标识

 }

2、粒子系统ParticleSystem类

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

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 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()

  {

   // 计算粒子位置及大小

   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)

  {

   // 初始化粒子位置和大小

   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);

    }

   }

  }

 }

3、Viewport布局

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<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="#FFFFFFFF" />

      </Model3DGroup>

     </ModelVisual3D.Content>

    </ModelVisual3D>

   </Viewport3D.Children>

</Viewport3D>

4、交互逻辑

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

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();

 }

抽时间这些实例要逐个做成demo,看下效果。

------------------------------------------------------------------------------------------------------------

转载内容,如有问题请及时联系,将及时下架。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值