SyntaxBomb - Indie Coders

Languages & Coding => Blitz Code Archives => 3D Graphics - Effects => Topic started by: BlitzBot on June 29, 2017, 00:28:42

Title: [bb] Explosion Generator (non interactive) by Matty [ 1+ years ago ]
Post by: BlitzBot on June 29, 2017, 00:28:42
Title : Explosion Generator (non interactive)
Author : Matty
Posted : 1+ years ago

Description : This program generates explosion animated images in the format of a 4096x4096 bitmap with 64 frames (8x8 512x512).

There are only two parameters the user needs to set (at the top of the program.)

These are:

1 - flag indicating whether to save/render the image to the hard drive (in subfolder erenders - make sure you have folder permissions!)

2 - the qty of renders you wish to save.

The program will exit after completing the final render or on pressing escape.

Of course using these images in a game will most likely require they be downsampled first......


Code :
Code (blitzbasic) Select
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Only two parameters you need!
Const saverenders = False ;change this accordingly NOTE RENDERING IS SLOW!
Global qty = 4 ;number of explosions to render as animated images change this accordingly

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Matt Lloyd Explosion Generator (as used in my Space Battle Game for Android Devices)
;
;4-April-2015 ML
; Note/Caveat - this code is not pretty - I fully admit that.  It is not intended to be.  It does its job and that's it.
;
; This program will generate 2d renders of explosions using blitz3d at a resolution of 512x512.
;
;   No user interaction is required once the program starts......fire and forget.......
;
; If you wish to save these renders then you need to change the value of the const at the top of the program (set 'saverenders' to true)
;
; Renders are saved as 4096x4096 images (8x8 frames of 512x512 images) into a sub folder called 'erenders' with file naming convention
; 'explosion_currentdatetime_indexnumber.bmp'
;
; As far as I am aware 4096x4096 is the largest image that blitz can manage without internally resizing it - so why not go for the maximum resolution!
;
;
; Note 2 - It takes a few sequences to warm up before it attempts to render as it tries to make sure that
; as much of the texture atlas is consumed.
;
; Note 3  - It exports to bitmap. Yuck.  That can be changed pretty easily.
;
; Note 4 - I imagine this may fail to render anything on certain PCs if they can't keep up with the frame rate.
;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Technically no need to touch anything beyond this point!  All trespassers will be shot and so forth!
HidePointer
Global camera,ent,pivot,speciallist$
Global explosiontexture
Global cdate$ = Replace(CurrentDate$()," ","_")+"_"+Replace(CurrentTime$(),":","_")
SeedRnd MilliSecs()
main()
End


Function main()

;miscellaneous vars - you don't need to touch these...
Local box, render, e.explosion, time, time2, time3, frame, f0,f1,f2
Local q, xx#,yy#,zz#,aab,aac,aae,x11,y11

init()

box = CreateCube()
MoveEntity box,0,0,80
EntityAlpha box,0

render = CreateImage(4096,4096); 512*8, 512*8
e.explosion = First explosion
time = MilliSecs()
time2 = 10000
time3 = 10000

Repeat
time11 = MilliSecs()
Cls
frame = frame + 1

If(MilliSecs()>time And e=Null) Then
f0 = f1
f1 = frame
f2 = f2+1
time2 = f1 + (290/17)
time3 = f1 + (130/17)
For q = 0 To 2
If(q>0) Then
xx# = Rnd(-10,10)
yy# = Rnd(-10,10)
zz# = Rnd(-8,2)
EndIf
aab = 1 - Sgn(Rand(0,20))
aac = 1 - Sgn(Rand(0,2))
aae = Sgn(Rand(0,20))

createexplosion(box,1,aae,aac,aab,Rnd(0.65,1.35),1,0,0,0,0,0,xx,yy,10+zz);
If(q=2)
createexplosion(box,0,0,aac,1,Rnd(0.7,1.05),1,0,0,0,0,0,xx,yy,10+zz);
EndIf
Next
EndIf

If(frame>time3) Then
For q = 0 To 2
If(q<>-1) Then
xx# = Rnd(-20,20)
yy# = Rnd(-20,20)
zz# = Rnd(-1,1)
EndIf
aac = 1 - Sgn(Rand(0,10))
createexplosion(box,3,1,aac,0,Rnd(0.8,1.35),   1,0,0,0,0,0,xx,yy,16+zz);
If(q=0) Then
createexplosion(box,0,0,0,1,Rnd(0.6,1.0),1,0,0,0,0,0,xx,yy,16+zz);
EndIf
Next
time3 = frame + 100000
EndIf

If(frame>time2) Then
For q = 0 To 1
xx# = Rnd(-20,20)
yy# = Rnd(-20,20)
If(q=2) Then
xx=xx*1.5
yy=yy*1.5
EndIf
zz# = Rnd(-2,4)
aab = 1- Sgn(Rand(0,1))
createexplosion(box,1,aab,1-aab,0,Rnd(0.5,0.85),   1,0,0,0,0,0,xx,yy,8+zz);
If(q=0) Then
aab = 1- Sgn(Rand(0,1))
createexplosion(box,0,0,1-aab,aab,Rnd(0.3,0.5),1,0,0,0,0,0,xx,yy,9+zz);
EndIf
Next
time2 = frame + 10000
EndIf

updateexplosion()
RenderWorld
If(saverenders) Then
x11 = (frame - f1) Mod 8
y11 = ((frame - f1) - x11) / 8
CopyRect 0,0,512,512,x11*512,y11*512,BackBuffer(),ImageBuffer(render)
e.explosion = First explosion
If(e.explosion = Null And (f1-f0)>55 And (f1-f0)<64) Then
i11=i11+1
If(i11>2) Then
xr = 3
yr = 3
CopyRect xr*512,yr*512,512,512,0,0,ImageBuffer(render),BackBuffer()
Text 0,0,(f1 - f0)+" Sequence Length"
Text 256,30,"......Please wait Saving LARGE image......",1,1
Flip
SaveImage render,"erendersexplosion_"+cdate$+"_"+i11+".bmp"
qty = qty - 1
Color 0,0,0
SetBuffer ImageBuffer(render)
Rect 0,0,ImageWidth(render),ImageHeight(render),1
SetBuffer BackBuffer()
EndIf
EndIf
Else
e.explosion = First explosion
EndIf
Color 255,255,255
Text 0,0,f1 - f0
If saverenders Then Text 0,15,qty+" renders to go!"
Flip
time22 = MilliSecs()-time11
If(time22<17) Then
Delay 17 - time22
EndIf
Until KeyHit(1) Or qty<=0
End Function

Type explosion

Field originalent
Field ent
Field typ$
Field vx#,vy#,vz#
Field sx#,sy#,sz#
Field r#,g#,b#,a#
Field dp#,dy#,dr#
Field time#
Field timestep#
Field trailcreated
Field special

End Type

Function updateexplosion()

defaulttimestep#=0.025
For e.explosion = Each explosion
timestep# = e imestep
TranslateEntity eent,evx*(timestep/defaulttimestep),evy*(timestep/defaulttimestep),evz*(timestep/defaulttimestep),True
ScaleEntity eent,esx,esy,esz
EntityColor eent,e,eg,e
EntityAlpha eent,Float(ea)/255.0
TurnEntity eent,edp,edy,edr
e ime=e ime+timestep
updatefunction(e)
If(especial=1 And e ime >= 0 And e ime<e imestep*5) Then
createexplosion(ent,2,True,False,False,4,1,0,0,0,0,0)
EndIf
If(especial=1 And e ime >= e imestep*5) Then
EntityAlpha ent,0
EndIf
If(especial>0 And e ime>e imestep*Rand(5,10)) Then
createexplosion(eent,0,True,True,False,3,1,0,0,0,0,especial-1)
especial = 0
EndIf
If(e ime>=1.0 Or ea <= 0 Or esx<=0.001 Or esy<0.001 Or esz<0.001 Or (e<=0 And eg<=0 And e<=0))
FreeEntity eent
Delete e
EndIf
Next

End Function

Function updatefunction(e.explosion)

If(e yp="flames")

If(e ime<0.05) Then
esx = esx * (1.0 + ((e ime)/0.05)*0.0125)
esy = esy * (1.0 + ((e ime)/0.05)*0.0125)
esz = esz * (1.0 + ((e ime)/0.05)*0.0125)
ea = ea * (1.0-e imestep*15)
MoveEntity eent,evx,evy,evz
Else
If(e ime<0.5) Then
esx = esx * (1.05-e imestep*55)
esy = esy * (1.05-e imestep*55)
esz = esz * (1.05-e imestep*55)
ea = ea * (1.0-e imestep*5)
Else
esx = esx * (1.05-e imestep*5)
esy = esy * (1.05-e imestep*5)
esz = esz * (1.05-e imestep*5)
ea = ea * (1.0-e imestep*25)
EndIf
EndIf
EndIf


If(e yp="smoke") Then
If(e ime<0.15) Then
esx = esx *(1.0+(e ime/0.15)*0.1)
esy = esy *(1.0+(e ime/0.15)*0.1)
esz = esz *(1.0+(e ime/0.15)*0.1)
ea = ea - 0.5
Else
If(e ime>0.5)
esx = esx *(1.0-((e ime-0.5)/0.5)*0.025)
esy = esy *(1.0-((e ime-0.5)/0.5)*0.025)
esz = esz *(1.0-((e ime-0.5)/0.5)*0.025)
EndIf
ea=ea-1.25
EndIf

If(e ime<0.3) Then
evx = evx * (1.0 - (e ime/0.3)^2)
evy = evy * (1.0 - (e ime/0.3)^2)
evz = evz * (1.0 - (e ime/0.3)^2)
EndIf

EndIf


If(e yp="sparks")

ea = 255.0 - (Float(e railcreated) /50.0) *128.0

esx = esx * (1.0-e imestep)*0.925
esx = esx * (1.0-e imestep)*0.925
esx = esx * (1.0-e imestep)*0.925

MoveEntity eent,evx,evy,evz


If(e railcreated<50 )

;create a spark at our location with an increased time.....
f.explosion = New explosion
f yp = "smoke"
foriginalent = eent
fent = CreateCube()
EntityTexture fent,explosiontexture
EntityFX fent,1+16+32
fvx = evx*0.0125
fvy = evy*0.0125
fvz = evz*0.0125
fsx = esx*1.5
fsy = esy*1.5
fsz = esz*1.5
PositionEntity fent,EntityX(eent,True),EntityY(eent,True),EntityZ(eent,True)
f ime = 0
f imestep = 0.075
f = 128
fg = 128
f = 128
fa = 40
fdp=Rnd(-10,10)
fdy=Rnd(-10,10)
fdr=Rnd(-10,10)
e railcreated=e railcreated+1
EndIf
EndIf

If(esx<=0) Then esx=0.001
If(esy<=0) Then esy=0.001
If(esz<=0) Then esz=0.001
If(ea>255) Then ea=255
If(ea<0) Then ea=0
If(ea>255) Then ea=255
If(e>255) Then e=255
If(eg>255) Then eg=255
If(e>255) Then e=255
If(e<0) Then e=0
If(eg<0) Then eg=0
If(e<0) Then e=0


End Function


Function createexplosion(ent,n,hasflames=True,hassparks=True,hassmoke=True,scale#=1.0,size#=1.0,offsetx#=0,offsety#=0,offsetz#=0,starttime#=0.0,special=0,posx#=0,posy#=0,posz#=0)

If(explosiontexture=0) Then
texsize = 256
explosiontexture = CreateTexture(texsize,texsize,1+4+2)
SetBuffer TextureBuffer(explosiontexture)

pxx# = Float(texsize/2)-1
pyy# = Float(texsize/2)-1

rr# = 0.1

For px = 0 To texsize-1
For py = 0 To texsize-1
WritePixel px,py,0
Next
Next

aa = ((texsize/2)-4)*8
For jj = 0 To aa
For angle = 0 To 3600
myx# = pxx + rr*Cos(Float(angle)/10.0)
myy# = pyy + rr*Sin(Float(angle)/10.0)
col = Rand(250,255)
alpha = (col - (rr*Float(0.16))^2)
If(alpha<0) Then alpha = 0
If(alpha>255) Then alpha = 255
col = alpha
WritePixel Int(myx),Int(myy),alpha Shl 24 Or col Shl 16 Or col Shl 8 Or col
Next
rr=rr+0.1
Next
SetBuffer BackBuffer()
EndIf


;get bounding box....
xw# = MeshWidth(ent)*size
yw# = MeshHeight(ent)*size
zw# = MeshDepth(ent)*size

TFormPoint -xw/2,-yw/2,-zw/2,ent,0
x0# = TFormedX()
y0# = TFormedY()
z0# = TFormedZ()

TFormPoint +xw/2,+yw/2,+zw/2,ent,0
x1# = TFormedX()
y1# = TFormedY()
z1# = TFormedZ()


;cube = CreateCube()
If(x0<x1) Then xa# = x0 Else xa# = x1
If(y0<y1) Then ya# = y0 Else ya# = y1
If(z0<xz) Then za# = z0 Else za# = z1

xstep# = Abs(x1-x0) / 6.0
ystep# = Abs(y1-y0) / 6.0
zstep# = Abs(z1-z0) / 6.0

cx# = (offsetx)*(xw)+(x0+x1)/2.0
cy# = (offsety)*(yw)+(y0+y1)/2.0
cz# = (offsetz)*(zw)+(z0+z1)/2.0


;flames
For nn = 1 To n+1
If(hasflames)
For i=-1 To 1
x# = cx+xstep*i*scale*0.5
For j=-1 To 1
y# = cy+ystep*j*scale*0.5
For k=-1 To 1
If(i=0 And j=0 And k=0) Then
Else

z#=cz+zstep*k*scale*0.5
e.explosion = New explosion
e yp = "flames"
eoriginalent = ent
eent = CreateCube()
RotateMesh eent,45,45,45
aaa = CreateCube()
AddMesh(aaa,eent)
FreeEntity aaa
EntityTexture eent,explosiontexture
EntityFX eent,1+16+32

evx = scale*Rnd(-1.5,1.5)
evy = scale*Rnd(-1.5,1.5)
evz = scale*Rnd(-1.5,1.5)
aad# = Rnd(0.975,1.01)
esx = 7.0*scale*aad
esy = 7.0*scale*aad
esz = 7.0*scale*aad
PositionEntity eent,x+posx,y+posy,z+posz

e = 255
eg = 110
e = 64
ea = 32

edp=Rnd(-4,4)
edy=Rnd(-4,4)
edr=Rnd(-4,4)
e ime = starttime
e imestep = 0.005
EntityBlend eent,3
EndIf
Next
Next
Next
EndIf
;smoke
If(hassmoke)
bstep = Abs(xstep)
If(Abs(ystep)>bstep) Then bstep = Abs(ystep)
If(Abs(zstep)>bstep) Then bstep = Abs(zstep)
For i=-1 To 1
x# = cx+xstep*i*scale
For j=-1 To 1
y# = cy+ystep*j*scale
For k=-1 To 1
z#=cz+zstep*k*scale
e.explosion = New explosion
e yp = "smoke"
eoriginalent = ent
eent = CreateCube()
EntityTexture eent,explosiontexture
EntityFX eent,16+1+32

sc#=Rand(0.7,1.2)
esx = 5.0*scale*sc
esy = 5.0*scale*sc
esz = 5.0*scale*sc

rad# = scale * Rnd(0,2)
angle1# = Rnd(360)
angle2#= Rnd(360)

evx= 2.5*rad*Cos(angle1)
evy= 2.5*rad*Sin(angle1)
evz= 2.5*rad*Cos(angle2)

rad = rad*bstep*0.5
PositionEntity eent,posx+cx+rad*Cos(angle1),posy+cy+rad*Sin(angle1),posz+cz+rad*Cos(angle2)

e ime = starttime
e imestep = 0.0075
grey=Rand(-8,128)
e = 48+grey
eg = 48+grey
e = 48+grey

ea = 32

edp=Rnd(-2,2)
edy=Rnd(-2,2)
edr=Rnd(-2,2)

Next
Next
Next

EndIf
Next
;sparks
If(hassparks)
For i=-1 To 1
x# = cx+xstep*i*Rnd(12,20)*scale
For j=-1 To 1
y# = cy+ystep*j*Rnd(12,20)*scale
For k=-1 To 1
If(i=0 And j=0 And k=0) Then
Else
z#=cz+zstep*k*Rnd(12,20)*scale
e.explosion = New explosion
e yp = "sparks"
eoriginalent = ent
eent = CreateCube()
EntityTexture eent,explosiontexture
EntityFX eent,1+16+32
EntityBlend eent,3
rad# = scale * Rnd(0,2)
angle1# = Rnd(360)
angle2#= Rnd(360)

evx= 1.05*rad*Cos(angle1)
evy= 1.05*rad*Sin(angle1)
evz= 1.05*rad*Cos(angle2)
aad# = Rnd(0.95,1.05)
esx = scale*1.4*aad
esy = scale*1.4*aad
esz = scale*1.4*aad
PositionEntity eent,x+posx,y+posy,z+posz
e ime = starttime+0.9975
e imestep = 0.000125
e = 255
eg = 128
e = 32
ea = 255

edp=Rnd(-12,12)
edy=Rnd(-1.5,1.5)
edr=Rnd(-1,1)
If(Rand(0,100)<70) Then
especial = special
If(especial>0) Then
speciallist=speciallist+" " +especial
EndIf
special = 0
EndIf
EndIf
Next
Next
Next
EndIf

End Function

Function init()
Graphics3D 512,512,0,6
camera=CreateCamera()
CameraClsColor camera,0,0,0
AmbientLight(255,255,255)
MoveEntity camera,0,0,00
SetBuffer BackBuffer()
End Function


Comments :


BlitzSupport(Posted 1+ years ago)

 Awesome!


Rick Nasher(Posted 1+ years ago)

 Very impressive explosions without any media! Didn't even know was possible like this. Amazing piece of code and not even that large or anything.


xlsior(Posted 1+ years ago)

 Very, very nice -- I don't suppose there's a way to save them with transparent backgrounds instead of black?


Matty(Posted 1+ years ago)

 Hi xlsior - most likely, but not using the standard 2d image saving routines that blitz comes with.  There is a tga code archives entry which could be applied easily enough.In my own project I didn't need transparency since I was going to be using additive blending .... but yep that would be a good idea.


*(Posted 1+ years ago)

 Might have a go at converting to max or monkey mainly as this would be a brilliant addition for all of us blitzers to use :)Might even make an appearance in Star Rogue :)


_PJ_(Posted 1+ years ago)

 This is very nice indeed, thanks Matty!Maybe setting the Graphics command to a resolution which is more native to the user's screen/gpu may allow for better framerate if they have problems.The viewport itself may be fixed to only render the 512x512 portion so the imagess are still valid, but some GPU perform at their best when at a "comfortable" resolution and/or fullscreen mode.___<div class="quote"> I don't suppose there's a way to save them with transparent backgrounds instead of black? </div>Not by default, you would either need to write a bmp file byte-by-byte* with the alpha flag set or use (as suggested) tga export function from code archives.* Something like:i) get readpixelfast valueii) set alpha flag on valueiii) poke value to bankiv) writebytes of bank to file as bmpThis will be slower than the savebuffer commands of course.


Matty(Posted 1+ years ago)

 Here are some sample explosions<a href="http://mattiesgames.com/articles/mygamepics.html" target="_blank">Link - see bottom of page - long page</a>


Rick Nasher(Posted 1+ years ago)

 That game is looking just as awesome as the explosions!


Matty(Posted 1+ years ago)

 Edit - here is a version which outputs an image with transparency as a tga image (easy file format to write)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Only two parameters you need!
Global  saverenders = True ;change this accordingly NOTE RENDERING IS SLOW!
Global qty = 0 ;number of explosions to render as animated images change this accordingly


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Matt Lloyd Explosion Generator (as used in my Space Battle Game for Android Devices)
;
;4-April-2015 ML
; Note/Caveat - this code is not pretty - I fully admit that.  It is not intended to be.  It does its job and that's it.
;
; This program will generate 2d renders of explosions using blitz3d at a resolution of 512x512.
;
;   No user interaction is required once the program starts......fire and forget.......
;
; If you wish to save these renders then you need to change the value of the const at the top of the program (set 'saverenders' to true)
;
; Renders are saved as 4096x4096 images (8x8 frames of 512x512 images) into a sub folder called 'erenders' with file naming convention
; 'explosion_currentdatetime_indexnumber.tga' (new ! with alpha transparency)
;
; As far as I am aware 4096x4096 is the largest image that blitz can manage without internally resizing it - so why not go for the maximum resolution!
;
; Note 2 - It takes a few sequences to warm up before it attempts to render as it tries to make sure that
; as much of the texture atlas is consumed.
;
;
;
;
;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Technically no need to touch anything beyond this point!  All trespassers will be shot and so forth!
HidePointer
Global camera,ent,pivot,speciallist$
Global explosiontexture
Global cdate$ = Replace(CurrentDate$()," ","_")+"_"+Replace(CurrentTime$(),":","_")
Global rendertex

SeedRnd MilliSecs()
main()
End
Function main()

;miscellaneous vars - you don't need to touch these...
Local box, render, e.explosion, time, time2, time3, frame, f0,f1,f2
Local q, xx#,yy#,zz#,aab,aac,aae,x11,y11

init()
qty2$ = Input("Qty To Save (erenders/)? (enter -1 to view only)")
qty = Int(qty2$)
If(qty<0) Then qty = -1
If(qty>999) Then qty = 999




box = CreateCube()
MoveEntity box,0,0,80
EntityAlpha box,0

render = CreateImage(4096,4096); 512*8, 512*8
rendertex = CreateTexture(4096,4096,1+2)
clearrendertex()
e.explosion = First explosion
time = MilliSecs()
time2 = 10000
time3 = 10000
Repeat
time11 = MilliSecs()
Cls
frame = frame + 1

If(MilliSecs()>time And e=Null) Then
f0 = f1
f1 = frame
f2 = f2+1
time2 = f1 + (290/17)
time3 = f1 + (130/17)
For q = 0 To 2
If(q>0) Then
xx# = Rnd(-10,10)
yy# = Rnd(-10,10)
zz# = Rnd(-8,2)
EndIf
aab = 1 - Sgn(Rand(0,20))
aac = 1 - Sgn(Rand(0,2))
aae = Sgn(Rand(0,20))

createexplosion(box,1,aae,aac,aab,Rnd(0.65,1.35),1,0,0,0,0,0,xx,yy,10+zz);
If(q=2)
createexplosion(box,0,0,aac,1,Rnd(0.7,1.05),1,0,0,0,0,0,xx,yy,10+zz);
EndIf
Next
EndIf

If(frame>time3) Then
For q = 0 To 2
If(q<>-1) Then
xx# = Rnd(-20,20)
yy# = Rnd(-20,20)
zz# = Rnd(-1,1)
EndIf
aac = 1 - Sgn(Rand(0,10))
createexplosion(box,3,1,aac,0,Rnd(0.8,1.35),   1,0,0,0,0,0,xx,yy,16+zz);
If(q=0) Then
createexplosion(box,0,0,0,1,Rnd(0.6,1.0),1,0,0,0,0,0,xx,yy,16+zz);
EndIf
Next
time3 = frame + 100000
EndIf

If(frame>time2) Then
For q = 0 To 1
xx# = Rnd(-20,20)
yy# = Rnd(-20,20)
If(q=2) Then
xx=xx*1.5
yy=yy*1.5
EndIf
zz# = Rnd(-2,4)
aab = 1- Sgn(Rand(0,1))
createexplosion(box,1,aab,1-aab,0,Rnd(0.5,0.85),   1,0,0,0,0,0,xx,yy,8+zz);
If(q=0) Then
aab = 1- Sgn(Rand(0,1))
createexplosion(box,0,0,1-aab,aab,Rnd(0.3,0.5),1,0,0,0,0,0,xx,yy,9+zz);
EndIf
Next
time2 = frame + 10000
EndIf

updateexplosion()
CameraClsMode camera,True,True
RenderWorld
If(saverenders And qty>0) Then
x11 = (frame - f1) Mod 8
y11 = ((frame - f1) - x11) / 8
If(i11>1) Then savetorendertex(x11,y11)

;CopyRect 0,0,512,512,x11*512,y11*512,BackBuffer(),ImageBuffer(render)
e.explosion = First explosion
If(e.explosion = Null And (f1-f0)>55 And (f1-f0)<64) Then
i11=i11+1
If(i11>2) Then
xr = 3
yr = 3
;CopyRect xr*512,yr*512,512,512,0,0,ImageBuffer(render),BackBuffer()
Color 0,0,0
Text 0,0,(f1 - f0)+" Sequence Length"
Text 256,30,"......Please wait Saving LARGE image......",1,1
Flip
If(FileType("erenders")=2) Then
;SaveImage render,"erendersexplosion_"+cdate$+"_"+i11+".bmp"
saverendertex("erendersexplosion_"+cdate$+"_"+i11+".tga")
Else
If(FileType("erenders")=0) Then
CreateDir("erenders")
If(FileType("erenders")=2) Then
;SaveImage render,"erendersexplosion_"+cdate$+"_"+i11+".bmp"
saverendertex("erendersexplosion_"+cdate$+"_"+i11+".tga")
EndIf
EndIf
EndIf
qty = qty - 1
Color 0,0,0
SetBuffer ImageBuffer(render)
Rect 0,0,ImageWidth(render),ImageHeight(render),1
SetBuffer BackBuffer()
EndIf
EndIf



Else
e.explosion = First explosion
EndIf
Color 255,255,255
Text 0,0,f1 - f0
If saverenders Then Text 0,15,qty+" renders to go!"
Text 400,0,"ESC to Exit"
Flip
time22 = MilliSecs()-time11
If(time22<17) Then
Delay 17 - time22
EndIf
Until KeyHit(1) Or qty=0
End Function

Type explosion

Field originalent
Field ent
Field typ$
Field vx#,vy#,vz#
Field sx#,sy#,sz#
Field r#,g#,b#,a#
Field dp#,dy#,dr#
Field time#
Field timestep#
Field trailcreated
Field special

End Type

Function updateexplosion()

defaulttimestep#=0.025
For e.explosion = Each explosion
timestep# = e imestep
TranslateEntity eent,evx*(timestep/defaulttimestep),evy*(timestep/defaulttimestep),evz*(timestep/defaulttimestep),True
ScaleEntity eent,esx,esy,esz
EntityColor eent,e,eg,e
EntityAlpha eent,Float(ea)/255.0
TurnEntity eent,edp,edy,edr
e ime=e ime+timestep
updatefunction(e)
If(especial=1 And e ime >= 0 And e ime<e imestep*5) Then
createexplosion(ent,2,True,False,False,4,1,0,0,0,0,0)
EndIf
If(especial=1 And e ime >= e imestep*5) Then
EntityAlpha ent,0
EndIf
If(especial>0 And e ime>e imestep*Rand(5,10)) Then
createexplosion(eent,0,True,True,False,3,1,0,0,0,0,especial-1)
especial = 0
EndIf
If(e ime>=1.0 Or ea <= 0 Or esx<=0.001 Or esy<0.001 Or esz<0.001 Or (e<=0 And eg<=0 And e<=0))
FreeEntity eent
Delete e
EndIf
Next

End Function

Function updatefunction(e.explosion)

If(e yp="flames")

If(e ime<0.05) Then
esx = esx * (1.0 + ((e ime)/0.05)*0.0125)
esy = esy * (1.0 + ((e ime)/0.05)*0.0125)
esz = esz * (1.0 + ((e ime)/0.05)*0.0125)
ea = ea * (1.0-e imestep*15)
MoveEntity eent,evx,evy,evz
Else
If(e ime<0.5) Then
esx = esx * (1.05-e imestep*55)
esy = esy * (1.05-e imestep*55)
esz = esz * (1.05-e imestep*55)
ea = ea * (1.0-e imestep*5)
Else
esx = esx * (1.05-e imestep*5)
esy = esy * (1.05-e imestep*5)
esz = esz * (1.05-e imestep*5)
ea = ea * (1.0-e imestep*25)
EndIf
EndIf
EndIf


If(e yp="smoke") Then
If(e ime<0.15) Then
esx = esx *(1.0+(e ime/0.15)*0.1)
esy = esy *(1.0+(e ime/0.15)*0.1)
esz = esz *(1.0+(e ime/0.15)*0.1)
ea = ea - 0.5
Else
If(e ime>0.5)
esx = esx *(1.0-((e ime-0.5)/0.5)*0.025)
esy = esy *(1.0-((e ime-0.5)/0.5)*0.025)
esz = esz *(1.0-((e ime-0.5)/0.5)*0.025)
EndIf
ea=ea-1.25
EndIf

If(e ime<0.3) Then
evx = evx * (1.0 - (e ime/0.3)^2)
evy = evy * (1.0 - (e ime/0.3)^2)
evz = evz * (1.0 - (e ime/0.3)^2)
EndIf

EndIf


If(e yp="sparks")

ea = 255.0 - (Float(e railcreated) /50.0) *128.0

esx = esx * (1.0-e imestep)*0.925
esx = esx * (1.0-e imestep)*0.925
esx = esx * (1.0-e imestep)*0.925

MoveEntity eent,evx,evy,evz


If(e railcreated<50 )

;create a spark at our location with an increased time.....
f.explosion = New explosion
f yp = "smoke"
foriginalent = eent
fent = CreateCube()
EntityTexture fent,explosiontexture
EntityFX fent,1+16+32
fvx = evx*0.0125
fvy = evy*0.0125
fvz = evz*0.0125
fsx = esx*1.5
fsy = esy*1.5
fsz = esz*1.5
PositionEntity fent,EntityX(eent,True),EntityY(eent,True),EntityZ(eent,True)
f ime = 0
f imestep = 0.075
f = 128
fg = 128
f = 128
fa = 40
fdp=Rnd(-10,10)
fdy=Rnd(-10,10)
fdr=Rnd(-10,10)
e railcreated=e railcreated+1
EndIf
EndIf

If(esx<=0) Then esx=0.001
If(esy<=0) Then esy=0.001
If(esz<=0) Then esz=0.001
If(ea>255) Then ea=255
If(ea<0) Then ea=0
If(ea>255) Then ea=255
If(e>255) Then e=255
If(eg>255) Then eg=255
If(e>255) Then e=255
If(e<0) Then e=0
If(eg<0) Then eg=0
If(e<0) Then e=0


End Function


Function createexplosion(ent,n,hasflames=True,hassparks=True,hassmoke=True,scale#=1.0,size#=1.0,offsetx#=0,offsety#=0,offsetz#=0,starttime#=0.0,special=0,posx#=0,posy#=0,posz#=0)

If(explosiontexture=0) Then
texsize = 256
explosiontexture = CreateTexture(texsize,texsize,1+4+2)
SetBuffer TextureBuffer(explosiontexture)

pxx# = Float(texsize/2)-1
pyy# = Float(texsize/2)-1

rr# = 0.1

For px = 0 To texsize-1
For py = 0 To texsize-1
WritePixel px,py,0
Next
Next

aa = ((texsize/2)-4)*8
For jj = 0 To aa
For angle = 0 To 3600
myx# = pxx + rr*Cos(Float(angle)/10.0)
myy# = pyy + rr*Sin(Float(angle)/10.0)
col = Rand(250,255)
alpha = (col - (rr*Float(0.16))^2)
If(alpha<0) Then alpha = 0
If(alpha>255) Then alpha = 255
col = alpha
WritePixel Int(myx),Int(myy),alpha Shl 24 Or col Shl 16 Or col Shl 8 Or col
Next
rr=rr+0.1
Next
SetBuffer BackBuffer()
EndIf


;get bounding box....
xw# = MeshWidth(ent)*size
yw# = MeshHeight(ent)*size
zw# = MeshDepth(ent)*size

TFormPoint -xw/2,-yw/2,-zw/2,ent,0
x0# = TFormedX()
y0# = TFormedY()
z0# = TFormedZ()

TFormPoint +xw/2,+yw/2,+zw/2,ent,0
x1# = TFormedX()
y1# = TFormedY()
z1# = TFormedZ()


;cube = CreateCube()
If(x0<x1) Then xa# = x0 Else xa# = x1
If(y0<y1) Then ya# = y0 Else ya# = y1
If(z0<xz) Then za# = z0 Else za# = z1

xstep# = Abs(x1-x0) / 6.0
ystep# = Abs(y1-y0) / 6.0
zstep# = Abs(z1-z0) / 6.0

cx# = (offsetx)*(xw)+(x0+x1)/2.0
cy# = (offsety)*(yw)+(y0+y1)/2.0
cz# = (offsetz)*(zw)+(z0+z1)/2.0


;flames
For nn = 1 To n+1
If(hasflames)
For i=-1 To 1
x# = cx+xstep*i*scale*0.5
For j=-1 To 1
y# = cy+ystep*j*scale*0.5
For k=-1 To 1
If(i=0 And j=0 And k=0) Then
Else

z#=cz+zstep*k*scale*0.5
e.explosion = New explosion
e yp = "flames"
eoriginalent = ent
eent = CreateCube()
RotateMesh eent,45,45,45
aaa = CreateCube()
AddMesh(aaa,eent)
FreeEntity aaa
EntityTexture eent,explosiontexture
EntityFX eent,1+16+32

evx = scale*Rnd(-1.5,1.5)
evy = scale*Rnd(-1.5,1.5)
evz = scale*Rnd(-1.5,1.5)
aad# = Rnd(0.975,1.01)
esx = 7.0*scale*aad
esy = 7.0*scale*aad
esz = 7.0*scale*aad
PositionEntity eent,x+posx,y+posy,z+posz

e = 255
eg = 110
e = 64
ea = 32

edp=Rnd(-4,4)
edy=Rnd(-4,4)
edr=Rnd(-4,4)
e ime = starttime
e imestep = 0.005
EntityBlend eent,3
EndIf
Next
Next
Next
EndIf
;smoke
If(hassmoke)
bstep = Abs(xstep)
If(Abs(ystep)>bstep) Then bstep = Abs(ystep)
If(Abs(zstep)>bstep) Then bstep = Abs(zstep)
For i=-1 To 1
x# = cx+xstep*i*scale
For j=-1 To 1
y# = cy+ystep*j*scale
For k=-1 To 1
z#=cz+zstep*k*scale
e.explosion = New explosion
e yp = "smoke"
eoriginalent = ent
eent = CreateCube()
EntityTexture eent,explosiontexture
EntityFX eent,16+1+32

sc#=Rand(0.7,1.2)
esx = 5.0*scale*sc
esy = 5.0*scale*sc
esz = 5.0*scale*sc

rad# = scale * Rnd(0,2)
angle1# = Rnd(360)
angle2#= Rnd(360)

evx= 2.5*rad*Cos(angle1)
evy= 2.5*rad*Sin(angle1)
evz= 2.5*rad*Cos(angle2)

rad = rad*bstep*0.5
PositionEntity eent,posx+cx+rad*Cos(angle1),posy+cy+rad*Sin(angle1),posz+cz+rad*Cos(angle2)

e ime = starttime
e imestep = 0.0075
grey=Rand(-8,128)
e = 48+grey
eg = 48+grey
e = 48+grey

ea = 32

edp=Rnd(-2,2)
edy=Rnd(-2,2)
edr=Rnd(-2,2)

Next
Next
Next

EndIf
Next
;sparks
If(hassparks)
For i=-1 To 1
x# = cx+xstep*i*Rnd(12,20)*scale
For j=-1 To 1
y# = cy+ystep*j*Rnd(12,20)*scale
For k=-1 To 1
If(i=0 And j=0 And k=0) Then
Else
z#=cz+zstep*k*Rnd(12,20)*scale
e.explosion = New explosion
e yp = "sparks"
eoriginalent = ent
eent = CreateCube()
EntityTexture eent,explosiontexture
EntityFX eent,1+16+32
EntityBlend eent,3
rad# = scale * Rnd(0,2)
angle1# = Rnd(360)
angle2#= Rnd(360)

evx= 1.05*rad*Cos(angle1)
evy= 1.05*rad*Sin(angle1)
evz= 1.05*rad*Cos(angle2)
aad# = Rnd(0.95,1.05)
esx = scale*1.4*aad
esy = scale*1.4*aad
esz = scale*1.4*aad
PositionEntity eent,x+posx,y+posy,z+posz
e ime = starttime+0.9975
e imestep = 0.000125
e = 255
eg = 128
e = 32
ea = 255

edp=Rnd(-12,12)
edy=Rnd(-1.5,1.5)
edr=Rnd(-1,1)
If(Rand(0,100)<70) Then
especial = special
If(especial>0) Then
speciallist=speciallist+" " +especial
EndIf
special = 0
EndIf
EndIf
Next
Next
Next
EndIf

End Function

Function init()
Graphics3D 512,512,0,6
camera=CreateCamera()
CameraClsColor camera,0,0,0
AmbientLight(255,255,255)
MoveEntity camera,0,0,00
SetBuffer BackBuffer()
End Function
Function clearrendertex()
SetBuffer TextureBuffer(rendertex)
LockBuffer TextureBuffer(rendertex)
For x = 0 To 4095
For y = 0 To 4095
WritePixelFast x,y,0
Next
Next
UnlockBuffer TextureBuffer(rendertex)
SetBuffer BackBuffer()
End Function
Function savetorendertex(x11,y11)
;save as a texture.......with alpha...by rendering over black and white respectively......
CameraClsColor camera,0,0,0
RenderWorld
CopyRect 0,0,512,512,x11*512,y11*512,BackBuffer(),TextureBuffer(rendertex)
CameraClsColor camera,255,255,255
RenderWorld
CameraClsColor camera,0,0,0
LockBuffer BackBuffer()
LockBuffer TextureBuffer(rendertex)
For x=0 To 511
For y = 0 To 511
ix11 = x11*512 + x
iy11 = y11*512 + y
rgbblack = ReadPixelFast(ix11,iy11,TextureBuffer(rendertex))
rgbwhite = ReadPixelFast(x,y,BackBuffer())
;all the pixels that are black 0,0,0 and white 255,255,255 are transparent....
rb = (rgbblack Shr 16) And 255
gb = (rgbblack Shr 8) And 255
bb = rgbblack And 255

rw = (rgbwhite Shr 16) And 255
gw = (rgbwhite Shr 8) And 255
bw = rgbwhite And 255

alpha = 255
If(rb=0 And gb=0 And bb=0 And rw=255 And gw=255 And bw=255) Then
;completely transparent....
alpha = 0
EndIf
sb = (rb + gb + bb)/3
sw = (rw + gw + bw)/3
awb = 255 - (sw - sb)
If(awb<0) Then awb = 0
If(awb>255) Then awb = 255
alpha = awb

WritePixelFast(ix11,iy11,rb Shl 16 Or gb Shl 8 Or bb Or alpha Shl 24,TextureBuffer(rendertex))
Next
Next
UnlockBuffer TextureBuffer(rendertex)
UnlockBuffer BackBuffer()
End Function
Function saverendertex(filename$)
outbank = CreateBank(18+4096*4096*4)
PokeByte outbank,0,0
PokeByte outbank,1,0
PokeByte outbank,2,2
For i = 1 To 9
PokeByte outbank,2+i,0
Next
PokeShort outbank,12,4096
PokeShort outbank,14,4096
PokeByte outbank,16,32
PokeByte outbank,17,0
offset = 18
LockBuffer TextureBuffer(rendertex)
For iy = 4095 To 0 Step -1
For ix = 0 To 4095
argb = ReadPixelFast(ix,iy,TextureBuffer(rendertex))
PokeByte outbank,offset,argb And 255
PokeByte outbank,offset+1,(argb Shr 8) And 255
PokeByte outbank,offset+2,(argb Shr 16) And 255
PokeByte outbank,offset+3,(argb Shr 24) And 255
offset = offset + 4
Next
Next
UnlockBuffer TextureBuffer(rendertex)

outfile = WriteFile(filename)
WriteBytes outbank,outfile,0,BankSize(outbank)
CloseFile outfile
FreeBank outbank
End Function



xlsior(Posted 1+ years ago)

 Nice of you to revisit this!When I run it, it shows a slow explosion being rendered with a white background, it says to wait while saving a large image, but the resulting image loads in Photoshop with a black background, not transparent... Do I need to tweak anything else, or is this Photoshop misunderstanding the transparancy?


Matty(Posted 1+ years ago)

 Id say it is photoshop.  It opens paint.net with correct alpha.


Matty(Posted 1+ years ago)

 Additional : its slower because it has to render each frame twice. Once with a black and once with a white background to calculate the alpha channel pixel by pixel.


xlsior(Posted 1+ years ago)

 Yup, you're right -- the alpha does show properly in paint.netAgain, fantastic job!


Bobysait(Posted 1+ years ago)

 It's quite good !But ... Save yourself some headackes and use the tabulation key :)There is no way programming can be fun while debugging such unindented code.ps : just a tip for the alpha without the tga extension :You could use 2 bitmaps for output- one with the color- one with the alpha on the red channel (or blue channel, it should be faster as there is no shift to perform)Then it is easy to convert on any software or on blitzmax (where you can save in png with alpha and compression using SavePixmapPNG) [/i]