Single Surface Particles

Blitz3D Forums/Blitz3D Programming/Single Surface Particles

CopperCircle(Posted 2003) [#1]
Im trying to get my head round manipulating vertices and want to make a full single surface particle system, here`s a modified version of the code Joker posted, I have added vertex alpha fading and removed the timing codem, but im still not sure how to add scaling?

http://www.apaj15.dsl.pipex.com/SSParticles.zip


Ross C(Posted 2003) [#2]
Hey, i'm Joker incase you were wondering, a wee name change ^_^

Scaling was a wee bit of a toughy for me at first :)

The scaling i'm using the now, assummes the particle the square. Now i don't know if the version i posted had rotation in it? Anyway, i used an angle of 45 deg for the unrotated particle.

Then i basically used sin and cos to position the vertex.

VertexCoords(fire_surface,p\pindex+0,p\x+Sin(p\ang)*p\size,p\y+Cos(p\ang)*p\size,p\z)



p\x being the centre of the quad.
p\ang being the z angle of rotation
p\size, being the scaled size

say sin(45),cos(45)
this would give co-ords of (0.7,0.7)
if you had a scale variable, then multiply the co-ords by it
sin(45)*2,cos(45)*2
(1.4,1.4)

Now, add those co-ords to the centre co-ords. that positions one of your vertexs. For the next one, add 90 to the angle and do the same
VertexCoords(fire_surface,p\pindex+1,p\x+Sin(p\ang+90)*p\size,p\y+Cos(p\ang+90)*p\size,p\z)


This time add 180, and the next time, add 270. This should position all you vertexs and scale them outwards.

There prob is another way which was explained to me, but i choose to go with this. Easier for me to understand.

For the stuff to do with making the particles always face the camera, i again used sin and cos, but altered the y axis of the particle.

I'll send you make 'complete' system if you wish?


Ross C(Posted 2003) [#3]
Ok, i'll edited your .bb file to add scaling

;---------------------------------
;Single Surface Particles by Joker
;Modified by CopperCircle 18/10/03
;---------------------------------

Graphics3D 800,600,32,2
SetBuffer BackBuffer()

cam=CreatePivot()

camera=CreateCamera(cam)
PositionEntity camera,0,15,-30

mesh=CreateMesh()

surface=CreateSurface(mesh)

NUM_PARTICLES=60

Type s_part
	Field x#,y#,z#; central position for the quad
	Field index; index for the first vertex
	Field ang#; ang value. -45 for normal
	Field alpha#
	Field speed#
	Field fadebias#
	Field life%
	Field ang_speed#
	Field active
	Field pindex
	Field scale#; ******** ADDED
End Type

ang=-45
index=0

tex=LoadTexture("smoke.bmp",2)

EntityTexture mesh,tex
EntityFX mesh,32+2
EntityBlend mesh,3
ScaleEntity mesh,4,4,4

For loop=0 To NUM_PARTICLES
	Gosub create_spart
Next

FreeTexture tex

While Not KeyHit(1)
	
	cx=EntityPitch(camera,True)
	cy=EntityYaw(camera,True)
	cz=0
	
	If KeyDown(2) Then Gosub create_spart
	
	RotateEntity mesh,cx,cy,cz
	
	If MilliSecs()<timer+1000 Then
		frame=frame+1
	Else
		fps=frame
		frame=0
		timer=MilliSecs()
	End If
	
	Gosub update_spart
	UpdateWorld
	RenderWorld
	Text 0,0,"Number of quads="+(index/4)+" fps="+fps+" tris rendered="+TrisRendered()
	Text 0,15,"Press 1 to add particles."
	Flip 0
Wend
End

.create_spart
	p.s_part=New s_part
	p\pindex=index
	index=index+4
	p\active=1
	p\x=Rnd(-2,2)
	p\y=0
	p\z=Rnd(-2,2)
	p\life=Rnd(200,600)
	p\fadebias=0.002
	p\speed=Rnd(0.01,0.02)
	p\ang_speed=Rnd(0.1,2)
	p\ang=Rnd(-45,135)
	v0=AddVertex(surface,p\x,p\y,p\z,0,1)
	v1=AddVertex(surface,p\x,p\y,p\z,1,1)
	v2=AddVertex(surface,p\x,p\y,p\z,0,0)
	v3=AddVertex(surface,p\x,p\y,p\z,1,0)
	tri=AddTriangle(surface,v0,v1,v2)
	tri1=AddTriangle(surface,v1,v3,v2)
	p\scale=Rnd(0.5,1); ******** ADDED
Return

.update_spart
For p.s_part=Each s_part
	If p\active=1 Then
		p\life=p\life-1
		p\y=p\y+p\speed
		p\ang=p\ang+p\ang_speed
		p\scale=p\scale+0.01; ******** ADDED
		
		VertexCoords(surface,p\pindex+0,p\x+Sin(p\ang)*p\scale,p\y+Cos(p\ang)*p\scale,p\z);; ******** EDITED
		VertexCoords(surface,p\pindex+1,p\x+Sin(p\ang+90)*p\scale,p\y+Cos(p\ang+90)*p\scale,p\z); ******** EDITED
		VertexCoords(surface,p\pindex+2,p\x+Sin(p\ang-90)*p\scale,p\y+Cos(p\ang-90)*p\scale,p\z); ******** EDITED
		VertexCoords(surface,p\pindex+3,p\x+Sin(p\ang+180)*p\scale,p\y+Cos(p\ang+180)*p\scale,p\z); ******** EDITED
		VertexColor surface,p\pindex+0,200,200,200,p\life*p\fadebias
		VertexColor surface,p\pindex+1,200,200,200,p\life*p\fadebias
		VertexColor surface,p\pindex+2,200,200,200,p\life*p\fadebias
		VertexColor surface,p\pindex+3,200,200,200,p\life*p\fadebias
		If p\life=0
			p\active=0
			VertexColor surface,p\pindex+0,200,200,200,0
			VertexColor surface,p\pindex+1,200,200,200,0
			VertexColor surface,p\pindex+2,200,200,200,0
			VertexColor surface,p\pindex+3,200,200,200,0
			Gosub new_spart
		End If
	End If
Next
Return

.new_spart
	loop_exit=0
	For p.s_part=Each s_part
		If p\active=0 Then
			p\active=1
			p\x=Rnd(-2,2)
			p\y=0
			p\z=Rnd(-2,2)
			p\life=Rnd(200,600)
			p\fadebias=0.002
			p\speed=Rnd(0.01,0.02)
			p\ang_speed=Rnd(0.1,2)
			p\ang=Rnd(-45,135)
			p\scale=Rnd(0.5,1); ******** ADDED
			loop_exit=1
			VertexCoords(surface,p\pindex+0,p\x+Sin(p\ang)*p\scale,p\y+Cos(p\ang)*p\scale,p\z); ******** EDITED
			VertexCoords(surface,p\pindex+1,p\x+Sin(p\ang+90)*p\scale,p\y+Cos(p\ang+90)*p\scale,p\z); ******** EDITED
			VertexCoords(surface,p\pindex+2,p\x+Sin(p\ang-90)*p\scale,p\y+Cos(p\ang-90)*p\scale,p\z); ******** EDITED
			VertexCoords(surface,p\pindex+3,p\x+Sin(p\ang+180)*p\scale,p\y+Cos(p\ang+180)*p\scale,p\z); ******** EDITED
		End If
		If loop_exit=1 Then Exit
	Next
Return



CopperCircle(Posted 2003) [#4]
Thanks Ross, I see now. Vertex manipulation is great stuff once you get to understand the basics.


Ross C(Posted 2003) [#5]
Yeah, it's pretty cool. If you need anymore help, just post back. Have a go tho, at making the particles always face the camera :)


CopperCircle(Posted 2003) [#6]
The big problem I see now is the speed hit scaling adds, without scaling I get over 400fps with 120 quads, with scaling I get 68fps!


Ross C(Posted 2003) [#7]
Well, just move the camera back a bit. It's probably the fill rate that's killing the fps. Your particles in a game usually won't fill the whole screen anyways :)