3d lightning like test

Miscellaneous Forums/Blitz Showcase/3d lightning like test

Hey everyone. I've created some code to create lightning, sort of. Involves deforming a mesh in real-time. You can use these function for whatever. Could a get a fps on the code running as it is though, please? Press space bar to get the TRUE fps reading, thanks :)

It's better when viewed moving. Remember the below code is simply just to rotate them. The functions do the work of creating and deforming the meshes. Hopefully is useful to someone other than me :)



Graphics3D 800,600
SetBuffer BackBuffer()
;WireFrame True

Type bolt
	Field x#,y#,z#
	Field mesh
	Field surf
	Field segments ; number of segments the cylinder has |===|===| = 2 segments
	Field divisions ; how smooth the cylinder looks
	Field seg_length#
End Type 



Global piv=CreatePivot()
Global cam=CreateCamera(piv)
PositionEntity cam,0,5,-11
RotateEntity cam,30,0,0
CameraRange cam,0.1,100

Global light=CreateLight()
TurnEntity light,45,45,45

For loop=0 To 13
	l.bolt=New bolt
		l\x=0
		l\y=0
		l\z=0
		l\mesh=CreateMesh()
		l\surf=CreateSurface(l\mesh)
		l\segments=Rand(3,5)
		l\seg_length=Rand(5,7)
		l\divisions=3
	
	create_rod(l\mesh,l\surf,l\segments,l\divisions,l\seg_length)
	
	UpdateNormals(l\mesh)
	EntityFX l\mesh,32+2
	;PositionEntity l\mesh,0,0,-(l\seg_length*l\segments)*0.5
	ScaleEntity l\mesh,0.2,0.2,1

Next

Global sync=1 ; for v-sync

Dim random#(7,2)




While Not KeyHit(1)
	
	If KeyDown(203) Then RotateEntity piv,EntityPitch(piv),EntityYaw(piv)+1,EntityRoll(piv)
	If KeyDown(205) Then RotateEntity piv,EntityPitch(piv),EntityYaw(piv)-1,EntityRoll(piv)
	If KeyDown(200) Then RotateEntity piv,EntityPitch(piv)-1,EntityYaw(piv),EntityRoll(piv)
	If KeyDown(208) Then RotateEntity piv,EntityPitch(piv)+1,EntityYaw(piv),EntityRoll(piv)
	If KeyHit(57) Then sync=1-sync
	For l.bolt=Each bolt
		reset_rod(l\mesh,l\surf,l\segments,l\divisions,l\seg_length)
		randomise_rod(l\mesh,l\surf,l\segments,l\divisions)
		TurnEntity l\mesh,0,Rnd(0.1,2),0
	Next

	
	If MilliSecs()<timer+1000 Then
								frame=frame+1
	Else
								fps=frame
								frame=0
								timer=MilliSecs()
	End If
	UpdateWorld
	RenderWorld
	Text 0,0,fps
	;Text 0,10," Press SPACE BAR to disable/enable v-sync"
	Flip sync
	;Delay 6
Wend
End


Function create_rod(mesh,surf,segments,divisions,segment_length)

	count=0

	For loop=0 To segments
	
		For loop1=1 To divisions

			AddVertex(surf,  Cos(loop1*(360/divisions))  ,  Sin(loop1*(360/divisions))  ,  loop*segment_length  )
			VertexColor surf,count,70,130,250,0.3
			count=count+1

		Next
	
	Next
	
	
	For loop=0 To segments
	
		For loop1=1 To divisions

			temp=AddVertex(surf,  (Cos(loop1*(360/divisions))/4)  ,  (Sin(loop1*(360/divisions))/4)  ,  loop*segment_length  )
			VertexColor surf,temp,70,130,250,0.7

		Next
	
	Next
		
	
	For loop=0 To segments-1
	
		For loop1=0 To divisions-1; must always be 1 less than divisions, because vertex index starts at 0
	
			If loop1<divisions-1 Then
				tri=AddTriangle(surf,loop*divisions+loop1,(loop+1)*divisions+loop1+1,(loop+1)*divisions+loop1)
				tri1=AddTriangle(surf,loop*divisions+loop1,loop*divisions+loop1+1,(loop+1)*divisions+loop1+1)
			Else
				tri=AddTriangle(surf,loop*divisions+loop1,(loop+1)*divisions+0,(loop+1)*divisions+loop1)
				tri1=AddTriangle(surf,loop*divisions+loop1,loop*divisions+0,(loop+1)*divisions+0)
			End If
			
		Next
	Next
	
	For loop=0 To segments-1
	
		For loop1=0 To divisions-1; must always be 1 less than divisions, because vertex index starts at 0
	
			If loop1<divisions-1 Then
				tri = AddTriangle(surf , count+ loop*divisions+loop1, count+ (loop+1)*divisions+loop1+1,	count+ (loop+1)*divisions+loop1)
				tri1= AddTriangle(surf , count+ loop*divisions+loop1, count+ loop*divisions+loop1+1,		count+ (loop+1)*divisions+loop1+1)
			Else
				tri = AddTriangle(surf , count+ loop*divisions+loop1, count+ (loop+1)*divisions+0,			count+ (loop+1)*divisions+loop1)
				tri1= AddTriangle(surf , count+ loop*divisions+loop1, count+ loop*divisions+0,				count+ (loop+1)*divisions+0)
			End If
	
		Next
	Next

	
	UpdateNormals(mesh)
	;ScaleMesh mesh,0.2,0.2,1
End Function

Function reset_rod(mesh,surf,segments,divisions,segment_length)

	count=0
	For loop=0 To segments
		For loop1=1 To divisions
			VertexCoords(surf,count, Cos(loop1*(360/divisions))  ,  Sin(loop1*(360/divisions))  ,  loop*segment_length  )
			count=count+1
		Next
	Next
	
	count1=0
	For loop=0 To segments
		For loop1=1 To divisions
			VertexCoords(surf,count+count1, (Cos(loop1*(360/divisions))/4)  ,  (Sin(loop1*(360/divisions))/4)  ,  loop*segment_length  )
			count1=count1+1
		Next
	Next


End Function

Function randomise_rod(mesh,surf,segments,divisions,spread=5)

	count=0
	For loop#=0 To segments
		
		random(loop,0)=Rnd(-spread,spread)
		random(loop,0)=random(loop,0) *(loop/segments) ; FOR X VERT. after the * sign, cause the tapering effect.
		
		random(loop,1)=Rnd(-spread,spread) ; FOR Y VERT
		random(loop,1)=random(loop,1) *(loop/segments)
		
		random(loop,2)=Rnd(-spread,spread) ; FOR Z VERT
		random(loop,2)=random(loop,2) *(loop/segments)
		
		For loop1=0 To divisions-1
			VertexCoords( surf,count,VertexX(surf,count)+(random(loop,0)), VertexY(surf,count)+(random(loop,1)), VertexZ(surf,count)+(random(loop,2)) ) 
			count=count+1
		Next
	Next
	
	count1=0
	For loop#=0 To segments
		
	
		For loop1=0 To divisions-1
			VertexCoords( surf,count+count1,VertexX(surf,count+count1)+(random(loop,0)), VertexY(surf,count+count1)+(random(loop,1)), VertexZ(surf,count+count1)+(random(loop,2)) ) 
			count1=count1+1
		Next
	Next


End Function


any chance of a screenie ross boi :)

Done :)

Almost 700 fps at it's highest (gf3 ti 200, p4 1,8). But for a lightning, your effect could do with a retouch.

Explain please, i'm open to ideas to improve it :)

Most lightnings have forks, and unless it's a longlasting one (like those globes ya' know), it will not move, also normal lightnings usually have more kinks. But you seem to have the base, if you can add forks etc it will be awesome :)

I could find the end of a segment and generate a new bolt from that point... Thanks, i'll be back soon :)

that looks good for electrical effects.

Hey again. I've made this so it now looks like real(ish) lightning. You can use this for whatever you want.

Graphics3D 800,600
SetBuffer BackBuffer()
WireFrame True

Type bolt
	Field ID ; which bolt it belongs to
	Field x#,y#,z#
	Field mesh
	Field surf
	Field segments ; number of segments the cylinder has |===|===| = 2 segments
	Field divisions ; how smooth the cylinder looks
	Field seg_length#
	Field status; has been checked for possiblity of creating a branch
	Field timer
	Field time
End Type 

Type lightning
	Field ID
	Field number
	Field max_number
	Field time
	Field timer
End Type


Global piv=CreatePivot()
Global cam=CreateCamera(piv)
PositionEntity cam,0,5,-71
RotateEntity cam,30,0,0
CameraRange cam,0.1,100

Global light=CreateLight()
TurnEntity light,45,45,45


Global sync=1 ; for v-sync

Dim random#(7,2)


Global id=0
Global ltime=Rand(100,1000)
Global ltimer=MilliSecs()


While Not KeyHit(1)
	
	If KeyDown(203) Then RotateEntity piv,EntityPitch(piv),EntityYaw(piv)+1,EntityRoll(piv)
	If KeyDown(205) Then RotateEntity piv,EntityPitch(piv),EntityYaw(piv)-1,EntityRoll(piv)
	If KeyDown(200) Then RotateEntity piv,EntityPitch(piv)-1,EntityYaw(piv),EntityRoll(piv)
	If KeyDown(208) Then RotateEntity piv,EntityPitch(piv)+1,EntityYaw(piv),EntityRoll(piv)
	If KeyHit(57) Then sync=1-sync


	If KeyHit(2) Then generate_bolt()
	If MilliSecs()>ltime+ltimer Then
		generate_bolt()
		ltimer=MilliSecs()
		ltime=Rand(100,1000)
	End If
	
	
	If MilliSecs()<timer+1000 Then
								frame=frame+1
	Else
								fps=frame
								frame=0
								timer=MilliSecs()
	End If
	update_bolt()
	UpdateWorld
	RenderWorld
	Text 0,0,fps
	Text 0,10," Press SPACE BAR to disable/enable v-sync"
	Flip sync
	Delay 6
Wend
End

Function generate_bolt()
	b.lightning=New lightning
		id=id+1
		b\ID=id
		b\max_number=Rand(5,10)
		b\number=0
		b\time=10
		b\timer=MilliSecs()
			l.bolt=New bolt
				l\ID=b\ID
				l\x=Rand(-15,15)
				l\y=6
				l\z=Rand(-15,15)
				l\mesh=CreateMesh()
				l\surf=CreateSurface(l\mesh)
				l\segments=Rand(3,5)
				l\seg_length=Rand(7,7)
				l\divisions=3
				l\time=20
				l\timer=MilliSecs()

				create_rod(l\mesh,l\surf,l\segments,l\divisions,l\seg_length)
				;randomise_rod(l\mesh,l\surf,l\segments,l\divisions)

				EntityFX l\mesh,32+2
				PositionEntity l\mesh,l\x,l\y,l\z
				RotateMesh l\mesh,Rnd(70,110),0,0
				ScaleEntity l\mesh,0.2,1,0.2
				;EntityColor l\mesh,100,255,0

				temp_x=find_coord(l\mesh,l\surf,l\segments,l\divisions,l\seg_length,0)
				temp_y=find_coord(l\mesh,l\surf,l\segments,l\divisions,l\seg_length,1)
				temp_z=find_coord(l\mesh,l\surf,l\segments,l\divisions,l\seg_length,2)


End Function


Function update_bolt()

	temp_status=0
	
	For b.lightning= Each lightning
		If MilliSecs()>b\time+b\timer Then
			If b\number < b\max_number Then
			
				b\timer=MilliSecs()
				b\number=b\number+1; increase the number of bolts generated

				For l.bolt=Each bolt
					If l\id=b\id Then

						temp.bolt=l.bolt
						If l\status=1 Then temp_status=1
						If l\status=0 Then ; bolt has not been checked to generate more bolts
						
							If Rand(0,9)=>0 Then ; random if any bolts are generated
								temp_bolt=0
								temp_status=0
								
								For loop=1 To Rand(2,3) ; how many are generated
									temp_bolt=temp_bolt+1

									l.bolt=temp.bolt ; make sure the type handle is the same is it started
									temp_x=find_coord(l\mesh,l\surf,l\segments,l\divisions,l\seg_length,0)
									temp_y=find_coord(l\mesh,l\surf,l\segments,l\divisions,l\seg_length,1)
									temp_z=find_coord(l\mesh,l\surf,l\segments,l\divisions,l\seg_length,2)

									l.bolt=New bolt
										l\ID=b\ID
										l\x=temp_x
										l\y=temp_y
										l\z=temp_z
										l\mesh=CreateMesh()
										l\surf=CreateSurface(l\mesh)
										l\segments=Rand(3,5)
										l\seg_length=Rand(5,7)
										l\divisions=3
										l\time=0
										l\timer=MilliSecs()
									
									create_rod(l\mesh,l\surf,l\segments,l\divisions,l\seg_length)
									;randomise_rod(l\mesh,l\surf,l\segments,l\divisions)

									EntityFX l\mesh,32+2
									PositionEntity l\mesh,l\x,l\y,l\z
									ScaleEntity l\mesh,0.2,1,0.2
									RotateMesh l\mesh,Rnd(30,150),Rnd(30,150),Rnd(30,150)
								Next
								
								DebugLog(" no. of bolts="+temp_bolt)
						
							End If
							
							l.bolt=temp.bolt
							l\status=1 ; has been checked
						End If
					End If
					If l\status=1 And temp_status=0 Then Exit ; if lightning bolts have been generated then exit the loop
				Next
							
				
			ElseIf b\number => b\max_number Then
			
				delete_rods(b\ID)
				Delete b.lightning
				
			End If
		End If
	Next
End Function

Function find_coord(mesh,surf,segments,divisions,segment_length,coord)
	find_seg=segments-1
	count=0
	For loop=0 To segments
		For loop1=1 To divisions
			VertexCoords( surf,count,VertexX(surf,count)+(random(loop,0)), VertexY(surf,count)+(random(loop,1)), VertexZ(surf,count)+(random(loop,2)) ) 
			count=count+1
		Next
	Next

	count1=0
	For loop=0 To segments
		For loop1=1 To divisions
			VertexCoords( surf,count+count1,VertexX(surf,count+count1)+(random(loop,0)), VertexY(surf,count+count1)+(random(loop,1)), VertexZ(surf,count+count1)+(random(loop,2)) ) 
			count1=count1+1
		Next
		If find_seg=loop Then
			TFormPoint VertexX(surf,count+count1), VertexY(surf,count+count1), VertexZ(surf,count+count1), mesh, 0
			If coord=0 Then
				Return TFormedX() ; Point x#, y#, z#, source_entity, dest_entity(EntityX(mesh)+VertexX(surf,count+count1))
			ElseIf coord=1 Then
				Return TFormedY() ; (EntityY(mesh)+VertexY(surf,count+count1))
			ElseIf coord=2 Then
				Return TFormedZ() ; (EntityZ(mesh)+VertexZ(surf,count+count1))
			End If
		End If
	Next
End Function

Function delete_rods(id)
	For l.bolt=Each bolt
		If l\ID=id Then
			FreeEntity l\mesh
			Delete l.bolt
		End If
	Next
End Function

Function create_rod(mesh,surf,segments,divisions,segment_length)

	count=0

	For loop=0 To segments
	
		For loop1=1 To divisions

			AddVertex(surf,  Cos(loop1*(360/divisions))  ,  Sin(loop1*(360/divisions))  ,  loop*segment_length  )
			VertexColor surf,count,255,255,255,0.2;70,130,250,0.3
			count=count+1

		Next
	
	Next
	
	
	For loop=0 To segments
	
		For loop1=1 To divisions

			temp=AddVertex(surf,  (Cos(loop1*(360/divisions))/6)  ,  (Sin(loop1*(360/divisions))/6)  ,  loop*segment_length  )
			VertexColor surf,temp,255,255,255,0.5;70,130,250,0.7

		Next
	
	Next
		
	
	For loop=0 To segments-1
	
		For loop1=0 To divisions-1; must always be 1 less than divisions, because vertex index starts at 0
	
			If loop1<divisions-1 Then
				tri=AddTriangle(surf,loop*divisions+loop1,(loop+1)*divisions+loop1+1,(loop+1)*divisions+loop1)
				tri1=AddTriangle(surf,loop*divisions+loop1,loop*divisions+loop1+1,(loop+1)*divisions+loop1+1)
			Else
				tri=AddTriangle(surf,loop*divisions+loop1,(loop+1)*divisions+0,(loop+1)*divisions+loop1)
				tri1=AddTriangle(surf,loop*divisions+loop1,loop*divisions+0,(loop+1)*divisions+0)
			End If
			
		Next
	Next
	
	For loop=0 To segments-1
	
		For loop1=0 To divisions-1; must always be 1 less than divisions, because vertex index starts at 0
	
			If loop1<divisions-1 Then
				tri = AddTriangle(surf , count+ loop*divisions+loop1, count+ (loop+1)*divisions+loop1+1,	count+ (loop+1)*divisions+loop1)
				tri1= AddTriangle(surf , count+ loop*divisions+loop1, count+ loop*divisions+loop1+1,		count+ (loop+1)*divisions+loop1+1)
			Else
				tri = AddTriangle(surf , count+ loop*divisions+loop1, count+ (loop+1)*divisions+0,			count+ (loop+1)*divisions+loop1)
				tri1= AddTriangle(surf , count+ loop*divisions+loop1, count+ loop*divisions+0,				count+ (loop+1)*divisions+0)
			End If
	
		Next
	Next

	
	UpdateNormals(mesh)
	;ScaleMesh mesh,0.2,0.2,1
End Function

Function reset_rod(mesh,surf,segments,divisions,segment_length)

	count=0
	For loop=0 To segments
		For loop1=1 To divisions
			VertexCoords(surf,count, Cos(loop1*(360/divisions))  ,  Sin(loop1*(360/divisions))  ,  loop*segment_length  )
			count=count+1
		Next
	Next
	
	count1=0
	For loop=0 To segments
		For loop1=1 To divisions
			VertexCoords(surf,count+count1, (Cos(loop1*(360/divisions))/4)  ,  (Sin(loop1*(360/divisions))/4)  ,  loop*segment_length  )
			count1=count1+1
		Next
	Next


End Function

Function randomise_rod(mesh,surf,segments,divisions,spread=5)

	count=0
	For loop#=0 To segments
		
		random(loop,0)=Rnd(-spread,spread)
		random(loop,0)=random(loop,0) *(loop/segments) ; FOR X VERT. after the * sign, cause the tapering effect.
		
		random(loop,1)=Rnd(-spread,spread) ; FOR Y VERT
		random(loop,1)=random(loop,1) *(loop/segments)
		
		random(loop,2)=Rnd(-spread,spread) ; FOR Z VERT
		random(loop,2)=random(loop,2) *(loop/segments)
		
		For loop1=0 To divisions-1
			VertexCoords( surf,count,VertexX(surf,count)+(random(loop,0)), VertexY(surf,count)+(random(loop,1)), VertexZ(surf,count)+(random(loop,2)) ) 
			count=count+1
		Next
	Next
	
	count1=0
	For loop#=0 To segments
		
	
		For loop1=0 To divisions-1
			VertexCoords( surf,count+count1,VertexX(surf,count+count1)+(random(loop,0)), VertexY(surf,count+count1)+(random(loop,1)), VertexZ(surf,count+count1)+(random(loop,2)) ) 
			count1=count1+1
		Next
	Next


End Function


Lighnings usually just appear and disapear, they don't build up this way (yes, he can continue complaining for an eternity ;)

Yeah, i've got a few things too clean up :)

SWEET.

Actually I add a EntityBblend l\mesh,3 and I like it more ;)

Paolo.

awesome mann..... perfect for when i stop time in my game :)

very cool!!! :-)