This is a refined version of Dr Tank's
exploding sphere using vertexdata. I have converted all the arrays into memblocks and put the whole thing into a set of functions so you can now make any number of objects explode all over the place
.
Version 3 (11/12/10)
- This version has 3-axis floors, which should have been added with 3-axis gravity
- This version allows you to specify where the center of the explosion will be at explode-time. Because of this, some of the setup functions needed to be moved to BOOM_ExplodeObject, so expect that to be a little slower.
- BOOM_SetupObject now preserves the object's position and rotation
BOOM_SetupObject(ObjectNo,FloorX,FloorY,FloorZ) gets the object ready to blow up. The Floors are the global positions where the fragments will stop moving.
BOOM_Update() should be called each loop. It moves all the pieces.
BOOM_ExplodeObject(ObjectNo,Violence,vx,vy,vz,ox,oy,oz) explodes the specified object. Violence is how forceful the explosion is. The vx-z values are initial velocities on each axis. The o values specify the center of the explosion relative to the center of the object.
BOOM_UnsetObject(ObjectNo) removes the object from the explosion system but does not delete it or reset its vertexdata.
`Make any object explode
`Demo V3
`Now with:
`- 3D Floors
`- Change center of explosion
`by Dr Tank and BMacZero
sync on : sync rate 60
autocam off
set display mode desktop width(),desktop height(),32
`======= Explosions Setup =======
type BOOM_ObjectType
ObjectNo as integer
FaceCount as integer
VertCount as integer
Mem1 as integer
Mem2 as integer
Mem3 as integer
Mem4 as integer
Mem5 as integer
ExplodeTime as integer
Violence as float
FloorX as float
FloorY as float
FloorZ as float
endtype
DIM BOOM_Objects(0) as BOOM_ObjectType
DIM BOOM_AngSpeeds#(0)
global BOOM_gravityx# `Acceleration due to gravity
global BOOM_gravityy#
global BOOM_gravityz#
BOOM_gravityx#=0
BOOM_gravityy#=-10
BOOM_gravityz#=0
`================================
`Demo objects
make object sphere 1,50,10,10
make object cylinder 2,50
BOOM_SetupObject(1,-1000,-50,-1000)
BOOM_SetupObject(2,-1000,-1000,-1000)
position object 2,-50,0,0
`Floor
make object plane 3,500,500
color object 3,rgb(255,255,255)
position object 3,0,-50,0
xrotate object 3,-90
position camera 100,20,300
point camera 0,-40,0
do
timestart = timer()
BOOM_Update()
uptime = timer()-timestart
if mouseclick()=1 then timestart = timer() : BOOM_ExplodeObject(1,700,3,0,0,0,0,0) : if exptime = 0 then exptime = timer()-timestart
if mouseclick()=2 then timestart = timer() : BOOM_ExplodeObject(2,700,0,0,0,0,-50,0) : if exptime = 0 then exptime = timer()-timestart
text 10,10,str$(screen fps())
text 10,30,"Update time: "+str$(uptime)
text 10,40,"Explode time: "+str$(exptime)
sync
loop
`======= Explosions Functions =======
`Add an object to the explosion system
`You can the detonate at any time with BOOM_ExplodeObject
function BOOM_SetupObject(ObjectNo as integer,FloorX as float,FloorY as float,FloorZ as float)
array insert at bottom BOOM_Objects(0)
temp=array count(BOOM_Objects(0))
BOOM_Objects(temp).ObjectNo=ObjectNo
BOOM_Objects(temp).FloorX=FloorX
BOOM_Objects(temp).FloorY=FloorY
BOOM_Objects(temp).FloorZ=FloorZ
BOOM_Objects(temp).Mem1=FreeMemblock()
temp2=FreeMesh()
`CHANGE OBJECT TO NO SHARED VERTICES FORMAT
tx#=object position x(ObjectNo)
ty#=object position y(ObjectNo)
tz#=object position z(ObjectNo)
rx#=object angle x(ObjectNo)
ry#=object angle y(ObjectNo)
rz#=object angle z(ObjectNo)
make mesh from object temp2,ObjectNo
delete object ObjectNo
make memblock from mesh BOOM_Objects(temp).Mem1,temp2
make mesh from memblock temp2,BOOM_Objects(temp).Mem1
delete memblock BOOM_Objects(temp).Mem1
make object ObjectNo,temp2,1
delete mesh temp2
`Put the object back where it was
position object ObjectNo,tx#,ty#,tz#
rotate object ObjectNo,rx#,ry#,rz#
set object cull ObjectNo,0 `so you can see backfaces
LOCK VERTEXDATA FOR LIMB ObjectNo,0,1
BOOM_Objects(temp).VertCount=GET VERTEXDATA VERTEX COUNT()
BOOM_Objects(temp).FaceCount=BOOM_Objects(temp).VertCount/3
UNLOCK VERTEXDATA
`BOOM_AngSpeeds is just constants, same for any object
`All we do here is add more if you set up an object with more verts that we can currently handle
temp2=array count(BOOM_AngSpeeds#(0))
if BOOM_Objects(temp).FaceCount>temp2
dim BOOM_AngSpeeds#(BOOM_Objects(temp).FaceCount)
for c=temp2+1 to BOOM_Objects(temp).FaceCount
BOOM_AngSpeeds#(c)=0.5*(rnd(11)-5.5)
next c
endif
make memblock BOOM_Objects(temp).Mem1,BOOM_Objects(temp).FaceCount*3*4
BOOM_Objects(temp).Mem2=FreeMemblock()
make memblock BOOM_Objects(temp).Mem2,BOOM_Objects(temp).FaceCount*4
BOOM_Objects(temp).Mem3=FreeMemblock()
make memblock BOOM_Objects(temp).Mem3,(BOOM_Objects(temp).VertCount+1)*4*9
BOOM_Objects(temp).Mem4=FreeMemblock()
make memblock BOOM_Objects(temp).Mem4,3*(BOOM_Objects(temp).FaceCount+1)*4
BOOM_Objects(temp).Mem5=FreeMemblock()
make memblock BOOM_Objects(temp).Mem5,(BOOM_Objects(temp).VertCount+1)*4*9
endfunction
`Causes an object that has been added to the explosion system to detonate
`Violence is the force of the explosion
`vx, vy, and vz represent the general direction of the explosion (useful for simulating,
` for example, a glass being shot)
`ox, oy, and oz represent the "epicenter" of the explosion relative to the object's center
` (all the pieces will explode away from this point)
function BOOM_ExplodeObject(objectno,Violence#,vx as float,vy as float, vz as float, ox as float, oy as float, oz as float)
for c=1 to array count(BOOM_Objects(0))
if BOOM_Objects(c).objectno=objectno then BOOMID=c
next c
`Offset to the epicenter
vertsoff(objectno,-ox,-oy,-oz)
position object objectno,object position x(objectno)+ox,object position y(objectno)+oy,object position z(objectno)+oz
`More setup tasks that were moved here to enable the center offset
local dim temp1#(3,BOOM_Objects(BOOMID).FaceCount)
local dim temp2#(3,BOOM_Objects(BOOMID).VertCount)
lock vertexdata for limb objectno,0
FOR N=0 TO BOOM_Objects(BOOMID).VertCount-1
temp2#(1,N)=GET VERTEXDATA POSITION X(N)
temp2#(2,N)=GET VERTEXDATA POSITION Y(N)
temp2#(3,N)=GET VERTEXDATA POSITION Z(N)
NEXT N
unlock vertexdata
`Calculate exit velocities
for f=0 to BOOM_Objects(BOOMID).FaceCount-1
n=f*3
for c=1 to 3
temp#=(temp2#(c,n+0)+temp2#(c,n+1)+temp2#(c,n+2))/3.0
write memblock float BOOM_Objects(BOOMID).Mem1,f*12+(c-1)*4,temp#
temp2#(c,n+0)=temp2#(c,n+0)-temp#
temp2#(c,n+1)=temp2#(c,n+1)-temp#
temp2#(c,n+2)=temp2#(c,n+2)-temp#
next c
next f
`Set up fragment rotation
for f=0 to BOOM_Objects(BOOMID).FaceCount-1
mag#=0.0
for c= 1 to 3
temp1#(c,f)=rnd(5)-2.5
inc mag#,temp1#(c,f)*temp1#(c,f)
next c
mag#=sqrt(mag#)
`normalise..
for c=1 to 3
temp1#(c,f)=temp1#(c,f)/mag#
next c
`get components parallel to, perpendicular to, and perpendicular to both..
s=3*f-1
for a=1 to 3
v=s+a
dotp#=temp2#(1,v)*temp1#(1,f)+temp2#(2,v)*temp1#(2,f)+temp2#(3,v)*temp1#(3,f)
for x=1 to 3
temp#=dotp#*temp1#(x,f)
write memblock float BOOM_Objects(BOOMID).Mem5,(v*9+x)*4,temp#
write memblock float BOOM_Objects(BOOMID).Mem5,(v*9+x+3)*4,temp2#(x,v)-temp#
next x
write memblock float BOOM_Objects(BOOMID).Mem5,(v*9+7)*4,memblock float(BOOM_Objects(BOOMID).Mem5,(v*9+5)*4)*temp1#(3,f)-memblock float(BOOM_Objects(BOOMID).Mem5,(v*9+6)*4)*temp1#(2,f)
write memblock float BOOM_Objects(BOOMID).Mem5,(v*9+8)*4,memblock float(BOOM_Objects(BOOMID).Mem5,(v*9+6)*4)*temp1#(1,f)-memblock float(BOOM_Objects(BOOMID).Mem5,(v*9+4)*4)*temp1#(3,f)
write memblock float BOOM_Objects(BOOMID).Mem5,(v*9+9)*4,memblock float(BOOM_Objects(BOOMID).Mem5,(v*9+4)*4)*temp1#(2,f)-memblock float(BOOM_Objects(BOOMID).Mem5,(v*9+5)*4)*temp1#(1,f)
next a
next f
UNDIM temp1#(0,0)
UNDIM temp2#(0,0)
if BOOMID>0
if BOOM_Objects(BOOMID).ExplodeTime=0
BOOM_Objects(BOOMID).ExplodeTime=timer()
BOOM_Objects(BOOMID).Violence=Violence#
for f=0 to BOOM_Objects(BOOMID).FaceCount-1
`Randomizes exit velocities
c#=sqrt(rnd(256))
for c=1 to 3
if c=1 then off#=vx
if c=2 then off#=vy
if c=3 then off#=vz
write memblock float BOOM_Objects(BOOMID).Mem4,(f*3+c)*4,(Violence#/100000)*c#*memblock float(BOOM_Objects(BOOMID).Mem1,f*12+(c-1)*4)+off#
next c
next f
endif
exitfunction 1
endif
endfunction 0
`Call this every loop - updates exploded object's vertices
function BOOM_Update()
for d=1 to array count(BOOM_Objects(0))
if BOOM_Objects(d).ExplodeTime>0
bad=1 `Used to stop animation when all pieces hit the floor
LOCK VERTEXDATA FOR LIMB BOOM_Objects(d).ObjectNo,0,1
for f=0 to BOOM_Objects(d).FaceCount-1
write memblock float BOOM_Objects(d).Mem2,f*4,wrapvalue(memblock float(BOOM_Objects(d).Mem2,f*4)+BOOM_AngSpeeds#(f)*BOOM_Objects(d).Violence/60)
`Move Faces, c is each axis
for c=1 to 3
if c=1 then temp2#=BOOM_gravityx#
if c=2 then temp2#=BOOM_gravityy#
if c=3 then temp2#=BOOM_gravityz#
temp#=memblock float(BOOM_Objects(d).Mem1,f*12+(c-1)*4)+memblock float(BOOM_Objects(d).Mem4,(f*3+c)*4)+temp2#*((timer()-BOOM_Objects(d).ExplodeTime)/1000.0)^2
write memblock float BOOM_Objects(d).Mem1,f*12+(c-1)*4,temp#
next c
`Check floors
bad2=1
if BOOM_gravityx#<=0
if memblock float(BOOM_Objects(d).Mem1,f*12+0*4)+object position x(BOOM_Objects(d).ObjectNo)>BOOM_Objects(d).FloorX then bad2=0
else
if memblock float(BOOM_Objects(d).Mem1,f*12+0*4)+object position x(BOOM_Objects(d).ObjectNo)<BOOM_Objects(d).FloorX then bad2=0
endif
if BOOM_gravityy#<=0
if memblock float(BOOM_Objects(d).Mem1,f*12+1*4)+object position y(BOOM_Objects(d).ObjectNo)>BOOM_Objects(d).FloorY then bad2=0
else
if memblock float(BOOM_Objects(d).Mem1,f*12+1*4)+object position y(BOOM_Objects(d).ObjectNo)<BOOM_Objects(d).FloorY then bad2=0
endif
if BOOM_gravityz#<=0
if memblock float(BOOM_Objects(d).Mem1,f*12+2*4)+object position z(BOOM_Objects(d).ObjectNo)>BOOM_Objects(d).FloorZ then bad2=0
else
if memblock float(BOOM_Objects(d).Mem1,f*12+2*4)+object position z(BOOM_Objects(d).ObjectNo)<BOOM_Objects(d).FloorZ then bad2=0
endif
if bad2=0
bad=0
ct#=cos(memblock float(BOOM_Objects(d).Mem2,f*4))
st#=sin(memblock float(BOOM_Objects(d).Mem2,f*4))
s=3*f-1
for a=1 to 3
v=s+a
`Calculate rotation of fragments
offsetposx#=memblock float(BOOM_Objects(d).Mem5,(v*9+1)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+4)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+7)*4)
offsetposy#=memblock float(BOOM_Objects(d).Mem5,(v*9+2)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+5)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+8)*4)
offsetposz#=memblock float(BOOM_Objects(d).Mem5,(v*9+3)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+6)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+9)*4)
set vertexdata position v,memblock float(BOOM_Objects(d).Mem1,f*12)+offsetposx#,memblock float(BOOM_Objects(d).Mem1,f*12+4)+offsetposy#,memblock float(BOOM_Objects(d).Mem1,f*12+8)+offsetposz#
next a
endif
next f
UNLOCK VERTEXDATA
if bad=1 then BOOM_Objects(d).ExplodeTime=-1
endif
next d
endfunction
`Remove an object from the explosion system
function BOOM_UnsetObject(objectno)
for c=1 to array count(BOOM_Objects(0))
if BOOM_Objects(c).objectno=objectno then BOOMID=c
next c
if BOOMID>0
if memblock exist(BOOM_Objects(BOOMID).Mem1) then delete memblock BOOM_Objects(BOOMID).Mem1
if memblock exist(BOOM_Objects(BOOMID).Mem2) then delete memblock BOOM_Objects(BOOMID).Mem2
if memblock exist(BOOM_Objects(BOOMID).Mem3) then delete memblock BOOM_Objects(BOOMID).Mem3
if memblock exist(BOOM_Objects(BOOMID).Mem4) then delete memblock BOOM_Objects(BOOMID).Mem4
if memblock exist(BOOM_Objects(BOOMID).Mem5) then delete memblock BOOM_Objects(BOOMID).Mem5
array delete element BOOM_Objects(0),BOOMID
exitfunction 1
endif
endfunction 0
`Support functions; find free objects
`Replace with your own free object system if you so desire
function FreeMemblock()
repeat
inc temp
until memblock exist(temp)=0
endfunction temp
function FreeMesh()
repeat
inc temp
until mesh exist(temp)=0
endfunction temp
`Support function; offsets an object's geometry at the vertex level
function vertsoff(object,offx as float,offy as float,offz as float)
lock vertexdata for limb object,0,2
for c=0 to get vertexdata vertex count()-1
set vertexdata position c,get vertexdata position x(c)+offx,get vertexdata position y(c)+offy,get vertexdata position z(c)+offz
next c
unlock vertexdata
endfunction
`Support
function sign(value as float)
if value>0 then exitfunction 1
if value<0 then exitfunction -1
endfunction 0
`====================================
Version 2 (9/12/10)
- This version has 3-axis gravity, and the way gravity is handled has been changed slightly, so you may need to redo your gravity values.
- This version does not use the BOOMID system to identify the objects, it just uses the object number.
BOOM_SetupObject(ObjectNo,FloorPos) gets the object ready to blow up. The FloorPos is the global y position where the fragments will stop moving downward. Note that calling this command resets the object's position and rotation.
BOOM_Update() should be called each loop. It moves all the pieces.
BOOM_ExplodeObject(ObjectNo,Violence,vx,vy,vz) explodes the specified object. Violence is how forceful the explosion is. The vx-z values are initial velocities on each axis.
BOOM_UnsetObject(ObjectNo) removes the object from the explosion system but does not delete it or reset its vertexdata.
sync on : sync rate 60
autocam off
set display mode desktop width(),desktop height(),32
`======= Explosions Setup =======
type BOOM_ObjectType
ObjectNo as integer
FaceCount as integer
VertCount as integer
Mem1 as integer
Mem2 as integer
Mem3 as integer
Mem4 as integer
Mem5 as integer
ExplodeTime as integer
Violence as float
FloorPos as float
endtype
DIM BOOM_Objects(0) as BOOM_ObjectType
DIM BOOM_AngSpeeds#(0)
global BOOM_gravityx# `Acceleration due to gravity
global BOOM_gravityy#
global BOOM_gravityz#
BOOM_gravityx#=0
BOOM_gravityy#=-10
BOOM_gravityz#=0
`================================
make object sphere 1,50,10,10
make object cylinder 2,50
BOOM_SetupObject(1,-50)
BOOM_SetupObject(2,-1000)
position object 2,-50,0,0
position camera 100,10,300
point camera 0,-40,0
do
BOOM_Update()
if mouseclick()=1 then BOOM_ExplodeObject(1,700,3,0,0)
if mouseclick()=2 then BOOM_ExplodeObject(2,700,0,0,0)
if spacekey() and pressed=0 then pressed=1 : BOOM_UnsetObject(1)
if spacekey()=0 then pressed=0
text 10,10,str$(screen fps())
sync
loop
function BOOM_SetupObject(ObjectNo as integer,FloorPos as float)
array insert at bottom BOOM_Objects(0)
temp=array count(BOOM_Objects(0))
BOOM_Objects(temp).ObjectNo=ObjectNo
BOOM_Objects(temp).FloorPos=FloorPos
BOOM_Objects(temp).Mem1=FreeMemblock()
temp2=FreeMesh()
`CHANGE OBJECT TO NO SHARED VERTICES FORMAT
make mesh from object temp2,ObjectNo
delete object ObjectNo
make memblock from mesh BOOM_Objects(temp).Mem1,temp2
make mesh from memblock temp2,BOOM_Objects(temp).Mem1
delete memblock BOOM_Objects(temp).Mem1
make object ObjectNo,temp2,1
delete mesh temp2
set object cull ObjectNo,0 `so you can see backfaces
LOCK VERTEXDATA FOR LIMB ObjectNo,0,1
BOOM_Objects(temp).VertCount=GET VERTEXDATA VERTEX COUNT()
BOOM_Objects(temp).FaceCount=BOOM_Objects(temp).VertCount/3
`These arrays only needed in this function
local dim temp1#(3,BOOM_Objects(temp).FaceCount)
local dim temp2#(3,BOOM_Objects(temp).VertCount)
`BOOM_AngSpeeds is just constants, same for any object
`All we do here is add more if you set up an object with more verts that we can currently handle
temp2=array count(BOOM_AngSpeeds#(0))
if BOOM_Objects(temp).FaceCount>temp2
dim BOOM_AngSpeeds#(BOOM_Objects(temp).FaceCount)
for c=temp2+1 to BOOM_Objects(temp).FaceCount
BOOM_AngSpeeds#(c)=0.5*(rnd(11)-5.5)
next c
endif
FOR N=0 TO BOOM_Objects(temp).VertCount-1
temp2#(1,n)=GET VERTEXDATA POSITION X(N)
temp2#(2,n)=GET VERTEXDATA POSITION Y(N)
temp2#(3,n)=GET VERTEXDATA POSITION Z(N)
NEXT N
UNLOCK VERTEXDATA
make memblock BOOM_Objects(temp).Mem1,BOOM_Objects(temp).FaceCount*3*4
BOOM_Objects(temp).Mem2=FreeMemblock()
make memblock BOOM_Objects(temp).Mem2,BOOM_Objects(temp).FaceCount*4
BOOM_Objects(temp).Mem3=FreeMemblock()
make memblock BOOM_Objects(temp).Mem3,(BOOM_Objects(temp).VertCount+1)*4*9
BOOM_Objects(temp).Mem5=FreeMemblock()
make memblock BOOM_Objects(temp).Mem5,(BOOM_Objects(temp).VertCount+1)*4*9
for f=0 to BOOM_Objects(temp).FaceCount-1
n=f*3
for c=1 to 3
temp#=(temp2#(c,n+0)+temp2#(c,n+1)+temp2#(c,n+2))/3.0
write memblock float BOOM_Objects(temp).Mem1,f*12+(c-1)*4,temp#
temp2#(c,n+0)=temp2#(c,n+0)-temp#
temp2#(c,n+1)=temp2#(c,n+1)-temp#
temp2#(c,n+2)=temp2#(c,n+2)-temp#
next c
next f
`Set up fragment rotation
for f=0 to BOOM_Objects(temp).FaceCount-1
mag#=0.0
for c= 1 to 3
temp1#(c,f)=rnd(5)-2.5
inc mag#,temp1#(c,f)*temp1#(c,f)
next c
mag#=sqrt(mag#)
`normalise..
for c=1 to 3
temp1#(c,f)=temp1#(c,f)/mag#
next c
`get components parallel to, perpendicular to, and perpendicular to both..
s=3*f-1
for a=1 to 3
v=s+a
dotp#=temp2#(1,v)*temp1#(1,f)+temp2#(2,v)*temp1#(2,f)+temp2#(3,v)*temp1#(3,f)
for x=1 to 3
temp#=dotp#*temp1#(x,f)
write memblock float BOOM_Objects(temp).Mem5,(v*9+x)*4,temp#
write memblock float BOOM_Objects(temp).Mem5,(v*9+x+3)*4,temp2#(x,v)-temp#
next x
write memblock float BOOM_Objects(temp).Mem5,(v*9+7)*4,memblock float(BOOM_Objects(temp).Mem5,(v*9+5)*4)*temp1#(3,f)-memblock float(BOOM_Objects(temp).Mem5,(v*9+6)*4)*temp1#(2,f)
write memblock float BOOM_Objects(temp).Mem5,(v*9+8)*4,memblock float(BOOM_Objects(temp).Mem5,(v*9+6)*4)*temp1#(1,f)-memblock float(BOOM_Objects(temp).Mem5,(v*9+4)*4)*temp1#(3,f)
write memblock float BOOM_Objects(temp).Mem5,(v*9+9)*4,memblock float(BOOM_Objects(temp).Mem5,(v*9+4)*4)*temp1#(2,f)-memblock float(BOOM_Objects(temp).Mem5,(v*9+5)*4)*temp1#(1,f)
next a
next f
UNDIM temp1#(0,0)
UNDIM temp2#(0,0)
BOOM_Objects(temp).Mem4=FreeMemblock()
make memblock BOOM_Objects(temp).Mem4,3*(BOOM_Objects(temp).FaceCount+1)*4
endfunction
function BOOM_ExplodeObject(objectno,Violence#,vx as float,vy as float, vz as float)
for c=1 to array count(BOOM_Objects(0))
if BOOM_Objects(c).objectno=objectno then BOOMID=c
next c
if BOOMID>0
if BOOM_Objects(BOOMID).ExplodeTime=0
BOOM_Objects(BOOMID).ExplodeTime=timer()
BOOM_Objects(BOOMID).Violence=Violence#
for f=0 to BOOM_Objects(BOOMID).FaceCount-1
`Randomizes exit velocities
c#=sqrt(rnd(256))
for c=1 to 3
if c=1 then off#=vx
if c=2 then off#=vy
if c=3 then off#=vz
write memblock float BOOM_Objects(BOOMID).Mem4,(f*3+c)*4,(Violence#/100000)*c#*memblock float(BOOM_Objects(BOOMID).Mem1,f*12+(c-1)*4)+off#
next c
next f
endif
exitfunction 1
endif
endfunction 0
function BOOM_Update()
for d=1 to array count(BOOM_Objects(0))
if BOOM_Objects(d).ExplodeTime>0
bad=1 `Used to stop animation when all pieces hit the floor
LOCK VERTEXDATA FOR LIMB BOOM_Objects(d).ObjectNo,0,1
for f=0 to BOOM_Objects(d).FaceCount-1
write memblock float BOOM_Objects(d).Mem2,f*4,wrapvalue(memblock float(BOOM_Objects(d).Mem2,f*4)+BOOM_AngSpeeds#(f)*BOOM_Objects(d).Violence/60)
`Move Faces, c is each axis
for c=1 to 3
if c=1 then temp2#=BOOM_gravityx#
if c=2 then temp2#=BOOM_gravityy#
if c=3 then temp2#=BOOM_gravityz#
temp#=memblock float(BOOM_Objects(d).Mem1,f*12+(c-1)*4)+memblock float(BOOM_Objects(d).Mem4,(f*3+c)*4)+temp2#*((timer()-BOOM_Objects(d).ExplodeTime)/1000.0)^2
write memblock float BOOM_Objects(d).Mem1,f*12+(c-1)*4,temp#
next c
ct#=cos(memblock float(BOOM_Objects(d).Mem2,f*4))
st#=sin(memblock float(BOOM_Objects(d).Mem2,f*4))
s=3*f-1
for a=1 to 3
v=s+a
`Calculate rotation of fragments
offsetposx#=memblock float(BOOM_Objects(d).Mem5,(v*9+1)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+4)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+7)*4)
offsetposy#=memblock float(BOOM_Objects(d).Mem5,(v*9+2)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+5)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+8)*4)
offsetposz#=memblock float(BOOM_Objects(d).Mem5,(v*9+3)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+6)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+9)*4)
if memblock float(BOOM_Objects(d).Mem1,f*12+4)+offsetposy#+object position y(BOOM_Objects(d).ObjectNo)>=BOOM_Objects(d).FloorPos
bad=0
set vertexdata position v,memblock float(BOOM_Objects(d).Mem1,f*12)+offsetposx#,memblock float(BOOM_Objects(d).Mem1,f*12+4)+offsetposy#,memblock float(BOOM_Objects(d).Mem1,f*12+8)+offsetposz#
endif
next a
next f
UNLOCK VERTEXDATA
if bad=1 then BOOM_Objects(d).ExplodeTime=-1
endif
next d
endfunction
function BOOM_UnsetObject(objectno)
for c=1 to array count(BOOM_Objects(0))
if BOOM_Objects(c).objectno=objectno then BOOMID=c
next c
if BOOMID>0
if memblock exist(BOOM_Objects(BOOMID).Mem1) then delete memblock BOOM_Objects(BOOMID).Mem1
if memblock exist(BOOM_Objects(BOOMID).Mem2) then delete memblock BOOM_Objects(BOOMID).Mem2
if memblock exist(BOOM_Objects(BOOMID).Mem3) then delete memblock BOOM_Objects(BOOMID).Mem3
if memblock exist(BOOM_Objects(BOOMID).Mem4) then delete memblock BOOM_Objects(BOOMID).Mem4
if memblock exist(BOOM_Objects(BOOMID).Mem5) then delete memblock BOOM_Objects(BOOMID).Mem5
array delete element BOOM_Objects(0),BOOMID
exitfunction 1
endif
endfunction 0
function FreeMemblock()
repeat
inc temp
until memblock exist(temp)=0
endfunction temp
function FreeMesh()
repeat
inc temp
until mesh exist(temp)=0
endfunction temp
Version 1
ID=BOOM_SetupObject(ObjectNo,FloorPos) gets the object ready to blow up. The FloorPos is the global y position where the fragments will stop moving downward.
BOOM_Update() should be called each loop. It moves all the pieces.
BOOM_ExplodeObject(ID,Violence) explodes the specified object (ID is the value that was returned from BOOM_SetupObject). Violence is just how forceful the explosion is.
In this demo, left-click to explode the sphere, and right-click to explode the cylinder.
sync on : sync rate 60
autocam off
`======= Explosions Setup =======
type BOOM_ObjectType
ObjectNo as integer
FaceCount as integer
VertCount as integer
Mem1 as integer
Mem2 as integer
Mem3 as integer
Mem4 as integer
Mem5 as integer
ExplodeTime as integer
Violence as float
FloorPos as float
endtype
DIM BOOM_Objects(0) as BOOM_ObjectType
DIM BOOM_AngSpeeds#(0)
global BOOM_gravity# `Acceleration due to gravity
BOOM_gravity#=0.0002
`================================
make object sphere 1,50,10,10
make object cylinder 2,50
sphere1=BOOM_SetupObject(1,-50)
sphere2=BOOM_SetupObject(2,-1000)
position object 2,-50,0,0
position camera 100,10,300
point camera 0,-40,0
do
BOOM_Update()
if mouseclick()=1 then BOOM_ExplodeObject(sphere1,700)
if mouseclick()=2 then BOOM_ExplodeObject(sphere2,700)
text 10,10,str$(screen fps())
sync
loop
function BOOM_SetupObject(ObjectNo as integer,FloorPos as float)
array insert at bottom BOOM_Objects(0)
temp=array count(BOOM_Objects(0))
BOOM_Objects(temp).ObjectNo=ObjectNo
BOOM_Objects(temp).FloorPos=FloorPos
BOOM_Objects(temp).Mem1=FreeMemblock()
temp2=FreeMesh()
`CHANGE OBJECT TO NO SHARED VERTICES FORMAT
make mesh from object temp2,ObjectNo
delete object ObjectNo
make memblock from mesh BOOM_Objects(temp).Mem1,temp2
make mesh from memblock temp2,BOOM_Objects(temp).Mem1
delete memblock BOOM_Objects(temp).Mem1
make object ObjectNo,temp2,1
delete mesh temp2
set object cull ObjectNo,0 `so you can see backfaces
LOCK VERTEXDATA FOR LIMB ObjectNo,0,1
BOOM_Objects(temp).VertCount=GET VERTEXDATA VERTEX COUNT()
BOOM_Objects(temp).FaceCount=BOOM_Objects(temp).VertCount/3
`These arrays only needed in this function
local dim temp1#(3,BOOM_Objects(temp).FaceCount)
local dim temp2#(3,BOOM_Objects(temp).VertCount)
`BOOM_AngSpeeds is just constants, same for any object
`All we do here is add more if you set up an object with more verts that we can currently handle
temp2=array count(BOOM_AngSpeeds#(0))
if BOOM_Objects(temp).FaceCount>temp2
dim BOOM_AngSpeeds#(BOOM_Objects(temp).FaceCount)
for c=temp2+1 to BOOM_Objects(temp).FaceCount
BOOM_AngSpeeds#(c)=0.5*(rnd(11)-5.5)
next c
endif
FOR N=0 TO BOOM_Objects(temp).VertCount-1
temp2#(1,n)=GET VERTEXDATA POSITION X(N)
temp2#(2,n)=GET VERTEXDATA POSITION Y(N)
temp2#(3,n)=GET VERTEXDATA POSITION Z(N)
NEXT N
UNLOCK VERTEXDATA
make memblock BOOM_Objects(temp).Mem1,BOOM_Objects(temp).FaceCount*3*4
BOOM_Objects(temp).Mem2=FreeMemblock()
make memblock BOOM_Objects(temp).Mem2,BOOM_Objects(temp).FaceCount*4
BOOM_Objects(temp).Mem3=FreeMemblock()
make memblock BOOM_Objects(temp).Mem3,(BOOM_Objects(temp).VertCount+1)*4*9
BOOM_Objects(temp).Mem5=FreeMemblock()
make memblock BOOM_Objects(temp).Mem5,(BOOM_Objects(temp).VertCount+1)*4*9
for f=0 to BOOM_Objects(temp).FaceCount-1
n=f*3
for c=1 to 3
temp#=(temp2#(c,n)+temp2#(c,n+1)+temp2#(c,n+2))/3.0
write memblock float BOOM_Objects(temp).Mem1,f*12+(c-1)*4,temp#
temp2#(c,n)=temp2#(c,n)-temp#
temp2#(c,n+1)=temp2#(c,n+1)-temp#
temp2#(c,n+2)=temp2#(c,n+2)-temp#
next c
next f
for f=0 to BOOM_Objects(temp).FaceCount-1
mag#=0.0
for c= 1 to 3
temp1#(c,f)=rnd(5)-2.5
inc mag#,temp1#(c,f)*temp1#(c,f)
next c
mag#=sqrt(mag#)
`normalise..
for c=1 to 3
temp1#(c,f)=temp1#(c,f)/mag#
next c
`get components parallel to, perpendicular to, and perpendicular to both..
s=3*f-1
for a=1 to 3
v=s+a
dotp#=temp2#(1,v)*temp1#(1,f)+temp2#(2,v)*temp1#(2,f)+temp2#(3,v)*temp1#(3,f)
for x=1 to 3
temp#=dotp#*temp1#(x,f)
write memblock float BOOM_Objects(temp).Mem5,(v*9+x)*4,temp#
write memblock float BOOM_Objects(temp).Mem5,(v*9+x+3)*4,temp2#(x,v)-temp#
next x
write memblock float BOOM_Objects(temp).Mem5,(v*9+7)*4,memblock float(BOOM_Objects(temp).Mem5,(v*9+5)*4)*temp1#(3,f)-memblock float(BOOM_Objects(temp).Mem5,(v*9+6)*4)*temp1#(2,f)
write memblock float BOOM_Objects(temp).Mem5,(v*9+8)*4,memblock float(BOOM_Objects(temp).Mem5,(v*9+6)*4)*temp1#(1,f)-memblock float(BOOM_Objects(temp).Mem5,(v*9+4)*4)*temp1#(3,f)
write memblock float BOOM_Objects(temp).Mem5,(v*9+9)*4,memblock float(BOOM_Objects(temp).Mem5,(v*9+4)*4)*temp1#(2,f)-memblock float(BOOM_Objects(temp).Mem5,(v*9+5)*4)*temp1#(1,f)
next a
next f
UNDIM temp1#(0,0)
UNDIM temp2#(0,0)
BOOM_Objects(temp).Mem4=FreeMemblock()
make memblock BOOM_Objects(temp).Mem4,3*(BOOM_Objects(temp).FaceCount+1)*4
endfunction temp
function BOOM_ExplodeObject(BOOMID,Violence#)
if BOOM_Objects(BOOMID).ExplodeTime=0
BOOM_Objects(BOOMID).ExplodeTime=timer()
BOOM_Objects(BOOMID).Violence=Violence#
for f=0 to BOOM_Objects(BOOMID).FaceCount-1
`Randomizes exit velocities
c#=sqrt(rnd(256))
for c=1 to 3
write memblock float BOOM_Objects(BOOMID).Mem4,(f*3+c)*4,(Violence#/100000)*c#*memblock float(BOOM_Objects(BOOMID).Mem1,f*12+(c-1)*4)
next c
next f
endif
endfunction
function BOOM_Update()
for d=1 to array count(BOOM_Objects(0))
if BOOM_Objects(d).ExplodeTime>0
bad=1 `Used to stop animation when all pieces hit the floor
LOCK VERTEXDATA FOR LIMB BOOM_Objects(d).ObjectNo,0,1
for f=0 to BOOM_Objects(d).FaceCount-1
write memblock float BOOM_Objects(d).Mem2,f*4,wrapvalue(memblock float(BOOM_Objects(d).Mem2,f*4)+BOOM_AngSpeeds#(f)*BOOM_Objects(d).Violence/60)
`Move Faces, c is each axis
for c=1 to 3
temp#=memblock float(BOOM_Objects(d).Mem1,f*12+(c-1)*4)
inc temp#,memblock float(BOOM_Objects(d).Mem4,(f*3+c)*4)
write memblock float BOOM_Objects(d).Mem1,f*12+(c-1)*4,temp#
next c
ct#=cos(memblock float(BOOM_Objects(d).Mem2,f*4))
st#=sin(memblock float(BOOM_Objects(d).Mem2,f*4))
s=3*f-1
for a=1 to 3
v=s+a
`Effect of gravity
temp#=0.5*BOOM_gravity#*(timer()-BOOM_Objects(d).ExplodeTime)^2
offsetposx#=memblock float(BOOM_Objects(d).Mem5,(v*9+1)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+4)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+7)*4)
offsetposy#=memblock float(BOOM_Objects(d).Mem5,(v*9+2)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+5)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+8)*4)-temp#
offsetposz#=memblock float(BOOM_Objects(d).Mem5,(v*9+3)*4)+ct#*memblock float(BOOM_Objects(d).Mem5,(v*9+6)*4)+st#*memblock float(BOOM_Objects(d).Mem5,(v*9+9)*4)
if memblock float(BOOM_Objects(d).Mem1,f*12+4)+offsetposy#+object position y(BOOM_Objects(d).ObjectNo)>=BOOM_Objects(d).FloorPos
bad=0
set vertexdata position v,memblock float(BOOM_Objects(d).Mem1,f*12)+offsetposx#,memblock float(BOOM_Objects(d).Mem1,f*12+4)+offsetposy#,memblock float(BOOM_Objects(d).Mem1,f*12+8)+offsetposz#
endif
next a
next f
UNLOCK VERTEXDATA
if bad=1 then BOOM_Objects(d).ExplodeTime=-1
endif
next d
endfunction
function FreeMemblock()
repeat
inc temp
until memblock exist(temp)=0
endfunction temp
function FreeMesh()
repeat
inc temp
until mesh exist(temp)=0
endfunction temp
Latest progress: Fog of War implemented; frustrated by pathfinding >.>