Lightning闪电
by Ian McDougall

文件下载

1.0 Abstract摘要

一天晚上当看到闪电和风暴时,我就打算写一篇关于闪电的文章。One night when there was a lightning storm (2 or 3 nights ago) I decided I would write an article on lightning just for fun. This is the first time I have ever tried to simulate lightning before. If there are any spelling mistakes or similar please E-Mail then to me at javaman@telusplanet.net.

1.1 About this Article关于文章

代码是用VB+DX8写的,可在此here下载。All the demo code is in Visual Basic with DirectX8. There is a demo with code and exe that you can get here.

2.0 Getting down to work开始工作

首先建立一个标准的场景,我加入了大雾来表现下鱼的样子。First off, you just set up a normal Direct3D scene. I added a bit of fog to make it look like it's raining, but you don抰 have to do this if you don抰 want to.

实现这个方法我使用了两个类,第一个类名称叫"clsLighteningBoltMain",第2个为"clsLighteningBolt"Enough of that on with the fun. I use 2 classes in this method: the first you only need on ref to its name is "clsLighteningBoltMain". It's more or less just a container class for the second class called "clsLighteningBolt".

2.1 clsLighteningBoltMain类

Class variables主要类成员变量

Private BoltArray  as clsLighteningBolt

This is the head of are singly linked list

Functions过程

Public Function Get_YfromXZ(ByVal X as single, ByVal Z as single) as Single

这个过程返回地面在X,Z的高度(注:此返回值为0因为地面是平面)This function returns the height of the ground at X, Z. (Note: This function only returns 0 because our ground is flat)


Public Sub AddBolt(ByVal x As Single, ByVal y As Single, ByVal z As Single, lColor As Long)

这个过程加入启使的X,Y,Z坐标并带有颜色值。This sub adds a bolt to the list at the starting pos of X, Y, Z with the color lColor (Note: for some unknown reason color is not working; if any one finds out why please e-mail me)

Public Sub DrawBolts()

这个过程绘出连续闪电,将远离的移除。This sub draws the bolt list and removes any bolts that say they can be removed.

2.2 clsLighteningBolt类

Variables类成员变量

Public iNext  as clsLighteningBolt

指向下一个Pointer to the next bolt in the list

Public Parent     as clsLighteningBoltMain

Pointer to the container class (so we can call Get_YFromXZ)

Functions过程

Public Sub Init_Bolt(ByVal X as single, ByVal Y as single, _
          ByVal Z as Single, iColor as Long)

设置开始的值Sets the bolt startup values

Public Function Draw_Bolt() as Boolean

Draws the bolt and returns false if it's done (e.g. hit the ground)

2.3 How the code works代码是任何工作的

2.3.1 clsLighteningMain

Get_YFromXZ

This function returns the height of the ground/strike plane at position (x, z).

Public Function Get_YFromXZ(ByVal x As Single, _
                          ByVal z As Single) As Single
  Get_YFromXZ = 0
End Function

AddBolt

This sub adds a bolt to the start of the bolt list with the specified position and color.

Public Sub AddBolt(ByVal x As Single, ByVal y As Single, ByVal z As Single, lColor As Long)

  Dim NewBolt As New clsLighteningBolt
NewBolt.Init_Bolt x, y, z, lColor
Set NewBolt.iNext = BoltArray
Set BoltArray = NewBolt
Set NewBolt.Parent = Me
End Sub

DrawBolts

这个过程绘出每节闪电,将碰到地面的移除This sub draws all of the bolts in the bolt list and removes bolts that have hit the ground.

Public Sub DrawBolts()
  Dim Curr As clsLighteningBolt
 Dim Last As clsLighteningBolt
  Device.SetVertexShader FVF_LineVertex

  Set Curr = BoltArray
  Device.SetTexture 0, Nothing

 Do

If Curr Is Nothing Then Exit Do

 If Curr.Draw_Bolt() = False Then

 If Not Last Is Nothing Then

 Set Last.iNext = Curr.iNext

 Set Curr = Curr.iNext

 Else

 Set BoltArray = Curr.iNext

 Set Curr = BoltArray

 End If
 Else
 Set Last = Curr
 Set Curr = Curr.iNext
 End If
Loop
End Sub

2.3.2 clsLighteningBolt

InitBolt

设置第一节闪电This sub just sets the first line segment up.

Public Sub Init_Bolt(ByVal x As Single, ByVal y As Single, ByVal z As Single, ByVal iColor As Long)
  ReDim Lines(1)
  NumberLines = 1
  With Lines(0)
 .x = x
 .y = y
 .z = z
   .Color = iColor
  End With
  With Lines(1)
  .x = x
 .y = y - 0.06 牋?.z = z 牋?.Color = iColor End With End Sub

DrawBolt

这个过程绘制一个或多个顶点,并返回成功或失败。This sub draws and adds one more vertex to the line strip and returns true if its not done yet and false if it is.

Public Function Draw_Bolt() As Boolean
NumberLines = NumberLines + 1
ReDim Preserve Lines(NumberLines)
With Lines(NumberLines)
    .x = Lines(NumberLines - 1).x + (1 - Rnd * 2) * 0.3
    .y = Lines(NumberLines - 1).y - (Rnd + 0.55)
    .z = Lines(NumberLines - 1).z + (1 - Rnd * 2) * 0.3
    .Color = Lines(0).Color
End With

3.0 Theory理论

3.1 How it works它是如何工作的

这里有一个表包含了每一节。The way this works is really simple when you think about it. There is a list of all the bolts that this container needs to think about. You add and remove bolts from there. Here's a picture to help out with this one:

Adding a new bolt加入新节

Step One:第一步

创建一个新节的类并赋值Create a new bolt class and set its variables.

Step 2:两步

新节加入到列表的右面Insert the new bolt into the list right after the head.

Removing a bolt移除一节

Steps:

    ?
  1. Set 1.iNext = 2.iNext ?
  2. Set 2.iNext = Nothing ?
  3. Set 2 = Nothing

计算出下一节方在那里Figuring out where to put the next vertex for a bolt is even easier then that. Here's how:

1.调整数组大小Resize the Vertex array so you can fit one more vertex in it

2.设置X值为 X 到 X(index-1) + 1-(rnd * 2) * 0.3,Z轴不变。Set the X to X(index-1) + 1-(rnd * 2) * 0.3 and same for the z coordint

3.设置Y值为y 到 Y(index-1) - (rnd + .55)   Set y to Y(index-1) - (rnd + .55)

最后绘制闪电Now last but not least: drawing the bolt. I do it with DirectX using a line strip.

Device.DrawPrimitiveUP D3DPT_LINESTRIP, NumberLines, Lines(0), Length_LineVertex


4.0 Conclusion

Well that all there is to it. Not hard, is it?

WepPage: http://www.telusplanet.net/public/javaman/

E-Mail: javaman@telusplanet.net