Author |
Topic: Quest for fire library (group effort ) (Read 679 times) |
|
DDRM
Global Moderator
member is offline


Posts: 36
|
 |
Re: Quest for fire library (group effort )
« Reply #13 on: Jan 11th, 2018, 09:04am » |
|
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
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 803
|
 |
Re: Quest for fire library (group effort )
« Reply #14 on: Jan 11th, 2018, 1:02pm » |
|
on Jan 11th, 2018, 08:48am, DDRM wrote:| I don't know how to do the equivalent in SDL |
|
SDL is 2D only (I assume you're relying on the third dimension, otherwise you wouldn't be using D3DLIB - unless you want it solely for transparency in which case GDIPlus might be easier).
For 3D stuff in BBCSDL you need to use OpenGL (which is generally more straightforward than Direct3D because of the 'flat' interface); there's no shortage of documentation online. For enabling alphablending you can look at 'bbcowl.bbc' which relies on it I think.
Mind you I'm not sure that you will find a direct OpenGL equivalent of 'set emissive materialcoloursource to "diffuse vertex colour"' (without coding a shader) - and Google doesn't help.
Richard.
|
|
|
|
DDRM
Global Moderator
member is offline


Posts: 36
|
 |
Re: Quest for fire library (group effort )
« Reply #15 on: Jan 11th, 2018, 3:13pm » |
|
Hi Richard,
Actually the flames themselves are rendered flat at the moment, though their positioning relative to each other and the logs uses the Z dimension, and the logs are cylinders, arranged in 3D. Yes, I really meant OpenGL for the 3D work in BBC-SDL.
The main reason I went for D3D was the Gouraud shading. The transparency is also nice, though as I say it doesn't seem to be working very well - in my flight sim you could see through the propeller disc very nicely, but the transparency is much higher- that makes the flames nigh on invisible, but still doesn't work. I like the idea of GDIP - I'll have a think.
I don't think not having the emissivity is a deal-breaker..
Best wishes,
D
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 803
|
 |
Re: Quest for fire library (group effort )
« Reply #16 on: Jan 12th, 2018, 09:48am » |
|
on Jan 11th, 2018, 09:04am, DDRM wrote:| Here's the code for the logs: you'll need my Make3DLib |
|
This code fails with an 'Invalid channel' error for me. After a little investigation the cause appears to be this line in your Make3DLib library:
Code: f%=OPENOUT(@dir$+name$+".FVF") @dir$ is, of course, commonly a 'read only' directory. It's where the program itself is stored, which will typically be in a 'protected' folder - and it certainly is when one simply copies-and-pastes code from a web site into a freshly-opened BB4W IDE as I did.
Therefore you should not attempt to open a file for writing in @dir$, and certainly not in a library! Places that are 'guaranteed' to be writable include @tmp$ (for temporary files that are not wanted after the program ends) and @usr$ (for files which need to be kept from one 'session' to the next, such as a high-score table).
I put 'guaranteed' in quotes because OPENOUT may still fail in those directories if the file is locked (e.g. currently open by another program) or read-only. This can largely be avoided by using a 'unique' filename such as one containing a UUID or a random number or the date/time etc.
Richard.
|
|
Logged
|
|
|
|
DDRM
Global Moderator
member is offline


Posts: 36
|
 |
Re: Quest for fire library (group effort )
« Reply #17 on: Jan 12th, 2018, 10:14am » |
|
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 21nbufs%=4REM Here I'm actually reserving arrays 1 BIGGER than nbufs% (i.e. 0 - nbufs%), which gives me one for background scene - here, the logsDIM 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%):QUITON ERROR PROCcleanup(nbufs%):PRINT REPORT$:ENDd% = FN_initd3d(@hwnd%, 1, 1)IF d% = 0 ERROR 100, "Can't initialise Direct3D"REM Set alpha blendingSYS !(!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) 103l%(0)!0 = 3 : REM directional light, taken from manual (parameters adjusted)l%(0)!4 = FN_f4(1) : REM red componentl%(0)!8 = FN_f4(1) : REM green componentl%(0)!12 = FN_f4(1) : REM blue componentl%(0)!64 = FN_f4(0.5) : REM. X component of directionl%(0)!68 = FN_f4(-0.50) : REM. Y component of directionl%(0)!72 = FN_f4(0.2) : REM. Z component of directionnv%=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!":ENDX(0)=-0.2Y(0)=0.3Z(0)=0.8REM Set up vertex buffers for each flameFOR 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!":ENDNEXT x%e() = 0,0,-10 :REM Eye/camera positiona() = 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 10NEXT 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 CreateVertexBufferIF 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 flamen2%=n%^2hn=n%/2DIM f(n2%+1,2)hw=w/2dw=hw*0.8FOR 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 bufferSYS!(!B%+44),B%,0,N%*L%,^P%,0:REM pVB::Lockvb%=P% :REM vb% is a pointer to where we have got to in the bufferdc%=(1<<16)-(2<<8)-1 :REM calculate difference in colour for one level higherFOR 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::UnlockENDPROC: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 Zvb%!12=FN_f4(0.0)vb%!16=FN_f4(0.0)vb%!20=FN_f4(1.0)REM Now the colourvb%!24=c%vb%+=28 :REM Update pointer. I do it here so it's easy to change if you change the vertex sizeENDPROC:DEF PROCcleanup(nbufs%) : REM From example, slightly amended to allow for multiple buffersLOCAL 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
Global Moderator
member is offline


Posts: 36
|
 |
Re: Quest for fire library (group effort )
« Reply #18 on: Jan 12th, 2018, 10:24am » |
|
...and here's (an improved) version of the Logs program that doesn't need Make3dLib (the relevant sections are included).
Richard: thanks for your comments about using @dir$, which I will try to note and apply - especially in something like a library. However, I haven't changed it here, because the program is generating a file which will be used by another program. So your comment is important, in that it illustrates that this program (and its output file logs.fvf) will need to be in the same directory as the "flames" program (which will load the logs file from its host directory). I guess one solution might be to amend the routine to open a file save box, so the user can choose where to put it.
In the case of this type of program, which is going to be used essentially during a development phase, I think it DOES make sense to have things working in the same directory. Obviously in a finished "package" it would make sense to put all FVF files etc into a resource directory relative to the running program.
Best wishes,
D Code:REM Version of Logs with routines from Make3dLib includednf%=8maxverts%=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%=&52f%=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%=TRUELOCAL r,r2r=1r2=1LOCAL vpf%,nv%,l,tdu,tdv,a,pa,py,pz,py2,pz2,ey,ez,ey2,ez2,ny,nz,ny2,nz2,eny,enz,eny2,enz2IF capped% THEN vpf%=12 ELSE vpf%=6nv%=vpf%*(endface%-startface%+1)l=1tdu=texmaxu-texminutdv=texmaxv-texminvFOR 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% THENvn(a*vpf%+6,0)=-10vn(a*vpf%+6,1)=pyvn(a*vpf%+6,2)=pzvn(a*vpf%+7,0)=-10vn(a*vpf%+7,1)=0vn(a*vpf%+7,2)=0vn(a*vpf%+8,0)=-10vn(a*vpf%+8,1)=py2vn(a*vpf%+8,2)=pz2vn(a*vpf%+9,0)=l+10vn(a*vpf%+9,1)=ey2vn(a*vpf%+9,2)=ez2vn(a*vpf%+10,0)=l+10vn(a*vpf%+10,1)=0vn(a*vpf%+10,2)=0vn(a*vpf%+11,0)=l+10vn(a*vpf%+11,1)=ey2vn(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% ENDIFNEXT aENDPROC: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,1xrm()=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)+=dzNEXT 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)*=zfNEXT x%ENDPROC:DEFFNOpenFVF(name$,nv%,vf%)LOCAL f%,vs%vs%=0IF vf% AND 2 THEN vs%+=12IF vf% AND &10 THEN vs%+=12IF vf% AND &40 THEN vs%+=4IF vf% AND &80 THEN vs%+=4IF vf% AND &100 THEN vs%+=8REM Create file and fill it with dataf%=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 demoDEF PROC4(F%, A%)BPUT#F%,A% : BPUT#F%,A%>>8 : BPUT#F%,A%>>16 : BPUT#F%,A%>>24ENDPROC:REM Stolen from Richard's D3D libraryDEF 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)=&3FF00000A#*=U#CALL F%,A#,A%=A%
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 803
|
 |
Re: Quest for fire library (group effort )
« Reply #19 on: Jan 12th, 2018, 11:41am » |
|
on Jan 12th, 2018, 10:14am, DDRM wrote:| 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 |
|
That surprises me. I would have expected the Z-buffer to be the determining factor, i.e. I would have expected that a 'foreground' object, with or without transparency, would always appear 'in front of' a background object, irrespective of the order in which they are specified in the list of buffers. Otherwise it would imply that you need to change the buffer order depending on the viewpoint, which surely can't be right?
I wonder if you have fallen into the same trap as I did, briefly, when making the BBC OWL simulation. That is, to assume that the Z-buffer has 'infinite' depth resolution, which of course it doesn't because the values stored are only 32-bit floats (if that). The implication is that you need to ensure that two objects (in my case they were concentric spheres) are sufficiently separated that there will be no ambiguity about which is 'in front'. If their depths are too similar they may round to the same value in the Z-buffer and then I could believe that the order in which they are specified does indeed matter.
Quote:| However, I haven't changed it here, because the program is generating a file which will be used by another program. |
|
I don't think that, in itself, makes a difference because (for example) @tmp$ points to the same location in all BB4W programs so a file created there by one will be visible to another.
What perhaps you really mean is that your library is intended to be a developers' library, i.e. that rather being installed from a deployed application at run time you expect it to be used by a developer to build that application (or, to be more precise, files used by the application).
That's not something I have ever come across before, but if it is the case I would say that (1) you need to make it very clear, because it's so out of the ordinary and (2) you need to check for the file creation having failed and generate a 'helpful' message rather than throwing a generic error.
Richard.
|
|
Logged
|
|
|
|
DDRM
Global Moderator
member is offline


Posts: 36
|
 |
Re: Quest for fire library (group effort )
« Reply #20 on: Jan 12th, 2018, 12:41pm » |
|
Hi Richard,
What I saw was that the Z position correctly controlled which was drawn in front of the other (I agree very small Z differences don't always work quite as you expect) - and indeed, the flames can render BETWEEN the logs if you position it right - but that when the flames were rendered in front of the logs (but before the logs themselves had been rendered) you couldn't see the logs through them. When you render the logs first, then the flames, you CAN see through them to the logs behind. I can imagine that it's problematic for D3D to realise that something it's already dealt with is transparent, and the new thing it's rendering behind it should be partially rendered with it. I guess the moral of the story is "render transparent things last".
With regard to directories, I agree that library functions need, by default, to save somewhere sensible (and writable!) I rather assumed that the dir$ active at the time relates to the program calling the library - is that not the case? Nonetheless, your point is well made that I can't assume that a program will be running from a writable directory. I wasn't thinking about a "development library", but that the programs using it will be for creating resources (FVF files) as part of the development process: typically I keep all such "helper" programs, together with working resource files, together in one folder (in this case, called D3D), but obviously not everyone works the same way!
Does getting the routine in the library to open a "save as" box seem a reasonable solution? I'm not keen on using temp$ or usr$ because (a) the user may not know where they are, and be unable to find the file, and (b) don't you have to assume that things in the temp directory can be deleted when this use is finished? I don't think Windows does automated garbage collection in the way Android does, but my understanding was that you shouldn't rely on things staying in the temp directory for long... Maybe I'm very old-fashioned in this, as I think you've suggested before 
Best wishes,
D
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 803
|
 |
Re: Quest for fire library (group effort )
« Reply #21 on: Jan 12th, 2018, 3:56pm » |
|
on Jan 12th, 2018, 12:41pm, DDRM wrote:| I rather assumed that the dir$ active at the time relates to the program calling the library - is that not the case? |
|
I'm not sure what you mean by "relates to" in this sense. @dir$ is initialised to point to the directory from which the program was originally loaded, if that is known. If the program was pasted in (or typed, or dropped) then of course that isn't known - indeed the program may not be saved at all - in which case @dir$ cannot be relied upon to point to anywhere specific.
That was the case when I received the 'Invalid channel' error: I had pasted your program from the forum but had not saved it. As a result @dir$ pointed to the EXAMPLES folder of the BB4W installation (under C:\Program Files (x86)\BBC BASIC) which is definitely not writable unless 'run as' elevated.
Quote:| Does getting the routine in the library to open a "save as" box seem a reasonable solution? |
|
I don't think I've entirely understood the possible usage cases. If the purpose of the library is for a software developer to create an FVF file, which he will eventually ship with his program, then he will be wanting to create it in @dir$ or a sub-directory thereof. If it's intended that the library itself be shipped with the program, so that the FVF file is created 'on the fly' at run time, then it will need to be created in @tmp$.
In the former case I suppose it would be acceptable to open a file selector, but not in the latter case. For all I know you may intend that the library can be used in both these scenarios. The only fully flexible approach, I would have thought, is for the path/filename to be supplied as a parameter and not determined by the library at all. Indeed, looking at your code, why does the library decide the directory and extension when these could simply be passed in the name$ parameter?
Finally, I'd recommend that you replace the old CPU-dependent version of FN_f4 (which uses x86 assembler code) with the entirely-BASIC version listed below. Not only is it CPU-agnostic, benchmarking showed it to be faster (you may remember that I posted an earlier version to the discussion group as a challenge to see if anybody could improve on it).
Richard.
Code: REM Convert to 4-byte float DEF FN_f4(a#)LOCALP%:P%=^a#:IFABSa#<1E-38THEN=FALSE =P%!4ANDNOT&7FFFFFFFOR(P%!4-&38000000<<3OR!P%>>29AND7)+(!P%>>28AND1)
|
|
|
|
DDRM
Global Moderator
member is offline


Posts: 36
|
 |
Re: Quest for fire library (group effort )
« Reply #22 on: Jan 15th, 2018, 08:13am » |
|
Hi Richard, Quote:| Indeed, looking at your code, why does the library decide the directory and extension when these could simply be passed in the name$ parameter? |
|
Quote:MAJIKTHISE: Bloody ‘ell! That’s what I call thinking! Here Vroomfondel, why do we never think of things like that?
VROOMFONDEL: Dunno. Think our minds must be too highly trained Majikthise |
|
Duh, yes, that would be much more sensible... I'll change it.
Thanks also for the updated version of FN_f4
Best wishes,
D
|
|
Logged
|
|
|
|
michael
Full Member
member is offline


Posts: 157
|
 |
Re: Quest for fire library (group effort )
« Reply #23 on: Jan 17th, 2018, 12:44am » |
|
The 3D fire is pretty cool.
|
|
Logged
|
I like reinventing the wheel, but for now I will work on tools for D3D
|
|
|
|