Author |
Topic: Quest for fire library (group effort ) (Read 393 times) |
|
michael
Senior Member
member is offline


Posts: 335
|
 |
Quest for fire library (group effort )
« Thread started on: Dec 22nd, 2017, 04:33am » |
|
I invite anyone to come to Richards forum and contribute to the fire library:
I am working on a sample and I would be happy to see your example of a fire animation. (it can be any size, within reason)
Here is a link:
http://bbcbasic.conforums.com/index.cgi?board=graphics&action=display&num=1513881353
|
|
Logged
|
I like making program generators and like reinventing the wheel
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Quest for fire library (group effort )
« Reply #1 on: Dec 26th, 2017, 2:03pm » |
|
A fire effect:
https://pastebin.com/AkjKJGWD
Scroll the page all the way down until you reach the "RAW Paste Data" section, then left-click somewhere inside that box, press CTRL+A to select all code, then CTRL+C to copy the code onto the Windows clipboard, then paste the code inside the BB4W IDE with CTRL+V.
Or do it your own way 
David. --
|
|
Logged
|
|
|
|
michael
Senior Member
member is offline


Posts: 335
|
 |
Re: Quest for fire library (group effort )
« Reply #3 on: Dec 27th, 2017, 12:47am » |
|
Very nice fire samples.
|
|
Logged
|
I like making program generators and like reinventing the wheel
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Quest for fire library (group effort )
« Reply #4 on: Dec 27th, 2017, 2:12pm » |
|
on Dec 27th, 2017, 12:47am, michael wrote:
Thanks. I've now modified the program to be frame-rate independent, so that the animation runs at pretty much the same speed whether on slow or fast computers. It also has lower CPU usage:
https://pastebin.com/kFjw5vab
A further (possible) improvement would be to reduce the size of the fire particles as their height increases.
I'll take the opportunity here to re-post this (relevant!) bit of code by Jan Vibe which I converted to BB4W from the original ARM BBC BASIC:
Code:
REM > INFERNO
REM by Jan Vibe
REM Adapted for BB4W by DW
REMMODE27:OFF:PROCT
MODE 19 : OFF : PROCpaletted : PROCT
FORN%=0TO1280STEP2:GCOLRND(15):PLOT N%,0:NEXT
FORY%=2TO960STEP2
FORX%=0TO1280STEP2
R%=2*(RND(3)-2):C%=ABS(POINT(X%+R%,Y%-2)):IF RND(1)>.8 C%=C%MOD15+1
GCOLC%:LINE X%,Y%,X%,Y%:PROCT
NEXT X%
NEXT Y%
REPEAT:PROCT:UNTIL0
DEFPROCT
IF TIME>T% THEN
LOCAL F%:S%=S%MOD15+1
FORN%=1TO15:F%=(S%+N%)MOD15+1:COLOURF%,255,16*N%,0:NEXT
PROCanimate
T%=TIME+5
ENDIF
ENDPROC
REM Code from the BB4W Programmer's Reference:
DEF PROCanimate
LOCAL C%, pal%()
DIM pal%(15)
SYS "GetPaletteEntries", @hpal%, 0, 16, ^pal%(0)
pal%() AND= &E0F0F0
FOR C% = 0 TO 15 : SWAP ?^pal%(C%), ?(2+^pal%(C%)) : NEXT
SYS "SetDIBColorTable", @memhdc%, 0, 16, ^pal%(0)
SYS "InvalidateRect", @hwnd%, 0, 0
ENDPROC
DEF PROCpaletted
LOCAL bits%, hbm%, oldbm%, bmih{}
DIM bmih{Size%, Width%, Height%, Planes{l&,h&}, BitCount{l&,h&}, \
\ Compression%, SizeImage%, XPelsPerMeter%, YPelsPerMeter%, \
\ ClrUsed%, ClrImportant%}
bmih.Size% = DIM(bmih{})
bmih.Width% = @vdu%!208
bmih.Height% = @vdu%!212
bmih.Planes.l& = 1
bmih.BitCount.l& = 4
SYS "CreateDIBSection", @memhdc%, bmih{}, 0, ^bits%, 0, 0 TO hbm%
IF hbm% = 0 ERROR 100, "Couldn't create DIBSection"
SYS "SelectObject", @memhdc%, hbm% TO oldbm%
SYS "DeleteObject", oldbm%
PROCanimate
ENDPROC
David. --
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Quest for fire library (group effort )
« Reply #5 on: Dec 27th, 2017, 8:02pm » |
|
This version works with BB4W and BBCSDL (tested under BBCSDL Win32 and Android (ARM)).
https://pastebin.com/dp5EhtfJ
The YouTube video linked-to below shows the program running on a Motorola Moto G4 Plus (Snapdragon 617 ARM-basec SoC):
https://youtu.be/7i8532in0H0
David. --
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Quest for fire library (group effort )
« Reply #6 on: Dec 28th, 2017, 06:06am » |
|
I've modified my program so that the fire has a broader base (the X co-ordinate of each fire 'particle' is normally distributed via the Box–Muller transform):
https://pastebin.com/BdrggHwz
Two further improvements that could be made:
1) Reduce fire particle size with increasing height 2) Use a better colour table :) 3) Apply a smoothing filter
Anyway, I think I'm done with this fire thing for now. It's been fun.
David. --
PS. I mentioned Box-Muller transform, here's a quick demo:
Code:
REM Box-Muller transform demo
REM See Wikipedia https://tinyurl.com/argkvx3
MODE 8 : OFF
ORIGIN 640, 512
scale = 100
REPEAT
u1 = RND(1)
u2 = RND(1)
r = SQR(-2 * LNu1)
a = 2*PI * u2
x = r * COSa
y = r * SINa
PLOT 2*scale*x, 2*scale*y
UNTIL FALSE
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Quest for fire library (group effort )
« Reply #7 on: Jan 2nd, 2018, 2:05pm » |
|
Hi everyone, and a Happy New Year!
I had a play with this. I make no claims that it is any better than previous offerings... but it was fun doing it.
Seems to run OK in BB4W and in BBC_SDL, though rather slower in the latter - you might want to change the WAIT to 5, or even 1.
If you want your flames to go more red at the top, change the "-2*x%" in the green component of the colour definitions in PROCDrawFlame to "-4*x%".
I have thought about converting it to use D3D: then you could blend colours for the triangles, and make them semi-transparent, so you could see the firewood through them. I'm not sure what will happen if I try to rewrite the vertex buffers dynamically - it may cause a spectacular crash... Does anyone know?
Best wishes,
D Code:
MODE 21
*REFRESH OFF
GCOL 3
FOR duration%=0 TO 100
CLS
PROCDrawLog(180,420,-30,100,320)
PROCDrawLog(200,370,0,80,340)
PROCDrawLog(240,330,30,90,320)
PROCDrawFlame(430,420,210,500)
PROCDrawFlame(300,400,210,400)
PROCDrawFlame(500,400,210,400)
PROCDrawFlame(400,300,210,300)
PROCDrawLog(780,420,-30,30,120)
PROCDrawLog(800,370,0,25,140)
PROCDrawLog(840,330,30,30,120)
PROCDrawFlame(830,420,50,70)
PROCDrawFlame(800,400,50,70)
PROCDrawFlame(900,400,50,70)
PROCDrawFlame(850,350,50,85)
*REFRESH
WAIT 10
NEXT duration%
*REFRESH ON
END
:
DEFPROCDrawLog(px%,py%,a%,w%,l%)
COLOUR 3,50,30,0
MOVE px%,py%
MOVE px%+w%*COSRAD(a%+90),py%+w%*SINRAD(a%+90)
PLOT 117,px%+l%*COSRAD(a%)+w%*COSRAD(a%+90),py%+l%*SINRAD(a%)+w%*SINRAD(a%+90)
ENDPROC
:
DEFPROCDrawFlame(px%,py%,w%,h%)
LOCAL x%,hw%,dw%,dh%,f%()
DIM f%(26,2)
hw%=w%/2
dw%=hw%*0.8
dh%=h%/25
FOR x%=0 TO 25
f%(x%,1)=px%+RND(x%)
f%(x%,0)=f%(x%,1)-hw%+ABS(dw%-dw%*SQR(x%)/2.5)+RND(x%)*hw%/100
f%(x%,2)=f%(x%,1)+hw%-ABS(dw%-dw%*SQR(x%)/2.5)-RND(x%)*hw%/100
NEXT x%
f%(26,1)=px%+RND(x%)
f%(26,0)=f%(26,1)
f%(26,2)=f%(26,1)
GCOL 3
FOR x%=0 TO 25
COLOUR 3,200+x%,150-2*x%,26-x%
MOVE f%(x%,1),x%*dh%+py%
MOVE f%(x%+1,1),(x%+1)*dh%+py%
PLOT 85,f%(x%,0),x%*dh%+py%
PLOT 85,f%(x%+1,0),(x%+1)*dh% +py%
MOVE f%(x%,1),x%*dh%+py%
MOVE f%(x%+1,1),(x%+1)*dh%+py%
PLOT 85,f%(x%,2),x%*dh%+py%
PLOT 85,f%(x%+1,2),(x%+1)*dh%+py%
COLOUR 3,220+x%,220-2*x%,70-x%
MOVE f%(x%,1),x%*dh%+py%
MOVE f%(x%+1,1),(x%+1)*dh%+py%
PLOT 85,(f%(x%,0)+f%(x%,1))/2,x%*dh%+py%
PLOT 85,(f%(x%+1,0)+f%(x%+1,1))/2,(x%+1)*dh% +py%
MOVE f%(x%,1),x%*dh%+py%
MOVE f%(x%+1,1),(x%+1)*dh%+py%
PLOT 85,(f%(x%,2)+f%(x%,1))/2,x%*dh%+py%
PLOT 85,(f%(x%+1,2)+f%(x%+1,1))/2,(x%+1)*dh% +py%
NEXT x%
ENDPROC
|
|
Logged
|
|
|
|
David Williams
Developer
member is offline

meh

Gender: 
Posts: 452
|
 |
Re: Quest for fire library (group effort )
« Reply #8 on: Jan 3rd, 2018, 02:31am » |
|
on Jan 2nd, 2018, 2:05pm, DDRM wrote:Hi everyone, and a Happy New Year!
I had a play with this. I make no claims that it is any better than previous offerings... but it was fun doing it. |
|
Happy New Year to you, too 
I like your approach to the quest for fire - seems like clever use of the PLOT command. Amazingly I wasn't aware that PLOT can also be used to draw parallelograms (which you used for drawing the logs). I really am slow to learn. By the way, those logs were too dark on my screen! I didn't notice them until I actually looked for them after I had glanced at the code. Anyway, that was easy enough to fix.
David. --
|
|
Logged
|
|
|
|
michael
Senior Member
member is offline


Posts: 335
|
 |
Re: Quest for fire library (group effort )
« Reply #9 on: Jan 3rd, 2018, 05:34am » |
|
That was a unique fire demo DDRM. Looks cool. Happy new year to all.
|
|
Logged
|
I like making program generators and like reinventing the wheel
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Quest for fire library (group effort )
« Reply #10 on: Jan 11th, 2018, 08:48am » |
|
Hi Folks,
Well, I did have a go at doing it in D3D. It's proved harder than I hoped to get nice transparency effects - I can't seem to get it to show the logs through the flames, for example, and I don't think I understand emissivity properly! Anyway, I think the Gouraud shading makes the flames look quite nice, and they DO overlap each other...
Here's the code for the "flames" bit. It requires an FVF file for the logs: I'll post code for that separately in a moment.
At the moment this is written specifically for BB4W, and Windows, since it uses a number of D3D SYS calls. I don't know how to do the equivalent in SDL, but I'd be interested to see a conversion! I presume a lot of the stuff with FVF buffers should be fairly straightforward to convert.
Best wishes,
D Code:
HIMEM=LOMEM+1E8
MODE 21
nbufs%=4
REM Here I'm actually reserving arrays 1 BIGGER than nbufs% (i.e. 0 - nbufs%), which gives me one for background scene - here, the logs
DIM l%(nbufs%), b%(nbufs%), n%(nbufs%), f%(nbufs%), s%(nbufs%), m%(nbufs%), t%(nbufs%), y(nbufs%), p(nbufs%), r(nbufs%), X(nbufs%), Y(nbufs%), Z(nbufs%), e(2), a(2)
INSTALL @lib$+"D3DLIBA"
ON CLOSE PROCcleanup(nbufs%):QUIT
ON ERROR PROCcleanup(nbufs%):PRINT REPORT$:END
d% = FN_initd3d(@hwnd%, 1, 1)
IF d% = 0 ERROR 100, "Can't initialise Direct3D"
REM David's attempt to set alpha blending
SYS !(!d%+200),d%,27,1:REM SetRenderState(Alphablendenable)
SYS !(!d%+200),d%,19,5:REM SetRenderState( set source blend to D3DBLEND_SRCALPHA)
SYS !(!d%+200),d%,20,6:REM SetRenderState(set destination blend to D3DBLEND_INVSRCALPHA)
SYS !(!d%+200),d%,148,1:REM SetRenderState(set emissive materialcoloursource to "diffuse vertex colour")
DIM l%(0) 103
l%(0)!0 = 3 : REM directional light, taken from manual (parameters adjusted)
l%(0)!4 = FN_f4(1) : REM red component
l%(0)!8 = FN_f4(1) : REM green component
l%(0)!12 = FN_f4(1) : REM blue component
l%(0)!64 = FN_f4(0.5) : REM. X component of direction
l%(0)!68 = FN_f4(-0.50) : REM. Y component of direction
l%(0)!72 = FN_f4(0.2) : REM. Z component of direction
nv%=26*12 :REM number of layers * 4 triangles (2 on each side between this layer and the next)
REM Set up vertex buffers for each flame
FOR x%=0 TO nbufs%-1
n%(x%)=nv%
f%(x%)=&52
s%(x%)=28
X(x%)=(x%-0.8)/2
Y(x%)=(x% MOD 2)*0.5
b%(x%)=FN_setupVbuf(d%,n%(x%),f%(x%),s%(x%))
IF b%(x%)=0 THEN PROCcleanup(nbufs%):PRINT x%,"Disaster!":END
NEXT x%
REM Set up vertex buffer by loading the background "scene" - here it's just 3 logs!
b%(nbufs%)=FN_load3d(d%,"logs.fvf",n%(nbufs%),f%(nbufs%),s%(nbufs%))
IF b%(nbufs%)=0 THEN PROCcleanup(nbufs%):PRINT "Logs failed to load!":END
X(nbufs%)=-0.5
Z(nbufs%)=0.8
p() = 0 :REM No pan/roll/yaw - could be omitted!
r() = 0
y()=0
e() = 0,0,-10 :REM Eye/camera position
a() = 0, 1, 0 :REM Point you are looking at (centre of screen)
FOR duration%=0 TO 100
FOR x%=0 TO nbufs%-1
PROCWriteVBufData(b%(x%),n%(x%),s%(x%),1,2) :REM Re-write the actual vertex data to make flames flicker
NEXT x%
PROC_render(d%, &FF101010, 1, l%(), nbufs%+1, m%(), t%(), b%(), n%(), f%(), s%(), y(), p(), r(), X(), Y(), Z(), e(), a(), PI/4, 5/4, 1, 1000,0)
WAIT 10
NEXT duration%
PROCcleanup(nbufs%)
END
:
DEF FN_setupVbuf(D%,N%,V%,L%) :REM Adapted from D3DLib (as some of the other D3D stuff!)
LOCAL B%,R%
SYS!(!D%+92),D%,N%*L%,0,V%,0,^B% TO R%:REM CreateVertexBuffer
IF R% THEN=0
=B%
:
DEFPROCWriteVBufData(B%,N%,L%,w,h)
LOCAL P%,vb%
LOCAL x%,n%,n2%,c1%,c2%,dc%,hn,hw,dw,f()
n%=5 :REM you can change this to change the shape/detail of the flame - there will be n%^2 layers.
REM If you make n% more than 5, you may need to increase the memory reserved at the beginning, or it will crash!
n2%=n%^2
hn=n%/2
DIM f(n2%+1,2)
hw=w/2
dw=hw*0.8
FOR x%=0 TO n2%
f(x%,1)=RND(x%)/(4*n2%)
f(x%,0)=f(x%,1)-hw+ABS(dw-dw*SQR(x%)/hn)+RND(x%)*hw/(8*n2%)
f(x%,2)=f(x%,1)+hw-ABS(dw-dw*SQR(x%)/hn)-RND(x%)*hw/(8*n2%)
NEXT x%
f(n2%+1,1)=RND(n2%)/(2*n2%)
f(n2%+1,0)=f(n2%+1,1)
f(n2%+1,2)=f(n2%+1,1)
SYS!(!B%+44),B%,0,N%*L%,^P%,0:REM pVB::Lock
vb%=P% :REM vb% is a pointer to where we have got to in the buffer
dc%=(1<<16)-(2<<8)-1 :REM calculate difference in colour for one level higher
FOR x%=0 TO n2%
REM Calculate colours for edge and centre of the flame at this level
c1%=((160+x%)<<16)+((130-2*x%)<8)+26-x% +(&80<<24)
c2%=((190+x%)<<16)+((158-x%)<<8)+55-x% +(&80<<24)
REM write data for the trapezium between this level and the next
REM 4 triangles, two from the left edge to the centre, and two from the right edge to the centre
PROCDoPoint(f(x%,0),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%-dc%,vb%)
PROCDoPoint(f(x%,1),x%*h/(n2%+1),0,c2%,vb%)
PROCDoPoint(f(x%,0),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%+1,0),(x%+1)*h/(n2%+1),0,c1%-dc%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%,vb%)
PROCDoPoint(f(x%,2),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%,1),x%*h/(n2%+1),0,c2%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%-dc%,vb%)
PROCDoPoint(f(x%,2),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%-dc%,vb%)
PROCDoPoint(f(x%+1,2),(x%+1)*h/(n2%+1),0,c1%-dc%,vb%)
NEXT x%
SYS!(!B%+48),B%:REM pVB::Unlock
ENDPROC
:
DEFPROCDoPoint(x,y,z,c%, RETURN vb%)
REM Here are the coordinates of the point
!vb%=FN_f4(x)
vb%!4=FN_f4(y)
vb%!8=FN_f4(z)
REM Now need normals! Assume all points are flat in the plane,so normal faces towards Z
vb%!12=FN_f4(0.0)
vb%!16=FN_f4(0.0)
vb%!20=FN_f4(1.0)
REM Now the colour
vb%!24=c%
vb%+=28 :REM Update pointer. I do it here so it's easy to change if you change the vertex size
ENDPROC
:
DEF PROCcleanup(nbufs%) : REM From example, slightly amended to allow for multiple buffers
LOCAL x%
FOR x%=0 TO nbufs%
t%(nbufs%) += 0:IF t%(nbufs%) PROC_release(t%(nbufs%))
b%(nbufs%) += 0:IF b%(nbufs%) PROC_release(b%(nbufs%))
b%(nbufs%) += 0:IF b%(nbufs%) PROC_release(b%(nbufs%))
NEXT x%
d% += 0 :IF d% PROC_release(d%)
ENDPROC
|
|
Logged
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Quest for fire library (group effort )
« Reply #11 on: Jan 11th, 2018, 09:05am » |
|
Here's the code for the logs: you'll need my Make3DLib, which I actually keep in my D3D folder: amend the INSTALL address accordingly.
Make3DLib is available in the files area on the groups.io site: if you give me a couple of minutes I'll update the version there to make sure it is the current one.
Best wishes,
D Code:
INSTALL "Make3DLib"
nf%=6
maxverts%=FNGetNumVerts("Cylinder",nf%,1,nf%,TRUE)
DIM v(maxverts%-1,2),n(maxverts%-1,2),t(maxverts%-1,1)
nf%=6
totalverts%=3*FNGetNumVerts("Cylinder",nf%,1,nf%,TRUE)
vf%=&52
f%=FNOpenFVF("logs",totalverts%,vf%)
nv%=FNGetNumVerts("cylinder",nf%,1,nf%,TRUE)
PROCMake3D_Cylinder(nf%,v(),n(),t(),1,nf%,TRUE,0.0,1.0,0.0,1.0)
PROCStretch(nv%,v(),2,0.3,0.3)
PROCFindNormals(nv%,v(),n())
PROCExtendFVF(f%,vf%,nv%,v(),n(),t(),&FF403510,&FFF0F0F0)
nv%=FNGetNumVerts("cylinder",nf%,1,nf%,TRUE)
PROCMake3D_Cylinder(nf%,v(),n(),t(),1,nf%,TRUE,0.0,1.0,0.0,1.0)
PROCStretch(nv%,v(),2,0.3,0.3)
PROCFindNormals(nv%,v(),n())
PROCRotate(v(),0,0,PI/8)
PROCRotate(n(),0,0,PI/8)
PROCShift(v(),0.1,0.5,-0.5,nv%)
PROCShift(n(),0.1,0.5,-0.5,nv%)
PROCExtendFVF(f%,vf%,nv%,v(),n(),t(),&FF403510,&FFF0F0F0)
nv%=FNGetNumVerts("cylinder",nf%,1,nf%,TRUE)
PROCMake3D_Cylinder(nf%,v(),n(),t(),1,nf%,TRUE,0.0,1.0,0.0,1.0)
PROCStretch(nv%,v(),2,0.3,0.3)
PROCFindNormals(nv%,v(),n())
PROCRotate(v(),0,-PI/8,-PI/8)
PROCRotate(n(),0,-PI/8,-PI/8)
PROCShift(v(),0.1,-0.5,0.5,nv%)
PROCShift(n(),0.1,-0.5,0.5,nv%)
PROCExtendFVF(f%,vf%,nv%,v(),n(),t(),&FF403510,&FFF0F0F0)
PROCCloseFVF(f%)
END
|
|
Logged
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Quest for fire library (group effort )
« Reply #12 on: Jan 12th, 2018, 08:40am » |
|
OK, I've sorted out a couple of things. It turns out the order you render the buffers is critical: if you want things to show through, they need to have been rendered first - at least, when I put the logs in buffer 0 they show through, rather than being hidden. If you change Z(0)=0.8 to Z(0)=0.5, you'll be able to see the flames interleaved with the logs, since the front log is now closer than the flames.
I've also amended the code so that the flames become more transparent (less opaque) as they get higher. I don't know if you like it, but it demonstrates a technique...
I spotted that a problem I'd had earlier was not due to memory within BB4W, but the way I reserved buffer space, so I've removed the HIMEM change at the beginning.
Best wishes,
D Code:
MODE 21
nbufs%=4
REM Here I'm actually reserving arrays 1 BIGGER than nbufs% (i.e. 0 - nbufs%), which gives me one for background scene - here, the logs
DIM l%(0), b%(nbufs%), n%(nbufs%), f%(nbufs%), s%(nbufs%), m%(nbufs%), t%(nbufs%), y(nbufs%), p(nbufs%), r(nbufs%), X(nbufs%), Y(nbufs%), Z(nbufs%), e(2), a(2)
INSTALL @lib$+"D3DLIBA"
ON CLOSE PROCcleanup(nbufs%):QUIT
ON ERROR PROCcleanup(nbufs%):PRINT REPORT$:END
d% = FN_initd3d(@hwnd%, 1, 1)
IF d% = 0 ERROR 100, "Can't initialise Direct3D"
REM Set alpha blending
SYS !(!d%+200),d%,27,1:REM SetRenderState(Alphablendenable)
SYS !(!d%+200),d%,19,5:REM SetRenderState( set source blend to D3DBLEND_SRCALPHA)
SYS !(!d%+200),d%,20,6:REM SetRenderState(set destination blend to D3DBLEND_INVSRCALPHA)
SYS !(!d%+200),d%,148,1:REM SetRenderState(set emissive materialcoloursource to "diffuse vertex colour")
DIM l%(0) 103
l%(0)!0 = 3 : REM directional light, taken from manual (parameters adjusted)
l%(0)!4 = FN_f4(1) : REM red component
l%(0)!8 = FN_f4(1) : REM green component
l%(0)!12 = FN_f4(1) : REM blue component
l%(0)!64 = FN_f4(0.5) : REM. X component of direction
l%(0)!68 = FN_f4(-0.50) : REM. Y component of direction
l%(0)!72 = FN_f4(0.2) : REM. Z component of direction
nv%=26*12 :REM number of layers * 4 triangles (2 on each side between this layer and the next). Amend if you change the n% in PROCWriteVBufData!
REM Set up vertex buffer by loading the background "scene" - here it's just 3 logs!
b%(0)=FN_load3d(d%,"logs.fvf",n%(0),f%(0),s%(0))
IF b%(0)=0 THEN PROCcleanup(nbufs%):PRINT "Logs failed to load!":END
X(0)=-0.2
Y(0)=0.3
Z(0)=0.8
REM Set up vertex buffers for each flame
FOR x%=1 TO nbufs%
n%(x%)=nv%
f%(x%)=&52
s%(x%)=28
X(x%)=(x%-0.8)/2
Y(x%)=(x% MOD 2)*0.5
b%(x%)=FN_setupVbuf(d%,n%(x%),f%(x%),s%(x%))
IF b%(x%)=0 THEN PROCcleanup(nbufs%):PRINT x%,"Disaster!":END
NEXT x%
e() = 0,0,-10 :REM Eye/camera position
a() = 0, 1, 0 :REM Point you are looking at (centre of screen)
FOR duration%=0 TO 100
FOR x%=1 TO nbufs%
PROCWriteVBufData(b%(x%),n%(x%),s%(x%),1,2) :REM Re-write the actual vertex data to make flames flicker
NEXT x%
PROC_render(d%, &FF101010, 1, l%(), nbufs%+1, m%(), t%(), b%(), n%(), f%(), s%(), y(), p(), r(), X(), Y(), Z(), e(), a(), PI/4, 5/4, 1, 1000,0)
WAIT 10
NEXT duration%
PROCcleanup(nbufs%)
END
:
DEF FN_setupVbuf(D%,N%,V%,L%) :REM Adapted from D3DLib (as some of the other D3D stuff!)
LOCAL B%,R%
SYS!(!D%+92),D%,N%*L%,0,V%,0,^B% TO R%:REM CreateVertexBuffer
IF R% THEN=0
=B%
:
DEFPROCWriteVBufData(B%,N%,L%,w,h)
LOCAL P%,vb%
LOCAL x%,n%,n2%,c1%,c2%,dc%,hn,hw,dw,f()
n%=5 :REM you can change this to change the shape/detail of the flame - there will be n%^2 layers.
REM If you make n% more than 5, you will need to increase the space allocated for the buffers, or it will crash!
REM Now calculate coordinates for flame
n2%=n%^2
hn=n%/2
DIM f(n2%+1,2)
hw=w/2
dw=hw*0.8
FOR x%=0 TO n2%
f(x%,1)=RND(x%)/(4*n2%)
f(x%,0)=f(x%,1)-hw+ABS(dw-dw*SQR(x%)/hn)+RND(x%)*hw/(8*n2%)
f(x%,2)=f(x%,1)+hw-ABS(dw-dw*SQR(x%)/hn)-RND(x%)*hw/(8*n2%)
NEXT x%
f(n2%+1,1)=RND(n2%)/(2*n2%)
f(n2%+1,0)=f(n2%+1,1)
f(n2%+1,2)=f(n2%+1,1)
REM Now write it into the buffer
SYS!(!B%+44),B%,0,N%*L%,^P%,0:REM pVB::Lock
vb%=P% :REM vb% is a pointer to where we have got to in the buffer
dc%=(1<<16)-(2<<8)-1 :REM calculate difference in colour for one level higher
FOR x%=0 TO n2%
REM Calculate colours for edge and centre of the flame at this level
c1%=((160+x%)<<16)+((130-2*x%)<8)+26-x% +((&80-x%*5)<<24) :REM Last section controls opacity
c2%=((190+x%)<<16)+((158-x%)<<8)+55-x% +((&80-x%*5)<<24) :REM Change the "x%*5" to reduce the fade-out of flames
REM write data for the trapezium between this level and the next
REM 4 triangles, two from the left edge to the centre, and two from the right edge to the centre
PROCDoPoint(f(x%,0),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%-dc%,vb%)
PROCDoPoint(f(x%,1),x%*h/(n2%+1),0,c2%,vb%)
PROCDoPoint(f(x%,0),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%+1,0),(x%+1)*h/(n2%+1),0,c1%-dc%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%,vb%)
PROCDoPoint(f(x%,2),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%,1),x%*h/(n2%+1),0,c2%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%-dc%,vb%)
PROCDoPoint(f(x%,2),x%*h/(n2%+1),0,c1%,vb%)
PROCDoPoint(f(x%+1,1),(x%+1)*h/(n2%+1),0,c2%-dc%,vb%)
PROCDoPoint(f(x%+1,2),(x%+1)*h/(n2%+1),0,c1%-dc%,vb%)
NEXT x%
SYS!(!B%+48),B%:REM pVB::Unlock
ENDPROC
:
DEFPROCDoPoint(x,y,z,c%, RETURN vb%)
REM Here are the coordinates of the point
!vb%=FN_f4(x)
vb%!4=FN_f4(y)
vb%!8=FN_f4(z)
REM Add normals. Assume all points are flat in the plane,so normal faces towards Z
vb%!12=FN_f4(0.0)
vb%!16=FN_f4(0.0)
vb%!20=FN_f4(1.0)
REM Now the colour
vb%!24=c%
vb%+=28 :REM Update pointer. I do it here so it's easy to change if you change the vertex size
ENDPROC
:
DEF PROCcleanup(nbufs%) : REM From example, slightly amended to allow for multiple buffers
LOCAL x%
FOR x%=0 TO nbufs%
t%(nbufs%) += 0:IF t%(nbufs%) PROC_release(t%(nbufs%))
b%(nbufs%) += 0:IF b%(nbufs%) PROC_release(b%(nbufs%))
b%(nbufs%) += 0:IF b%(nbufs%) PROC_release(b%(nbufs%))
NEXT x%
d% += 0 :IF d% PROC_release(d%)
ENDPROC
|
|
Logged
|
|
|
|
DDRM
Administrator
member is offline


Gender: 
Posts: 321
|
 |
Re: Quest for fire library (group effort )
« Reply #13 on: Jan 12th, 2018, 08:59am » |
|
...and here's (an improved) version of the Logs program that doesn't need Make3dLib (the relevant sections are included).
Best wishes,
D Code:REM Version of Logs with routines from Make3dLib included
nf%=8
maxverts%=FNGetNumVerts("Cylinder",nf%,1,nf%,TRUE)
DIM v(maxverts%-1,2),n(maxverts%-1,2),t(maxverts%-1,1)
totalverts%=3*FNGetNumVerts("Cylinder",nf%,1,nf%,TRUE)
vf%=&52
f%=FNOpenFVF("logs",totalverts%,vf%)
nv%=FNGetNumVerts("cylinder",nf%,1,nf%,TRUE)
PROCMake3D_Cylinder(nf%,v(),n(),t(),1,nf%,TRUE,0.0,1.0,0.0,1.0)
PROCStretch(nv%,v(),2,0.3,0.3)
PROCExtendFVF(f%,vf%,nv%,v(),n(),t(),&FF403510,&FFF0F0F0)
nv%=FNGetNumVerts("cylinder",nf%,1,nf%,TRUE)
PROCMake3D_Cylinder(nf%,v(),n(),t(),1,nf%,TRUE,0.0,1.0,0.0,1.0)
PROCStretch(nv%,v(),2,0.3,0.3)
PROCRotate(v(),0,0,PI/8)
PROCRotate(n(),0,0,PI/8)
PROCShift(v(),0.1,0.5,-0.5,nv%)
PROCShift(n(),0.1,0.5,-0.5,nv%)
PROCExtendFVF(f%,vf%,nv%,v(),n(),t(),&FF403510,&FFF0F0F0)
nv%=FNGetNumVerts("cylinder",nf%,1,nf%,TRUE)
PROCMake3D_Cylinder(nf%,v(),n(),t(),1,nf%,TRUE,0.0,1.0,0.0,1.0)
PROCStretch(nv%,v(),2,0.3,0.3)
PROCRotate(v(),0,-PI/8,-PI/8)
PROCRotate(n(),0,-PI/8,-PI/8)
PROCShift(v(),0.1,-0.5,0.5,nv%)
PROCShift(n(),0.1,-0.5,0.5,nv%)
PROCExtendFVF(f%,vf%,nv%,v(),n(),t(),&FF403510,&FFF0F0F0)
PROCCloseFVF(f%)
END
:
DEFFNGetNumVerts(n$,nf%,startface%,endface%,capped%)
LOCAL nv%,vpf%
PROCUpcase(n$)
CASE n$ OF
WHEN "CYLINDER","PRISM","TRUNCCONE":
IF capped% THEN vpf%=12 ELSE vpf%=6
nv%=vpf%*(endface%-startface%+1)
WHEN "SPHERE":
nv%=(endface%-startface%+1)*2*nf% *6
IF startface%=1 THEN nv%-=nf%*6
IF endface%=nf% THEN nv%-=nf%*6
WHEN "CONE":
IF capped% THEN vpf%=6 ELSE vpf%=3
nv%=vpf%*(endface%-startface%+1)
ENDCASE
=nv%
:
DEFPROCMake3D_Cylinder(nf%,v(),vn(),t(),startface%,endface%,capped%,texminu,texmaxu,texminv,texmaxv):Make3dLibNormals%=TRUE
LOCAL r,r2
r=1
r2=1
LOCAL vpf%,nv%,l,tdu,tdv,a,pa,py,pz,py2,pz2,ey,ez,ey2,ez2,ny,nz,ny2,nz2,eny,enz,eny2,enz2
IF capped% THEN vpf%=12 ELSE vpf%=6
nv%=vpf%*(endface%-startface%+1)
l=1
tdu=texmaxu-texminu
tdv=texmaxv-texminv
FOR a=0 TO endface%-startface%
pa=a+startface%-1
py=r*SIN(pa*2*PI/nf%)
pz=r*COS(pa*2*PI/nf%)
py2=r*SIN((pa+1)*2*PI/nf%)
pz2=r*COS((pa+1)*2*PI/nf%)
ey=r2*SIN(pa*2*PI/nf%)
ez=r2*COS(pa*2*PI/nf%)
ey2=r2*SIN((pa+1)*2*PI/nf%)
ez2=r2*COS((pa+1)*2*PI/nf%)
v(a*vpf%,0)=0
v(a*vpf%,1)=py
v(a*vpf%,2)=pz
v(a*vpf%+1,0)=l
v(a*vpf%+1,1)=ey2
v(a*vpf%+1,2)=ez2
v(a*vpf%+2,0)=l
v(a*vpf%+2,1)=ey
v(a*vpf%+2,2)=ez
v(a*vpf%+3,0)=0
v(a*vpf%+3,1)=py
v(a*vpf%+3,2)=pz
v(a*vpf%+4,0)=0
v(a*vpf%+4,1)=py2
v(a*vpf%+4,2)=pz2
v(a*vpf%+5,0)=l
v(a*vpf%+5,1)=ey2
v(a*vpf%+5,2)=ez2
IF Make3dLibNormals% THEN
ny=(r+1)*SIN(pa*2*PI/nf%)
nz=(r+1)*COS(pa*2*PI/nf%)
ny2=(r+1)*SIN((pa+1)*2*PI/nf%)
nz2=(r+1)*COS((pa+1)*2*PI/nf%)
eny=(r2+1)*SIN(pa*2*PI/nf%)
enz=(r2+1)*COS(pa*2*PI/nf%)
eny2=(r2+1)*SIN((pa+1)*2*PI/nf%)
enz2=(r2+1)*COS((pa+1)*2*PI/nf%)
vn(a*vpf%,0)=0
vn(a*vpf%,1)=ny
vn(a*vpf%,2)=nz
vn(a*vpf%+1,0)=l
vn(a*vpf%+1,1)=eny2
vn(a*vpf%+1,2)=enz2
vn(a*vpf%+2,0)=l
vn(a*vpf%+2,1)=eny
vn(a*vpf%+2,2)=enz
vn(a*vpf%+3,0)=0
vn(a*vpf%+3,1)=ny
vn(a*vpf%+3,2)=nz
vn(a*vpf%+4,0)=0
vn(a*vpf%+4,1)=ny2
vn(a*vpf%+4,2)=nz2
vn(a*vpf%+5,0)=l
vn(a*vpf%+5,1)=eny2
vn(a*vpf%+5,2)=enz2
ENDIF
t(a*vpf%,0)=texminu
t(a*vpf%,1)=texminv+tdv*pa/nf%
t(a*vpf%+1,0)=texmaxu
t(a*vpf%+1,1)=texminv+tdv*(pa+1)/nf%
t(a*vpf%+2,0)=texmaxu
t(a*vpf%+2,1)=texminv+tdv*pa/nf%
t(a*vpf%+3,0)=texminu
t(a*vpf%+3,1)=texminv+tdv*pa/nf%
t(a*vpf%+4,0)=texminu
t(a*vpf%+4,1)=texminv+tdv*(pa+1)/nf%
t(a*vpf%+5,0)=texmaxu
t(a*vpf%+5,1)=texminv+tdv*(pa+1)/nf%
IF capped% THEN
v(a*vpf%+6,0)=0
v(a*vpf%+6,1)=py
v(a*vpf%+6,2)=pz
v(a*vpf%+7,0)=0
v(a*vpf%+7,1)=0
v(a*vpf%+7,2)=0
v(a*vpf%+8,0)=0
v(a*vpf%+8,1)=py2
v(a*vpf%+8,2)=pz2
v(a*vpf%+9,0)=l
v(a*vpf%+9,1)=ey
v(a*vpf%+9,2)=ez
v(a*vpf%+10,0)=l
v(a*vpf%+10,1)=0
v(a*vpf%+10,2)=0
v(a*vpf%+11,0)=l
v(a*vpf%+11,1)=ey2
v(a*vpf%+11,2)=ez2
IF Make3dLibNormals% THEN
vn(a*vpf%+6,0)=-10
vn(a*vpf%+6,1)=py
vn(a*vpf%+6,2)=pz
vn(a*vpf%+7,0)=-10
vn(a*vpf%+7,1)=0
vn(a*vpf%+7,2)=0
vn(a*vpf%+8,0)=-10
vn(a*vpf%+8,1)=py2
vn(a*vpf%+8,2)=pz2
vn(a*vpf%+9,0)=l+10
vn(a*vpf%+9,1)=ey2
vn(a*vpf%+9,2)=ez2
vn(a*vpf%+10,0)=l+10
vn(a*vpf%+10,1)=0
vn(a*vpf%+10,2)=0
vn(a*vpf%+11,0)=l+10
vn(a*vpf%+11,1)=ey2
vn(a*vpf%+11,2)=ez2
ENDIF
t(a*vpf%+6,0)=texminu
t(a*vpf%+6,1)=texminv+tdv*a/nf%
t(a*vpf%+7,0)=texminu+tdu/2
t(a*vpf%+7,1)=texminv+tdv/2
t(a*vpf%+8,0)=texminu
t(a*vpf%+8,1)=texminv+tdv*(a+1)/nf%
t(a*vpf%+9,0)=texmaxu
t(a*vpf%+9,1)=texminv+tdv*a/nf%
t(a*vpf%+10,0)=texminu+tdu/2
t(a*vpf%+10,1)=texminv+tdv/2
t(a*vpf%+11,0)=texmaxu
t(a*vpf%+11,1)=texminv+tdv*(a+1)/nf%
ENDIF
NEXT a
ENDPROC
:
DEFPROCRotate(a(),xa,ya,za)
LOCAL xrm(),yrm(),zrm()
DIM xrm(2,2),yrm(2,2),zrm(2,2)
xrm()=1,0,0,0,COS(xa),-SIN(xa),0,SIN(xa),COS(xa)
yrm()=COS(ya),0,SIN(ya),0,1,0,-SIN(ya),0,COS(ya)
zrm()=COS(za),-SIN(za),0,SIN(za),COS(za),0,0,0,1
xrm()=xrm().yrm()
xrm()=xrm().zrm()
a()=a().xrm()
ENDPROC
:
DEFPROCShift(a(),dx,dy,dz,nv%)
LOCAL x%
FOR x%=0 TO nv%-1
a(x%,0)+=dx
a(x%,1)+=dy
a(x%,2)+=dz
NEXT x%
ENDPROC
:
DEFPROCStretch(nv%,v(),xf,yf,zf)
LOCAL x%
FOR x%=0 TO nv%-1
v(x%,0)*=xf
v(x%,1)*=yf
v(x%,2)*=zf
NEXT x%
ENDPROC
:
DEFFNOpenFVF(name$,nv%,vf%)
LOCAL f%,vs%
vs%=0
IF vf% AND 2 THEN vs%+=12
IF vf% AND &10 THEN vs%+=12
IF vf% AND &40 THEN vs%+=4
IF vf% AND &80 THEN vs%+=4
IF vf% AND &100 THEN vs%+=8
REM Create file and fill it with data
f%=OPENOUT(@dir$+name$+".FVF")
PROC4(f%,nv%)
PROC4(f%,(vs%<<16)+vf%)
=f%
:
DEFPROCCloseFVF(f%)
CLOSE #f%
ENDPROC
:
DEFPROCExtendFVF(f%,vf%,nv%,vdat(),ndat(),tdat(),acol%,scol%)
LOCAL x%
FOR x%=0 TO nv%-1
IF vf% AND 2 THEN PROC4(f%,FN_f4(vdat(x%,0))):PROC4(f%,FN_f4(vdat(x%,1))):PROC4(f%,FN_f4(vdat(x%,2)))
IF vf% AND &10 THEN PROC4(f%,FN_f4(ndat(x%,0))):PROC4(f%,FN_f4(ndat(x%,1))):PROC4(f%,FN_f4(ndat(x%,2)))
IF vf% AND &40 THEN PROC4(f%,acol%)
IF vf% AND &80 THEN PROC4(f%,scol%)
IF vf% AND &100 THEN PROC4(f%,FN_f4(tdat(x%,0))):PROC4(f%,FN_f4(tdat(x%,1)))
NEXT x%
ENDPROC
:
DEFPROCUpcase(RETURN n$)
LOCAL x%
FOR x%=1 TO LEN(n$)
IF ASC(MID$(n$,x%,1))>96 AND ASC(MID$(n$,x%,1))<123 THEN n$=LEFT$(n$,x%-1)+CHR$(ASC(MID$(n$,x%,1))-32)+MID$(n$,x%+1)
NEXT x%
ENDPROC
:
REM Stolen from Richard's D3D demo
DEF PROC4(F%, A%)
BPUT#F%,A% : BPUT#F%,A%>>8 : BPUT#F%,A%>>16 : BPUT#F%,A%>>24
ENDPROC
:
REM Stolen from Richard's D3D library
DEF FN_f4(A#)
LOCAL A%,P%,U#
PRIVATE F%
IF F%=0 THEN
DIM P% 10
[OPT 2
.F%
mov esi,[ebp+2]:mov edi,[ebp+7]
fld qword [esi]:fstp dword [edi]
ret
]
ENDIF
!(^U#+4)=&3FF00000
A#*=U#
CALL F%,A#,A%
=A%
|
|
Logged
|
|
|
|
|